Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[RFC 4/4] hid: intel-ish-hid: ISH HID client driver

513 views
Skip to first unread message

Srinivas Pandruvada

unread,
May 31, 2016, 12:30:05 AM5/31/16
to
From: Daniel Drubin <daniel...@intel.com>

This driver is responsible for implementing ISH HID client, which
gets HID description and report. Once it has completely gets
report descriptors, it registers as a HID LL drivers. This implements
necessary callbacks so that it can be used by HID sensor hub driver.

Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
---
drivers/hid/intel-ish-hid/Makefile | 4 +
drivers/hid/intel-ish-hid/ishtp-hid-client.c | 672 +++++++++++++++++++++++++++
drivers/hid/intel-ish-hid/ishtp-hid.c | 201 ++++++++
drivers/hid/intel-ish-hid/ishtp-hid.h | 157 +++++++
4 files changed, 1034 insertions(+)
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid-client.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.h

diff --git a/drivers/hid/intel-ish-hid/Makefile b/drivers/hid/intel-ish-hid/Makefile
index 2c83cb9..6727c66 100644
--- a/drivers/hid/intel-ish-hid/Makefile
+++ b/drivers/hid/intel-ish-hid/Makefile
@@ -13,4 +13,8 @@ obj-$(CONFIG_INTEL_ISH_HID_IPC) += intel-ish-ipc.o
intel-ish-ipc-objs := ipc/ipc.o
intel-ish-ipc-objs += ipc/pci-ish.o

+obj-$(CONFIG_INTEL_ISH_HID) += intel-ishtp-hid.o
+intel-ishtp-hid-objs := ishtp-hid.o
+intel-ishtp-hid-objs += ishtp-hid-client.o
+
ccflags-y += -Idrivers/hid/intel-ish-hid/ishtp
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
new file mode 100644
index 0000000..5d22be6
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
@@ -0,0 +1,672 @@
+/*
+ * ISHTP client driver for HID (ISH)
+ *
+ * Copyright (c) 2014-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/hid.h>
+#include "ishtp/ishtp-dev.h"
+#include "ishtp/client.h"
+#include "ishtp-hid.h"
+
+/* Rx ring buffer pool size */
+#define HID_CL_RX_RING_SIZE 32
+#define HID_CL_TX_RING_SIZE 16
+
+/**
+ * report_bad_packets() - Report bad packets
+ * @hid_ishtp_cl: Client instance to get stats
+ * @recv_buf: Raw received host interface message
+ * @cur_pos: Current position index in payload
+ * @payload_len: Length of payload expected
+ *
+ * Dumps error in case bad packet is received
+ */
+static void report_bad_packet(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
+ size_t cur_pos, size_t payload_len)
+{
+ struct hostif_msg *recv_msg = recv_buf;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ dev_err(&hid_ishtp_cl->device->dev, "[hid-ish]: BAD packet %02X\n"
+ "total_bad=%u cur_pos=%u\n"
+ "[%02X %02X %02X %02X]\n"
+ "payload_len=%u\n"
+ "multi_packet_cnt=%u\n"
+ "is_response=%02X\n",
+ recv_msg->hdr.command, client_data->bad_recv_cnt,
+ (unsigned int)cur_pos,
+ ((unsigned char *)recv_msg)[0], ((unsigned char *)recv_msg)[1],
+ ((unsigned char *)recv_msg)[2], ((unsigned char *)recv_msg)[3],
+ (unsigned int)payload_len, client_data->multi_packet_cnt,
+ recv_msg->hdr.command & ~CMD_MASK);
+}
+
+/**
+ * process_recv() - Received and parse incoming packet
+ * @hid_ishtp_cl: Client instance to get stats
+ * @recv_buf: Raw received host interface message
+ * @data_len: length of the message
+ *
+ * Parse the incoming packet. If it is a response packet then it will update
+ * per instance flags and wake up the caller waiting to for the response.
+ */
+static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
+ size_t data_len)
+{
+ struct hostif_msg *recv_msg;
+ unsigned char *payload;
+ struct device_info *dev_info;
+ int i, j;
+ size_t payload_len, total_len, cur_pos;
+ int report_type;
+ struct report_list *reports_list;
+ char *reports;
+ size_t report_len;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ if (data_len < sizeof(struct hostif_msg_hdr)) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: error, received %u which is "
+ "less than data header %u\n",
+ (unsigned int)data_len,
+ (unsigned int)sizeof(struct hostif_msg_hdr));
+ ++client_data->bad_recv_cnt;
+ ish_hw_reset(hid_ishtp_cl->dev);
+ return;
+ }
+
+ payload = recv_buf + sizeof(struct hostif_msg_hdr);
+ total_len = data_len;
+ cur_pos = 0;
+
+ do {
+ recv_msg = (struct hostif_msg *)(recv_buf + cur_pos);
+ payload_len = recv_msg->hdr.size;
+
+ /* Sanity checks */
+ if (cur_pos + payload_len + sizeof(struct hostif_msg) >
+ total_len) {
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+ }
+
+
+ switch (recv_msg->hdr.command & CMD_MASK) {
+ case HOSTIF_DM_ENUM_DEVICES:
+ if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
+ client_data->init_done)) {
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg,
+ cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+ }
+ client_data->hid_dev_count = (unsigned int)*payload;
+ client_data->hid_devices = devm_kzalloc(
+ &hid_ishtp_cl->device->dev,
+ client_data->hid_dev_count *
+ sizeof(struct device_info),
+ GFP_KERNEL);
+ if (!client_data->hid_devices) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "Mem alloc failed for hid device info\n");
+ wake_up(&client_data->init_wait);
+ break;
+ }
+ for (i = 0; i < client_data->hid_dev_count; ++i) {
+ if (1 + sizeof(struct device_info) * i >=
+ payload_len) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: [ENUM_DEVICES]:"
+ " content size %lu "
+ "is bigger than "
+ "payload_len %u\n",
+ 1 + sizeof(struct device_info)
+ * i,
+ (unsigned int)payload_len);
+ }
+
+ if (1 + sizeof(struct device_info) * i >=
+ data_len)
+ break;
+
+ dev_info = (struct device_info *)(payload + 1 +
+ sizeof(struct device_info) * i);
+ if (client_data->hid_devices)
+ memcpy(client_data->hid_devices + i,
+ dev_info,
+ sizeof(struct device_info));
+ }
+
+ client_data->enum_devices_done = 1;
+ wake_up(&client_data->init_wait);
+
+ break;
+
+ case HOSTIF_GET_HID_DESCRIPTOR:
+ if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
+ client_data->init_done)) {
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg,
+ cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+ }
+ client_data->hid_descr[client_data->cur_hid_dev] =
+ devm_kmalloc(&hid_ishtp_cl->device->dev,
+ payload_len, GFP_KERNEL);
+ if (client_data->hid_descr[client_data->cur_hid_dev]) {
+ memcpy(client_data->hid_descr[
+ client_data->cur_hid_dev],
+ payload, payload_len);
+ client_data->hid_descr_size[
+ client_data->cur_hid_dev] = payload_len;
+ client_data->hid_descr_done = 1;
+ }
+ wake_up(&client_data->init_wait);
+
+ break;
+
+ case HOSTIF_GET_REPORT_DESCRIPTOR:
+ if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
+ client_data->init_done)) {
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg,
+ cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+ }
+ client_data->report_descr[client_data->cur_hid_dev] =
+ devm_kmalloc(&hid_ishtp_cl->device->dev,
+ payload_len, GFP_KERNEL);
+ if (client_data->report_descr[
+ client_data->cur_hid_dev]) {
+ memcpy(client_data->report_descr[
+ client_data->cur_hid_dev], payload,
+ payload_len);
+ client_data->report_descr_size[
+ client_data->cur_hid_dev] = payload_len;
+ client_data->report_descr_done = 1;
+ }
+ wake_up(&client_data->init_wait);
+
+ break;
+
+ case HOSTIF_GET_FEATURE_REPORT:
+ report_type = HID_FEATURE_REPORT;
+ goto do_get_report;
+
+ case HOSTIF_GET_INPUT_REPORT:
+ report_type = HID_INPUT_REPORT;
+do_get_report:
+ /* Get index of device that matches this id */
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ if (recv_msg->hdr.device_id ==
+ client_data->hid_devices[i].dev_id)
+ if (client_data->hid_sensor_hubs[i]) {
+ hid_input_report(
+ client_data->hid_sensor_hubs[
+ i],
+ report_type, payload,
+ payload_len, 0);
+ break;
+ }
+ }
+ client_data->get_report_done = 1;
+ wake_up(&client_data->ishtp_hid_wait);
+ break;
+
+ case HOSTIF_SET_FEATURE_REPORT:
+ client_data->get_report_done = 1;
+ wake_up(&client_data->ishtp_hid_wait);
+ break;
+
+ case HOSTIF_PUBLISH_INPUT_REPORT:
+ report_type = HID_INPUT_REPORT;
+ for (i = 0; i < client_data->num_hid_devices; ++i)
+ if (recv_msg->hdr.device_id ==
+ client_data->hid_devices[i].dev_id)
+ if (client_data->hid_sensor_hubs[i])
+ hid_input_report(
+ client_data->hid_sensor_hubs[
+ i],
+ report_type, payload,
+ payload_len, 0);
+ break;
+
+ case HOSTIF_PUBLISH_INPUT_REPORT_LIST:
+ report_type = HID_INPUT_REPORT;
+ reports_list = (struct report_list *)payload;
+ reports = (char *)reports_list->reports;
+
+ for (j = 0; j < reports_list->num_of_reports; j++) {
+ recv_msg = (struct hostif_msg *)(reports +
+ sizeof(uint16_t));
+ report_len = *(uint16_t *)reports;
+ payload = reports + sizeof(uint16_t) +
+ sizeof(struct hostif_msg_hdr);
+ payload_len = report_len -
+ sizeof(struct hostif_msg_hdr);
+
+ for (i = 0; i < client_data->num_hid_devices;
+ ++i)
+ if (recv_msg->hdr.device_id ==
+ client_data->hid_devices[i].dev_id &&
+ client_data->hid_sensor_hubs[i]) {
+ hid_input_report(
+ client_data->hid_sensor_hubs[
+ i],
+ report_type,
+ payload, payload_len,
+ 0);
+ }
+
+ reports += sizeof(uint16_t) + report_len;
+ }
+ break;
+ default:
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+
+ }
+
+ if (!cur_pos && cur_pos + payload_len +
+ sizeof(struct hostif_msg) < total_len)
+ ++client_data->multi_packet_cnt;
+
+ cur_pos += payload_len + sizeof(struct hostif_msg);
+ payload += payload_len + sizeof(struct hostif_msg);
+
+ } while (cur_pos < total_len);
+}
+
+/**
+ * ish_cl_event_cb() - bus driver callback for incoming message/packet
+ * @device: Pointer to the the ishtp client device for which this message
+ * is targeted
+ *
+ * Remove the packet from the list and process the message by calling
+ * process_recv
+ */
+static void ish_cl_event_cb(struct ishtp_cl_device *device)
+{
+ struct ishtp_cl *hid_ishtp_cl = device->driver_data;
+ struct ishtp_cl_rb *rb_in_proc;
+ size_t r_length;
+ unsigned long flags;
+
+ if (!hid_ishtp_cl)
+ return;
+
+ spin_lock_irqsave(&hid_ishtp_cl->in_process_spinlock, flags);
+ while (!list_empty(&hid_ishtp_cl->in_process_list.list)) {
+ rb_in_proc = list_entry(
+ hid_ishtp_cl->in_process_list.list.next,
+ struct ishtp_cl_rb, list);
+ list_del_init(&rb_in_proc->list);
+ spin_unlock_irqrestore(&hid_ishtp_cl->in_process_spinlock,
+ flags);
+
+ if (!rb_in_proc->buffer.data)
+ return;
+
+ r_length = rb_in_proc->buf_idx;
+
+ /* decide what to do with received data */
+ process_recv(hid_ishtp_cl, rb_in_proc->buffer.data, r_length);
+
+ ishtp_io_rb_recycle(rb_in_proc);
+ spin_lock_irqsave(&hid_ishtp_cl->in_process_spinlock, flags);
+ }
+ spin_unlock_irqrestore(&hid_ishtp_cl->in_process_spinlock, flags);
+}
+
+/**
+ * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
+ * @hid: hid device instance for this request
+ * @buf: feature buffer
+ * @len: Length of feature buffer
+ * @report_id: Report id for the feature set request
+ *
+ * This is called from hid core .request() callback. This function doesn't wait
+ * for response.
+ */
+void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len,
+ int report_id)
+{
+ struct ishtp_cl *hid_ishtp_cl = hid->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ struct hostif_msg *msg = (struct hostif_msg *)buf;
+ int rv;
+ int i;
+
+ memset(msg, 0, sizeof(struct hostif_msg));
+ msg->hdr.command = HOSTIF_SET_FEATURE_REPORT;
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ if (hid == client_data->hid_sensor_hubs[i]) {
+ msg->hdr.device_id =
+ client_data->hid_devices[i].dev_id;
+ break;
+ }
+ }
+
+ if (i == client_data->num_hid_devices)
+ return;
+
+ rv = ishtp_cl_send(hid_ishtp_cl, buf, len);
+}
+
+/**
+ * hid_ishtp_get_report() - request to get feature/input report
+ * @hid: hid device instance for this request
+ * @report_id: Report id for the get request
+ * @report_type: Report type for the this request
+ *
+ * This is called from hid core .request() callback. This function will send
+ * request to FW and return without waiting for response.
+ */
+void hid_ishtp_get_report(struct hid_device *hid, int report_id,
+ int report_type)
+{
+ struct ishtp_cl *hid_ishtp_cl = hid->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ static unsigned char buf[10];
+ unsigned int len;
+ struct hostif_msg_to_sensor *msg = (struct hostif_msg_to_sensor *)buf;
+ int rv;
+ int i;
+
+ len = sizeof(struct hostif_msg_to_sensor);
+
+ memset(msg, 0, sizeof(struct hostif_msg_to_sensor));
+ msg->hdr.command = (report_type == HID_FEATURE_REPORT) ?
+ HOSTIF_GET_FEATURE_REPORT : HOSTIF_GET_INPUT_REPORT;
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ if (hid == client_data->hid_sensor_hubs[i]) {
+ msg->hdr.device_id =
+ client_data->hid_devices[i].dev_id;
+ break;
+ }
+ }
+
+ if (i == client_data->num_hid_devices)
+ return;
+
+ msg->report_id = report_id;
+ rv = ishtp_cl_send(hid_ishtp_cl, buf, len);
+}
+
+/**
+ * hid_ishtp_cl_init() - Init function for ISHTP client
+ * @hid_istp_cl: ISHTP client instance
+ *
+ * This function complete the initializtion of the client. The summary of
+ * processing:
+ * - Send request to enumerate the hid clients
+ * Get the HID descriptor for each enumearated device
+ * Get report description of each device
+ * Register each device wik hid core by calling ishtp_hid_probe
+ */
+static int hid_ishtp_cl_init(struct ishtp_cl *hid_ishtp_cl)
+{
+ static unsigned char buf[512];
+ unsigned int len;
+ struct hostif_msg *msg = (struct hostif_msg *)buf;
+ struct ishtp_device *dev;
+ int retry_count;
+ unsigned long flags;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ int i;
+ int rv;
+
+ init_waitqueue_head(&client_data->init_wait);
+ init_waitqueue_head(&client_data->ishtp_hid_wait);
+
+ rv = ishtp_cl_link(hid_ishtp_cl, ISHTP_HOST_CLIENT_ID_ANY);
+ if (rv)
+ return -ENOMEM;
+
+ client_data->init_done = 0;
+
+ dev = hid_ishtp_cl->dev;
+
+ /* Connect to FW client */
+ hid_ishtp_cl->rx_ring_size = HID_CL_RX_RING_SIZE;
+ hid_ishtp_cl->tx_ring_size = HID_CL_TX_RING_SIZE;
+
+ spin_lock_irqsave(&dev->fw_clients_lock, flags);
+ i = ishtp_fw_cl_by_uuid(dev, &hid_ishtp_guid);
+ if (i < 0) {
+ spin_unlock_irqrestore(&dev->fw_clients_lock, flags);
+ return i;
+ }
+ hid_ishtp_cl->fw_client_id = dev->fw_clients[i].client_id;
+ spin_unlock_irqrestore(&dev->fw_clients_lock, flags);
+ hid_ishtp_cl->state = ISHTP_CL_CONNECTING;
+
+ rv = ishtp_cl_connect(hid_ishtp_cl);
+ if (rv)
+ goto ret;
+
+ /* Register read callback */
+ ishtp_register_event_cb(hid_ishtp_cl->device, ish_cl_event_cb);
+
+ /* Send HOSTIF_DM_ENUM_DEVICES */
+ memset(msg, 0, sizeof(struct hostif_msg));
+ msg->hdr.command = HOSTIF_DM_ENUM_DEVICES;
+ len = sizeof(struct hostif_msg);
+ rv = ishtp_cl_send(hid_ishtp_cl, buf, len);
+ if (rv)
+ goto ret;
+
+ rv = 0;
+
+ retry_count = 0;
+ while (!client_data->enum_devices_done &&
+ retry_count < 10) {
+ wait_event_timeout(client_data->init_wait,
+ client_data->enum_devices_done,
+ 3 * HZ);
+ ++retry_count;
+ if (!client_data->enum_devices_done)
+ /* Send HOSTIF_DM_ENUM_DEVICES */
+ rv = ishtp_cl_send(hid_ishtp_cl, buf, len);
+ }
+ if (!client_data->enum_devices_done) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: timed out waiting for enum_devices\n");
+ rv = -ETIMEDOUT;
+ goto ret;
+ }
+ if (!client_data->hid_devices) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: failed to allocate HID dev structures\n");
+ rv = -ENOMEM;
+ goto ret;
+ }
+
+ client_data->num_hid_devices = client_data->hid_dev_count;
+ dev_warn(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
+ client_data->num_hid_devices);
+
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ client_data->cur_hid_dev = i;
+
+ /* Get HID descriptor */
+ client_data->hid_descr_done = 0;
+ memset(msg, 0, sizeof(struct hostif_msg));
+ msg->hdr.command = HOSTIF_GET_HID_DESCRIPTOR;
+ msg->hdr.device_id = client_data->hid_devices[i].dev_id;
+ len = sizeof(struct hostif_msg);
+ rv = ishtp_cl_send(hid_ishtp_cl, buf, len);
+ rv = 0;
+
+ if (!client_data->hid_descr_done)
+ wait_event_timeout(client_data->init_wait,
+ client_data->hid_descr_done,
+ 30 * HZ);
+ if (!client_data->hid_descr_done) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: timed out for hid_descr_done\n");
+ continue;
+ }
+
+ if (!client_data->hid_descr[i]) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: allocation HID desc fail\n");
+ continue;
+ }
+
+ /* Get report descriptor */
+ client_data->report_descr_done = 0;
+ memset(msg, 0, sizeof(struct hostif_msg));
+ msg->hdr.command = HOSTIF_GET_REPORT_DESCRIPTOR;
+ msg->hdr.device_id = client_data->hid_devices[i].dev_id;
+ len = sizeof(struct hostif_msg);
+ rv = ishtp_cl_send(hid_ishtp_cl, buf, len);
+
+ rv = 0;
+
+ if (!client_data->report_descr_done)
+ wait_event_timeout(client_data->init_wait,
+ client_data->report_descr_done,
+ 30 * HZ);
+ if (!client_data->report_descr_done) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: timed out for report descr\n");
+ continue;
+ }
+
+ if (!client_data->report_descr[i]) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: failed to alloc report descr\n");
+ continue;
+ }
+
+ rv = ishtp_hid_probe(i, hid_ishtp_cl);
+ if (rv) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: HID probe for #%u failed: %d\n",
+ i, rv);
+ continue;
+ }
+ } /* for() on all hid devices */
+
+ret:
+ client_data->init_done = 1;
+
+ return rv;
+}
+
+/**
+ * hid_ishtp_cl_probe() - ISHTP client driver probe
+ * @cl_device: ISHTP client device instance
+ *
+ * This function calls on device create on ISHTP bus
+ */
+static int hid_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
+{
+ struct ishtp_cl *hid_ishtp_cl;
+ struct ishtp_cl_data *client_data;
+ int rv;
+
+ if (!cl_device)
+ return -ENODEV;
+
+ if (uuid_le_cmp(hid_ishtp_guid,
+ cl_device->fw_client->props.protocol_name) != 0)
+ return -ENODEV;
+
+ client_data = devm_kzalloc(&cl_device->dev, sizeof(*client_data),
+ GFP_KERNEL);
+ if (!client_data)
+ return -ENOMEM;
+
+ hid_ishtp_cl = ishtp_cl_allocate(cl_device->ishtp_dev);
+ if (!hid_ishtp_cl)
+ return -ENOMEM;
+
+ cl_device->driver_data = hid_ishtp_cl;
+ hid_ishtp_cl->client_data = client_data;
+
+ rv = hid_ishtp_cl_init(hid_ishtp_cl);
+ if (rv) {
+ ishtp_cl_free(hid_ishtp_cl);
+ return rv;
+ }
+
+ return 0;
+}
+
+/**
+ * hid_ishtp_cl_remove() - ISHTP client driver remove
+ * @cl_device: ISHTP client device instance
+ *
+ * This function calls on device create on ISHTP bus
+ */
+static int hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
+{
+ struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ ishtp_hid_remove(hid_ishtp_cl);
+
+ ishtp_cl_unlink(hid_ishtp_cl);
+ ishtp_cl_flush_queues(hid_ishtp_cl);
+
+ /* disband and free all Tx and Rx client-level rings */
+ ishtp_cl_free(hid_ishtp_cl);
+ hid_ishtp_cl = NULL;
+
+ client_data->num_hid_devices = 0;
+
+ return 0;
+}
+
+
+struct ishtp_cl_driver hid_ishtp_cl_driver = {
+ .name = "ish",
+ .probe = hid_ishtp_cl_probe,
+ .remove = hid_ishtp_cl_remove,
+};
+
+static int __init ish_hid_init(void)
+{
+ int rv;
+
+ /* Register ISHTP client device driver with ISHTP Bus */
+ rv = ishtp_cl_driver_register(&hid_ishtp_cl_driver);
+
+ return rv;
+
+}
+late_initcall(ish_hid_init);
+
+MODULE_DESCRIPTION("ISH ISHTP HID client driver");
+/* Primary author */
+MODULE_AUTHOR("Daniel Drubin <daniel...@intel.com>");
+/* Modification for multi instance support and clean up */
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas....@linux.intel.com>");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.c b/drivers/hid/intel-ish-hid/ishtp-hid.c
new file mode 100644
index 0000000..f0c5569
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp-hid.c
@@ -0,0 +1,201 @@
+/*
+ * ISHTP-HID glue driver.
+ *
+ * Copyright (c) 2012-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/hid.h>
+#include "ishtp/client.h"
+#include "ishtp-hid.h"
+
+/**
+ * ishtp_hid_parse() - hid-core .parse() callback
+ * @hid: hid device instance
+ *
+ * This function gets called during call to hid_add_device
+ */
+static int ishtp_hid_parse(struct hid_device *hid)
+{
+ struct ishtp_cl *hid_ishtp_cl = hid->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ int rv;
+
+ rv = hid_parse_report(hid,
+ client_data->report_descr[client_data->cur_hid_dev],
+ client_data->report_descr_size[client_data->cur_hid_dev]);
+ if (rv)
+ return rv;
+
+ return 0;
+}
+
+/* Empty callbacks with success return code */
+static int ishtp_hid_start(struct hid_device *hid)
+{
+ return 0;
+}
+
+static void ishtp_hid_stop(struct hid_device *hid)
+{
+}
+
+static int ishtp_hid_open(struct hid_device *hid)
+{
+ return 0;
+}
+
+static void ishtp_hid_close(struct hid_device *hid)
+{
+}
+
+static int ishtp_raw_request(struct hid_device *hdev, unsigned char reportnum,
+ __u8 *buf, size_t len, unsigned char rtype, int reqtype)
+{
+ return 0;
+}
+
+/**
+ * ishtp_hid_request() - hid-core .request() callback
+ * @hid: hid device instance
+ * @rep: pointer to hid_report
+ * @reqtype: type of req. [GET|SET]_REPORT
+ *
+ * This function is used to set/get feaure/input report.
+ */
+static void ishtp_hid_request(struct hid_device *hid, struct hid_report *rep,
+ int reqtype)
+{
+ /* the specific report length, just HID part of it */
+ unsigned int len = ((rep->size - 1) >> 3) + 1 + (rep->id > 0);
+ char *buf;
+ unsigned int header_size = sizeof(struct hostif_msg);
+
+ len += header_size;
+
+ switch (reqtype) {
+ case HID_REQ_GET_REPORT:
+ hid_ishtp_get_report(hid, rep->id, rep->type);
+ break;
+ case HID_REQ_SET_REPORT:
+ /*
+ * Spare 7 bytes for 64b accesses through
+ * get/put_unaligned_le64()
+ */
+ buf = kzalloc(len + 7, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ hid_output_report(rep, buf + header_size);
+ hid_ishtp_set_feature(hid, buf, len, rep->id);
+ kfree(buf);
+ break;
+ }
+}
+
+/**
+ * ishtp_wait_for_response() - hid-core .wait() callback
+ * @hid: hid device instance
+ *
+ * This function is used to wait after get feaure/input report.
+ */
+static int ishtp_wait_for_response(struct hid_device *hid)
+{
+ struct ishtp_cl *hid_ishtp_cl = hid->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ if (!client_data->get_report_done)
+ wait_event_timeout(client_data->ishtp_hid_wait,
+ client_data->get_report_done, 3 * HZ);
+
+ if (!client_data->get_report_done) {
+ hid_err(hid,
+ "timeout waiting for response from ISHTP device\n");
+ return -1;
+ }
+
+ client_data->get_report_done = 0;
+
+ return 0;
+}
+
+static struct hid_ll_driver ishtp_hid_ll_driver = {
+ .parse = ishtp_hid_parse,
+ .start = ishtp_hid_start,
+ .stop = ishtp_hid_stop,
+ .open = ishtp_hid_open,
+ .close = ishtp_hid_close,
+ .request = ishtp_hid_request,
+ .wait = ishtp_wait_for_response,
+ .raw_request = ishtp_raw_request
+};
+
+/**
+ * ishtp_hid_probe() - hid register ll driver
+ * @curr_hid_dev: Index of hid device calling to register
+ * @hid_ishtp_cl: ISHTP Client instance
+ *
+ * This function is used to allocate and add HID device.
+ */
+int ishtp_hid_probe(unsigned int cur_hid_dev, struct ishtp_cl *hid_ishtp_cl)
+{
+ int rv;
+ struct hid_device *hid;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ hid = hid_allocate_device();
+ if (IS_ERR(hid)) {
+ rv = PTR_ERR(hid);
+ return -ENOMEM;
+ }
+
+ hid->driver_data = hid_ishtp_cl;
+
+ client_data->hid_sensor_hubs[cur_hid_dev] = hid;
+
+ hid->ll_driver = &ishtp_hid_ll_driver;
+ hid->bus = BUS_ISHTP;
+ hid->version = le16_to_cpu(ISH_HID_VERSION);
+ hid->vendor = le16_to_cpu(ISH_HID_VENDOR);
+ hid->product = le16_to_cpu(ISH_HID_PRODUCT);
+
+ snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", "hid-ishtp",
+ hid->vendor, hid->product);
+
+ rv = hid_add_device(hid);
+ if (rv) {
+ if (rv != -ENODEV)
+ hid_err(hid, "[hid-ishtp]: can't add HID device: %d\n",
+ rv);
+ kfree(hid);
+ return rv;
+ }
+
+ return 0;
+}
+
+/**
+ * ishtp_hid_probe() - Remove registered hid device
+ * @hid_ishtp_cl: ISHTP Client instance
+ *
+ * This function is used to destroy allocatd HID device.
+ */
+void ishtp_hid_remove(struct ishtp_cl *hid_ishtp_cl)
+{
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ int i;
+
+ for (i = 0; i < client_data->num_hid_devices; ++i)
+ if (client_data->hid_sensor_hubs[i]) {
+ hid_destroy_device(client_data->hid_sensor_hubs[i]);
+ client_data->hid_sensor_hubs[i] = NULL;
+ }
+}
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.h b/drivers/hid/intel-ish-hid/ishtp-hid.h
new file mode 100644
index 0000000..9bf9198
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp-hid.h
@@ -0,0 +1,157 @@
+/*
+ * ISHTP-HID glue driver's definitions.
+ *
+ * Copyright (c) 2014-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+#ifndef ISHTP_HID__H
+#define ISHTP_HID__H
+
+/* ISH Transport protocol id */
+#define BUS_ISHTP 0x44
+
+/* The fixed ISH product and vendor id */
+#define ISH_HID_VENDOR 0x8086
+#define ISH_HID_PRODUCT 0x22D8
+#define ISH_HID_VERSION 0x0200
+
+#define CMD_MASK 0x7F
+#define IS_RESPONSE 0x80
+
+/* ISH Transport protocol (ISHTP in short) GUID */
+static const uuid_le hid_ishtp_guid = UUID_LE(0x33AECD58, 0xB679, 0x4E54,
+ 0x9B, 0xD9, 0xA0, 0x4D, 0x34,
+ 0xF0, 0xC2, 0x26);
+
+/* ISH HID message structure */
+struct hostif_msg_hdr {
+ uint8_t command; /* Bit 7: is_response */
+ uint8_t device_id;
+ uint8_t status;
+ uint8_t flags;
+ uint16_t size;
+} __packed;
+
+struct hostif_msg {
+ struct hostif_msg_hdr hdr;
+} __packed;
+
+struct hostif_msg_to_sensor {
+ struct hostif_msg_hdr hdr;
+ uint8_t report_id;
+} __packed;
+
+struct device_info {
+ uint32_t dev_id;
+ uint8_t dev_class;
+ uint16_t pid;
+ uint16_t vid;
+} __packed;
+
+struct ishtp_version {
+ uint8_t major;
+ uint8_t minor;
+ uint8_t hotfix;
+ uint16_t build;
+} __packed;
+
+/* struct for ISHTP aggregated input data */
+struct report_list {
+ uint16_t total_size;
+ uint8_t num_of_reports;
+ uint8_t flags;
+ struct {
+ uint16_t size_of_report;
+ uint8_t report[1];
+ } __packed reports[1];
+} __packed;
+
+/* HOSTIF commands */
+#define HOSTIF_HID_COMMAND_BASE 0
+#define HOSTIF_GET_HID_DESCRIPTOR 0
+#define HOSTIF_GET_REPORT_DESCRIPTOR 1
+#define HOSTIF_GET_FEATURE_REPORT 2
+#define HOSTIF_SET_FEATURE_REPORT 3
+#define HOSTIF_GET_INPUT_REPORT 4
+#define HOSTIF_PUBLISH_INPUT_REPORT 5
+#define HOSTIF_PUBLISH_INPUT_REPORT_LIST 6
+#define HOSTIF_DM_COMMAND_BASE 32
+#define HOSTIF_DM_ENUM_DEVICES 33
+#define HOSTIF_DM_ADD_DEVICE 34
+
+#define MAX_HID_DEVICES 32
+
+/**
+ * struct ishtp_cl_data - Encapsulate per ISH TP HID Client
+ * @enum_device_done: Enum devices response complete flag
+ * @hid_descr_done: HID descriptor complete flag
+ * @report_descr_done: Get report descriptor complete flag
+ * @get_report_done: Get Feature/Input report complete flag
+ * used during get/set request from hid core
+ * @init_done: Init process completed successfully
+ * @num_hid_devices: Number of HID devices enumerated in this client
+ * @cur_hid_dev: This keeps track of the device index for which
+ * initialization and registration with HID core
+ * in progress.
+ * @hid_devices: Store vid/pid/devid for each enumerated HID device
+ * @report_descr: Stores the raw report descriptors for each HID device
+ * @report_descr_size: Report description of size of above repo_descr[]
+ * @hid_sensor_hubs: Pointer to hid_device for all HID device, so that
+ * when clients are removed, they can be freed
+ * @hid_descr: Pointer to hid descriptor for each enumerated hid
+ * device
+ * @hid_descr_size: Size of each above report descriptor
+ * @init_wait: Wait queue to wait during initialization, where the
+ * client send message to ISH FW and wait for response
+ * @ishtp_hid_wait: The wait for get report during wait callback from hid
+ * core
+ * @bad_recv_cnt: Running count of packets received with error
+ * @multi_packet_cnt: Count of fragmented packet count
+ *
+ * This structure is used to store completion flags and per client data like
+ * like report description, number of HID devices etc.
+ */
+struct ishtp_cl_data {
+ /* completion flags */
+ int enum_devices_done;
+ int hid_descr_done;
+ int report_descr_done;
+ int get_report_done;
+ int init_done;
+
+ unsigned int num_hid_devices;
+ unsigned int cur_hid_dev;
+ unsigned int hid_dev_count;
+
+ struct device_info *hid_devices;
+ unsigned char *report_descr[MAX_HID_DEVICES];
+ int report_descr_size[MAX_HID_DEVICES];
+ struct hid_device *hid_sensor_hubs[MAX_HID_DEVICES];
+ unsigned char *hid_descr[MAX_HID_DEVICES];
+ int hid_descr_size[MAX_HID_DEVICES];
+
+ wait_queue_head_t init_wait;
+ wait_queue_head_t ishtp_hid_wait;
+
+ /* Statistics */
+ unsigned int bad_recv_cnt;
+ int multi_packet_cnt;
+};
+
+/* Interface functions between HID LL driver and ISH TP client */
+void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len,
+ int report_id);
+void hid_ishtp_get_report(struct hid_device *hid, int report_id,
+ int report_type);
+int ishtp_hid_probe(unsigned int cur_hid_dev, struct ishtp_cl *hid_ishtp_cl);
+void ishtp_hid_remove(struct ishtp_cl *hid_ishtp_cl);
+
+#endif /* ISHTP_HID__H */
--
1.9.1

Srinivas Pandruvada

unread,
May 31, 2016, 12:30:05 AM5/31/16
to
Starting from Cherrytrail, multiple generation of Intel processors offers
on package sensor hub. Several recent tablets, 2-in-1 convertible laptops
are using ISH instead of external sensor hubs. This resulted in lack of
support of sensor function like device rotation and auto backlight
adjustment. In addition, depending on the OEM implementation, support of ISH
is required to support low power sleep states.

The support of ISH on Linux platforms is not new. Android platforms with
Intel SoCs had this support for a while submitted by Daniel Drubin.
This patcheset is reusing most of those changes with clean up and
removing Android platform specific changes.

This series is tested on:
- Lenovo Yoga 260 with Skylake processor
- HP Pavilion x2 detachable with Cherrytrail

The user mode ABI is still same as external sensor hubs using Linux
IIO. So existing user mode software should still work without change.
This series primarily brings in new HID transport used in ISH.

This series submitted as a RFC to try on several devices. We have
received request from Linux users who wanted this support. So I hope all
those users try and give feedback.

Daniel Drubin (3):
hid: intel_ish-hid: ISH Transport layer
hid: intel-ish-hid: ipc layer
hid: intel-ish-hid: ISH HID client driver

Srinivas Pandruvada (1):
Documentation: hid: Intel ISH HID document

