| .. | .. |
|---|
| 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; |
|---|