hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/hid/intel-ish-hid/ishtp/client.c
....@@ -1,17 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * ISHTP client logic
34 *
45 * Copyright (c) 2003-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
- *
156 */
167
178 #include <linux/slab.h>
....@@ -21,6 +12,25 @@
2112 #include <linux/dma-mapping.h>
2213 #include "hbm.h"
2314 #include "client.h"
15
+
16
+int ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl)
17
+{
18
+ unsigned long tx_free_flags;
19
+ int size;
20
+
21
+ spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
22
+ size = cl->tx_ring_free_size * cl->device->fw_client->props.max_msg_length;
23
+ spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags);
24
+
25
+ return size;
26
+}
27
+EXPORT_SYMBOL(ishtp_cl_get_tx_free_buffer_size);
28
+
29
+int ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl)
30
+{
31
+ return cl->tx_ring_free_size;
32
+}
33
+EXPORT_SYMBOL(ishtp_cl_get_tx_free_rings);
2434
2535 /**
2636 * ishtp_read_list_flush() - Flush read queue
....@@ -90,6 +100,7 @@
90100
91101 cl->rx_ring_size = CL_DEF_RX_RING_SIZE;
92102 cl->tx_ring_size = CL_DEF_TX_RING_SIZE;
103
+ cl->tx_ring_free_size = cl->tx_ring_size;
93104
94105 /* dma */
95106 cl->last_tx_path = CL_TX_PATH_IPC;
....@@ -106,7 +117,7 @@
106117 *
107118 * Return: The allocated client instance or NULL on failure
108119 */
109
-struct ishtp_cl *ishtp_cl_allocate(struct ishtp_device *dev)
120
+struct ishtp_cl *ishtp_cl_allocate(struct ishtp_cl_device *cl_device)
110121 {
111122 struct ishtp_cl *cl;
112123
....@@ -114,7 +125,7 @@
114125 if (!cl)
115126 return NULL;
116127
117
- ishtp_cl_init(cl, dev);
128
+ ishtp_cl_init(cl, cl_device->ishtp_dev);
118129 return cl;
119130 }
120131 EXPORT_SYMBOL(ishtp_cl_allocate);
....@@ -148,9 +159,6 @@
148159 /**
149160 * ishtp_cl_link() - Reserve a host id and link the client instance
150161 * @cl: client device instance
151
- * @id: host client id to use. It can be ISHTP_HOST_CLIENT_ID_ANY if any
152
- * id from the available can be used
153
- *
154162 *
155163 * This allocates a single bit in the hostmap. This function will make sure
156164 * that not many client sessions are opened at the same time. Once allocated
....@@ -159,11 +167,11 @@
159167 *
160168 * Return: 0 or error code on failure
161169 */
162
-int ishtp_cl_link(struct ishtp_cl *cl, int id)
170
+int ishtp_cl_link(struct ishtp_cl *cl)
163171 {
164172 struct ishtp_device *dev;
165
- unsigned long flags, flags_cl;
166
- int ret = 0;
173
+ unsigned long flags, flags_cl;
174
+ int id, ret = 0;
167175
168176 if (WARN_ON(!cl || !cl->dev))
169177 return -EINVAL;
....@@ -177,10 +185,7 @@
177185 goto unlock_dev;
178186 }
179187
180
- /* If Id is not assigned get one*/
181
- if (id == ISHTP_HOST_CLIENT_ID_ANY)
182
- id = find_first_zero_bit(dev->host_clients_map,
183
- ISHTP_CLIENTS_MAX);
188
+ id = find_first_zero_bit(dev->host_clients_map, ISHTP_CLIENTS_MAX);
184189
185190 if (id >= ISHTP_CLIENTS_MAX) {
186191 spin_unlock_irqrestore(&dev->device_lock, flags);
....@@ -577,6 +582,8 @@
577582 * max ISHTP message size per client
578583 */
579584 list_del_init(&cl_msg->list);
585
+ --cl->tx_ring_free_size;
586
+
580587 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags);
581588 memcpy(cl_msg->send_buf.data, buf, length);
582589 cl_msg->send_buf.size = length;
....@@ -619,13 +626,14 @@
619626 }
620627
621628 /**
622
- * ipc_tx_callback() - IPC tx callback function
629
+ * ipc_tx_send() - IPC tx send function
623630 * @prm: Pointer to client device instance
624631 *
625
- * Send message over IPC either first time or on callback on previous message
626
- * completion
632
+ * Send message over IPC. Message will be split into fragments
633
+ * if message size is bigger than IPC FIFO size, and all
634
+ * fragments will be sent one by one.
627635 */
628
-static void ipc_tx_callback(void *prm)
636
+static void ipc_tx_send(void *prm)
629637 {
630638 struct ishtp_cl *cl = prm;
631639 struct ishtp_cl_tx_ring *cl_msg;
....@@ -670,31 +678,41 @@
670678 list);
671679 rem = cl_msg->send_buf.size - cl->tx_offs;
672680
673
- ishtp_hdr.host_addr = cl->host_client_id;
674
- ishtp_hdr.fw_addr = cl->fw_client_id;
675
- ishtp_hdr.reserved = 0;
676
- pmsg = cl_msg->send_buf.data + cl->tx_offs;
681
+ while (rem > 0) {
682
+ ishtp_hdr.host_addr = cl->host_client_id;
683
+ ishtp_hdr.fw_addr = cl->fw_client_id;
684
+ ishtp_hdr.reserved = 0;
685
+ pmsg = cl_msg->send_buf.data + cl->tx_offs;
677686
678
- if (rem <= dev->mtu) {
679
- ishtp_hdr.length = rem;
680
- ishtp_hdr.msg_complete = 1;
681
- cl->sending = 0;
682
- list_del_init(&cl_msg->list); /* Must be before write */
683
- spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
684
- /* Submit to IPC queue with no callback */
685
- ishtp_write_message(dev, &ishtp_hdr, pmsg);
686
- spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
687
- list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
688
- spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
689
- tx_free_flags);
690
- } else {
691
- /* Send IPC fragment */
692
- spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
693
- cl->tx_offs += dev->mtu;
694
- ishtp_hdr.length = dev->mtu;
695
- ishtp_hdr.msg_complete = 0;
696
- ishtp_send_msg(dev, &ishtp_hdr, pmsg, ipc_tx_callback, cl);
687
+ if (rem <= dev->mtu) {
688
+ /* Last fragment or only one packet */
689
+ ishtp_hdr.length = rem;
690
+ ishtp_hdr.msg_complete = 1;
691
+ /* Submit to IPC queue with no callback */
692
+ ishtp_write_message(dev, &ishtp_hdr, pmsg);
693
+ cl->tx_offs = 0;
694
+ cl->sending = 0;
695
+
696
+ break;
697
+ } else {
698
+ /* Send ipc fragment */
699
+ ishtp_hdr.length = dev->mtu;
700
+ ishtp_hdr.msg_complete = 0;
701
+ /* All fregments submitted to IPC queue with no callback */
702
+ ishtp_write_message(dev, &ishtp_hdr, pmsg);
703
+ cl->tx_offs += dev->mtu;
704
+ rem = cl_msg->send_buf.size - cl->tx_offs;
705
+ }
697706 }
707
+
708
+ list_del_init(&cl_msg->list);
709
+ spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
710
+
711
+ spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
712
+ list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
713
+ ++cl->tx_ring_free_size;
714
+ spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
715
+ tx_free_flags);
698716 }
699717
700718 /**
....@@ -712,7 +730,7 @@
712730 return;
713731
714732 cl->tx_offs = 0;
715
- ipc_tx_callback(cl);
733
+ ipc_tx_send(cl);
716734 ++cl->send_msg_cnt_ipc;
717735 }
718736
....@@ -778,6 +796,7 @@
778796 ishtp_write_message(dev, &hdr, (unsigned char *)&dma_xfer);
779797 spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
780798 list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
799
+ ++cl->tx_ring_free_size;
781800 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags);
782801 ++cl->send_msg_cnt_dma;
783802 }
....@@ -1045,3 +1064,45 @@
10451064 eoi:
10461065 return;
10471066 }
1067
+
1068
+void *ishtp_get_client_data(struct ishtp_cl *cl)
1069
+{
1070
+ return cl->client_data;
1071
+}
1072
+EXPORT_SYMBOL(ishtp_get_client_data);
1073
+
1074
+void ishtp_set_client_data(struct ishtp_cl *cl, void *data)
1075
+{
1076
+ cl->client_data = data;
1077
+}
1078
+EXPORT_SYMBOL(ishtp_set_client_data);
1079
+
1080
+struct ishtp_device *ishtp_get_ishtp_device(struct ishtp_cl *cl)
1081
+{
1082
+ return cl->dev;
1083
+}
1084
+EXPORT_SYMBOL(ishtp_get_ishtp_device);
1085
+
1086
+void ishtp_set_tx_ring_size(struct ishtp_cl *cl, int size)
1087
+{
1088
+ cl->tx_ring_size = size;
1089
+}
1090
+EXPORT_SYMBOL(ishtp_set_tx_ring_size);
1091
+
1092
+void ishtp_set_rx_ring_size(struct ishtp_cl *cl, int size)
1093
+{
1094
+ cl->rx_ring_size = size;
1095
+}
1096
+EXPORT_SYMBOL(ishtp_set_rx_ring_size);
1097
+
1098
+void ishtp_set_connection_state(struct ishtp_cl *cl, int state)
1099
+{
1100
+ cl->state = state;
1101
+}
1102
+EXPORT_SYMBOL(ishtp_set_connection_state);
1103
+
1104
+void ishtp_cl_set_fw_client_id(struct ishtp_cl *cl, int fw_client_id)
1105
+{
1106
+ cl->fw_client_id = fw_client_id;
1107
+}
1108
+EXPORT_SYMBOL(ishtp_cl_set_fw_client_id);