Documentation/hid/intel-ish-hid.txt | 375 +++++++++
drivers/hid/Kconfig | 2 +
drivers/hid/Makefile | 2 +
drivers/hid/intel-ish-hid/Kconfig | 27 +
drivers/hid/intel-ish-hid/Makefile | 20 +
drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h | 220 +++++
drivers/hid/intel-ish-hid/ipc/hw-ish.h | 71 ++
drivers/hid/intel-ish-hid/ipc/ipc.c | 710 ++++++++++++++++
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 238 ++++++
drivers/hid/intel-ish-hid/ipc/utils.h | 65 ++
drivers/hid/intel-ish-hid/ishtp-hid-client.c | 672 +++++++++++++++
drivers/hid/intel-ish-hid/ishtp-hid.c | 201 +++++
drivers/hid/intel-ish-hid/ishtp-hid.h | 157 ++++
drivers/hid/intel-ish-hid/ishtp/bus.c | 670 +++++++++++++++
drivers/hid/intel-ish-hid/ishtp/bus.h | 99 +++
drivers/hid/intel-ish-hid/ishtp/client.c | 1131 ++++++++++++++++++++++++++
drivers/hid/intel-ish-hid/ishtp/client.h | 196 +++++
drivers/hid/intel-ish-hid/ishtp/dma-if.c | 175 ++++
drivers/hid/intel-ish-hid/ishtp/hbm.c | 911 +++++++++++++++++++++
drivers/hid/intel-ish-hid/ishtp/hbm.h | 319 ++++++++
drivers/hid/intel-ish-hid/ishtp/init.c | 94 +++
drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h | 276 +++++++
include/trace/events/intel_ish.h | 30 +
23 files changed, 6661 insertions(+)
create mode 100644 Documentation/hid/intel-ish-hid.txt
create mode 100644 drivers/hid/intel-ish-hid/Kconfig
create mode 100644 drivers/hid/intel-ish-hid/Makefile
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/ipc.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/pci-ish.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/utils.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid-client.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/bus.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/bus.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/client.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/client.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/dma-if.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/hbm.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/hbm.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/init.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
create mode 100644 include/trace/events/intel_ish.h

--
1.9.1

Srinivas Pandruvada

unread,
May 31, 2016, 12:30:06 AM5/31/16
to
From: Daniel Drubin <daniel...@intel.com>

This layer is responsible for
- Enumerating over PCI bus
- Inform FW about host readiness
- Provide HW interface to transport layer for control and messages
- Interrupt handling and routing

Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
---
drivers/hid/intel-ish-hid/Kconfig | 5 +
drivers/hid/intel-ish-hid/Makefile | 6 +
drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h | 220 +++++++++
drivers/hid/intel-ish-hid/ipc/hw-ish.h | 71 +++
drivers/hid/intel-ish-hid/ipc/ipc.c | 710 ++++++++++++++++++++++++++++
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 238 ++++++++++
drivers/hid/intel-ish-hid/ipc/utils.h | 65 +++
include/trace/events/intel_ish.h | 30 ++
8 files changed, 1345 insertions(+)
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/ipc.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/pci-ish.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/utils.h
create mode 100644 include/trace/events/intel_ish.h

diff --git a/drivers/hid/intel-ish-hid/Kconfig b/drivers/hid/intel-ish-hid/Kconfig
index 8914f3b..88967a1 100644
--- a/drivers/hid/intel-ish-hid/Kconfig
+++ b/drivers/hid/intel-ish-hid/Kconfig
@@ -5,10 +5,15 @@ config INTEL_ISH_HID_TRANSPORT
bool
default n

+config INTEL_ISH_HID_IPC
+ bool
+ default n
+
config INTEL_ISH_HID
bool "Intel Integrated Sensor Hub"
default n
select INTEL_ISH_HID_TRANSPORT
+ select INTEL_ISH_HID_IPC
help
The Integrated Sensor Hub (ISH) enables the ability to offload
sensor polling and algorithm processing to a dedicated low power
diff --git a/drivers/hid/intel-ish-hid/Makefile b/drivers/hid/intel-ish-hid/Makefile
index a5eaa6e..2c83cb9 100644
--- a/drivers/hid/intel-ish-hid/Makefile
+++ b/drivers/hid/intel-ish-hid/Makefile
@@ -8,3 +8,9 @@ intel-ishtp-objs += ishtp/hbm.o
intel-ishtp-objs += ishtp/client.o
intel-ishtp-objs += ishtp/bus.o
intel-ishtp-objs += ishtp/dma-if.o
+
+obj-$(CONFIG_INTEL_ISH_HID_IPC) += intel-ish-ipc.o
+intel-ish-ipc-objs := ipc/ipc.o
+intel-ish-ipc-objs += ipc/pci-ish.o
+
+ccflags-y += -Idrivers/hid/intel-ish-hid/ishtp
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h b/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
new file mode 100644
index 0000000..f6eac6d
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
@@ -0,0 +1,220 @@
+/*
+ * ISH registers definitions
+ *
+ * Copyright (c) 2012-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _ISHTP_ISH_REGS_H_
+#define _ISHTP_ISH_REGS_H_
+
+
+/*** IPC PCI Offsets and sizes ***/
+/* ISH IPC Base Address */
+#define IPC_REG_BASE 0x0000
+/* Peripheral Interrupt Status Register */
+#define IPC_REG_PISR_CHV_AB (IPC_REG_BASE + 0x00)
+/* Peripheral Interrupt Mask Register */
+#define IPC_REG_PIMR_CHV_AB (IPC_REG_BASE + 0x04)
+/*BXT, CHV_K0*/
+/*Peripheral Interrupt Status Register */
+#define IPC_REG_PISR_BXT (IPC_REG_BASE + 0x0C)
+/*Peripheral Interrupt Mask Register */
+#define IPC_REG_PIMR_BXT (IPC_REG_BASE + 0x08)
+/***********************************/
+/* ISH Host Firmware status Register */
+#define IPC_REG_ISH_HOST_FWSTS (IPC_REG_BASE + 0x34)
+/* Host Communication Register */
+#define IPC_REG_HOST_COMM (IPC_REG_BASE + 0x38)
+/* Reset register */
+#define IPC_REG_ISH_RST (IPC_REG_BASE + 0x44)
+
+/* Inbound doorbell register Host to ISH */
+#define IPC_REG_HOST2ISH_DRBL (IPC_REG_BASE + 0x48)
+/* Outbound doorbell register ISH to Host */
+#define IPC_REG_ISH2HOST_DRBL (IPC_REG_BASE + 0x54)
+/* ISH to HOST message registers */
+#define IPC_REG_ISH2HOST_MSG (IPC_REG_BASE + 0x60)
+/* HOST to ISH message registers */
+#define IPC_REG_HOST2ISH_MSG (IPC_REG_BASE + 0xE0)
+/* REMAP2 to enable DMA (D3 RCR) */
+#define IPC_REG_ISH_RMP2 (IPC_REG_BASE + 0x368)
+
+#define IPC_REG_MAX (IPC_REG_BASE + 0x400)
+
+/*** register bits - HISR ***/
+/* bit corresponds HOST2ISH interrupt in PISR and PIMR registers */
+#define IPC_INT_HOST2ISH_BIT (1<<0)
+/***********************************/
+/*CHV_A0, CHV_B0*/
+/* bit corresponds ISH2HOST interrupt in PISR and PIMR registers */
+#define IPC_INT_ISH2HOST_BIT_CHV_AB (1<<3)
+/*BXT, CHV_K0*/
+/* bit corresponds ISH2HOST interrupt in PISR and PIMR registers */
+#define IPC_INT_ISH2HOST_BIT_BXT (1<<0)
+/***********************************/
+
+/* bit corresponds ISH2HOST busy clear interrupt in PIMR register */
+#define IPC_INT_ISH2HOST_CLR_MASK_BIT (1<<11)
+
+/* offset of ISH2HOST busy clear interrupt in IPC_BUSY_CLR register */
+#define IPC_INT_ISH2HOST_CLR_OFFS (0)
+
+/* bit corresponds ISH2HOST busy clear interrupt in IPC_BUSY_CLR register */
+#define IPC_INT_ISH2HOST_CLR_BIT (1<<IPC_INT_ISH2HOST_CLR_OFFS)
+
+/* bit corresponds busy bit in doorbell registers */
+#define IPC_DRBL_BUSY_OFFS (31)
+#define IPC_DRBL_BUSY_BIT (1<<IPC_DRBL_BUSY_OFFS)
+
+#define IPC_HOST_OWNS_MSG_OFFS (30)
+
+/*
+ * A0: bit means that host owns MSGnn registers and is reading them.
+ * ISH FW may not write to them
+ */
+#define IPC_HOST_OWNS_MSG_BIT (1<<IPC_HOST_OWNS_MSG_OFFS)
+
+/*
+ * Host status bits (HOSTCOMM)
+ */
+/* bit corresponds host ready bit in Host Status Register (HOST_COMM) */
+#define IPC_HOSTCOMM_READY_OFFS (7)
+#define IPC_HOSTCOMM_READY_BIT (1<<IPC_HOSTCOMM_READY_OFFS)
+
+/***********************************/
+/*CHV_A0, CHV_B0*/
+#define IPC_HOSTCOMM_INT_EN_OFFS_CHV_AB (31)
+#define IPC_HOSTCOMM_INT_EN_BIT_CHV_AB \
+ (1<<IPC_HOSTCOMM_INT_EN_OFFS_CHV_AB)
+/*BXT, CHV_K0*/
+#define IPC_PIMR_INT_EN_OFFS_BXT (0)
+#define IPC_PIMR_INT_EN_BIT_BXT (1<<IPC_PIMR_INT_EN_OFFS_BXT)
+
+#define IPC_HOST2ISH_BUSYCLEAR_MASK_OFFS_BXT (8)
+#define IPC_HOST2ISH_BUSYCLEAR_MASK_BIT \
+ (1<<IPC_HOST2ISH_BUSYCLEAR_MASK_OFFS_BXT)
+/***********************************/
+/*
+ * both Host and ISH have ILUP at bit 0
+ * bit corresponds host ready bit in both status registers
+ */
+#define IPC_ILUP_OFFS (0)
+#define IPC_ILUP_BIT (1<<IPC_ILUP_OFFS)
+
+/*
+ * FW status bits (relevant)
+ */
+#define IPC_FWSTS_ILUP 0x1
+#define IPC_FWSTS_ISHTP_UP (1<<1)
+#define IPC_FWSTS_DMA0 (1<<16)
+#define IPC_FWSTS_DMA1 (1<<17)
+#define IPC_FWSTS_DMA2 (1<<18)
+#define IPC_FWSTS_DMA3 (1<<19)
+
+#define IPC_ISH_IN_DMA \
+ (IPC_FWSTS_DMA0 | IPC_FWSTS_DMA1 | IPC_FWSTS_DMA2 | IPC_FWSTS_DMA3)
+
+/* bit corresponds host ready bit in ISH FW Status Register */
+#define IPC_ISH_ISHTP_READY_OFFS (1)
+#define IPC_ISH_ISHTP_READY_BIT (1<<IPC_ISH_ISHTP_READY_OFFS)
+
+#define IPC_RMP2_DMA_ENABLED 0x1 /* Value to enable DMA, per D3 RCR */
+
+#define IPC_MSG_MAX_SIZE 0x80
+
+
+#define IPC_HEADER_LENGTH_MASK 0x03FF
+#define IPC_HEADER_PROTOCOL_MASK 0x0F
+#define IPC_HEADER_MNG_CMD_MASK 0x0F
+
+#define IPC_HEADER_LENGTH_OFFSET 0
+#define IPC_HEADER_PROTOCOL_OFFSET 10
+#define IPC_HEADER_MNG_CMD_OFFSET 16
+
+#define IPC_HEADER_GET_LENGTH(drbl_reg) \
+ (((drbl_reg) >> IPC_HEADER_LENGTH_OFFSET)&IPC_HEADER_LENGTH_MASK)
+#define IPC_HEADER_GET_PROTOCOL(drbl_reg) \
+ (((drbl_reg) >> IPC_HEADER_PROTOCOL_OFFSET)&IPC_HEADER_PROTOCOL_MASK)
+#define IPC_HEADER_GET_MNG_CMD(drbl_reg) \
+ (((drbl_reg) >> IPC_HEADER_MNG_CMD_OFFSET)&IPC_HEADER_MNG_CMD_MASK)
+
+#define IPC_IS_BUSY(drbl_reg) \
+ (((drbl_reg)&IPC_DRBL_BUSY_BIT) == ((uint32_t)IPC_DRBL_BUSY_BIT))
+
+/***********************************/
+/*CHV_A0, CHV_B0*/
+#define IPC_INT_FROM_ISH_TO_HOST_CHV_AB(drbl_reg) \
+ (((drbl_reg)&IPC_INT_ISH2HOST_BIT_CHV_AB) == \
+ ((u32)IPC_INT_ISH2HOST_BIT_CHV_AB))
+/*BXT, CHV_K0*/
+#define IPC_INT_FROM_ISH_TO_HOST_BXT(drbl_reg) \
+ (((drbl_reg)&IPC_INT_ISH2HOST_BIT_BXT) == \
+ ((u32)IPC_INT_ISH2HOST_BIT_BXT))
+/***********************************/
+
+#define IPC_BUILD_HEADER(length, protocol, busy) \
+ (((busy)<<IPC_DRBL_BUSY_OFFS) | \
+ ((protocol) << IPC_HEADER_PROTOCOL_OFFSET) | \
+ ((length)<<IPC_HEADER_LENGTH_OFFSET))
+
+#define IPC_BUILD_MNG_MSG(cmd, length) \
+ (((1)<<IPC_DRBL_BUSY_OFFS)| \
+ ((IPC_PROTOCOL_MNG)<<IPC_HEADER_PROTOCOL_OFFSET)| \
+ ((cmd)<<IPC_HEADER_MNG_CMD_OFFSET)|((length)<<IPC_HEADER_LENGTH_OFFSET))
+
+
+#define IPC_SET_HOST_READY(host_status) \
+ ((host_status) |= (IPC_HOSTCOMM_READY_BIT))
+
+#define IPC_SET_HOST_ILUP(host_status) \
+ ((host_status) |= (IPC_ILUP_BIT))
+
+#define IPC_CLEAR_HOST_READY(host_status) \
+ ((host_status) ^= (IPC_HOSTCOMM_READY_BIT))
+
+#define IPC_CLEAR_HOST_ILUP(host_status) \
+ ((host_status) ^= (IPC_ILUP_BIT))
+
+/* todo - temp until PIMR HW ready */
+#define IPC_HOST_BUSY_READING_OFFS 6
+
+/* bit corresponds host ready bit in Host Status Register (HOST_COMM) */
+#define IPC_HOST_BUSY_READING_BIT (1<<IPC_HOST_BUSY_READING_OFFS)
+
+#define IPC_SET_HOST_BUSY_READING(host_status) \
+ ((host_status) |= (IPC_HOST_BUSY_READING_BIT))
+
+#define IPC_CLEAR_HOST_BUSY_READING(host_status)\
+ ((host_status) ^= (IPC_HOST_BUSY_READING_BIT))
+
+
+#define IPC_IS_ISH_ISHTP_READY(ish_status) \
+ (((ish_status) & IPC_ISH_ISHTP_READY_BIT) == \
+ ((uint32_t)IPC_ISH_ISHTP_READY_BIT))
+
+#define IPC_IS_ISH_ILUP(ish_status) \
+ (((ish_status) & IPC_ILUP_BIT) == ((uint32_t)IPC_ILUP_BIT))
+
+
+#define IPC_PROTOCOL_ISHTP 1
+#define IPC_PROTOCOL_MNG 3
+
+#define MNG_RX_CMPL_ENABLE 0
+#define MNG_RX_CMPL_DISABLE 1
+#define MNG_RX_CMPL_INDICATION 2
+#define MNG_RESET_NOTIFY 3
+#define MNG_RESET_NOTIFY_ACK 4
+#define MNG_SYNC_FW_CLOCK 5
+#define MNG_ILLEGAL_CMD 0xFF
+
+#endif /* _ISHTP_ISH_REGS_H_ */
+
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
new file mode 100644
index 0000000..21c3c5d3
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -0,0 +1,71 @@
+/*
+ * H/W layer of ISHTP provider device (ISH)
+ *
+ * Copyright (c) 2014-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _ISHTP_HW_ISH_H_
+#define _ISHTP_HW_ISH_H_
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include "hw-ish-regs.h"
+#include "ishtp-dev.h"
+
+#define CHV_DEVICE_ID 0x22D8
+#define BXT_Ax_DEVICE_ID 0x0AA2
+#define BXT_Bx_DEVICE_ID 0x1AA2
+#define BXTP_Ax_DEVICE_ID 0x5AA2
+#define SPT_Ax_DEVICE_ID 0x9D35
+
+#define REVISION_ID_CHT_A0 0x6
+#define REVISION_ID_CHT_Ax_SI 0x0
+#define REVISION_ID_CHT_Bx_SI 0x10
+#define REVISION_ID_CHT_Kx_SI 0x20
+#define REVISION_ID_CHT_Dx_SI 0x30
+#define REVISION_ID_CHT_B0 0xB0
+#define REVISION_ID_SI_MASK 0x70
+
+struct ipc_rst_payload_type {
+ uint16_t reset_id;
+ uint16_t reserved;
+};
+
+struct time_sync_format {
+ uint8_t ts1_source;
+ uint8_t ts2_source;
+ uint16_t reserved;
+} __packed;
+
+struct ipc_time_update_msg {
+ uint64_t primary_host_time;
+ struct time_sync_format sync_info;
+ uint64_t secondary_host_time;
+} __packed;
+
+enum {
+ HOST_UTC_TIME_USEC = 0,
+ HOST_SYSTEM_TIME_USEC = 1
+};
+
+struct ish_hw {
+ void __iomem *mem_addr;
+};
+
+#define to_ish_hw(dev) (struct ish_hw *)((dev)->hw)
+
+irqreturn_t ish_irq_handler(int irq, void *dev_id);
+struct ishtp_device *ish_dev_init(struct pci_dev *pdev);
+int ish_hw_start(struct ishtp_device *dev);
+
+#endif /* _ISHTP_HW_ISH_H_ */
+
diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c
new file mode 100644
index 0000000..fdc242a
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/ipc.c
@@ -0,0 +1,710 @@
+/*
+ * H/W layer of ISHTP provider device (ISH)
+ *
+ * Copyright (c) 2014-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include "client.h"
+#include "hw-ish.h"
+#include "utils.h"
+#include "hbm.h"
+
+/* For FW reset flow */
+static struct work_struct fw_reset_work;
+static struct ishtp_device *ishtp_dev;
+
+/* ish_reg_read - reads 32bit register */
+static inline uint32_t ish_reg_read(const struct ishtp_device *dev,
+ unsigned long offset)
+{
+ struct ish_hw *hw = to_ish_hw(dev);
+
+ return readl(hw->mem_addr + offset);
+}
+
+/* ish_reg_write - writes 32bit register */
+static inline void ish_reg_write(struct ishtp_device *dev, unsigned long offset,
+ uint32_t value)
+{
+ struct ish_hw *hw = to_ish_hw(dev);
+
+ writel(value, hw->mem_addr + offset);
+}
+
+static inline uint32_t _ish_read_fw_sts_reg(struct ishtp_device *dev)
+{
+ return ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
+}
+
+bool check_generated_interrupt(struct ishtp_device *dev)
+{
+ bool interrupt_generated = true;
+ uint32_t pisr_val = 0;
+
+ if (dev->pdev->device == CHV_DEVICE_ID) {
+ pisr_val = ish_reg_read(dev, IPC_REG_PISR_CHV_AB);
+ interrupt_generated = IPC_INT_FROM_ISH_TO_HOST_CHV_AB(pisr_val);
+ } else {
+ pisr_val = ish_reg_read(dev, IPC_REG_PISR_BXT);
+ interrupt_generated = IPC_INT_FROM_ISH_TO_HOST_BXT(pisr_val);
+ }
+
+ return interrupt_generated;
+}
+
+/* ish_is_input_ready - check if ISH FW is ready for receiving data */
+static bool ish_is_input_ready(struct ishtp_device *dev)
+{
+ uint32_t doorbell_val;
+
+ doorbell_val = ish_reg_read(dev, IPC_REG_HOST2ISH_DRBL);
+ return !IPC_IS_BUSY(doorbell_val);
+}
+
+/* set_host_ready - set host ready indication to FW */
+void set_host_ready(struct ishtp_device *dev)
+{
+ if (dev->pdev->device == CHV_DEVICE_ID) {
+ if (dev->pdev->revision == REVISION_ID_CHT_A0 ||
+ (dev->pdev->revision & REVISION_ID_SI_MASK) ==
+ REVISION_ID_CHT_Ax_SI)
+ ish_reg_write(dev, IPC_REG_HOST_COMM, 0x81);
+ else if (dev->pdev->revision == REVISION_ID_CHT_B0 ||
+ (dev->pdev->revision & REVISION_ID_SI_MASK) ==
+ REVISION_ID_CHT_Bx_SI ||
+ (dev->pdev->revision & REVISION_ID_SI_MASK) ==
+ REVISION_ID_CHT_Kx_SI ||
+ (dev->pdev->revision & REVISION_ID_SI_MASK) ==
+ REVISION_ID_CHT_Dx_SI) {
+ uint32_t host_comm_val;
+
+ host_comm_val = ish_reg_read(dev, IPC_REG_HOST_COMM);
+ host_comm_val |= IPC_HOSTCOMM_INT_EN_BIT_CHV_AB | 0x81;
+ ish_reg_write(dev, IPC_REG_HOST_COMM, host_comm_val);
+ }
+ } else {
+ uint32_t host_pimr_val;
+
+ host_pimr_val = ish_reg_read(dev, IPC_REG_PIMR_BXT);
+ host_pimr_val |= IPC_PIMR_INT_EN_BIT_BXT;
+ /*
+ * disable interrupt generated instead of
+ * RX_complete_msg
+ */
+ host_pimr_val &= ~IPC_HOST2ISH_BUSYCLEAR_MASK_BIT;
+
+ ish_reg_write(dev, IPC_REG_PIMR_BXT, host_pimr_val);
+ }
+}
+
+/* ishtp_fw_is_ready - check if the hw is ready */
+static bool ishtp_fw_is_ready(struct ishtp_device *dev)
+{
+ uint32_t ish_status = _ish_read_fw_sts_reg(dev);
+
+ return IPC_IS_ISH_ILUP(ish_status) &&
+ IPC_IS_ISH_ISHTP_READY(ish_status);
+}
+
+/* Indicate to FW that the host is ready */
+static void ish_set_host_rdy(struct ishtp_device *dev)
+{
+ uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM);
+
+ IPC_SET_HOST_READY(host_status);
+ ish_reg_write(dev, IPC_REG_HOST_COMM, host_status);
+}
+
+void ish_clr_host_rdy(struct ishtp_device *dev)
+{
+ uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM);
+
+ IPC_CLEAR_HOST_READY(host_status);
+ ish_reg_write(dev, IPC_REG_HOST_COMM, host_status);
+}
+
+/* _ish_read_hdr - reads hdr of 32 bit length. */
+static uint32_t _ishtp_read_hdr(const struct ishtp_device *dev)
+{
+ return ish_reg_read(dev, IPC_REG_ISH2HOST_MSG);
+}
+
+/* ish_read - reads a message from ishtp device. */
+static int _ishtp_read(struct ishtp_device *dev, unsigned char *buffer,
+ unsigned long buffer_length)
+{
+ uint32_t i;
+ uint32_t *r_buf = (uint32_t *)buffer;
+ uint32_t msg_offs;
+
+ msg_offs = IPC_REG_ISH2HOST_MSG + sizeof(struct ishtp_msg_hdr);
+ for (i = 0; i < buffer_length; i += sizeof(uint32_t))
+ *r_buf++ = ish_reg_read(dev, msg_offs + i);
+
+ return 0;
+}
+
+/**
+ * write_ipc_from_queue() - try to write ipc msg from Tx queue to device
+ * @dev: ishtp device pointer
+ *
+ * Check if DRBL is cleared. if it is - write the first IPC msg, then call
+ * the callback function (unless it's NULL)
+ */
+int write_ipc_from_queue(struct ishtp_device *dev)
+{
+ struct wr_msg_ctl_info *ipc_link;
+ unsigned long length;
+ unsigned long rem;
+ unsigned long flags;
+ uint32_t doorbell_val;
+ uint32_t *r_buf;
+ uint32_t reg_addr;
+ int i;
+ void (*ipc_send_compl)(void *);
+ void *ipc_send_compl_prm;
+ static int out_ipc_locked;
+ unsigned long out_ipc_flags;
+
+ if (dev->dev_state == ISHTP_DEV_DISABLED)
+ return -EINVAL;
+
+ spin_lock_irqsave(&dev->out_ipc_spinlock, out_ipc_flags);
+ if (out_ipc_locked) {
+ spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags);
+ return -EBUSY;
+ }
+ out_ipc_locked = 1;
+ if (!ish_is_input_ready(dev)) {
+ out_ipc_locked = 0;
+ spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags);
+ return -EBUSY;
+ }
+ spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags);
+
+ spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
+ /*
+ * if tx send list is empty - return 0;
+ * may happen, as RX_COMPLETE handler doesn't check list emptiness.
+ */
+ if (list_empty(&dev->wr_processing_list_head.link)) {
+ spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
+ out_ipc_locked = 0;
+ return 0;
+ }
+
+ ipc_link = list_entry(dev->wr_processing_list_head.link.next,
+ struct wr_msg_ctl_info, link);
+ /* first 4 bytes of the data is the doorbell value (IPC header) */
+ length = ipc_link->length - sizeof(uint32_t);
+ doorbell_val = *(uint32_t *)ipc_link->inline_data;
+ r_buf = (uint32_t *)(ipc_link->inline_data + sizeof(uint32_t));
+
+ /* If sending MNG_SYNC_FW_CLOCK, update clock again */
+ if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
+ IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) {
+ struct timespec ts_system;
+ struct timeval tv_utc;
+ uint64_t usec_system, usec_utc;
+ struct ipc_time_update_msg time_update;
+ struct time_sync_format ts_format;
+
+ get_monotonic_boottime(&ts_system);
+ do_gettimeofday(&tv_utc);
+ usec_system = (timespec_to_ns(&ts_system)) / NSEC_PER_USEC;
+ usec_utc = (uint64_t)tv_utc.tv_sec * 1000000 +
+ ((uint32_t)tv_utc.tv_usec);
+ ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
+ ts_format.ts2_source = HOST_UTC_TIME_USEC;
+
+ time_update.primary_host_time = usec_system;
+ time_update.secondary_host_time = usec_utc;
+ time_update.sync_info = ts_format;
+
+ memcpy(r_buf, &time_update, sizeof(struct ipc_time_update_msg));
+ }
+
+ for (i = 0, reg_addr = IPC_REG_HOST2ISH_MSG; i < length >> 2; i++,
+ reg_addr += 4)
+ ish_reg_write(dev, reg_addr, r_buf[i]);
+
+ rem = length & 0x3;
+ if (rem > 0) {
+ uint32_t reg = 0;
+
+ memcpy(&reg, &r_buf[length >> 2], rem);
+ ish_reg_write(dev, reg_addr, reg);
+ }
+ /* Flush writes to msg registers and doorbell */
+ ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
+
+ /* Update IPC counters */
+ ++dev->ipc_tx_cnt;
+ dev->ipc_tx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val);
+
+ ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, doorbell_val);
+ out_ipc_locked = 0;
+
+ ipc_send_compl = ipc_link->ipc_send_compl;
+ ipc_send_compl_prm = ipc_link->ipc_send_compl_prm;
+ list_del_init(&ipc_link->link);
+ list_add_tail(&ipc_link->link, &dev->wr_free_list_head.link);
+ spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
+
+ /*
+ * callback will be called out of spinlock,
+ * after ipc_link returned to free list
+ */
+ if (ipc_send_compl)
+ ipc_send_compl(ipc_send_compl_prm);
+
+ return 0;
+}
+
+/**
+ * write_ipc_to_queue() - write ipc msg to Tx queue
+ * @dev: ishtp device instance
+ * @ipc_send_compl: Send complete callback
+ * @ipc_send_compl_prm: Parameter to send in complete callback
+ * @msg: Pointer to message
+ * @length: Length of message
+ *
+ * Recived msg with IPC (and upper protocol) header and add it to the device
+ * Tx-to-write list then try to send the first IPC waiting msg
+ * (if DRBL is cleared)
+ * This function returns negative value for failure (means free list
+ * is empty, or msg too long) and 0 for success.
+ */
+static int write_ipc_to_queue(struct ishtp_device *dev,
+ void (*ipc_send_compl)(void *), void *ipc_send_compl_prm,
+ unsigned char *msg, int length)
+{
+ struct wr_msg_ctl_info *ipc_link;
+ unsigned long flags;
+
+ if (length > IPC_FULL_MSG_SIZE)
+ return -EMSGSIZE;
+
+ spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
+ if (list_empty(&dev->wr_free_list_head.link)) {
+ spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
+ return -ENOMEM;
+ }
+ ipc_link = list_entry(dev->wr_free_list_head.link.next,
+ struct wr_msg_ctl_info, link);
+ list_del_init(&ipc_link->link);
+
+ ipc_link->ipc_send_compl = ipc_send_compl;
+ ipc_link->ipc_send_compl_prm = ipc_send_compl_prm;
+ ipc_link->length = length;
+ memcpy(ipc_link->inline_data, msg, length);
+
+ list_add_tail(&ipc_link->link, &dev->wr_processing_list_head.link);
+ spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
+
+ write_ipc_from_queue(dev);
+
+ return 0;
+}
+
+/* Send a bus management message */
+static int ipc_send_mng_msg(struct ishtp_device *dev, uint32_t msg_code,
+ void *msg, size_t size)
+{
+ unsigned char ipc_msg[IPC_FULL_MSG_SIZE];
+ uint32_t drbl_val = IPC_BUILD_MNG_MSG(msg_code, size);
+
+ memcpy(ipc_msg, &drbl_val, sizeof(uint32_t));
+ memcpy(ipc_msg + sizeof(uint32_t), msg, size);
+ return write_ipc_to_queue(dev, NULL, NULL, ipc_msg,
+ sizeof(uint32_t) + size);
+}
+
+static int ish_fw_reset_handler(struct ishtp_device *dev)
+{
+ uint32_t reset_id;
+ unsigned long flags;
+ struct wr_msg_ctl_info *processing, *next;
+
+ /* Read reset ID */
+ reset_id = ish_reg_read(dev, IPC_REG_ISH2HOST_MSG) & 0xFFFF;
+
+ /* Clear IPC output queue */
+ spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
+ list_for_each_entry_safe(processing, next,
+ &dev->wr_processing_list_head.link, link) {
+ list_del(&processing->link);
+ list_add_tail(&processing->link, &dev->wr_free_list_head.link);
+ }
+ spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
+
+ /* ISHTP notification in IPC_RESET */
+ ishtp_reset_handler(dev);
+
+ if (!ish_is_input_ready(dev))
+ timed_wait_for_timeout(WAIT_FOR_SEND_SLICE,
+ ish_is_input_ready(dev), (2 * HZ));
+
+ /* ISH FW is dead */
+ if (!ish_is_input_ready(dev))
+ return -EPIPE;
+ /*
+ * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending
+ * RESET_NOTIFY_ACK - FW will be checking for it
+ */
+ ish_set_host_rdy(dev);
+ /* Send RESET_NOTIFY_ACK (with reset_id) */
+ ipc_send_mng_msg(dev, MNG_RESET_NOTIFY_ACK, &reset_id,
+ sizeof(uint32_t));
+
+ /* Wait for ISH FW'es ILUP and ISHTP_READY */
+ timed_wait_for_timeout(WAIT_FOR_SEND_SLICE, ishtp_fw_is_ready(dev),
+ (2 * HZ));
+ if (!ishtp_fw_is_ready(dev)) {
+ /* ISH FW is dead */
+ uint32_t ish_status;
+
+ ish_status = _ish_read_fw_sts_reg(dev);
+ dev_err(dev->devc,
+ "[ishtp-ish]: completed reset, ISH is dead "
+ "(FWSTS = %08X)\n",
+ ish_status);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void fw_reset_work_fn(struct work_struct *unused)
+{
+ int rv;
+
+ rv = ish_fw_reset_handler(ishtp_dev);
+ if (!rv) {
+ /* ISH is ILUP & ISHTP-ready. Restart ISHTP */
+ schedule_timeout(HZ / 3);
+ ishtp_dev->recvd_hw_ready = 1;
+ wake_up(&ishtp_dev->wait_hw_ready);
+
+ /* ISHTP notification in IPC_RESET sequence completion */
+ ishtp_reset_compl_handler(ishtp_dev);
+ } else
+ dev_err(ishtp_dev->devc, "[ishtp-ish]: FW reset failed (%d)\n",
+ rv);
+}
+
+static void _ish_sync_fw_clock(struct ishtp_device *dev)
+{
+ static unsigned long prev_sync;
+ struct timespec ts;
+ uint64_t usec;
+
+ if (prev_sync && jiffies - prev_sync < 20 * HZ)
+ return;
+
+ prev_sync = jiffies;
+ get_monotonic_boottime(&ts);
+ usec = (timespec_to_ns(&ts)) / NSEC_PER_USEC;
+ ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t));
+}
+
+/*
+ * recv_ipc() - Receive and process IPC management messages
+ * @dev: ishtp device instance
+ * @doorbell_val: doorbell value
+ *
+ * This function runs in ISR context.
+ * NOTE: Any other mng command than reset_notify and reset_notify_ack
+ * won't wake BH handler
+ */
+static void recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val)
+{
+ uint32_t mng_cmd;
+
+ mng_cmd = IPC_HEADER_GET_MNG_CMD(doorbell_val);
+
+ switch (mng_cmd) {
+ default:
+ break;
+
+ case MNG_RX_CMPL_INDICATION:
+ if (dev->suspend_flag) {
+ dev->suspend_flag = 0;
+ wake_up(&dev->suspend_wait);
+ }
+ write_ipc_from_queue(dev);
+ break;
+
+ case MNG_RESET_NOTIFY:
+ if (!ishtp_dev) {
+ ishtp_dev = dev;
+ INIT_WORK(&fw_reset_work, fw_reset_work_fn);
+ }
+ schedule_work(&fw_reset_work);
+ break;
+
+ case MNG_RESET_NOTIFY_ACK:
+ dev->recvd_hw_ready = 1;
+ wake_up(&dev->wait_hw_ready);
+ break;
+ }
+}
+
+/* ish_irq_handler - ISR of the ISHTP device */
+irqreturn_t ish_irq_handler(int irq, void *dev_id)
+{
+ struct ishtp_device *dev = dev_id;
+ uint32_t doorbell_val;
+ bool interrupt_generated;
+
+ /* Check that it's interrupt from ISH (may be shared) */
+ interrupt_generated = check_generated_interrupt(dev);
+
+ if (!interrupt_generated)
+ return IRQ_NONE;
+
+ doorbell_val = ish_reg_read(dev, IPC_REG_ISH2HOST_DRBL);
+ if (!IPC_IS_BUSY(doorbell_val))
+ return IRQ_HANDLED;
+
+ if (dev->dev_state == ISHTP_DEV_DISABLED)
+ return IRQ_HANDLED;
+
+ /* Sanity check: IPC dgram length in header */
+ if (IPC_HEADER_GET_LENGTH(doorbell_val) > IPC_PAYLOAD_SIZE) {
+ dev_err(dev->devc,
+ "IPC hdr - bad length: %u; dropped\n",
+ (unsigned int)IPC_HEADER_GET_LENGTH(doorbell_val));
+ goto eoi;
+ }
+
+ switch (IPC_HEADER_GET_PROTOCOL(doorbell_val)) {
+ default:
+ break;
+ case IPC_PROTOCOL_MNG:
+ recv_ipc(dev, doorbell_val);
+ break;
+ case IPC_PROTOCOL_ISHTP:
+ ishtp_recv(dev);
+ break;
+ }
+
+eoi:
+ /* Update IPC counters */
+ ++dev->ipc_rx_cnt;
+ dev->ipc_rx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val);
+
+ ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0);
+ /* Flush write to doorbell */
+ ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
+
+ return IRQ_HANDLED;
+}
+
+static int _ish_hw_reset(struct ishtp_device *dev)
+{
+ struct pci_dev *pdev = dev->pdev;
+ int rv;
+ unsigned int dma_delay;
+ uint16_t csr;
+
+ if (!pdev)
+ return -ENODEV;
+
+ rv = pci_reset_function(pdev);
+ if (!rv)
+ dev->dev_state = ISHTP_DEV_RESETTING;
+
+ if (!pdev->pm_cap) {
+ dev_err(&pdev->dev, "Can't reset - no PM caps\n");
+ return -EINVAL;
+ }
+
+ /* Now trigger reset to FW */
+ ish_reg_write(dev, IPC_REG_ISH_RMP2, 0);
+
+ for (dma_delay = 0; dma_delay < MAX_DMA_DELAY &&
+ _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA);
+ dma_delay += 5)
+ mdelay(5);
+
+ if (dma_delay >= MAX_DMA_DELAY) {
+ dev_err(&pdev->dev,
+ "Can't reset - stuck with DMA in-progress\n");
+ return -EBUSY;
+ }
+
+ pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &csr);
+
+ csr &= ~PCI_PM_CTRL_STATE_MASK;
+ csr |= PCI_D3hot;
+ pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr);
+
+ mdelay(pdev->d3_delay);
+
+ csr &= ~PCI_PM_CTRL_STATE_MASK;
+ csr |= PCI_D0;
+ pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr);
+
+ ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED);
+
+ /*
+ * Send 0 IPC message so that ISH FW wakes up if it was already
+ * asleep
+ */
+ ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT);
+
+ /* Flush writes to doorbell and REMAP2 */
+ ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
+
+ return 0;
+}
+
+/* _ish_ipc_reset - resets host and fw IPC and upper layers. */
+static int _ish_ipc_reset(struct ishtp_device *dev)
+{
+ struct ipc_rst_payload_type ipc_mng_msg;
+ int rv = 0;
+
+ ipc_mng_msg.reset_id = 1;
+ ipc_mng_msg.reserved = 0;
+
+ set_host_ready(dev);
+
+ /* Clear the incoming doorbell */
+ ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0);
+ /* Flush write to doorbell */
+ ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
+
+ dev->recvd_hw_ready = 0;
+
+ /* send message */
+ rv = ipc_send_mng_msg(dev, MNG_RESET_NOTIFY, &ipc_mng_msg,
+ sizeof(struct ipc_rst_payload_type));
+ if (rv) {
+ dev_err(dev->devc, "Failed to send IPC MNG_RESET_NOTIFY\n");
+ return rv;
+ }
+
+ wait_event_timeout(dev->wait_hw_ready, dev->recvd_hw_ready, 2 * HZ);
+ if (!dev->recvd_hw_ready) {
+ dev_err(dev->devc, "Timed out waiting for HW ready\n");
+ rv = -ENODEV;
+ }
+
+ return rv;
+}
+
+int ish_hw_start(struct ishtp_device *dev)
+{
+ ish_set_host_rdy(dev);
+ /* After that we can enable ISH DMA operation */
+ ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED);
+
+ /*
+ * Send 0 IPC message so that ISH FW wakes up if it was already
+ * asleep
+ */
+ ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT);
+ /* Flush write to doorbell */
+ ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
+
+ set_host_ready(dev);
+
+ /* wait for FW-initiated reset flow */
+ if (!dev->recvd_hw_ready)
+ wait_event_timeout(dev->wait_hw_ready, dev->recvd_hw_ready,
+ 10 * HZ);
+
+ if (!dev->recvd_hw_ready) {
+ dev_err(dev->devc,
+ "[ishtp-ish]: Timed out waiting for "
+ "FW-initiated reset\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static uint32_t ish_ipc_get_header(struct ishtp_device *dev, int length,
+ int busy)
+{
+ uint32_t drbl_val;
+
+ drbl_val = IPC_BUILD_HEADER(length, IPC_PROTOCOL_ISHTP, busy);
+
+ return drbl_val;
+}
+
+static const struct ishtp_hw_ops ish_hw_ops = {
+ .hw_reset = _ish_hw_reset,
+ .ipc_reset = _ish_ipc_reset,
+ .ipc_get_header = ish_ipc_get_header,
+ .ishtp_read = _ishtp_read,
+ .write = write_ipc_to_queue,
+ .get_fw_status = _ish_read_fw_sts_reg,
+ .sync_fw_clock = _ish_sync_fw_clock,
+ .ishtp_read_hdr = _ishtp_read_hdr
+};
+
+struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
+{
+ struct ishtp_device *dev;
+ int i;
+
+ dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw),
+ GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ ishtp_device_init(dev);
+
+ init_waitqueue_head(&dev->wait_hw_ready);
+
+ spin_lock_init(&dev->wr_processing_spinlock);
+ spin_lock_init(&dev->out_ipc_spinlock);
+
+ /* Init IPC processing and free lists */
+ INIT_LIST_HEAD(&dev->wr_processing_list_head.link);
+ INIT_LIST_HEAD(&dev->wr_free_list_head.link);
+ for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) {
+ struct wr_msg_ctl_info *tx_buf;
+
+ tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL);
+ if (!tx_buf) {
+ /*
+ * IPC buffers may be limited or not available
+ * at all - although this shouldn't happen
+ */
+ dev_err(dev->devc,
+ "[ishtp-ish]: failure in Tx FIFO "
+ "allocations (%d)\n", i);
+ break;
+ }
+ list_add_tail(&tx_buf->link, &dev->wr_free_list_head.link);
+ }
+
+ dev->ops = &ish_hw_ops;
+ dev->devc = &pdev->dev;
+ dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr);
+ return dev;
+}
+
+void ishtp_device_disable(struct ishtp_device *dev)
+{
+ dev->dev_state = ISHTP_DEV_DISABLED;
+ ish_clr_host_rdy(dev);
+ kfree(dev->fw_clients);
+}
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
new file mode 100644
index 0000000..e4d00d2
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -0,0 +1,238 @@
+/*
+ * PCI glue for ISHTP provider device (ISH) driver
+ *
+ * Copyright (c) 2014-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/miscdevice.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/intel_ish.h>
+#include "ishtp-dev.h"
+#include "hw-ish.h"
+
+static const struct pci_device_id ish_pci_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CHV_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Ax_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Bx_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXTP_Ax_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)},
+ {0, }
+};
+MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
+
+static void ish_event_tracer(struct ishtp_device *dev, char *format, ...)
+{
+ if (trace_ishtp_dump_enabled()) {
+ va_list args;
+ char tmp_buf[100];
+
+ va_start(args, format);
+ vsnprintf(tmp_buf, sizeof(tmp_buf), format, args);
+ va_end(args);
+
+ trace_ishtp_dump(tmp_buf);
+ }
+}
+
+static int ish_init(struct ishtp_device *dev)
+{
+ int ret;
+
+ dev_set_drvdata(dev->devc, dev);
+
+ init_waitqueue_head(&dev->suspend_wait);
+
+ /* Register ishtp bus */
+ ret = ishtp_cl_bus_init();
+ if (ret) {
+ dev_err(dev->devc, "ISH: Init hw failed.\n");
+ return ret;
+ }
+
+ /* Set the state of ISH HW to start */
+ ret = ish_hw_start(dev);
+ if (ret) {
+ dev_err(dev->devc, "ISH: Init hw failed.\n");
+ goto bus_unreg;
+ }
+
+ /* Start the inter process communication to ISH processor */
+ ret = ishtp_start(dev);
+ if (ret) {
+ dev_err(dev->devc, "ISHTP: Protocol init failed.\n");
+ goto bus_unreg;
+ }
+
+ return 0;
+
+bus_unreg:
+ ishtp_cl_bus_exit();
+
+ return ret;
+}
+
+static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct ishtp_device *dev;
+ struct ish_hw *hw;
+ int ret;
+
+ /* enable pci dev */
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "ISH: Failed to enable PCI device\n");
+ return ret;
+ }
+
+ /* set PCI host mastering */
+ pci_set_master(pdev);
+
+ /* pci request regions for ISH driver */
+ ret = pci_request_regions(pdev, KBUILD_MODNAME);
+ if (ret) {
+ dev_err(&pdev->dev, "ISH: Failed to get PCI regions\n");
+ goto disable_device;
+ }
+
+ /* allocates and initializes the ISH dev structure */
+ dev = ish_dev_init(pdev);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto release_regions;
+ }
+ hw = to_ish_hw(dev);
+ dev->print_log = ish_event_tracer;
+
+ /* mapping IO device memory */
+ hw->mem_addr = pci_iomap(pdev, 0, 0);
+ if (!hw->mem_addr) {
+ dev_err(&pdev->dev, "ISH: mapping I/O range failure\n");
+ ret = -ENOMEM;
+ goto free_device;
+ }
+
+ dev->pdev = pdev;
+
+ /*
+ * PCI quirk: prevent from being put into D3 state. ISH has internal
+ * power management logic to transition to low power state based
+ * on the usage. So no explicit action is required to change the
+ * state to D3.
+ */
+ pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
+
+
+ /* request and enable interrupt */
+ ret = request_irq(pdev->irq, ish_irq_handler, IRQF_NO_SUSPEND,
+ KBUILD_MODNAME, dev);
+ if (ret) {
+ dev_err(&pdev->dev, "ISH: request IRQ failure (%d)\n",
+ pdev->irq);
+ goto free_device;
+ }
+
+ ret = ish_init(dev);
+ if (ret)
+ goto free_device;
+
+ return 0;
+
+free_device:
+ pci_iounmap(pdev, hw->mem_addr);
+ kfree(dev);
+release_regions:
+ pci_release_regions(pdev);
+disable_device:
+ pci_disable_device(pdev);
+ dev_err(&pdev->dev, "ISH: PCI driver initialization failed.\n");
+
+ return ret;
+}
+
+static int ish_suspend(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct ishtp_device *dev = pci_get_drvdata(pdev);
+
+ enable_irq_wake(pdev->irq);
+ /*
+ * If previous suspend hasn't been asnwered then ISH is likely dead,
+ * don't attempt nested notification
+ */
+ if (dev->suspend_flag)
+ return 0;
+
+ dev->suspend_flag = 1;
+ ishtp_send_suspend(dev);
+
+ /* 25 ms should be enough for live ISH to flush all IPC buf */
+ if (dev->suspend_flag)
+ wait_event_timeout(dev->suspend_wait, !dev->suspend_flag,
+ msecs_to_jiffies(25));
+
+ return 0;
+}
+
+static int ish_resume(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct ishtp_device *dev = pci_get_drvdata(pdev);
+
+ disable_irq_wake(pdev->irq);
+ ishtp_send_resume(dev);
+ dev->suspend_flag = 0;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops ish_pm_ops = {
+ .suspend = ish_suspend,
+ .resume = ish_resume,
+};
+#define ISHTP_ISH_PM_OPS (&ish_pm_ops)
+#else
+#define ISHTP_ISH_PM_OPS NULL
+#endif
+
+static struct pci_driver ish_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = ish_pci_tbl,
+ .probe = ish_probe,
+ .driver.pm = ISHTP_ISH_PM_OPS,
+};
+
+static int __init ish_driver_init(void)
+{
+ return pci_register_driver(&ish_driver);
+}
+device_initcall(ish_driver_init);
+
+/* Primary author */
+MODULE_AUTHOR("Daniel Drubin <daniel...@intel.com>");
+/* Adoption to upstream Linux kernel */
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas....@linux.intel.com>");
+
+MODULE_DESCRIPTION("Intel(R) Integrated Sensor Hub PCI Device Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/hid/intel-ish-hid/ipc/utils.h b/drivers/hid/intel-ish-hid/ipc/utils.h
new file mode 100644
index 0000000..cc646de
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/utils.h
@@ -0,0 +1,65 @@
+/*
+ * Utility macros of ISH
+ *
+ * Copyright (c) 2014-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+#ifndef UTILS__H
+#define UTILS__H
+
+#define WAIT_FOR_SEND_SLICE (HZ / 10)
+#define WAIT_FOR_CONNECT_SLICE (HZ / 10)
+
+/*
+ * Waits for specified event when a thread that triggers event can't signal
+ * Also, waits *at_least* `timeinc` after condition is satisfied
+ */
+#define timed_wait_for(timeinc, condition) \
+ do { \
+ int completed = 0; \
+ do { \
+ unsigned long j; \
+ int done = 0; \
+ \
+ completed = (condition); \
+ for (j = jiffies, done = 0; !done; ) { \
+ schedule_timeout(timeinc); \
+ if (time_is_before_eq_jiffies(j + timeinc)) \
+ done = 1; \
+ } \
+ } while (!(completed)); \
+ } while (0)
+
+
+/*
+ * Waits for specified event when a thread that triggers event
+ * can't signal with timeout (use whenever we may hang)
+ */
+#define timed_wait_for_timeout(timeinc, condition, timeout) \
+ do { \
+ int t = timeout; \
+ do { \
+ unsigned long j; \
+ int done = 0; \
+ \
+ for (j = jiffies, done = 0; !done; ) { \
+ schedule_timeout(timeinc); \
+ if (time_is_before_eq_jiffies(j + timeinc)) \
+ done = 1; \
+ } \
+ t -= timeinc; \
+ if (t <= 0) \
+ break; \
+ } while (!(condition)); \
+ } while (0)
+
+#endif /* UTILS__H */
+
diff --git a/include/trace/events/intel_ish.h b/include/trace/events/intel_ish.h
new file mode 100644
index 0000000..92f7d5b
--- /dev/null
+++ b/include/trace/events/intel_ish.h
@@ -0,0 +1,30 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_ish
+
+#if !defined(_TRACE_INTEL_ISH_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_INTEL_ISH_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ishtp_dump,
+
+ TP_PROTO(const char *message),
+
+ TP_ARGS(message),
+
+ TP_STRUCT__entry(
+ __string(message, message)
+ ),
+
+ TP_fast_assign(
+ __assign_str(message, message);
+ ),
+
+ TP_printk("%s", __get_str(message))
+);
+
+
+#endif /* _TRACE_INTEL_ISH_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--
1.9.1

