mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 23:23:03 +00:00
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
This commit is contained in:
commit
c1f4c2b28c
@ -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
|
||||
|
@ -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;
|
||||
@ -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
|
||||
|
@ -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);
|
||||
@ -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);
|
||||
|
@ -637,6 +637,58 @@ eoi:
|
||||
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
|
||||
@ -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)
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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",
|
||||
@ -202,6 +202,7 @@ static void ish_remove(struct pci_dev *pdev)
|
||||
kfree(ishtp_dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static struct device *ish_resume_device;
|
||||
|
||||
/**
|
||||
@ -293,7 +294,6 @@ 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,
|
||||
@ -301,7 +301,7 @@ static const struct dev_pm_ops ish_pm_ops = {
|
||||
#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,
|
||||
|
@ -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 },
|
||||
|
Loading…
Reference in New Issue
Block a user