diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-07 13:05:39 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-07 13:05:39 -0500 |
| commit | c1f4c2b28c11f6d042d15100b36a4ebba07c48b2 (patch) | |
| tree | aff0d38d2bc3161d5ef3374f434b57519b30ffce | |
| parent | bc33b0ca11e3df467777a4fa7639ba488c9d4911 (diff) | |
| parent | 4c4480aad0d8eaf0d52b6f2c8c5dfbe0531cbbea (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/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
| -rw-r--r-- | drivers/hid/hid-ids.h | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-sensor-custom.c | 6 | ||||
| -rw-r--r-- | drivers/hid/hid-sensor-hub.c | 15 | ||||
| -rw-r--r-- | drivers/hid/intel-ish-hid/ipc/ipc.c | 102 | ||||
| -rw-r--r-- | drivers/hid/intel-ish-hid/ipc/pci-ish.c | 6 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 1 |
6 files changed, 95 insertions, 36 deletions
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 6cfb5cacc253..575aa65436d1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -179,6 +179,7 @@ | |||
| 179 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 | 179 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 |
| 180 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 | 180 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 |
| 181 | #define USB_DEVICE_ID_ATEN_CS682 0x2213 | 181 | #define USB_DEVICE_ID_ATEN_CS682 0x2213 |
| 182 | #define USB_DEVICE_ID_ATEN_CS692 0x8021 | ||
| 182 | 183 | ||
| 183 | #define USB_VENDOR_ID_ATMEL 0x03eb | 184 | #define USB_VENDOR_ID_ATMEL 0x03eb |
| 184 | #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c | 185 | #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c |
diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c index 5614fee82347..3a84aaf1418b 100644 --- a/drivers/hid/hid-sensor-custom.c +++ b/drivers/hid/hid-sensor-custom.c | |||
| @@ -292,11 +292,11 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr, | |||
| 292 | bool input = false; | 292 | bool input = false; |
| 293 | int value = 0; | 293 | int value = 0; |
| 294 | 294 | ||
| 295 | if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage, | 295 | if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage, |
| 296 | name) == 3) { | 296 | name) == 3) { |
| 297 | feature = true; | 297 | feature = true; |
| 298 | field_index = index + sensor_inst->input_field_count; | 298 | field_index = index + sensor_inst->input_field_count; |
| 299 | } else if (sscanf(attr->attr.name, "input-%d-%x-%s", &index, &usage, | 299 | } else if (sscanf(attr->attr.name, "input-%x-%x-%s", &index, &usage, |
| 300 | name) == 3) { | 300 | name) == 3) { |
| 301 | input = true; | 301 | input = true; |
| 302 | field_index = index; | 302 | field_index = index; |
| @@ -398,7 +398,7 @@ static ssize_t store_value(struct device *dev, struct device_attribute *attr, | |||
| 398 | char name[HID_CUSTOM_NAME_LENGTH]; | 398 | char name[HID_CUSTOM_NAME_LENGTH]; |
| 399 | int value; | 399 | int value; |
| 400 | 400 | ||
| 401 | if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage, | 401 | if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage, |
| 402 | name) == 3) { | 402 | name) == 3) { |
| 403 | field_index = index + sensor_inst->input_field_count; | 403 | field_index = index + sensor_inst->input_field_count; |
| 404 | } else | 404 | } else |
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 658a607dc6d9..c5c3d6111729 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c | |||
| @@ -251,6 +251,9 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, | |||
| 251 | struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); | 251 | struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev); |
| 252 | int report_size; | 252 | int report_size; |
| 253 | int ret = 0; | 253 | int ret = 0; |
| 254 | u8 *val_ptr; | ||
| 255 | int buffer_index = 0; | ||
| 256 | int i; | ||
| 254 | 257 | ||
| 255 | mutex_lock(&data->mutex); | 258 | mutex_lock(&data->mutex); |
| 256 | report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); | 259 | report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); |
| @@ -271,7 +274,17 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, | |||
| 271 | goto done_proc; | 274 | goto done_proc; |
| 272 | } | 275 | } |
| 273 | ret = min(report_size, buffer_size); | 276 | ret = min(report_size, buffer_size); |
| 274 | memcpy(buffer, report->field[field_index]->value, ret); | 277 | |
| 278 | val_ptr = (u8 *)report->field[field_index]->value; | ||
| 279 | for (i = 0; i < report->field[field_index]->report_count; ++i) { | ||
| 280 | if (buffer_index >= ret) | ||
| 281 | break; | ||
| 282 | |||
| 283 | memcpy(&((u8 *)buffer)[buffer_index], val_ptr, | ||
| 284 | report->field[field_index]->report_size / 8); | ||
| 285 | val_ptr += sizeof(__s32); | ||
| 286 | buffer_index += (report->field[field_index]->report_size / 8); | ||
| 287 | } | ||
| 275 | 288 | ||
| 276 | done_proc: | 289 | done_proc: |
| 277 | mutex_unlock(&data->mutex); | 290 | mutex_unlock(&data->mutex); |
diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index e2517c11e0ee..0c9ac4d5d850 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c | |||
| @@ -638,6 +638,58 @@ eoi: | |||
| 638 | } | 638 | } |
| 639 | 639 | ||
| 640 | /** | 640 | /** |
| 641 | * ish_disable_dma() - disable dma communication between host and ISHFW | ||
| 642 | * @dev: ishtp device pointer | ||
| 643 | * | ||
| 644 | * Clear the dma enable bit and wait for dma inactive. | ||
| 645 | * | ||
| 646 | * Return: 0 for success else error code. | ||
| 647 | */ | ||
| 648 | static int ish_disable_dma(struct ishtp_device *dev) | ||
| 649 | { | ||
| 650 | unsigned int dma_delay; | ||
| 651 | |||
| 652 | /* Clear the dma enable bit */ | ||
| 653 | ish_reg_write(dev, IPC_REG_ISH_RMP2, 0); | ||
| 654 | |||
| 655 | /* wait for dma inactive */ | ||
| 656 | for (dma_delay = 0; dma_delay < MAX_DMA_DELAY && | ||
| 657 | _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA); | ||
| 658 | dma_delay += 5) | ||
| 659 | mdelay(5); | ||
| 660 | |||
| 661 | if (dma_delay >= MAX_DMA_DELAY) { | ||
| 662 | dev_err(dev->devc, | ||
| 663 | "Wait for DMA inactive timeout\n"); | ||
| 664 | return -EBUSY; | ||
| 665 | } | ||
| 666 | |||
| 667 | return 0; | ||
| 668 | } | ||
| 669 | |||
| 670 | /** | ||
| 671 | * ish_wakeup() - wakeup ishfw from waiting-for-host state | ||
| 672 | * @dev: ishtp device pointer | ||
| 673 | * | ||
| 674 | * Set the dma enable bit and send a void message to FW, | ||
| 675 | * it wil wakeup FW from waiting-for-host state. | ||
| 676 | */ | ||
| 677 | static void ish_wakeup(struct ishtp_device *dev) | ||
| 678 | { | ||
| 679 | /* Set dma enable bit */ | ||
| 680 | ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); | ||
| 681 | |||
| 682 | /* | ||
| 683 | * Send 0 IPC message so that ISH FW wakes up if it was already | ||
| 684 | * asleep. | ||
| 685 | */ | ||
| 686 | ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); | ||
| 687 | |||
| 688 | /* Flush writes to doorbell and REMAP2 */ | ||
| 689 | ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); | ||
| 690 | } | ||
| 691 | |||
| 692 | /** | ||
| 641 | * _ish_hw_reset() - HW reset | 693 | * _ish_hw_reset() - HW reset |
| 642 | * @dev: ishtp device pointer | 694 | * @dev: ishtp device pointer |
| 643 | * | 695 | * |
| @@ -649,7 +701,6 @@ static int _ish_hw_reset(struct ishtp_device *dev) | |||
| 649 | { | 701 | { |
| 650 | struct pci_dev *pdev = dev->pdev; | 702 | struct pci_dev *pdev = dev->pdev; |
| 651 | int rv; | 703 | int rv; |
| 652 | unsigned int dma_delay; | ||
| 653 | uint16_t csr; | 704 | uint16_t csr; |
| 654 | 705 | ||
| 655 | if (!pdev) | 706 | if (!pdev) |
| @@ -664,15 +715,8 @@ static int _ish_hw_reset(struct ishtp_device *dev) | |||
| 664 | return -EINVAL; | 715 | return -EINVAL; |
| 665 | } | 716 | } |
| 666 | 717 | ||
| 667 | /* Now trigger reset to FW */ | 718 | /* Disable dma communication between FW and host */ |
| 668 | ish_reg_write(dev, IPC_REG_ISH_RMP2, 0); | 719 | if (ish_disable_dma(dev)) { |
| 669 | |||
| 670 | for (dma_delay = 0; dma_delay < MAX_DMA_DELAY && | ||
| 671 | _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA); | ||
| 672 | dma_delay += 5) | ||
| 673 | mdelay(5); | ||
| 674 | |||
| 675 | if (dma_delay >= MAX_DMA_DELAY) { | ||
| 676 | dev_err(&pdev->dev, | 720 | dev_err(&pdev->dev, |
| 677 | "Can't reset - stuck with DMA in-progress\n"); | 721 | "Can't reset - stuck with DMA in-progress\n"); |
| 678 | return -EBUSY; | 722 | return -EBUSY; |
| @@ -690,16 +734,8 @@ static int _ish_hw_reset(struct ishtp_device *dev) | |||
| 690 | csr |= PCI_D0; | 734 | csr |= PCI_D0; |
| 691 | pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); | 735 | pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); |
| 692 | 736 | ||
| 693 | ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); | 737 | /* Now we can enable ISH DMA operation and wakeup ISHFW */ |
| 694 | 738 | ish_wakeup(dev); | |
| 695 | /* | ||
| 696 | * Send 0 IPC message so that ISH FW wakes up if it was already | ||
| 697 | * asleep | ||
| 698 | */ | ||
| 699 | ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); | ||
| 700 | |||
| 701 | /* Flush writes to doorbell and REMAP2 */ | ||
| 702 | ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); | ||
| 703 | 739 | ||
| 704 | return 0; | 740 | return 0; |
| 705 | } | 741 | } |
| @@ -758,16 +794,9 @@ static int _ish_ipc_reset(struct ishtp_device *dev) | |||
| 758 | int ish_hw_start(struct ishtp_device *dev) | 794 | int ish_hw_start(struct ishtp_device *dev) |
| 759 | { | 795 | { |
| 760 | ish_set_host_rdy(dev); | 796 | ish_set_host_rdy(dev); |
| 761 | /* After that we can enable ISH DMA operation */ | ||
| 762 | ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); | ||
| 763 | 797 | ||
| 764 | /* | 798 | /* After that we can enable ISH DMA operation and wakeup ISHFW */ |
| 765 | * Send 0 IPC message so that ISH FW wakes up if it was already | 799 | ish_wakeup(dev); |
| 766 | * asleep | ||
| 767 | */ | ||
| 768 | ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); | ||
| 769 | /* Flush write to doorbell */ | ||
| 770 | ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); | ||
| 771 | 800 | ||
| 772 | set_host_ready(dev); | 801 | set_host_ready(dev); |
| 773 | 802 | ||
| @@ -876,6 +905,21 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) | |||
| 876 | */ | 905 | */ |
| 877 | void ish_device_disable(struct ishtp_device *dev) | 906 | void ish_device_disable(struct ishtp_device *dev) |
| 878 | { | 907 | { |
| 908 | struct pci_dev *pdev = dev->pdev; | ||
| 909 | |||
| 910 | if (!pdev) | ||
| 911 | return; | ||
| 912 | |||
| 913 | /* Disable dma communication between FW and host */ | ||
| 914 | if (ish_disable_dma(dev)) { | ||
| 915 | dev_err(&pdev->dev, | ||
| 916 | "Can't reset - stuck with DMA in-progress\n"); | ||
| 917 | return; | ||
| 918 | } | ||
| 919 | |||
| 920 | /* Put ISH to D3hot state for power saving */ | ||
| 921 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 922 | |||
| 879 | dev->dev_state = ISHTP_DEV_DISABLED; | 923 | dev->dev_state = ISHTP_DEV_DISABLED; |
| 880 | ish_clr_host_rdy(dev); | 924 | ish_clr_host_rdy(dev); |
| 881 | } | 925 | } |
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index 42f0beeb09fd..20d647d2dd2c 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c | |||
| @@ -146,7 +146,7 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 146 | pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3; | 146 | pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3; |
| 147 | 147 | ||
| 148 | /* request and enable interrupt */ | 148 | /* request and enable interrupt */ |
| 149 | ret = request_irq(pdev->irq, ish_irq_handler, IRQF_NO_SUSPEND, | 149 | ret = request_irq(pdev->irq, ish_irq_handler, IRQF_SHARED, |
| 150 | KBUILD_MODNAME, dev); | 150 | KBUILD_MODNAME, dev); |
| 151 | if (ret) { | 151 | if (ret) { |
| 152 | dev_err(&pdev->dev, "ISH: request IRQ failure (%d)\n", | 152 | dev_err(&pdev->dev, "ISH: request IRQ failure (%d)\n", |
| @@ -202,6 +202,7 @@ static void ish_remove(struct pci_dev *pdev) | |||
| 202 | kfree(ishtp_dev); | 202 | kfree(ishtp_dev); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | #ifdef CONFIG_PM | ||
| 205 | static struct device *ish_resume_device; | 206 | static struct device *ish_resume_device; |
| 206 | 207 | ||
| 207 | /** | 208 | /** |
| @@ -293,7 +294,6 @@ static int ish_resume(struct device *device) | |||
| 293 | return 0; | 294 | return 0; |
| 294 | } | 295 | } |
| 295 | 296 | ||
| 296 | #ifdef CONFIG_PM | ||
| 297 | static const struct dev_pm_ops ish_pm_ops = { | 297 | static const struct dev_pm_ops ish_pm_ops = { |
| 298 | .suspend = ish_suspend, | 298 | .suspend = ish_suspend, |
| 299 | .resume = ish_resume, | 299 | .resume = ish_resume, |
| @@ -301,7 +301,7 @@ static const struct dev_pm_ops ish_pm_ops = { | |||
| 301 | #define ISHTP_ISH_PM_OPS (&ish_pm_ops) | 301 | #define ISHTP_ISH_PM_OPS (&ish_pm_ops) |
| 302 | #else | 302 | #else |
| 303 | #define ISHTP_ISH_PM_OPS NULL | 303 | #define ISHTP_ISH_PM_OPS NULL |
| 304 | #endif | 304 | #endif /* CONFIG_PM */ |
| 305 | 305 | ||
| 306 | static struct pci_driver ish_driver = { | 306 | static struct pci_driver ish_driver = { |
| 307 | .name = KBUILD_MODNAME, | 307 | .name = KBUILD_MODNAME, |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 354d49ea36dd..e6cfd323babc 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -63,6 +63,7 @@ static const struct hid_blacklist { | |||
| 63 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, | 63 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, |
| 64 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, | 64 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, |
| 65 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET }, | 65 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET }, |
| 66 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET }, | ||
| 66 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET }, | 67 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET }, |
| 67 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, | 68 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, |
| 68 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, | 69 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, |