Srinivas Pandruvada

unread,
May 31, 2016, 12:40:05 AM5/31/16
to
Document explaining ISH HID operation and implementation.

Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
---
Documentation/hid/intel-ish-hid.txt | 375 ++++++++++++++++++++++++++++++++++++
1 file changed, 375 insertions(+)
create mode 100644 Documentation/hid/intel-ish-hid.txt

diff --git a/Documentation/hid/intel-ish-hid.txt b/Documentation/hid/intel-ish-hid.txt
new file mode 100644
index 0000000..83a636e
--- /dev/null
+++ b/Documentation/hid/intel-ish-hid.txt
@@ -0,0 +1,375 @@
+Intel Integrated Sensor Hub (ISH)
+===============================
+
+A sensor hub enables the ability to offload sensor polling and algorithm
+processing to a dedicated low power co-processor. This allows the core
+processor to go into low power modes more often, resulting in the increased
+battery life.
+There are many vendors providing external sensor hubs confirming to HID
+Sensor usage tables, and used in several tablets, 2 in 1 convertible laptops
+and embedded products. Linux had this support since Linux 3.9.
+
+Intel® introduced integrated sensor hubs as a part of the SoC starting from
+Cherry Trail and now supported on multiple generations of CPU packages. There
+are many commercial devices already shipped with Integrated Sensor Hubs (ISH).
+These ISH also comply to HID sensor specification, but the difference is the
+transport protocol used for communication. The current external sensor hubs
+mainly use HID over i2C or USB. But ISH doesn't use either i2c or USB.
+
+This document provides an overview of transport protocol and how it is
+implemented.
+
+
+ISH Implementation: Block Diagram
+----------------------------------------
+ ---------------------------
+ | User Space Applications |
+ ---------------------------
+
+----------------IIO ABI----------------
+ --------------------------
+ | IIO Sensor Drivers |
+ --------------------------
+ --------------------------
+ | IIO core |
+ --------------------------
+ --------------------------
+ | HID Sensor Hub MFD |
+ --------------------------
+ --------------------------
+ | HID Core |
+ --------------------------
+ --------------------------
+ | HID over ISH Client |
+ --------------------------
+ --------------------------
+ | ISH Client over ISHTP |
+ --------------------------
+ --------------------------
+ | ISH Transport (ISHTP) |
+ --------------------------
+ --------------------------
+ | IPC Drivers |
+ --------------------------
+OS
+---------------- PCI -----------------
+Hardware + Firmware
+ ----------------------------
+ | ISH Hardware/Firmware(FW) |
+ ----------------------------
+
+------------------------------------------
+
+High level processing in above blocks:
+
+---
+Hardware Interface
+The ISH is exposed as "Non-VGA unclassified PCI device" to the host. The PCI
+product and vendor IDs are changed from different generations of processors. So
+the source code which enumerate drivers needs to update from generation to
+generation.
+
+---
+Inter Processor Communication (IPC) driver:
+Location: drivers/hid/intel-ish-hid/ipc
+
+The IPC message used memory mapped I/O. The registers are defined in
+hw-ish-regs.h.
+
+IPC/FW message types
+There are two types of messages, one for management of link and other messages
+are to and from transport layers.
+
+TX and RX of Transport messages:
+A set of memory mapped register offers support of multi byte messages TX and
+RX (E.g.IPC_REG_ISH2HOST_MSG, IPC_REG_HOST2ISH_MSG). The messaging uses
+doorbell register to trigger processing on client and server side.
+The IPC layer maintains internal queues to sequence messages and send them in
+order to the FW. Optionally the caller can register handler to get notification
+of completion.
+
+Transport layer interface
+To abstract HW level IPC communication a set of callbacks are registered.
+The transport layer uses them to send and receive messages.
+Refer to struct ishtp_hw_ops for callbacks.
+
+---
+ISH Transport layer
+Location: drivers/hid/intel-ish-hid/ishtp/
+
+A Generic Transport Layer
+The transport layer is a bi-directional protocol, which defines:
+- Set of commands to start, stop, connect, disconnect and flow control
+(ishtp/hbm.h) for details
+- A flow control mechanism to avoid buffer overflows
+
+This protocol resembles bus messages described in the following document:
+http://www.intel.com/content/dam/www/public/us/en/documents/technical-\
+specifications/dcmi-hi-1-0-spec.pdf
+Chater 7: Bus Message Layer
+
+DMA
+The transport layer allocate 1 MB TX and 1 MB RX buffer. This buffer is divided
+into slots of 4K buffer. This buffer is shared among all connected clients.
+So when a message is to be sent or received by a client, it finds an empty
+slot and either fill for TX or send DMA address to FW for RX.
+By default all RX messages uses DMA as there is more upstream data for sensors
+than downstream. For TX client send interface has flag to send via DMA, which
+is not set by default as there is less TX data other setting some feature
+reports by HID sensor hub driver.
+
+Ring Buffers
+When a client initiate a connection, a ring or RX and TX buffers are allocated.
+The size of ring can be specified by the client. HID client set 16 and 32 for
+TX and RX buffers respectively. On send request from client, the data to be
+sent is copied to one of the send ring buffer and scheduled to be sent using
+bus message protocol. These buffers are required because the FW may have not
+processed last message and may not have enough flow control credits to send.
+Same thing holds true on receive side and flow control is required.
+
+Host Enumeration
+The host enumeration bus command allow discovery of clients present in
+the FW. There can be multiple sensor clients and clients for calibration
+function.
+To ease in implantation and allow independent driver handle each client
+this transport layer takes advantage of Linux Bus driver model. Each
+client is registered as device on the the transport bus (ishtp bus).
+
+ISH Client over generic transport layer
+The ISH client defines interface to send and receive HID style command
+and responses. Refer to ishtp-hid.h.
+These commands are for"
+- Get HID descriptor
+- Get report descriptor
+- Get/Set feature report
+- Get input reports
+
+---
+HID over ISH Client
+Location: drivers/hid/intel-ish-hid
+
+This implanted as ISHTP client driver, which
+- enumerate HID devices under FW ISH client
+- Get Report descriptor
+- Register with HID core as a LL driver
+- Process Get/Set feature request
+- Get input reports
+
+----
+HID Sensor Hub MFD and IIO sensor drivers
+
+The functionality in these drivers is the same as an external sensor hub.
+These drivers don't require changes to handle ISH other than some
+optimizations.
+----
+
+========================================================================================
+End to End Startup HID transport Sequence Diagram
+
+HID-ISH-CLN ISHTP IPC HW
+ | | | |
+ | | |-----WAKE UP------------------>|
+ | | | |
+ | | |-----HOST READY--------------->|
+ | | | |
+ | | |<----MNG_RESET_NOTIFY_ACK----- |
+ | | | |
+ | |<----ISHTP_START------ | |
+ | | | |
+ | |<-----------------HOST_START_RES_CMD-------------------|
+ | | | |
+ | |------------------QUERY_SUBSCRIBER-------------------->|
+ | | | |
+ | |------------------HOST_ENUM_REQ_CMD------------------->|
+ | | | |
+ | |<-----------------HOST_ENUM_RES_CMD--------------------|
+ | | | |
+ | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>|
+ | | | |
+ | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------|
+ | Create new device on in ishtp bus | |
+ | | | |
+ | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>|
+ | | | |
+ | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------|
+ | Create new device on in ishtp bus | |
+ | | | |
+ | |--Repeat HOST_CLIENT_PROPERTIES_REQ_CMD-till last one--|
+ | | | |
+ probed()
+ |----ishtp_cl_connect-->|----------------- CLIENT_CONNECT_REQ_CMD-------------->|
+ | | | |
+ | |<----------------CLIENT_CONNECT_RES_CMD----------------|
+ | | | |
+ |register event callback| | |
+ | | | |
+ |ishtp_cl_send(
+ HOSTIF_DM_ENUM_DEVICES) |----------fill ishtp_msg_hdr struct write to HW----- >|
+ | | | |
+ | | |<-----IRQ(IPC_PROTOCOL_ISHTP---|
+ | | | |
+ | |<------------ DMA_XFER---------------------------------|
+ |<--ENUM_DEVICE RSP-----| | |
+ | |------------ DMA_XFER_ACK----------------------------->|
+ | | | |
+for each enumerated device
+ |ishtp_cl_send(
+ HOSTIF_GET_HID_DESCRIPTOR |----------fill ishtp_msg_hdr struct write to HW--- >|
+ | | | |
+ ...Response
+ | | | |
+for each enumerated device
+ |ishtp_cl_send(
+ HOSTIF_GET_REPORT_DESCRIPTOR |----------fill ishtp_msg_hdr struct write to HW- >|
+ | | | |
+ | | | |
+ hid_allocate_device
+ | | | |
+ hid_add_device | | |
+ | | | |
+
+
+========================================================================================
+ISH Debugging
+
+To debug ISH, event tracing mechanism is used. To enable debug logs
+echo 1 > /sys/kernel/debug/tracing/events/intel_ish/enable
+cat sys/kernel/debug/tracing/trace
+
+========================================================================================
+ISH IIO sysfs Example on Lenovo thinkpad Yoga 260
+
+root@otcpl-ThinkPad-Yoga-260:~# tree -l /sys/bus/iio/devices/
+/sys/bus/iio/devices/
+├── iio:device0 -> ../../../devices/0044:8086:22D8.0001/HID-SENSOR-200073.9.auto/iio:device0
+│   ├── buffer
+│   │   ├── enable
+│   │   ├── length
+│   │   └── watermark
+...
+│   ├── in_accel_hysteresis
+│   ├── in_accel_offset
+│   ├── in_accel_sampling_frequency
+│   ├── in_accel_scale
+│   ├── in_accel_x_raw
+│   ├── in_accel_y_raw
+│   ├── in_accel_z_raw
+│   ├── name
+│   ├── scan_elements
+│   │   ├── in_accel_x_en
+│   │   ├── in_accel_x_index
+│   │   ├── in_accel_x_type
+│   │   ├── in_accel_y_en
+│   │   ├── in_accel_y_index
+│   │   ├── in_accel_y_type
+│   │   ├── in_accel_z_en
+│   │   ├── in_accel_z_index
+│   │   └── in_accel_z_type
+...
+│   │   ├── devices
+│   │   │   │   ├── buffer
+│   │   │   │   │   ├── enable
+│   │   │   │   │   ├── length
+│   │   │   │   │   └── watermark
+│   │   │   │   ├── dev
+│   │   │   │   ├── in_intensity_both_raw
+│   │   │   │   ├── in_intensity_hysteresis
+│   │   │   │   ├── in_intensity_offset
+│   │   │   │   ├── in_intensity_sampling_frequency
+│   │   │   │   ├── in_intensity_scale
+│   │   │   │   ├── name
+│   │   │   │   ├── scan_elements
+│   │   │   │   │   ├── in_intensity_both_en
+│   │   │   │   │   ├── in_intensity_both_index
+│   │   │   │   │   └── in_intensity_both_type
+│   │   │   │   ├── trigger
+│   │   │   │   │   └── current_trigger
+...
+│   │   │   │   ├── buffer
+│   │   │   │   │   ├── enable
+│   │   │   │   │   ├── length
+│   │   │   │   │   └── watermark
+│   │   │   │   ├── dev
+│   │   │   │   ├── in_magn_hysteresis
+│   │   │   │   ├── in_magn_offset
+│   │   │   │   ├── in_magn_sampling_frequency
+│   │   │   │   ├── in_magn_scale
+│   │   │   │   ├── in_magn_x_raw
+│   │   │   │   ├── in_magn_y_raw
+│   │   │   │   ├── in_magn_z_raw
+│   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_raw
+│   │   │   │   ├── in_rot_hysteresis
+│   │   │   │   ├── in_rot_offset
+│   │   │   │   ├── in_rot_sampling_frequency
+│   │   │   │   ├── in_rot_scale
+│   │   │   │   ├── name
+...
+│   │   │   │   ├── scan_elements
+│   │   │   │   │   ├── in_magn_x_en
+│   │   │   │   │   ├── in_magn_x_index
+│   │   │   │   │   ├── in_magn_x_type
+│   │   │   │   │   ├── in_magn_y_en
+│   │   │   │   │   ├── in_magn_y_index
+│   │   │   │   │   ├── in_magn_y_type
+│   │   │   │   │   ├── in_magn_z_en
+│   │   │   │   │   ├── in_magn_z_index
+│   │   │   │   │   ├── in_magn_z_type
+│   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_en
+│   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_index
+│   │   │   │   │   └── in_rot_from_north_magnetic_tilt_comp_type
+│   │   │   │   ├── trigger
+│   │   │   │   │   └── current_trigger
+...
+│   │   │   │   ├── buffer
+│   │   │   │   │   ├── enable
+│   │   │   │   │   ├── length
+│   │   │   │   │   └── watermark
+│   │   │   │   ├── dev
+│   │   │   │   ├── in_anglvel_hysteresis
+│   │   │   │   ├── in_anglvel_offset
+│   │   │   │   ├── in_anglvel_sampling_frequency
+│   │   │   │   ├── in_anglvel_scale
+│   │   │   │   ├── in_anglvel_x_raw
+│   │   │   │   ├── in_anglvel_y_raw
+│   │   │   │   ├── in_anglvel_z_raw
+│   │   │   │   ├── name
+│   │   │   │   ├── scan_elements
+│   │   │   │   │   ├── in_anglvel_x_en
+│   │   │   │   │   ├── in_anglvel_x_index
+│   │   │   │   │   ├── in_anglvel_x_type
+│   │   │   │   │   ├── in_anglvel_y_en
+│   │   │   │   │   ├── in_anglvel_y_index
+│   │   │   │   │   ├── in_anglvel_y_type
+│   │   │   │   │   ├── in_anglvel_z_en
+│   │   │   │   │   ├── in_anglvel_z_index
+│   │   │   │   │   └── in_anglvel_z_type
+│   │   │   │   ├── trigger
+│   │   │   │   │   └── current_trigger
+...
+│   │   │   │   ├── buffer
+│   │   │   │   │   ├── enable
+│   │   │   │   │   ├── length
+│   │   │   │   │   └── watermark
+│   │   │   │   ├── dev
+│   │   │   │   ├── in_anglvel_hysteresis
+│   │   │   │   ├── in_anglvel_offset
+│   │   │   │   ├── in_anglvel_sampling_frequency
+│   │   │   │   ├── in_anglvel_scale
+│   │   │   │   ├── in_anglvel_x_raw
+│   │   │   │   ├── in_anglvel_y_raw
+│   │   │   │   ├── in_anglvel_z_raw
+│   │   │   │   ├── name
+│   │   │   │   ├── scan_elements
+│   │   │   │   │   ├── in_anglvel_x_en
+│   │   │   │   │   ├── in_anglvel_x_index
+│   │   │   │   │   ├── in_anglvel_x_type
+│   │   │   │   │   ├── in_anglvel_y_en
+│   │   │   │   │   ├── in_anglvel_y_index
+│   │   │   │   │   ├── in_anglvel_y_type
+│   │   │   │   │   ├── in_anglvel_z_en
+│   │   │   │   │   ├── in_anglvel_z_index
+│   │   │   │   │   └── in_anglvel_z_type
+│   │   │   │   ├── trigger
+│   │   │   │   │   └── current_trigger
+...
+
--
1.9.1

Atri Bhattacharya

unread,
Jun 1, 2016, 9:50:08 AM6/1/16
to
Hi!
Thanks a lot for adding support for this. I have a Lenovo Thinkpad Yoga
260, so I decided to give it a try. I used your patches on kernel 4.6.0
and installed the patched kernel. Now, I see that the device is
recognised immediately. I use the iio-sensor-proxy application from
[1], and it now recognises the sensors. But changing orientation
doesn't seem to do anything, and moreover upon a wakeup from suspend I
see the following messages on the journal:

Jun 01 15:15:09 tp-yoga260 kernel: [drm] RC6 on
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0001:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0001:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0001:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0001:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0001:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0001:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0001:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0001:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0002:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0002:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0002:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: hid-sensor-hub 0044:8086:22D8.0002:
timeout waiting for response from ISHTP device
Jun 01 15:15:09 tp-yoga260 kernel: PM: resume of devices complete after
37095.288 msecs

Also suspend and wakeup seems to be really slow now. Please let me know
if there is any other info I can provide.

Thanks and best wishes.

[1] https://github.com/hadess/iio-sensor-proxy

--
Atri Bhattacharya
Wed 1 Jun 15:22:32 CEST 2016

Sent from openSUSE Tumbleweed (20160529) (x86_64) on my laptop.

m...@danielturton.net

unread,
Jun 2, 2016, 11:10:06 AM6/2/16
to
Hello,

My thanks to you and your team for releasing this patch to get the sensor
hubs up and running on Linux machines.

I've compiled a new kernel with the patches you've provided, but it appears
that it's not being detected just yet. I have a Thinkpad 460 Yoga that I'm
testing on.

From the compile log for the custom kernel:

  CC      drivers/hid/intel-ish-hid/ipc/pci-ish.o
  CC      fs/proc/vmcore.o
  CC [M]  net/netfilter/xt_TCPOPTSTRIP.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.o
  CC      drivers/hid/intel-ish-hid/ishtp-hid.o
  CC [M]  net/rds/connection.o
  CC [M]  net/netfilter/xt_TEE.o
  CC      fs/proc/kmsg.o
  CC      drivers/hid/intel-ish-hid/ishtp-hid-client.o
  CC      fs/proc/page.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.o

  LD      drivers/hid/intel-ish-hid/intel-ishtp.o
  LD      drivers/hid/intel-ish-hid/intel-ish-ipc.o
  LD      drivers/hid/intel-ish-hid/intel-ishtp-hid.o
  LD      drivers/hid/intel-ish-hid/built-in.o
  LD      drivers/hid/usbhid/built-in.o
  CC [M]  drivers/hid/usbhid/hid-core.o

  LD      fs/proc/proc.o
  LD      fs/proc/built-in.o
  CC      fs/pstore/inode.o
  CC [M]  net/netfilter/xt_TRACE.o
  CC [M]  drivers/gpu/drm/amd/amdgpu/cz_smc.o
  CC [M]  net/rds/info.o
  CC [M]  net/netfilter/xt_IDLETIMER.o
  CC      fs/pstore/platform.o
  CC [M]  drivers/hid/usbhid/hid-quirks.o

From lspci -vvvnn:

00:13.0 Non-VGA unclassified device [0000]: Intel Corporation Device
[8086:9d35] (rev 21)
        Subsystem: Lenovo Device [17aa:504c]
        Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop-
ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
<TAbort- <MAbort- >SERR- <PERR- INTx-
        Interrupt: pin A routed to IRQ 255
        Region 0: Memory at d564b000 (64-bit, non-prefetchable)
[disabled] [size=4K]
        Capabilities: [80] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA
PME(D0-,D1-,D2-,D3hot-,D3cold-)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0
PME-

not much mention from dmesg unfortunately when checking for the hardware
id:

[    0.453834] pci 0000:00:13.0: [8086:9d35] type 00 class 0x000000
[    0.453853] pci 0000:00:13.0: reg 0x10: [mem 0xd564b000-0xd564bfff
64bit]

Please let me know what other information I can provide to help narrow the
issue down, or if there's something that I may be doing incorrectly.

Thanks!

Daniel Turton

Grant Likely

unread,
Jun 9, 2016, 5:50:10 PM6/9/16
to
On Tue, May 31, 2016 at 5:27 AM, Srinivas Pandruvada
<srinivas....@linux.intel.com> wrote:
> Starting from Cherrytrail, multiple generation of Intel processors offers
> on package sensor hub. Several recent tablets, 2-in-1 convertible laptops
> are using ISH instead of external sensor hubs. This resulted in lack of
> support of sensor function like device rotation and auto backlight
> adjustment. In addition, depending on the OEM implementation, support of ISH
> is required to support low power sleep states.
>
> The support of ISH on Linux platforms is not new. Android platforms with
> Intel SoCs had this support for a while submitted by Daniel Drubin.
> This patcheset is reusing most of those changes with clean up and
> removing Android platform specific changes.

Hi Srinivas,

Thanks for this patch series. I've got an HP Spectre x360 G2
(skylake), and I've built a 4.6.0 kernel with this driver patched in.
It detects the sensors hub, and creates IIO devices under
/sys/bus/iio/devices:

$ ls /sys/bus/iio/devices/
iio:device0 iio:device1 iio:device2 iio:device3 iio:device4
iio:device5 iio:device6 iio:device7 iio:device8 iio:device9
trigger0 trigger1 trigger2 trigger3 trigger4 trigger5 trigger6
trigger7 trigger8 trigger9

However, I haven't figured out how to test it yet. (This is the first
time I'm working with IIO). Do you have any test code or test
procedures to show if it is working?

Thanks,
g.

Srinivas Pandruvada

unread,
Jun 9, 2016, 6:00:09 PM6/9/16
to
Hi,
If you use Fedora 23 (or any distro with iio-sensor-proxy with gnome
rotation stuff), you should be able to do screen rotation and
brightness using ALS.
Each of these folders should have some raw sysfs files 
in_xxx_raw_xx

You should be able to use "cat" on them.

Thanks,
Srinivas

Grant Likely

unread,
Jun 10, 2016, 5:50:04 AM6/10/16
to
Yes, I do see the in_*_raw_* files in sysfs, and I'm able to get data
out of them. Gnome also seems to recognize that the accelerometers are
there because it adds a rotation lock button to the system menu.

However, the events are getting through yet. It may be that I'm
missing something in my kernel config. I'm rebuilding the kernel with
Debian's config for the 4.5.5 kernel as a quick sanity test. I'll
report back when I've tried.

I'll also take some time and review the patch series later this afternoon.

g.

Srinivas Pandruvada

unread,
Jun 10, 2016, 10:00:06 AM6/10/16
to
On Fri, 2016-06-10 at 10:44 +0100, Grant Likely wrote:
[...]
>
> Yes, I do see the in_*_raw_* files in sysfs, and I'm able to get data
> out of them. Gnome also seems to recognize that the accelerometers
> are
> there because it adds a rotation lock button to the system menu.
>
> However, the events are getting through yet. It may be that I'm
> missing something in my kernel config. I'm rebuilding the kernel with
> Debian's config for the 4.5.5 kernel as a quick sanity test. I'll
> report back when I've tried.
>
You need to add in /usr/lib/system/systemd/iio-sensor-*

After=multi-user.target


This service starts too early.

> I'll also take some time and review the patch series later this
> afternoon.

Atri Bhattacharya reported issues with suspend/resume. With my test
patches it is fixed for him

If you want to hold on, I will repost with fixes for susend/resume.

Thanks,
Srinivas

Grant Likely

unread,
Jun 10, 2016, 10:10:07 AM6/10/16
to
Still no joy here on getting wired up to Gnome. The sensors exist, and
I can view the output. For example, the following shell command will
give a live view of the accelerometer settings:

while true; clear; do { for f in iio\:device*/in_accel*raw; do echo $f
`cat $f`; done }; sleep 0.25s; done

In "Laptop mode":
iio:device1/in_accel_x_raw 2184
iio:device1/in_accel_y_raw -968620
iio:device1/in_accel_z_raw -224273
iio:device3/in_accel_x_raw 5784
iio:device3/in_accel_y_raw -946324
iio:device3/in_accel_z_raw -218647

When rotated clockwise 90 degrees:
iio:device1/in_accel_x_raw 1013843
iio:device1/in_accel_y_raw 8523
iio:device1/in_accel_z_raw -12259
iio:device3/in_accel_x_raw 1012352
iio:device3/in_accel_y_raw 14487
iio:device3/in_accel_z_raw -6891

When lying flat:
iio:device1/in_accel_x_raw 6995
iio:device1/in_accel_y_raw -32824
iio:device1/in_accel_z_raw -986080
iio:device3/in_accel_x_raw 5797
iio:device3/in_accel_y_raw -31402
iio:device3/in_accel_z_raw -984732

However, Gnome isn't picking up the rotation events. I don't know
where in the stack things are falling down. I do have iio-sensor-proxy
running. Any hints on debugging this?

Yet, some stuff is working now. The keyboard (but not the trackpad)
gets disabled when folded back in tablet mode.

g.

Bastien Nocera

unread,
Jun 10, 2016, 10:30:05 AM6/10/16
to
On Fri, 2016-06-10 at 06:55 -0700, Srinivas Pandruvada wrote:
> On Fri, 2016-06-10 at 10:44 +0100, Grant Likely wrote:
> [...]
> >
> > Yes, I do see the in_*_raw_* files in sysfs, and I'm able to get
> > data
> > out of them. Gnome also seems to recognize that the accelerometers
> > are
> > there because it adds a rotation lock button to the system menu.
> >
> > However, the events are getting through yet. It may be that I'm
> > missing something in my kernel config. I'm rebuilding the kernel
> > with
> > Debian's config for the 4.5.5 kernel as a quick sanity test. I'll
> > report back when I've tried.
> >
> You need to add in /usr/lib/system/systemd/iio-sensor-*
>
> After=multi-user.target
>
>
> This service starts too early.

Nobody has been able to explain to me why that would be a problem.

Can you back this up with some data? Does iio-sensor-proxy exit too
early? Does that leave time to the IIO sub-system to do some init work
it should already have done?

See also https://github.com/hadess/iio-sensor-proxy/issues/82

Srinivas Pandruvada

unread,
Jun 10, 2016, 10:50:04 AM6/10/16
to
On Fri, 2016-06-10 at 16:26 +0200, Bastien Nocera wrote:
> On Fri, 2016-06-10 at 06:55 -0700, Srinivas Pandruvada wrote:
> > On Fri, 2016-06-10 at 10:44 +0100, Grant Likely wrote:
> > [...]
> > >
> > > Yes, I do see the in_*_raw_* files in sysfs, and I'm able to get
> > > data
> > > out of them. Gnome also seems to recognize that the
> > > accelerometers
> > > are
> > > there because it adds a rotation lock button to the system menu.
> > >
> > > However, the events are getting through yet. It may be that I'm
> > > missing something in my kernel config. I'm rebuilding the kernel
> > > with
> > > Debian's config for the 4.5.5 kernel as a quick sanity test. I'll
> > > report back when I've tried.
> > >
> > You need to add in /usr/lib/system/systemd/iio-sensor-*
> >
> > After=multi-user.target
> >
> >
> > This service starts too early.
>
> Nobody has been able to explain to me why that would be a problem.
>
> Can you back this up with some data? Does iio-sensor-proxy exit too
> early? Does that leave time to the IIO sub-system to do some init
> work
> it should already have done?
The driver's  trigger callback doesn't even get called to take any
action or provide any data. So to get called need to restart the
service or do suspend/resume.
After=multi-user.target, is not the ideal solution as it is too late.
So need further debug.

Bastien Nocera

unread,
Jun 10, 2016, 11:10:04 AM6/10/16
to
Are there any errors when setting the triggers?

The code there is probably a bit naive, but I'd rather fix that rather
than postpone the start of the daemon.

> After=multi-user.target, is not the ideal solution as it is too late.
> So need further debug.
>
> >
> > See also https://github.com/hadess/iio-sensor-proxy/issues/82
> >
> > > > I'll also take some time and review the patch series later this
> > > > afternoon.
> > >
> > > Atri Bhattacharya reported issues with suspend/resume. With my
> > > test
> > > patches it is fixed for him
> > >
> > > If you want to hold on, I will repost with fixes for
> > > susend/resume.
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> input" in
> the body of a message to majo...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Bastien Nocera

unread,
Jun 10, 2016, 11:30:05 AM6/10/16
to
On Fri, 2016-06-10 at 08:23 -0700, Srinivas Pandruvada wrote:
> On Fri, 2016-06-10 at 17:04 +0200, Bastien Nocera wrote:
> > >
>
> [...]
>
> > Are there any errors when setting the triggers?
> >
> Is there any debug option in this service to give more verbose
> output?

Add:
Environment="G_MESSAGES_DEBUG=all"

To the service file. You should see the debug in systemctl:
systemctl status iio-sensor-proxy.service

Or in journalctl if there's too much data:
journalctl --reverse -u iio-sensor-proxy.service

Cheers

Srinivas Pandruvada

unread,
Jun 10, 2016, 11:30:08 AM6/10/16
to
On Fri, 2016-06-10 at 17:04 +0200, Bastien Nocera wrote:
> >

[...]

> Are there any errors when setting the triggers?
>
Is there any debug option in this service to give more verbose output?


> The code there is probably a bit naive, but I'd rather fix that
> rather
> than postpone the start of the daemon.
Agree, we shouldn't postpone. 

Thanks,
Srinivas

Srinivas Pandruvada

unread,
Jun 11, 2016, 8:20:05 AM6/11/16
to
Need enum quirk to change the base of enums to 1 for
power and report descriptors.

Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
---
drivers/hid/hid-sensor-hub.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 3d5ba5b..658a607 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -16,6 +16,7 @@
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
+
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
@@ -798,6 +799,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
USB_DEVICE_ID_ITE_LENOVO_YOGA900),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_0,
+ 0x22D8),
+ .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
HID_ANY_ID) },
{ }
--
2.5.5

