.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * H/W layer of ISHTP provider device (ISH) |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2014-2016, Intel Corporation. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms and conditions of the GNU General Public License, |
---|
8 | | - * version 2, as published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | | - * more details. |
---|
14 | 6 | */ |
---|
15 | 7 | |
---|
16 | 8 | #include <linux/sched.h> |
---|
.. | .. |
---|
259 | 251 | int i; |
---|
260 | 252 | void (*ipc_send_compl)(void *); |
---|
261 | 253 | void *ipc_send_compl_prm; |
---|
262 | | - static int out_ipc_locked; |
---|
263 | | - unsigned long out_ipc_flags; |
---|
264 | 254 | |
---|
265 | 255 | if (dev->dev_state == ISHTP_DEV_DISABLED) |
---|
266 | | - return -EINVAL; |
---|
267 | | - |
---|
268 | | - spin_lock_irqsave(&dev->out_ipc_spinlock, out_ipc_flags); |
---|
269 | | - if (out_ipc_locked) { |
---|
270 | | - spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); |
---|
271 | | - return -EBUSY; |
---|
272 | | - } |
---|
273 | | - out_ipc_locked = 1; |
---|
274 | | - if (!ish_is_input_ready(dev)) { |
---|
275 | | - out_ipc_locked = 0; |
---|
276 | | - spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); |
---|
277 | | - return -EBUSY; |
---|
278 | | - } |
---|
279 | | - spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); |
---|
| 256 | + return -EINVAL; |
---|
280 | 257 | |
---|
281 | 258 | spin_lock_irqsave(&dev->wr_processing_spinlock, flags); |
---|
| 259 | + if (!ish_is_input_ready(dev)) { |
---|
| 260 | + spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); |
---|
| 261 | + return -EBUSY; |
---|
| 262 | + } |
---|
| 263 | + |
---|
282 | 264 | /* |
---|
283 | 265 | * if tx send list is empty - return 0; |
---|
284 | 266 | * may happen, as RX_COMPLETE handler doesn't check list emptiness. |
---|
285 | 267 | */ |
---|
286 | | - if (list_empty(&dev->wr_processing_list_head.link)) { |
---|
| 268 | + if (list_empty(&dev->wr_processing_list)) { |
---|
287 | 269 | spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); |
---|
288 | | - out_ipc_locked = 0; |
---|
289 | 270 | return 0; |
---|
290 | 271 | } |
---|
291 | 272 | |
---|
292 | | - ipc_link = list_entry(dev->wr_processing_list_head.link.next, |
---|
293 | | - struct wr_msg_ctl_info, link); |
---|
| 273 | + ipc_link = list_first_entry(&dev->wr_processing_list, |
---|
| 274 | + struct wr_msg_ctl_info, link); |
---|
294 | 275 | /* first 4 bytes of the data is the doorbell value (IPC header) */ |
---|
295 | 276 | length = ipc_link->length - sizeof(uint32_t); |
---|
296 | 277 | doorbell_val = *(uint32_t *)ipc_link->inline_data; |
---|
.. | .. |
---|
328 | 309 | memcpy(®, &r_buf[length >> 2], rem); |
---|
329 | 310 | ish_reg_write(dev, reg_addr, reg); |
---|
330 | 311 | } |
---|
| 312 | + ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, doorbell_val); |
---|
| 313 | + |
---|
331 | 314 | /* Flush writes to msg registers and doorbell */ |
---|
332 | 315 | ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); |
---|
333 | 316 | |
---|
.. | .. |
---|
335 | 318 | ++dev->ipc_tx_cnt; |
---|
336 | 319 | dev->ipc_tx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val); |
---|
337 | 320 | |
---|
338 | | - ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, doorbell_val); |
---|
339 | | - out_ipc_locked = 0; |
---|
340 | | - |
---|
341 | 321 | ipc_send_compl = ipc_link->ipc_send_compl; |
---|
342 | 322 | ipc_send_compl_prm = ipc_link->ipc_send_compl_prm; |
---|
343 | 323 | list_del_init(&ipc_link->link); |
---|
344 | | - list_add_tail(&ipc_link->link, &dev->wr_free_list_head.link); |
---|
| 324 | + list_add(&ipc_link->link, &dev->wr_free_list); |
---|
345 | 325 | spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); |
---|
346 | 326 | |
---|
347 | 327 | /* |
---|
.. | .. |
---|
375 | 355 | unsigned char *msg, int length) |
---|
376 | 356 | { |
---|
377 | 357 | struct wr_msg_ctl_info *ipc_link; |
---|
378 | | - unsigned long flags; |
---|
| 358 | + unsigned long flags; |
---|
379 | 359 | |
---|
380 | 360 | if (length > IPC_FULL_MSG_SIZE) |
---|
381 | 361 | return -EMSGSIZE; |
---|
382 | 362 | |
---|
383 | 363 | spin_lock_irqsave(&dev->wr_processing_spinlock, flags); |
---|
384 | | - if (list_empty(&dev->wr_free_list_head.link)) { |
---|
| 364 | + if (list_empty(&dev->wr_free_list)) { |
---|
385 | 365 | spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); |
---|
386 | 366 | return -ENOMEM; |
---|
387 | 367 | } |
---|
388 | | - ipc_link = list_entry(dev->wr_free_list_head.link.next, |
---|
389 | | - struct wr_msg_ctl_info, link); |
---|
| 368 | + ipc_link = list_first_entry(&dev->wr_free_list, |
---|
| 369 | + struct wr_msg_ctl_info, link); |
---|
390 | 370 | list_del_init(&ipc_link->link); |
---|
391 | 371 | |
---|
392 | 372 | ipc_link->ipc_send_compl = ipc_send_compl; |
---|
.. | .. |
---|
394 | 374 | ipc_link->length = length; |
---|
395 | 375 | memcpy(ipc_link->inline_data, msg, length); |
---|
396 | 376 | |
---|
397 | | - list_add_tail(&ipc_link->link, &dev->wr_processing_list_head.link); |
---|
| 377 | + list_add_tail(&ipc_link->link, &dev->wr_processing_list); |
---|
398 | 378 | spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); |
---|
399 | 379 | |
---|
400 | 380 | write_ipc_from_queue(dev); |
---|
.. | .. |
---|
490 | 470 | { |
---|
491 | 471 | uint32_t reset_id; |
---|
492 | 472 | unsigned long flags; |
---|
493 | | - struct wr_msg_ctl_info *processing, *next; |
---|
494 | 473 | |
---|
495 | 474 | /* Read reset ID */ |
---|
496 | 475 | reset_id = ish_reg_read(dev, IPC_REG_ISH2HOST_MSG) & 0xFFFF; |
---|
497 | 476 | |
---|
498 | 477 | /* Clear IPC output queue */ |
---|
499 | 478 | spin_lock_irqsave(&dev->wr_processing_spinlock, flags); |
---|
500 | | - list_for_each_entry_safe(processing, next, |
---|
501 | | - &dev->wr_processing_list_head.link, link) { |
---|
502 | | - list_move_tail(&processing->link, &dev->wr_free_list_head.link); |
---|
503 | | - } |
---|
| 479 | + list_splice_init(&dev->wr_processing_list, &dev->wr_free_list); |
---|
504 | 480 | spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); |
---|
505 | 481 | |
---|
506 | 482 | /* ISHTP notification in IPC_RESET */ |
---|
.. | .. |
---|
696 | 672 | * |
---|
697 | 673 | * Return: 0 for success else error code. |
---|
698 | 674 | */ |
---|
699 | | -static int ish_disable_dma(struct ishtp_device *dev) |
---|
| 675 | +int ish_disable_dma(struct ishtp_device *dev) |
---|
700 | 676 | { |
---|
701 | 677 | unsigned int dma_delay; |
---|
702 | 678 | |
---|
.. | .. |
---|
779 | 755 | csr |= PCI_D3hot; |
---|
780 | 756 | pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); |
---|
781 | 757 | |
---|
782 | | - mdelay(pdev->d3_delay); |
---|
| 758 | + mdelay(pdev->d3hot_delay); |
---|
783 | 759 | |
---|
784 | 760 | csr &= ~PCI_PM_CTRL_STATE_MASK; |
---|
785 | 761 | csr |= PCI_D0; |
---|
.. | .. |
---|
921 | 897 | init_waitqueue_head(&dev->wait_hw_ready); |
---|
922 | 898 | |
---|
923 | 899 | spin_lock_init(&dev->wr_processing_spinlock); |
---|
924 | | - spin_lock_init(&dev->out_ipc_spinlock); |
---|
925 | 900 | |
---|
926 | 901 | /* Init IPC processing and free lists */ |
---|
927 | | - INIT_LIST_HEAD(&dev->wr_processing_list_head.link); |
---|
928 | | - INIT_LIST_HEAD(&dev->wr_free_list_head.link); |
---|
929 | | - for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) { |
---|
| 902 | + INIT_LIST_HEAD(&dev->wr_processing_list); |
---|
| 903 | + INIT_LIST_HEAD(&dev->wr_free_list); |
---|
| 904 | + for (i = 0; i < IPC_TX_FIFO_SIZE; i++) { |
---|
930 | 905 | struct wr_msg_ctl_info *tx_buf; |
---|
931 | 906 | |
---|
932 | 907 | tx_buf = devm_kzalloc(&pdev->dev, |
---|
.. | .. |
---|
942 | 917 | i); |
---|
943 | 918 | break; |
---|
944 | 919 | } |
---|
945 | | - list_add_tail(&tx_buf->link, &dev->wr_free_list_head.link); |
---|
| 920 | + list_add_tail(&tx_buf->link, &dev->wr_free_list); |
---|
946 | 921 | } |
---|
947 | 922 | |
---|
948 | 923 | dev->ops = &ish_hw_ops; |
---|