Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jikos/hid

Pull HID fixes from Jiri Kosina:

 - modprobe-after-rmmod load failure bugfix for intel-ish, from Even Xu

 - IRQ probing bugfix for intel-ish, from Srinivas Pandruvada

 - attribute parsing fix in hid-sensor, from Ooi, Joyce

 - other small misc fixes / quirky device additions

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
  HID: sensor: fix attributes in HID sensor interface
  HID: intel-ish-hid: request_irq failure
  HID: intel-ish-hid: Fix driver reinit failure
  HID: intel-ish-hid: Move DMA disable code to new function
  HID: intel-ish-hid: consolidate ish wake up operation
  HID: usbhid: add ATEN CS962 to list of quirky devices
  HID: intel-ish-hid: Fix !CONFIG_PM build warning
  HID: sensor-hub: Fix packing of result buffer for feature report
  • Loading branch information
Linus Torvalds committed Nov 7, 2016
2 parents bc33b0c + 4c4480a commit c1f4c2b
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 36 deletions.
1 change: 1 addition & 0 deletions drivers/hid/hid-ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@
#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208
#define USB_DEVICE_ID_ATEN_CS682 0x2213
#define USB_DEVICE_ID_ATEN_CS692 0x8021

#define USB_VENDOR_ID_ATMEL 0x03eb
#define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c
Expand Down
6 changes: 3 additions & 3 deletions drivers/hid/hid-sensor-custom.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,11 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
bool input = false;
int value = 0;

if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage,
if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage,
name) == 3) {
feature = true;
field_index = index + sensor_inst->input_field_count;
} else if (sscanf(attr->attr.name, "input-%d-%x-%s", &index, &usage,
} else if (sscanf(attr->attr.name, "input-%x-%x-%s", &index, &usage,
name) == 3) {
input = true;
field_index = index;
Expand Down Expand Up @@ -398,7 +398,7 @@ static ssize_t store_value(struct device *dev, struct device_attribute *attr,
char name[HID_CUSTOM_NAME_LENGTH];
int value;

if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage,
if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage,
name) == 3) {
field_index = index + sensor_inst->input_field_count;
} else
Expand Down
15 changes: 14 additions & 1 deletion drivers/hid/hid-sensor-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
int report_size;
int ret = 0;
u8 *val_ptr;
int buffer_index = 0;
int i;

mutex_lock(&data->mutex);
report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
Expand All @@ -271,7 +274,17 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
goto done_proc;
}
ret = min(report_size, buffer_size);
memcpy(buffer, report->field[field_index]->value, ret);

val_ptr = (u8 *)report->field[field_index]->value;
for (i = 0; i < report->field[field_index]->report_count; ++i) {
if (buffer_index >= ret)
break;

memcpy(&((u8 *)buffer)[buffer_index], val_ptr,
report->field[field_index]->report_size / 8);
val_ptr += sizeof(__s32);
buffer_index += (report->field[field_index]->report_size / 8);
}

done_proc:
mutex_unlock(&data->mutex);
Expand Down
102 changes: 73 additions & 29 deletions drivers/hid/intel-ish-hid/ipc/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,58 @@ irqreturn_t ish_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}

/**
* ish_disable_dma() - disable dma communication between host and ISHFW
* @dev: ishtp device pointer
*
* Clear the dma enable bit and wait for dma inactive.
*
* Return: 0 for success else error code.
*/
static int ish_disable_dma(struct ishtp_device *dev)
{
unsigned int dma_delay;

/* Clear the dma enable bit */
ish_reg_write(dev, IPC_REG_ISH_RMP2, 0);

/* wait for dma inactive */
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(dev->devc,
"Wait for DMA inactive timeout\n");
return -EBUSY;
}

return 0;
}

/**
* ish_wakeup() - wakeup ishfw from waiting-for-host state
* @dev: ishtp device pointer
*
* Set the dma enable bit and send a void message to FW,
* it wil wakeup FW from waiting-for-host state.
*/
static void ish_wakeup(struct ishtp_device *dev)
{
/* Set dma enable bit */
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);
}

/**
* _ish_hw_reset() - HW reset
* @dev: ishtp device pointer
Expand All @@ -649,7 +701,6 @@ 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)
Expand All @@ -664,15 +715,8 @@ static int _ish_hw_reset(struct ishtp_device *dev)
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) {
/* Disable dma communication between FW and host */
if (ish_disable_dma(dev)) {
dev_err(&pdev->dev,
"Can't reset - stuck with DMA in-progress\n");
return -EBUSY;
Expand All @@ -690,16 +734,8 @@ static int _ish_hw_reset(struct ishtp_device *dev)
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);
/* Now we can enable ISH DMA operation and wakeup ISHFW */
ish_wakeup(dev);

return 0;
}
Expand Down Expand Up @@ -758,16 +794,9 @@ static int _ish_ipc_reset(struct ishtp_device *dev)
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);
/* After that we can enable ISH DMA operation and wakeup ISHFW */
ish_wakeup(dev);

set_host_ready(dev);

Expand Down Expand Up @@ -876,6 +905,21 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
*/
void ish_device_disable(struct ishtp_device *dev)
{
struct pci_dev *pdev = dev->pdev;

if (!pdev)
return;

/* Disable dma communication between FW and host */
if (ish_disable_dma(dev)) {
dev_err(&pdev->dev,
"Can't reset - stuck with DMA in-progress\n");
return;
}

/* Put ISH to D3hot state for power saving */
pci_set_power_state(pdev, PCI_D3hot);

dev->dev_state = ISHTP_DEV_DISABLED;
ish_clr_host_rdy(dev);
}
6 changes: 3 additions & 3 deletions drivers/hid/intel-ish-hid/ipc/pci-ish.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;

/* request and enable interrupt */
ret = request_irq(pdev->irq, ish_irq_handler, IRQF_NO_SUSPEND,
ret = request_irq(pdev->irq, ish_irq_handler, IRQF_SHARED,
KBUILD_MODNAME, dev);
if (ret) {
dev_err(&pdev->dev, "ISH: request IRQ failure (%d)\n",
Expand Down Expand Up @@ -202,6 +202,7 @@ static void ish_remove(struct pci_dev *pdev)
kfree(ishtp_dev);
}

#ifdef CONFIG_PM
static struct device *ish_resume_device;

/**
Expand Down Expand Up @@ -293,15 +294,14 @@ static int ish_resume(struct device *device)
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
#endif /* CONFIG_PM */

static struct pci_driver ish_driver = {
.name = KBUILD_MODNAME,
Expand Down
1 change: 1 addition & 0 deletions drivers/hid/usbhid/hid-quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET },
Expand Down

0 comments on commit c1f4c2b

Please sign in to comment.