Srinivas Pandruvada

unread,
Jun 11, 2016, 8:20:05 AM6/11/16
to
Starting from Cherrytrail, multiple generation of Intel processors offers
on package sensor hub. Several recent tablets, 2-in-1 convertible laptops
are using ISH instead of external sensor hubs. This resulted in lack of
support of sensor function like device rotation and auto backlight
adjustment.
In addition, depending on the OEM implementation, support of ISH is required
to support low power sleep states.

The support of ISH on Linux platforms is not new. Android platforms with
Intel SoCs had this support for a while submitted by Daniel Drubin.
This patcheset is reusing most of those changes with clean up and
removing Android platform specific changes.

The user mode ABI is still same as external sensor hubs using Linux
IIO. So existing user mode software should still work.
This series primarily brings in new HID transport used in ISH.

Thanks to the community members who tested RFC patches and provided
feedback.

For users testing on Linux distributions using IIO sensor proxy,
a short term work around is required till we have debugged this issue.
In systemd unit file iio-sensor-proxy.service
In the section "[Unit]" add
After=multi-user.target

Daniel Drubin (3):
hid: intel_ish-hid: ISH Transport layer
hid: intel-ish-hid: ipc layer
hid: intel-ish-hid: ISH HID client driver

Srinivas Pandruvada (3):
Documentation: hid: Intel ISH HID document
iio: hid-sensors: use asynchronous resume
hid: hid-sensor-hub: Add ISH quirk

Documentation/hid/intel-ish-hid.txt | 417 ++++++++
drivers/hid/Kconfig | 2 +
drivers/hid/Makefile | 2 +
drivers/hid/hid-sensor-hub.c | 4 +
drivers/hid/intel-ish-hid/Kconfig | 27 +
drivers/hid/intel-ish-hid/Makefile | 20 +
drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h | 220 ++++
drivers/hid/intel-ish-hid/ipc/hw-ish.h | 70 ++
drivers/hid/intel-ish-hid/ipc/ipc.c | 720 +++++++++++++
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 305 ++++++
drivers/hid/intel-ish-hid/ipc/utils.h | 64 ++
drivers/hid/intel-ish-hid/ishtp-hid-client.c | 922 ++++++++++++++++
drivers/hid/intel-ish-hid/ishtp-hid.c | 231 ++++
drivers/hid/intel-ish-hid/ishtp-hid.h | 182 ++++
drivers/hid/intel-ish-hid/ishtp/bus.c | 774 ++++++++++++++
drivers/hid/intel-ish-hid/ishtp/bus.h | 105 ++
drivers/hid/intel-ish-hid/ishtp/client.c | 1129 ++++++++++++++++++++
drivers/hid/intel-ish-hid/ishtp/client.h | 194 ++++
drivers/hid/intel-ish-hid/ishtp/dma-if.c | 178 +++
drivers/hid/intel-ish-hid/ishtp/hbm.c | 911 ++++++++++++++++
drivers/hid/intel-ish-hid/ishtp/hbm.h | 319 ++++++
drivers/hid/intel-ish-hid/ishtp/init.c | 94 ++
drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h | 280 +++++
.../iio/common/hid-sensors/hid-sensor-trigger.c | 21 +-
include/linux/hid-sensor-hub.h | 1 +
include/trace/events/intel_ish.h | 30 +
include/uapi/linux/input.h | 1 +
27 files changed, 7222 insertions(+), 1 deletion(-)
create mode 100644 Documentation/hid/intel-ish-hid.txt
create mode 100644 drivers/hid/intel-ish-hid/Kconfig
create mode 100644 drivers/hid/intel-ish-hid/Makefile
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/ipc.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/pci-ish.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/utils.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid-client.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/bus.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/bus.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/client.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/client.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/dma-if.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/hbm.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/hbm.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/init.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
create mode 100644 include/trace/events/intel_ish.h

--
2.5.5

Srinivas Pandruvada

unread,
Jun 11, 2016, 8:20:05 AM6/11/16
to
From: Daniel Drubin <daniel...@intel.com>

