Lines Matching +full:pmsg +full:- +full:size
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (c) 2003-2016, Intel Corporation.
12 #include <linux/dma-mapping.h>
18 * ishtp_read_list_flush() - Flush read queue
29 spin_lock_irqsave(&cl->dev->read_list_spinlock, flags); in ishtp_read_list_flush()
30 list_for_each_entry_safe(rb, next, &cl->dev->read_list.list, list) in ishtp_read_list_flush()
31 if (rb->cl && ishtp_cl_cmp_id(cl, rb->cl)) { in ishtp_read_list_flush()
32 list_del(&rb->list); in ishtp_read_list_flush()
33 spin_lock(&cl->free_list_spinlock); in ishtp_read_list_flush()
34 list_add_tail(&rb->list, &cl->free_rb_list.list); in ishtp_read_list_flush()
35 spin_unlock(&cl->free_list_spinlock); in ishtp_read_list_flush()
37 spin_unlock_irqrestore(&cl->dev->read_list_spinlock, flags); in ishtp_read_list_flush()
41 * ishtp_cl_flush_queues() - Flush all queues for a client
47 * Return: 0 on success else -EINVAL if device is NULL
51 if (WARN_ON(!cl || !cl->dev)) in ishtp_cl_flush_queues()
52 return -EINVAL; in ishtp_cl_flush_queues()
61 * ishtp_cl_init() - Initialize all fields of a client device
71 init_waitqueue_head(&cl->wait_ctrl_res); in ishtp_cl_init()
72 spin_lock_init(&cl->free_list_spinlock); in ishtp_cl_init()
73 spin_lock_init(&cl->in_process_spinlock); in ishtp_cl_init()
74 spin_lock_init(&cl->tx_list_spinlock); in ishtp_cl_init()
75 spin_lock_init(&cl->tx_free_list_spinlock); in ishtp_cl_init()
76 spin_lock_init(&cl->fc_spinlock); in ishtp_cl_init()
77 INIT_LIST_HEAD(&cl->link); in ishtp_cl_init()
78 cl->dev = dev; in ishtp_cl_init()
80 INIT_LIST_HEAD(&cl->free_rb_list.list); in ishtp_cl_init()
81 INIT_LIST_HEAD(&cl->tx_list.list); in ishtp_cl_init()
82 INIT_LIST_HEAD(&cl->tx_free_list.list); in ishtp_cl_init()
83 INIT_LIST_HEAD(&cl->in_process_list.list); in ishtp_cl_init()
85 cl->rx_ring_size = CL_DEF_RX_RING_SIZE; in ishtp_cl_init()
86 cl->tx_ring_size = CL_DEF_TX_RING_SIZE; in ishtp_cl_init()
87 cl->tx_ring_free_size = cl->tx_ring_size; in ishtp_cl_init()
90 cl->last_tx_path = CL_TX_PATH_IPC; in ishtp_cl_init()
91 cl->last_dma_acked = 1; in ishtp_cl_init()
92 cl->last_dma_addr = NULL; in ishtp_cl_init()
93 cl->last_ipc_acked = 1; in ishtp_cl_init()
97 * ishtp_cl_allocate() - allocates client structure and sets it up.
112 ishtp_cl_init(cl, cl_device->ishtp_dev); in ishtp_cl_allocate()
118 * ishtp_cl_free() - Frees a client device
131 dev = cl->dev; in ishtp_cl_free()
135 spin_lock_irqsave(&dev->cl_list_lock, flags); in ishtp_cl_free()
139 spin_unlock_irqrestore(&dev->cl_list_lock, flags); in ishtp_cl_free()
144 * ishtp_cl_link() - Reserve a host id and link the client instance
160 if (WARN_ON(!cl || !cl->dev)) in ishtp_cl_link()
161 return -EINVAL; in ishtp_cl_link()
163 dev = cl->dev; in ishtp_cl_link()
165 spin_lock_irqsave(&dev->device_lock, flags); in ishtp_cl_link()
167 if (dev->open_handle_count >= ISHTP_MAX_OPEN_HANDLE_COUNT) { in ishtp_cl_link()
168 ret = -EMFILE; in ishtp_cl_link()
172 id = find_first_zero_bit(dev->host_clients_map, ISHTP_CLIENTS_MAX); in ishtp_cl_link()
175 spin_unlock_irqrestore(&dev->device_lock, flags); in ishtp_cl_link()
176 dev_err(&cl->device->dev, "id exceeded %d", ISHTP_CLIENTS_MAX); in ishtp_cl_link()
177 return -ENOENT; in ishtp_cl_link()
180 dev->open_handle_count++; in ishtp_cl_link()
181 cl->host_client_id = id; in ishtp_cl_link()
182 spin_lock_irqsave(&dev->cl_list_lock, flags_cl); in ishtp_cl_link()
183 if (dev->dev_state != ISHTP_DEV_ENABLED) { in ishtp_cl_link()
184 ret = -ENODEV; in ishtp_cl_link()
187 list_add_tail(&cl->link, &dev->cl_list); in ishtp_cl_link()
188 set_bit(id, dev->host_clients_map); in ishtp_cl_link()
189 cl->state = ISHTP_CL_INITIALIZING; in ishtp_cl_link()
192 spin_unlock_irqrestore(&dev->cl_list_lock, flags_cl); in ishtp_cl_link()
194 spin_unlock_irqrestore(&dev->device_lock, flags); in ishtp_cl_link()
200 * ishtp_cl_unlink() - remove fw_cl from the client device list
212 if (!cl || !cl->dev) in ishtp_cl_unlink()
215 dev = cl->dev; in ishtp_cl_unlink()
217 spin_lock_irqsave(&dev->device_lock, flags); in ishtp_cl_unlink()
218 if (dev->open_handle_count > 0) { in ishtp_cl_unlink()
219 clear_bit(cl->host_client_id, dev->host_clients_map); in ishtp_cl_unlink()
220 dev->open_handle_count--; in ishtp_cl_unlink()
222 spin_unlock_irqrestore(&dev->device_lock, flags); in ishtp_cl_unlink()
228 spin_lock_irqsave(&dev->cl_list_lock, flags); in ishtp_cl_unlink()
229 list_for_each_entry(pos, &dev->cl_list, link) in ishtp_cl_unlink()
230 if (cl->host_client_id == pos->host_client_id) { in ishtp_cl_unlink()
231 list_del_init(&pos->link); in ishtp_cl_unlink()
234 spin_unlock_irqrestore(&dev->cl_list_lock, flags); in ishtp_cl_unlink()
239 * ishtp_cl_disconnect() - Send disconnect request to firmware
251 if (WARN_ON(!cl || !cl->dev)) in ishtp_cl_disconnect()
252 return -ENODEV; in ishtp_cl_disconnect()
254 dev = cl->dev; in ishtp_cl_disconnect()
256 dev->print_log(dev, "%s() state %d\n", __func__, cl->state); in ishtp_cl_disconnect()
258 if (cl->state != ISHTP_CL_DISCONNECTING) { in ishtp_cl_disconnect()
259 dev->print_log(dev, "%s() Disconnect in progress\n", __func__); in ishtp_cl_disconnect()
264 dev->print_log(dev, "%s() Failed to disconnect\n", __func__); in ishtp_cl_disconnect()
265 dev_err(&cl->device->dev, "failed to disconnect.\n"); in ishtp_cl_disconnect()
266 return -ENODEV; in ishtp_cl_disconnect()
269 wait_event_interruptible_timeout(cl->wait_ctrl_res, in ishtp_cl_disconnect()
270 (dev->dev_state != ISHTP_DEV_ENABLED || in ishtp_cl_disconnect()
271 cl->state == ISHTP_CL_DISCONNECTED), in ishtp_cl_disconnect()
275 * If FW reset arrived, this will happen. Don't check cl->, in ishtp_cl_disconnect()
278 if (dev->dev_state != ISHTP_DEV_ENABLED) { in ishtp_cl_disconnect()
279 dev->print_log(dev, "%s() dev_state != ISHTP_DEV_ENABLED\n", in ishtp_cl_disconnect()
281 return -ENODEV; in ishtp_cl_disconnect()
284 if (cl->state == ISHTP_CL_DISCONNECTED) { in ishtp_cl_disconnect()
285 dev->print_log(dev, "%s() successful\n", __func__); in ishtp_cl_disconnect()
289 return -ENODEV; in ishtp_cl_disconnect()
294 * ishtp_cl_is_other_connecting() - Check other client is connecting
307 if (WARN_ON(!cl || !cl->dev)) in ishtp_cl_is_other_connecting()
310 dev = cl->dev; in ishtp_cl_is_other_connecting()
311 spin_lock_irqsave(&dev->cl_list_lock, flags); in ishtp_cl_is_other_connecting()
312 list_for_each_entry(pos, &dev->cl_list, link) { in ishtp_cl_is_other_connecting()
313 if ((pos->state == ISHTP_CL_CONNECTING) && (pos != cl) && in ishtp_cl_is_other_connecting()
314 cl->fw_client_id == pos->fw_client_id) { in ishtp_cl_is_other_connecting()
315 spin_unlock_irqrestore(&dev->cl_list_lock, flags); in ishtp_cl_is_other_connecting()
319 spin_unlock_irqrestore(&dev->cl_list_lock, flags); in ishtp_cl_is_other_connecting()
325 * ishtp_cl_connect_to_fw() - Send connect request to firmware
340 if (WARN_ON(!cl || !cl->dev)) in ishtp_cl_connect_to_fw()
341 return -ENODEV; in ishtp_cl_connect_to_fw()
343 dev = cl->dev; in ishtp_cl_connect_to_fw()
346 dev->print_log(dev, "%s() Busy\n", __func__); in ishtp_cl_connect_to_fw()
347 return -EBUSY; in ishtp_cl_connect_to_fw()
351 dev->print_log(dev, "%s() HBM connect req fail\n", __func__); in ishtp_cl_connect_to_fw()
352 return -ENODEV; in ishtp_cl_connect_to_fw()
355 rets = wait_event_interruptible_timeout(cl->wait_ctrl_res, in ishtp_cl_connect_to_fw()
356 (dev->dev_state == ISHTP_DEV_ENABLED && in ishtp_cl_connect_to_fw()
357 (cl->state == ISHTP_CL_CONNECTED || in ishtp_cl_connect_to_fw()
358 cl->state == ISHTP_CL_DISCONNECTED)), in ishtp_cl_connect_to_fw()
362 * If FW reset arrived, this will happen. Don't check cl->, in ishtp_cl_connect_to_fw()
365 if (dev->dev_state != ISHTP_DEV_ENABLED) { in ishtp_cl_connect_to_fw()
366 dev->print_log(dev, "%s() dev_state != ISHTP_DEV_ENABLED\n", in ishtp_cl_connect_to_fw()
368 return -EFAULT; in ishtp_cl_connect_to_fw()
371 if (cl->state != ISHTP_CL_CONNECTED) { in ishtp_cl_connect_to_fw()
372 dev->print_log(dev, "%s() state != ISHTP_CL_CONNECTED\n", in ishtp_cl_connect_to_fw()
374 return -EFAULT; in ishtp_cl_connect_to_fw()
377 rets = cl->status; in ishtp_cl_connect_to_fw()
379 dev->print_log(dev, "%s() Invalid status\n", __func__); in ishtp_cl_connect_to_fw()
385 dev->print_log(dev, "%s() Bind error\n", __func__); in ishtp_cl_connect_to_fw()
394 * ishtp_cl_connect() - Build connection with firmware
409 if (!cl || !cl->dev) in ishtp_cl_connect()
410 return -ENODEV; in ishtp_cl_connect()
412 dev = cl->dev; in ishtp_cl_connect()
414 dev->print_log(dev, "%s() current_state = %d\n", __func__, cl->state); in ishtp_cl_connect()
418 dev->print_log(dev, "%s() Connect to fw failed\n", __func__); in ishtp_cl_connect()
424 dev->print_log(dev, "%s() Alloc RX ring failed\n", __func__); in ishtp_cl_connect()
432 dev->print_log(dev, "%s() Alloc TX ring failed\n", __func__); in ishtp_cl_connect()
440 * Upon successful connection and allocation, start flow-control. in ishtp_cl_connect()
449 * ishtp_cl_establish_connection() - Establish connection with the firmware
452 * @tx_size: TX ring buffer size
453 * @rx_size: RX ring buffer size
476 if (!cl || !cl->dev) in ishtp_cl_establish_connection()
477 return -ENODEV; in ishtp_cl_establish_connection()
479 dev = cl->dev; in ishtp_cl_establish_connection()
485 cl->host_client_id = 0; in ishtp_cl_establish_connection()
486 cl->fw_client_id = 0; in ishtp_cl_establish_connection()
487 cl->ishtp_flow_ctrl_creds = 0; in ishtp_cl_establish_connection()
488 cl->out_flow_ctrl_creds = 0; in ishtp_cl_establish_connection()
490 cl->last_tx_path = CL_TX_PATH_IPC; in ishtp_cl_establish_connection()
491 cl->last_dma_acked = 1; in ishtp_cl_establish_connection()
492 cl->last_dma_addr = NULL; in ishtp_cl_establish_connection()
493 cl->last_ipc_acked = 1; in ishtp_cl_establish_connection()
495 cl->sending = 0; in ishtp_cl_establish_connection()
496 cl->err_send_msg = 0; in ishtp_cl_establish_connection()
497 cl->err_send_fc = 0; in ishtp_cl_establish_connection()
499 cl->send_msg_cnt_ipc = 0; in ishtp_cl_establish_connection()
500 cl->send_msg_cnt_dma = 0; in ishtp_cl_establish_connection()
501 cl->recv_msg_cnt_ipc = 0; in ishtp_cl_establish_connection()
502 cl->recv_msg_cnt_dma = 0; in ishtp_cl_establish_connection()
503 cl->recv_msg_num_frags = 0; in ishtp_cl_establish_connection()
504 cl->ishtp_flow_ctrl_cnt = 0; in ishtp_cl_establish_connection()
505 cl->out_flow_ctrl_cnt = 0; in ishtp_cl_establish_connection()
511 dev->print_log(dev, "%s() ishtp_cl_link failed\n", __func__); in ishtp_cl_establish_connection()
518 dev->print_log(dev, in ishtp_cl_establish_connection()
520 return -ENOENT; in ishtp_cl_establish_connection()
539 dev->print_log(dev, in ishtp_cl_establish_connection()
550 * ishtp_cl_destroy_connection() - Disconnect with the firmware
569 if (cl->state != ISHTP_CL_DISCONNECTED) { in ishtp_cl_destroy_connection()
581 * ishtp_cl_read_start() - Prepare to read client message
599 if (WARN_ON(!cl || !cl->dev)) in ishtp_cl_read_start()
600 return -ENODEV; in ishtp_cl_read_start()
602 dev = cl->dev; in ishtp_cl_read_start()
604 if (cl->state != ISHTP_CL_CONNECTED) in ishtp_cl_read_start()
605 return -ENODEV; in ishtp_cl_read_start()
607 if (dev->dev_state != ISHTP_DEV_ENABLED) in ishtp_cl_read_start()
608 return -ENODEV; in ishtp_cl_read_start()
610 i = ishtp_fw_cl_by_id(dev, cl->fw_client_id); in ishtp_cl_read_start()
612 dev_err(&cl->device->dev, "no such fw client %d\n", in ishtp_cl_read_start()
613 cl->fw_client_id); in ishtp_cl_read_start()
614 return -ENODEV; in ishtp_cl_read_start()
618 spin_lock_irqsave(&cl->free_list_spinlock, flags); in ishtp_cl_read_start()
619 if (list_empty(&cl->free_rb_list.list)) { in ishtp_cl_read_start()
620 dev_warn(&cl->device->dev, in ishtp_cl_read_start()
621 "[ishtp-ish] Rx buffers pool is empty\n"); in ishtp_cl_read_start()
622 rets = -ENOMEM; in ishtp_cl_read_start()
624 spin_unlock_irqrestore(&cl->free_list_spinlock, flags); in ishtp_cl_read_start()
627 rb = list_entry(cl->free_rb_list.list.next, struct ishtp_cl_rb, list); in ishtp_cl_read_start()
628 list_del_init(&rb->list); in ishtp_cl_read_start()
629 spin_unlock_irqrestore(&cl->free_list_spinlock, flags); in ishtp_cl_read_start()
631 rb->cl = cl; in ishtp_cl_read_start()
632 rb->buf_idx = 0; in ishtp_cl_read_start()
634 INIT_LIST_HEAD(&rb->list); in ishtp_cl_read_start()
638 * This must be BEFORE sending flow control - in ishtp_cl_read_start()
641 spin_lock_irqsave(&dev->read_list_spinlock, dev_flags); in ishtp_cl_read_start()
642 list_add_tail(&rb->list, &dev->read_list.list); in ishtp_cl_read_start()
643 spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags); in ishtp_cl_read_start()
645 rets = -ENODEV; in ishtp_cl_read_start()
651 spin_lock_irqsave(&dev->read_list_spinlock, dev_flags); in ishtp_cl_read_start()
652 list_del(&rb->list); in ishtp_cl_read_start()
653 spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags); in ishtp_cl_read_start()
655 spin_lock_irqsave(&cl->free_list_spinlock, flags); in ishtp_cl_read_start()
656 list_add_tail(&rb->list, &cl->free_rb_list.list); in ishtp_cl_read_start()
657 spin_unlock_irqrestore(&cl->free_list_spinlock, flags); in ishtp_cl_read_start()
663 * ishtp_cl_send() - Send a message to firmware
682 if (WARN_ON(!cl || !cl->dev)) in ishtp_cl_send()
683 return -ENODEV; in ishtp_cl_send()
685 dev = cl->dev; in ishtp_cl_send()
687 if (cl->state != ISHTP_CL_CONNECTED) { in ishtp_cl_send()
688 ++cl->err_send_msg; in ishtp_cl_send()
689 return -EPIPE; in ishtp_cl_send()
692 if (dev->dev_state != ISHTP_DEV_ENABLED) { in ishtp_cl_send()
693 ++cl->err_send_msg; in ishtp_cl_send()
694 return -ENODEV; in ishtp_cl_send()
698 id = ishtp_fw_cl_by_id(dev, cl->fw_client_id); in ishtp_cl_send()
700 ++cl->err_send_msg; in ishtp_cl_send()
701 return -ENOENT; in ishtp_cl_send()
704 if (length > dev->fw_clients[id].props.max_msg_length) { in ishtp_cl_send()
705 ++cl->err_send_msg; in ishtp_cl_send()
706 return -EMSGSIZE; in ishtp_cl_send()
710 spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); in ishtp_cl_send()
711 if (list_empty(&cl->tx_free_list.list)) { in ishtp_cl_send()
712 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, in ishtp_cl_send()
714 ++cl->err_send_msg; in ishtp_cl_send()
715 return -ENOMEM; in ishtp_cl_send()
718 cl_msg = list_first_entry(&cl->tx_free_list.list, in ishtp_cl_send()
720 if (!cl_msg->send_buf.data) { in ishtp_cl_send()
721 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, in ishtp_cl_send()
723 return -EIO; in ishtp_cl_send()
724 /* Should not happen, as free list is pre-allocated */ in ishtp_cl_send()
728 * max ISHTP message size per client in ishtp_cl_send()
730 list_del_init(&cl_msg->list); in ishtp_cl_send()
731 --cl->tx_ring_free_size; in ishtp_cl_send()
733 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); in ishtp_cl_send()
734 memcpy(cl_msg->send_buf.data, buf, length); in ishtp_cl_send()
735 cl_msg->send_buf.size = length; in ishtp_cl_send()
736 spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags); in ishtp_cl_send()
737 have_msg_to_send = !list_empty(&cl->tx_list.list); in ishtp_cl_send()
738 list_add_tail(&cl_msg->list, &cl->tx_list.list); in ishtp_cl_send()
739 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); in ishtp_cl_send()
741 if (!have_msg_to_send && cl->ishtp_flow_ctrl_creds > 0) in ishtp_cl_send()
749 * ishtp_cl_read_complete() - read complete
759 struct ishtp_cl *cl = rb->cl; in ishtp_cl_read_complete()
761 spin_lock_irqsave(&cl->in_process_spinlock, flags); in ishtp_cl_read_complete()
763 * if in-process list is empty, then need to schedule in ishtp_cl_read_complete()
766 schedule_work_flag = list_empty(&cl->in_process_list.list); in ishtp_cl_read_complete()
767 list_add_tail(&rb->list, &cl->in_process_list.list); in ishtp_cl_read_complete()
768 spin_unlock_irqrestore(&cl->in_process_spinlock, flags); in ishtp_cl_read_complete()
771 ishtp_cl_bus_rx_event(cl->device); in ishtp_cl_read_complete()
775 * ipc_tx_send() - IPC tx send function
779 * if message size is bigger than IPC FIFO size, and all
787 struct ishtp_device *dev = (cl ? cl->dev : NULL); in ipc_tx_send()
790 unsigned char *pmsg; in ipc_tx_send() local
799 if (dev->dev_state != ISHTP_DEV_ENABLED) in ipc_tx_send()
802 if (cl->state != ISHTP_CL_CONNECTED) in ipc_tx_send()
805 spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags); in ipc_tx_send()
806 if (list_empty(&cl->tx_list.list)) { in ipc_tx_send()
807 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); in ipc_tx_send()
811 if (cl->ishtp_flow_ctrl_creds != 1 && !cl->sending) { in ipc_tx_send()
812 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); in ipc_tx_send()
816 if (!cl->sending) { in ipc_tx_send()
817 --cl->ishtp_flow_ctrl_creds; in ipc_tx_send()
818 cl->last_ipc_acked = 0; in ipc_tx_send()
819 cl->last_tx_path = CL_TX_PATH_IPC; in ipc_tx_send()
820 cl->sending = 1; in ipc_tx_send()
823 cl_msg = list_entry(cl->tx_list.list.next, struct ishtp_cl_tx_ring, in ipc_tx_send()
825 rem = cl_msg->send_buf.size - cl->tx_offs; in ipc_tx_send()
828 ishtp_hdr.host_addr = cl->host_client_id; in ipc_tx_send()
829 ishtp_hdr.fw_addr = cl->fw_client_id; in ipc_tx_send()
831 pmsg = cl_msg->send_buf.data + cl->tx_offs; in ipc_tx_send()
833 if (rem <= dev->mtu) { in ipc_tx_send()
838 ishtp_write_message(dev, &ishtp_hdr, pmsg); in ipc_tx_send()
839 cl->tx_offs = 0; in ipc_tx_send()
840 cl->sending = 0; in ipc_tx_send()
845 ishtp_hdr.length = dev->mtu; in ipc_tx_send()
848 ishtp_write_message(dev, &ishtp_hdr, pmsg); in ipc_tx_send()
849 cl->tx_offs += dev->mtu; in ipc_tx_send()
850 rem = cl_msg->send_buf.size - cl->tx_offs; in ipc_tx_send()
854 list_del_init(&cl_msg->list); in ipc_tx_send()
855 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); in ipc_tx_send()
857 spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); in ipc_tx_send()
858 list_add_tail(&cl_msg->list, &cl->tx_free_list.list); in ipc_tx_send()
859 ++cl->tx_ring_free_size; in ipc_tx_send()
860 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, in ipc_tx_send()
865 * ishtp_cl_send_msg_ipc() -Send message using IPC
875 if (cl->last_tx_path == CL_TX_PATH_DMA && cl->last_dma_acked == 0) in ishtp_cl_send_msg_ipc()
878 cl->tx_offs = 0; in ishtp_cl_send_msg_ipc()
880 ++cl->send_msg_cnt_ipc; in ishtp_cl_send_msg_ipc()
884 * ishtp_cl_send_msg_dma() -Send message using DMA
901 if (cl->last_tx_path == CL_TX_PATH_IPC && cl->last_ipc_acked == 0) in ishtp_cl_send_msg_dma()
904 spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags); in ishtp_cl_send_msg_dma()
905 if (list_empty(&cl->tx_list.list)) { in ishtp_cl_send_msg_dma()
906 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); in ishtp_cl_send_msg_dma()
910 cl_msg = list_entry(cl->tx_list.list.next, struct ishtp_cl_tx_ring, in ishtp_cl_send_msg_dma()
913 msg_addr = ishtp_cl_get_dma_send_buf(dev, cl_msg->send_buf.size); in ishtp_cl_send_msg_dma()
915 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); in ishtp_cl_send_msg_dma()
916 if (dev->transfer_path == CL_TX_PATH_DEFAULT) in ishtp_cl_send_msg_dma()
921 list_del_init(&cl_msg->list); /* Must be before write */ in ishtp_cl_send_msg_dma()
922 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); in ishtp_cl_send_msg_dma()
924 --cl->ishtp_flow_ctrl_creds; in ishtp_cl_send_msg_dma()
925 cl->last_dma_acked = 0; in ishtp_cl_send_msg_dma()
926 cl->last_dma_addr = msg_addr; in ishtp_cl_send_msg_dma()
927 cl->last_tx_path = CL_TX_PATH_DMA; in ishtp_cl_send_msg_dma()
930 memcpy(msg_addr, cl_msg->send_buf.data, cl_msg->send_buf.size); in ishtp_cl_send_msg_dma()
936 if (dev->ops->dma_no_cache_snooping && in ishtp_cl_send_msg_dma()
937 dev->ops->dma_no_cache_snooping(dev)) in ishtp_cl_send_msg_dma()
938 clflush_cache_range(msg_addr, cl_msg->send_buf.size); in ishtp_cl_send_msg_dma()
941 off = msg_addr - (unsigned char *)dev->ishtp_host_dma_tx_buf; in ishtp_cl_send_msg_dma()
944 dma_xfer.fw_client_id = cl->fw_client_id; in ishtp_cl_send_msg_dma()
945 dma_xfer.host_client_id = cl->host_client_id; in ishtp_cl_send_msg_dma()
947 dma_xfer.msg_addr = dev->ishtp_host_dma_tx_buf_phys + off; in ishtp_cl_send_msg_dma()
948 dma_xfer.msg_length = cl_msg->send_buf.size; in ishtp_cl_send_msg_dma()
951 spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); in ishtp_cl_send_msg_dma()
952 list_add_tail(&cl_msg->list, &cl->tx_free_list.list); in ishtp_cl_send_msg_dma()
953 ++cl->tx_ring_free_size; in ishtp_cl_send_msg_dma()
954 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); in ishtp_cl_send_msg_dma()
955 ++cl->send_msg_cnt_dma; in ishtp_cl_send_msg_dma()
959 * ishtp_cl_send_msg() -Send message using DMA or IPC
967 if (dev->transfer_path == CL_TX_PATH_DMA) in ishtp_cl_send_msg()
974 * recv_ishtp_cl_msg() -Receive client message
991 if (ishtp_hdr->reserved) { in recv_ishtp_cl_msg()
992 dev_err(dev->devc, "corrupted message header.\n"); in recv_ishtp_cl_msg()
996 if (ishtp_hdr->length > IPC_PAYLOAD_SIZE) { in recv_ishtp_cl_msg()
997 dev_err(dev->devc, in recv_ishtp_cl_msg()
1002 spin_lock_irqsave(&dev->read_list_spinlock, flags); in recv_ishtp_cl_msg()
1003 list_for_each_entry(rb, &dev->read_list.list, list) { in recv_ishtp_cl_msg()
1004 cl = rb->cl; in recv_ishtp_cl_msg()
1005 if (!cl || !(cl->host_client_id == ishtp_hdr->host_addr && in recv_ishtp_cl_msg()
1006 cl->fw_client_id == ishtp_hdr->fw_addr) || in recv_ishtp_cl_msg()
1007 !(cl->state == ISHTP_CL_CONNECTED)) in recv_ishtp_cl_msg()
1011 if (rb->buffer.size == 0 || rb->buffer.data == NULL) { in recv_ishtp_cl_msg()
1012 spin_unlock_irqrestore(&dev->read_list_spinlock, flags); in recv_ishtp_cl_msg()
1013 dev_err(&cl->device->dev, in recv_ishtp_cl_msg()
1015 list_del(&rb->list); in recv_ishtp_cl_msg()
1017 cl->status = -ENOMEM; in recv_ishtp_cl_msg()
1023 * size, drop message and return to free buffer. in recv_ishtp_cl_msg()
1027 if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) { in recv_ishtp_cl_msg()
1028 spin_unlock_irqrestore(&dev->read_list_spinlock, flags); in recv_ishtp_cl_msg()
1029 dev_err(&cl->device->dev, in recv_ishtp_cl_msg()
1030 "message overflow. size %d len %d idx %ld\n", in recv_ishtp_cl_msg()
1031 rb->buffer.size, ishtp_hdr->length, in recv_ishtp_cl_msg()
1032 rb->buf_idx); in recv_ishtp_cl_msg()
1033 list_del(&rb->list); in recv_ishtp_cl_msg()
1035 cl->status = -EIO; in recv_ishtp_cl_msg()
1039 buffer = rb->buffer.data + rb->buf_idx; in recv_ishtp_cl_msg()
1040 dev->ops->ishtp_read(dev, buffer, ishtp_hdr->length); in recv_ishtp_cl_msg()
1042 rb->buf_idx += ishtp_hdr->length; in recv_ishtp_cl_msg()
1043 if (ishtp_hdr->msg_complete) { in recv_ishtp_cl_msg()
1044 /* Last fragment in message - it's complete */ in recv_ishtp_cl_msg()
1045 cl->status = 0; in recv_ishtp_cl_msg()
1046 list_del(&rb->list); in recv_ishtp_cl_msg()
1049 --cl->out_flow_ctrl_creds; in recv_ishtp_cl_msg()
1054 spin_lock(&cl->free_list_spinlock); in recv_ishtp_cl_msg()
1056 if (!list_empty(&cl->free_rb_list.list)) { in recv_ishtp_cl_msg()
1057 new_rb = list_entry(cl->free_rb_list.list.next, in recv_ishtp_cl_msg()
1059 list_del_init(&new_rb->list); in recv_ishtp_cl_msg()
1060 spin_unlock(&cl->free_list_spinlock); in recv_ishtp_cl_msg()
1061 new_rb->cl = cl; in recv_ishtp_cl_msg()
1062 new_rb->buf_idx = 0; in recv_ishtp_cl_msg()
1063 INIT_LIST_HEAD(&new_rb->list); in recv_ishtp_cl_msg()
1064 list_add_tail(&new_rb->list, in recv_ishtp_cl_msg()
1065 &dev->read_list.list); in recv_ishtp_cl_msg()
1069 spin_unlock(&cl->free_list_spinlock); in recv_ishtp_cl_msg()
1073 ++cl->recv_msg_num_frags; in recv_ishtp_cl_msg()
1082 spin_unlock_irqrestore(&dev->read_list_spinlock, flags); in recv_ishtp_cl_msg()
1087 dev_err(dev->devc, "Dropped Rx msg - no request\n"); in recv_ishtp_cl_msg()
1088 dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length); in recv_ishtp_cl_msg()
1093 cl = complete_rb->cl; in recv_ishtp_cl_msg()
1094 cl->ts_rx = ktime_get(); in recv_ishtp_cl_msg()
1095 ++cl->recv_msg_cnt_ipc; in recv_ishtp_cl_msg()
1103 * recv_ishtp_cl_msg_dma() -Receive client message
1121 spin_lock_irqsave(&dev->read_list_spinlock, flags); in recv_ishtp_cl_msg_dma()
1123 list_for_each_entry(rb, &dev->read_list.list, list) { in recv_ishtp_cl_msg_dma()
1124 cl = rb->cl; in recv_ishtp_cl_msg_dma()
1125 if (!cl || !(cl->host_client_id == hbm->host_client_id && in recv_ishtp_cl_msg_dma()
1126 cl->fw_client_id == hbm->fw_client_id) || in recv_ishtp_cl_msg_dma()
1127 !(cl->state == ISHTP_CL_CONNECTED)) in recv_ishtp_cl_msg_dma()
1133 if (rb->buffer.size == 0 || rb->buffer.data == NULL) { in recv_ishtp_cl_msg_dma()
1134 spin_unlock_irqrestore(&dev->read_list_spinlock, flags); in recv_ishtp_cl_msg_dma()
1135 dev_err(&cl->device->dev, in recv_ishtp_cl_msg_dma()
1137 list_del(&rb->list); in recv_ishtp_cl_msg_dma()
1139 cl->status = -ENOMEM; in recv_ishtp_cl_msg_dma()
1145 * size, drop message and return to free buffer. in recv_ishtp_cl_msg_dma()
1149 if (rb->buffer.size < hbm->msg_length) { in recv_ishtp_cl_msg_dma()
1150 spin_unlock_irqrestore(&dev->read_list_spinlock, flags); in recv_ishtp_cl_msg_dma()
1151 dev_err(&cl->device->dev, in recv_ishtp_cl_msg_dma()
1152 "message overflow. size %d len %d idx %ld\n", in recv_ishtp_cl_msg_dma()
1153 rb->buffer.size, hbm->msg_length, rb->buf_idx); in recv_ishtp_cl_msg_dma()
1154 list_del(&rb->list); in recv_ishtp_cl_msg_dma()
1156 cl->status = -EIO; in recv_ishtp_cl_msg_dma()
1160 buffer = rb->buffer.data; in recv_ishtp_cl_msg_dma()
1166 if (dev->ops->dma_no_cache_snooping && in recv_ishtp_cl_msg_dma()
1167 dev->ops->dma_no_cache_snooping(dev)) in recv_ishtp_cl_msg_dma()
1168 clflush_cache_range(msg, hbm->msg_length); in recv_ishtp_cl_msg_dma()
1170 memcpy(buffer, msg, hbm->msg_length); in recv_ishtp_cl_msg_dma()
1171 rb->buf_idx = hbm->msg_length; in recv_ishtp_cl_msg_dma()
1173 /* Last fragment in message - it's complete */ in recv_ishtp_cl_msg_dma()
1174 cl->status = 0; in recv_ishtp_cl_msg_dma()
1175 list_del(&rb->list); in recv_ishtp_cl_msg_dma()
1178 --cl->out_flow_ctrl_creds; in recv_ishtp_cl_msg_dma()
1183 spin_lock(&cl->free_list_spinlock); in recv_ishtp_cl_msg_dma()
1185 if (!list_empty(&cl->free_rb_list.list)) { in recv_ishtp_cl_msg_dma()
1186 new_rb = list_entry(cl->free_rb_list.list.next, in recv_ishtp_cl_msg_dma()
1188 list_del_init(&new_rb->list); in recv_ishtp_cl_msg_dma()
1189 spin_unlock(&cl->free_list_spinlock); in recv_ishtp_cl_msg_dma()
1190 new_rb->cl = cl; in recv_ishtp_cl_msg_dma()
1191 new_rb->buf_idx = 0; in recv_ishtp_cl_msg_dma()
1192 INIT_LIST_HEAD(&new_rb->list); in recv_ishtp_cl_msg_dma()
1193 list_add_tail(&new_rb->list, in recv_ishtp_cl_msg_dma()
1194 &dev->read_list.list); in recv_ishtp_cl_msg_dma()
1198 spin_unlock(&cl->free_list_spinlock); in recv_ishtp_cl_msg_dma()
1202 ++cl->recv_msg_num_frags; in recv_ishtp_cl_msg_dma()
1211 spin_unlock_irqrestore(&dev->read_list_spinlock, flags); in recv_ishtp_cl_msg_dma()
1214 dev_err(dev->devc, "Dropped Rx (DMA) msg - no request\n"); in recv_ishtp_cl_msg_dma()
1219 cl = complete_rb->cl; in recv_ishtp_cl_msg_dma()
1220 cl->ts_rx = ktime_get(); in recv_ishtp_cl_msg_dma()
1221 ++cl->recv_msg_cnt_dma; in recv_ishtp_cl_msg_dma()
1230 return cl->client_data; in ishtp_get_client_data()
1236 cl->client_data = data; in ishtp_set_client_data()
1242 return cl->dev; in ishtp_get_ishtp_device()
1246 void ishtp_set_tx_ring_size(struct ishtp_cl *cl, int size) in ishtp_set_tx_ring_size() argument
1248 cl->tx_ring_size = size; in ishtp_set_tx_ring_size()
1252 void ishtp_set_rx_ring_size(struct ishtp_cl *cl, int size) in ishtp_set_rx_ring_size() argument
1254 cl->rx_ring_size = size; in ishtp_set_rx_ring_size()
1260 cl->state = state; in ishtp_set_connection_state()
1266 cl->fw_client_id = fw_client_id; in ishtp_cl_set_fw_client_id()