Commit 9f66d83e authored by Jiri Kosina's avatar Jiri Kosina

Merge branch 'for-5.1/i2c-hid' into for-linus

Fix dmesg flood for Elan touchpanels which are too slow to assert IRQ from Kai-Heng Feng
parents edaea3d9 09cc8b36
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET BIT(1) #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET BIT(1)
#define I2C_HID_QUIRK_NO_RUNTIME_PM BIT(2) #define I2C_HID_QUIRK_NO_RUNTIME_PM BIT(2)
#define I2C_HID_QUIRK_DELAY_AFTER_SLEEP BIT(3) #define I2C_HID_QUIRK_DELAY_AFTER_SLEEP BIT(3)
#define I2C_HID_QUIRK_BOGUS_IRQ BIT(4)
/* flags */ /* flags */
#define I2C_HID_STARTED 0 #define I2C_HID_STARTED 0
...@@ -181,6 +182,8 @@ static const struct i2c_hid_quirks { ...@@ -181,6 +182,8 @@ static const struct i2c_hid_quirks {
I2C_HID_QUIRK_NO_RUNTIME_PM }, I2C_HID_QUIRK_NO_RUNTIME_PM },
{ I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0, { I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0,
I2C_HID_QUIRK_NO_RUNTIME_PM }, I2C_HID_QUIRK_NO_RUNTIME_PM },
{ USB_VENDOR_ID_ELAN, HID_ANY_ID,
I2C_HID_QUIRK_BOGUS_IRQ },
{ 0, 0 } { 0, 0 }
}; };
...@@ -505,6 +508,12 @@ static void i2c_hid_get_input(struct i2c_hid *ihid) ...@@ -505,6 +508,12 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
return; return;
} }
if (ihid->quirks & I2C_HID_QUIRK_BOGUS_IRQ && ret_size == 0xffff) {
dev_warn_once(&ihid->client->dev, "%s: IRQ triggered but "
"there's no data\n", __func__);
return;
}
if ((ret_size > size) || (ret_size < 2)) { if ((ret_size > size) || (ret_size < 2)) {
dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n", dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
__func__, size, ret_size); __func__, size, ret_size);
......
...@@ -259,33 +259,22 @@ static int write_ipc_from_queue(struct ishtp_device *dev) ...@@ -259,33 +259,22 @@ static int write_ipc_from_queue(struct ishtp_device *dev)
int i; int i;
void (*ipc_send_compl)(void *); void (*ipc_send_compl)(void *);
void *ipc_send_compl_prm; void *ipc_send_compl_prm;
static int out_ipc_locked;
unsigned long out_ipc_flags;
if (dev->dev_state == ISHTP_DEV_DISABLED) if (dev->dev_state == ISHTP_DEV_DISABLED)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&dev->out_ipc_spinlock, out_ipc_flags); spin_lock_irqsave(&dev->wr_processing_spinlock, 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)) { if (!ish_is_input_ready(dev)) {
out_ipc_locked = 0; spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags);
return -EBUSY; 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; * if tx send list is empty - return 0;
* may happen, as RX_COMPLETE handler doesn't check list emptiness. * may happen, as RX_COMPLETE handler doesn't check list emptiness.
*/ */
if (list_empty(&dev->wr_processing_list)) { if (list_empty(&dev->wr_processing_list)) {
spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
out_ipc_locked = 0;
return 0; return 0;
} }
...@@ -328,6 +317,8 @@ static int write_ipc_from_queue(struct ishtp_device *dev) ...@@ -328,6 +317,8 @@ static int write_ipc_from_queue(struct ishtp_device *dev)
memcpy(&reg, &r_buf[length >> 2], rem); memcpy(&reg, &r_buf[length >> 2], rem);
ish_reg_write(dev, reg_addr, reg); ish_reg_write(dev, reg_addr, reg);
} }
ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, doorbell_val);
/* Flush writes to msg registers and doorbell */ /* Flush writes to msg registers and doorbell */
ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
...@@ -335,9 +326,6 @@ static int write_ipc_from_queue(struct ishtp_device *dev) ...@@ -335,9 +326,6 @@ static int write_ipc_from_queue(struct ishtp_device *dev)
++dev->ipc_tx_cnt; ++dev->ipc_tx_cnt;
dev->ipc_tx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val); 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 = ipc_link->ipc_send_compl;
ipc_send_compl_prm = ipc_link->ipc_send_compl_prm; ipc_send_compl_prm = ipc_link->ipc_send_compl_prm;
list_del_init(&ipc_link->link); list_del_init(&ipc_link->link);
...@@ -917,7 +905,6 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) ...@@ -917,7 +905,6 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
init_waitqueue_head(&dev->wait_hw_ready); init_waitqueue_head(&dev->wait_hw_ready);
spin_lock_init(&dev->wr_processing_spinlock); spin_lock_init(&dev->wr_processing_spinlock);
spin_lock_init(&dev->out_ipc_spinlock);
/* Init IPC processing and free lists */ /* Init IPC processing and free lists */
INIT_LIST_HEAD(&dev->wr_processing_list); INIT_LIST_HEAD(&dev->wr_processing_list);
......
...@@ -119,7 +119,7 @@ int ishtp_send_msg(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr, ...@@ -119,7 +119,7 @@ int ishtp_send_msg(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr,
* Return: This returns IPC send message status. * Return: This returns IPC send message status.
*/ */
int ishtp_write_message(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr, int ishtp_write_message(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr,
unsigned char *buf) void *buf)
{ {
return ishtp_send_msg(dev, hdr, buf, NULL, NULL); return ishtp_send_msg(dev, hdr, buf, NULL, NULL);
} }
...@@ -672,7 +672,8 @@ int ishtp_cl_device_bind(struct ishtp_cl *cl) ...@@ -672,7 +672,8 @@ int ishtp_cl_device_bind(struct ishtp_cl *cl)
spin_lock_irqsave(&cl->dev->device_list_lock, flags); spin_lock_irqsave(&cl->dev->device_list_lock, flags);
list_for_each_entry(cl_device, &cl->dev->device_list, list_for_each_entry(cl_device, &cl->dev->device_list,
device_link) { device_link) {
if (cl_device->fw_client->client_id == cl->fw_client_id) { if (cl_device->fw_client &&
cl_device->fw_client->client_id == cl->fw_client_id) {
cl->device = cl_device; cl->device = cl_device;
rv = 0; rv = 0;
break; break;
...@@ -732,6 +733,7 @@ void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev, ...@@ -732,6 +733,7 @@ void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev,
spin_lock_irqsave(&ishtp_dev->device_list_lock, flags); spin_lock_irqsave(&ishtp_dev->device_list_lock, flags);
list_for_each_entry_safe(cl_device, n, &ishtp_dev->device_list, list_for_each_entry_safe(cl_device, n, &ishtp_dev->device_list,
device_link) { device_link) {
cl_device->fw_client = NULL;
if (warm_reset && cl_device->reference_count) if (warm_reset && cl_device->reference_count)
continue; continue;
......
...@@ -85,7 +85,7 @@ int ishtp_send_msg(struct ishtp_device *dev, ...@@ -85,7 +85,7 @@ int ishtp_send_msg(struct ishtp_device *dev,
/* Write a single-fragment message */ /* Write a single-fragment message */
int ishtp_write_message(struct ishtp_device *dev, int ishtp_write_message(struct ishtp_device *dev,
struct ishtp_msg_hdr *hdr, struct ishtp_msg_hdr *hdr,
unsigned char *buf); void *buf);
/* Use DMA to send/receive messages */ /* Use DMA to send/receive messages */
int ishtp_use_dma_transfer(void); int ishtp_use_dma_transfer(void);
......
...@@ -136,19 +136,14 @@ int ishtp_hbm_start_wait(struct ishtp_device *dev) ...@@ -136,19 +136,14 @@ int ishtp_hbm_start_wait(struct ishtp_device *dev)
int ishtp_hbm_start_req(struct ishtp_device *dev) int ishtp_hbm_start_req(struct ishtp_device *dev)
{ {
struct ishtp_msg_hdr hdr; struct ishtp_msg_hdr hdr;
unsigned char data[128]; struct hbm_host_version_request start_req = { 0 };
struct ishtp_msg_hdr *ishtp_hdr = &hdr;
struct hbm_host_version_request *start_req;
const size_t len = sizeof(struct hbm_host_version_request);
ishtp_hbm_hdr(ishtp_hdr, len); ishtp_hbm_hdr(&hdr, sizeof(start_req));
/* host start message */ /* host start message */
start_req = (struct hbm_host_version_request *)data; start_req.hbm_cmd = HOST_START_REQ_CMD;
memset(start_req, 0, len); start_req.host_version.major_version = HBM_MAJOR_VERSION;
start_req->hbm_cmd = HOST_START_REQ_CMD; start_req.host_version.minor_version = HBM_MINOR_VERSION;
start_req->host_version.major_version = HBM_MAJOR_VERSION;
start_req->host_version.minor_version = HBM_MINOR_VERSION;
/* /*
* (!) Response to HBM start may be so quick that this thread would get * (!) Response to HBM start may be so quick that this thread would get
...@@ -156,7 +151,7 @@ int ishtp_hbm_start_req(struct ishtp_device *dev) ...@@ -156,7 +151,7 @@ int ishtp_hbm_start_req(struct ishtp_device *dev)
* So set it at first, change back to ISHTP_HBM_IDLE upon failure * So set it at first, change back to ISHTP_HBM_IDLE upon failure
*/ */
dev->hbm_state = ISHTP_HBM_START; dev->hbm_state = ISHTP_HBM_START;
if (ishtp_write_message(dev, ishtp_hdr, data)) { if (ishtp_write_message(dev, &hdr, &start_req)) {
dev_err(dev->devc, "version message send failed\n"); dev_err(dev->devc, "version message send failed\n");
dev->dev_state = ISHTP_DEV_RESETTING; dev->dev_state = ISHTP_DEV_RESETTING;
dev->hbm_state = ISHTP_HBM_IDLE; dev->hbm_state = ISHTP_HBM_IDLE;
...@@ -178,19 +173,13 @@ int ishtp_hbm_start_req(struct ishtp_device *dev) ...@@ -178,19 +173,13 @@ int ishtp_hbm_start_req(struct ishtp_device *dev)
void ishtp_hbm_enum_clients_req(struct ishtp_device *dev) void ishtp_hbm_enum_clients_req(struct ishtp_device *dev)
{ {
struct ishtp_msg_hdr hdr; struct ishtp_msg_hdr hdr;
unsigned char data[128]; struct hbm_host_enum_request enum_req = { 0 };
struct ishtp_msg_hdr *ishtp_hdr = &hdr;
struct hbm_host_enum_request *enum_req;
const size_t len = sizeof(struct hbm_host_enum_request);
/* enumerate clients */ /* enumerate clients */
ishtp_hbm_hdr(ishtp_hdr, len); ishtp_hbm_hdr(&hdr, sizeof(enum_req));
enum_req.hbm_cmd = HOST_ENUM_REQ_CMD;
enum_req = (struct hbm_host_enum_request *)data; if (ishtp_write_message(dev, &hdr, &enum_req)) {
memset(enum_req, 0, len);
enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
if (ishtp_write_message(dev, ishtp_hdr, data)) {
dev->dev_state = ISHTP_DEV_RESETTING; dev->dev_state = ISHTP_DEV_RESETTING;
dev_err(dev->devc, "enumeration request send failed\n"); dev_err(dev->devc, "enumeration request send failed\n");
ish_hw_reset(dev); ish_hw_reset(dev);
...@@ -208,12 +197,8 @@ void ishtp_hbm_enum_clients_req(struct ishtp_device *dev) ...@@ -208,12 +197,8 @@ void ishtp_hbm_enum_clients_req(struct ishtp_device *dev)
*/ */
static int ishtp_hbm_prop_req(struct ishtp_device *dev) static int ishtp_hbm_prop_req(struct ishtp_device *dev)
{ {
struct ishtp_msg_hdr hdr; struct ishtp_msg_hdr hdr;
unsigned char data[128]; struct hbm_props_request prop_req = { 0 };
struct ishtp_msg_hdr *ishtp_hdr = &hdr;
struct hbm_props_request *prop_req;
const size_t len = sizeof(struct hbm_props_request);
unsigned long next_client_index; unsigned long next_client_index;
uint8_t client_num; uint8_t client_num;
...@@ -237,15 +222,12 @@ static int ishtp_hbm_prop_req(struct ishtp_device *dev) ...@@ -237,15 +222,12 @@ static int ishtp_hbm_prop_req(struct ishtp_device *dev)
dev->fw_clients[client_num].client_id = next_client_index; dev->fw_clients[client_num].client_id = next_client_index;
ishtp_hbm_hdr(ishtp_hdr, len); ishtp_hbm_hdr(&hdr, sizeof(prop_req));
prop_req = (struct hbm_props_request *)data;
memset(prop_req, 0, sizeof(struct hbm_props_request)); prop_req.hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
prop_req.address = next_client_index;
prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; if (ishtp_write_message(dev, &hdr, &prop_req)) {
prop_req->address = next_client_index;
if (ishtp_write_message(dev, ishtp_hdr, data)) {
dev->dev_state = ISHTP_DEV_RESETTING; dev->dev_state = ISHTP_DEV_RESETTING;
dev_err(dev->devc, "properties request send failed\n"); dev_err(dev->devc, "properties request send failed\n");
ish_hw_reset(dev); ish_hw_reset(dev);
...@@ -266,19 +248,14 @@ static int ishtp_hbm_prop_req(struct ishtp_device *dev) ...@@ -266,19 +248,14 @@ static int ishtp_hbm_prop_req(struct ishtp_device *dev)
static void ishtp_hbm_stop_req(struct ishtp_device *dev) static void ishtp_hbm_stop_req(struct ishtp_device *dev)
{ {
struct ishtp_msg_hdr hdr; struct ishtp_msg_hdr hdr;
unsigned char data[128]; struct hbm_host_stop_request stop_req = { 0 } ;
struct ishtp_msg_hdr *ishtp_hdr = &hdr;
struct hbm_host_stop_request *req;
const size_t len = sizeof(struct hbm_host_stop_request);
ishtp_hbm_hdr(ishtp_hdr, len); ishtp_hbm_hdr(&hdr, sizeof(stop_req));
req = (struct hbm_host_stop_request *)data;
memset(req, 0, sizeof(struct hbm_host_stop_request)); stop_req.hbm_cmd = HOST_STOP_REQ_CMD;
req->hbm_cmd = HOST_STOP_REQ_CMD; stop_req.reason = DRIVER_STOP_REQUEST;
req->reason = DRIVER_STOP_REQUEST;
ishtp_write_message(dev, ishtp_hdr, data); ishtp_write_message(dev, &hdr, &stop_req);
} }
/** /**
...@@ -294,15 +271,15 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev, ...@@ -294,15 +271,15 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
struct ishtp_cl *cl) struct ishtp_cl *cl)
{ {
struct ishtp_msg_hdr hdr; struct ishtp_msg_hdr hdr;
unsigned char data[128]; struct hbm_flow_control flow_ctrl;
struct ishtp_msg_hdr *ishtp_hdr = &hdr; const size_t len = sizeof(flow_ctrl);
const size_t len = sizeof(struct hbm_flow_control);
int rv; int rv;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&cl->fc_spinlock, flags); spin_lock_irqsave(&cl->fc_spinlock, flags);
ishtp_hbm_hdr(ishtp_hdr, len);
ishtp_hbm_cl_hdr(cl, ISHTP_FLOW_CONTROL_CMD, data, len); ishtp_hbm_hdr(&hdr, len);
ishtp_hbm_cl_hdr(cl, ISHTP_FLOW_CONTROL_CMD, &flow_ctrl, len);
/* /*
* Sync possible race when RB recycle and packet receive paths * Sync possible race when RB recycle and packet receive paths
...@@ -315,7 +292,7 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev, ...@@ -315,7 +292,7 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
cl->recv_msg_num_frags = 0; cl->recv_msg_num_frags = 0;
rv = ishtp_write_message(dev, ishtp_hdr, data); rv = ishtp_write_message(dev, &hdr, &flow_ctrl);
if (!rv) { if (!rv) {
++cl->out_flow_ctrl_creds; ++cl->out_flow_ctrl_creds;
++cl->out_flow_ctrl_cnt; ++cl->out_flow_ctrl_cnt;
...@@ -345,14 +322,13 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev, ...@@ -345,14 +322,13 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
int ishtp_hbm_cl_disconnect_req(struct ishtp_device *dev, struct ishtp_cl *cl) int ishtp_hbm_cl_disconnect_req(struct ishtp_device *dev, struct ishtp_cl *cl)
{ {
struct ishtp_msg_hdr hdr; struct ishtp_msg_hdr hdr;
unsigned char data[128]; struct hbm_client_connect_request disconn_req;
struct ishtp_msg_hdr *ishtp_hdr = &hdr; const size_t len = sizeof(disconn_req);
const size_t len = sizeof(struct hbm_client_connect_request);
ishtp_hbm_hdr(ishtp_hdr, len); ishtp_hbm_hdr(&hdr, len);
ishtp_hbm_cl_hdr(cl, CLIENT_DISCONNECT_REQ_CMD, data, len); ishtp_hbm_cl_hdr(cl, CLIENT_DISCONNECT_REQ_CMD, &disconn_req, len);
return ishtp_write_message(dev, ishtp_hdr, data); return ishtp_write_message(dev, &hdr, &disconn_req);
} }
/** /**
...@@ -391,14 +367,13 @@ static void ishtp_hbm_cl_disconnect_res(struct ishtp_device *dev, ...@@ -391,14 +367,13 @@ static void ishtp_hbm_cl_disconnect_res(struct ishtp_device *dev,
int ishtp_hbm_cl_connect_req(struct ishtp_device *dev, struct ishtp_cl *cl) int ishtp_hbm_cl_connect_req(struct ishtp_device *dev, struct ishtp_cl *cl)
{ {
struct ishtp_msg_hdr hdr; struct ishtp_msg_hdr hdr;
unsigned char data[128]; struct hbm_client_connect_request conn_req;
struct ishtp_msg_hdr *ishtp_hdr = &hdr; const size_t len = sizeof(conn_req);
const size_t len = sizeof(struct hbm_client_connect_request);
ishtp_hbm_hdr(ishtp_hdr, len); ishtp_hbm_hdr(&hdr, len);
ishtp_hbm_cl_hdr(cl, CLIENT_CONNECT_REQ_CMD, data, len); ishtp_hbm_cl_hdr(cl, CLIENT_CONNECT_REQ_CMD, &conn_req, len);
return ishtp_write_message(dev, ishtp_hdr, data); return ishtp_write_message(dev, &hdr, &conn_req);
} }
/** /**
......
...@@ -211,8 +211,6 @@ struct ishtp_device { ...@@ -211,8 +211,6 @@ struct ishtp_device {
/* For both processing list and free list */ /* For both processing list and free list */
spinlock_t wr_processing_spinlock; spinlock_t wr_processing_spinlock;
spinlock_t out_ipc_spinlock;
struct ishtp_fw_client *fw_clients; /*Note:memory has to be allocated*/ struct ishtp_fw_client *fw_clients; /*Note:memory has to be allocated*/
DECLARE_BITMAP(fw_clients_map, ISHTP_CLIENTS_MAX); DECLARE_BITMAP(fw_clients_map, ISHTP_CLIENTS_MAX);
DECLARE_BITMAP(host_clients_map, ISHTP_CLIENTS_MAX); DECLARE_BITMAP(host_clients_map, ISHTP_CLIENTS_MAX);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment