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 }, |