aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2016-08-07 05:25:34 -0400
committerJiri Kosina <jkosina@suse.cz>2016-08-17 05:13:07 -0400
commit3703f53b99e4a7c373ce3568dd3f91f175ebb626 (patch)
treedd49617d6ba5537349792f1e0349957912491186
parent17e2adf2a7d755e17fa75495d29cb98d553d4a66 (diff)
HID: intel_ish-hid: ISH Transport layer
The ISH transport layer (ishtp) is a bi-directional protocol implemented on the top of PCI based inter processor communication layer. This layer offers: - Connection management - Flow control with the firmware - Multiple client sessions - Client message transfer - Client message reception - DMA for RX and TX for fast data transfer Refer to Documentation/hid/intel-ish-hid.txt for overview of the functionality implemented in this layer. Original-author: Daniel Drubin <daniel.drubin@intel.com> Reviewed-and-tested-by: Ooi, Joyce <joyce.ooi@intel.com> Tested-by: Grant Likely <grant.likely@secretlab.ca> Tested-by: Rann Bar-On <rb6@duke.edu> Tested-by: Atri Bhattacharya <badshah400@aim.com> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/Kconfig2
-rw-r--r--drivers/hid/Makefile2
-rw-r--r--drivers/hid/intel-ish-hid/Kconfig17
-rw-r--r--drivers/hid/intel-ish-hid/Makefile12
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/bus.c791
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/bus.h114
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/client-buffers.c258
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/client.c1054
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/client.h182
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/dma-if.c175
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/hbm.c1032
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/hbm.h321
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/init.c115
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h277
14 files changed, 4352 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 78ac4811bd3c..5f590e16e41b 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -967,4 +967,6 @@ source "drivers/hid/usbhid/Kconfig"
967 967
968source "drivers/hid/i2c-hid/Kconfig" 968source "drivers/hid/i2c-hid/Kconfig"
969 969
970source "drivers/hid/intel-ish-hid/Kconfig"
971
970endmenu 972endmenu
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index fc4b2aa47f2e..86b2b5785fd2 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -113,3 +113,5 @@ obj-$(CONFIG_USB_MOUSE) += usbhid/
113obj-$(CONFIG_USB_KBD) += usbhid/ 113obj-$(CONFIG_USB_KBD) += usbhid/
114 114
115obj-$(CONFIG_I2C_HID) += i2c-hid/ 115obj-$(CONFIG_I2C_HID) += i2c-hid/
116
117obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/
diff --git a/drivers/hid/intel-ish-hid/Kconfig b/drivers/hid/intel-ish-hid/Kconfig
new file mode 100644
index 000000000000..ea065b3684a2
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/Kconfig
@@ -0,0 +1,17 @@
1menu "Intel ISH HID support"
2 depends on X86_64 && PCI
3
4config INTEL_ISH_HID
5 tristate "Intel Integrated Sensor Hub"
6 default n
7 select HID
8 help
9 The Integrated Sensor Hub (ISH) enables the ability to offload
10 sensor polling and algorithm processing to a dedicated low power
11 processor in the chipset. This allows the core processor to go into
12 low power modes more often, resulting in the increased battery life.
13 The current processors that support ISH are: Cherrytrail, Skylake,
14 Broxton and Kaby Lake.
15
16 Say Y here if you want to support Intel ISH. If unsure, say N.
17endmenu
diff --git a/drivers/hid/intel-ish-hid/Makefile b/drivers/hid/intel-ish-hid/Makefile
new file mode 100644
index 000000000000..7b32d49624ae
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile - Intel ISH HID drivers
3# Copyright (c) 2014-2016, Intel Corporation.
4#
5#
6obj-$(CONFIG_INTEL_ISH_HID) += intel-ishtp.o
7intel-ishtp-objs := ishtp/init.o
8intel-ishtp-objs += ishtp/hbm.o
9intel-ishtp-objs += ishtp/client.o
10intel-ishtp-objs += ishtp/bus.o
11intel-ishtp-objs += ishtp/dma-if.o
12intel-ishtp-objs += ishtp/client-buffers.o
diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c
new file mode 100644
index 000000000000..0183eacaf6c9
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/bus.c
@@ -0,0 +1,791 @@
1/*
2 * ISHTP bus driver
3 *
4 * Copyright (c) 2012-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 */
15
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/kernel.h>
20#include <linux/device.h>
21#include <linux/sched.h>
22#include <linux/slab.h>
23#include "bus.h"
24#include "ishtp-dev.h"
25#include "client.h"
26#include "hbm.h"
27
28static int ishtp_use_dma;
29module_param_named(ishtp_use_dma, ishtp_use_dma, int, 0600);
30MODULE_PARM_DESC(ishtp_use_dma, "Use DMA to send messages");
31
32#define to_ishtp_cl_driver(d) container_of(d, struct ishtp_cl_driver, driver)
33#define to_ishtp_cl_device(d) container_of(d, struct ishtp_cl_device, dev)
34static bool ishtp_device_ready;
35
36/**
37 * ishtp_recv() - process ishtp message
38 * @dev: ishtp device
39 *
40 * If a message with valid header and size is received, then
41 * this function calls appropriate handler. The host or firmware
42 * address is zero, then they are host bus management message,
43 * otherwise they are message fo clients.
44 */
45void ishtp_recv(struct ishtp_device *dev)
46{
47 uint32_t msg_hdr;
48 struct ishtp_msg_hdr *ishtp_hdr;
49
50 /* Read ISHTP header dword */
51 msg_hdr = dev->ops->ishtp_read_hdr(dev);
52 if (!msg_hdr)
53 return;
54
55 dev->ops->sync_fw_clock(dev);
56
57 ishtp_hdr = (struct ishtp_msg_hdr *)&msg_hdr;
58 dev->ishtp_msg_hdr = msg_hdr;
59
60 /* Sanity check: ISHTP frag. length in header */
61 if (ishtp_hdr->length > dev->mtu) {
62 dev_err(dev->devc,
63 "ISHTP hdr - bad length: %u; dropped [%08X]\n",
64 (unsigned int)ishtp_hdr->length, msg_hdr);
65 return;
66 }
67
68 /* ISHTP bus message */
69 if (!ishtp_hdr->host_addr && !ishtp_hdr->fw_addr)
70 recv_hbm(dev, ishtp_hdr);
71 /* ISHTP fixed-client message */
72 else if (!ishtp_hdr->host_addr)
73 recv_fixed_cl_msg(dev, ishtp_hdr);
74 else
75 /* ISHTP client message */
76 recv_ishtp_cl_msg(dev, ishtp_hdr);
77}
78EXPORT_SYMBOL(ishtp_recv);
79
80/**
81 * ishtp_send_msg() - Send ishtp message
82 * @dev: ishtp device
83 * @hdr: Message header
84 * @msg: Message contents
85 * @ipc_send_compl: completion callback
86 * @ipc_send_compl_prm: completion callback parameter
87 *
88 * Send a multi fragment message via IPC. After sending the first fragment
89 * the completion callback is called to schedule transmit of next fragment.
90 *
91 * Return: This returns IPC send message status.
92 */
93int ishtp_send_msg(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr,
94 void *msg, void(*ipc_send_compl)(void *),
95 void *ipc_send_compl_prm)
96{
97 unsigned char ipc_msg[IPC_FULL_MSG_SIZE];
98 uint32_t drbl_val;
99
100 drbl_val = dev->ops->ipc_get_header(dev, hdr->length +
101 sizeof(struct ishtp_msg_hdr),
102 1);
103
104 memcpy(ipc_msg, &drbl_val, sizeof(uint32_t));
105 memcpy(ipc_msg + sizeof(uint32_t), hdr, sizeof(uint32_t));
106 memcpy(ipc_msg + 2 * sizeof(uint32_t), msg, hdr->length);
107 return dev->ops->write(dev, ipc_send_compl, ipc_send_compl_prm,
108 ipc_msg, 2 * sizeof(uint32_t) + hdr->length);
109}
110
111/**
112 * ishtp_write_message() - Send ishtp single fragment message
113 * @dev: ishtp device
114 * @hdr: Message header
115 * @buf: message data
116 *
117 * Send a single fragment message via IPC. This returns IPC send message
118 * status.
119 *
120 * Return: This returns IPC send message status.
121 */
122int ishtp_write_message(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr,
123 unsigned char *buf)
124{
125 return ishtp_send_msg(dev, hdr, buf, NULL, NULL);
126}
127
128/**
129 * ishtp_fw_cl_by_uuid() - locate index of fw client
130 * @dev: ishtp device
131 * @uuid: uuid of the client to search
132 *
133 * Search firmware client using UUID.
134 *
135 * Return: fw client index or -ENOENT if not found
136 */
137int ishtp_fw_cl_by_uuid(struct ishtp_device *dev, const uuid_le *uuid)
138{
139 int i, res = -ENOENT;
140
141 for (i = 0; i < dev->fw_clients_num; ++i) {
142 if (uuid_le_cmp(*uuid, dev->fw_clients[i].props.protocol_name)
143 == 0) {
144 res = i;
145 break;
146 }
147 }
148 return res;
149}
150EXPORT_SYMBOL(ishtp_fw_cl_by_uuid);
151
152/**
153 * ishtp_fw_cl_by_id() - return index to fw_clients for client_id
154 * @dev: the ishtp device structure
155 * @client_id: fw client id to search
156 *
157 * Search firmware client using client id.
158 *
159 * Return: index on success, -ENOENT on failure.
160 */
161int ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id)
162{
163 int i, res = -ENOENT;
164 unsigned long flags;
165
166 spin_lock_irqsave(&dev->fw_clients_lock, flags);
167 for (i = 0; i < dev->fw_clients_num; i++) {
168 if (dev->fw_clients[i].client_id == client_id) {
169 res = i;
170 break;
171 }
172 }
173 spin_unlock_irqrestore(&dev->fw_clients_lock, flags);
174
175 return res;
176}
177
178/**
179 * ishtp_cl_device_probe() - Bus probe() callback
180 * @dev: the device structure
181 *
182 * This is a bus probe callback and calls the drive probe function.
183 *
184 * Return: Return value from driver probe() call.
185 */
186static int ishtp_cl_device_probe(struct device *dev)
187{
188 struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
189 struct ishtp_cl_driver *driver;
190
191 if (!device)
192 return 0;
193
194 driver = to_ishtp_cl_driver(dev->driver);
195 if (!driver || !driver->probe)
196 return -ENODEV;
197
198 return driver->probe(device);
199}
200
201/**
202 * ishtp_cl_device_remove() - Bus remove() callback
203 * @dev: the device structure
204 *
205 * This is a bus remove callback and calls the drive remove function.
206 * Since the ISH driver model supports only built in, this is
207 * primarily can be called during pci driver init failure.
208 *
209 * Return: Return value from driver remove() call.
210 */
211static int ishtp_cl_device_remove(struct device *dev)
212{
213 struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
214 struct ishtp_cl_driver *driver;
215
216 if (!device || !dev->driver)
217 return 0;
218
219 if (device->event_cb) {
220 device->event_cb = NULL;
221 cancel_work_sync(&device->event_work);
222 }
223
224 driver = to_ishtp_cl_driver(dev->driver);
225 if (!driver->remove) {
226 dev->driver = NULL;
227
228 return 0;
229 }
230
231 return driver->remove(device);
232}
233
234/**
235 * ishtp_cl_device_suspend() - Bus suspend callback
236 * @dev: device
237 *
238 * Called during device suspend process.
239 *
240 * Return: Return value from driver suspend() call.
241 */
242static int ishtp_cl_device_suspend(struct device *dev)
243{
244 struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
245 struct ishtp_cl_driver *driver;
246 int ret = 0;
247
248 if (!device)
249 return 0;
250
251 driver = to_ishtp_cl_driver(dev->driver);
252 if (driver && driver->driver.pm) {
253 if (driver->driver.pm->suspend)
254 ret = driver->driver.pm->suspend(dev);
255 }
256
257 return ret;
258}
259
260/**
261 * ishtp_cl_device_resume() - Bus resume callback
262 * @dev: device
263 *
264 * Called during device resume process.
265 *
266 * Return: Return value from driver resume() call.
267 */
268static int ishtp_cl_device_resume(struct device *dev)
269{
270 struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
271 struct ishtp_cl_driver *driver;
272 int ret = 0;
273
274 if (!device)
275 return 0;
276
277 /*
278 * When ISH needs hard reset, it is done asynchrnously, hence bus
279 * resume will be called before full ISH resume
280 */
281 if (device->ishtp_dev->resume_flag)
282 return 0;
283
284 driver = to_ishtp_cl_driver(dev->driver);
285 if (driver && driver->driver.pm) {
286 if (driver->driver.pm->resume)
287 ret = driver->driver.pm->resume(dev);
288 }
289
290 return ret;
291}
292
293/**
294 * ishtp_cl_device_reset() - Reset callback
295 * @device: ishtp client device instance
296 *
297 * This is a callback when HW reset is done and the device need
298 * reinit.
299 *
300 * Return: Return value from driver reset() call.
301 */
302static int ishtp_cl_device_reset(struct ishtp_cl_device *device)
303{
304 struct ishtp_cl_driver *driver;
305 int ret = 0;
306
307 device->event_cb = NULL;
308 cancel_work_sync(&device->event_work);
309
310 driver = to_ishtp_cl_driver(device->dev.driver);
311 if (driver && driver->reset)
312 ret = driver->reset(device);
313
314 return ret;
315}
316
317static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
318 char *buf)
319{
320 int len;
321
322 len = snprintf(buf, PAGE_SIZE, "ishtp:%s\n", dev_name(dev));
323 return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
324}
325
326static struct device_attribute ishtp_cl_dev_attrs[] = {
327 __ATTR_RO(modalias),
328 __ATTR_NULL,
329};
330
331static int ishtp_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
332{
333 if (add_uevent_var(env, "MODALIAS=ishtp:%s", dev_name(dev)))
334 return -ENOMEM;
335 return 0;
336}
337
338static const struct dev_pm_ops ishtp_cl_bus_dev_pm_ops = {
339 /* Suspend callbacks */
340 .suspend = ishtp_cl_device_suspend,
341 .resume = ishtp_cl_device_resume,
342 /* Hibernate callbacks */
343 .freeze = ishtp_cl_device_suspend,
344 .thaw = ishtp_cl_device_resume,
345 .restore = ishtp_cl_device_resume,
346};
347
348static struct bus_type ishtp_cl_bus_type = {
349 .name = "ishtp",
350 .dev_attrs = ishtp_cl_dev_attrs,
351 .probe = ishtp_cl_device_probe,
352 .remove = ishtp_cl_device_remove,
353 .pm = &ishtp_cl_bus_dev_pm_ops,
354 .uevent = ishtp_cl_uevent,
355};
356
357static void ishtp_cl_dev_release(struct device *dev)
358{
359 kfree(to_ishtp_cl_device(dev));
360}
361
362static struct device_type ishtp_cl_device_type = {
363 .release = ishtp_cl_dev_release,
364};
365
366/**
367 * ishtp_bus_add_device() - Function to create device on bus
368 * @dev: ishtp device
369 * @uuid: uuid of the client
370 * @name: Name of the client
371 *
372 * Allocate ISHTP bus client device, attach it to uuid
373 * and register with ISHTP bus.
374 *
375 * Return: ishtp_cl_device pointer or NULL on failure
376 */
377static struct ishtp_cl_device *ishtp_bus_add_device(struct ishtp_device *dev,
378 uuid_le uuid, char *name)
379{
380 struct ishtp_cl_device *device;
381 int status;
382 unsigned long flags;
383 struct list_head *pos;
384
385 spin_lock_irqsave(&dev->device_list_lock, flags);
386 list_for_each(pos, &dev->device_list) {
387 device = list_entry(pos, struct ishtp_cl_device, device_link);
388 if (!strcmp(name, dev_name(&device->dev))) {
389 device->fw_client = &dev->fw_clients[
390 dev->fw_client_presentation_num - 1];
391 spin_unlock_irqrestore(&dev->device_list_lock, flags);
392 ishtp_cl_device_reset(device);
393 return device;
394 }
395 }
396 spin_unlock_irqrestore(&dev->device_list_lock, flags);
397
398 device = kzalloc(sizeof(struct ishtp_cl_device), GFP_KERNEL);
399 if (!device)
400 return NULL;
401
402 device->dev.parent = dev->devc;
403 device->dev.bus = &ishtp_cl_bus_type;
404 device->dev.type = &ishtp_cl_device_type;
405 device->ishtp_dev = dev;
406
407 device->fw_client =
408 &dev->fw_clients[dev->fw_client_presentation_num - 1];
409
410 dev_set_name(&device->dev, "%s", name);
411
412 spin_lock_irqsave(&dev->device_list_lock, flags);
413 list_add_tail(&device->device_link, &dev->device_list);
414 spin_unlock_irqrestore(&dev->device_list_lock, flags);
415
416 status = device_register(&device->dev);
417 if (status) {
418 spin_lock_irqsave(&dev->device_list_lock, flags);
419 list_del(&device->device_link);
420 spin_unlock_irqrestore(&dev->device_list_lock, flags);
421 dev_err(dev->devc, "Failed to register ISHTP client device\n");
422 kfree(device);
423 return NULL;
424 }
425
426 ishtp_device_ready = true;
427
428 return device;
429}
430
431/**
432 * ishtp_bus_remove_device() - Function to relase device on bus
433 * @device: client device instance
434 *
435 * This is a counterpart of ishtp_bus_add_device.
436 * Device is unregistered.
437 * the device structure is freed in 'ishtp_cl_dev_release' function
438 * Called only during error in pci driver init path.
439 */
440static void ishtp_bus_remove_device(struct ishtp_cl_device *device)
441{
442 device_unregister(&device->dev);
443}
444
445/**
446 * __ishtp_cl_driver_register() - Client driver register
447 * @driver: the client driver instance
448 * @owner: Owner of this driver module
449 *
450 * Once a client driver is probed, it created a client
451 * instance and registers with the bus.
452 *
453 * Return: Return value of driver_register or -ENODEV if not ready
454 */
455int __ishtp_cl_driver_register(struct ishtp_cl_driver *driver,
456 struct module *owner)
457{
458 int err;
459
460 if (!ishtp_device_ready)
461 return -ENODEV;
462
463 driver->driver.name = driver->name;
464 driver->driver.owner = owner;
465 driver->driver.bus = &ishtp_cl_bus_type;
466
467 err = driver_register(&driver->driver);
468 if (err)
469 return err;
470
471 return 0;
472}
473EXPORT_SYMBOL(__ishtp_cl_driver_register);
474
475/**
476 * ishtp_cl_driver_unregister() - Client driver unregister
477 * @driver: the client driver instance
478 *
479 * Unregister client during device removal process.
480 */
481void ishtp_cl_driver_unregister(struct ishtp_cl_driver *driver)
482{
483 driver_unregister(&driver->driver);
484}
485EXPORT_SYMBOL(ishtp_cl_driver_unregister);
486
487/**
488 * ishtp_bus_event_work() - event work function
489 * @work: work struct pointer
490 *
491 * Once an event is received for a client this work
492 * function is called. If the device has registered a
493 * callback then the callback is called.
494 */
495static void ishtp_bus_event_work(struct work_struct *work)
496{
497 struct ishtp_cl_device *device;
498
499 device = container_of(work, struct ishtp_cl_device, event_work);
500
501 if (device->event_cb)
502 device->event_cb(device);
503}
504
505/**
506 * ishtp_cl_bus_rx_event() - schedule event work
507 * @device: client device instance
508 *
509 * Once an event is received for a client this schedules
510 * a work function to process.
511 */
512void ishtp_cl_bus_rx_event(struct ishtp_cl_device *device)
513{
514 if (!device || !device->event_cb)
515 return;
516
517 if (device->event_cb)
518 schedule_work(&device->event_work);
519}
520
521/**
522 * ishtp_register_event_cb() - Register callback
523 * @device: client device instance
524 * @event_cb: Event processor for an client
525 *
526 * Register a callback for events, called from client driver
527 *
528 * Return: Return 0 or -EALREADY if already registered
529 */
530int ishtp_register_event_cb(struct ishtp_cl_device *device,
531 void (*event_cb)(struct ishtp_cl_device *))
532{
533 if (device->event_cb)
534 return -EALREADY;
535
536 device->event_cb = event_cb;
537 INIT_WORK(&device->event_work, ishtp_bus_event_work);
538
539 return 0;
540}
541EXPORT_SYMBOL(ishtp_register_event_cb);
542
543/**
544 * ishtp_get_device() - update usage count for the device
545 * @cl_device: client device instance
546 *
547 * Increment the usage count. The device can't be deleted
548 */
549void ishtp_get_device(struct ishtp_cl_device *cl_device)
550{
551 cl_device->reference_count++;
552}
553EXPORT_SYMBOL(ishtp_get_device);
554
555/**
556 * ishtp_put_device() - decrement usage count for the device
557 * @cl_device: client device instance
558 *
559 * Decrement the usage count. The device can be deleted is count = 0
560 */
561void ishtp_put_device(struct ishtp_cl_device *cl_device)
562{
563 cl_device->reference_count--;
564}
565EXPORT_SYMBOL(ishtp_put_device);
566
567/**
568 * ishtp_bus_new_client() - Create a new client
569 * @dev: ISHTP device instance
570 *
571 * Once bus protocol enumerates a client, this is called
572 * to add a device for the client.
573 *
574 * Return: 0 on success or error code on failure
575 */
576int ishtp_bus_new_client(struct ishtp_device *dev)
577{
578 int i;
579 char *dev_name;
580 struct ishtp_cl_device *cl_device;
581 uuid_le device_uuid;
582
583 /*
584 * For all reported clients, create an unconnected client and add its
585 * device to ISHTP bus.
586 * If appropriate driver has loaded, this will trigger its probe().
587 * Otherwise, probe() will be called when driver is loaded
588 */
589 i = dev->fw_client_presentation_num - 1;
590 device_uuid = dev->fw_clients[i].props.protocol_name;
591 dev_name = kasprintf(GFP_KERNEL,
592 "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
593 device_uuid.b[3], device_uuid.b[2], device_uuid.b[1],
594 device_uuid.b[0], device_uuid.b[5], device_uuid.b[4],
595 device_uuid.b[7], device_uuid.b[6], device_uuid.b[8],
596 device_uuid.b[9], device_uuid.b[10], device_uuid.b[11],
597 device_uuid.b[12], device_uuid.b[13], device_uuid.b[14],
598 device_uuid.b[15]);
599 if (!dev_name)
600 return -ENOMEM;
601
602 cl_device = ishtp_bus_add_device(dev, device_uuid, dev_name);
603 if (!cl_device) {
604 kfree(dev_name);
605 return -ENOENT;
606 }
607
608 kfree(dev_name);
609
610 return 0;
611}
612
613/**
614 * ishtp_cl_device_bind() - bind a device
615 * @cl: ishtp client device
616 *
617 * Binds connected ishtp_cl to ISHTP bus device
618 *
619 * Return: 0 on success or fault code
620 */
621int ishtp_cl_device_bind(struct ishtp_cl *cl)
622{
623 struct ishtp_cl_device *cl_device;
624 unsigned long flags;
625 int rv;
626
627 if (!cl->fw_client_id || cl->state != ISHTP_CL_CONNECTED)
628 return -EFAULT;
629
630 rv = -ENOENT;
631 spin_lock_irqsave(&cl->dev->device_list_lock, flags);
632 list_for_each_entry(cl_device, &cl->dev->device_list,
633 device_link) {
634 if (cl_device->fw_client->client_id == cl->fw_client_id) {
635 cl->device = cl_device;
636 rv = 0;
637 break;
638 }
639 }
640 spin_unlock_irqrestore(&cl->dev->device_list_lock, flags);
641 return rv;
642}
643
644/**
645 * ishtp_bus_remove_all_clients() - Remove all clients
646 * @ishtp_dev: ishtp device
647 * @warm_reset: Reset due to FW reset dure to errors or S3 suspend
648 *
649 * This is part of reset/remove flow. This function the main processing
650 * only targets error processing, if the FW has forced reset or
651 * error to remove connected clients. When warm reset the client devices are
652 * not removed.
653 */
654void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev,
655 bool warm_reset)
656{
657 struct ishtp_cl_device *cl_device, *n;
658 struct ishtp_cl *cl;
659 unsigned long flags;
660
661 spin_lock_irqsave(&ishtp_dev->cl_list_lock, flags);
662 list_for_each_entry(cl, &ishtp_dev->cl_list, link) {
663 cl->state = ISHTP_CL_DISCONNECTED;
664
665 /*
666 * Wake any pending process. The waiter would check dev->state
667 * and determine that it's not enabled already,
668 * and will return error to its caller
669 */
670 wake_up_interruptible(&cl->wait_ctrl_res);
671
672 /* Disband any pending read/write requests and free rb */
673 ishtp_cl_flush_queues(cl);
674
675 /* Remove all free and in_process rings, both Rx and Tx */
676 ishtp_cl_free_rx_ring(cl);
677 ishtp_cl_free_tx_ring(cl);
678
679 /*
680 * Free client and ISHTP bus client device structures
681 * don't free host client because it is part of the OS fd
682 * structure
683 */
684 }
685 spin_unlock_irqrestore(&ishtp_dev->cl_list_lock, flags);
686
687 /* Release DMA buffers for client messages */
688 ishtp_cl_free_dma_buf(ishtp_dev);
689
690 /* remove bus clients */
691 spin_lock_irqsave(&ishtp_dev->device_list_lock, flags);
692 list_for_each_entry_safe(cl_device, n, &ishtp_dev->device_list,
693 device_link) {
694 if (warm_reset && cl_device->reference_count)
695 continue;
696
697 list_del(&cl_device->device_link);
698 spin_unlock_irqrestore(&ishtp_dev->device_list_lock, flags);
699 ishtp_bus_remove_device(cl_device);
700 spin_lock_irqsave(&ishtp_dev->device_list_lock, flags);
701 }
702 spin_unlock_irqrestore(&ishtp_dev->device_list_lock, flags);
703
704 /* Free all client structures */
705 spin_lock_irqsave(&ishtp_dev->fw_clients_lock, flags);
706 kfree(ishtp_dev->fw_clients);
707 ishtp_dev->fw_clients = NULL;
708 ishtp_dev->fw_clients_num = 0;
709 ishtp_dev->fw_client_presentation_num = 0;
710 ishtp_dev->fw_client_index = 0;
711 bitmap_zero(ishtp_dev->fw_clients_map, ISHTP_CLIENTS_MAX);
712 spin_unlock_irqrestore(&ishtp_dev->fw_clients_lock, flags);
713}
714EXPORT_SYMBOL(ishtp_bus_remove_all_clients);
715
716/**
717 * ishtp_reset_handler() - IPC reset handler
718 * @dev: ishtp device
719 *
720 * ISHTP Handler for IPC_RESET notification
721 */
722void ishtp_reset_handler(struct ishtp_device *dev)
723{
724 unsigned long flags;
725
726 /* Handle FW-initiated reset */
727 dev->dev_state = ISHTP_DEV_RESETTING;
728
729 /* Clear BH processing queue - no further HBMs */
730 spin_lock_irqsave(&dev->rd_msg_spinlock, flags);
731 dev->rd_msg_fifo_head = dev->rd_msg_fifo_tail = 0;
732 spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
733
734 /* Handle ISH FW reset against upper layers */
735 ishtp_bus_remove_all_clients(dev, true);
736}
737EXPORT_SYMBOL(ishtp_reset_handler);
738
739/**
740 * ishtp_reset_compl_handler() - Reset completion handler
741 * @dev: ishtp device
742 *
743 * ISHTP handler for IPC_RESET sequence completion to start
744 * host message bus start protocol sequence.
745 */
746void ishtp_reset_compl_handler(struct ishtp_device *dev)
747{
748 dev->dev_state = ISHTP_DEV_INIT_CLIENTS;
749 dev->hbm_state = ISHTP_HBM_START;
750 ishtp_hbm_start_req(dev);
751}
752EXPORT_SYMBOL(ishtp_reset_compl_handler);
753
754/**
755 * ishtp_use_dma_transfer() - Function to use DMA
756 *
757 * This interface is used to enable usage of DMA
758 *
759 * Return non zero if DMA can be enabled
760 */
761int ishtp_use_dma_transfer(void)
762{
763 return ishtp_use_dma;
764}
765
766/**
767 * ishtp_bus_register() - Function to register bus
768 *
769 * This register ishtp bus
770 *
771 * Return: Return output of bus_register
772 */
773static int __init ishtp_bus_register(void)
774{
775 return bus_register(&ishtp_cl_bus_type);
776}
777
778/**
779 * ishtp_bus_unregister() - Function to unregister bus
780 *
781 * This unregister ishtp bus
782 */
783static void __exit ishtp_bus_unregister(void)
784{
785 bus_unregister(&ishtp_cl_bus_type);
786}
787
788module_init(ishtp_bus_register);
789module_exit(ishtp_bus_unregister);
790
791MODULE_LICENSE("GPL");
diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.h b/drivers/hid/intel-ish-hid/ishtp/bus.h
new file mode 100644
index 000000000000..a1ffae7f26ad
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/bus.h
@@ -0,0 +1,114 @@
1/*
2 * ISHTP bus definitions
3 *
4 * 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 */
15#ifndef _LINUX_ISHTP_CL_BUS_H
16#define _LINUX_ISHTP_CL_BUS_H
17
18#include <linux/device.h>
19#include <linux/mod_devicetable.h>
20
21struct ishtp_cl;
22struct ishtp_cl_device;
23struct ishtp_device;
24struct ishtp_msg_hdr;
25
26/**
27 * struct ishtp_cl_device - ISHTP device handle
28 * @dev: device pointer
29 * @ishtp_dev: pointer to ishtp device structure to primarily to access
30 * hw device operation callbacks and properties
31 * @fw_client: fw_client pointer to get fw information like protocol name
32 * max message length etc.
33 * @device_link: Link to next client in the list on a bus
34 * @event_work: Used to schedule rx event for client
35 * @driver_data: Storage driver private data
36 * @reference_count: Used for get/put device
37 * @event_cb: Callback to driver to send events
38 *
39 * An ishtp_cl_device pointer is returned from ishtp_add_device()
40 * and links ISHTP bus clients to their actual host client pointer.
41 * Drivers for ISHTP devices will get an ishtp_cl_device pointer
42 * when being probed and shall use it for doing bus I/O.
43 */
44struct ishtp_cl_device {
45 struct device dev;
46 struct ishtp_device *ishtp_dev;
47 struct ishtp_fw_client *fw_client;
48 struct list_head device_link;
49 struct work_struct event_work;
50 void *driver_data;
51 int reference_count;
52 void (*event_cb)(struct ishtp_cl_device *device);
53};
54
55/**
56 * struct ishtp_cl_device - ISHTP device handle
57 * @driver: driver instance on a bus
58 * @name: Name of the device for probe
59 * @probe: driver callback for device probe
60 * @remove: driver callback on device removal
61 *
62 * Client drivers defines to get probed/removed for ISHTP client device.
63 */
64struct ishtp_cl_driver {
65 struct device_driver driver;
66 const char *name;
67 int (*probe)(struct ishtp_cl_device *dev);
68 int (*remove)(struct ishtp_cl_device *dev);
69 int (*reset)(struct ishtp_cl_device *dev);
70 const struct dev_pm_ops *pm;
71};
72
73
74int ishtp_bus_new_client(struct ishtp_device *dev);
75void ishtp_remove_all_clients(struct ishtp_device *dev);
76int ishtp_cl_device_bind(struct ishtp_cl *cl);
77void ishtp_cl_bus_rx_event(struct ishtp_cl_device *device);
78
79/* Write a multi-fragment message */
80int ishtp_send_msg(struct ishtp_device *dev,
81 struct ishtp_msg_hdr *hdr, void *msg,
82 void (*ipc_send_compl)(void *),
83 void *ipc_send_compl_prm);
84
85/* Write a single-fragment message */
86int ishtp_write_message(struct ishtp_device *dev,
87 struct ishtp_msg_hdr *hdr,
88 unsigned char *buf);
89
90/* Use DMA to send/receive messages */
91int ishtp_use_dma_transfer(void);
92
93/* Exported functions */
94void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev,
95 bool warm_reset);
96
97void ishtp_recv(struct ishtp_device *dev);
98void ishtp_reset_handler(struct ishtp_device *dev);
99void ishtp_reset_compl_handler(struct ishtp_device *dev);
100
101void ishtp_put_device(struct ishtp_cl_device *);
102void ishtp_get_device(struct ishtp_cl_device *);
103
104int __ishtp_cl_driver_register(struct ishtp_cl_driver *driver,
105 struct module *owner);
106#define ishtp_cl_driver_register(driver) \
107 __ishtp_cl_driver_register(driver, THIS_MODULE)
108void ishtp_cl_driver_unregister(struct ishtp_cl_driver *driver);
109
110int ishtp_register_event_cb(struct ishtp_cl_device *device,
111 void (*read_cb)(struct ishtp_cl_device *));
112int ishtp_fw_cl_by_uuid(struct ishtp_device *dev, const uuid_le *cuuid);
113
114#endif /* _LINUX_ISHTP_CL_BUS_H */
diff --git a/drivers/hid/intel-ish-hid/ishtp/client-buffers.c b/drivers/hid/intel-ish-hid/ishtp/client-buffers.c
new file mode 100644
index 000000000000..3f5ce5ee687e
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/client-buffers.c
@@ -0,0 +1,258 @@
1/*
2 * ISHTP Ring Buffers
3 *
4 * 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 *
15 */
16
17#include <linux/slab.h>
18#include "client.h"
19
20/**
21 * ishtp_cl_alloc_rx_ring() - Allocate RX ring buffers
22 * @cl: client device instance
23 *
24 * Allocate and initialize RX ring buffers
25 *
26 * Return: 0 on success else -ENOMEM
27 */
28int ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl)
29{
30 size_t len = cl->device->fw_client->props.max_msg_length;
31 int j;
32 struct ishtp_cl_rb *rb;
33 int ret = 0;
34 unsigned long flags;
35
36 for (j = 0; j < cl->rx_ring_size; ++j) {
37 rb = ishtp_io_rb_init(cl);
38 if (!rb) {
39 ret = -ENOMEM;
40 goto out;
41 }
42 ret = ishtp_io_rb_alloc_buf(rb, len);
43 if (ret)
44 goto out;
45 spin_lock_irqsave(&cl->free_list_spinlock, flags);
46 list_add_tail(&rb->list, &cl->free_rb_list.list);
47 spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
48 }
49
50 return 0;
51
52out:
53 dev_err(&cl->device->dev, "error in allocating Rx buffers\n");
54 ishtp_cl_free_rx_ring(cl);
55 return ret;
56}
57
58/**
59 * ishtp_cl_alloc_tx_ring() - Allocate TX ring buffers
60 * @cl: client device instance
61 *
62 * Allocate and initialize TX ring buffers
63 *
64 * Return: 0 on success else -ENOMEM
65 */
66int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl)
67{
68 size_t len = cl->device->fw_client->props.max_msg_length;
69 int j;
70 unsigned long flags;
71
72 /* Allocate pool to free Tx bufs */
73 for (j = 0; j < cl->tx_ring_size; ++j) {
74 struct ishtp_cl_tx_ring *tx_buf;
75
76 tx_buf = kmalloc(sizeof(struct ishtp_cl_tx_ring), GFP_KERNEL);
77 if (!tx_buf)
78 goto out;
79
80 memset(tx_buf, 0, sizeof(struct ishtp_cl_tx_ring));
81 tx_buf->send_buf.data = kmalloc(len, GFP_KERNEL);
82 if (!tx_buf->send_buf.data) {
83 kfree(tx_buf);
84 goto out;
85 }
86
87 spin_lock_irqsave(&cl->tx_free_list_spinlock, flags);
88 list_add_tail(&tx_buf->list, &cl->tx_free_list.list);
89 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, flags);
90 }
91 return 0;
92out:
93 dev_err(&cl->device->dev, "error in allocating Tx pool\n");
94 ishtp_cl_free_rx_ring(cl);
95 return -ENOMEM;
96}
97
98/**
99 * ishtp_cl_free_rx_ring() - Free RX ring buffers
100 * @cl: client device instance
101 *
102 * Free RX ring buffers
103 */
104void ishtp_cl_free_rx_ring(struct ishtp_cl *cl)
105{
106 struct ishtp_cl_rb *rb;
107 unsigned long flags;
108
109 /* release allocated memory - pass over free_rb_list */
110 spin_lock_irqsave(&cl->free_list_spinlock, flags);
111 while (!list_empty(&cl->free_rb_list.list)) {
112 rb = list_entry(cl->free_rb_list.list.next, struct ishtp_cl_rb,
113 list);
114 list_del(&rb->list);
115 kfree(rb->buffer.data);
116 kfree(rb);
117 }
118 spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
119 /* release allocated memory - pass over in_process_list */
120 spin_lock_irqsave(&cl->in_process_spinlock, flags);
121 while (!list_empty(&cl->in_process_list.list)) {
122 rb = list_entry(cl->in_process_list.list.next,
123 struct ishtp_cl_rb, list);
124 list_del(&rb->list);
125 kfree(rb->buffer.data);
126 kfree(rb);
127 }
128 spin_unlock_irqrestore(&cl->in_process_spinlock, flags);
129}
130
131/**
132 * ishtp_cl_free_tx_ring() - Free TX ring buffers
133 * @cl: client device instance
134 *
135 * Free TX ring buffers
136 */
137void ishtp_cl_free_tx_ring(struct ishtp_cl *cl)
138{
139 struct ishtp_cl_tx_ring *tx_buf;
140 unsigned long flags;
141
142 spin_lock_irqsave(&cl->tx_free_list_spinlock, flags);
143 /* release allocated memory - pass over tx_free_list */
144 while (!list_empty(&cl->tx_free_list.list)) {
145 tx_buf = list_entry(cl->tx_free_list.list.next,
146 struct ishtp_cl_tx_ring, list);
147 list_del(&tx_buf->list);
148 kfree(tx_buf->send_buf.data);
149 kfree(tx_buf);
150 }
151 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, flags);
152
153 spin_lock_irqsave(&cl->tx_list_spinlock, flags);
154 /* release allocated memory - pass over tx_list */
155 while (!list_empty(&cl->tx_list.list)) {
156 tx_buf = list_entry(cl->tx_list.list.next,
157 struct ishtp_cl_tx_ring, list);
158 list_del(&tx_buf->list);
159 kfree(tx_buf->send_buf.data);
160 kfree(tx_buf);
161 }
162 spin_unlock_irqrestore(&cl->tx_list_spinlock, flags);
163}
164
165/**
166 * ishtp_io_rb_free() - Free IO request block
167 * @rb: IO request block
168 *
169 * Free io request block memory
170 */
171void ishtp_io_rb_free(struct ishtp_cl_rb *rb)
172{
173 if (rb == NULL)
174 return;
175
176 kfree(rb->buffer.data);
177 kfree(rb);
178}
179
180/**
181 * ishtp_io_rb_init() - Allocate and init IO request block
182 * @cl: client device instance
183 *
184 * Allocate and initialize request block
185 *
186 * Return: Allocted IO request block pointer
187 */
188struct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl)
189{
190 struct ishtp_cl_rb *rb;
191
192 rb = kzalloc(sizeof(struct ishtp_cl_rb), GFP_KERNEL);
193 if (!rb)
194 return NULL;
195
196 INIT_LIST_HEAD(&rb->list);
197 rb->cl = cl;
198 rb->buf_idx = 0;
199 return rb;
200}
201
202/**
203 * ishtp_io_rb_alloc_buf() - Allocate and init response buffer
204 * @rb: IO request block
205 * @length: length of response buffer
206 *
207 * Allocate respose buffer
208 *
209 * Return: 0 on success else -ENOMEM
210 */
211int ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length)
212{
213 if (!rb)
214 return -EINVAL;
215
216 if (length == 0)
217 return 0;
218
219 rb->buffer.data = kmalloc(length, GFP_KERNEL);
220 if (!rb->buffer.data)
221 return -ENOMEM;
222
223 rb->buffer.size = length;
224 return 0;
225}
226
227/**
228 * ishtp_cl_io_rb_recycle() - Recycle IO request blocks
229 * @rb: IO request block
230 *
231 * Re-append rb to its client's free list and send flow control if needed
232 *
233 * Return: 0 on success else -EFAULT
234 */
235int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb)
236{
237 struct ishtp_cl *cl;
238 int rets = 0;
239 unsigned long flags;
240
241 if (!rb || !rb->cl)
242 return -EFAULT;
243
244 cl = rb->cl;
245 spin_lock_irqsave(&cl->free_list_spinlock, flags);
246 list_add_tail(&rb->list, &cl->free_rb_list.list);
247 spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
248
249 /*
250 * If we returned the first buffer to empty 'free' list,
251 * send flow control
252 */
253 if (!cl->out_flow_ctrl_creds)
254 rets = ishtp_cl_read_start(cl);
255
256 return rets;
257}
258EXPORT_SYMBOL(ishtp_cl_io_rb_recycle);
diff --git a/drivers/hid/intel-ish-hid/ishtp/client.c b/drivers/hid/intel-ish-hid/ishtp/client.c
new file mode 100644
index 000000000000..aad61328f282
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/client.c
@@ -0,0 +1,1054 @@
1/*
2 * ISHTP client logic
3 *
4 * 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 *
15 */
16
17#include <linux/slab.h>
18#include <linux/sched.h>
19#include <linux/wait.h>
20#include <linux/delay.h>
21#include <linux/dma-mapping.h>
22#include "hbm.h"
23#include "client.h"
24
25/**
26 * ishtp_read_list_flush() - Flush read queue
27 * @cl: ishtp client instance
28 *
29 * Used to remove all entries from read queue for a client
30 */
31static void ishtp_read_list_flush(struct ishtp_cl *cl)
32{
33 struct ishtp_cl_rb *rb;
34 struct ishtp_cl_rb *next;
35 unsigned long flags;
36
37 spin_lock_irqsave(&cl->dev->read_list_spinlock, flags);
38 list_for_each_entry_safe(rb, next, &cl->dev->read_list.list, list)
39 if (rb->cl && ishtp_cl_cmp_id(cl, rb->cl)) {
40 list_del(&rb->list);
41 ishtp_io_rb_free(rb);
42 }
43 spin_unlock_irqrestore(&cl->dev->read_list_spinlock, flags);
44}
45
46/**
47 * ishtp_cl_flush_queues() - Flush all queues for a client
48 * @cl: ishtp client instance
49 *
50 * Used to remove all queues for a client. This is called when a client device
51 * needs reset due to error, S3 resume or during module removal
52 *
53 * Return: 0 on success else -EINVAL if device is NULL
54 */
55int ishtp_cl_flush_queues(struct ishtp_cl *cl)
56{
57 if (WARN_ON(!cl || !cl->dev))
58 return -EINVAL;
59
60 ishtp_read_list_flush(cl);
61
62 return 0;
63}
64EXPORT_SYMBOL(ishtp_cl_flush_queues);
65
66/**
67 * ishtp_cl_init() - Initialize all fields of a client device
68 * @cl: ishtp client instance
69 * @dev: ishtp device
70 *
71 * Initializes a client device fields: Init spinlocks, init queues etc.
72 * This function is called during new client creation
73 */
74static void ishtp_cl_init(struct ishtp_cl *cl, struct ishtp_device *dev)
75{
76 memset(cl, 0, sizeof(struct ishtp_cl));
77 init_waitqueue_head(&cl->wait_ctrl_res);
78 spin_lock_init(&cl->free_list_spinlock);
79 spin_lock_init(&cl->in_process_spinlock);
80 spin_lock_init(&cl->tx_list_spinlock);
81 spin_lock_init(&cl->tx_free_list_spinlock);
82 spin_lock_init(&cl->fc_spinlock);
83 INIT_LIST_HEAD(&cl->link);
84 cl->dev = dev;
85
86 INIT_LIST_HEAD(&cl->free_rb_list.list);
87 INIT_LIST_HEAD(&cl->tx_list.list);
88 INIT_LIST_HEAD(&cl->tx_free_list.list);
89 INIT_LIST_HEAD(&cl->in_process_list.list);
90
91 cl->rx_ring_size = CL_DEF_RX_RING_SIZE;
92 cl->tx_ring_size = CL_DEF_TX_RING_SIZE;
93
94 /* dma */
95 cl->last_tx_path = CL_TX_PATH_IPC;
96 cl->last_dma_acked = 1;
97 cl->last_dma_addr = NULL;
98 cl->last_ipc_acked = 1;
99}
100
101/**
102 * ishtp_cl_allocate() - allocates client structure and sets it up.
103 * @dev: ishtp device
104 *
105 * Allocate memory for new client device and call to initialize each field.
106 *
107 * Return: The allocated client instance or NULL on failure
108 */
109struct ishtp_cl *ishtp_cl_allocate(struct ishtp_device *dev)
110{
111 struct ishtp_cl *cl;
112
113 cl = kmalloc(sizeof(struct ishtp_cl), GFP_KERNEL);
114 if (!cl)
115 return NULL;
116
117 ishtp_cl_init(cl, dev);
118 return cl;
119}
120EXPORT_SYMBOL(ishtp_cl_allocate);
121
122/**
123 * ishtp_cl_free() - Frees a client device
124 * @cl: client device instance
125 *
126 * Frees a client device
127 */
128void ishtp_cl_free(struct ishtp_cl *cl)
129{
130 struct ishtp_device *dev;
131 unsigned long flags;
132
133 if (!cl)
134 return;
135
136 dev = cl->dev;
137 if (!dev)
138 return;
139
140 spin_lock_irqsave(&dev->cl_list_lock, flags);
141 ishtp_cl_free_rx_ring(cl);
142 ishtp_cl_free_tx_ring(cl);
143 kfree(cl);
144 spin_unlock_irqrestore(&dev->cl_list_lock, flags);
145}
146EXPORT_SYMBOL(ishtp_cl_free);
147
148/**
149 * ishtp_cl_link() - Reserve a host id and link the client instance
150 * @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 *
154 *
155 * This allocates a single bit in the hostmap. This function will make sure
156 * that not many client sessions are opened at the same time. Once allocated
157 * the client device instance is added to the ishtp device in the current
158 * client list
159 *
160 * Return: 0 or error code on failure
161 */
162int ishtp_cl_link(struct ishtp_cl *cl, int id)
163{
164 struct ishtp_device *dev;
165 unsigned long flags, flags_cl;
166 int ret = 0;
167
168 if (WARN_ON(!cl || !cl->dev))
169 return -EINVAL;
170
171 dev = cl->dev;
172
173 spin_lock_irqsave(&dev->device_lock, flags);
174
175 if (dev->open_handle_count >= ISHTP_MAX_OPEN_HANDLE_COUNT) {
176 ret = -EMFILE;
177 goto unlock_dev;
178 }
179
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);
184
185 if (id >= ISHTP_CLIENTS_MAX) {
186 spin_unlock_irqrestore(&dev->device_lock, flags);
187 dev_err(&cl->device->dev, "id exceeded %d", ISHTP_CLIENTS_MAX);
188 return -ENOENT;
189 }
190
191 dev->open_handle_count++;
192 cl->host_client_id = id;
193 spin_lock_irqsave(&dev->cl_list_lock, flags_cl);
194 if (dev->dev_state != ISHTP_DEV_ENABLED) {
195 ret = -ENODEV;
196 goto unlock_cl;
197 }
198 list_add_tail(&cl->link, &dev->cl_list);
199 set_bit(id, dev->host_clients_map);
200 cl->state = ISHTP_CL_INITIALIZING;
201
202unlock_cl:
203 spin_unlock_irqrestore(&dev->cl_list_lock, flags_cl);
204unlock_dev:
205 spin_unlock_irqrestore(&dev->device_lock, flags);
206 return ret;
207}
208EXPORT_SYMBOL(ishtp_cl_link);
209
210/**
211 * ishtp_cl_unlink() - remove fw_cl from the client device list
212 * @cl: client device instance
213 *
214 * Remove a previously linked device to a ishtp device
215 */
216void ishtp_cl_unlink(struct ishtp_cl *cl)
217{
218 struct ishtp_device *dev;
219 struct ishtp_cl *pos;
220 unsigned long flags;
221
222 /* don't shout on error exit path */
223 if (!cl || !cl->dev)
224 return;
225
226 dev = cl->dev;
227
228 spin_lock_irqsave(&dev->device_lock, flags);
229 if (dev->open_handle_count > 0) {
230 clear_bit(cl->host_client_id, dev->host_clients_map);
231 dev->open_handle_count--;
232 }
233 spin_unlock_irqrestore(&dev->device_lock, flags);
234
235 /*
236 * This checks that 'cl' is actually linked into device's structure,
237 * before attempting 'list_del'
238 */
239 spin_lock_irqsave(&dev->cl_list_lock, flags);
240 list_for_each_entry(pos, &dev->cl_list, link)
241 if (cl->host_client_id == pos->host_client_id) {
242 list_del_init(&pos->link);
243 break;
244 }
245 spin_unlock_irqrestore(&dev->cl_list_lock, flags);
246}
247EXPORT_SYMBOL(ishtp_cl_unlink);
248
249/**
250 * ishtp_cl_disconnect() - Send disconnect request to firmware
251 * @cl: client device instance
252 *
253 * Send a disconnect request for a client to firmware.
254 *
255 * Return: 0 if successful disconnect response from the firmware or error
256 * code on failure
257 */
258int ishtp_cl_disconnect(struct ishtp_cl *cl)
259{
260 struct ishtp_device *dev;
261 int err;
262
263 if (WARN_ON(!cl || !cl->dev))
264 return -ENODEV;
265
266 dev = cl->dev;
267
268 dev->print_log(dev, "%s() state %d\n", __func__, cl->state);
269
270 if (cl->state != ISHTP_CL_DISCONNECTING) {
271 dev->print_log(dev, "%s() Disconnect in progress\n", __func__);
272 return 0;
273 }
274
275 if (ishtp_hbm_cl_disconnect_req(dev, cl)) {
276 dev->print_log(dev, "%s() Failed to disconnect\n", __func__);
277 dev_err(&cl->device->dev, "failed to disconnect.\n");
278 return -ENODEV;
279 }
280
281 err = wait_event_interruptible_timeout(cl->wait_ctrl_res,
282 (dev->dev_state != ISHTP_DEV_ENABLED ||
283 cl->state == ISHTP_CL_DISCONNECTED),
284 ishtp_secs_to_jiffies(ISHTP_CL_CONNECT_TIMEOUT));
285
286 /*
287 * If FW reset arrived, this will happen. Don't check cl->,
288 * as 'cl' may be freed already
289 */
290 if (dev->dev_state != ISHTP_DEV_ENABLED) {
291 dev->print_log(dev, "%s() dev_state != ISHTP_DEV_ENABLED\n",
292 __func__);
293 return -ENODEV;
294 }
295
296 if (cl->state == ISHTP_CL_DISCONNECTED) {
297 dev->print_log(dev, "%s() successful\n", __func__);
298 return 0;
299 }
300
301 return -ENODEV;
302}
303EXPORT_SYMBOL(ishtp_cl_disconnect);
304
305/**
306 * ishtp_cl_is_other_connecting() - Check other client is connecting
307 * @cl: client device instance
308 *
309 * Checks if other client with the same fw client id is connecting
310 *
311 * Return: true if other client is connected else false
312 */
313static bool ishtp_cl_is_other_connecting(struct ishtp_cl *cl)
314{
315 struct ishtp_device *dev;
316 struct ishtp_cl *pos;
317 unsigned long flags;
318
319 if (WARN_ON(!cl || !cl->dev))
320 return false;
321
322 dev = cl->dev;
323 spin_lock_irqsave(&dev->cl_list_lock, flags);
324 list_for_each_entry(pos, &dev->cl_list, link) {
325 if ((pos->state == ISHTP_CL_CONNECTING) && (pos != cl) &&
326 cl->fw_client_id == pos->fw_client_id) {
327 spin_unlock_irqrestore(&dev->cl_list_lock, flags);
328 return true;
329 }
330 }
331 spin_unlock_irqrestore(&dev->cl_list_lock, flags);
332
333 return false;
334}
335
336/**
337 * ishtp_cl_connect() - Send connect request to firmware
338 * @cl: client device instance
339 *
340 * Send a connect request for a client to firmware. If successful it will
341 * RX and TX ring buffers
342 *
343 * Return: 0 if successful connect response from the firmware and able
344 * to bind and allocate ring buffers or error code on failure
345 */
346int ishtp_cl_connect(struct ishtp_cl *cl)
347{
348 struct ishtp_device *dev;
349 int rets;
350
351 if (WARN_ON(!cl || !cl->dev))
352 return -ENODEV;
353
354 dev = cl->dev;
355
356 dev->print_log(dev, "%s() current_state = %d\n", __func__, cl->state);
357
358 if (ishtp_cl_is_other_connecting(cl)) {
359 dev->print_log(dev, "%s() Busy\n", __func__);
360 return -EBUSY;
361 }
362
363 if (ishtp_hbm_cl_connect_req(dev, cl)) {
364 dev->print_log(dev, "%s() HBM connect req fail\n", __func__);
365 return -ENODEV;
366 }
367
368 rets = wait_event_interruptible_timeout(cl->wait_ctrl_res,
369 (dev->dev_state == ISHTP_DEV_ENABLED &&
370 (cl->state == ISHTP_CL_CONNECTED ||
371 cl->state == ISHTP_CL_DISCONNECTED)),
372 ishtp_secs_to_jiffies(
373 ISHTP_CL_CONNECT_TIMEOUT));
374 /*
375 * If FW reset arrived, this will happen. Don't check cl->,
376 * as 'cl' may be freed already
377 */
378 if (dev->dev_state != ISHTP_DEV_ENABLED) {
379 dev->print_log(dev, "%s() dev_state != ISHTP_DEV_ENABLED\n",
380 __func__);
381 return -EFAULT;
382 }
383
384 if (cl->state != ISHTP_CL_CONNECTED) {
385 dev->print_log(dev, "%s() state != ISHTP_CL_CONNECTED\n",
386 __func__);
387 return -EFAULT;
388 }
389
390 rets = cl->status;
391 if (rets) {
392 dev->print_log(dev, "%s() Invalid status\n", __func__);
393 return rets;
394 }
395
396 rets = ishtp_cl_device_bind(cl);
397 if (rets) {
398 dev->print_log(dev, "%s() Bind error\n", __func__);
399 ishtp_cl_disconnect(cl);
400 return rets;
401 }
402
403 rets = ishtp_cl_alloc_rx_ring(cl);
404 if (rets) {
405 dev->print_log(dev, "%s() Alloc RX ring failed\n", __func__);
406 /* if failed allocation, disconnect */
407 ishtp_cl_disconnect(cl);
408 return rets;
409 }
410
411 rets = ishtp_cl_alloc_tx_ring(cl);
412 if (rets) {
413 dev->print_log(dev, "%s() Alloc TX ring failed\n", __func__);
414 /* if failed allocation, disconnect */
415 ishtp_cl_free_rx_ring(cl);
416 ishtp_cl_disconnect(cl);
417 return rets;
418 }
419
420 /* Upon successful connection and allocation, emit flow-control */
421 rets = ishtp_cl_read_start(cl);
422
423 dev->print_log(dev, "%s() successful\n", __func__);
424
425 return rets;
426}
427EXPORT_SYMBOL(ishtp_cl_connect);
428
429/**
430 * ishtp_cl_read_start() - Prepare to read client message
431 * @cl: client device instance
432 *
433 * Get a free buffer from pool of free read buffers and add to read buffer
434 * pool to add contents. Send a flow control request to firmware to be able
435 * send next message.
436 *
437 * Return: 0 if successful or error code on failure
438 */
439int ishtp_cl_read_start(struct ishtp_cl *cl)
440{
441 struct ishtp_device *dev;
442 struct ishtp_cl_rb *rb;
443 int rets;
444 int i;
445 unsigned long flags;
446 unsigned long dev_flags;
447
448 if (WARN_ON(!cl || !cl->dev))
449 return -ENODEV;
450
451 dev = cl->dev;
452
453 if (cl->state != ISHTP_CL_CONNECTED)
454 return -ENODEV;
455
456 if (dev->dev_state != ISHTP_DEV_ENABLED)
457 return -ENODEV;
458
459 i = ishtp_fw_cl_by_id(dev, cl->fw_client_id);
460 if (i < 0) {
461 dev_err(&cl->device->dev, "no such fw client %d\n",
462 cl->fw_client_id);
463 return -ENODEV;
464 }
465
466 /* The current rb is the head of the free rb list */
467 spin_lock_irqsave(&cl->free_list_spinlock, flags);
468 if (list_empty(&cl->free_rb_list.list)) {
469 dev_warn(&cl->device->dev,
470 "[ishtp-ish] Rx buffers pool is empty\n");
471 rets = -ENOMEM;
472 rb = NULL;
473 spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
474 goto out;
475 }
476 rb = list_entry(cl->free_rb_list.list.next, struct ishtp_cl_rb, list);
477 list_del_init(&rb->list);
478 spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
479
480 rb->cl = cl;
481 rb->buf_idx = 0;
482
483 INIT_LIST_HEAD(&rb->list);
484 rets = 0;
485
486 /*
487 * This must be BEFORE sending flow control -
488 * response in ISR may come too fast...
489 */
490 spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
491 list_add_tail(&rb->list, &dev->read_list.list);
492 spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
493 if (ishtp_hbm_cl_flow_control_req(dev, cl)) {
494 rets = -ENODEV;
495 goto out;
496 }
497out:
498 /* if ishtp_hbm_cl_flow_control_req failed, return rb to free list */
499 if (rets && rb) {
500 spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
501 list_del(&rb->list);
502 spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
503
504 spin_lock_irqsave(&cl->free_list_spinlock, flags);
505 list_add_tail(&rb->list, &cl->free_rb_list.list);
506 spin_unlock_irqrestore(&cl->free_list_spinlock, flags);
507 }
508 return rets;
509}
510
511/**
512 * ishtp_cl_send() - Send a message to firmware
513 * @cl: client device instance
514 * @buf: message buffer
515 * @length: length of message
516 *
517 * If the client is correct state to send message, this function gets a buffer
518 * from tx ring buffers, copy the message data and call to send the message
519 * using ishtp_cl_send_msg()
520 *
521 * Return: 0 if successful or error code on failure
522 */
523int ishtp_cl_send(struct ishtp_cl *cl, uint8_t *buf, size_t length)
524{
525 struct ishtp_device *dev;
526 int id;
527 struct ishtp_cl_tx_ring *cl_msg;
528 int have_msg_to_send = 0;
529 unsigned long tx_flags, tx_free_flags;
530
531 if (WARN_ON(!cl || !cl->dev))
532 return -ENODEV;
533
534 dev = cl->dev;
535
536 if (cl->state != ISHTP_CL_CONNECTED) {
537 ++cl->err_send_msg;
538 return -EPIPE;
539 }
540
541 if (dev->dev_state != ISHTP_DEV_ENABLED) {
542 ++cl->err_send_msg;
543 return -ENODEV;
544 }
545
546 /* Check if we have fw client device */
547 id = ishtp_fw_cl_by_id(dev, cl->fw_client_id);
548 if (id < 0) {
549 ++cl->err_send_msg;
550 return -ENOENT;
551 }
552
553 if (length > dev->fw_clients[id].props.max_msg_length) {
554 ++cl->err_send_msg;
555 return -EMSGSIZE;
556 }
557
558 /* No free bufs */
559 spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
560 if (list_empty(&cl->tx_free_list.list)) {
561 spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
562 tx_free_flags);
563 ++cl->err_send_msg;
564 return -ENOMEM;
565 }
566
567 cl_msg = list_first_entry(&cl->tx_free_list.list,
568 struct ishtp_cl_tx_ring, list);
569 if (!cl_msg->send_buf.data) {
570 spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
571 tx_free_flags);
572 return -EIO;
573 /* Should not happen, as free list is pre-allocated */
574 }
575 /*
576 * This is safe, as 'length' is already checked for not exceeding
577 * max ISHTP message size per client
578 */
579 list_del_init(&cl_msg->list);
580 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags);
581 memcpy(cl_msg->send_buf.data, buf, length);
582 cl_msg->send_buf.size = length;
583 spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags);
584 have_msg_to_send = !list_empty(&cl->tx_list.list);
585 list_add_tail(&cl_msg->list, &cl->tx_list.list);
586 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
587
588 if (!have_msg_to_send && cl->ishtp_flow_ctrl_creds > 0)
589 ishtp_cl_send_msg(dev, cl);
590
591 return 0;
592}
593EXPORT_SYMBOL(ishtp_cl_send);
594
595/**
596 * ishtp_cl_read_complete() - read complete
597 * @rb: Pointer to client request block
598 *
599 * If the message is completely received call ishtp_cl_bus_rx_event()
600 * to process message
601 */
602static void ishtp_cl_read_complete(struct ishtp_cl_rb *rb)
603{
604 unsigned long flags;
605 int schedule_work_flag = 0;
606 struct ishtp_cl *cl = rb->cl;
607
608 spin_lock_irqsave(&cl->in_process_spinlock, flags);
609 /*
610 * if in-process list is empty, then need to schedule
611 * the processing thread
612 */
613 schedule_work_flag = list_empty(&cl->in_process_list.list);
614 list_add_tail(&rb->list, &cl->in_process_list.list);
615 spin_unlock_irqrestore(&cl->in_process_spinlock, flags);
616
617 if (schedule_work_flag)
618 ishtp_cl_bus_rx_event(cl->device);
619}
620
621/**
622 * ipc_tx_callback() - IPC tx callback function
623 * @prm: Pointer to client device instance
624 *
625 * Send message over IPC either first time or on callback on previous message
626 * completion
627 */
628static void ipc_tx_callback(void *prm)
629{
630 struct ishtp_cl *cl = prm;
631 struct ishtp_cl_tx_ring *cl_msg;
632 size_t rem;
633 struct ishtp_device *dev = (cl ? cl->dev : NULL);
634 struct ishtp_msg_hdr ishtp_hdr;
635 unsigned long tx_flags, tx_free_flags;
636 unsigned char *pmsg;
637
638 if (!dev)
639 return;
640
641 /*
642 * Other conditions if some critical error has
643 * occurred before this callback is called
644 */
645 if (dev->dev_state != ISHTP_DEV_ENABLED)
646 return;
647
648 if (cl->state != ISHTP_CL_CONNECTED)
649 return;
650
651 spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags);
652 if (list_empty(&cl->tx_list.list)) {
653 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
654 return;
655 }
656
657 if (cl->ishtp_flow_ctrl_creds != 1 && !cl->sending) {
658 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
659 return;
660 }
661
662 if (!cl->sending) {
663 --cl->ishtp_flow_ctrl_creds;
664 cl->last_ipc_acked = 0;
665 cl->last_tx_path = CL_TX_PATH_IPC;
666 cl->sending = 1;
667 }
668
669 cl_msg = list_entry(cl->tx_list.list.next, struct ishtp_cl_tx_ring,
670 list);
671 rem = cl_msg->send_buf.size - cl->tx_offs;
672
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;
677
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);
697 }
698}
699
700/**
701 * ishtp_cl_send_msg_ipc() -Send message using IPC
702 * @dev: ISHTP device instance
703 * @cl: Pointer to client device instance
704 *
705 * Send message over IPC not using DMA
706 */
707static void ishtp_cl_send_msg_ipc(struct ishtp_device *dev,
708 struct ishtp_cl *cl)
709{
710 /* If last DMA message wasn't acked yet, leave this one in Tx queue */
711 if (cl->last_tx_path == CL_TX_PATH_DMA && cl->last_dma_acked == 0)
712 return;
713
714 cl->tx_offs = 0;
715 ipc_tx_callback(cl);
716 ++cl->send_msg_cnt_ipc;
717}
718
719/**
720 * ishtp_cl_send_msg_dma() -Send message using DMA
721 * @dev: ISHTP device instance
722 * @cl: Pointer to client device instance
723 *
724 * Send message using DMA
725 */
726static void ishtp_cl_send_msg_dma(struct ishtp_device *dev,
727 struct ishtp_cl *cl)
728{
729 struct ishtp_msg_hdr hdr;
730 struct dma_xfer_hbm dma_xfer;
731 unsigned char *msg_addr;
732 int off;
733 struct ishtp_cl_tx_ring *cl_msg;
734 unsigned long tx_flags, tx_free_flags;
735
736 /* If last IPC message wasn't acked yet, leave this one in Tx queue */
737 if (cl->last_tx_path == CL_TX_PATH_IPC && cl->last_ipc_acked == 0)
738 return;
739
740 spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags);
741 if (list_empty(&cl->tx_list.list)) {
742 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
743 return;
744 }
745
746 cl_msg = list_entry(cl->tx_list.list.next, struct ishtp_cl_tx_ring,
747 list);
748
749 msg_addr = ishtp_cl_get_dma_send_buf(dev, cl_msg->send_buf.size);
750 if (!msg_addr) {
751 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
752 if (dev->transfer_path == CL_TX_PATH_DEFAULT)
753 ishtp_cl_send_msg_ipc(dev, cl);
754 return;
755 }
756
757 list_del_init(&cl_msg->list); /* Must be before write */
758 spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
759
760 --cl->ishtp_flow_ctrl_creds;
761 cl->last_dma_acked = 0;
762 cl->last_dma_addr = msg_addr;
763 cl->last_tx_path = CL_TX_PATH_DMA;
764
765 /* write msg to dma buf */
766 memcpy(msg_addr, cl_msg->send_buf.data, cl_msg->send_buf.size);
767
768 /* send dma_xfer hbm msg */
769 off = msg_addr - (unsigned char *)dev->ishtp_host_dma_tx_buf;
770 ishtp_hbm_hdr(&hdr, sizeof(struct dma_xfer_hbm));
771 dma_xfer.hbm = DMA_XFER;
772 dma_xfer.fw_client_id = cl->fw_client_id;
773 dma_xfer.host_client_id = cl->host_client_id;
774 dma_xfer.reserved = 0;
775 dma_xfer.msg_addr = dev->ishtp_host_dma_tx_buf_phys + off;
776 dma_xfer.msg_length = cl_msg->send_buf.size;
777 dma_xfer.reserved2 = 0;
778 ishtp_write_message(dev, &hdr, (unsigned char *)&dma_xfer);
779 spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
780 list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
781 spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags);
782 ++cl->send_msg_cnt_dma;
783}
784
785/**
786 * ishtp_cl_send_msg() -Send message using DMA or IPC
787 * @dev: ISHTP device instance
788 * @cl: Pointer to client device instance
789 *
790 * Send message using DMA or IPC based on transfer_path
791 */
792void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl)
793{
794 if (dev->transfer_path == CL_TX_PATH_DMA)
795 ishtp_cl_send_msg_dma(dev, cl);
796 else
797 ishtp_cl_send_msg_ipc(dev, cl);
798}
799
800/**
801 * recv_ishtp_cl_msg() -Receive client message
802 * @dev: ISHTP device instance
803 * @ishtp_hdr: Pointer to message header
804 *
805 * Receive and dispatch ISHTP client messages. This function executes in ISR
806 * context
807 */
808void recv_ishtp_cl_msg(struct ishtp_device *dev,
809 struct ishtp_msg_hdr *ishtp_hdr)
810{
811 struct ishtp_cl *cl;
812 struct ishtp_cl_rb *rb;
813 struct ishtp_cl_rb *new_rb;
814 unsigned char *buffer = NULL;
815 struct ishtp_cl_rb *complete_rb = NULL;
816 unsigned long dev_flags;
817 unsigned long flags;
818 int rb_count;
819
820 if (ishtp_hdr->reserved) {
821 dev_err(dev->devc, "corrupted message header.\n");
822 goto eoi;
823 }
824
825 if (ishtp_hdr->length > IPC_PAYLOAD_SIZE) {
826 dev_err(dev->devc,
827 "ISHTP message length in hdr exceeds IPC MTU\n");
828 goto eoi;
829 }
830
831 spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
832 rb_count = -1;
833 list_for_each_entry(rb, &dev->read_list.list, list) {
834 ++rb_count;
835 cl = rb->cl;
836 if (!cl || !(cl->host_client_id == ishtp_hdr->host_addr &&
837 cl->fw_client_id == ishtp_hdr->fw_addr) ||
838 !(cl->state == ISHTP_CL_CONNECTED))
839 continue;
840
841 /* If no Rx buffer is allocated, disband the rb */
842 if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
843 spin_unlock_irqrestore(&dev->read_list_spinlock,
844 dev_flags);
845 dev_err(&cl->device->dev,
846 "Rx buffer is not allocated.\n");
847 list_del(&rb->list);
848 ishtp_io_rb_free(rb);
849 cl->status = -ENOMEM;
850 goto eoi;
851 }
852
853 /*
854 * If message buffer overflown (exceeds max. client msg
855 * size, drop message and return to free buffer.
856 * Do we need to disconnect such a client? (We don't send
857 * back FC, so communication will be stuck anyway)
858 */
859 if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) {
860 spin_unlock_irqrestore(&dev->read_list_spinlock,
861 dev_flags);
862 dev_err(&cl->device->dev,
863 "message overflow. size %d len %d idx %ld\n",
864 rb->buffer.size, ishtp_hdr->length,
865 rb->buf_idx);
866 list_del(&rb->list);
867 ishtp_cl_io_rb_recycle(rb);
868 cl->status = -EIO;
869 goto eoi;
870 }
871
872 buffer = rb->buffer.data + rb->buf_idx;
873 dev->ops->ishtp_read(dev, buffer, ishtp_hdr->length);
874
875 rb->buf_idx += ishtp_hdr->length;
876 if (ishtp_hdr->msg_complete) {
877 /* Last fragment in message - it's complete */
878 cl->status = 0;
879 list_del(&rb->list);
880 complete_rb = rb;
881
882 --cl->out_flow_ctrl_creds;
883 /*
884 * the whole msg arrived, send a new FC, and add a new
885 * rb buffer for the next coming msg
886 */
887 spin_lock_irqsave(&cl->free_list_spinlock, flags);
888
889 if (!list_empty(&cl->free_rb_list.list)) {
890 new_rb = list_entry(cl->free_rb_list.list.next,
891 struct ishtp_cl_rb, list);
892 list_del_init(&new_rb->list);
893 spin_unlock_irqrestore(&cl->free_list_spinlock,
894 flags);
895 new_rb->cl = cl;
896 new_rb->buf_idx = 0;
897 INIT_LIST_HEAD(&new_rb->list);
898 list_add_tail(&new_rb->list,
899 &dev->read_list.list);
900
901 ishtp_hbm_cl_flow_control_req(dev, cl);
902 } else {
903 spin_unlock_irqrestore(&cl->free_list_spinlock,
904 flags);
905 }
906 }
907 /* One more fragment in message (even if this was last) */
908 ++cl->recv_msg_num_frags;
909
910 /*
911 * We can safely break here (and in BH too),
912 * a single input message can go only to a single request!
913 */
914 break;
915 }
916
917 spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
918 /* If it's nobody's message, just read and discard it */
919 if (!buffer) {
920 uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
921
922 dev_err(dev->devc, "Dropped Rx msg - no request\n");
923 dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length);
924 goto eoi;
925 }
926
927 if (complete_rb) {
928 getnstimeofday(&cl->ts_rx);
929 ++cl->recv_msg_cnt_ipc;
930 ishtp_cl_read_complete(complete_rb);
931 }
932eoi:
933 return;
934}
935
936/**
937 * recv_ishtp_cl_msg_dma() -Receive client message
938 * @dev: ISHTP device instance
939 * @msg: message pointer
940 * @hbm: hbm buffer
941 *
942 * Receive and dispatch ISHTP client messages using DMA. This function executes
943 * in ISR context
944 */
945void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
946 struct dma_xfer_hbm *hbm)
947{
948 struct ishtp_cl *cl;
949 struct ishtp_cl_rb *rb;
950 struct ishtp_cl_rb *new_rb;
951 unsigned char *buffer = NULL;
952 struct ishtp_cl_rb *complete_rb = NULL;
953 unsigned long dev_flags;
954 unsigned long flags;
955
956 spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
957 list_for_each_entry(rb, &dev->read_list.list, list) {
958 cl = rb->cl;
959 if (!cl || !(cl->host_client_id == hbm->host_client_id &&
960 cl->fw_client_id == hbm->fw_client_id) ||
961 !(cl->state == ISHTP_CL_CONNECTED))
962 continue;
963
964 /*
965 * If no Rx buffer is allocated, disband the rb
966 */
967 if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
968 spin_unlock_irqrestore(&dev->read_list_spinlock,
969 dev_flags);
970 dev_err(&cl->device->dev,
971 "response buffer is not allocated.\n");
972 list_del(&rb->list);
973 ishtp_io_rb_free(rb);
974 cl->status = -ENOMEM;
975 goto eoi;
976 }
977
978 /*
979 * If message buffer overflown (exceeds max. client msg
980 * size, drop message and return to free buffer.
981 * Do we need to disconnect such a client? (We don't send
982 * back FC, so communication will be stuck anyway)
983 */
984 if (rb->buffer.size < hbm->msg_length) {
985 spin_unlock_irqrestore(&dev->read_list_spinlock,
986 dev_flags);
987 dev_err(&cl->device->dev,
988 "message overflow. size %d len %d idx %ld\n",
989 rb->buffer.size, hbm->msg_length, rb->buf_idx);
990 list_del(&rb->list);
991 ishtp_cl_io_rb_recycle(rb);
992 cl->status = -EIO;
993 goto eoi;
994 }
995
996 buffer = rb->buffer.data;
997 memcpy(buffer, msg, hbm->msg_length);
998 rb->buf_idx = hbm->msg_length;
999
1000 /* Last fragment in message - it's complete */
1001 cl->status = 0;
1002 list_del(&rb->list);
1003 complete_rb = rb;
1004
1005 --cl->out_flow_ctrl_creds;
1006 /*
1007 * the whole msg arrived, send a new FC, and add a new
1008 * rb buffer for the next coming msg
1009 */
1010 spin_lock_irqsave(&cl->free_list_spinlock, flags);
1011
1012 if (!list_empty(&cl->free_rb_list.list)) {
1013 new_rb = list_entry(cl->free_rb_list.list.next,
1014 struct ishtp_cl_rb, list);
1015 list_del_init(&new_rb->list);
1016 spin_unlock_irqrestore(&cl->free_list_spinlock,
1017 flags);
1018 new_rb->cl = cl;
1019 new_rb->buf_idx = 0;
1020 INIT_LIST_HEAD(&new_rb->list);
1021 list_add_tail(&new_rb->list,
1022 &dev->read_list.list);
1023
1024 ishtp_hbm_cl_flow_control_req(dev, cl);
1025 } else {
1026 spin_unlock_irqrestore(&cl->free_list_spinlock,
1027 flags);
1028 }
1029
1030 /* One more fragment in message (this is always last) */
1031 ++cl->recv_msg_num_frags;
1032
1033 /*
1034 * We can safely break here (and in BH too),
1035 * a single input message can go only to a single request!
1036 */
1037 break;
1038 }
1039
1040 spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
1041 /* If it's nobody's message, just read and discard it */
1042 if (!buffer) {
1043 dev_err(dev->devc, "Dropped Rx (DMA) msg - no request\n");
1044 goto eoi;
1045 }
1046
1047 if (complete_rb) {
1048 getnstimeofday(&cl->ts_rx);
1049 ++cl->recv_msg_cnt_dma;
1050 ishtp_cl_read_complete(complete_rb);
1051 }
1052eoi:
1053 return;
1054}
diff --git a/drivers/hid/intel-ish-hid/ishtp/client.h b/drivers/hid/intel-ish-hid/ishtp/client.h
new file mode 100644
index 000000000000..444d069c2ed4
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/client.h
@@ -0,0 +1,182 @@
1/*
2 * ISHTP client logic
3 *
4 * 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 */
15
16#ifndef _ISHTP_CLIENT_H_
17#define _ISHTP_CLIENT_H_
18
19#include <linux/types.h>
20#include "ishtp-dev.h"
21
22/* Client state */
23enum cl_state {
24 ISHTP_CL_INITIALIZING = 0,
25 ISHTP_CL_CONNECTING,
26 ISHTP_CL_CONNECTED,
27 ISHTP_CL_DISCONNECTING,
28 ISHTP_CL_DISCONNECTED
29};
30
31/* Tx and Rx ring size */
32#define CL_DEF_RX_RING_SIZE 2
33#define CL_DEF_TX_RING_SIZE 2
34#define CL_MAX_RX_RING_SIZE 32
35#define CL_MAX_TX_RING_SIZE 32
36
37#define DMA_SLOT_SIZE 4096
38/* Number of IPC fragments after which it's worth sending via DMA */
39#define DMA_WORTH_THRESHOLD 3
40
41/* DMA/IPC Tx paths. Other the default means enforcement */
42#define CL_TX_PATH_DEFAULT 0
43#define CL_TX_PATH_IPC 1
44#define CL_TX_PATH_DMA 2
45
46/* Client Tx buffer list entry */
47struct ishtp_cl_tx_ring {
48 struct list_head list;
49 struct ishtp_msg_data send_buf;
50};
51
52/* ISHTP client instance */
53struct ishtp_cl {
54 struct list_head link;
55 struct ishtp_device *dev;
56 enum cl_state state;
57 int status;
58
59 /* Link to ISHTP bus device */
60 struct ishtp_cl_device *device;
61
62 /* ID of client connected */
63 uint8_t host_client_id;
64 uint8_t fw_client_id;
65 uint8_t ishtp_flow_ctrl_creds;
66 uint8_t out_flow_ctrl_creds;
67
68 /* dma */
69 int last_tx_path;
70 /* 0: ack wasn't received,1:ack was received */
71 int last_dma_acked;
72 unsigned char *last_dma_addr;
73 /* 0: ack wasn't received,1:ack was received */
74 int last_ipc_acked;
75
76 /* Rx ring buffer pool */
77 unsigned int rx_ring_size;
78 struct ishtp_cl_rb free_rb_list;
79 spinlock_t free_list_spinlock;
80 /* Rx in-process list */
81 struct ishtp_cl_rb in_process_list;
82 spinlock_t in_process_spinlock;
83
84 /* Client Tx buffers list */
85 unsigned int tx_ring_size;
86 struct ishtp_cl_tx_ring tx_list, tx_free_list;
87 spinlock_t tx_list_spinlock;
88 spinlock_t tx_free_list_spinlock;
89 size_t tx_offs; /* Offset in buffer at head of 'tx_list' */
90
91 /**
92 * if we get a FC, and the list is not empty, we must know whether we
93 * are at the middle of sending.
94 * if so -need to increase FC counter, otherwise, need to start sending
95 * the first msg in list
96 * (!)This is for counting-FC implementation only. Within single-FC the
97 * other party may NOT send FC until it receives complete message
98 */
99 int sending;
100
101 /* Send FC spinlock */
102 spinlock_t fc_spinlock;
103
104 /* wait queue for connect and disconnect response from FW */
105 wait_queue_head_t wait_ctrl_res;
106
107 /* Error stats */
108 unsigned int err_send_msg;
109 unsigned int err_send_fc;
110
111 /* Send/recv stats */
112 unsigned int send_msg_cnt_ipc;
113 unsigned int send_msg_cnt_dma;
114 unsigned int recv_msg_cnt_ipc;
115 unsigned int recv_msg_cnt_dma;
116 unsigned int recv_msg_num_frags;
117 unsigned int ishtp_flow_ctrl_cnt;
118 unsigned int out_flow_ctrl_cnt;
119
120 /* Rx msg ... out FC timing */
121 struct timespec ts_rx;
122 struct timespec ts_out_fc;
123 struct timespec ts_max_fc_delay;
124 void *client_data;
125};
126
127/* Client connection managenment internal functions */
128int ishtp_can_client_connect(struct ishtp_device *ishtp_dev, uuid_le *uuid);
129int ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id);
130void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl);
131void recv_ishtp_cl_msg(struct ishtp_device *dev,
132 struct ishtp_msg_hdr *ishtp_hdr);
133int ishtp_cl_read_start(struct ishtp_cl *cl);
134
135/* Ring Buffer I/F */
136int ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl);
137int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl);
138void ishtp_cl_free_rx_ring(struct ishtp_cl *cl);
139void ishtp_cl_free_tx_ring(struct ishtp_cl *cl);
140
141/* DMA I/F functions */
142void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
143 struct dma_xfer_hbm *hbm);
144void ishtp_cl_alloc_dma_buf(struct ishtp_device *dev);
145void ishtp_cl_free_dma_buf(struct ishtp_device *dev);
146void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev,
147 uint32_t size);
148void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev,
149 void *msg_addr,
150 uint8_t size);
151
152/* Request blocks alloc/free I/F */
153struct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl);
154void ishtp_io_rb_free(struct ishtp_cl_rb *priv_rb);
155int ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length);
156
157/**
158 * ishtp_cl_cmp_id - tells if file private data have same id
159 * returns true - if ids are the same and not NULL
160 */
161static inline bool ishtp_cl_cmp_id(const struct ishtp_cl *cl1,
162 const struct ishtp_cl *cl2)
163{
164 return cl1 && cl2 &&
165 (cl1->host_client_id == cl2->host_client_id) &&
166 (cl1->fw_client_id == cl2->fw_client_id);
167}
168
169/* exported functions from ISHTP under client management scope */
170struct ishtp_cl *ishtp_cl_allocate(struct ishtp_device *dev);
171void ishtp_cl_free(struct ishtp_cl *cl);
172int ishtp_cl_link(struct ishtp_cl *cl, int id);
173void ishtp_cl_unlink(struct ishtp_cl *cl);
174int ishtp_cl_disconnect(struct ishtp_cl *cl);
175int ishtp_cl_connect(struct ishtp_cl *cl);
176int ishtp_cl_send(struct ishtp_cl *cl, uint8_t *buf, size_t length);
177int ishtp_cl_flush_queues(struct ishtp_cl *cl);
178
179/* exported functions from ISHTP client buffer management scope */
180int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb);
181
182#endif /* _ISHTP_CLIENT_H_ */
diff --git a/drivers/hid/intel-ish-hid/ishtp/dma-if.c b/drivers/hid/intel-ish-hid/ishtp/dma-if.c
new file mode 100644
index 000000000000..2783f3666114
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/dma-if.c
@@ -0,0 +1,175 @@
1/*
2 * ISHTP DMA I/F functions
3 *
4 * 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 *
15 */
16
17#include <linux/slab.h>
18#include <linux/sched.h>
19#include <linux/wait.h>
20#include <linux/delay.h>
21#include <linux/dma-mapping.h>
22#include "ishtp-dev.h"
23#include "client.h"
24
25/**
26 * ishtp_cl_alloc_dma_buf() - Allocate DMA RX and TX buffer
27 * @dev: ishtp device
28 *
29 * Allocate RX and TX DMA buffer once during bus setup.
30 * It allocates 1MB, RX and TX DMA buffer, which are divided
31 * into slots.
32 */
33void ishtp_cl_alloc_dma_buf(struct ishtp_device *dev)
34{
35 dma_addr_t h;
36
37 if (dev->ishtp_host_dma_tx_buf)
38 return;
39
40 dev->ishtp_host_dma_tx_buf_size = 1024*1024;
41 dev->ishtp_host_dma_rx_buf_size = 1024*1024;
42
43 /* Allocate Tx buffer and init usage bitmap */
44 dev->ishtp_host_dma_tx_buf = dma_alloc_coherent(dev->devc,
45 dev->ishtp_host_dma_tx_buf_size,
46 &h, GFP_KERNEL);
47 if (dev->ishtp_host_dma_tx_buf)
48 dev->ishtp_host_dma_tx_buf_phys = h;
49
50 dev->ishtp_dma_num_slots = dev->ishtp_host_dma_tx_buf_size /
51 DMA_SLOT_SIZE;
52
53 dev->ishtp_dma_tx_map = kcalloc(dev->ishtp_dma_num_slots,
54 sizeof(uint8_t),
55 GFP_KERNEL);
56 spin_lock_init(&dev->ishtp_dma_tx_lock);
57
58 /* Allocate Rx buffer */
59 dev->ishtp_host_dma_rx_buf = dma_alloc_coherent(dev->devc,
60 dev->ishtp_host_dma_rx_buf_size,
61 &h, GFP_KERNEL);
62
63 if (dev->ishtp_host_dma_rx_buf)
64 dev->ishtp_host_dma_rx_buf_phys = h;
65}
66
67/**
68 * ishtp_cl_free_dma_buf() - Free DMA RX and TX buffer
69 * @dev: ishtp device
70 *
71 * Free DMA buffer when all clients are released. This is
72 * only happens during error path in ISH built in driver
73 * model
74 */
75void ishtp_cl_free_dma_buf(struct ishtp_device *dev)
76{
77 dma_addr_t h;
78
79 if (dev->ishtp_host_dma_tx_buf) {
80 h = dev->ishtp_host_dma_tx_buf_phys;
81 dma_free_coherent(dev->devc, dev->ishtp_host_dma_tx_buf_size,
82 dev->ishtp_host_dma_tx_buf, h);
83 }
84
85 if (dev->ishtp_host_dma_rx_buf) {
86 h = dev->ishtp_host_dma_rx_buf_phys;
87 dma_free_coherent(dev->devc, dev->ishtp_host_dma_rx_buf_size,
88 dev->ishtp_host_dma_rx_buf, h);
89 }
90
91 kfree(dev->ishtp_dma_tx_map);
92 dev->ishtp_host_dma_tx_buf = NULL;
93 dev->ishtp_host_dma_rx_buf = NULL;
94 dev->ishtp_dma_tx_map = NULL;
95}
96
97/*
98 * ishtp_cl_get_dma_send_buf() - Get a DMA memory slot
99 * @dev: ishtp device
100 * @size: Size of memory to get
101 *
102 * Find and return free address of "size" bytes in dma tx buffer.
103 * the function will mark this address as "in-used" memory.
104 *
105 * Return: NULL when no free buffer else a buffer to copy
106 */
107void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev,
108 uint32_t size)
109{
110 unsigned long flags;
111 int i, j, free;
112 /* additional slot is needed if there is rem */
113 int required_slots = (size / DMA_SLOT_SIZE)
114 + 1 * (size % DMA_SLOT_SIZE != 0);
115
116 spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
117 for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) {
118 free = 1;
119 for (j = 0; j < required_slots; j++)
120 if (dev->ishtp_dma_tx_map[i+j]) {
121 free = 0;
122 i += j;
123 break;
124 }
125 if (free) {
126 /* mark memory as "caught" */
127 for (j = 0; j < required_slots; j++)
128 dev->ishtp_dma_tx_map[i+j] = 1;
129 spin_unlock_irqrestore(&dev->ishtp_dma_tx_lock, flags);
130 return (i * DMA_SLOT_SIZE) +
131 (unsigned char *)dev->ishtp_host_dma_tx_buf;
132 }
133 }
134 spin_unlock_irqrestore(&dev->ishtp_dma_tx_lock, flags);
135 dev_err(dev->devc, "No free DMA buffer to send msg\n");
136 return NULL;
137}
138
139/*
140 * ishtp_cl_release_dma_acked_mem() - Release DMA memory slot
141 * @dev: ishtp device
142 * @msg_addr: message address of slot
143 * @size: Size of memory to get
144 *
145 * Release_dma_acked_mem - returnes the acked memory to free list.
146 * (from msg_addr, size bytes long)
147 */
148void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev,
149 void *msg_addr,
150 uint8_t size)
151{
152 unsigned long flags;
153 int acked_slots = (size / DMA_SLOT_SIZE)
154 + 1 * (size % DMA_SLOT_SIZE != 0);
155 int i, j;
156
157 if ((msg_addr - dev->ishtp_host_dma_tx_buf) % DMA_SLOT_SIZE) {
158 dev_err(dev->devc, "Bad DMA Tx ack address\n");
159 return;
160 }
161
162 i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE;
163 spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
164 for (j = 0; j < acked_slots; j++) {
165 if ((i + j) >= dev->ishtp_dma_num_slots ||
166 !dev->ishtp_dma_tx_map[i+j]) {
167 /* no such slot, or memory is already free */
168 spin_unlock_irqrestore(&dev->ishtp_dma_tx_lock, flags);
169 dev_err(dev->devc, "Bad DMA Tx ack address\n");
170 return;
171 }
172 dev->ishtp_dma_tx_map[i+j] = 0;
173 }
174 spin_unlock_irqrestore(&dev->ishtp_dma_tx_lock, flags);
175}
diff --git a/drivers/hid/intel-ish-hid/ishtp/hbm.c b/drivers/hid/intel-ish-hid/ishtp/hbm.c
new file mode 100644
index 000000000000..74bffee60774
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/hbm.c
@@ -0,0 +1,1032 @@
1/*
2 * ISHTP bus layer messages handling
3 *
4 * 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 *
15 */
16
17#include <linux/export.h>
18#include <linux/slab.h>
19#include <linux/sched.h>
20#include <linux/wait.h>
21#include <linux/spinlock.h>
22#include <linux/miscdevice.h>
23#include "ishtp-dev.h"
24#include "hbm.h"
25#include "client.h"
26
27/**
28 * ishtp_hbm_fw_cl_allocate() - Allocate FW clients
29 * @dev: ISHTP device instance
30 *
31 * Allocates storage for fw clients
32 */
33static void ishtp_hbm_fw_cl_allocate(struct ishtp_device *dev)
34{
35 struct ishtp_fw_client *clients;
36 int b;
37
38 /* count how many ISH clients we have */
39 for_each_set_bit(b, dev->fw_clients_map, ISHTP_CLIENTS_MAX)
40 dev->fw_clients_num++;
41
42 if (dev->fw_clients_num <= 0)
43 return;
44
45 /* allocate storage for fw clients representation */
46 clients = kcalloc(dev->fw_clients_num, sizeof(struct ishtp_fw_client),
47 GFP_KERNEL);
48 if (!clients) {
49 dev->dev_state = ISHTP_DEV_RESETTING;
50 ish_hw_reset(dev);
51 return;
52 }
53 dev->fw_clients = clients;
54}
55
56/**
57 * ishtp_hbm_cl_hdr() - construct client hbm header
58 * @cl: client
59 * @hbm_cmd: host bus message command
60 * @buf: buffer for cl header
61 * @len: buffer length
62 *
63 * Initialize HBM buffer
64 */
65static inline void ishtp_hbm_cl_hdr(struct ishtp_cl *cl, uint8_t hbm_cmd,
66 void *buf, size_t len)
67{
68 struct ishtp_hbm_cl_cmd *cmd = buf;
69
70 memset(cmd, 0, len);
71
72 cmd->hbm_cmd = hbm_cmd;
73 cmd->host_addr = cl->host_client_id;
74 cmd->fw_addr = cl->fw_client_id;
75}
76
77/**
78 * ishtp_hbm_cl_addr_equal() - Compare client address
79 * @cl: client
80 * @buf: Client command buffer
81 *
82 * Compare client address with the address in command buffer
83 *
84 * Return: True if they have the same address
85 */
86static inline bool ishtp_hbm_cl_addr_equal(struct ishtp_cl *cl, void *buf)
87{
88 struct ishtp_hbm_cl_cmd *cmd = buf;
89
90 return cl->host_client_id == cmd->host_addr &&
91 cl->fw_client_id == cmd->fw_addr;
92}
93
94/**
95 * ishtp_hbm_start_wait() - Wait for HBM start message
96 * @dev: ISHTP device instance
97 *
98 * Wait for HBM start message from firmware
99 *
100 * Return: 0 if HBM start is/was received else timeout error
101 */
102int ishtp_hbm_start_wait(struct ishtp_device *dev)
103{
104 int ret;
105
106 if (dev->hbm_state > ISHTP_HBM_START)
107 return 0;
108
109 dev_dbg(dev->devc, "Going to wait for ishtp start. hbm_state=%08X\n",
110 dev->hbm_state);
111 ret = wait_event_interruptible_timeout(dev->wait_hbm_recvd_msg,
112 dev->hbm_state >= ISHTP_HBM_STARTED,
113 (ISHTP_INTEROP_TIMEOUT * HZ));
114
115 dev_dbg(dev->devc,
116 "Woke up from waiting for ishtp start. hbm_state=%08X\n",
117 dev->hbm_state);
118
119 if (ret <= 0 && (dev->hbm_state <= ISHTP_HBM_START)) {
120 dev->hbm_state = ISHTP_HBM_IDLE;
121 dev_err(dev->devc,
122 "waiting for ishtp start failed. ret=%d hbm_state=%08X\n",
123 ret, dev->hbm_state);
124 return -ETIMEDOUT;
125 }
126 return 0;
127}
128
129/**
130 * ishtp_hbm_start_req() - Send HBM start message
131 * @dev: ISHTP device instance
132 *
133 * Send HBM start message to firmware
134 *
135 * Return: 0 if success else error code
136 */
137int ishtp_hbm_start_req(struct ishtp_device *dev)
138{
139 struct ishtp_msg_hdr hdr;
140 unsigned char data[128];
141 struct ishtp_msg_hdr *ishtp_hdr = &hdr;
142 struct hbm_host_version_request *start_req;
143 const size_t len = sizeof(struct hbm_host_version_request);
144
145 ishtp_hbm_hdr(ishtp_hdr, len);
146
147 /* host start message */
148 start_req = (struct hbm_host_version_request *)data;
149 memset(start_req, 0, len);
150 start_req->hbm_cmd = HOST_START_REQ_CMD;
151 start_req->host_version.major_version = HBM_MAJOR_VERSION;
152 start_req->host_version.minor_version = HBM_MINOR_VERSION;
153
154 /*
155 * (!) Response to HBM start may be so quick that this thread would get
156 * preempted BEFORE managing to set hbm_state = ISHTP_HBM_START.
157 * So set it at first, change back to ISHTP_HBM_IDLE upon failure
158 */
159 dev->hbm_state = ISHTP_HBM_START;
160 if (ishtp_write_message(dev, ishtp_hdr, data)) {
161 dev_err(dev->devc, "version message send failed\n");
162 dev->dev_state = ISHTP_DEV_RESETTING;
163 dev->hbm_state = ISHTP_HBM_IDLE;
164 ish_hw_reset(dev);
165 return -ENODEV;
166 }
167
168 return 0;
169}
170
171/**
172 * ishtp_hbm_enum_clients_req() - Send client enum req
173 * @dev: ISHTP device instance
174 *
175 * Send enumeration client request message
176 *
177 * Return: 0 if success else error code
178 */
179void ishtp_hbm_enum_clients_req(struct ishtp_device *dev)
180{
181 struct ishtp_msg_hdr hdr;
182 unsigned char data[128];
183 struct ishtp_msg_hdr *ishtp_hdr = &hdr;
184 struct hbm_host_enum_request *enum_req;
185 const size_t len = sizeof(struct hbm_host_enum_request);
186
187 /* enumerate clients */
188 ishtp_hbm_hdr(ishtp_hdr, len);
189
190 enum_req = (struct hbm_host_enum_request *)data;
191 memset(enum_req, 0, len);
192 enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
193
194 if (ishtp_write_message(dev, ishtp_hdr, data)) {
195 dev->dev_state = ISHTP_DEV_RESETTING;
196 dev_err(dev->devc, "enumeration request send failed\n");
197 ish_hw_reset(dev);
198 }
199 dev->hbm_state = ISHTP_HBM_ENUM_CLIENTS;
200}
201
202/**
203 * ishtp_hbm_prop_req() - Request property
204 * @dev: ISHTP device instance
205 *
206 * Request property for a single client
207 *
208 * Return: 0 if success else error code
209 */
210static int ishtp_hbm_prop_req(struct ishtp_device *dev)
211{
212
213 struct ishtp_msg_hdr hdr;
214 unsigned char data[128];
215 struct ishtp_msg_hdr *ishtp_hdr = &hdr;
216 struct hbm_props_request *prop_req;
217 const size_t len = sizeof(struct hbm_props_request);
218 unsigned long next_client_index;
219 uint8_t client_num;
220
221 client_num = dev->fw_client_presentation_num;
222
223 next_client_index = find_next_bit(dev->fw_clients_map,
224 ISHTP_CLIENTS_MAX, dev->fw_client_index);
225
226 /* We got all client properties */
227 if (next_client_index == ISHTP_CLIENTS_MAX) {
228 dev->hbm_state = ISHTP_HBM_WORKING;
229 dev->dev_state = ISHTP_DEV_ENABLED;
230
231 for (dev->fw_client_presentation_num = 1;
232 dev->fw_client_presentation_num < client_num + 1;
233 ++dev->fw_client_presentation_num)
234 /* Add new client device */
235 ishtp_bus_new_client(dev);
236 return 0;
237 }
238
239 dev->fw_clients[client_num].client_id = next_client_index;
240
241 ishtp_hbm_hdr(ishtp_hdr, len);
242 prop_req = (struct hbm_props_request *)data;
243
244 memset(prop_req, 0, sizeof(struct hbm_props_request));
245
246 prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
247 prop_req->address = next_client_index;
248
249 if (ishtp_write_message(dev, ishtp_hdr, data)) {
250 dev->dev_state = ISHTP_DEV_RESETTING;
251 dev_err(dev->devc, "properties request send failed\n");
252 ish_hw_reset(dev);
253 return -EIO;
254 }
255
256 dev->fw_client_index = next_client_index;
257
258 return 0;
259}
260
261/**
262 * ishtp_hbm_stop_req() - Send HBM stop
263 * @dev: ISHTP device instance
264 *
265 * Send stop request message
266 */
267static void ishtp_hbm_stop_req(struct ishtp_device *dev)
268{
269 struct ishtp_msg_hdr hdr;
270 unsigned char data[128];
271 struct ishtp_msg_hdr *ishtp_hdr = &hdr;
272 struct hbm_host_stop_request *req;
273 const size_t len = sizeof(struct hbm_host_stop_request);
274
275 ishtp_hbm_hdr(ishtp_hdr, len);
276 req = (struct hbm_host_stop_request *)data;
277
278 memset(req, 0, sizeof(struct hbm_host_stop_request));
279 req->hbm_cmd = HOST_STOP_REQ_CMD;
280 req->reason = DRIVER_STOP_REQUEST;
281
282 ishtp_write_message(dev, ishtp_hdr, data);
283}
284
285/**
286 * ishtp_hbm_cl_flow_control_req() - Send flow control request
287 * @dev: ISHTP device instance
288 * @cl: ISHTP client instance
289 *
290 * Send flow control request
291 *
292 * Return: 0 if success else error code
293 */
294int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
295 struct ishtp_cl *cl)
296{
297 struct ishtp_msg_hdr hdr;
298 unsigned char data[128];
299 struct ishtp_msg_hdr *ishtp_hdr = &hdr;
300 const size_t len = sizeof(struct hbm_flow_control);
301 int rv;
302 unsigned int num_frags;
303 unsigned long flags;
304
305 spin_lock_irqsave(&cl->fc_spinlock, flags);
306 ishtp_hbm_hdr(ishtp_hdr, len);
307 ishtp_hbm_cl_hdr(cl, ISHTP_FLOW_CONTROL_CMD, data, len);
308
309 /*
310 * Sync possible race when RB recycle and packet receive paths
311 * both try to send an out FC
312 */
313 if (cl->out_flow_ctrl_creds) {
314 spin_unlock_irqrestore(&cl->fc_spinlock, flags);
315 return 0;
316 }
317
318 num_frags = cl->recv_msg_num_frags;
319 cl->recv_msg_num_frags = 0;
320
321 rv = ishtp_write_message(dev, ishtp_hdr, data);
322 if (!rv) {
323 ++cl->out_flow_ctrl_creds;
324 ++cl->out_flow_ctrl_cnt;
325 getnstimeofday(&cl->ts_out_fc);
326 if (cl->ts_rx.tv_sec && cl->ts_rx.tv_nsec) {
327 struct timespec ts_diff;
328
329 ts_diff = timespec_sub(cl->ts_out_fc, cl->ts_rx);
330 if (timespec_compare(&ts_diff, &cl->ts_max_fc_delay)
331 > 0)
332 cl->ts_max_fc_delay = ts_diff;
333 }
334 } else {
335 ++cl->err_send_fc;
336 }
337
338 spin_unlock_irqrestore(&cl->fc_spinlock, flags);
339 return rv;
340}
341
342/**
343 * ishtp_hbm_cl_disconnect_req() - Send disconnect request
344 * @dev: ISHTP device instance
345 * @cl: ISHTP client instance
346 *
347 * Send disconnect message to fw
348 *
349 * Return: 0 if success else error code
350 */
351int ishtp_hbm_cl_disconnect_req(struct ishtp_device *dev, struct ishtp_cl *cl)
352{
353 struct ishtp_msg_hdr hdr;
354 unsigned char data[128];
355 struct ishtp_msg_hdr *ishtp_hdr = &hdr;
356 const size_t len = sizeof(struct hbm_client_connect_request);
357
358 ishtp_hbm_hdr(ishtp_hdr, len);
359 ishtp_hbm_cl_hdr(cl, CLIENT_DISCONNECT_REQ_CMD, data, len);
360
361 return ishtp_write_message(dev, ishtp_hdr, data);
362}
363
364/**
365 * ishtp_hbm_cl_disconnect_res() - Get disconnect response
366 * @dev: ISHTP device instance
367 * @rs: Response message
368 *
369 * Received disconnect response from fw
370 */
371static void ishtp_hbm_cl_disconnect_res(struct ishtp_device *dev,
372 struct hbm_client_connect_response *rs)
373{
374 struct ishtp_cl *cl = NULL;
375 unsigned long flags;
376
377 spin_lock_irqsave(&dev->cl_list_lock, flags);
378 list_for_each_entry(cl, &dev->cl_list, link) {
379 if (!rs->status && ishtp_hbm_cl_addr_equal(cl, rs)) {
380 cl->state = ISHTP_CL_DISCONNECTED;
381 break;
382 }
383 }
384 if (cl)
385 wake_up_interruptible(&cl->wait_ctrl_res);
386 spin_unlock_irqrestore(&dev->cl_list_lock, flags);
387}
388
389/**
390 * ishtp_hbm_cl_connect_req() - Send connect request
391 * @dev: ISHTP device instance
392 * @cl: client device instance
393 *
394 * Send connection request to specific fw client
395 *
396 * Return: 0 if success else error code
397 */
398int ishtp_hbm_cl_connect_req(struct ishtp_device *dev, struct ishtp_cl *cl)
399{
400 struct ishtp_msg_hdr hdr;
401 unsigned char data[128];
402 struct ishtp_msg_hdr *ishtp_hdr = &hdr;
403 const size_t len = sizeof(struct hbm_client_connect_request);
404
405 ishtp_hbm_hdr(ishtp_hdr, len);
406 ishtp_hbm_cl_hdr(cl, CLIENT_CONNECT_REQ_CMD, data, len);
407
408 return ishtp_write_message(dev, ishtp_hdr, data);
409}
410
411/**
412 * ishtp_hbm_cl_connect_res() - Get connect response
413 * @dev: ISHTP device instance
414 * @rs: Response message
415 *
416 * Received connect response from fw
417 */
418static void ishtp_hbm_cl_connect_res(struct ishtp_device *dev,
419 struct hbm_client_connect_response *rs)
420{
421 struct ishtp_cl *cl = NULL;
422 unsigned long flags;
423
424 spin_lock_irqsave(&dev->cl_list_lock, flags);
425 list_for_each_entry(cl, &dev->cl_list, link) {
426 if (ishtp_hbm_cl_addr_equal(cl, rs)) {
427 if (!rs->status) {
428 cl->state = ISHTP_CL_CONNECTED;
429 cl->status = 0;
430 } else {
431 cl->state = ISHTP_CL_DISCONNECTED;
432 cl->status = -ENODEV;
433 }
434 break;
435 }
436 }
437 if (cl)
438 wake_up_interruptible(&cl->wait_ctrl_res);
439 spin_unlock_irqrestore(&dev->cl_list_lock, flags);
440}
441
442/**
443 * ishtp_client_disconnect_request() - Receive disconnect request
444 * @dev: ISHTP device instance
445 * @disconnect_req: disconnect request structure
446 *
447 * Disconnect request bus message from the fw. Send diconnect response.
448 */
449static void ishtp_hbm_fw_disconnect_req(struct ishtp_device *dev,
450 struct hbm_client_connect_request *disconnect_req)
451{
452 struct ishtp_cl *cl;
453 const size_t len = sizeof(struct hbm_client_connect_response);
454 unsigned long flags;
455 struct ishtp_msg_hdr hdr;
456 unsigned char data[4]; /* All HBM messages are 4 bytes */
457
458 spin_lock_irqsave(&dev->cl_list_lock, flags);
459 list_for_each_entry(cl, &dev->cl_list, link) {
460 if (ishtp_hbm_cl_addr_equal(cl, disconnect_req)) {
461 cl->state = ISHTP_CL_DISCONNECTED;
462
463 /* send disconnect response */
464 ishtp_hbm_hdr(&hdr, len);
465 ishtp_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, data,
466 len);
467 ishtp_write_message(dev, &hdr, data);
468 break;
469 }
470 }
471 spin_unlock_irqrestore(&dev->cl_list_lock, flags);
472}
473
474/**
475 * ishtp_hbm_dma_xfer_ack(() - Receive transfer ACK
476 * @dev: ISHTP device instance
477 * @dma_xfer: HBM transfer message
478 *
479 * Receive ack for ISHTP-over-DMA client message
480 */
481static void ishtp_hbm_dma_xfer_ack(struct ishtp_device *dev,
482 struct dma_xfer_hbm *dma_xfer)
483{
484 void *msg;
485 uint64_t offs;
486 struct ishtp_msg_hdr *ishtp_hdr =
487 (struct ishtp_msg_hdr *)&dev->ishtp_msg_hdr;
488 unsigned int msg_offs;
489 struct ishtp_cl *cl;
490
491 for (msg_offs = 0; msg_offs < ishtp_hdr->length;
492 msg_offs += sizeof(struct dma_xfer_hbm)) {
493 offs = dma_xfer->msg_addr - dev->ishtp_host_dma_tx_buf_phys;
494 if (offs > dev->ishtp_host_dma_tx_buf_size) {
495 dev_err(dev->devc, "Bad DMA Tx ack message address\n");
496 return;
497 }
498 if (dma_xfer->msg_length >
499 dev->ishtp_host_dma_tx_buf_size - offs) {
500 dev_err(dev->devc, "Bad DMA Tx ack message size\n");
501 return;
502 }
503
504 /* logical address of the acked mem */
505 msg = (unsigned char *)dev->ishtp_host_dma_tx_buf + offs;
506 ishtp_cl_release_dma_acked_mem(dev, msg, dma_xfer->msg_length);
507
508 list_for_each_entry(cl, &dev->cl_list, link) {
509 if (cl->fw_client_id == dma_xfer->fw_client_id &&
510 cl->host_client_id == dma_xfer->host_client_id)
511 /*
512 * in case that a single ack may be sent
513 * over several dma transfers, and the last msg
514 * addr was inside the acked memory, but not in
515 * its start
516 */
517 if (cl->last_dma_addr >=
518 (unsigned char *)msg &&
519 cl->last_dma_addr <
520 (unsigned char *)msg +
521 dma_xfer->msg_length) {
522 cl->last_dma_acked = 1;
523
524 if (!list_empty(&cl->tx_list.list) &&
525 cl->ishtp_flow_ctrl_creds) {
526 /*
527 * start sending the first msg
528 */
529 ishtp_cl_send_msg(dev, cl);
530 }
531 }
532 }
533 ++dma_xfer;
534 }
535}
536
537/**
538 * ishtp_hbm_dma_xfer() - Receive DMA transfer message
539 * @dev: ISHTP device instance
540 * @dma_xfer: HBM transfer message
541 *
542 * Receive ISHTP-over-DMA client message
543 */
544static void ishtp_hbm_dma_xfer(struct ishtp_device *dev,
545 struct dma_xfer_hbm *dma_xfer)
546{
547 void *msg;
548 uint64_t offs;
549 struct ishtp_msg_hdr hdr;
550 struct ishtp_msg_hdr *ishtp_hdr =
551 (struct ishtp_msg_hdr *) &dev->ishtp_msg_hdr;
552 struct dma_xfer_hbm *prm = dma_xfer;
553 unsigned int msg_offs;
554
555 for (msg_offs = 0; msg_offs < ishtp_hdr->length;
556 msg_offs += sizeof(struct dma_xfer_hbm)) {
557
558 offs = dma_xfer->msg_addr - dev->ishtp_host_dma_rx_buf_phys;
559 if (offs > dev->ishtp_host_dma_rx_buf_size) {
560 dev_err(dev->devc, "Bad DMA Rx message address\n");
561 return;
562 }
563 if (dma_xfer->msg_length >
564 dev->ishtp_host_dma_rx_buf_size - offs) {
565 dev_err(dev->devc, "Bad DMA Rx message size\n");
566 return;
567 }
568 msg = dev->ishtp_host_dma_rx_buf + offs;
569 recv_ishtp_cl_msg_dma(dev, msg, dma_xfer);
570 dma_xfer->hbm = DMA_XFER_ACK; /* Prepare for response */
571 ++dma_xfer;
572 }
573
574 /* Send DMA_XFER_ACK [...] */
575 ishtp_hbm_hdr(&hdr, ishtp_hdr->length);
576 ishtp_write_message(dev, &hdr, (unsigned char *)prm);
577}
578
579/**
580 * ishtp_hbm_dispatch() - HBM dispatch function
581 * @dev: ISHTP device instance
582 * @hdr: bus message
583 *
584 * Bottom half read routine after ISR to handle the read bus message cmd
585 * processing
586 */
587void ishtp_hbm_dispatch(struct ishtp_device *dev,
588 struct ishtp_bus_message *hdr)
589{
590 struct ishtp_bus_message *ishtp_msg;
591 struct ishtp_fw_client *fw_client;
592 struct hbm_host_version_response *version_res;
593 struct hbm_client_connect_response *connect_res;
594 struct hbm_client_connect_response *disconnect_res;
595 struct hbm_client_connect_request *disconnect_req;
596 struct hbm_props_response *props_res;
597 struct hbm_host_enum_response *enum_res;
598 struct ishtp_msg_hdr ishtp_hdr;
599 struct dma_alloc_notify dma_alloc_notify;
600 struct dma_xfer_hbm *dma_xfer;
601
602 ishtp_msg = hdr;
603
604 switch (ishtp_msg->hbm_cmd) {
605 case HOST_START_RES_CMD:
606 version_res = (struct hbm_host_version_response *)ishtp_msg;
607 if (!version_res->host_version_supported) {
608 dev->version = version_res->fw_max_version;
609
610 dev->hbm_state = ISHTP_HBM_STOPPED;
611 ishtp_hbm_stop_req(dev);
612 return;
613 }
614
615 dev->version.major_version = HBM_MAJOR_VERSION;
616 dev->version.minor_version = HBM_MINOR_VERSION;
617 if (dev->dev_state == ISHTP_DEV_INIT_CLIENTS &&
618 dev->hbm_state == ISHTP_HBM_START) {
619 dev->hbm_state = ISHTP_HBM_STARTED;
620 ishtp_hbm_enum_clients_req(dev);
621 } else {
622 dev_err(dev->devc,
623 "reset: wrong host start response\n");
624 /* BUG: why do we arrive here? */
625 ish_hw_reset(dev);
626 return;
627 }
628
629 wake_up_interruptible(&dev->wait_hbm_recvd_msg);
630 break;
631
632 case CLIENT_CONNECT_RES_CMD:
633 connect_res = (struct hbm_client_connect_response *)ishtp_msg;
634 ishtp_hbm_cl_connect_res(dev, connect_res);
635 break;
636
637 case CLIENT_DISCONNECT_RES_CMD:
638 disconnect_res =
639 (struct hbm_client_connect_response *)ishtp_msg;
640 ishtp_hbm_cl_disconnect_res(dev, disconnect_res);
641 break;
642
643 case HOST_CLIENT_PROPERTIES_RES_CMD:
644 props_res = (struct hbm_props_response *)ishtp_msg;
645 fw_client = &dev->fw_clients[dev->fw_client_presentation_num];
646
647 if (props_res->status || !dev->fw_clients) {
648 dev_err(dev->devc,
649 "reset: properties response hbm wrong status\n");
650 ish_hw_reset(dev);
651 return;
652 }
653
654 if (fw_client->client_id != props_res->address) {
655 dev_err(dev->devc,
656 "reset: host properties response address mismatch [%02X %02X]\n",
657 fw_client->client_id, props_res->address);
658 ish_hw_reset(dev);
659 return;
660 }
661
662 if (dev->dev_state != ISHTP_DEV_INIT_CLIENTS ||
663 dev->hbm_state != ISHTP_HBM_CLIENT_PROPERTIES) {
664 dev_err(dev->devc,
665 "reset: unexpected properties response\n");
666 ish_hw_reset(dev);
667 return;
668 }
669
670 fw_client->props = props_res->client_properties;
671 dev->fw_client_index++;
672 dev->fw_client_presentation_num++;
673
674 /* request property for the next client */
675 ishtp_hbm_prop_req(dev);
676
677 if (dev->dev_state != ISHTP_DEV_ENABLED)
678 break;
679
680 if (!ishtp_use_dma_transfer())
681 break;
682
683 dev_dbg(dev->devc, "Requesting to use DMA\n");
684 ishtp_cl_alloc_dma_buf(dev);
685 if (dev->ishtp_host_dma_rx_buf) {
686 const size_t len = sizeof(dma_alloc_notify);
687
688 memset(&dma_alloc_notify, 0, sizeof(dma_alloc_notify));
689 dma_alloc_notify.hbm = DMA_BUFFER_ALLOC_NOTIFY;
690 dma_alloc_notify.buf_size =
691 dev->ishtp_host_dma_rx_buf_size;
692 dma_alloc_notify.buf_address =
693 dev->ishtp_host_dma_rx_buf_phys;
694 ishtp_hbm_hdr(&ishtp_hdr, len);
695 ishtp_write_message(dev, &ishtp_hdr,
696 (unsigned char *)&dma_alloc_notify);
697 }
698
699 break;
700
701 case HOST_ENUM_RES_CMD:
702 enum_res = (struct hbm_host_enum_response *) ishtp_msg;
703 memcpy(dev->fw_clients_map, enum_res->valid_addresses, 32);
704 if (dev->dev_state == ISHTP_DEV_INIT_CLIENTS &&
705 dev->hbm_state == ISHTP_HBM_ENUM_CLIENTS) {
706 dev->fw_client_presentation_num = 0;
707 dev->fw_client_index = 0;
708
709 ishtp_hbm_fw_cl_allocate(dev);
710 dev->hbm_state = ISHTP_HBM_CLIENT_PROPERTIES;
711
712 /* first property request */
713 ishtp_hbm_prop_req(dev);
714 } else {
715 dev_err(dev->devc,
716 "reset: unexpected enumeration response hbm\n");
717 ish_hw_reset(dev);
718 return;
719 }
720 break;
721
722 case HOST_STOP_RES_CMD:
723 if (dev->hbm_state != ISHTP_HBM_STOPPED)
724 dev_err(dev->devc, "unexpected stop response\n");
725
726 dev->dev_state = ISHTP_DEV_DISABLED;
727 dev_info(dev->devc, "reset: FW stop response\n");
728 ish_hw_reset(dev);
729 break;
730
731 case CLIENT_DISCONNECT_REQ_CMD:
732 /* search for client */
733 disconnect_req =
734 (struct hbm_client_connect_request *)ishtp_msg;
735 ishtp_hbm_fw_disconnect_req(dev, disconnect_req);
736 break;
737
738 case FW_STOP_REQ_CMD:
739 dev->hbm_state = ISHTP_HBM_STOPPED;
740 break;
741
742 case DMA_BUFFER_ALLOC_RESPONSE:
743 dev->ishtp_host_dma_enabled = 1;
744 break;
745
746 case DMA_XFER:
747 dma_xfer = (struct dma_xfer_hbm *)ishtp_msg;
748 if (!dev->ishtp_host_dma_enabled) {
749 dev_err(dev->devc,
750 "DMA XFER requested but DMA is not enabled\n");
751 break;
752 }
753 ishtp_hbm_dma_xfer(dev, dma_xfer);
754 break;
755
756 case DMA_XFER_ACK:
757 dma_xfer = (struct dma_xfer_hbm *)ishtp_msg;
758 if (!dev->ishtp_host_dma_enabled ||
759 !dev->ishtp_host_dma_tx_buf) {
760 dev_err(dev->devc,
761 "DMA XFER acked but DMA Tx is not enabled\n");
762 break;
763 }
764 ishtp_hbm_dma_xfer_ack(dev, dma_xfer);
765 break;
766
767 default:
768 dev_err(dev->devc, "unknown HBM: %u\n",
769 (unsigned int)ishtp_msg->hbm_cmd);
770
771 break;
772 }
773}
774
775/**
776 * bh_hbm_work_fn() - HBM work function
777 * @work: work struct
778 *
779 * Bottom half processing work function (instead of thread handler)
780 * for processing hbm messages
781 */
782void bh_hbm_work_fn(struct work_struct *work)
783{
784 unsigned long flags;
785 struct ishtp_device *dev;
786 unsigned char hbm[IPC_PAYLOAD_SIZE];
787
788 dev = container_of(work, struct ishtp_device, bh_hbm_work);
789 spin_lock_irqsave(&dev->rd_msg_spinlock, flags);
790 if (dev->rd_msg_fifo_head != dev->rd_msg_fifo_tail) {
791 memcpy(hbm, dev->rd_msg_fifo + dev->rd_msg_fifo_head,
792 IPC_PAYLOAD_SIZE);
793 dev->rd_msg_fifo_head =
794 (dev->rd_msg_fifo_head + IPC_PAYLOAD_SIZE) %
795 (RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE);
796 spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
797 ishtp_hbm_dispatch(dev, (struct ishtp_bus_message *)hbm);
798 } else {
799 spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
800 }
801}
802
803/**
804 * recv_hbm() - Receive HBM message
805 * @dev: ISHTP device instance
806 * @ishtp_hdr: received bus message
807 *
808 * Receive and process ISHTP bus messages in ISR context. This will schedule
809 * work function to process message
810 */
811void recv_hbm(struct ishtp_device *dev, struct ishtp_msg_hdr *ishtp_hdr)
812{
813 uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
814 struct ishtp_bus_message *ishtp_msg =
815 (struct ishtp_bus_message *)rd_msg_buf;
816 unsigned long flags;
817
818 dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length);
819
820 /* Flow control - handle in place */
821 if (ishtp_msg->hbm_cmd == ISHTP_FLOW_CONTROL_CMD) {
822 struct hbm_flow_control *flow_control =
823 (struct hbm_flow_control *)ishtp_msg;
824 struct ishtp_cl *cl = NULL;
825 unsigned long flags, tx_flags;
826
827 spin_lock_irqsave(&dev->cl_list_lock, flags);
828 list_for_each_entry(cl, &dev->cl_list, link) {
829 if (cl->host_client_id == flow_control->host_addr &&
830 cl->fw_client_id ==
831 flow_control->fw_addr) {
832 /*
833 * NOTE: It's valid only for counting
834 * flow-control implementation to receive a
835 * FC in the middle of sending. Meanwhile not
836 * supported
837 */
838 if (cl->ishtp_flow_ctrl_creds)
839 dev_err(dev->devc,
840 "recv extra FC from FW client %u (host client %u) (FC count was %d)\n",
841 (unsigned int)cl->fw_client_id,
842 (unsigned int)cl->host_client_id,
843 cl->ishtp_flow_ctrl_creds);
844 else {
845 ++cl->ishtp_flow_ctrl_creds;
846 ++cl->ishtp_flow_ctrl_cnt;
847 cl->last_ipc_acked = 1;
848 spin_lock_irqsave(
849 &cl->tx_list_spinlock,
850 tx_flags);
851 if (!list_empty(&cl->tx_list.list)) {
852 /*
853 * start sending the first msg
854 * = the callback function
855 */
856 spin_unlock_irqrestore(
857 &cl->tx_list_spinlock,
858 tx_flags);
859 ishtp_cl_send_msg(dev, cl);
860 } else {
861 spin_unlock_irqrestore(
862 &cl->tx_list_spinlock,
863 tx_flags);
864 }
865 }
866 break;
867 }
868 }
869 spin_unlock_irqrestore(&dev->cl_list_lock, flags);
870 goto eoi;
871 }
872
873 /*
874 * Some messages that are safe for ISR processing and important
875 * to be done "quickly" and in-order, go here
876 */
877 if (ishtp_msg->hbm_cmd == CLIENT_CONNECT_RES_CMD ||
878 ishtp_msg->hbm_cmd == CLIENT_DISCONNECT_RES_CMD ||
879 ishtp_msg->hbm_cmd == CLIENT_DISCONNECT_REQ_CMD ||
880 ishtp_msg->hbm_cmd == DMA_XFER) {
881 ishtp_hbm_dispatch(dev, ishtp_msg);
882 goto eoi;
883 }
884
885 /*
886 * All other HBMs go here.
887 * We schedule HBMs for processing serially by using system wq,
888 * possibly there will be multiple HBMs scheduled at the same time.
889 */
890 spin_lock_irqsave(&dev->rd_msg_spinlock, flags);
891 if ((dev->rd_msg_fifo_tail + IPC_PAYLOAD_SIZE) %
892 (RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE) ==
893 dev->rd_msg_fifo_head) {
894 spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
895 dev_err(dev->devc, "BH buffer overflow, dropping HBM %u\n",
896 (unsigned int)ishtp_msg->hbm_cmd);
897 goto eoi;
898 }
899 memcpy(dev->rd_msg_fifo + dev->rd_msg_fifo_tail, ishtp_msg,
900 ishtp_hdr->length);
901 dev->rd_msg_fifo_tail = (dev->rd_msg_fifo_tail + IPC_PAYLOAD_SIZE) %
902 (RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE);
903 spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
904 schedule_work(&dev->bh_hbm_work);
905eoi:
906 return;
907}
908
909/**
910 * recv_fixed_cl_msg() - Receive fixed client message
911 * @dev: ISHTP device instance
912 * @ishtp_hdr: received bus message
913 *
914 * Receive and process ISHTP fixed client messages (address == 0)
915 * in ISR context
916 */
917void recv_fixed_cl_msg(struct ishtp_device *dev,
918 struct ishtp_msg_hdr *ishtp_hdr)
919{
920 uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
921
922 dev->print_log(dev,
923 "%s() got fixed client msg from client #%d\n",
924 __func__, ishtp_hdr->fw_addr);
925 dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length);
926 if (ishtp_hdr->fw_addr == ISHTP_SYSTEM_STATE_CLIENT_ADDR) {
927 struct ish_system_states_header *msg_hdr =
928 (struct ish_system_states_header *)rd_msg_buf;
929 if (msg_hdr->cmd == SYSTEM_STATE_SUBSCRIBE)
930 ishtp_send_resume(dev);
931 /* if FW request arrived here, the system is not suspended */
932 else
933 dev_err(dev->devc, "unknown fixed client msg [%02X]\n",
934 msg_hdr->cmd);
935 }
936}
937
938/**
939 * fix_cl_hdr() - Initialize fixed client header
940 * @hdr: message header
941 * @length: length of message
942 * @cl_addr: Client address
943 *
944 * Initialize message header for fixed client
945 */
946static inline void fix_cl_hdr(struct ishtp_msg_hdr *hdr, size_t length,
947 uint8_t cl_addr)
948{
949 hdr->host_addr = 0;
950 hdr->fw_addr = cl_addr;
951 hdr->length = length;
952 hdr->msg_complete = 1;
953 hdr->reserved = 0;
954}
955
956/*** Suspend and resume notification ***/
957
958static uint32_t current_state;
959static uint32_t supported_states = 0 | SUSPEND_STATE_BIT;
960
961/**
962 * ishtp_send_suspend() - Send suspend message to FW
963 * @dev: ISHTP device instance
964 *
965 * Send suspend message to FW. This is useful for system freeze (non S3) case
966 */
967void ishtp_send_suspend(struct ishtp_device *dev)
968{
969 struct ishtp_msg_hdr ishtp_hdr;
970 struct ish_system_states_status state_status_msg;
971 const size_t len = sizeof(struct ish_system_states_status);
972
973 fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR);
974
975 memset(&state_status_msg, 0, len);
976 state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS;
977 state_status_msg.supported_states = supported_states;
978 current_state |= SUSPEND_STATE_BIT;
979 dev->print_log(dev, "%s() sends SUSPEND notification\n", __func__);
980 state_status_msg.states_status = current_state;
981
982 ishtp_write_message(dev, &ishtp_hdr,
983 (unsigned char *)&state_status_msg);
984}
985EXPORT_SYMBOL(ishtp_send_suspend);
986
987/**
988 * ishtp_send_resume() - Send resume message to FW
989 * @dev: ISHTP device instance
990 *
991 * Send resume message to FW. This is useful for system freeze (non S3) case
992 */
993void ishtp_send_resume(struct ishtp_device *dev)
994{
995 struct ishtp_msg_hdr ishtp_hdr;
996 struct ish_system_states_status state_status_msg;
997 const size_t len = sizeof(struct ish_system_states_status);
998
999 fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR);
1000
1001 memset(&state_status_msg, 0, len);
1002 state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS;
1003 state_status_msg.supported_states = supported_states;
1004 current_state &= ~SUSPEND_STATE_BIT;
1005 dev->print_log(dev, "%s() sends RESUME notification\n", __func__);
1006 state_status_msg.states_status = current_state;
1007
1008 ishtp_write_message(dev, &ishtp_hdr,
1009 (unsigned char *)&state_status_msg);
1010}
1011EXPORT_SYMBOL(ishtp_send_resume);
1012
1013/**
1014 * ishtp_query_subscribers() - Send query subscribers message
1015 * @dev: ISHTP device instance
1016 *
1017 * Send message to query subscribers
1018 */
1019void ishtp_query_subscribers(struct ishtp_device *dev)
1020{
1021 struct ishtp_msg_hdr ishtp_hdr;
1022 struct ish_system_states_query_subscribers query_subscribers_msg;
1023 const size_t len = sizeof(struct ish_system_states_query_subscribers);
1024
1025 fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR);
1026
1027 memset(&query_subscribers_msg, 0, len);
1028 query_subscribers_msg.hdr.cmd = SYSTEM_STATE_QUERY_SUBSCRIBERS;
1029
1030 ishtp_write_message(dev, &ishtp_hdr,
1031 (unsigned char *)&query_subscribers_msg);
1032}
diff --git a/drivers/hid/intel-ish-hid/ishtp/hbm.h b/drivers/hid/intel-ish-hid/ishtp/hbm.h
new file mode 100644
index 000000000000..d96111cef7f8
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/hbm.h
@@ -0,0 +1,321 @@
1/*
2 * ISHTP bus layer messages handling
3 *
4 * 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 */
15
16#ifndef _ISHTP_HBM_H_
17#define _ISHTP_HBM_H_
18
19#include <linux/uuid.h>
20
21struct ishtp_device;
22struct ishtp_msg_hdr;
23struct ishtp_cl;
24
25/*
26 * Timeouts in Seconds
27 */
28#define ISHTP_INTEROP_TIMEOUT 7 /* Timeout on ready message */
29
30#define ISHTP_CL_CONNECT_TIMEOUT 15 /* HPS: Client Connect Timeout */
31
32/*
33 * ISHTP Version
34 */
35#define HBM_MINOR_VERSION 0
36#define HBM_MAJOR_VERSION 1
37
38/* Host bus message command opcode */
39#define ISHTP_HBM_CMD_OP_MSK 0x7f
40/* Host bus message command RESPONSE */
41#define ISHTP_HBM_CMD_RES_MSK 0x80
42
43/*
44 * ISHTP Bus Message Command IDs
45 */
46#define HOST_START_REQ_CMD 0x01
47#define HOST_START_RES_CMD 0x81
48
49#define HOST_STOP_REQ_CMD 0x02
50#define HOST_STOP_RES_CMD 0x82
51
52#define FW_STOP_REQ_CMD 0x03
53
54#define HOST_ENUM_REQ_CMD 0x04
55#define HOST_ENUM_RES_CMD 0x84
56
57#define HOST_CLIENT_PROPERTIES_REQ_CMD 0x05
58#define HOST_CLIENT_PROPERTIES_RES_CMD 0x85
59
60#define CLIENT_CONNECT_REQ_CMD 0x06
61#define CLIENT_CONNECT_RES_CMD 0x86
62
63#define CLIENT_DISCONNECT_REQ_CMD 0x07
64#define CLIENT_DISCONNECT_RES_CMD 0x87
65
66#define ISHTP_FLOW_CONTROL_CMD 0x08
67
68#define DMA_BUFFER_ALLOC_NOTIFY 0x11
69#define DMA_BUFFER_ALLOC_RESPONSE 0x91
70
71#define DMA_XFER 0x12
72#define DMA_XFER_ACK 0x92
73
74/*
75 * ISHTP Stop Reason
76 * used by hbm_host_stop_request.reason
77 */
78#define DRIVER_STOP_REQUEST 0x00
79
80/*
81 * ISHTP BUS Interface Section
82 */
83struct ishtp_msg_hdr {
84 uint32_t fw_addr:8;
85 uint32_t host_addr:8;
86 uint32_t length:9;
87 uint32_t reserved:6;
88 uint32_t msg_complete:1;
89} __packed;
90
91struct ishtp_bus_message {
92 uint8_t hbm_cmd;
93 uint8_t data[0];
94} __packed;
95
96/**
97 * struct hbm_cl_cmd - client specific host bus command
98 * CONNECT, DISCONNECT, and FlOW CONTROL
99 *
100 * @hbm_cmd - bus message command header
101 * @fw_addr - address of the fw client
102 * @host_addr - address of the client in the driver
103 * @data
104 */
105struct ishtp_hbm_cl_cmd {
106 uint8_t hbm_cmd;
107 uint8_t fw_addr;
108 uint8_t host_addr;
109 uint8_t data;
110};
111
112struct hbm_version {
113 uint8_t minor_version;
114 uint8_t major_version;
115} __packed;
116
117struct hbm_host_version_request {
118 uint8_t hbm_cmd;
119 uint8_t reserved;
120 struct hbm_version host_version;
121} __packed;
122
123struct hbm_host_version_response {
124 uint8_t hbm_cmd;
125 uint8_t host_version_supported;
126 struct hbm_version fw_max_version;
127} __packed;
128
129struct hbm_host_stop_request {
130 uint8_t hbm_cmd;
131 uint8_t reason;
132 uint8_t reserved[2];
133} __packed;
134
135struct hbm_host_stop_response {
136 uint8_t hbm_cmd;
137 uint8_t reserved[3];
138} __packed;
139
140struct hbm_host_enum_request {
141 uint8_t hbm_cmd;
142 uint8_t reserved[3];
143} __packed;
144
145struct hbm_host_enum_response {
146 uint8_t hbm_cmd;
147 uint8_t reserved[3];
148 uint8_t valid_addresses[32];
149} __packed;
150
151struct ishtp_client_properties {
152 uuid_le protocol_name;
153 uint8_t protocol_version;
154 uint8_t max_number_of_connections;
155 uint8_t fixed_address;
156 uint8_t single_recv_buf;
157 uint32_t max_msg_length;
158 uint8_t dma_hdr_len;
159#define ISHTP_CLIENT_DMA_ENABLED 0x80
160 uint8_t reserved4;
161 uint8_t reserved5;
162 uint8_t reserved6;
163} __packed;
164
165struct hbm_props_request {
166 uint8_t hbm_cmd;
167 uint8_t address;
168 uint8_t reserved[2];
169} __packed;
170
171struct hbm_props_response {
172 uint8_t hbm_cmd;
173 uint8_t address;
174 uint8_t status;
175 uint8_t reserved[1];
176 struct ishtp_client_properties client_properties;
177} __packed;
178
179/**
180 * struct hbm_client_connect_request - connect/disconnect request
181 *
182 * @hbm_cmd - bus message command header
183 * @fw_addr - address of the fw client
184 * @host_addr - address of the client in the driver
185 * @reserved
186 */
187struct hbm_client_connect_request {
188 uint8_t hbm_cmd;
189 uint8_t fw_addr;
190 uint8_t host_addr;
191 uint8_t reserved;
192} __packed;
193
194/**
195 * struct hbm_client_connect_response - connect/disconnect response
196 *
197 * @hbm_cmd - bus message command header
198 * @fw_addr - address of the fw client
199 * @host_addr - address of the client in the driver
200 * @status - status of the request
201 */
202struct hbm_client_connect_response {
203 uint8_t hbm_cmd;
204 uint8_t fw_addr;
205 uint8_t host_addr;
206 uint8_t status;
207} __packed;
208
209
210#define ISHTP_FC_MESSAGE_RESERVED_LENGTH 5
211
212struct hbm_flow_control {
213 uint8_t hbm_cmd;
214 uint8_t fw_addr;
215 uint8_t host_addr;
216 uint8_t reserved[ISHTP_FC_MESSAGE_RESERVED_LENGTH];
217} __packed;
218
219struct dma_alloc_notify {
220 uint8_t hbm;
221 uint8_t status;
222 uint8_t reserved[2];
223 uint32_t buf_size;
224 uint64_t buf_address;
225 /* [...] May come more size/address pairs */
226} __packed;
227
228struct dma_xfer_hbm {
229 uint8_t hbm;
230 uint8_t fw_client_id;
231 uint8_t host_client_id;
232 uint8_t reserved;
233 uint64_t msg_addr;
234 uint32_t msg_length;
235 uint32_t reserved2;
236} __packed;
237
238/* System state */
239#define ISHTP_SYSTEM_STATE_CLIENT_ADDR 13
240
241#define SYSTEM_STATE_SUBSCRIBE 0x1
242#define SYSTEM_STATE_STATUS 0x2
243#define SYSTEM_STATE_QUERY_SUBSCRIBERS 0x3
244#define SYSTEM_STATE_STATE_CHANGE_REQ 0x4
245/*indicates suspend and resume states*/
246#define SUSPEND_STATE_BIT (1<<1)
247
248struct ish_system_states_header {
249 uint32_t cmd;
250 uint32_t cmd_status; /*responses will have this set*/
251} __packed;
252
253struct ish_system_states_subscribe {
254 struct ish_system_states_header hdr;
255 uint32_t states;
256} __packed;
257
258struct ish_system_states_status {
259 struct ish_system_states_header hdr;
260 uint32_t supported_states;
261 uint32_t states_status;
262} __packed;
263
264struct ish_system_states_query_subscribers {
265 struct ish_system_states_header hdr;
266} __packed;
267
268struct ish_system_states_state_change_req {
269 struct ish_system_states_header hdr;
270 uint32_t requested_states;
271 uint32_t states_status;
272} __packed;
273
274/**
275 * enum ishtp_hbm_state - host bus message protocol state
276 *
277 * @ISHTP_HBM_IDLE : protocol not started
278 * @ISHTP_HBM_START : start request message was sent
279 * @ISHTP_HBM_ENUM_CLIENTS : enumeration request was sent
280 * @ISHTP_HBM_CLIENT_PROPERTIES : acquiring clients properties
281 */
282enum ishtp_hbm_state {
283 ISHTP_HBM_IDLE = 0,
284 ISHTP_HBM_START,
285 ISHTP_HBM_STARTED,
286 ISHTP_HBM_ENUM_CLIENTS,
287 ISHTP_HBM_CLIENT_PROPERTIES,
288 ISHTP_HBM_WORKING,
289 ISHTP_HBM_STOPPED,
290};
291
292static inline void ishtp_hbm_hdr(struct ishtp_msg_hdr *hdr, size_t length)
293{
294 hdr->host_addr = 0;
295 hdr->fw_addr = 0;
296 hdr->length = length;
297 hdr->msg_complete = 1;
298 hdr->reserved = 0;
299}
300
301int ishtp_hbm_start_req(struct ishtp_device *dev);
302int ishtp_hbm_start_wait(struct ishtp_device *dev);
303int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
304 struct ishtp_cl *cl);
305int ishtp_hbm_cl_disconnect_req(struct ishtp_device *dev, struct ishtp_cl *cl);
306int ishtp_hbm_cl_connect_req(struct ishtp_device *dev, struct ishtp_cl *cl);
307void ishtp_hbm_enum_clients_req(struct ishtp_device *dev);
308void bh_hbm_work_fn(struct work_struct *work);
309void recv_hbm(struct ishtp_device *dev, struct ishtp_msg_hdr *ishtp_hdr);
310void recv_fixed_cl_msg(struct ishtp_device *dev,
311 struct ishtp_msg_hdr *ishtp_hdr);
312void ishtp_hbm_dispatch(struct ishtp_device *dev,
313 struct ishtp_bus_message *hdr);
314
315void ishtp_query_subscribers(struct ishtp_device *dev);
316
317/* Exported I/F */
318void ishtp_send_suspend(struct ishtp_device *dev);
319void ishtp_send_resume(struct ishtp_device *dev);
320
321#endif /* _ISHTP_HBM_H_ */
diff --git a/drivers/hid/intel-ish-hid/ishtp/init.c b/drivers/hid/intel-ish-hid/ishtp/init.c
new file mode 100644
index 000000000000..ac364418e17c
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/init.c
@@ -0,0 +1,115 @@
1/*
2 * Initialization protocol for ISHTP driver
3 *
4 * 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 */
15
16#include <linux/export.h>
17#include <linux/slab.h>
18#include <linux/sched.h>
19#include <linux/miscdevice.h>
20#include "ishtp-dev.h"
21#include "hbm.h"
22#include "client.h"
23
24/**
25 * ishtp_dev_state_str() -Convert to string format
26 * @state: state to convert
27 *
28 * Convert state to string for prints
29 *
30 * Return: character pointer to converted string
31 */
32const char *ishtp_dev_state_str(int state)
33{
34 switch (state) {
35 case ISHTP_DEV_INITIALIZING:
36 return "INITIALIZING";
37 case ISHTP_DEV_INIT_CLIENTS:
38 return "INIT_CLIENTS";
39 case ISHTP_DEV_ENABLED:
40 return "ENABLED";
41 case ISHTP_DEV_RESETTING:
42 return "RESETTING";
43 case ISHTP_DEV_DISABLED:
44 return "DISABLED";
45 case ISHTP_DEV_POWER_DOWN:
46 return "POWER_DOWN";
47 case ISHTP_DEV_POWER_UP:
48 return "POWER_UP";
49 default:
50 return "unknown";
51 }
52}
53
54/**
55 * ishtp_device_init() - ishtp device init
56 * @dev: ISHTP device instance
57 *
58 * After ISHTP device is alloacted, this function is used to initialize
59 * each field which includes spin lock, work struct and lists
60 */
61void ishtp_device_init(struct ishtp_device *dev)
62{
63 dev->dev_state = ISHTP_DEV_INITIALIZING;
64 INIT_LIST_HEAD(&dev->cl_list);
65 INIT_LIST_HEAD(&dev->device_list);
66 dev->rd_msg_fifo_head = 0;
67 dev->rd_msg_fifo_tail = 0;
68 spin_lock_init(&dev->rd_msg_spinlock);
69
70 init_waitqueue_head(&dev->wait_hbm_recvd_msg);
71 spin_lock_init(&dev->read_list_spinlock);
72 spin_lock_init(&dev->device_lock);
73 spin_lock_init(&dev->device_list_lock);
74 spin_lock_init(&dev->cl_list_lock);
75 spin_lock_init(&dev->fw_clients_lock);
76 INIT_WORK(&dev->bh_hbm_work, bh_hbm_work_fn);
77
78 bitmap_zero(dev->host_clients_map, ISHTP_CLIENTS_MAX);
79 dev->open_handle_count = 0;
80
81 /*
82 * Reserving client ID 0 for ISHTP Bus Message communications
83 */
84 bitmap_set(dev->host_clients_map, 0, 1);
85
86 INIT_LIST_HEAD(&dev->read_list.list);
87
88}
89EXPORT_SYMBOL(ishtp_device_init);
90
91/**
92 * ishtp_start() - Start ISH processing
93 * @dev: ISHTP device instance
94 *
95 * Start ISHTP processing by sending query subscriber message
96 *
97 * Return: 0 on success else -ENODEV
98 */
99int ishtp_start(struct ishtp_device *dev)
100{
101 if (ishtp_hbm_start_wait(dev)) {
102 dev_err(dev->devc, "HBM haven't started");
103 goto err;
104 }
105
106 /* suspend & resume notification - send QUERY_SUBSCRIBERS msg */
107 ishtp_query_subscribers(dev);
108
109 return 0;
110err:
111 dev_err(dev->devc, "link layer initialization failed.\n");
112 dev->dev_state = ISHTP_DEV_DISABLED;
113 return -ENODEV;
114}
115EXPORT_SYMBOL(ishtp_start);
diff --git a/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h b/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
new file mode 100644
index 000000000000..a94f9a8a96a0
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
@@ -0,0 +1,277 @@
1/*
2 * Most ISHTP provider device and ISHTP logic declarations
3 *
4 * 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 */
15
16#ifndef _ISHTP_DEV_H_
17#define _ISHTP_DEV_H_
18
19#include <linux/types.h>
20#include <linux/spinlock.h>
21#include "bus.h"
22#include "hbm.h"
23
24#define IPC_PAYLOAD_SIZE 128
25#define ISHTP_RD_MSG_BUF_SIZE IPC_PAYLOAD_SIZE
26#define IPC_FULL_MSG_SIZE 132
27
28/* Number of messages to be held in ISR->BH FIFO */
29#define RD_INT_FIFO_SIZE 64
30
31/*
32 * Number of IPC messages to be held in Tx FIFO, to be sent by ISR -
33 * Tx complete interrupt or RX_COMPLETE handler
34 */
35#define IPC_TX_FIFO_SIZE 512
36
37/*
38 * Number of Maximum ISHTP Clients
39 */
40#define ISHTP_CLIENTS_MAX 256
41
42/*
43 * Number of File descriptors/handles
44 * that can be opened to the driver.
45 *
46 * Limit to 255: 256 Total Clients
47 * minus internal client for ISHTP Bus Messages
48 */
49#define ISHTP_MAX_OPEN_HANDLE_COUNT (ISHTP_CLIENTS_MAX - 1)
50
51/* Internal Clients Number */
52#define ISHTP_HOST_CLIENT_ID_ANY (-1)
53#define ISHTP_HBM_HOST_CLIENT_ID 0
54
55#define MAX_DMA_DELAY 20
56
57/* ISHTP device states */
58enum ishtp_dev_state {
59 ISHTP_DEV_INITIALIZING = 0,
60 ISHTP_DEV_INIT_CLIENTS,
61 ISHTP_DEV_ENABLED,
62 ISHTP_DEV_RESETTING,
63 ISHTP_DEV_DISABLED,
64 ISHTP_DEV_POWER_DOWN,
65 ISHTP_DEV_POWER_UP
66};
67const char *ishtp_dev_state_str(int state);
68
69struct ishtp_cl;
70
71/**
72 * struct ishtp_fw_client - representation of fw client
73 *
74 * @props - client properties
75 * @client_id - fw client id
76 */
77struct ishtp_fw_client {
78 struct ishtp_client_properties props;
79 uint8_t client_id;
80};
81
82/**
83 * struct ishtp_msg_data - ISHTP message data struct
84 * @size: Size of data in the *data
85 * @data: Pointer to data
86 */
87struct ishtp_msg_data {
88 uint32_t size;
89 unsigned char *data;
90};
91
92/*
93 * struct ishtp_cl_rb - request block structure
94 * @list: Link to list members
95 * @cl: ISHTP client instance
96 * @buffer: message header
97 * @buf_idx: Index into buffer
98 * @read_time: unused at this time
99 */
100struct ishtp_cl_rb {
101 struct list_head list;
102 struct ishtp_cl *cl;
103 struct ishtp_msg_data buffer;
104 unsigned long buf_idx;
105 unsigned long read_time;
106};
107
108/*
109 * Control info for IPC messages ISHTP/IPC sending FIFO -
110 * list with inline data buffer
111 * This structure will be filled with parameters submitted
112 * by the caller glue layer
113 * 'buf' may be pointing to the external buffer or to 'inline_data'
114 * 'offset' will be initialized to 0 by submitting
115 *
116 * 'ipc_send_compl' is intended for use by clients that send fragmented
117 * messages. When a fragment is sent down to IPC msg regs,
118 * it will be called.
119 * If it has more fragments to send, it will do it. With last fragment
120 * it will send appropriate ISHTP "message-complete" flag.
121 * It will remove the outstanding message
122 * (mark outstanding buffer as available).
123 * If counting flow control is in work and there are more flow control
124 * credits, it can put the next client message queued in cl.
125 * structure for IPC processing.
126 *
127 */
128struct wr_msg_ctl_info {
129 /* Will be called with 'ipc_send_compl_prm' as parameter */
130 void (*ipc_send_compl)(void *);
131
132 void *ipc_send_compl_prm;
133 size_t length;
134 struct list_head link;
135 unsigned char inline_data[IPC_FULL_MSG_SIZE];
136};
137
138/*
139 * The ISHTP layer talks to hardware IPC message using the following
140 * callbacks
141 */
142struct ishtp_hw_ops {
143 int (*hw_reset)(struct ishtp_device *dev);
144 int (*ipc_reset)(struct ishtp_device *dev);
145 uint32_t (*ipc_get_header)(struct ishtp_device *dev, int length,
146 int busy);
147 int (*write)(struct ishtp_device *dev,
148 void (*ipc_send_compl)(void *), void *ipc_send_compl_prm,
149 unsigned char *msg, int length);
150 uint32_t (*ishtp_read_hdr)(const struct ishtp_device *dev);
151 int (*ishtp_read)(struct ishtp_device *dev, unsigned char *buffer,
152 unsigned long buffer_length);
153 uint32_t (*get_fw_status)(struct ishtp_device *dev);
154 void (*sync_fw_clock)(struct ishtp_device *dev);
155};
156
157/**
158 * struct ishtp_device - ISHTP private device struct
159 */
160struct ishtp_device {
161 struct device *devc; /* pointer to lowest device */
162 struct pci_dev *pdev; /* PCI device to get device ids */
163
164 /* waitq for waiting for suspend response */
165 wait_queue_head_t suspend_wait;
166 bool suspend_flag; /* Suspend is active */
167
168 /* waitq for waiting for resume response */
169 wait_queue_head_t resume_wait;
170 bool resume_flag; /*Resume is active */
171
172 /*
173 * lock for the device, for everything that doesn't have
174 * a dedicated spinlock
175 */
176 spinlock_t device_lock;
177
178 bool recvd_hw_ready;
179 struct hbm_version version;
180 int transfer_path; /* Choice of transfer path: IPC or DMA */
181
182 /* ishtp device states */
183 enum ishtp_dev_state dev_state;
184 enum ishtp_hbm_state hbm_state;
185
186 /* driver read queue */
187 struct ishtp_cl_rb read_list;
188 spinlock_t read_list_spinlock;
189
190 /* list of ishtp_cl's */
191 struct list_head cl_list;
192 spinlock_t cl_list_lock;
193 long open_handle_count;
194
195 /* List of bus devices */
196 struct list_head device_list;
197 spinlock_t device_list_lock;
198
199 /* waiting queues for receive message from FW */
200 wait_queue_head_t wait_hw_ready;
201 wait_queue_head_t wait_hbm_recvd_msg;
202
203 /* FIFO for input messages for BH processing */
204 unsigned char rd_msg_fifo[RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE];
205 unsigned int rd_msg_fifo_head, rd_msg_fifo_tail;
206 spinlock_t rd_msg_spinlock;
207 struct work_struct bh_hbm_work;
208
209 /* IPC write queue */
210 struct wr_msg_ctl_info wr_processing_list_head, wr_free_list_head;
211 /* For both processing list and free list */
212 spinlock_t wr_processing_spinlock;
213
214 spinlock_t out_ipc_spinlock;
215
216 struct ishtp_fw_client *fw_clients; /*Note:memory has to be allocated*/
217 DECLARE_BITMAP(fw_clients_map, ISHTP_CLIENTS_MAX);
218 DECLARE_BITMAP(host_clients_map, ISHTP_CLIENTS_MAX);
219 uint8_t fw_clients_num;
220 uint8_t fw_client_presentation_num;
221 uint8_t fw_client_index;
222 spinlock_t fw_clients_lock;
223
224 /* TX DMA buffers and slots */
225 int ishtp_host_dma_enabled;
226 void *ishtp_host_dma_tx_buf;
227 unsigned int ishtp_host_dma_tx_buf_size;
228 uint64_t ishtp_host_dma_tx_buf_phys;
229 int ishtp_dma_num_slots;
230
231 /* map of 4k blocks in Tx dma buf: 0-free, 1-used */
232 uint8_t *ishtp_dma_tx_map;
233 spinlock_t ishtp_dma_tx_lock;
234
235 /* RX DMA buffers and slots */
236 void *ishtp_host_dma_rx_buf;
237 unsigned int ishtp_host_dma_rx_buf_size;
238 uint64_t ishtp_host_dma_rx_buf_phys;
239
240 /* Dump to trace buffers if enabled*/
241 void (*print_log)(struct ishtp_device *dev, char *format, ...);
242
243 /* Debug stats */
244 unsigned int ipc_rx_cnt;
245 unsigned long long ipc_rx_bytes_cnt;
246 unsigned int ipc_tx_cnt;
247 unsigned long long ipc_tx_bytes_cnt;
248
249 const struct ishtp_hw_ops *ops;
250 size_t mtu;
251 uint32_t ishtp_msg_hdr;
252 char hw[0] __aligned(sizeof(void *));
253};
254
255static inline unsigned long ishtp_secs_to_jiffies(unsigned long sec)
256{
257 return msecs_to_jiffies(sec * MSEC_PER_SEC);
258}
259
260/*
261 * Register Access Function
262 */
263static inline int ish_ipc_reset(struct ishtp_device *dev)
264{
265 return dev->ops->ipc_reset(dev);
266}
267
268static inline int ish_hw_reset(struct ishtp_device *dev)
269{
270 return dev->ops->hw_reset(dev);
271}
272
273/* Exported function */
274void ishtp_device_init(struct ishtp_device *dev);
275int ishtp_start(struct ishtp_device *dev);
276
277#endif /*_ISHTP_DEV_H_*/