This layer is responsible for
- Enumerating over PCI bus
- Inform FW about host readiness
- Provide HW interface to transport layer for control and messages
- Interrupt handling and routing

Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
---
drivers/hid/intel-ish-hid/Kconfig | 5 +
drivers/hid/intel-ish-hid/Makefile | 6 +
drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h | 220 +++++++++
drivers/hid/intel-ish-hid/ipc/hw-ish.h | 70 +++
drivers/hid/intel-ish-hid/ipc/ipc.c | 720 ++++++++++++++++++++++++++++
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 305 ++++++++++++
drivers/hid/intel-ish-hid/ipc/utils.h | 64 +++
include/trace/events/intel_ish.h | 30 ++
8 files changed, 1420 insertions(+)
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/ipc.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/pci-ish.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/utils.h
new file mode 100644
index 0000000..ab68afc
+ ((cmd)<<IPC_HEADER_MNG_CMD_OFFSET)| \
+ ((length)<<IPC_HEADER_LENGTH_OFFSET))
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
new file mode 100644
index 0000000..02f68ad
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -0,0 +1,70 @@
diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c
new file mode 100644
index 0000000..dd5df4b
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/ipc.c
@@ -0,0 +1,720 @@
+ unsigned long offset,
+ uint32_t value)
+{
+ struct ish_hw *hw = to_ish_hw(dev);
+
+ writel(value, hw->mem_addr + offset);
+}
+
+static inline uint32_t _ish_read_fw_sts_reg(struct ishtp_device *dev)
+{
+ return ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
+}
+
+bool check_generated_interrupt(struct ishtp_device *dev)
+{
+ bool interrupt_generated = true;
+ uint32_t pisr_val = 0;
+
+ if (dev->pdev->device == CHV_DEVICE_ID) {
+ pisr_val = ish_reg_read(dev, IPC_REG_PISR_CHV_AB);
+ interrupt_generated =
+ IPC_INT_FROM_ISH_TO_HOST_CHV_AB(pisr_val);
+ sizeof(struct ipc_time_update_msg));
+ wake_up_interruptible(&ishtp_dev->wait_hw_ready);
+ wake_up_interruptible(&dev->suspend_wait);
+ }
+ if (dev->resume_flag) {
+ dev->resume_flag = 0;
+ wake_up_interruptible(&dev->resume_wait);
+ }
+
+ write_ipc_from_queue(dev);
+ break;
+
+ case MNG_RESET_NOTIFY:
+ if (!ishtp_dev) {
+ ishtp_dev = dev;
+ INIT_WORK(&fw_reset_work, fw_reset_work_fn);
+ }
+ schedule_work(&fw_reset_work);
+ break;
+
+ case MNG_RESET_NOTIFY_ACK:
+ dev->recvd_hw_ready = 1;
+ wake_up_interruptible(&dev->wait_hw_ready);
+ wait_event_interruptible_timeout(dev->wait_hw_ready,
+ dev->recvd_hw_ready, 2 * HZ);
+ wait_event_interruptible_timeout(dev->wait_hw_ready,
+ dev->recvd_hw_ready,
new file mode 100644
index 0000000..e737992
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -0,0 +1,305 @@
+/**
+ * ish_event_tracer() - Callback function to dump trace messages
+ *
+ * @dev: ishtp device
+ * @format: printf style format
+ *
+ * Callback to direct log messages to Linux trace buffers
+ */
+static void ish_event_tracer(struct ishtp_device *dev, char *format, ...)
+{
+ if (trace_ishtp_dump_enabled()) {
+ va_list args;
+ char tmp_buf[100];
+
+ va_start(args, format);
+ vsnprintf(tmp_buf, sizeof(tmp_buf), format, args);
+ va_end(args);
+
+ trace_ishtp_dump(tmp_buf);
+ }
+}
+
+/**
+ * ish_init() - Init function
+ *
+ * @dev: ishtp device
+ *
+ * This function initialize wait queues for suspend/resume and call
+ * calls hadware initialization function. This will initiate
+ * startup sequence
+ */
+static int ish_init(struct ishtp_device *dev)
+{
+ int ret;
+
+ dev_set_drvdata(dev->devc, dev);
+
+ init_waitqueue_head(&dev->suspend_wait);
+ init_waitqueue_head(&dev->resume_wait);
+/**
+ * ish_probe() - PCI driver probe callback
+ *
+ * @pdev: pci device
+ * @ent: pci device id
+ *
+ * Initialize PCI function, setup interrupt and call for ISH initialization
+ */
+static struct device *ish_resume_device;
+
+/**
+ * ish_resume_handler() - Work function to complete resume
+ *
+ * @work: work struct
+ *
+ * The resume work function to complete resume function asynchronously.
+ * There are two types of platforms, one where ISH is not powered off,
+ * in that case a simple resume message is enough, others we need
+ * a reset sequence.
+ */
+static void ish_resume_handler(struct work_struct *work)
+{
+ struct pci_dev *pdev = to_pci_dev(ish_resume_device);
+ struct ishtp_device *dev = pci_get_drvdata(pdev);
+ int ret;
+
+ ishtp_send_resume(dev);
+
+ /* 50 ms to get resume response */
+ if (dev->resume_flag)
+ ret = wait_event_interruptible_timeout(dev->resume_wait,
+ !dev->resume_flag,
+ msecs_to_jiffies(50));
+
+ if (dev->resume_flag) {
+ ish_hw_reset(dev);
+ ish_ipc_reset(dev);
+ }
+}
+
+/**
+ * ish_suspend() - ISH suspend callback
+ *
+ * @device: device pointer
+ *
+ * ISH suspend callback
+ */
+static int ish_suspend(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct ishtp_device *dev = pci_get_drvdata(pdev);
+
+ enable_irq_wake(pdev->irq);
+ /*
+ * If previous suspend hasn't been asnwered then ISH is likely dead,
+ * don't attempt nested notification
+ */
+ if (dev->suspend_flag)
+ return 0;
+
+ dev->resume_flag = 0;
+ dev->suspend_flag = 1;
+ ishtp_send_suspend(dev);
+
+ /* 25 ms should be enough for live ISH to flush all IPC buf */
+ if (dev->suspend_flag)
+ wait_event_interruptible_timeout(dev->suspend_wait,
+ !dev->suspend_flag,
+ msecs_to_jiffies(25));
+
+ return 0;
+}
+
+static DECLARE_WORK(resume_work, ish_resume_handler);
+/**
+ * ish_resume() - ISH resume callback
+ *
+ * @device: device pointer
+ *
+ * ISH resume callback
+ */
+static int ish_resume(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct ishtp_device *dev = pci_get_drvdata(pdev);
+
+ ish_resume_device = device;
+ dev->resume_flag = 1;
+
+ disable_irq_wake(pdev->irq);
+ schedule_work(&resume_work);
diff --git a/drivers/hid/intel-ish-hid/ipc/utils.h b/drivers/hid/intel-ish-hid/ipc/utils.h
new file mode 100644
index 0000000..5a82123
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ipc/utils.h
@@ -0,0 +1,64 @@
diff --git a/include/trace/events/intel_ish.h b/include/trace/events/intel_ish.h
new file mode 100644
2.5.5

Srinivas Pandruvada

unread,
Jun 11, 2016, 8:20:06 AM6/11/16
to
Document explaining ISH HID operation and implementation.

Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
---
Documentation/hid/intel-ish-hid.txt | 417 ++++++++++++++++++++++++++++++++++++
1 file changed, 417 insertions(+)
create mode 100644 Documentation/hid/intel-ish-hid.txt

diff --git a/Documentation/hid/intel-ish-hid.txt b/Documentation/hid/intel-ish-hid.txt
new file mode 100644
index 0000000..2de0ab5
--- /dev/null
+++ b/Documentation/hid/intel-ish-hid.txt
@@ -0,0 +1,417 @@
+RX (E.g.IPC_REG_ISH2HOST_MSG, IPC_REG_HOST2ISH_MSG). The IPC layer maintains
+internal queues to sequence messages and send them in order to the FW.
+Optionally the caller can register handler to get notification of completion.
+A door bell mechanism is used in messaging to trigger processing in host and
+client firmware side. When ISH interrupt handler is called, the ISH2HOST
+doorbell register is used by host drivers to determine that the interrupt
+is for ISH.
+Each side has 32 32-bit message registers and a 32-bit doorbell. Doorbell
+register has the following format:
+Bits 0..6: fragment length (7 bits are used)
+Bits 10..13: encapsulated protocol
+Bits 16..19: management command (for IPC management protocol)
+Bit 31: doorbell trigger (signal H/W interrupt to the other side)
+Other bits are reserved, should be 0.
+
+Transport layer interface
+To abstract HW level IPC communication, a set of callbacks are registered.
+The transport layer uses them to send and receive messages.
+Refer to struct ishtp_hw_ops for callbacks.
+
+---
+ISH Transport layer
+Location: drivers/hid/intel-ish-hid/ishtp/
+
+A Generic Transport Layer
+The transport layer is a bi-directional protocol, which defines:
+- Set of commands to start, stop, connect, disconnect and flow control
+(ishtp/hbm.h) for details
+- A flow control mechanism to avoid buffer overflows
+
+This protocol resembles bus messages described in the following document:
+http://www.intel.com/content/dam/www/public/us/en/documents/technical-\
+specifications/dcmi-hi-1-0-spec.pdf
+Chater 7: Bus Message Layer
+
+Connection and Flow Control Mechanism
+Each FW client and a protocol is identified by an UUID. In order to communicate
+to a FW client, a connection must be established using connect request and
+response bus messages. If successful, a pair (host_client_id and fw_client_id)
+will identify the connection.
+Once connection is established, peers send each other flow control bus messages
+independently. Every peer may send a message only if it has received a
+flow-control credit before. Once it sent a message, it may not send another one
+before receiving the next FC credit.
+Either side can send disconnect request bus message to end communication. Also
+the link will be dropped if major FW reset occurs.
+
+Peer to Peer data transfer
+The host allocates TX and RX buffers. Each side (host and FW) manages its DMA
+transfer memory independently. When an ISHTP client from either host or FW side
+wants to send something, it decides whether to send over IPC or over DMA;
+for each transfer the decision is independent. The sending side sends DMA_XFER
+message when the message is in the respective host buffer (TX when host client
+sends, RX when FW client sends). The recipient of DMA message responds with
+DMA_XFER_ACK, indicating the sender that the memory region for that message
+may be reused.
+DMA initialization is started with host sending DMA_ALLOC_NOTIFY bus message
+(that includes RX buffer) and FW responds with DMA_ALLOC_NOTIFY_ACK.
+Additionally to DMA address communication, this sequence checks capabilities:
+if thw host doesn't support DMA, then it won't send DMA allocation, so FW can't
+send DMA; if FW doesn't support DMA then it won't respond with
+DMA_ALLOC_NOTIFY_ACK, in which case host will not use DMA transfers.
+Here ISH acts as busmaster DMA controller. Hence when host sends DMA_XFER,
+it's request to do host->ISH DMA transfer; when FW sends DMA_XFER, it means
+that it already did DMA and the message resides at host. Thus, DMA_XFER
+and DMA_XFER_ACK act as ownership indicators.
+At initial state all outgoing memory belongs to the sender (TX to host, RX to
+FW), DMA_XFER transfers ownership on the region that contains ISHTP message to
+the receiving side, DMA_XFER_ACK returns ownership to the sender. A sender
+needs not wait for previous DMA_XFER to be ack'ed, and may send another message
+as long as remaining continuous memory in its ownership is enough.
+In principle, multiple DMA_XFER and DMA_XFER_ACK messages may be sent at once
+(up to IPC MTU), thus allowing for interrupt throttling.
+Currently, ISH FW decides to send over DMA if ISHTP message is more than 3 IPC
+fragments and via IPC otherwise. Host right now never decides to send over DMA
+because at this time there is no streaming case for larger messages.
+
+Ring Buffers
+When a client initiate a connection, a ring or RX and TX buffers are allocated.
+The size of ring can be specified by the client. HID client set 16 and 32 for
+TX and RX buffers respectively. On send request from client, the data to be
+sent is copied to one of the send ring buffer and scheduled to be sent using
+bus message protocol. These buffers are required because the FW may have not
+processed last message and may not have enough flow control credits to send.
+Same thing holds true on receive side and flow control is required.
+
+Host Enumeration
+The host enumeration bus command allow discovery of clients present in
+the FW. There can be multiple sensor clients and clients for calibration
+function.
+To ease in implantation and allow independent driver handle each client
+this transport layer takes advantage of Linux Bus driver model. Each
+client is registered as device on the the transport bus (ishtp bus).
+Enumeration sequence of messages:
+- Host sends HOST_START_REQ_CMD, indicating that host ISHTP layer is up.
+- FW responds with HOST_START_RES_CMD
+- Host sends HOST_ENUM_REQ_CMD (enumerate FW clients)
+- FW responds with HOST_ENUM_RES_CMD that includes bitmap of available FW
+client IDs
+- For each FW ID found in that bitmap host sends
+HOST_CLIENT_PROPERTIES_REQ_CMD
+- FW responds with HOST_CLIENT_PROPERTIES_RES_CMD. Properties include UUID,
+max ISHTP message size, etc.
+- Once host received properties for that last discovered client, it considers
+ISHTP device fully functional (and allocates DMA buffers)
+
+---
+HID over ISH Client
+Location: drivers/hid/intel-ish-hid
+
+This implanted as ISHTP client driver, which
+- enumerate HID devices under FW ISH client
+- Get Report descriptor
+- Register with HID core as a LL driver
+- Process Get/Set feature request
+- Get input reports
+
+----
+HID Sensor Hub MFD and IIO sensor drivers
+
+The functionality in these drivers is the same as an external sensor hub.
+Refer to
+Documentation/hid/hid-sensor.txt for HID sensor
+Documentation/ABI/testing/sysfs-bus-iio for IIO ABIs to user space
+
+----
+
+========================================================================================
+End to End HID transport Sequence Diagram
--
2.5.5

Srinivas Pandruvada

unread,
Jun 11, 2016, 8:20:06 AM6/11/16
to
From: Daniel Drubin <daniel...@intel.com>

This driver is responsible for implementing ISH HID client, which
gets HID description and report. Once it has completely gets
report descriptors, it registers as a HID LL drivers. This implements
necessary callbacks so that it can be used by HID sensor hub driver.

Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
---
drivers/hid/intel-ish-hid/Makefile | 4 +
drivers/hid/intel-ish-hid/ishtp-hid-client.c | 922 +++++++++++++++++++++++++++
drivers/hid/intel-ish-hid/ishtp-hid.c | 231 +++++++
drivers/hid/intel-ish-hid/ishtp-hid.h | 182 ++++++
include/uapi/linux/input.h | 1 +
5 files changed, 1340 insertions(+)
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid-client.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.h

diff --git a/drivers/hid/intel-ish-hid/Makefile b/drivers/hid/intel-ish-hid/Makefile
index 2c83cb9..6727c66 100644
--- a/drivers/hid/intel-ish-hid/Makefile
+++ b/drivers/hid/intel-ish-hid/Makefile
@@ -13,4 +13,8 @@ obj-$(CONFIG_INTEL_ISH_HID_IPC) += intel-ish-ipc.o
intel-ish-ipc-objs := ipc/ipc.o
intel-ish-ipc-objs += ipc/pci-ish.o

+obj-$(CONFIG_INTEL_ISH_HID) += intel-ishtp-hid.o
+intel-ishtp-hid-objs := ishtp-hid.o
+intel-ishtp-hid-objs += ishtp-hid-client.o
+
ccflags-y += -Idrivers/hid/intel-ish-hid/ishtp
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
new file mode 100644
index 0000000..0a81a47
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
@@ -0,0 +1,922 @@
+/*
+ * ISHTP client driver for HID (ISH)
+ *
+ * Copyright (c) 2014-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+}
+
+/**
+ * process_recv() - Received and parse incoming packet
+ * @hid_ishtp_cl: Client instance to get stats
+ * @recv_buf: Raw received host interface message
+ * @data_len: length of the message
+ *
+ * Parse the incoming packet. If it is a response packet then it will update
+ * per instance flags and wake up the caller waiting to for the response.
+ */
+static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
+ size_t data_len)
+{
+ struct hostif_msg *recv_msg;
+ unsigned char *payload;
+ struct device_info *dev_info;
+ int i, j;
+ size_t payload_len, total_len, cur_pos;
+ int report_type;
+ struct report_list *reports_list;
+ char *reports;
+ size_t report_len;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ int curr_hid_dev = client_data->cur_hid_dev;
+
+ if (data_len < sizeof(struct hostif_msg_hdr)) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: error, received %u which is less than data header %u\n",
+ (unsigned int)data_len,
+ (unsigned int)sizeof(struct hostif_msg_hdr));
+ ++client_data->bad_recv_cnt;
+ ish_hw_reset(hid_ishtp_cl->dev);
+ return;
+ }
+
+ payload = recv_buf + sizeof(struct hostif_msg_hdr);
+ total_len = data_len;
+ cur_pos = 0;
+
+ do {
+ recv_msg = (struct hostif_msg *)(recv_buf + cur_pos);
+ payload_len = recv_msg->hdr.size;
+
+ /* Sanity checks */
+ if (cur_pos + payload_len + sizeof(struct hostif_msg) >
+ total_len) {
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+ }
+
+ hid_ishtp_trace(client_data, "%s %d\n",
+ __func__, recv_msg->hdr.command & CMD_MASK);
+
+ switch (recv_msg->hdr.command & CMD_MASK) {
+ case HOSTIF_DM_ENUM_DEVICES:
+ if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
+ client_data->init_done)) {
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg,
+ cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+ }
+ client_data->hid_dev_count = (unsigned int)*payload;
+ if (!client_data->hid_devices)
+ client_data->hid_devices = devm_kzalloc(
+ &hid_ishtp_cl->device->dev,
+ client_data->hid_dev_count *
+ sizeof(struct device_info),
+ GFP_KERNEL);
+ if (!client_data->hid_devices) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "Mem alloc failed for hid device info\n");
+ wake_up_interruptible(&client_data->init_wait);
+ break;
+ }
+ for (i = 0; i < client_data->hid_dev_count; ++i) {
+ if (1 + sizeof(struct device_info) * i >=
+ payload_len) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: [ENUM_DEVICES]: content size %lu is bigger than payload_len %u\n",
+ 1 + sizeof(struct device_info)
+ * i,
+ (unsigned int)payload_len);
+ }
+
+ if (1 + sizeof(struct device_info) * i >=
+ data_len)
+ break;
+
+ dev_info = (struct device_info *)(payload + 1 +
+ sizeof(struct device_info) * i);
+ if (client_data->hid_devices)
+ memcpy(client_data->hid_devices + i,
+ dev_info,
+ sizeof(struct device_info));
+ }
+
+ client_data->enum_devices_done = true;
+ wake_up_interruptible(&client_data->init_wait);
+
+ break;
+
+ case HOSTIF_GET_HID_DESCRIPTOR:
+ if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
+ client_data->init_done)) {
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg,
+ cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+ }
+ if (!client_data->hid_descr[curr_hid_dev])
+ client_data->hid_descr[curr_hid_dev] =
+ devm_kmalloc(&hid_ishtp_cl->device->dev,
+ payload_len, GFP_KERNEL);
+ if (client_data->hid_descr[curr_hid_dev]) {
+ memcpy(client_data->hid_descr[curr_hid_dev],
+ payload, payload_len);
+ client_data->hid_descr_size[curr_hid_dev] =
+ payload_len;
+ client_data->hid_descr_done = true;
+ }
+ wake_up_interruptible(&client_data->init_wait);
+
+ break;
+
+ case HOSTIF_GET_REPORT_DESCRIPTOR:
+ if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
+ client_data->init_done)) {
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg,
+ cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+ }
+ if (!client_data->report_descr[curr_hid_dev])
+ client_data->report_descr[curr_hid_dev] =
+ devm_kmalloc(&hid_ishtp_cl->device->dev,
+ payload_len, GFP_KERNEL);
+ if (client_data->report_descr[curr_hid_dev]) {
+ memcpy(client_data->report_descr[curr_hid_dev],
+ payload,
+ payload_len);
+ client_data->report_descr_size[curr_hid_dev] =
+ payload_len;
+ client_data->report_descr_done = true;
+ }
+ wake_up_interruptible(&client_data->init_wait);
+
+ break;
+
+ case HOSTIF_GET_FEATURE_REPORT:
+ report_type = HID_FEATURE_REPORT;
+ goto do_get_report;
+
+ case HOSTIF_GET_INPUT_REPORT:
+ report_type = HID_INPUT_REPORT;
+do_get_report:
+ /* Get index of device that matches this id */
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ if (recv_msg->hdr.device_id ==
+ client_data->hid_devices[i].dev_id)
+ if (client_data->hid_sensor_hubs[i]) {
+ hid_input_report(
+ client_data->hid_sensor_hubs[
+ i],
+ report_type, payload,
+ payload_len, 0);
+ ishtp_hid_wakeup(
+ client_data->hid_sensor_hubs[
+ i]);
+ break;
+ }
+ }
+ break;
+
+ case HOSTIF_SET_FEATURE_REPORT:
+ /* Get index of device that matches this id */
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ if (recv_msg->hdr.device_id ==
+ client_data->hid_devices[i].dev_id)
+ if (client_data->hid_sensor_hubs[i]) {
+ ishtp_hid_wakeup(
+ client_data->hid_sensor_hubs[
+ i]);
+ break;
+ }
+ }
+ break;
+
+ case HOSTIF_PUBLISH_INPUT_REPORT:
+ report_type = HID_INPUT_REPORT;
+ for (i = 0; i < client_data->num_hid_devices; ++i)
+ if (recv_msg->hdr.device_id ==
+ client_data->hid_devices[i].dev_id)
+ if (client_data->hid_sensor_hubs[i])
+ hid_input_report(
+ client_data->hid_sensor_hubs[
+ i],
+ report_type, payload,
+ payload_len, 0);
+ break;
+
+ case HOSTIF_PUBLISH_INPUT_REPORT_LIST:
+ report_type = HID_INPUT_REPORT;
+ reports_list = (struct report_list *)payload;
+ reports = (char *)reports_list->reports;
+
+ for (j = 0; j < reports_list->num_of_reports; j++) {
+ recv_msg = (struct hostif_msg *)(reports +
+ sizeof(uint16_t));
+ report_len = *(uint16_t *)reports;
+ payload = reports + sizeof(uint16_t) +
+ sizeof(struct hostif_msg_hdr);
+ payload_len = report_len -
+ sizeof(struct hostif_msg_hdr);
+
+ for (i = 0; i < client_data->num_hid_devices;
+ ++i)
+ if (recv_msg->hdr.device_id ==
+ client_data->hid_devices[i].dev_id &&
+ client_data->hid_sensor_hubs[i]) {
+ hid_input_report(
+ client_data->hid_sensor_hubs[
+ i],
+ report_type,
+ payload, payload_len,
+ 0);
+ }
+
+ reports += sizeof(uint16_t) + report_len;
+ }
+ break;
+ default:
+ ++client_data->bad_recv_cnt;
+ report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
+ payload_len);
+ ish_hw_reset(hid_ishtp_cl->dev);
+ break;
+
+ }
+
+ if (!cur_pos && cur_pos + payload_len +
+ sizeof(struct hostif_msg) < total_len)
+ ++client_data->multi_packet_cnt;
+
+ cur_pos += payload_len + sizeof(struct hostif_msg);
+ payload += payload_len + sizeof(struct hostif_msg);
+
+ } while (cur_pos < total_len);
+}
+
+/**
+ * ish_cl_event_cb() - bus driver callback for incoming message/packet
+ * @device: Pointer to the the ishtp client device for which this message
+ * is targeted
+ *
+ * Remove the packet from the list and process the message by calling
+ * process_recv
+ */
+static void ish_cl_event_cb(struct ishtp_cl_device *device)
+{
+ struct ishtp_cl *hid_ishtp_cl = device->driver_data;
+ struct ishtp_cl_rb *rb_in_proc;
+ size_t r_length;
+ unsigned long flags;
+
+ if (!hid_ishtp_cl)
+ return;
+
+ spin_lock_irqsave(&hid_ishtp_cl->in_process_spinlock, flags);
+ while (!list_empty(&hid_ishtp_cl->in_process_list.list)) {
+ rb_in_proc = list_entry(
+ hid_ishtp_cl->in_process_list.list.next,
+ struct ishtp_cl_rb, list);
+ list_del_init(&rb_in_proc->list);
+ spin_unlock_irqrestore(&hid_ishtp_cl->in_process_spinlock,
+ flags);
+
+ if (!rb_in_proc->buffer.data)
+ return;
+
+ r_length = rb_in_proc->buf_idx;
+
+ /* decide what to do with received data */
+ process_recv(hid_ishtp_cl, rb_in_proc->buffer.data, r_length);
+
+ ishtp_io_rb_recycle(rb_in_proc);
+ spin_lock_irqsave(&hid_ishtp_cl->in_process_spinlock, flags);
+ }
+ spin_unlock_irqrestore(&hid_ishtp_cl->in_process_spinlock, flags);
+}
+
+/**
+ * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
+ * @hid: hid device instance for this request
+ * @buf: feature buffer
+ * @len: Length of feature buffer
+ * @report_id: Report id for the feature set request
+ *
+ * This is called from hid core .request() callback. This function doesn't wait
+ * for response.
+ */
+void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len,
+ int report_id)
+{
+ struct ishtp_hid_data *hid_data = hid->driver_data;
+ struct ishtp_cl_data *client_data = hid_data->client_data;
+ struct hostif_msg *msg = (struct hostif_msg *)buf;
+ int rv;
+ int i;
+
+ hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid);
+
+ rv = ishtp_hid_link_ready_wait(client_data);
+ if (rv) {
+ hid_ishtp_trace(client_data, "%s hid %p link not ready\n",
+ __func__, hid);
+ return;
+ }
+
+ memset(msg, 0, sizeof(struct hostif_msg));
+ msg->hdr.command = HOSTIF_SET_FEATURE_REPORT;
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ if (hid == client_data->hid_sensor_hubs[i]) {
+ msg->hdr.device_id =
+ client_data->hid_devices[i].dev_id;
+ break;
+ }
+ }
+
+ if (i == client_data->num_hid_devices)
+ return;
+
+ rv = ishtp_cl_send(client_data->hid_ishtp_cl, buf, len);
+ if (rv)
+ hid_ishtp_trace(client_data, "%s hid %p send failed\n",
+ __func__, hid);
+}
+
+/**
+ * hid_ishtp_get_report() - request to get feature/input report
+ * @hid: hid device instance for this request
+ * @report_id: Report id for the get request
+ * @report_type: Report type for the this request
+ *
+ * This is called from hid core .request() callback. This function will send
+ * request to FW and return without waiting for response.
+ */
+void hid_ishtp_get_report(struct hid_device *hid, int report_id,
+ int report_type)
+{
+ struct ishtp_hid_data *hid_data = hid->driver_data;
+ struct ishtp_cl_data *client_data = hid_data->client_data;
+ static unsigned char buf[10];
+ unsigned int len;
+ struct hostif_msg_to_sensor *msg = (struct hostif_msg_to_sensor *)buf;
+ int rv;
+ int i;
+
+ hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid);
+ rv = ishtp_hid_link_ready_wait(client_data);
+ if (rv) {
+ hid_ishtp_trace(client_data, "%s hid %p link not ready\n",
+ __func__, hid);
+ return;
+ }
+
+ len = sizeof(struct hostif_msg_to_sensor);
+
+ memset(msg, 0, sizeof(struct hostif_msg_to_sensor));
+ msg->hdr.command = (report_type == HID_FEATURE_REPORT) ?
+ HOSTIF_GET_FEATURE_REPORT : HOSTIF_GET_INPUT_REPORT;
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ if (hid == client_data->hid_sensor_hubs[i]) {
+ msg->hdr.device_id =
+ client_data->hid_devices[i].dev_id;
+ break;
+ }
+ }
+
+ if (i == client_data->num_hid_devices)
+ return;
+
+ msg->report_id = report_id;
+ rv = ishtp_cl_send(client_data->hid_ishtp_cl, buf, len);
+ if (rv)
+ hid_ishtp_trace(client_data, "%s hid %p send failed\n",
+ __func__, hid);
+}
+
+/**
+ * ishtp_hid_link_ready_wait() - Wait for link ready
+ *
+ * @client_data: client data instance
+ *
+ * If the transport link started suspend process, then wait, till either
+ * resumed or timeout
+ */
+int ishtp_hid_link_ready_wait(struct ishtp_cl_data *client_data)
+{
+ int rc;
+
+ if (client_data->suspended) {
+ hid_ishtp_trace(client_data, "wait for link ready\n");
+ rc = wait_event_interruptible_timeout(
+ client_data->ishtp_resume_wait,
+ !client_data->suspended,
+ 5 * HZ);
+
+ if (rc == 0) {
+ hid_ishtp_trace(client_data, "link not ready\n");
+ return -EIO;
+ }
+ hid_ishtp_trace(client_data, "link ready\n");
+ }
+
+ return 0;
+}
+
+/**
+ * ishtp_enum_enum_devices() - Enumerate hid devices
+ *
+ * @client_data: client data instance
+ *
+ * Helper function to send request to firmware to enumerate HID devices
+ */
+static int ishtp_enum_enum_devices(struct ishtp_cl *hid_ishtp_cl)
+{
+ struct hostif_msg msg;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ int retry_count;
+ int rv;
+
+ /* Send HOSTIF_DM_ENUM_DEVICES */
+ memset(&msg, 0, sizeof(struct hostif_msg));
+ msg.hdr.command = HOSTIF_DM_ENUM_DEVICES;
+ rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *)&msg,
+ sizeof(struct hostif_msg));
+ if (rv)
+ return rv;
+
+ retry_count = 0;
+ while (!client_data->enum_devices_done &&
+ retry_count < 10) {
+ wait_event_interruptible_timeout(client_data->init_wait,
+ client_data->enum_devices_done,
+ 3 * HZ);
+ ++retry_count;
+ if (!client_data->enum_devices_done)
+ /* Send HOSTIF_DM_ENUM_DEVICES */
+ rv = ishtp_cl_send(hid_ishtp_cl,
+ (unsigned char *) &msg,
+ sizeof(struct hostif_msg));
+ }
+ if (!client_data->enum_devices_done) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: timed out waiting for enum_devices\n");
+ return -ETIMEDOUT;
+ }
+ if (!client_data->hid_devices) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: failed to allocate HID dev structures\n");
+ return -ENOMEM;
+ }
+
+ client_data->num_hid_devices = client_data->hid_dev_count;
+ dev_info(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
+ client_data->num_hid_devices);
+
+ return 0;
+}
+
+/**
+ * ishtp_get_hid_descriptor() - Get hid descriptor
+ *
+ * @client_data: client data instance
+ *
+ * Helper function to send request to firmware get HID descriptor of a device
+ */
+static int ishtp_get_hid_descriptor(struct ishtp_cl *hid_ishtp_cl, int index)
+{
+ struct hostif_msg msg;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ int rv;
+
+ /* Get HID descriptor */
+ client_data->hid_descr_done = false;
+ memset(&msg, 0, sizeof(struct hostif_msg));
+ msg.hdr.command = HOSTIF_GET_HID_DESCRIPTOR;
+ msg.hdr.device_id = client_data->hid_devices[index].dev_id;
+ rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg,
+ sizeof(struct hostif_msg));
+ if (rv)
+ return rv;
+
+ if (!client_data->hid_descr_done) {
+ wait_event_interruptible_timeout(client_data->init_wait,
+ client_data->hid_descr_done,
+ 3 * HZ);
+ if (!client_data->hid_descr_done) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: timed out for hid_descr_done\n");
+ return -EIO;
+ }
+
+ if (!client_data->hid_descr[index]) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: allocation HID desc fail\n");
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ishtp_get_report_descriptor() - Get report descriptor
+ *
+ * @client_data: client data instance
+ *
+ * Helper function to send request to firmware get HID report descriptor of
+ * a device
+ */
+static int ishtp_get_report_descriptor(struct ishtp_cl *hid_ishtp_cl,
+ int index)
+{
+ struct hostif_msg msg;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ int rv;
+
+ /* Get report descriptor */
+ client_data->report_descr_done = false;
+ memset(&msg, 0, sizeof(struct hostif_msg));
+ msg.hdr.command = HOSTIF_GET_REPORT_DESCRIPTOR;
+ msg.hdr.device_id = client_data->hid_devices[index].dev_id;
+ rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg,
+ sizeof(struct hostif_msg));
+ if (rv)
+ return rv;
+
+ if (!client_data->report_descr_done)
+ wait_event_interruptible_timeout(client_data->init_wait,
+ client_data->report_descr_done,
+ 3 * HZ);
+ if (!client_data->report_descr_done) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: timed out for report descr\n");
+ return -EIO;
+ }
+ if (!client_data->report_descr[index]) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: failed to alloc report descr\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/**
+ * hid_ishtp_cl_init() - Init function for ISHTP client
+ * @hid_istp_cl: ISHTP client instance
+ *
+ * This function complete the initializtion of the client. The summary of
+ * processing:
+ * - Send request to enumerate the hid clients
+ * Get the HID descriptor for each enumearated device
+ * Get report description of each device
+ * Register each device wik hid core by calling ishtp_hid_probe
+ */
+static int hid_ishtp_cl_init(struct ishtp_cl *hid_ishtp_cl, int reset)
+{
+ struct ishtp_device *dev;
+ unsigned long flags;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+ int i;
+ int rv;
+
+ hid_ishtp_trace(client_data, "%s reset flag: %d\n", __func__, reset);
+
+ rv = ishtp_cl_link(hid_ishtp_cl, ISHTP_HOST_CLIENT_ID_ANY);
+ if (rv) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "ishtp_cl_link failed\n");
+ return -ENOMEM;
+ }
+
+ client_data->init_done = 0;
+
+ dev = hid_ishtp_cl->dev;
+
+ /* Connect to FW client */
+ hid_ishtp_cl->rx_ring_size = HID_CL_RX_RING_SIZE;
+ hid_ishtp_cl->tx_ring_size = HID_CL_TX_RING_SIZE;
+
+ spin_lock_irqsave(&dev->fw_clients_lock, flags);
+ i = ishtp_fw_cl_by_uuid(dev, &hid_ishtp_guid);
+ if (i < 0) {
+ spin_unlock_irqrestore(&dev->fw_clients_lock, flags);
+ dev_err(&hid_ishtp_cl->device->dev,
+ "ish client uuid not found\n");
+ return i;
+ }
+ hid_ishtp_cl->fw_client_id = dev->fw_clients[i].client_id;
+ spin_unlock_irqrestore(&dev->fw_clients_lock, flags);
+ hid_ishtp_cl->state = ISHTP_CL_CONNECTING;
+
+ rv = ishtp_cl_connect(hid_ishtp_cl);
+ if (rv) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "client connect fail\n");
+ goto err_cl_unlink;
+ }
+
+ hid_ishtp_trace(client_data, "%s client connected\n", __func__);
+
+ /* Register read callback */
+ ishtp_register_event_cb(hid_ishtp_cl->device, ish_cl_event_cb);
+
+ rv = ishtp_enum_enum_devices(hid_ishtp_cl);
+ if (rv)
+ goto err_cl_disconnect;
+
+ hid_ishtp_trace(client_data, "%s enumerated device count %d\n",
+ __func__, client_data->num_hid_devices);
+
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ client_data->cur_hid_dev = i;
+
+ rv = ishtp_get_hid_descriptor(hid_ishtp_cl, i);
+ if (rv)
+ goto err_cl_disconnect;
+
+ rv = ishtp_get_report_descriptor(hid_ishtp_cl, i);
+ if (rv)
+ goto err_cl_disconnect;
+
+ if (!reset) {
+ rv = ishtp_hid_probe(i, client_data);
+ if (rv) {
+ dev_err(&hid_ishtp_cl->device->dev,
+ "[hid-ish]: HID probe for #%u failed: %d\n",
+ i, rv);
+ goto err_cl_disconnect;
+ }
+ }
+ } /* for() on all hid devices */
+
+ client_data->init_done = 1;
+ client_data->suspended = false;
+ wake_up_interruptible(&client_data->ishtp_resume_wait);
+ hid_ishtp_trace(client_data, "%s successful init\n", __func__);
+ return 0;
+
+err_cl_disconnect:
+ hid_ishtp_cl->state = ISHTP_CL_DISCONNECTING;
+ ishtp_cl_disconnect(hid_ishtp_cl);
+err_cl_unlink:
+ ishtp_cl_unlink(hid_ishtp_cl);
+ return rv;
+}
+
+void hid_ishtp_cl_deinit(struct ishtp_cl *hid_ishtp_cl)
+{
+ ishtp_cl_unlink(hid_ishtp_cl);
+ ishtp_cl_flush_queues(hid_ishtp_cl);
+
+ /* disband and free all Tx and Rx client-level rings */
+ ishtp_cl_free(hid_ishtp_cl);
+}
+
+static void hid_ishtp_cl_reset_handler(struct work_struct *work)
+{
+ struct ishtp_cl_data *client_data;
+ struct ishtp_cl *hid_ishtp_cl;
+ struct ishtp_cl_device *cl_device;
+ int retry;
+ int rv;
+
+ client_data = container_of(work, struct ishtp_cl_data, work);
+
+
+ hid_ishtp_cl = client_data->hid_ishtp_cl;
+ cl_device = client_data->cl_device;
+
+ hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
+ hid_ishtp_cl);
+
+ hid_ishtp_cl_deinit(hid_ishtp_cl);
+
+ hid_ishtp_cl = ishtp_cl_allocate(cl_device->ishtp_dev);
+ if (!hid_ishtp_cl)
+ return;
+
+ cl_device->driver_data = hid_ishtp_cl;
+ hid_ishtp_cl->client_data = client_data;
+ client_data->hid_ishtp_cl = hid_ishtp_cl;
+
+ client_data->num_hid_devices = 0;
+
+ for (retry = 0; retry < 3; ++retry) {
+ rv = hid_ishtp_cl_init(hid_ishtp_cl, 1);
+ if (!rv)
+ break;
+ dev_err(&hid_ishtp_cl->device->dev, "Retry reset init\n");
+ }
+ if (rv) {
+ dev_err(&hid_ishtp_cl->device->dev, "Reset Failed\n");
+ hid_ishtp_trace(client_data, "%s Failed hid_ishtp_cl %p\n",
+ __func__, hid_ishtp_cl);
+ }
+}
+
+/**
+ * hid_ishtp_cl_probe() - ISHTP client driver probe
+ * @cl_device: ISHTP client device instance
+ *
+ * This function calls on device create on ISHTP bus
+ */
+static int hid_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
+{
+ struct ishtp_cl *hid_ishtp_cl;
+ struct ishtp_cl_data *client_data;
+ int rv;
+
+ if (!cl_device)
+ return -ENODEV;
+
+ if (uuid_le_cmp(hid_ishtp_guid,
+ cl_device->fw_client->props.protocol_name) != 0)
+ return -ENODEV;
+
+ client_data = devm_kzalloc(&cl_device->dev, sizeof(*client_data),
+ GFP_KERNEL);
+ if (!client_data)
+ return -ENOMEM;
+
+ hid_ishtp_cl = ishtp_cl_allocate(cl_device->ishtp_dev);
+ if (!hid_ishtp_cl)
+ return -ENOMEM;
+
+ cl_device->driver_data = hid_ishtp_cl;
+ hid_ishtp_cl->client_data = client_data;
+ client_data->hid_ishtp_cl = hid_ishtp_cl;
+ client_data->cl_device = cl_device;
+
+ init_waitqueue_head(&client_data->init_wait);
+ init_waitqueue_head(&client_data->ishtp_resume_wait);
+
+ INIT_WORK(&client_data->work, hid_ishtp_cl_reset_handler);
+
+ rv = hid_ishtp_cl_init(hid_ishtp_cl, 0);
+ if (rv) {
+ ishtp_cl_free(hid_ishtp_cl);
+ return rv;
+ }
+ ishtp_get_device(cl_device);
+
+ return 0;
+}
+
+/**
+ * hid_ishtp_cl_remove() - ISHTP client driver remove
+ * @cl_device: ISHTP client device instance
+ *
+ * This function calls on device create on ISHTP bus
+ */
+static int hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
+{
+ struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
+ hid_ishtp_cl);
+
+ ishtp_put_device(cl_device);
+ ishtp_hid_remove(client_data);
+ hid_ishtp_cl_deinit(hid_ishtp_cl);
+
+ hid_ishtp_cl = NULL;
+
+ client_data->num_hid_devices = 0;
+
+ return 0;
+}
+
+static int hid_ishtp_cl_reset(struct ishtp_cl_device *cl_device)
+{
+ struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
+ hid_ishtp_cl);
+
+ schedule_work(&client_data->work);
+
+ return 0;
+}
+
+#define to_ishtp_cl_device(d) container_of(d, struct ishtp_cl_device, dev)
+
+static int hid_ishtp_cl_suspend(struct device *device)
+{
+ struct ishtp_cl_device *cl_device = to_ishtp_cl_device(device);
+ struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
+ hid_ishtp_cl);
+ client_data->suspended = true;
+
+ return 0;
+}
+
+static int hid_ishtp_cl_resume(struct device *device)
+{
+ struct ishtp_cl_device *cl_device = to_ishtp_cl_device(device);
+ struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data;
+ struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
+
+ hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
+ hid_ishtp_cl);
+ client_data->suspended = false;
+ return 0;
+}
+
+static const struct dev_pm_ops hid_ishtp_pm_ops = {
+ .suspend = hid_ishtp_cl_suspend,
+ .resume = hid_ishtp_cl_resume,
+};
+
+struct ishtp_cl_driver hid_ishtp_cl_driver = {
+ .name = "ish",
+ .probe = hid_ishtp_cl_probe,
+ .remove = hid_ishtp_cl_remove,
+ .reset = hid_ishtp_cl_reset,
+ .driver.pm = &hid_ishtp_pm_ops,
+};
+
+static int __init ish_hid_init(void)
+{
+ int rv;
+
+ /* Register ISHTP client device driver with ISHTP Bus */
+ rv = ishtp_cl_driver_register(&hid_ishtp_cl_driver);
+
+ return rv;
+
+}
+late_initcall(ish_hid_init);
+
+MODULE_DESCRIPTION("ISH ISHTP HID client driver");
+/* Primary author */
+MODULE_AUTHOR("Daniel Drubin <daniel...@intel.com>");
+/*
+ * Several modification for multi instance support
+ * suspend/resume and clean up
+ */
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas....@linux.intel.com>");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.c b/drivers/hid/intel-ish-hid/ishtp-hid.c
new file mode 100644
index 0000000..351c497
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp-hid.c
@@ -0,0 +1,231 @@
+/*
+ * ISHTP-HID glue driver.
+ *
+ * Copyright (c) 2012-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/hid.h>
+#include <uapi/linux/input.h>
+#include "ishtp/client.h"
+#include "ishtp-hid.h"
+
+/**
+ * ishtp_hid_parse() - hid-core .parse() callback
+ * @hid: hid device instance
+ *
+ * This function gets called during call to hid_add_device
+ */
+static int ishtp_hid_parse(struct hid_device *hid)
+{
+ struct ishtp_hid_data *hid_data = hid->driver_data;
+ struct ishtp_cl_data *client_data = hid_data->client_data;
+ int rv;
+
+ rv = hid_parse_report(hid, client_data->report_descr[hid_data->index],
+ client_data->report_descr_size[hid_data->index]);
+ if (rv)
+ return rv;
+
+ return 0;
+}
+
+/* Empty callbacks with success return code */
+static int ishtp_hid_start(struct hid_device *hid)
+{
+ return 0;
+}
+
+static void ishtp_hid_stop(struct hid_device *hid)
+{
+}
+
+static int ishtp_hid_open(struct hid_device *hid)
+{
+ return 0;
+}
+
+static void ishtp_hid_close(struct hid_device *hid)
+{
+}
+
+static int ishtp_raw_request(struct hid_device *hdev, unsigned char reportnum,
+ __u8 *buf, size_t len, unsigned char rtype, int reqtype)
+{
+ return 0;
+}
+
+/**
+ * ishtp_hid_request() - hid-core .request() callback
+ * @hid: hid device instance
+ * @rep: pointer to hid_report
+ * @reqtype: type of req. [GET|SET]_REPORT
+ *
+ break;
+ }
+}
+
+/**
+ * ishtp_wait_for_response() - hid-core .wait() callback
+ * @hid: hid device instance
+ *
+ * This function is used to wait after get feaure/input report.
+ */
+static int ishtp_wait_for_response(struct hid_device *hid)
+{
+ struct ishtp_hid_data *hid_data = hid->driver_data;
+ struct ishtp_cl_data *client_data = hid_data->client_data;
+ int rv;
+
+ hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid);
+
+ rv = ishtp_hid_link_ready_wait(hid_data->client_data);
+ if (rv)
+ return rv;
+
+ if (!hid_data->request_done)
+ wait_event_interruptible_timeout(hid_data->hid_wait,
+ hid_data->request_done, 3 * HZ);
+
+ if (!hid_data->request_done) {
+ hid_err(hid,
+ "timeout waiting for response from ISHTP device\n");
+ return -ETIMEDOUT;
+ }
+ hid_ishtp_trace(client_data, "%s hid %p done\n", __func__, hid);
+
+ hid_data->request_done = 0;
+
+ return 0;
+}
+
+void ishtp_hid_wakeup(struct hid_device *hid)
+{
+ struct ishtp_hid_data *hid_data = hid->driver_data;
+
+ hid_data->request_done = 1;
+ wake_up_interruptible(&hid_data->hid_wait);
+}
+
+static struct hid_ll_driver ishtp_hid_ll_driver = {
+ .parse = ishtp_hid_parse,
+ .start = ishtp_hid_start,
+ .stop = ishtp_hid_stop,
+ .open = ishtp_hid_open,
+ .close = ishtp_hid_close,
+ .request = ishtp_hid_request,
+ .wait = ishtp_wait_for_response,
+ .raw_request = ishtp_raw_request
+};
+
+/**
+ * ishtp_hid_probe() - hid register ll driver
+ * @curr_hid_dev: Index of hid device calling to register
+ * @hid_ishtp_cl: ISHTP Client instance
+ *
+ * This function is used to allocate and add HID device.
+ */
+int ishtp_hid_probe(unsigned int cur_hid_dev, struct ishtp_cl_data *client_data)
+{
+ int rv;
+ struct hid_device *hid;
+ struct ishtp_hid_data *hid_data;
+
+ hid = hid_allocate_device();
+ if (IS_ERR(hid)) {
+ rv = PTR_ERR(hid);
+ return -ENOMEM;
+ }
+
+ hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL);
+ if (!hid_data) {
+ rv = -ENOMEM;
+ goto err_hid_data;
+ }
+
+ hid_data->index = cur_hid_dev;
+ hid_data->client_data = client_data;
+ init_waitqueue_head(&hid_data->hid_wait);
+
+ hid->driver_data = hid_data;
+
+ client_data->hid_sensor_hubs[cur_hid_dev] = hid;
+
+ hid->ll_driver = &ishtp_hid_ll_driver;
+ hid->bus = BUS_INTEL_ISHTP;
+ hid->dev.parent = &client_data->cl_device->dev;
+ hid->version = le16_to_cpu(ISH_HID_VERSION);
+ hid->vendor = le16_to_cpu(ISH_HID_VENDOR);
+ hid->product = le16_to_cpu(ISH_HID_PRODUCT);
+ snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", "hid-ishtp",
+ hid->vendor, hid->product);
+
+ rv = hid_add_device(hid);
+ if (rv)
+ goto err_hid_device;
+
+ hid_ishtp_trace(client_data, "%s allocated hid %p\n", __func__, hid);
+
+ return 0;
+
+err_hid_device:
+ kfree(hid_data);
+err_hid_data:
+ kfree(hid);
+ return rv;
+}
+
+/**
+ * ishtp_hid_probe() - Remove registered hid device
+ * @hid_ishtp_cl: ISHTP Client instance
+ *
+ * This function is used to destroy allocatd HID device.
+ */
+void ishtp_hid_remove(struct ishtp_cl_data *client_data)
+{
+ int i;
+
+ for (i = 0; i < client_data->num_hid_devices; ++i) {
+ if (client_data->hid_sensor_hubs[i]) {
+ kfree(client_data->hid_sensor_hubs[i]->driver_data);
+ hid_destroy_device(client_data->hid_sensor_hubs[i]);
+ client_data->hid_sensor_hubs[i] = NULL;
+ }
+ }
+}
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.h b/drivers/hid/intel-ish-hid/ishtp-hid.h
new file mode 100644
index 0000000..f5c7eb7
--- /dev/null
+++ b/drivers/hid/intel-ish-hid/ishtp-hid.h
@@ -0,0 +1,182 @@
+/*
+ * ISHTP-HID glue driver's definitions.
+ *
+ * Copyright (c) 2014-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+#ifndef ISHTP_HID__H
+#define ISHTP_HID__H
+
+/* The fixed ISH product and vendor id */
+#define ISH_HID_VENDOR 0x8086
+#define ISH_HID_PRODUCT 0x22D8
+#define ISH_HID_VERSION 0x0200
+
+#define CMD_MASK 0x7F
+#define IS_RESPONSE 0x80
+
+/* Used to dump to Linux trace buffer, if enabled */
+#define hid_ishtp_trace(client, ...) \
+ client->cl_device->ishtp_dev->print_log(\
+ client->cl_device->ishtp_dev, __VA_ARGS__)
+ * @init_done: Init process completed successfully
+ * @suspended: System is under suspend state or in progress
+ * @num_hid_devices: Number of HID devices enumerated in this client
+ * @cur_hid_dev: This keeps track of the device index for which
+ * initialization and registration with HID core
+ * in progress.
+ * @hid_devices: Store vid/pid/devid for each enumerated HID device
+ * @report_descr: Stores the raw report descriptors for each HID device
+ * @report_descr_size: Report description of size of above repo_descr[]
+ * @hid_sensor_hubs: Pointer to hid_device for all HID device, so that
+ * when clients are removed, they can be freed
+ * @hid_descr: Pointer to hid descriptor for each enumerated hid
+ * device
+ * @hid_descr_size: Size of each above report descriptor
+ * @init_wait: Wait queue to wait during initialization, where the
+ * client send message to ISH FW and wait for response
+ * @ishtp_hid_wait: The wait for get report during wait callback from hid
+ * core
+ * @bad_recv_cnt: Running count of packets received with error
+ * @multi_packet_cnt: Count of fragmented packet count
+ *
+ * This structure is used to store completion flags and per client data like
+ * like report description, number of HID devices etc.
+ */
+struct ishtp_cl_data {
+ /* completion flags */
+ bool enum_devices_done;
+ bool hid_descr_done;
+ bool report_descr_done;
+ bool init_done;
+ bool suspended;
+
+ unsigned int num_hid_devices;
+ unsigned int cur_hid_dev;
+ unsigned int hid_dev_count;
+
+ struct device_info *hid_devices;
+ unsigned char *report_descr[MAX_HID_DEVICES];
+ int report_descr_size[MAX_HID_DEVICES];
+ struct hid_device *hid_sensor_hubs[MAX_HID_DEVICES];
+ unsigned char *hid_descr[MAX_HID_DEVICES];
+ int hid_descr_size[MAX_HID_DEVICES];
+
+ wait_queue_head_t init_wait;
+ wait_queue_head_t ishtp_resume_wait;
+ struct ishtp_cl *hid_ishtp_cl;
+
+ /* Statistics */
+ unsigned int bad_recv_cnt;
+ int multi_packet_cnt;
+
+ struct work_struct work;
+ struct ishtp_cl_device *cl_device;
+};
+
+/**
+ * struct ishtp_hid_data - Per instance HID data
+ * @index: Device index in the order of enumeration
+ * @request_done: Get Feature/Input report complete flag
+ * used during get/set request from hid core
+ * @client_data: Link to the client instance
+ * @hid_wait: Completion waitq
+ *
+ * Used to tie hid hid->driver data to driver client instance
+ */
+struct ishtp_hid_data {
+ int index;
+ bool request_done;
+ struct ishtp_cl_data *client_data;
+ wait_queue_head_t hid_wait;
+};
+
+/* Interface functions between HID LL driver and ISH TP client */
+void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len,
+ int report_id);
+void hid_ishtp_get_report(struct hid_device *hid, int report_id,
+ int report_type);
+int ishtp_hid_probe(unsigned int cur_hid_dev,
+ struct ishtp_cl_data *client_data);
+void ishtp_hid_remove(struct ishtp_cl_data *client_data);
+int ishtp_hid_link_ready_wait(struct ishtp_cl_data *client_data);
+void ishtp_hid_wakeup(struct hid_device *hid);
+
+#endif /* ISHTP_HID__H */
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 0111384..1b7bfc6 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -247,6 +247,7 @@ struct input_mask {
#define BUS_ATARI 0x1B
#define BUS_SPI 0x1C
#define BUS_RMI 0x1D
+#define BUS_INTEL_ISHTP 0x1E

/*
* MT_TOOL types
--
2.5.5

Grant Likely

unread,
Jun 14, 2016, 9:50:06 AM6/14/16
to
Still no joy on the sensors. The proxy starts up and detects the
sensors, but I don't see any sensor events occurring:

root@gladys:~# G_MESSAGES_DEBUG=all /usr/sbin/iio-sensor-proxy
** (process:2802): DEBUG: Found accel_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
** (process:2802): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
of type accelerometer at IIO Buffer accelerometer
** (process:2802): DEBUG: Found magn_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
** (process:2802): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
of type compass at IIO Buffer Compass
** (process:2802): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/trigger1
** (process:2802): DEBUG: Got type for in_accel_x: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Got type for in_accel_y: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Got type for in_accel_z: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Built channel array for in_accel_x: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Built channel array for in_accel_y: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Built channel array for in_accel_z: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/trigger6
** (process:2802): DEBUG: Got type for in_magn_x: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Got type for in_magn_y: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Got type for in_magn_z: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Got type for
in_rot_from_north_magnetic_tilt_comp: is signed: 1, bytes: 4,
bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Built channel array for in_magn_x: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Built channel array for in_magn_y: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Built channel array for in_magn_z: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Built channel array for
in_rot_from_north_magnetic_tilt_comp: is signed: 1, bytes: 4,
bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2802): DEBUG: Handling driver refcounting method
'ClaimLight' for ambient light sensor device
** (process:2802): DEBUG: Handling driver refcounting method
'ClaimAccelerometer' for accelerometer device
** (process:2802): DEBUG: Handling driver refcounting method
'ClaimAccelerometer' for accelerometer device
** (process:2802): DEBUG: No new data available
** (process:2802): DEBUG: No new data available
^C
root@gladys:~# G_MESSAGES_DEBUG=all /usr/sbin/iio-sensor-proxy
** (process:3568): DEBUG: Found accel_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
** (process:3568): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
of type accelerometer at IIO Buffer accelerometer
** (process:3568): DEBUG: Found magn_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
** (process:3568): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
of type compass at IIO Buffer Compass
** (process:3568): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/trigger1
** (process:3568): DEBUG: Got type for in_accel_x: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Got type for in_accel_y: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Got type for in_accel_z: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Built channel array for in_accel_x: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Built channel array for in_accel_y: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Built channel array for in_accel_z: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/trigger6
** (process:3568): DEBUG: Got type for in_magn_x: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Got type for in_magn_y: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Got type for in_magn_z: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Got type for
in_rot_from_north_magnetic_tilt_comp: is signed: 1, bytes: 4,
bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Built channel array for in_magn_x: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Built channel array for in_magn_y: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Built channel array for in_magn_z: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Built channel array for
in_rot_from_north_magnetic_tilt_comp: is signed: 1, bytes: 4,
bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:3568): DEBUG: Handling driver refcounting method
'ClaimAccelerometer' for accelerometer device
** (process:3568): DEBUG: Handling driver refcounting method
'ClaimLight' for ambient light sensor device
** (process:3568): DEBUG: Handling driver refcounting method
'ClaimAccelerometer' for accelerometer device
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
** (process:3568): DEBUG: No new data available
^C
root@gladys:~#

This is running on a 4.6.2 kernel with v2 of the ISH patch set.

Here is the kernel log output:

[ 0.000000] Linux version 4.6.2-gcl1+ (grant@gladys) (gcc version
5.3.1 20160528 (Debian 5.3.1-21) ) #8 SMP Tue Jun 14 12:19:30 BST 2016
[ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.6.2-gcl1+
root=/dev/mapper/gladys--vg-debian ro quiet
[ 0.000000] x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256
[ 0.000000] x86/fpu: xstate_offset[3]: 960, xstate_sizes[3]: 64
[ 0.000000] x86/fpu: xstate_offset[4]: 1024, xstate_sizes[4]: 64
[ 0.000000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating
point registers'
[ 0.000000] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
[ 0.000000] x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
[ 0.000000] x86/fpu: Supporting XSAVE feature 0x008: 'MPX bounds registers'
[ 0.000000] x86/fpu: Supporting XSAVE feature 0x010: 'MPX CSR'
[ 0.000000] x86/fpu: Enabled xstate features 0x1f, context size is
1088 bytes, using 'standard' format.
[ 0.000000] x86/fpu: Using 'eager' FPU context switches.
[ 0.000000] e820: BIOS-provided physical RAM map:
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x0000000000057fff] usable
[ 0.000000] BIOS-e820: [mem 0x0000000000058000-0x0000000000058fff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000000059000-0x000000000009dfff] usable
[ 0.000000] BIOS-e820: [mem 0x000000000009e000-0x000000000009ffff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000007ec6dfff] usable
[ 0.000000] BIOS-e820: [mem 0x000000007ec6e000-0x000000007ec6efff] ACPI NVS
[ 0.000000] BIOS-e820: [mem 0x000000007ec6f000-0x000000007ec98fff] reserved
[ 0.000000] BIOS-e820: [mem 0x000000007ec99000-0x00000000864c7fff] usable
[ 0.000000] BIOS-e820: [mem 0x00000000864c8000-0x00000000871ccfff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000871cd000-0x0000000087218fff] ACPI data
[ 0.000000] BIOS-e820: [mem 0x0000000087219000-0x0000000087b5afff] ACPI NVS
[ 0.000000] BIOS-e820: [mem 0x0000000087b5b000-0x0000000087f68fff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000087f69000-0x0000000087ffefff] type 20
[ 0.000000] BIOS-e820: [mem 0x0000000087fff000-0x0000000087ffffff] usable
[ 0.000000] BIOS-e820: [mem 0x0000000088000000-0x00000000880fffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000e0000000-0x00000000efffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fe000000-0x00000000fe010fff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fec00000-0x00000000fec00fff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000ff000000-0x00000000ffffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000100000000-0x0000000473ffffff] usable
[ 0.000000] NX (Execute Disable) protection: active
[ 0.000000] efi: EFI v2.40 by American Megatrends
[ 0.000000] efi: ESRT=0x87f65118 ACPI=0x871e4000 ACPI
2.0=0x871e4000 SMBIOS=0x853cb010
[ 0.000000] esrt: Reserving ESRT space from 0x0000000087f65118 to
0x0000000087f65150.
[ 0.000000] SMBIOS 2.8 present.
[ 0.000000] DMI: HP HP Spectre x360 Convertible/81A1, BIOS F.35 04/26/2016
[ 0.000000] e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
[ 0.000000] e820: remove [mem 0x000a0000-0x000fffff] usable
[ 0.000000] e820: last_pfn = 0x474000 max_arch_pfn = 0x400000000
[ 0.000000] MTRR default type: write-back
[ 0.000000] MTRR fixed ranges enabled:
[ 0.000000] 00000-9FFFF write-back
[ 0.000000] A0000-BFFFF uncachable
[ 0.000000] C0000-FFFFF write-protect
[ 0.000000] MTRR variable ranges enabled:
[ 0.000000] 0 base 00C0000000 mask 7FC0000000 uncachable
[ 0.000000] 1 base 00A0000000 mask 7FE0000000 uncachable
[ 0.000000] 2 base 0090000000 mask 7FF0000000 uncachable
[ 0.000000] 3 base 008C000000 mask 7FFC000000 uncachable
[ 0.000000] 4 base 008A000000 mask 7FFE000000 uncachable
[ 0.000000] 5 base 0089000000 mask 7FFF000000 uncachable
[ 0.000000] 6 base 0088800000 mask 7FFF800000 uncachable
[ 0.000000] 7 disabled
[ 0.000000] 8 disabled
[ 0.000000] 9 disabled
[ 0.000000] x86/PAT: Configuration [0-7]: WB WC UC- UC WB WC UC- WT
[ 0.000000] e820: last_pfn = 0x88000 max_arch_pfn = 0x400000000
[ 0.000000] Base memory trampoline at [ffff880000098000] 98000 size 24576
[ 0.000000] Using GB pages for direct mapping
[ 0.000000] BRK [0x03341000, 0x03341fff] PGTABLE
[ 0.000000] BRK [0x03342000, 0x03342fff] PGTABLE
[ 0.000000] BRK [0x03343000, 0x03343fff] PGTABLE
[ 0.000000] BRK [0x03344000, 0x03344fff] PGTABLE
[ 0.000000] BRK [0x03345000, 0x03345fff] PGTABLE
[ 0.000000] BRK [0x03346000, 0x03346fff] PGTABLE
[ 0.000000] RAMDISK: [mem 0x36022000-0x37008fff]
[ 0.000000] ACPI: Early table checksum verification disabled
[ 0.000000] ACPI: RSDP 0x00000000871E4000 000024 (v02 HPQOEM)
[ 0.000000] ACPI: XSDT 0x00000000871E40A8 0000D4 (v01 HPQOEM
SLIC-MPC 01072009 HP 00010013)
[ 0.000000] ACPI: FACP 0x0000000087210630 00010C (v05 HPQOEM
SLIC-MPC 01072009 HP 00010013)
[ 0.000000] ACPI: DSDT 0x00000000871E4210 02C419 (v02 HPQOEM 81A1
01072009 ACPI 20120913)
[ 0.000000] ACPI: FACS 0x0000000087B58F80 000040
[ 0.000000] ACPI: APIC 0x0000000087210740 000084 (v03 HPQOEM 81A1
01072009 HP 00010013)
[ 0.000000] ACPI: FPDT 0x00000000872107C8 000044 (v01 HPQOEM 81A1
01072009 HP 00010013)
[ 0.000000] ACPI: FIDT 0x0000000087210810 00009C (v01 HPQOEM 81A1
01072009 HP 00010013)
[ 0.000000] ACPI: MCFG 0x00000000872108B0 00003C (v01 HPQOEM 81A1
01072009 HP 00000097)
[ 0.000000] ACPI: HPET 0x00000000872108F0 000038 (v01 HPQOEM 81A1
01072009 HP 0005000B)
[ 0.000000] ACPI: SSDT 0x0000000087210928 000495 (v01 HPQOEM 81A1
00001000 ACPI 20120913)
[ 0.000000] ACPI: LPIT 0x0000000087210DC0 000094 (v01 HPQOEM 81A1
00000000 MSFT 0000005F)
[ 0.000000] ACPI: SSDT 0x0000000087210E58 000248 (v02 HPQOEM 81A1
00000000 ACPI 20120913)
[ 0.000000] ACPI: SSDT 0x00000000872110A0 0011A8 (v02 HPQOEM 81A1
00001000 ACPI 20120913)
[ 0.000000] ACPI: DBGP 0x0000000087212248 000034 (v01 HPQOEM 81A1
00000000 MSFT 0000005F)
[ 0.000000] ACPI: DBG2 0x0000000087212280 000054 (v00 HPQOEM 81A1
00000000 MSFT 0000005F)
[ 0.000000] ACPI: SSDT 0x00000000872122D8 000024 (v02 HPQOEM 81A1
00000000 ACPI 20120913)
[ 0.000000] ACPI: MSDM 0x0000000087212300 000055 (v03 HPQOEM
SLIC-MPC 00000001 ACPI 00010013)
[ 0.000000] ACPI: SSDT 0x0000000087212358 0053FD (v02 HPQOEM 81A1
00003000 ACPI 20120913)
[ 0.000000] ACPI: UEFI 0x0000000087217758 000042 (v01 HPQOEM 81A1
00000000 HP 00000000)
[ 0.000000] ACPI: SSDT 0x00000000872177A0 000E73 (v02 HPQOEM 81A1
00003000 ACPI 20120913)
[ 0.000000] ACPI: DMAR 0x0000000087218618 0000A8 (v01 HPQOEM 81A1
00000001 INTL 00000001)
[ 0.000000] ACPI: NHLT 0x00000000872186C0 00002D (v00 HPQOEM 81A1
00000002 01000013)
[ 0.000000] ACPI: TPM2 0x00000000872186F0 000034 (v03 HPQOEM 81A1
00000001 HP 00000000)
[ 0.000000] ACPI: ASF! 0x0000000087218728 0000A5 (v32 HPQOEM 81A1
00000001 HP 000F4240)
[ 0.000000] ACPI: BGRT 0x00000000872187D0 000038 (v01 HPQOEM 81A1
01072009 HP 00010013)
[ 0.000000] ACPI: Local APIC address 0xfee00000
[ 0.000000] No NUMA configuration found
[ 0.000000] Faking a node at [mem 0x0000000000000000-0x0000000473ffffff]
[ 0.000000] NODE_DATA(0) allocated [mem 0x473ff8000-0x473ffcfff]
[ 0.000000] Zone ranges:
[ 0.000000] DMA [mem 0x0000000000001000-0x0000000000ffffff]
[ 0.000000] DMA32 [mem 0x0000000001000000-0x00000000ffffffff]
[ 0.000000] Normal [mem 0x0000000100000000-0x0000000473ffffff]
[ 0.000000] Device empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000001000-0x0000000000057fff]
[ 0.000000] node 0: [mem 0x0000000000059000-0x000000000009dfff]
[ 0.000000] node 0: [mem 0x0000000000100000-0x000000007ec6dfff]
[ 0.000000] node 0: [mem 0x000000007ec99000-0x00000000864c7fff]
[ 0.000000] node 0: [mem 0x0000000087fff000-0x0000000087ffffff]
[ 0.000000] node 0: [mem 0x0000000100000000-0x0000000473ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000000001000-0x0000000473ffffff]
[ 0.000000] On node 0 totalpages: 4170810
[ 0.000000] DMA zone: 64 pages used for memmap
[ 0.000000] DMA zone: 22 pages reserved
[ 0.000000] DMA zone: 3996 pages, LIFO batch:0
[ 0.000000] DMA32 zone: 8531 pages used for memmap
[ 0.000000] DMA32 zone: 545950 pages, LIFO batch:31
[ 0.000000] Normal zone: 56576 pages used for memmap
[ 0.000000] Normal zone: 3620864 pages, LIFO batch:31
[ 0.000000] Reserving Intel graphics stolen memory at 0x89000000-0x8affffff
[ 0.000000] ACPI: PM-Timer IO Port: 0x1808
[ 0.000000] ACPI: Local APIC address 0xfee00000
[ 0.000000] ACPI: LAPIC_NMI (acpi_id[0x01] high edge lint[0x1])
[ 0.000000] ACPI: LAPIC_NMI (acpi_id[0x02] high edge lint[0x1])
[ 0.000000] ACPI: LAPIC_NMI (acpi_id[0x03] high edge lint[0x1])
[ 0.000000] ACPI: LAPIC_NMI (acpi_id[0x04] high edge lint[0x1])
[ 0.000000] IOAPIC[0]: apic_id 2, version 32, address 0xfec00000, GSI 0-119
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
[ 0.000000] ACPI: IRQ0 used by override.
[ 0.000000] ACPI: IRQ9 used by override.
[ 0.000000] Using ACPI (MADT) for SMP configuration information
[ 0.000000] ACPI: HPET id: 0x8086a701 base: 0xfed00000
[ 0.000000] smpboot: Allowing 4 CPUs, 0 hotplug CPUs
[ 0.000000] PM: Registered nosave memory: [mem 0x00000000-0x00000fff]
[ 0.000000] PM: Registered nosave memory: [mem 0x00058000-0x00058fff]
[ 0.000000] PM: Registered nosave memory: [mem 0x0009e000-0x0009ffff]
[ 0.000000] PM: Registered nosave memory: [mem 0x000a0000-0x000fffff]
[ 0.000000] PM: Registered nosave memory: [mem 0x7ec6e000-0x7ec6efff]
[ 0.000000] PM: Registered nosave memory: [mem 0x7ec6f000-0x7ec98fff]
[ 0.000000] PM: Registered nosave memory: [mem 0x864c8000-0x871ccfff]
[ 0.000000] PM: Registered nosave memory: [mem 0x871cd000-0x87218fff]
[ 0.000000] PM: Registered nosave memory: [mem 0x87219000-0x87b5afff]
[ 0.000000] PM: Registered nosave memory: [mem 0x87b5b000-0x87f68fff]
[ 0.000000] PM: Registered nosave memory: [mem 0x87f69000-0x87ffefff]
[ 0.000000] PM: Registered nosave memory: [mem 0x88000000-0x880fffff]
[ 0.000000] PM: Registered nosave memory: [mem 0x88100000-0x88ffffff]
[ 0.000000] PM: Registered nosave memory: [mem 0x89000000-0x8affffff]
[ 0.000000] PM: Registered nosave memory: [mem 0x8b000000-0xdfffffff]
[ 0.000000] PM: Registered nosave memory: [mem 0xe0000000-0xefffffff]
[ 0.000000] PM: Registered nosave memory: [mem 0xf0000000-0xfdffffff]
[ 0.000000] PM: Registered nosave memory: [mem 0xfe000000-0xfe010fff]
[ 0.000000] PM: Registered nosave memory: [mem 0xfe011000-0xfebfffff]
[ 0.000000] PM: Registered nosave memory: [mem 0xfec00000-0xfec00fff]
[ 0.000000] PM: Registered nosave memory: [mem 0xfec01000-0xfedfffff]
[ 0.000000] PM: Registered nosave memory: [mem 0xfee00000-0xfee00fff]
[ 0.000000] PM: Registered nosave memory: [mem 0xfee01000-0xfeffffff]
[ 0.000000] PM: Registered nosave memory: [mem 0xff000000-0xffffffff]
[ 0.000000] e820: [mem 0x8b000000-0xdfffffff] available for PCI devices
[ 0.000000] Booting paravirtualized kernel on bare hardware
[ 0.000000] clocksource: refined-jiffies: mask: 0xffffffff
max_cycles: 0xffffffff, max_idle_ns: 7645519600211568 ns
[ 0.000000] setup_percpu: NR_CPUS:8 nr_cpumask_bits:8 nr_cpu_ids:4
nr_node_ids:1
[ 0.000000] percpu: Embedded 32 pages/cpu @ffff880473c00000 s93080
r8192 d29800 u524288
[ 0.000000] pcpu-alloc: s93080 r8192 d29800 u524288 alloc=1*2097152
[ 0.000000] pcpu-alloc: [0] 0 1 2 3
[ 0.000000] Built 1 zonelists in Node order, mobility grouping on.
Total pages: 4105617
[ 0.000000] Policy zone: Normal
[ 0.000000] Kernel command line:
BOOT_IMAGE=/boot/vmlinuz-4.6.2-gcl1+
root=/dev/mapper/gladys--vg-debian ro quiet
[ 0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.000000] Memory: 16277592K/16683240K available (6489K kernel
code, 1150K rwdata, 2900K rodata, 1348K init, 792K bss, 405648K
reserved, 0K cma-reserved)
[ 0.000000] Hierarchical RCU implementation.
[ 0.000000] Build-time adjustment of leaf fanout to 64.
[ 0.000000] RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
[ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=4
[ 0.000000] NR_IRQS:4352 nr_irqs:1024 16
[ 0.000000] spurious 8259A interrupt: IRQ7.
[ 0.000000] Console: colour dummy device 80x25
[ 0.000000] console [tty0] enabled
[ 0.000000] clocksource: hpet: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 79635855245 ns
[ 0.000000] hpet clockevent registered
[ 0.000000] tsc: PIT calibration matches HPET. 1 loops
[ 0.000000] tsc: Detected 2591.938 MHz processor
[ 0.000022] Calibrating delay loop (skipped), value calculated
using timer frequency.. 5183.87 BogoMIPS (lpj=10367752)
[ 0.000024] pid_max: default: 32768 minimum: 301
[ 0.000032] ACPI: Core revision 20160108
[ 0.023560] ACPI Error: [\_SB_.PCI0.SAT1] Namespace lookup failure,
AE_NOT_FOUND (20160108/dswload-210)
[ 0.023564] ACPI Exception: AE_NOT_FOUND, During name
lookup/catalog (20160108/psobject-227)
[ 0.023617] ACPI Exception: AE_NOT_FOUND, (SSDT:81A1 ) while
loading table (20160108/tbxfload-227)
[ 0.032847] ACPI Error: 1 table load failures, 6 successful
(20160108/tbxfload-247)
[ 0.033067] Security Framework initialized
[ 0.033068] Yama: becoming mindful.
[ 0.033073] AppArmor: AppArmor disabled by boot time parameter
[ 0.033897] Dentry cache hash table entries: 2097152 (order: 12,
16777216 bytes)
[ 0.036231] Inode-cache hash table entries: 1048576 (order: 11,
8388608 bytes)
[ 0.037283] Mount-cache hash table entries: 32768 (order: 6, 262144 bytes)
[ 0.037297] Mountpoint-cache hash table entries: 32768 (order: 6,
262144 bytes)
[ 0.037509] CPU: Physical Processor ID: 0
[ 0.037510] CPU: Processor Core ID: 0
[ 0.037513] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
[ 0.037514] ENERGY_PERF_BIAS: View and update with x86_energy_perf_policy(8)
[ 0.037518] mce: CPU supports 8 MCE banks
[ 0.037530] CPU0: Thermal monitoring enabled (TM1)
[ 0.037537] process: using mwait in idle threads
[ 0.037539] Last level iTLB entries: 4KB 64, 2MB 8, 4MB 8
[ 0.037540] Last level dTLB entries: 4KB 64, 2MB 0, 4MB 0, 1GB 4
[ 0.037832] Freeing SMP alternatives memory: 28K (ffffffff81e72000
- ffffffff81e79000)
[ 0.041714] ftrace: allocating 25763 entries in 101 pages
[ 0.049725] smpboot: Max logical packages: 2
[ 0.049727] smpboot: APIC(0) Converting physical 0 to logical package 0
[ 0.049730] DMAR: Host address width 39
[ 0.049731] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[ 0.049737] DMAR: dmar0: reg_base_addr fed90000 ver 1:0 cap
1c0000c40660462 ecap 7e3ff0505e
[ 0.049738] DMAR: DRHD base: 0x000000fed91000 flags: 0x1
[ 0.049741] DMAR: dmar1: reg_base_addr fed91000 ver 1:0 cap
d2008c40660462 ecap f050da
[ 0.049742] DMAR: RMRR base: 0x00000086f6f000 end: 0x00000086f8efff
[ 0.049743] DMAR: RMRR base: 0x00000088800000 end: 0x0000008affffff
[ 0.049745] DMAR-IR: IOAPIC id 2 under DRHD base 0xfed91000 IOMMU 1
[ 0.049746] DMAR-IR: HPET id 0 under DRHD base 0xfed91000
[ 0.049746] DMAR-IR: x2apic is disabled because BIOS sets x2apic opt out bit.
[ 0.049748] DMAR-IR: Use 'intremap=no_x2apic_optout' to override
the BIOS setting.
[ 0.051125] DMAR-IR: Enabled IRQ remapping in xapic mode
[ 0.051126] x2apic: IRQ remapping doesn't support X2APIC mode
[ 0.055103] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
[ 0.094793] TSC deadline timer enabled
[ 0.094798] smpboot: CPU0: Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
(family: 0x6, model: 0x4e, stepping: 0x3)
[ 0.094811] Performance Events: PEBS fmt3+, 32-deep LBR, Skylake
events, full-width counters, Intel PMU driver.
[ 0.094833] ... version: 4
[ 0.094834] ... bit width: 48
[ 0.094835] ... generic registers: 4
[ 0.094835] ... value mask: 0000ffffffffffff
[ 0.094836] ... max period: 0000ffffffffffff
[ 0.094836] ... fixed-purpose events: 3
[ 0.094837] ... event mask: 000000070000000f
[ 0.095242] NMI watchdog: enabled on all CPUs, permanently consumes
one hw-PMU counter.
[ 0.095308] x86: Booting SMP configuration:
[ 0.095309] .... node #0, CPUs: #1 #2 #3
[ 0.336932] x86: Booted up 1 node, 4 CPUs
[ 0.336935] smpboot: Total of 4 processors activated (20738.16 BogoMIPS)
[ 0.340871] devtmpfs: initialized
[ 0.340918] x86/mm: Memory block size: 128MB
[ 0.343217] PM: Registering ACPI NVS region [mem
0x7ec6e000-0x7ec6efff] (4096 bytes)
[ 0.343218] PM: Registering ACPI NVS region [mem
0x87219000-0x87b5afff] (9707520 bytes)
[ 0.343394] clocksource: jiffies: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 7645041785100000 ns
[ 0.343471] pinctrl core: initialized pinctrl subsystem
[ 0.343581] NET: Registered protocol family 16
[ 0.352543] cpuidle: using governor ladder
[ 0.360957] cpuidle: using governor menu
[ 0.361011] ACPI: bus type PCI registered
[ 0.361013] acpiphp: ACPI Hot Plug PCI Controller Driver version: 0.5
[ 0.361079] PCI: MMCONFIG for domain 0000 [bus 00-ff] at [mem
0xe0000000-0xefffffff] (base 0xe0000000)
[ 0.361080] PCI: MMCONFIG at [mem 0xe0000000-0xefffffff] reserved in E820
[ 0.361091] PCI: Using configuration type 1 for base access
[ 0.372676] HugeTLB registered 1 GB page size, pre-allocated 0 pages
[ 0.372677] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[ 0.372896] ACPI: Added _OSI(Module Device)
[ 0.372898] ACPI: Added _OSI(Processor Device)
[ 0.372899] ACPI: Added _OSI(3.0 _SCP Extensions)
[ 0.372900] ACPI: Added _OSI(Processor Aggregator Device)
[ 0.374175] ACPI: Executed 24 blocks of module-level executable AML code
[ 0.383839] [Firmware Bug]: ACPI: BIOS _OSI(Linux) query ignored
[ 0.386855] ACPI: Dynamic OEM Table Load:
[ 0.386860] ACPI: SSDT 0xFFFF8804630EA800 000660 (v02 PmRef
Cpu0Ist 00003000 INTL 20120913)
[ 0.387724] ACPI: \_PR_.CPU0: _OSC native thermal LVT Acked
[ 0.389154] ACPI: Dynamic OEM Table Load:
[ 0.389159] ACPI: SSDT 0xFFFF880460C20400 00037F (v02 PmRef
Cpu0Cst 00003001 INTL 20120913)
[ 0.390513] ACPI: Dynamic OEM Table Load:
[ 0.390518] ACPI: SSDT 0xFFFF8804630EA000 0005AA (v02 PmRef ApIst
00003000 INTL 20120913)
[ 0.391507] ACPI: Dynamic OEM Table Load:
[ 0.391510] ACPI: SSDT 0xFFFF880460D87E00 000119 (v02 PmRef ApCst
00003000 INTL 20120913)
[ 0.393865] ACPI : EC: EC started
[ 0.404894] ACPI: Interpreter enabled
[ 0.404923] ACPI: (supports S0 S3 S4 S5)
[ 0.404924] ACPI: Using IOAPIC for interrupt routing
[ 0.404951] PCI: Using host bridge windows from ACPI; if necessary,
use "pci=nocrs" and report a bug
[ 0.406634] ACPI: Power Resource [PG00] (on)
[ 0.406893] ACPI: Power Resource [PG01] (on)
[ 0.407144] ACPI: Power Resource [PG02] (on)
[ 0.408459] ACPI: Power Resource [WRST] (off)
[ 0.408713] ACPI: Power Resource [WRST] (off)
[ 0.408966] ACPI: Power Resource [WRST] (off)
[ 0.409222] ACPI: Power Resource [WRST] (off)
[ 0.409476] ACPI: Power Resource [WRST] (off)
[ 0.409738] ACPI: Power Resource [WRST] (off)
[ 0.410187] ACPI: Power Resource [WRST] (off)
[ 0.410439] ACPI: Power Resource [WRST] (off)
[ 0.410690] ACPI: Power Resource [WRST] (off)
[ 0.411294] ACPI: Power Resource [WRST] (off)
[ 0.411547] ACPI: Power Resource [WRST] (off)
[ 0.411798] ACPI: Power Resource [WRST] (off)
[ 0.412049] ACPI: Power Resource [WRST] (off)
[ 0.412301] ACPI: Power Resource [WRST] (off)
[ 0.412554] ACPI: Power Resource [WRST] (off)
[ 0.412805] ACPI: Power Resource [WRST] (off)
[ 0.413062] ACPI: Power Resource [WRST] (off)
[ 0.413314] ACPI: Power Resource [WRST] (off)
[ 0.413566] ACPI: Power Resource [WRST] (off)
[ 0.413817] ACPI: Power Resource [WRST] (off)
[ 0.421419] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-fe])
[ 0.421424] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM
ClockPM Segments MSI]
[ 0.422692] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME
AER PCIeCapability]
[ 0.423177] PCI host bridge to bus 0000:00
[ 0.423179] pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7 window]
[ 0.423181] pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window]
[ 0.423182] pci_bus 0000:00: root bus resource [mem
0x000a0000-0x000bffff window]
[ 0.423183] pci_bus 0000:00: root bus resource [mem
0x000c0000-0x000c3fff window]
[ 0.423183] pci_bus 0000:00: root bus resource [mem
0x000c4000-0x000c7fff window]
[ 0.423184] pci_bus 0000:00: root bus resource [mem
0x000c8000-0x000cbfff window]
[ 0.423186] pci_bus 0000:00: root bus resource [mem
0x000cc000-0x000cffff window]
[ 0.423187] pci_bus 0000:00: root bus resource [mem
0x000d0000-0x000d3fff window]
[ 0.423188] pci_bus 0000:00: root bus resource [mem
0x000d4000-0x000d7fff window]
[ 0.423188] pci_bus 0000:00: root bus resource [mem
0x000d8000-0x000dbfff window]
[ 0.423189] pci_bus 0000:00: root bus resource [mem
0x000dc000-0x000dffff window]
[ 0.423190] pci_bus 0000:00: root bus resource [mem
0x8b000000-0xdfffffff window]
[ 0.423191] pci_bus 0000:00: root bus resource [mem
0xfd000000-0xfe7fffff window]
[ 0.423193] pci_bus 0000:00: root bus resource [bus 00-fe]
[ 0.423198] pci 0000:00:00.0: [8086:1904] type 00 class 0x060000
[ 0.423448] pci 0000:00:02.0: [8086:1916] type 00 class 0x030000
[ 0.423455] pci 0000:00:02.0: reg 0x10: [mem 0xde000000-0xdeffffff 64bit]
[ 0.423460] pci 0000:00:02.0: reg 0x18: [mem 0xc0000000-0xcfffffff
64bit pref]
[ 0.423463] pci 0000:00:02.0: reg 0x20: [io 0xf000-0xf03f]
[ 0.423623] pci 0000:00:13.0: [8086:9d35] type 00 class 0x000000
[ 0.423640] pci 0000:00:13.0: reg 0x10: [mem 0xdf32b000-0xdf32bfff 64bit]
[ 0.423790] pci 0000:00:14.0: [8086:9d2f] type 00 class 0x0c0330
[ 0.423808] pci 0000:00:14.0: reg 0x10: [mem 0xdf310000-0xdf31ffff 64bit]
[ 0.423873] pci 0000:00:14.0: PME# supported from D3hot D3cold
[ 0.423957] pci 0000:00:14.0: System wakeup disabled by ACPI
[ 0.423988] pci 0000:00:14.2: [8086:9d31] type 00 class 0x118000
[ 0.424005] pci 0000:00:14.2: reg 0x10: [mem 0xdf32a000-0xdf32afff 64bit]
[ 0.424153] pci 0000:00:16.0: [8086:9d3a] type 00 class 0x078000
[ 0.424167] pci 0000:00:16.0: reg 0x10: [mem 0xdf329000-0xdf329fff 64bit]
[ 0.424215] pci 0000:00:16.0: PME# supported from D3hot
[ 0.424345] pci 0000:00:1c.0: [8086:9d10] type 01 class 0x060400
[ 0.424400] pci 0000:00:1c.0: PME# supported from D0 D3hot D3cold
[ 0.424500] pci 0000:00:1c.0: System wakeup disabled by ACPI
[ 0.424527] pci 0000:00:1c.1: [8086:9d11] type 01 class 0x060400
[ 0.424583] pci 0000:00:1c.1: PME# supported from D0 D3hot D3cold
[ 0.424680] pci 0000:00:1c.1: System wakeup disabled by ACPI
[ 0.424713] pci 0000:00:1c.4: [8086:9d14] type 01 class 0x060400
[ 0.424775] pci 0000:00:1c.4: PME# supported from D0 D3hot D3cold
[ 0.424874] pci 0000:00:1c.4: System wakeup disabled by ACPI
[ 0.424917] pci 0000:00:1f.0: [8086:9d48] type 00 class 0x060100
[ 0.425114] pci 0000:00:1f.2: [8086:9d21] type 00 class 0x058000
[ 0.425122] pci 0000:00:1f.2: reg 0x10: [mem 0xdf324000-0xdf327fff]
[ 0.425258] pci 0000:00:1f.3: [8086:9d70] type 00 class 0x040100
[ 0.425277] pci 0000:00:1f.3: reg 0x10: [mem 0xdf320000-0xdf323fff 64bit]
[ 0.425302] pci 0000:00:1f.3: reg 0x20: [mem 0xdf300000-0xdf30ffff 64bit]
[ 0.425348] pci 0000:00:1f.3: PME# supported from D3hot D3cold
[ 0.425475] pci 0000:00:1f.3: System wakeup disabled by ACPI
[ 0.425507] pci 0000:00:1f.4: [8086:9d23] type 00 class 0x0c0500
[ 0.425554] pci 0000:00:1f.4: reg 0x10: [mem 0xdf328000-0xdf3280ff 64bit]
[ 0.425623] pci 0000:00:1f.4: reg 0x20: [io 0xf040-0xf05f]
[ 0.425851] pci 0000:01:00.0: [10ec:5227] type 00 class 0xff0000
[ 0.425871] pci 0000:01:00.0: reg 0x10: [mem 0xdf200000-0xdf200fff]
[ 0.425987] pci 0000:01:00.0: supports D1 D2
[ 0.425988] pci 0000:01:00.0: PME# supported from D1 D2 D3hot D3cold
[ 0.426064] pci 0000:01:00.0: System wakeup disabled by ACPI
[ 0.433081] pci 0000:00:1c.0: PCI bridge to [bus 01]
[ 0.433086] pci 0000:00:1c.0: bridge window [mem 0xdf200000-0xdf2fffff]
[ 0.433297] pci 0000:02:00.0: [8086:095a] type 00 class 0x028000
[ 0.433375] pci 0000:02:00.0: reg 0x10: [mem 0xdf100000-0xdf101fff 64bit]
[ 0.433630] pci 0000:02:00.0: PME# supported from D0 D3hot D3cold
[ 0.433825] pci 0000:02:00.0: System wakeup disabled by ACPI
[ 0.441226] pci 0000:00:1c.1: PCI bridge to [bus 02]
[ 0.441231] pci 0000:00:1c.1: bridge window [mem 0xdf100000-0xdf1fffff]
[ 0.441566] pci 0000:03:00.0: [1179:010f] type 00 class 0x010802
[ 0.441584] pci 0000:03:00.0: reg 0x10: [mem 0xdf000000-0xdf003fff 64bit]
[ 0.441739] pci 0000:03:00.0: System wakeup disabled by ACPI
[ 0.449360] pci 0000:00:1c.4: PCI bridge to [bus 03]
[ 0.449364] pci 0000:00:1c.4: bridge window [mem 0xdf000000-0xdf0fffff]
[ 0.451348] ACPI: PCI Interrupt Link [LNKA] (IRQs 3 4 5 6 10 *11 12 14 15)
[ 0.451395] ACPI: PCI Interrupt Link [LNKB] (IRQs 3 4 5 6 *10 11 12 14 15)
[ 0.451440] ACPI: PCI Interrupt Link [LNKC] (IRQs 3 4 5 6 10 *11 12 14 15)
[ 0.451485] ACPI: PCI Interrupt Link [LNKD] (IRQs 3 4 5 6 10 *11 12 14 15)
[ 0.451529] ACPI: PCI Interrupt Link [LNKE] (IRQs 3 4 5 6 10 *11 12 14 15)
[ 0.451574] ACPI: PCI Interrupt Link [LNKF] (IRQs 3 4 5 6 10 *11 12 14 15)
[ 0.451619] ACPI: PCI Interrupt Link [LNKG] (IRQs 3 4 5 6 10 *11 12 14 15)
[ 0.451663] ACPI: PCI Interrupt Link [LNKH] (IRQs 3 4 5 6 10 *11 12 14 15)
[ 0.452452] ACPI: Enabled 5 GPEs in block 00 to 7F
[ 0.452546] ACPI : EC: GPE = 0x17, I/O: command/status = 0x66, data = 0x62
[ 0.452618] vgaarb: setting as boot device: PCI:0000:00:02.0
[ 0.452619] vgaarb: device added:
PCI:0000:00:02.0,decodes=io+mem,owns=io+mem,locks=none
[ 0.452622] vgaarb: loaded
[ 0.452622] vgaarb: bridge control possible 0000:00:02.0
[ 0.452729] PCI: Using ACPI for IRQ routing
[ 0.480782] PCI: pci_cache_line_size set to 64 bytes
[ 0.481376] e820: reserve RAM buffer [mem 0x00058000-0x0005ffff]
[ 0.481377] e820: reserve RAM buffer [mem 0x0009e000-0x0009ffff]
[ 0.481378] e820: reserve RAM buffer [mem 0x7ec6e000-0x7fffffff]
[ 0.481379] e820: reserve RAM buffer [mem 0x864c8000-0x87ffffff]
[ 0.481524] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0, 0, 0, 0, 0, 0
[ 0.481528] hpet0: 8 comparators, 64-bit 24.000000 MHz counter
[ 0.483569] clocksource: Switched to clocksource hpet
[ 0.488311] VFS: Disk quotas dquot_6.6.0
[ 0.488343] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[ 0.488441] pnp: PnP ACPI init
[ 0.488612] system 00:00: [io 0x0680-0x069f] has been reserved
[ 0.488613] system 00:00: [io 0xffff] has been reserved
[ 0.488614] system 00:00: [io 0xffff] has been reserved
[ 0.488615] system 00:00: [io 0xffff] has been reserved
[ 0.488617] system 00:00: [io 0x1800-0x18fe] could not be reserved
[ 0.488618] system 00:00: [io 0x164e-0x164f] has been reserved
[ 0.488620] system 00:00: Plug and Play ACPI device, IDs PNP0c02 (active)
[ 0.488690] pnp 00:01: Plug and Play ACPI device, IDs PNP0b00 (active)
[ 0.488717] system 00:02: [io 0x1854-0x1857] has been reserved
[ 0.488719] system 00:02: Plug and Play ACPI device, IDs INT3f0d
PNP0c02 (active)
[ 0.488750] pnp 00:03: Plug and Play ACPI device, IDs HPQ8001
PNP0303 (active)
[ 0.488772] pnp 00:04: Plug and Play ACPI device, IDs SYN3206
SYN1e00 SYN0002 PNP0f13 (active)
[ 0.488931] system 00:05: [mem 0xfed10000-0xfed17fff] has been reserved
[ 0.488933] system 00:05: [mem 0xfed18000-0xfed18fff] has been reserved
[ 0.488934] system 00:05: [mem 0xfed19000-0xfed19fff] has been reserved
[ 0.488935] system 00:05: [mem 0xe0000000-0xefffffff] has been reserved
[ 0.488936] system 00:05: [mem 0xfed20000-0xfed3ffff] has been reserved
[ 0.488937] system 00:05: [mem 0xfed90000-0xfed93fff] could not be reserved
[ 0.488938] system 00:05: [mem 0xfed45000-0xfed8ffff] has been reserved
[ 0.488940] system 00:05: [mem 0xff000000-0xffffffff] has been reserved
[ 0.488941] system 00:05: [mem 0xfee00000-0xfeefffff] could not be reserved
[ 0.488942] system 00:05: [mem 0xdffe0000-0xdfffffff] has been reserved
[ 0.488944] system 00:05: Plug and Play ACPI device, IDs PNP0c02 (active)
[ 0.488972] system 00:06: [mem 0xfd000000-0xfdabffff] has been reserved
[ 0.488974] system 00:06: [mem 0xfdad0000-0xfdadffff] has been reserved
[ 0.488975] system 00:06: [mem 0xfdb00000-0xfdffffff] has been reserved
[ 0.488976] system 00:06: [mem 0xfe000000-0xfe01ffff] could not be reserved
[ 0.488977] system 00:06: [mem 0xfe036000-0xfe03bfff] has been reserved
[ 0.488978] system 00:06: [mem 0xfe03d000-0xfe3fffff] has been reserved
[ 0.488979] system 00:06: [mem 0xfe410000-0xfe7fffff] has been reserved
[ 0.488981] system 00:06: Plug and Play ACPI device, IDs PNP0c02 (active)
[ 0.489189] system 00:07: [io 0xff00-0xfffe] has been reserved
[ 0.489190] system 00:07: Plug and Play ACPI device, IDs PNP0c02 (active)
[ 0.489971] system 00:08: [mem 0xfe029000-0xfe029fff] has been reserved
[ 0.489972] system 00:08: [mem 0xfe028000-0xfe028fff] has been reserved
[ 0.489973] system 00:08: [mem 0xfdaf0000-0xfdafffff] has been reserved
[ 0.489975] system 00:08: [mem 0xfdae0000-0xfdaeffff] has been reserved
[ 0.489976] system 00:08: [mem 0xfdac0000-0xfdacffff] has been reserved
[ 0.489977] system 00:08: Plug and Play ACPI device, IDs PNP0c02 (active)
[ 0.491313] pnp: PnP ACPI: found 9 devices
[ 0.499891] clocksource: acpi_pm: mask: 0xffffff max_cycles:
0xffffff, max_idle_ns: 2085701024 ns
[ 0.499912] pci 0000:00:1c.0: PCI bridge to [bus 01]
[ 0.499916] pci 0000:00:1c.0: bridge window [mem 0xdf200000-0xdf2fffff]
[ 0.499921] pci 0000:00:1c.1: PCI bridge to [bus 02]
[ 0.499924] pci 0000:00:1c.1: bridge window [mem 0xdf100000-0xdf1fffff]
[ 0.499930] pci 0000:00:1c.4: PCI bridge to [bus 03]
[ 0.499933] pci 0000:00:1c.4: bridge window [mem 0xdf000000-0xdf0fffff]
[ 0.499939] pci_bus 0000:00: resource 4 [io 0x0000-0x0cf7 window]
[ 0.499940] pci_bus 0000:00: resource 5 [io 0x0d00-0xffff window]
[ 0.499941] pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff window]
[ 0.499942] pci_bus 0000:00: resource 7 [mem 0x000c0000-0x000c3fff window]
[ 0.499943] pci_bus 0000:00: resource 8 [mem 0x000c4000-0x000c7fff window]
[ 0.499944] pci_bus 0000:00: resource 9 [mem 0x000c8000-0x000cbfff window]
[ 0.499945] pci_bus 0000:00: resource 10 [mem 0x000cc000-0x000cffff window]
[ 0.499946] pci_bus 0000:00: resource 11 [mem 0x000d0000-0x000d3fff window]
[ 0.499947] pci_bus 0000:00: resource 12 [mem 0x000d4000-0x000d7fff window]
[ 0.499948] pci_bus 0000:00: resource 13 [mem 0x000d8000-0x000dbfff window]
[ 0.499949] pci_bus 0000:00: resource 14 [mem 0x000dc000-0x000dffff window]
[ 0.499950] pci_bus 0000:00: resource 15 [mem 0x8b000000-0xdfffffff window]
[ 0.499950] pci_bus 0000:00: resource 16 [mem 0xfd000000-0xfe7fffff window]
[ 0.499952] pci_bus 0000:01: resource 1 [mem 0xdf200000-0xdf2fffff]
[ 0.499953] pci_bus 0000:02: resource 1 [mem 0xdf100000-0xdf1fffff]
[ 0.499953] pci_bus 0000:03: resource 1 [mem 0xdf000000-0xdf0fffff]
[ 0.500108] NET: Registered protocol family 2
[ 0.500295] TCP established hash table entries: 131072 (order: 8,
1048576 bytes)
[ 0.500434] TCP bind hash table entries: 65536 (order: 8, 1048576 bytes)
[ 0.500532] TCP: Hash tables configured (established 131072 bind 65536)
[ 0.500550] UDP hash table entries: 8192 (order: 6, 262144 bytes)
[ 0.500584] UDP-Lite hash table entries: 8192 (order: 6, 262144 bytes)
[ 0.500717] NET: Registered protocol family 1
[ 0.500729] pci 0000:00:02.0: Video device with shadowed ROM at
[mem 0x000c0000-0x000dffff]
[ 0.501934] PCI: CLS 0 bytes, default 64
[ 0.501965] Unpacking initramfs...
[ 0.726991] Freeing initrd memory: 16284K (ffff880036022000 -
ffff880037009000)
[ 0.727012] PCI-DMA: Using software bounce buffering for IO (SWIOTLB)
[ 0.727014] software IO TLB [mem 0x806f3000-0x846f3000] (64MB)
mapped at [ffff8800806f3000-ffff8800846f2fff]
[ 0.727148] simple-framebuffer simple-framebuffer.0: framebuffer at
0xc0000000, 0x1d5000 bytes, mapped to 0xffffc90001c00000
[ 0.727150] simple-framebuffer simple-framebuffer.0:
format=a8r8g8b8, mode=800x600x32, linelength=3200
[ 0.728026] Console: switching to colour frame buffer device 100x37
[ 0.728724] simple-framebuffer simple-framebuffer.0: fb0: simplefb
registered!
[ 0.728939] futex hash table entries: 1024 (order: 4, 65536 bytes)
[ 0.728986] audit: initializing netlink subsys (disabled)
[ 0.728999] audit: type=2000 audit(1465914671.728:1): initialized
[ 0.729302] Initialise system trusted keyring
[ 0.729499] workingset: timestamp_bits=37 max_order=22 bucket_order=0
[ 0.729536] zbud: loaded
[ 0.730142] romfs: ROMFS MTD (C) 2007 Red Hat, Inc.
[ 0.761502] Key type asymmetric registered
[ 0.761505] Asymmetric key parser 'x509' registered
[ 0.761541] Block layer SCSI generic (bsg) driver version 0.4
loaded (major 250)
[ 0.761595] io scheduler noop registered
[ 0.761598] io scheduler deadline registered
[ 0.761655] io scheduler cfq registered (default)
[ 0.762173] aer 0000:00:1c.0:pcie02: service driver aer loaded
[ 0.762194] aer 0000:00:1c.1:pcie02: service driver aer loaded
[ 0.762216] aer 0000:00:1c.4:pcie02: service driver aer loaded
[ 0.762227] pcieport 0000:00:1c.0: Signaling PME through PCIe PME interrupt
[ 0.762228] pci 0000:01:00.0: Signaling PME through PCIe PME interrupt
[ 0.762230] pcie_pme 0000:00:1c.0:pcie01: service driver pcie_pme loaded
[ 0.762236] pcieport 0000:00:1c.1: Signaling PME through PCIe PME interrupt
[ 0.762237] pci 0000:02:00.0: Signaling PME through PCIe PME interrupt
[ 0.762239] pcie_pme 0000:00:1c.1:pcie01: service driver pcie_pme loaded
[ 0.762246] pcieport 0000:00:1c.4: Signaling PME through PCIe PME interrupt
[ 0.762246] pci 0000:03:00.0: Signaling PME through PCIe PME interrupt
[ 0.762249] pcie_pme 0000:00:1c.4:pcie01: service driver pcie_pme loaded
[ 0.762253] pci_hotplug: PCI Hot Plug PCI Core version: 0.5
[ 0.762257] pciehp: PCI Express Hot Plug Controller Driver version: 0.4
[ 0.762272] intel_idle: MWAIT substates: 0x11142120
[ 0.762272] intel_idle: v0.4.1 model 0x4E
[ 0.762435] intel_idle: lapic_timer_reliable_states 0xffffffff
[ 0.762475] GHES: HEST is not enabled!
[ 0.762542] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[ 0.763007] Linux agpgart interface v0.103
[ 0.763305] i8042: PNP: PS/2 Controller [PNP0303:PS2K,PNP0f13:PS2M]
at 0x60,0x64 irq 1,12
[ 0.770763] serio: i8042 KBD port at 0x60,0x64 irq 1
[ 0.770765] serio: i8042 AUX port at 0x60,0x64 irq 12
[ 0.771027] mousedev: PS/2 mouse device common for all mice
[ 0.771285] rtc_cmos 00:01: RTC can wake from S4
[ 0.771880] rtc_cmos 00:01: rtc core: registered rtc_cmos as rtc0
[ 0.771959] rtc_cmos 00:01: alarms up to one month, y3k, 242 bytes
nvram, hpet irqs
[ 0.771966] Intel P-state driver initializing.
[ 0.823816] intel_pstate: HWP enabled
[ 0.823828] ledtrig-cpu: registered to indicate activity on CPUs
[ 0.824036] EFI Variables Facility v0.08 2004-May-17
[ 0.828778] pstore: Registered efi as persistent store backend
[ 0.828796] hidraw: raw HID events driver (C) Jiri Kosina
[ 0.829052] intel_ish_ipc 0000:00:13.0: enabling device (0000 -> 0002)
[ 0.845705] input: AT Translated Set 2 keyboard as
/devices/platform/i8042/serio0/input/input0
[ 1.340502] NET: Registered protocol family 10
[ 1.340790] mip6: Mobile IPv6
[ 1.340793] NET: Registered protocol family 17
[ 1.340801] mpls_gso: MPLS GSO support
[ 1.341059] microcode: CPU0 sig=0x406e3, pf=0x80, revision=0x88
[ 1.341074] microcode: CPU1 sig=0x406e3, pf=0x80, revision=0x88
[ 1.341093] microcode: CPU2 sig=0x406e3, pf=0x80, revision=0x88
[ 1.341098] microcode: CPU3 sig=0x406e3, pf=0x80, revision=0x88
[ 1.341178] microcode: Microcode Update Driver: v2.01
<tig...@aivazian.fsnet.co.uk>, Peter Oruba
[ 1.341458] registered taskstats version 1
[ 1.341467] Loading compiled-in X.509 certificates
[ 1.341497] zswap: loaded using pool lzo/zbud
[ 1.342687] Key type encrypted registered
[ 1.344160] rtc_cmos 00:01: setting system clock to 2016-06-14
14:31:13 UTC (1465914673)
[ 1.345282] ish {33AECD58-B679-4E54-9BD9-A04D34F0C226}: [hid-ish]:
enum_devices_done OK, num_hid_devices=6
[ 1.386370] PM: Hibernation image not present or could not be loaded.
[ 1.387185] Freeing unused kernel memory: 1348K (ffffffff81d21000 -
ffffffff81e72000)
[ 1.387186] Write protecting the kernel read-only data: 12288k
[ 1.387678] Freeing unused kernel memory: 1688K (ffff880002a5a000 -
ffff880002c00000)
[ 1.389292] Freeing unused kernel memory: 1196K (ffff880002ed5000 -
ffff880003000000)
[ 1.394109] x86/mm: Checked W+X mappings: passed, no W+X pages found.
[ 1.436305] random: systemd-udevd urandom read with 17 bits of
entropy available
[ 1.456514] fjes: module verification failed: signature and/or
required key missing - tainting kernel
[ 1.456707] FUJITSU Extended Socket Network Device Driver - version
1.0 - Copyright (c) 2015 FUJITSU LIMITED
[ 1.480814] [Firmware Bug]: Invalid critical threshold (0)
[ 1.483549] thermal LNXTHERM:00: registered as thermal_zone0
[ 1.483551] ACPI: Thermal Zone [TZ01] (45 C)
[ 1.491312] rtsx_pci 0000:01:00.0: enabling device (0000 -> 0002)
[ 1.491433] rtsx_pci 0000:01:00.0: rtsx_pci_acquire_irq:
pcr->msi_en = 1, pci->irq = 145
[ 1.491796] ACPI: bus type USB registered
[ 1.491816] usbcore: registered new interface driver usbfs
[ 1.491847] usbcore: registered new interface driver hub
[ 1.491888] usbcore: registered new device driver usb
[ 1.493088] xhci_hcd 0000:00:14.0: xHCI Host Controller
[ 1.493096] xhci_hcd 0000:00:14.0: new USB bus registered, assigned
bus number 1
[ 1.493142] nvme nvme0: pci function 0000:03:00.0
[ 1.494298] xhci_hcd 0000:00:14.0: hcc params 0x200077c1 hci
version 0x100 quirks 0x00109810
[ 1.494316] xhci_hcd 0000:00:14.0: cache line size of 64 is not supported
[ 1.494490] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[ 1.494492] usb usb1: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[ 1.494493] usb usb1: Product: xHCI Host Controller
[ 1.494494] usb usb1: Manufacturer: Linux 4.6.2-gcl1+ xhci-hcd
[ 1.494495] usb usb1: SerialNumber: 0000:00:14.0
[ 1.494690] hub 1-0:1.0: USB hub found
[ 1.494757] hub 1-0:1.0: 12 ports detected
[ 1.501134] xhci_hcd 0000:00:14.0: xHCI Host Controller
[ 1.501138] xhci_hcd 0000:00:14.0: new USB bus registered, assigned
bus number 2
[ 1.501197] usb usb2: New USB device found, idVendor=1d6b, idProduct=0003
[ 1.501198] usb usb2: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[ 1.501199] usb usb2: Product: xHCI Host Controller
[ 1.501200] usb usb2: Manufacturer: Linux 4.6.2-gcl1+ xhci-hcd
[ 1.501201] usb usb2: SerialNumber: 0000:00:14.0
[ 1.501351] hub 2-0:1.0: USB hub found
[ 1.501362] hub 2-0:1.0: 6 ports detected
[ 1.504015] usb: port power management may be unreliable
[ 1.702796] nvme0n1: p1 p2 p3 p4 p5 p6
[ 1.727710] tsc: Refined TSC clocksource calibration: 2591.987 MHz
[ 1.727720] clocksource: tsc: mask: 0xffffffffffffffff max_cycles:
0x255caa87895, max_idle_ns: 440795290362 ns
[ 1.867746] usb 1-6: new high-speed USB device number 2 using xhci_hcd
[ 2.061667] usb 1-6: New USB device found, idVendor=1bcf, idProduct=2c7d
[ 2.061675] usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 2.061680] usb 1-6: Product: HP Truevision Full HD
[ 2.061683] usb 1-6: Manufacturer: DEKHP029I1833A
[ 2.231826] usb 1-7: new full-speed USB device number 3 using xhci_hcd
[ 2.339551] psmouse serio1: synaptics: queried max coordinates: x
[..5610], y [..4700]
[ 2.378122] psmouse serio1: synaptics: queried min coordinates: x
[1394..], y [1238..]
[ 2.418612] usb 1-7: New USB device found, idVendor=8087, idProduct=0a2a
[ 2.418619] usb 1-7: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.454739] psmouse serio1: synaptics: Touchpad model: 1, fw: 8.2,
id: 0x1e2b1, caps: 0xf00123/0x840300/0x12e800/0x0, board id: 2869, fw
id: 1953112
[ 2.503796] input: SynPS/2 Synaptics TouchPad as
/devices/platform/i8042/serio1/input/input2
[ 2.569517] device-mapper: uevent: version 1.0.3
[ 2.569613] device-mapper: ioctl: 4.34.0-ioctl (2015-10-28)
initialised: dm-d...@redhat.com
[ 2.587719] usb 1-8: new full-speed USB device number 4 using xhci_hcd
[ 2.600433] EXT4-fs (dm-0): mounted filesystem with ordered data
mode. Opts: (null)
[ 2.652860] systemd[1]: RTC configured in localtime, applying delta
of 60 minutes to system time.
[ 2.688589] systemd[1]: systemd 230 running in system mode. (+PAM
+AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP
+GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN)
[ 2.688763] systemd[1]: Detected architecture x86-64.
[ 2.688966] systemd[1]: Set hostname to <gladys>.
[ 2.727929] clocksource: Switched to clocksource tsc
[ 2.733963] systemd[1]: Listening on udev Kernel Socket.
[ 2.734016] systemd[1]: Listening on /dev/initctl Compatibility Named Pipe.
[ 2.734043] systemd[1]: Started Forward Password Requests to Wall
Directory Watch.
[ 2.734050] systemd[1]: Reached target User and Group Name Lookups.
[ 2.734056] systemd[1]: Reached target Remote File Systems (Pre).
[ 2.734061] systemd[1]: Reached target Encrypted Volumes.
[ 2.734080] systemd[1]: Listening on Syslog Socket.
[ 2.734133] systemd[1]: Listening on Journal Audit Socket.
[ 2.734142] systemd[1]: Reached target Remote File Systems.
[ 2.734211] systemd[1]: Created slice User and Session Slice.
[ 2.734231] systemd[1]: Listening on LVM2 poll daemon socket.
[ 2.734242] systemd[1]: Listening on LVM2 metadata daemon socket.
[ 2.734262] systemd[1]: Listening on udev Control Socket.
[ 2.734281] systemd[1]: Listening on Device-mapper event daemon FIFOs.
[ 2.734293] systemd[1]: Listening on fsck to fsckd communication Socket.
[ 2.734344] systemd[1]: Created slice System Slice.
[ 2.734356] systemd[1]: Reached target Slices.
[ 2.734409] systemd[1]: Created slice system-getty.slice.
[ 2.734458] systemd[1]: Created slice system-systemd\x2dfsck.slice.
[ 2.734483] systemd[1]: Listening on Journal Socket.
[ 2.755975] systemd[1]: Starting Set the console keyboard layout...
[ 2.756498] systemd[1]: Mounting Huge Pages File System...
[ 2.757105] systemd[1]: Mounting POSIX Message Queue File System...
[ 2.757483] systemd[1]: Starting Monitoring of LVM2 mirrors,
snapshots etc. using dmeventd or progress polling...
[ 2.757908] systemd[1]: Mounting Debug File System...
[ 2.758175] systemd[1]: Set up automount Arbitrary Executable File
Formats File System Automount Point.
[ 2.759703] systemd[1]: Listening on Journal Socket (/dev/log).
[ 2.760083] systemd[1]: Starting Journal Service...
[ 2.760415] systemd[1]: Starting Remount Root and Kernel File Systems...
[ 2.760797] systemd[1]: Starting Create list of required static
device nodes for the current kernel...
[ 2.760875] systemd[1]: Started Dispatch Password Requests to
Console Directory Watch.
[ 2.764433] systemd[1]: Starting Load Kernel Modules...
[ 2.765439] systemd[1]: Mounted Debug File System.
[ 2.765459] systemd[1]: Mounted POSIX Message Queue File System.
[ 2.765469] systemd[1]: Mounted Huge Pages File System.
[ 2.765758] systemd[1]: Started Create list of required static
device nodes for the current kernel.
[ 2.765931] EXT4-fs (dm-0): re-mounted. Opts: errors=remount-ro
[ 2.766529] systemd[1]: Started Remount Root and Kernel File Systems.
[ 2.767188] systemd[1]: Started LVM2 metadata daemon.
[ 2.767585] systemd[1]: Starting Load/Save Random Seed...
[ 2.769278] systemd[1]: Starting udev Coldplug all Devices...
[ 2.769697] systemd[1]: Starting Create Static Device Nodes in /dev...
[ 2.771286] systemd[1]: Started Load Kernel Modules.
[ 2.771487] systemd[1]: Started Load/Save Random Seed.
[ 2.776112] systemd[1]: Mounting Configuration File System...
[ 2.777745] systemd[1]: Starting Apply Kernel Variables...
[ 2.780077] systemd[1]: Mounted Configuration File System.
[ 2.781368] usb 1-8: New USB device found, idVendor=04f3, idProduct=2072
[ 2.781371] usb 1-8: New USB device strings: Mfr=4, Product=14,
SerialNumber=0
[ 2.781373] usb 1-8: Product: Touchscreen
[ 2.781375] usb 1-8: Manufacturer: ELAN
[ 2.781496] systemd[1]: Started Apply Kernel Variables.
[ 2.785590] systemd[1]: Started Monitoring of LVM2 mirrors,
snapshots etc. using dmeventd or progress polling.
[ 2.786117] systemd[1]: Started Create Static Device Nodes in /dev.
[ 2.786506] systemd[1]: Starting udev Kernel Device Manager...
[ 2.790685] systemd[1]: Started Journal Service.
[ 2.794159] systemd-journald[231]: Received request to flush
runtime journal from PID 1
[ 2.831196] input: Lid Switch as
/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input3
[ 2.834298] Initializing HPQ6001 module
[ 2.834346] input: HP Wireless hotkeys as /devices/virtual/input/input4
[ 2.836380] ACPI: Lid Switch [LID0]
[ 2.836439] input: Power Button as
/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input5
[ 2.836442] ACPI: Power Button [PWRB]
[ 2.836601] input: Power Button as
/devices/LNXSYSTM:00/LNXPWRBN:00/input/input6
[ 2.836604] ACPI: Power Button [PWRF]
[ 2.836851] ACPI: AC Adapter [ADP1] (off-line)
[ 2.840200] Bluetooth: Core ver 2.21
[ 2.840212] NET: Registered protocol family 31
[ 2.840214] Bluetooth: HCI device and connection manager initialized
[ 2.840216] Bluetooth: HCI socket layer initialized
[ 2.840219] Bluetooth: L2CAP socket layer initialized
[ 2.840223] Bluetooth: SCO socket layer initialized
[ 2.841896] Bluetooth: HCI UART driver ver 2.3
[ 2.841898] Bluetooth: HCI UART protocol H4 registered
[ 2.841900] Bluetooth: HCI UART protocol BCSP registered
[ 2.841901] Bluetooth: HCI UART protocol LL registered
[ 2.841902] Bluetooth: HCI UART protocol ATH3K registered
[ 2.841903] Bluetooth: HCI UART protocol Three-wire (H5) registered
[ 2.841937] Bluetooth: HCI UART protocol Intel registered
[ 2.841953] Bluetooth: HCI UART protocol BCM registered
[ 2.841953] Bluetooth: HCI UART protocol QCA registered
[ 2.848567] usbcore: registered new interface driver usbhid
[ 2.848569] usbhid: USB HID core driver
[ 2.865676] [drm] Initialized drm 1.1.0 20060810
[ 2.876538] mei_me 0000:00:16.0: enabling device (0000 -> 0002)
[ 2.879000] usbcore: registered new interface driver btusb
[ 2.881627] media: Linux media interface: v0.10
[ 2.883645] Linux video capture interface: v2.00
[ 2.885785] uvcvideo: Found UVC 1.00 device HP Truevision Full HD (1bcf:2c7d)
[ 2.890753] [drm] Memory usable by graphics device = 4096M
[ 2.890756] checking generic (c0000000 1d5000) vs hw (c0000000 10000000)
[ 2.890757] fb: switching to inteldrmfb from simple
[ 2.890793] Console: switching to colour dummy device 80x25
[ 2.890849] [drm] Replacing VGA console driver
[ 2.893060] uvcvideo 1-6:1.0: Entity type for entity Extension 4
was not initialized!
[ 2.893063] uvcvideo 1-6:1.0: Entity type for entity Extension 3
was not initialized!
[ 2.893064] uvcvideo 1-6:1.0: Entity type for entity Processing 2
was not initialized!
[ 2.893066] uvcvideo 1-6:1.0: Entity type for entity Camera 1 was
not initialized!
[ 2.893127] input: HP Truevision Full HD as
/devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:1.0/input/input7
[ 2.893148] usbcore: registered new interface driver uvcvideo
[ 2.893149] USB Video Class driver (1.1.1)
[ 2.893737] Bluetooth: hci0: read Intel version: 370810011003110e00
[ 2.894164] Bluetooth: hci0: Intel Bluetooth firmware file:
intel/ibt-hw-37.8.10-fw-1.10.3.11.e.bseq
[ 2.895773] tpm_tis MSFT0101:00: 2.0 TPM (device-id 0x1A, rev-id 16)
[ 2.897161] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[ 2.897163] [drm] Driver supports precise vblank timestamp query.
[ 2.903246] i915 0000:00:02.0: Direct firmware load for
i915/skl_dmc_ver1.bin failed with error -2
[ 2.903249] i915 0000:00:02.0: Failed to load DMC firmware
[https://01.org/linuxgraphics/intel-linux-graphics-firmwares],
disabling runtime power management.
[ 2.907555] vgaarb: device changed decodes:
PCI:0000:00:02.0,olddecodes=io+mem,decodes=io+mem:owns=io+mem
[ 2.934825] ACPI: Video Device [GFX0] (multi-head: yes rom: no post: no)
[ 2.935134] input: Video Bus as
/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input8
[ 2.935189] [drm] Initialized i915 1.6.0 20160229 for 0000:00:02.0 on minor 0
[ 2.935245] shpchp: Standard Hot Plug PCI Controller Driver version: 0.4
[ 2.935251] snd_hda_intel 0000:00:1f.3: enabling device (0000 -> 0002)
[ 2.944516] ACPI Warning: SystemIO range
0x000000000000F040-0x000000000000F05F conflicts with OpRegion
0x000000000000F040-0x000000000000F04F (\_SB.PCI0.SBUS.SMBI)
(20160108/utaddress-255)
[ 2.944522] ACPI: If an ACPI driver is available for this device,
you should use it instead of the native driver
[ 2.945315] Intel(R) Wireless WiFi driver for Linux
[ 2.945316] Copyright(c) 2003- 2015 Intel Corporation
[ 2.945485] iwlwifi 0000:02:00.0: enabling device (0000 -> 0002)
[ 2.946255] iwlwifi 0000:02:00.0: Direct firmware load for
iwlwifi-7265D-21.ucode failed with error -2
[ 2.946261] iwlwifi 0000:02:00.0: Direct firmware load for
iwlwifi-7265D-20.ucode failed with error -2
[ 2.946267] iwlwifi 0000:02:00.0: Direct firmware load for
iwlwifi-7265D-19.ucode failed with error -2
[ 2.946271] iwlwifi 0000:02:00.0: Direct firmware load for
iwlwifi-7265D-18.ucode failed with error -2
[ 2.946275] iwlwifi 0000:02:00.0: Direct firmware load for
iwlwifi-7265D-17.ucode failed with error -2
[ 2.946532] iwlwifi 0000:02:00.0: Unsupported splx structure
[ 2.949045] iwlwifi 0000:02:00.0: loaded firmware version
16.242414.0 op_mode iwlmvm
[ 2.956321] iwlwifi 0000:02:00.0: Detected Intel(R) Dual Band
Wireless AC 7265, REV=0x210
[ 2.956644] iwlwifi 0000:02:00.0: L1 Enabled - LTR Enabled
[ 2.957085] iwlwifi 0000:02:00.0: L1 Enabled - LTR Enabled
[ 2.979959] input: PC Speaker as /devices/platform/pcspkr/input/input9
[ 2.980690] Error: Driver 'pcspkr' is already registered, aborting...
[ 2.984757] FAT-fs (nvme0n1p1): utf8 is not a recommended IO
charset for FAT filesystems, filesystem will be case sensitive!
[ 3.025256] ieee80211 phy0: Selected rate control algorithm 'iwl-mvm-rs'
[ 3.046341] AVX2 version of gcm_enc/dec engaged.
[ 3.046343] AES CTR mode by8 optimization enabled
[ 3.072756] kvm: disabled by bios
[ 3.082766] Bluetooth: hci0: Intel Bluetooth firmware patch
completed and activated
[ 3.144395] intel_rapl: Found RAPL domain package
[ 3.144397] intel_rapl: Found RAPL domain core
[ 3.144399] intel_rapl: Found RAPL domain uncore
[ 3.144400] intel_rapl: Found RAPL domain dram
[ 3.145608] kvm: disabled by bios
[ 3.188612] snd_hda_intel 0000:00:1f.3: bound 0000:00:02.0 (ops
i915_audio_component_bind_ops [i915])
[ 3.188612] fbcon: inteldrmfb (fb0) is primary device
[ 3.204395] random: nonblocking pool is initialized
[ 3.217068] kvm: disabled by bios
[ 3.217087] snd_hda_codec_conexant hdaudioC0D0: CX20724: BIOS auto-probing.
[ 3.217590] snd_hda_codec_conexant hdaudioC0D0: autoconfig for
CX20724: line_outs=1 (0x17/0x0/0x0/0x0/0x0) type:speaker
[ 3.217591] snd_hda_codec_conexant hdaudioC0D0: speaker_outs=0
(0x0/0x0/0x0/0x0/0x0)
[ 3.217592] snd_hda_codec_conexant hdaudioC0D0: hp_outs=1
(0x16/0x0/0x0/0x0/0x0)
[ 3.217593] snd_hda_codec_conexant hdaudioC0D0: mono: mono_out=0x0
[ 3.217594] snd_hda_codec_conexant hdaudioC0D0: inputs:
[ 3.217595] snd_hda_codec_conexant hdaudioC0D0: Internal Mic=0x1a
[ 3.217596] snd_hda_codec_conexant hdaudioC0D0: Mic=0x19
[ 3.218722] snd_hda_codec_conexant hdaudioC0D0: Enable sync_write
for stable communication
[ 3.227240] input: HDA Digital PCBeep as
/devices/pci0000:00/0000:00:1f.3/sound/card0/input10
[ 3.227747] input: HDA Intel PCH Mic as
/devices/pci0000:00/0000:00:1f.3/sound/card0/input11
[ 3.227782] input: HDA Intel PCH Headphone as
/devices/pci0000:00/0000:00:1f.3/sound/card0/input12
[ 3.227814] input: HDA Intel PCH HDMI/DP,pcm=3 as
/devices/pci0000:00/0000:00:1f.3/sound/card0/input13
[ 3.227847] input: HDA Intel PCH HDMI/DP,pcm=7 as
/devices/pci0000:00/0000:00:1f.3/sound/card0/input14
[ 3.227880] input: HDA Intel PCH HDMI/DP,pcm=8 as
/devices/pci0000:00/0000:00:1f.3/sound/card0/input15
[ 3.285302] ACPI: Battery Slot [BAT0] (battery present)
[ 3.285591] wmi: Mapper loaded
[ 3.350850] Adding 31248380k swap on /dev/mapper/gladys--vg-swap.
Priority:-1 extents:1 across:31248380k SSFS
[ 3.353470] iwlwifi 0000:02:00.0 wlo1: renamed from wlan0
[ 3.362284] input: ELAN Touchscreen Pen as
/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/0003:04F3:2072.0007/input/input16
[ 3.362553] input: ELAN Touchscreen as
/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/0003:04F3:2072.0007/input/input17
[ 3.362949] hid-multitouch 0003:04F3:2072.0007:
input,hiddev0,hidraw0: USB HID v1.10 Keyboard [ELAN Touchscreen] on
usb-0000:00:14.0-8/input0
[ 3.369587] EXT4-fs (dm-1): mounted filesystem with ordered data
mode. Opts: (null)
[ 3.379530] ACPI Error: Field [D128] at 1152 exceeds Buffer [NULL]
size 160 (bits) (20160108/dsopcode-236)
[ 3.379534] ACPI Error: Method parse/execution failed [\HWMC] (Node
ffff8804630e4c58), AE_AML_BUFFER_LIMIT (20160108/psparse-542)
[ 3.379540] ACPI Error: Method parse/execution failed
[\_SB.WMID.WMAA] (Node ffff8804630e5b18), AE_AML_BUFFER_LIMIT
(20160108/psparse-542)
[ 3.379579] ACPI Error: Field [D128] at 1152 exceeds Buffer [NULL]
size 160 (bits) (20160108/dsopcode-236)
[ 3.379582] ACPI Error: Method parse/execution failed [\HWMC] (Node
ffff8804630e4c58), AE_AML_BUFFER_LIMIT (20160108/psparse-542)
[ 3.379587] ACPI Error: Method parse/execution failed
[\_SB.WMID.WMAA] (Node ffff8804630e5b18), AE_AML_BUFFER_LIMIT
(20160108/psparse-542)
[ 3.379621] ACPI Error: Field [D128] at 1152 exceeds Buffer [NULL]
size 160 (bits) (20160108/dsopcode-236)
[ 3.379623] ACPI Error: Method parse/execution failed [\HWMC] (Node
ffff8804630e4c58), AE_AML_BUFFER_LIMIT (20160108/psparse-542)
[ 3.379628] ACPI Error: Method parse/execution failed
[\_SB.WMID.WMAA] (Node ffff8804630e5b18), AE_AML_BUFFER_LIMIT
(20160108/psparse-542)
[ 3.379683] input: HP WMI hotkeys as /devices/virtual/input/input19
[ 3.380272] ACPI Error: Field [D128] at 1152 exceeds Buffer [NULL]
size 160 (bits) (20160108/dsopcode-236)
[ 3.380275] ACPI Error: Method parse/execution failed [\HWMC] (Node
ffff8804630e4c58), AE_AML_BUFFER_LIMIT (20160108/psparse-542)
[ 3.380281] ACPI Error: Method parse/execution failed
[\_SB.WMID.WMAA] (Node ffff8804630e5b18), AE_AML_BUFFER_LIMIT
(20160108/psparse-542)
[ 3.380317] ACPI Error: Field [D128] at 1152 exceeds Buffer [NULL]
size 160 (bits) (20160108/dsopcode-236)
[ 3.380320] ACPI Error: Method parse/execution failed [\HWMC] (Node
ffff8804630e4c58), AE_AML_BUFFER_LIMIT (20160108/psparse-542)
[ 3.380324] ACPI Error: Method parse/execution failed
[\_SB.WMID.WMAA] (Node ffff8804630e5b18), AE_AML_BUFFER_LIMIT
(20160108/psparse-542)
[ 3.600258] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[ 3.600259] Bluetooth: BNEP filters: protocol multicast
[ 3.600262] Bluetooth: BNEP socket layer initialized
[ 3.890655] ip_tables: (C) 2000-2006 Netfilter Core Team
[ 3.895545] ip6_tables: (C) 2000-2006 Netfilter Core Team
[ 3.905164] nf_conntrack version 0.5.0 (65536 buckets, 262144 max)
[ 4.000110] IPv6: ADDRCONF(NETDEV_UP): wlo1: link is not ready
[ 4.000462] iwlwifi 0000:02:00.0: L1 Enabled - LTR Enabled
[ 4.000902] iwlwifi 0000:02:00.0: L1 Enabled - LTR Enabled
[ 4.063035] iwlwifi 0000:02:00.0: L1 Enabled - LTR Enabled
[ 4.063481] iwlwifi 0000:02:00.0: L1 Enabled - LTR Enabled
[ 4.096171] IPv6: ADDRCONF(NETDEV_UP): wlo1: link is not ready
[ 4.180680] IPv6: ADDRCONF(NETDEV_UP): wlo1: link is not ready
[ 4.636315] Console: switching to colour frame buffer device 320x90
[ 4.646341] i915 0000:00:02.0: fb0: inteldrmfb frame buffer device
[ 4.795916] [drm] RC6 on
[ 5.996168] Bluetooth: RFCOMM TTY layer initialized
[ 5.996181] Bluetooth: RFCOMM socket layer initialized
[ 5.996192] Bluetooth: RFCOMM ver 1.11
[ 7.570966] wlo1: authenticate with 00:ac:54:f1:87:02
[ 7.576337] wlo1: send auth to 00:ac:54:f1:87:02 (try 1/3)
[ 7.579363] wlo1: authenticated
[ 7.579770] wlo1: associate with 00:ac:54:f1:87:02 (try 1/3)
[ 7.584033] wlo1: RX AssocResp from 00:ac:54:f1:87:02 (capab=0x431
status=0 aid=5)
[ 7.585967] wlo1: associated
[ 7.586012] IPv6: ADDRCONF(NETDEV_CHANGE): wlo1: link becomes ready
[ 20.124184] usb 1-3: new high-speed USB device number 5 using xhci_hcd
[ 20.310459] usb 1-3: New USB device found, idVendor=05e3, idProduct=0610
[ 20.310467] usb 1-3: New USB device strings: Mfr=0, Product=1, SerialNumber=0
[ 20.310472] usb 1-3: Product: USB2.0 Hub
[ 20.311423] hub 1-3:1.0: USB hub found
[ 20.311733] hub 1-3:1.0: 4 ports detected
[ 20.584205] usb 1-3.1: new high-speed USB device number 6 using xhci_hcd
[ 20.674490] usb 1-3.1: New USB device found, idVendor=05e3, idProduct=0610
[ 20.674498] usb 1-3.1: New USB device strings: Mfr=0, Product=1,
SerialNumber=0
[ 20.674502] usb 1-3.1: Product: USB2.0 Hub
[ 20.675491] hub 1-3.1:1.0: USB hub found
[ 20.675774] hub 1-3.1:1.0: 4 ports detected
[ 20.748195] usb 1-3.2: new low-speed USB device number 7 using xhci_hcd
[ 20.820235] usb 1-3.2: device descriptor read/64, error -32
[ 20.996233] usb 1-3.2: device descriptor read/64, error -32
[ 21.172205] usb 1-3.2: new low-speed USB device number 8 using xhci_hcd
[ 21.244244] usb 1-3.2: device descriptor read/64, error -32
[ 21.420239] usb 1-3.2: device descriptor read/64, error -32
[ 21.596206] usb 1-3.2: new low-speed USB device number 9 using xhci_hcd
[ 21.596841] usb 1-3.2: Device not responding to setup address.
[ 21.800847] usb 1-3.2: Device not responding to setup address.
[ 22.004207] usb 1-3.2: device not accepting address 9, error -71
[ 22.076226] usb 1-3.2: new low-speed USB device number 10 using xhci_hcd
[ 22.076868] usb 1-3.2: Device not responding to setup address.
[ 22.280846] usb 1-3.2: Device not responding to setup address.
[ 22.484225] usb 1-3.2: device not accepting address 10, error -71
[ 22.484683] usb 1-3-port2: unable to enumerate USB device
[ 22.556230] usb 1-3.3: new full-speed USB device number 11 using xhci_hcd
[ 22.649881] usb 1-3.3: New USB device found, idVendor=03f0, idProduct=d407
[ 22.649888] usb 1-3.3: New USB device strings: Mfr=1, Product=2,
SerialNumber=0
[ 22.649892] usb 1-3.3: Product: HP Link-5 Micro Receiver
[ 22.649895] usb 1-3.3: Manufacturer: HP
[ 22.653118] input: HP HP Link-5 Micro Receiver as
/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.3/1-3.3:1.0/0003:03F0:D407.0008/input/input20
[ 22.708826] hid-generic 0003:03F0:D407.0008: input,hidraw1: USB HID
v1.11 Keyboard [HP HP Link-5 Micro Receiver] on
usb-0000:00:14.0-3.3/input0
[ 22.713335] input: HP HP Link-5 Micro Receiver as
/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.3/1-3.3:1.1/0003:03F0:D407.0009/input/input21
[ 22.768737] hid-generic 0003:03F0:D407.0009: input,hiddev0,hidraw2:
USB HID v1.11 Mouse [HP HP Link-5 Micro Receiver] on
usb-0000:00:14.0-3.3/input1
[ 44.945907] fuse init (API version 7.24)

Bastien Nocera

unread,
Jun 14, 2016, 11:20:06 AM6/14/16
to
On Tue, 2016-06-14 at 14:44 +0100, Grant Likely wrote:
> On Fri, Jun 10, 2016 at 4:27 PM, Bastien Nocera <had...@hadess.net>
> wrote:
> > On Fri, 2016-06-10 at 08:23 -0700, Srinivas Pandruvada wrote:
> > > On Fri, 2016-06-10 at 17:04 +0200, Bastien Nocera wrote:
> > > > >
> > >
> > > [...]
> > >
> > > > Are there any errors when setting the triggers?
> > > >
> > > Is there any debug option in this service to give more verbose
> > > output?
> >
> > Add:
> > Environment="G_MESSAGES_DEBUG=all"
> >
> > To the service file. You should see the debug in systemctl:
> > systemctl status iio-sensor-proxy.service
> >
> > Or in journalctl if there's too much data:
> > journalctl --reverse -u iio-sensor-proxy.service
>
> Still no joy on the sensors. The proxy starts up and detects the
> sensors, but I don't see any sensor events occurring:

Could you try again with the current master of iio-sensor-proxy? Make
sure to install the file in the same location as in your distro
provided package.

I've added more debug/warnings to a few cases where it would have
silently failed in the past.

In particular, I don't see any messages that would be coming out of:
https://github.com/hadess/iio-sensor-proxy/blob/master/src/iio-buffer-utils.c#L512

Could it be that the sub-directory is populated after the device is
created in the kernel, causing a race?

Either that, or the contents of the scan_elements/ directory is not the
one expected by this code.

The output of this command should us that:
ls /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1/scan_elements

Cheers

Grant Likely

unread,
Jun 14, 2016, 12:10:05 PM6/14/16
to
Hmmm, this is interesting. I fetched, built and ran the latest
iio-sensor-proxy. It quit with the following error. However,
immediately afterwards, I ran the Debian packaged version (1.1-1), and
the sensors started to work. Something in the latest master activates
the sensors enough for the older version to work.

To make sure it wasn't fixed by a kernel upgrade, I also rebooted and
tried again:
1) Booted system - iio-sensor-proxy.service running --- No rotation sensing
2) # systemctl stop iio-sensor-proxy-service --- Turn off the agent
3) # G_MESSAGES_DEBUG=all /usr/bin/iio-sensor-proxy.orig ----
original version, still not working
4) # G_MESSAGES_DEBUG=all /usr/bin/iio-sensor-proxy.new ----
latest master, failed with error messages
5) # G_MESSAGES_DEBUG=all /usr/bin/iio-sensor-proxy.orig ----
original version, suddenly working

All of this was tested on Linus' latest master branch (4.7-rc3+)

Output from latest git master:

root@gladys:~# G_MESSAGES_DEBUG=all /usr/sbin/iio-sensor-proxy
** (process:9214): DEBUG: Found accel_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
** (process:9214): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
of type accelerometer at IIO Buffer accelerometer
** (process:9214): DEBUG: Found magn_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
** (process:9214): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
of type compass at IIO Buffer Compass
** (process:9214): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/trigger1

** (process:9214): WARNING **: Failed to enable any sensors for device
'/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1'

** (process:9214): WARNING **: Failed to enable any sensors for device
'/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1'
** (process:9214): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/trigger6

** (process:9214): WARNING **: Failed to enable any sensors for device
'/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6'

** (process:9214): WARNING **: Failed to enable any sensors for device
'/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6'




Full output running old, then new, then old:

Script started on Tue 14 Jun 2016 16:47:16 BST
root@gladys:/usr/sbin# G_MESSAGES_DEBUG=all /usr/sbin/iio-sensor-proxy.orig
** (process:2369): DEBUG: Found accel_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
** (process:2369): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
of type accelerometer at IIO Buffer accelerometer
** (process:2369): DEBUG: Found magn_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
** (process:2369): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
of type compass at IIO Buffer Compass
** (process:2369): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/trigger1
** (process:2369): DEBUG: Got type for in_accel_x: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Got type for in_accel_y: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Got type for in_accel_z: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Built channel array for in_accel_x: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Built channel array for in_accel_y: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Built channel array for in_accel_z: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/trigger6
** (process:2369): DEBUG: Got type for in_magn_x: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Got type for in_magn_y: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Got type for in_magn_z: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Got type for
in_rot_from_north_magnetic_tilt_comp: is signed: 1, bytes: 4,
bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Built channel array for in_magn_x: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Built channel array for in_magn_y: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Built channel array for in_magn_z: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Built channel array for
in_rot_from_north_magnetic_tilt_comp: is signed: 1, bytes: 4,
bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2369): DEBUG: Handling driver refcounting method
'ClaimLight' for ambient light sensor device
** (process:2369): DEBUG: Handling driver refcounting method
'ClaimAccelerometer' for accelerometer device
** (process:2369): DEBUG: Handling driver refcounting method
'ClaimAccelerometer' for accelerometer device
** (process:2369): DEBUG: No new data available
** (process:2369): DEBUG: No new data available
** (process:2369): DEBUG: No new data available
^C



root@gladys:/usr/sbin# G_MESSAGES_DEBUG=all /usr/sbin/iio-sensor-proxy.new
** (process:2468): DEBUG: Found accel_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
** (process:2468): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
of type accelerometer at IIO Buffer accelerometer
** (process:2468): DEBUG: Found magn_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
** (process:2468): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
of type compass at IIO Buffer Compass
** (process:2468): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/trigger1

** (process:2468): WARNING **: Failed to enable any sensors for device
'/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1'

** (process:2468): WARNING **: Failed to enable any sensors for device
'/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1'
** (process:2468): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/trigger6

** (process:2468): WARNING **: Failed to enable any sensors for device
'/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6'

** (process:2468): WARNING **: Failed to enable any sensors for device
'/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6'



root@gladys:/usr/sbin# G_MESSAGES_DEBUG=all /usr/sbin/iio-sensor-proxy.orig
** (process:2533): DEBUG: Found accel_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
** (process:2533): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
of type accelerometer at IIO Buffer accelerometer
** (process:2533): DEBUG: Found magn_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
** (process:2533): DEBUG: Found device
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
of type compass at IIO Buffer Compass
** (process:2533): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/trigger1
** (process:2533): DEBUG: Got type for in_accel_x: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Got type for in_accel_y: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Got type for in_accel_z: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Built channel array for in_accel_x: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Built channel array for in_accel_y: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Built channel array for in_accel_z: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/trigger6
** (process:2533): DEBUG: Got type for in_magn_x: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Got type for in_magn_y: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Got type for in_magn_z: is signed: 1, bytes:
4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Got type for
in_rot_from_north_magnetic_tilt_comp: is signed: 1, bytes: 4,
bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Built channel array for in_magn_x: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Built channel array for in_magn_y: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Built channel array for in_magn_z: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Built channel array for
in_rot_from_north_magnetic_tilt_comp: is signed: 1, bytes: 4,
bits_used: 32, shift: 0, mask: 0x0, be: 0
** (process:2533): DEBUG: Handling driver refcounting method
'ClaimLight' for ambient light sensor device
** (process:2533): DEBUG: Handling driver refcounting method
'ClaimAccelerometer' for accelerometer device
** (process:2533): DEBUG: Handling driver refcounting method
'ClaimAccelerometer' for accelerometer device
** (process:2533): DEBUG: Read from IIO: 4449, -1007689, 15468
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 0, 9, 0
** (process:2533): DEBUG: Emitted orientation changed: from undefined to normal
** (process:2533): DEBUG: Read from IIO: 3729, -1007724, 12494
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 0, 9, 0
** (process:2533): DEBUG: Read from IIO: -12800, -1056421, -2211
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 0, 9, 0
** (process:2533): DEBUG: Read from IIO: -642273, -671193, -106330
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 5, 6, 0
** (process:2533): DEBUG: Emitted orientation changed: from normal to right-up
** (process:2533): DEBUG: Read from IIO: -968979, -66939, 45709
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 8, 0, 0
** (process:2533): DEBUG: Read from IIO: -973822, -54006, 38730
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 8, 0, 0
** (process:2533): DEBUG: Read from IIO: -436204, -868488, -94847
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 3, 7, 0
** (process:2533): DEBUG: Emitted orientation changed: from right-up to normal
** (process:2533): DEBUG: Read from IIO: -32008, -988339, -7532
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 0, 8, 0
** (process:2533): DEBUG: Read from IIO: 22296, -1010201, 9358
** (process:2533): DEBUG: Accel sent by driver (quirk applied): 0, 9, 0
^C
root@gladys:/usr/sbin# exit

Script done on Tue 14 Jun 2016 16:47:49 BST

Bastien Nocera

unread,
Jun 14, 2016, 1:10:04 PM6/14/16
to
There's no changes in that code other than me introducing a bug that'd
make it throw a warning when the sensor was already enabled. Fixed now.

Could you try again, but make sure to replace the existing iio-sensor-
proxy so it's started on boot, when the device appears. If you see the
warning again, please attach the output out from "ls" as requested in
the earlier mail.

If it doesn't warn on startup, and it fails to work, then we're
probably looking at a bug in the kernel...

Cheers

Grant Likely

unread,
Jun 14, 2016, 5:40:05 PM6/14/16
to
Oops, missed that the first time. Here you go:

root@gladys:~# ls
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1/scan_elements
in_accel_x_en in_accel_y_en in_accel_z_en
in_accel_x_index in_accel_y_index in_accel_z_index
in_accel_x_type in_accel_y_type in_accel_z_type

> If it doesn't warn on startup, and it fails to work, then we're
> probably looking at a bug in the kernel...

Here is the output. The latest master still doesn't work. However, it
has the same behaviour that running the broken version of
iio-sensors-proxy (207b5bbd8) will cause the good one start working
(92fa6ea9e).

-- Logs begin at Tue 2016-06-14 22:19:47 BST, end at Tue 2016-06-14
22:20:52 BST. --
Jun 14 22:19:48 gladys systemd[1]: Starting IIO Sensor Proxy service...
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Found accel_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Found device /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1
of type accelerometer at IIO Buffer accelerometer
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Found magn_3d at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Found device /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6
of type compass at IIO Buffer Compass
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/trigger1
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Enabled sensor /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1/scan_elements/in_accel_x_en
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Enabled sensor /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1/scan_elements/in_accel_y_en
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Enabled sensor /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0001/HID-SENSOR-200073.8.auto/iio:device1/scan_elements/in_accel_z_en
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Got type for in_accel_x: is signed: 1, bytes: 4, bits_used: 32, shift:
0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Got type for in_accel_y: is signed: 1, bytes: 4, bits_used: 32, shift:
0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Got type for in_accel_z: is signed: 1, bytes: 4, bits_used: 32, shift:
0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Built channel array for in_accel_x: is signed: 1, bytes: 4, bits_used:
32, shift: 0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Built channel array for in_accel_y: is signed: 1, bytes: 4, bits_used:
32, shift: 0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Built channel array for in_accel_z: is signed: 1, bytes: 4, bits_used:
32, shift: 0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Found associated trigger at
/sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/trigger6
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Enabled sensor /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6/scan_elements/in_magn_x_en
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Enabled sensor /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6/scan_elements/in_magn_y_en
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Enabled sensor /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6/scan_elements/in_magn_z_en
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Enabled sensor /sys/devices/pci0000:00/0000:00:13.0/{33AECD58-B679-4E54-9BD9-A04D34F0C226}/001E:8086:22D8.0003/HID-SENSOR-200083.27.auto/iio:device6/scan_elements/in_rot_from_north_magnetic_tilt_comp_en
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Got type for in_magn_x: is signed: 1, bytes: 4, bits_used: 32, shift:
0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Got type for in_magn_y: is signed: 1, bytes: 4, bits_used: 32, shift:
0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Got type for in_magn_z: is signed: 1, bytes: 4, bits_used: 32, shift:
0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Got type for in_rot_from_north_magnetic_tilt_comp: is signed: 1,
bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Built channel array for in_magn_x: is signed: 1, bytes: 4, bits_used:
32, shift: 0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Built channel array for in_magn_y: is signed: 1, bytes: 4, bits_used:
32, shift: 0, mask: 0x0, be: 0
Jun 14 22:19:48 gladys systemd[1]: Started IIO Sensor Proxy service.
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Built channel array for in_magn_z: is signed: 1, bytes: 4, bits_used:
32, shift: 0, mask: 0x0, be: 0
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Built channel array for in_rot_from_north_magnetic_tilt_comp: is
signed: 1, bytes: 4, bits_used: 32, shift: 0, mask: 0x0, be: 0
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Handling driver refcounting method 'ClaimAccelerometer' for
accelerometer device
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Handling driver refcounting method 'ReleaseLight' for ambient light
sensor device
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
Handling driver refcounting method 'ClaimAccelerometer' for
accelerometer device
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:44 gladys iio-sensor-proxy[577]: ** (process:577): DEBUG:
No new data available
Jun 14 22:20:47 gladys systemd[1]: Stopping IIO Sensor Proxy service...
Jun 14 22:20:47 gladys iio-sensor-proxy[577]: ** (process:577):
Jun 14 22:20:47 gladys systemd[1]: Stopped IIO Sensor Proxy service.



>
> Cheers

Grant Likely

unread,
Jun 16, 2016, 3:20:06 PM6/16/16
to
On Sat, Jun 11, 2016 at 1:13 PM, Srinivas Pandruvada
<srinivas....@linux.intel.com> wrote:
> Starting from Cherrytrail, multiple generation of Intel processors offers
> on package sensor hub. Several recent tablets, 2-in-1 convertible laptops
> are using ISH instead of external sensor hubs. This resulted in lack of
> support of sensor function like device rotation and auto backlight
> adjustment.
> In addition, depending on the OEM implementation, support of ISH is required
> to support low power sleep states.
>
> The support of ISH on Linux platforms is not new. Android platforms with
> Intel SoCs had this support for a while submitted by Daniel Drubin.
> This patcheset is reusing most of those changes with clean up and
> removing Android platform specific changes.
>
> The user mode ABI is still same as external sensor hubs using Linux
> IIO. So existing user mode software should still work.
> This series primarily brings in new HID transport used in ISH.
>
> Thanks to the community members who tested RFC patches and provided
> feedback.
>
> For users testing on Linux distributions using IIO sensor proxy,
> a short term work around is required till we have debugged this issue.
> In systemd unit file iio-sensor-proxy.service
> In the section "[Unit]" add
> After=multi-user.target

Tested-by: Grant Likely <grant....@hpe.com>

There is still a fiddly problem on my laptop where the sensor data
doesn't always start streaming, but otherwise this version works for
me.

g.

Jiri Kosina

unread,
Jun 17, 2016, 4:50:05 PM6/17/16
to
On Fri, 17 Jun 2016, Jiri Kosina wrote:

> > +struct ishtp_cl_device *ishtp_bus_add_device(struct ishtp_device *dev,
> > + uuid_le uuid, char *name)
> > +{
>
> Should be static.

Actually, going deeper into the code and trying to untangle all the
dependencies, there are quite a few more in other ipc.c, hid-client.c,
etc. Please fix that globally in the next iteration.

Thanks,

--
Jiri Kosina
SUSE Labs

Jiri Kosina

unread,
Jun 17, 2016, 4:50:05 PM6/17/16
to
On Sat, 11 Jun 2016, Srinivas Pandruvada wrote:

[ ... snip ... ]
> diff --git a/drivers/hid/intel-ish-hid/Kconfig b/drivers/hid/intel-ish-hid/Kconfig
> new file mode 100644
> index 0000000..8914f3b
> --- /dev/null
> +++ b/drivers/hid/intel-ish-hid/Kconfig
> @@ -0,0 +1,22 @@
> +menu "Intel ISH HID support"
> + depends on X86 && PCI
> +
> +config INTEL_ISH_HID_TRANSPORT
> + bool
> + default n
> +
> +config INTEL_ISH_HID
> + bool "Intel Integrated Sensor Hub"

Why can't the transport driver be built as a module?

[ ... snip ... ]
> +/**
> + * ishtp_bus_add_device() - Function to create device on bus
> + *
> + * @dev: ishtp device
> + * @uuid: uuid of the client
> + * @name: Name of the client
> + *
> + * Allocate ISHTP bus client device, attach it to uuid
> + * and register with ISHTP bus.
> + */
> +struct ishtp_cl_device *ishtp_bus_add_device(struct ishtp_device *dev,
> + uuid_le uuid, char *name)
> +{

Should be static.

[ ... snip ... ]
> +/**
> + * ishtp_bus_remove_device() - Function to relase device on bus
> + *
> + * @device: client device instance
> + *
> + * This is a counterpart of ishtp_bus_add_device.
> + * Device is unregistered.
> + * the device structure is freed in 'ishtp_cl_dev_release' function
> + * Called only during error in pci driver init path.
> + */
> +void ishtp_bus_remove_device(struct ishtp_cl_device *device)
> +{

Should be static.

[ ... snip ... ]
> +/*
> + * ishtp_hbm_dma_xfer_ack - receive ack for ISHTP-over-DMA client message
> + *
> + * Constraint:
> + * First implementation is one ISHTP message per DMA transfer
> + */
> +void ishtp_hbm_dma_xfer_ack(struct ishtp_device *dev,

Should be static.

[ ... snip ... ]
> +/* ishtp_hbm_dma_xfer - receive ISHTP-over-DMA client message */
> +void ishtp_hbm_dma_xfer(struct ishtp_device *dev,
> + struct dma_xfer_hbm *dma_xfer)

Should be static.

Jiri Kosina

unread,
Jun 17, 2016, 4:50:05 PM6/17/16
to
On Sat, 11 Jun 2016, Srinivas Pandruvada wrote:

> Document explaining ISH HID operation and implementation.
>
> Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
> ---
> Documentation/hid/intel-ish-hid.txt | 417 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 417 insertions(+)
> create mode 100644 Documentation/hid/intel-ish-hid.txt
>
> diff --git a/Documentation/hid/intel-ish-hid.txt b/Documentation/hid/intel-ish-hid.txt
> new file mode 100644
> index 0000000..2de0ab5
> --- /dev/null
> +++ b/Documentation/hid/intel-ish-hid.txt
> @@ -0,0 +1,417 @@
> +Intel Integrated Sensor Hub (ISH)
> +===============================
> +
> +A sensor hub enables the ability to offload sensor polling and algorithm
> +processing to a dedicated low power co-processor. This allows the core
> +processor to go into low power modes more often, resulting in the increased
> +battery life.
[ ... snip ... ]

What I would like to see added here is a bit more of a higher-level
overview of the implementation.

It's a *lot* of new code. I am still trying to make my way through it. One
thing that I am currently trying to figure out, and which, if documented,
would be much easier to review, would be: my current understanding is that
this is both transport (ll) driver and a kind-of a bus at the same time.

Could yo please put some more comprehensive overview of the overall
architecture into the documentation?

Thanks,

Srinivas Pandruvada

unread,
Jun 17, 2016, 5:10:04 PM6/17/16
to
Great. I ran sparse and identified few more. I will fix this is new
iteration.

One thing I am still wondering is that the current ISH model is built
in only. Some distros configure CONFIG_HID as module. So in Kconfig in 
drivers/hid/intel-ish-hid/, I need to add "select HID".
What do you think about this?

Unless you are in middle of review, I want to go ahead and send v2.


Thanks,
Srinivas

Srinivas Pandruvada

unread,
Jun 17, 2016, 5:20:07 PM6/17/16
to
On Fri, 2016-06-17 at 22:43 +0200, Jiri Kosina wrote:
> On Sat, 11 Jun 2016, Srinivas Pandruvada wrote:
>
> [ ... snip ... ]
> > diff --git a/drivers/hid/intel-ish-hid/Kconfig b/drivers/hid/intel-
> ish-hid/Kconfig
> > new file mode 100644
> > index 0000000..8914f3b
> > --- /dev/null
> > +++ b/drivers/hid/intel-ish-hid/Kconfig
> > @@ -0,0 +1,22 @@
> > +menu "Intel ISH HID support"
> > +     depends on X86 && PCI
> > +
> > +config INTEL_ISH_HID_TRANSPORT
> > +     bool
> > +     default n
> > +
> > +config INTEL_ISH_HID
> > +     bool "Intel Integrated Sensor Hub"
>
> Why can't the transport driver be built as a module?
In current use case for PM, we don't want anyone to unload and
complain.
But if this is a strong requirement, I will change this to a module.

Thanks,
Srinivas

Jiri Kosina

unread,
Jun 20, 2016, 5:40:07 AM6/20/16
to
On Fri, 17 Jun 2016, Srinivas Pandruvada wrote:

> > > +config INTEL_ISH_HID_TRANSPORT
> > > +     bool
> > > +     default n
> > > +
> > > +config INTEL_ISH_HID
> > > +     bool "Intel Integrated Sensor Hub"
> >
> > Why can't the transport driver be built as a module?
> In current use case for PM, we don't want anyone to unload and
> complain.

Sorry, I don't understand this explanation, could you please elaborate?

Thanks,

One Thousand Gnomes

unread,
Jun 20, 2016, 10:30:07 AM6/20/16
to
If the driver isn't loaded your machine doesn't do power management.
There are a small set of drivers that need to be loaded to get pm even if
not using that device. ISH is one of them, and unlike the others not
sucked into a standard configuration.

If it's going to get loaded due to the presence of the PCI identifiers on
any normal distribution then it's in the same category as graphics and
ADSP based audio, both of which can be modules and the only real world
impact is they get loaded a second or two later during boot.

Alan

Srinivas Pandruvada

unread,
Jun 21, 2016, 6:50:05 PM6/21/16
to
Document explaining ISH HID operation and implementation.

Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
---
Documentation/hid/intel-ish-hid.txt | 449 ++++++++++++++++++++++++++++++++++++
1 file changed, 449 insertions(+)
create mode 100644 Documentation/hid/intel-ish-hid.txt

diff --git a/Documentation/hid/intel-ish-hid.txt b/Documentation/hid/intel-ish-hid.txt
new file mode 100644
index 0000000..8557280
--- /dev/null
+++ b/Documentation/hid/intel-ish-hid.txt
@@ -0,0 +1,449 @@
+Intel Integrated Sensor Hub (ISH)
+===============================
+
+A sensor hub enables the ability to offload sensor polling and algorithm
+processing to a dedicated low power co-processor. This allows the core
+processor to go into low power modes more often, resulting in the increased
+battery life.
+There are many vendors providing external sensor hubs confirming to HID
+Sensor usage tables, and used in several tablets, 2 in 1 convertible laptops
+and embedded products. Linux had this support since Linux 3.9.
+
+Intel® introduced integrated sensor hubs as a part of the SoC starting from
+Cherry Trail and now supported on multiple generations of CPU packages. There
+are many commercial devices already shipped with Integrated Sensor Hubs (ISH).
+These ISH also comply to HID sensor specification, but the difference is the
+transport protocol used for communication. The current external sensor hubs
+mainly use HID over i2C or USB. But ISH doesn't use either i2c or USB.
+
+Overview
+Using a analogy with a usbhid implementation, the ISH follows a similar model
+for a very high speed communication:
+
+ ----------------- ----------------------
+ | USB HID | --> | ISH HID |
+ ----------------- ----------------------
+ ----------------- ----------------------
+ | USB protocol | --> | ISH Transport |
+ ----------------- ----------------------
+ ----------------- ----------------------
+ | EHCI/XHCI | --> | ISH IPC |
+ ----------------- ----------------------
+ PCI PCI
+ ----------------- ----------------------
+ |Host controller| --> | ISH processor |
+ ----------------- ----------------------
+ USB Link
+ ----------------- ----------------------
+ | USB End points| --> | ISH Clients |
+ ----------------- ----------------------
+
+Like USB protocol provides a method for device enumeration, link management
+and user data encapsulation, the ISH also provides similar services. But it is
+very light weight tailored to manage and communicate with ISH client
+applications implemented in the firmware.
+The ISH allows multiple sensor management applications executing in the
+firmware. Like USB endpoints the messaging can be to/from a client. As part of
+enumeration process, these clients are identified. These clients can be simple
+HID sensor applications, sensor calibration application or senor firmware
+update application.
+The implementation model is similar, like usb bus, ISH transport is also
+implemented as a bus. Each client application executing in the ISH processor
+is registered as a device on this bus. The driver, which binds each device
+(ISH HID driver) identifies the device type and registers with the hid core.

Srinivas Pandruvada

unread,
Jun 21, 2016, 6:50:12 PM6/21/16
to
Change log
v2:
- Overview in documentation show analogy with usbhid implementation
- sparse errors for statics. Also pointed by Jiri
- Clearly marking exported function header file. Clean up all exports
unused inteface functions
- Changed to tristate from boolean as pointed by Jiri:
this required remove/unload functions
- Prevent crash when ISH enabled on non supported platform
- Break client.c to smaller part by seprating buffer allocations
- move bus register/unregister to ishtp module
- There is only one config symbol INTEL_ISH_HID, removed silent
config for TRANSPORT and IPC


Starting from Cherrytrail, multiple generation of Intel processors offers
on package sensor hub. Several recent tablets, 2-in-1 convertible laptops
are using ISH instead of external sensor hubs. This resulted in lack of
support of sensor function like device rotation and auto backlight
adjustment.
In addition, depending on the OEM implementation, support of ISH is required
to support low power sleep states.

The support of ISH on Linux platforms is not new. Android platforms with
Intel SoCs had this support for a while submitted by Daniel Drubin.
This patcheset is reusing most of those changes with clean up and
removing Android platform specific changes.

The user mode ABI is still same as external sensor hubs using Linux
IIO. So existing user mode software should still work.
This series primarily brings in new HID transport used in ISH.

Thanks to the community members who tested RFC patches and provided
feedback.

For users testing on Linux distributions using IIO sensor proxy,
a short term work around is required till we have debugged this issue.
In systemd unit file iio-sensor-proxy.service
In the section "[Unit]" add
After=multi-user.target

Daniel Drubin (3):
hid: intel_ish-hid: ISH Transport layer
hid: intel-ish-hid: ipc layer
hid: intel-ish-hid: ISH HID client driver

Srinivas Pandruvada (3):
Documentation: hid: Intel ISH HID document
iio: hid-sensors: use asynchronous resume
hid: hid-sensor-hub: Add ISH quirk

Documentation/hid/intel-ish-hid.txt | 449 ++++++++++
drivers/hid/Kconfig | 2 +
drivers/hid/Makefile | 2 +
drivers/hid/hid-sensor-hub.c | 4 +
drivers/hid/intel-ish-hid/Kconfig | 17 +
drivers/hid/intel-ish-hid/Makefile | 22 +
drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h | 220 +++++
drivers/hid/intel-ish-hid/ipc/hw-ish.h | 71 ++
drivers/hid/intel-ish-hid/ipc/ipc.c | 719 ++++++++++++++++
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 327 +++++++
drivers/hid/intel-ish-hid/ipc/utils.h | 64 ++
drivers/hid/intel-ish-hid/ishtp-hid-client.c | 935 +++++++++++++++++++++
drivers/hid/intel-ish-hid/ishtp-hid.c | 234 ++++++
drivers/hid/intel-ish-hid/ishtp-hid.h | 182 ++++
drivers/hid/intel-ish-hid/ishtp/bus.c | 780 +++++++++++++++++
drivers/hid/intel-ish-hid/ishtp/bus.h | 110 +++
drivers/hid/intel-ish-hid/ishtp/client-buffers.c | 214 +++++
drivers/hid/intel-ish-hid/ishtp/client.c | 935 +++++++++++++++++++++
drivers/hid/intel-ish-hid/ishtp/client.h | 182 ++++
drivers/hid/intel-ish-hid/ishtp/dma-if.c | 178 ++++
drivers/hid/intel-ish-hid/ishtp/hbm.c | 908 ++++++++++++++++++++
drivers/hid/intel-ish-hid/ishtp/hbm.h | 321 +++++++
drivers/hid/intel-ish-hid/ishtp/init.c | 93 ++
drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h | 277 ++++++
.../iio/common/hid-sensors/hid-sensor-trigger.c | 21 +-
include/linux/hid-sensor-hub.h | 1 +
include/trace/events/intel_ish.h | 30 +
include/uapi/linux/input.h | 1 +
28 files changed, 7298 insertions(+), 1 deletion(-)
create mode 100644 Documentation/hid/intel-ish-hid.txt
create mode 100644 drivers/hid/intel-ish-hid/Kconfig
create mode 100644 drivers/hid/intel-ish-hid/Makefile
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/hw-ish.h
create mode 100644 drivers/hid/intel-ish-hid/ipc/ipc.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/pci-ish.c
create mode 100644 drivers/hid/intel-ish-hid/ipc/utils.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid-client.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp-hid.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/bus.c
create mode 100644 drivers/hid/intel-ish-hid/ishtp/bus.h
create mode 100644 drivers/hid/intel-ish-hid/ishtp/client-buffers.c

Jonathan Cameron

unread,
Jun 26, 2016, 2:40:06 PM6/26/16
to
On 22/06/16 06:40, Srinivas Pandruvada wrote:
> Document explaining ISH HID operation and implementation.
>
> Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel.com>
A few really trivial point inline. I unfortunately don't have the time to
dive into this in sufficient depth to grasp every detail, but the
description seems pretty comprehensive to me.

I would however, put a blank line between paragraphs to make it a touch
easier to read...

Might even be worth taking this into a docbook file instead of straight
text...

Jonathan
blank line.
> +Chater 7: Bus Message Layer
Chapter.
implanted is an odd word choice...

Srinivas Pandruvada

unread,
Jun 27, 2016, 11:30:05 AM6/27/16
to
On Sun, 2016-06-26 at 19:32 +0100, Jonathan Cameron wrote:
> On 22/06/16 06:40, Srinivas Pandruvada wrote:
> >
> > Document explaining ISH HID operation and implementation.
> >
> > Signed-off-by: Srinivas Pandruvada <srinivas....@linux.intel
> > .com>
> A few really trivial point inline.  I unfortunately don't have the
> time to
> dive into this in sufficient depth to grasp every detail, but the
> description seems pretty comprehensive to me.
>
> I would however, put a blank line between paragraphs to make it a
> touch
> easier to read...
Thanks. I will take care of your comments in the next revision.

>
> Might even be worth taking this into a docbook file instead of
> straight
> text...
If we convert to docbook format, will it still go to Documentation/hid
folder, or somewhere else?

Thanks,
Srinivas

Jiri Kosina

unread,
Jun 27, 2016, 3:10:06 PM6/27/16
to
On Mon, 27 Jun 2016, Srinivas Pandruvada wrote:

> > Might even be worth taking this into a docbook file instead of
> > straight
> > text...
> If we convert to docbook format, will it still go to Documentation/hid
> folder, or somewhere else?

FWIW, I'd very much prefer the plain text format. Experience has taught me
that it has much more likelyhood of being actually read (as you don't have
to do any extra steps to obtain a readable document, just go and read it).

Grant Likely

unread,
Jul 5, 2016, 8:50:06 AM7/5/16
to

On 22/06/16 06:40, Srinivas Pandruvada wrote:
> Change log
> v2:
> - Overview in documentation show analogy with usbhid implementation
> - sparse errors for statics. Also pointed by Jiri
> - Clearly marking exported function header file. Clean up all exports
> unused inteface functions
> - Changed to tristate from boolean as pointed by Jiri:
> this required remove/unload functions
> - Prevent crash when ISH enabled on non supported platform
> - Break client.c to smaller part by seprating buffer allocations
> - move bus register/unregister to ishtp module
> - There is only one config symbol INTEL_ISH_HID, removed silent
> config for TRANSPORT and IPC
Tested-by: Grant Likely <grant....@secretlab.ca>

On an HP Spectre x360 laptop using v4.7-rc5.

In related news, the problem I had with the rotation events not showing
up on v1 of this series went away. I don't have a reason why, it just
suddenly started working.

g.

Grant Likely

unread,
Aug 24, 2016, 12:20:06 PM8/24/16
to
On Tue, Jul 5, 2016 at 8:42 AM, Grant Likely <gli...@secretlab.ca> wrote:
>
> On 22/06/16 06:40, Srinivas Pandruvada wrote:
>>
>> Change log
>> v2:
>> - Overview in documentation show analogy with usbhid implementation
>> - sparse errors for statics. Also pointed by Jiri
>> - Clearly marking exported function header file. Clean up all exports
>> unused inteface functions
>> - Changed to tristate from boolean as pointed by Jiri:
>> this required remove/unload functions
>> - Prevent crash when ISH enabled on non supported platform
>> - Break client.c to smaller part by seprating buffer allocations
>> - move bus register/unregister to ishtp module
>> - There is only one config symbol INTEL_ISH_HID, removed silent
>> config for TRANSPORT and IPC
>
> Tested-by: Grant Likely <grant....@secretlab.ca>
>
> On an HP Spectre x360 laptop using v4.7-rc5.

Hey Srinivas. Any progress on this patch series?

g.

Srinivas Pandruvada

unread,
Aug 24, 2016, 2:50:04 PM8/24/16
to
Unless someone has major objection, they can land up in 4.9.
They will go through two different trees, I can ping you once I see all
patches in linux-next.

Thanks,
Srinivas


>
> g.

Jiri Kosina

unread,
Aug 24, 2016, 5:20:05 PM8/24/16
to
On Wed, 24 Aug 2016, Grant Likely wrote:

> >> v2:
> >> - Overview in documentation show analogy with usbhid implementation
> >> - sparse errors for statics. Also pointed by Jiri
> >> - Clearly marking exported function header file. Clean up all exports
> >> unused inteface functions
> >> - Changed to tristate from boolean as pointed by Jiri:
> >> this required remove/unload functions
> >> - Prevent crash when ISH enabled on non supported platform
> >> - Break client.c to smaller part by seprating buffer allocations
> >> - move bus register/unregister to ishtp module
> >> - There is only one config symbol INTEL_ISH_HID, removed silent
> >> config for TRANSPORT and IPC
> >
> > Tested-by: Grant Likely <grant....@secretlab.ca>
> >
> > On an HP Spectre x360 laptop using v4.7-rc5.
>
> Hey Srinivas. Any progress on this patch series?

The HID part (with patch #5 omitted) should be in linux-next through
hid.git already.

Jonathan Cameron

unread,
Aug 24, 2016, 5:30:06 PM8/24/16
to
The one IIO patch was pulled by Greg KH last night so hit linux next
today. Hence all on it's way by the sound of it!

Jonathan

Grant Likely

unread,
Aug 31, 2016, 10:30:11 AM8/31/16
to
Nice!

Unfortunately, I've just hit a new bug after updating to v4.8-rc4.
4.7.0-rc6 works fine.

The kernel boots, and the driver loads, but the orientations are
wrong. It appears that the X/Y is getting swapped:

Normal orientation: display rotated 90 degrees CW
Rotated 90 degrees CW: display normal orientation
Rotated 180 degrees (upside down): display rotated 90 degrees CCW
Rotated 90 degrees CCW: display rotated 180 degrees

Cheers,
g.

Srinivas Pandruvada

unread,
Aug 31, 2016, 10:40:08 AM8/31/16
to
This is  also observed in all non ISH platforms too. I bisected it to
some commit, which I don't know how this impacts. Yesterday I sent
email to the list. Try reverting this, you should be fine.

 commit 703b5faf22fbddf984a361e6555f3a03fdba63d9
> Author: George Spelvin <li...@sciencehorizons.net>
> Date:   Fri Jun 10 00:22:12 2016 -0400
>
>     fs/dcache.c: Save one 32-bit multiply in dcache lookup
>
>     Noe that we're mixing in the parent pointer earlier, we
>     don't need to use hash_32() to mix its bits.  Instead, we can
>     just take the msbits of the hash value directly.
>
>     For those applications which use the partial_name_hash(),
>     move the multiply to end_name_hash.
>
>     Signed-off-by: George Spelvin <li...@sciencehorizons.net>
>     Signed-off-by: Linus Torvalds <torv...@linux-foundation.org>


Thanks,
Srinivas


> Cheers,
> g.
0 new messages