mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - memory leak fix for hid-elo driver (Dongliang Mu) - fix for hangs on newer AMD platforms with amd_sfh-driven hardware (Basavaraj Natikar ) - locking fix in i2c-hid (Daniel Thompson) - a few device-ID specific quirks * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: amd_sfh: Add interrupt handler to process interrupts HID: amd_sfh: Add functionality to clear interrupts HID: amd_sfh: Disable the interrupt for all command HID: amd_sfh: Correct the structure field name HID: amd_sfh: Handle amd_sfh work buffer in PM ops HID:Add support for UGTABLET WP5540 HID: amd_sfh: Add illuminance mask to limit ALS max value HID: amd_sfh: Increase sensor command timeout HID: i2c-hid: goodix: Fix a lockdep splat HID: elo: fix memory leak in elo_probe HID: apple: Set the tilde quirk flag on the Wellspring 5 and later
This commit is contained in:
commit
a254a9da45
@ -37,11 +37,11 @@ static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_
|
||||
{
|
||||
union cmd_response cmd_resp;
|
||||
|
||||
/* Get response with status within a max of 800 ms timeout */
|
||||
/* Get response with status within a max of 1600 ms timeout */
|
||||
if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
|
||||
(cmd_resp.response_v2.response == sensor_sts &&
|
||||
cmd_resp.response_v2.status == 0 && (sid == 0xff ||
|
||||
cmd_resp.response_v2.sensor_id == sid)), 500, 800000))
|
||||
cmd_resp.response_v2.sensor_id == sid)), 500, 1600000))
|
||||
return cmd_resp.response_v2.response;
|
||||
|
||||
return SENSOR_DISABLED;
|
||||
@ -53,6 +53,7 @@ static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sen
|
||||
|
||||
cmd_base.ul = 0;
|
||||
cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR;
|
||||
cmd_base.cmd_v2.intr_disable = 1;
|
||||
cmd_base.cmd_v2.period = info.period;
|
||||
cmd_base.cmd_v2.sensor_id = info.sensor_idx;
|
||||
cmd_base.cmd_v2.length = 16;
|
||||
@ -70,6 +71,7 @@ static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx)
|
||||
|
||||
cmd_base.ul = 0;
|
||||
cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR;
|
||||
cmd_base.cmd_v2.intr_disable = 1;
|
||||
cmd_base.cmd_v2.period = 0;
|
||||
cmd_base.cmd_v2.sensor_id = sensor_idx;
|
||||
cmd_base.cmd_v2.length = 16;
|
||||
@ -83,12 +85,51 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
|
||||
union sfh_cmd_base cmd_base;
|
||||
|
||||
cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS;
|
||||
cmd_base.cmd_v2.intr_disable = 1;
|
||||
cmd_base.cmd_v2.period = 0;
|
||||
cmd_base.cmd_v2.sensor_id = 0;
|
||||
|
||||
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
|
||||
}
|
||||
|
||||
static void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (readl(privdata->mmio + AMD_P2C_MSG(4))) {
|
||||
writel(0, privdata->mmio + AMD_P2C_MSG(4));
|
||||
writel(0xf, privdata->mmio + AMD_P2C_MSG(5));
|
||||
}
|
||||
}
|
||||
|
||||
static void amd_sfh_clear_intr(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (privdata->mp2_ops->clear_intr)
|
||||
privdata->mp2_ops->clear_intr(privdata);
|
||||
}
|
||||
|
||||
static irqreturn_t amd_sfh_irq_handler(int irq, void *data)
|
||||
{
|
||||
amd_sfh_clear_intr(data);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
int rc;
|
||||
|
||||
pci_intx(privdata->pdev, true);
|
||||
|
||||
rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq,
|
||||
amd_sfh_irq_handler, 0, DRIVER_NAME, privdata);
|
||||
if (rc) {
|
||||
dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n",
|
||||
privdata->pdev->irq, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
|
||||
{
|
||||
union sfh_cmd_param cmd_param;
|
||||
@ -193,6 +234,8 @@ static void amd_mp2_pci_remove(void *privdata)
|
||||
struct amd_mp2_dev *mp2 = privdata;
|
||||
amd_sfh_hid_client_deinit(privdata);
|
||||
mp2->mp2_ops->stop_all(mp2);
|
||||
pci_intx(mp2->pdev, false);
|
||||
amd_sfh_clear_intr(mp2);
|
||||
}
|
||||
|
||||
static const struct amd_mp2_ops amd_sfh_ops_v2 = {
|
||||
@ -200,6 +243,8 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
|
||||
.stop = amd_stop_sensor_v2,
|
||||
.stop_all = amd_stop_all_sensor_v2,
|
||||
.response = amd_sfh_wait_response_v2,
|
||||
.clear_intr = amd_sfh_clear_intr_v2,
|
||||
.init_intr = amd_sfh_irq_init_v2,
|
||||
};
|
||||
|
||||
static const struct amd_mp2_ops amd_sfh_ops = {
|
||||
@ -225,6 +270,14 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata)
|
||||
}
|
||||
}
|
||||
|
||||
static int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (privdata->mp2_ops->init_intr)
|
||||
return privdata->mp2_ops->init_intr(privdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct amd_mp2_dev *privdata;
|
||||
@ -261,9 +314,20 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
||||
|
||||
mp2_select_ops(privdata);
|
||||
|
||||
rc = amd_sfh_hid_client_init(privdata);
|
||||
if (rc)
|
||||
rc = amd_sfh_irq_init(privdata);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "amd_sfh_irq_init failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = amd_sfh_hid_client_init(privdata);
|
||||
if (rc) {
|
||||
amd_sfh_clear_intr(privdata);
|
||||
dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
amd_sfh_clear_intr(privdata);
|
||||
|
||||
return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
|
||||
}
|
||||
@ -290,6 +354,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
||||
amd_sfh_clear_intr(mp2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -312,6 +379,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&cl_data->work_buffer);
|
||||
amd_sfh_clear_intr(mp2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ union sfh_cmd_base {
|
||||
} s;
|
||||
struct {
|
||||
u32 cmd_id : 4;
|
||||
u32 intr_enable : 1;
|
||||
u32 intr_disable : 1;
|
||||
u32 rsvd1 : 3;
|
||||
u32 length : 7;
|
||||
u32 mem_type : 1;
|
||||
@ -141,5 +141,7 @@ struct amd_mp2_ops {
|
||||
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
|
||||
void (*stop_all)(struct amd_mp2_dev *privdata);
|
||||
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
|
||||
void (*clear_intr)(struct amd_mp2_dev *privdata);
|
||||
int (*init_intr)(struct amd_mp2_dev *privdata);
|
||||
};
|
||||
#endif
|
||||
|
@ -27,6 +27,7 @@
|
||||
#define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02
|
||||
#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05
|
||||
#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04
|
||||
#define ILLUMINANCE_MASK GENMASK(14, 0)
|
||||
|
||||
int get_report_descriptor(int sensor_idx, u8 *rep_desc)
|
||||
{
|
||||
@ -246,7 +247,8 @@ u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_
|
||||
get_common_inputs(&als_input.common_property, report_id);
|
||||
/* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */
|
||||
if (supported_input == V2_STATUS)
|
||||
als_input.illuminance_value = (int)readl(privdata->mmio + AMD_C2P_MSG(5));
|
||||
als_input.illuminance_value =
|
||||
readl(privdata->mmio + AMD_C2P_MSG(5)) & ILLUMINANCE_MASK;
|
||||
else
|
||||
als_input.illuminance_value =
|
||||
(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
||||
|
@ -691,49 +691,49 @@ static const struct hid_device_id apple_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
|
||||
|
@ -262,6 +262,7 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
|
||||
return 0;
|
||||
err_free:
|
||||
usb_put_dev(udev);
|
||||
kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1370,6 +1370,7 @@
|
||||
#define USB_VENDOR_ID_UGTIZER 0x2179
|
||||
#define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053
|
||||
#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077
|
||||
#define USB_DEVICE_ID_UGTIZER_TABLET_WP5540 0x0004
|
||||
|
||||
#define USB_VENDOR_ID_VIEWSONIC 0x0543
|
||||
#define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621
|
||||
|
@ -187,6 +187,7 @@ static const struct hid_device_id hid_quirks[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_WP5540), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
|
||||
|
@ -27,7 +27,6 @@ struct i2c_hid_of_goodix {
|
||||
|
||||
struct regulator *vdd;
|
||||
struct notifier_block nb;
|
||||
struct mutex regulator_mutex;
|
||||
struct gpio_desc *reset_gpio;
|
||||
const struct goodix_i2c_hid_timing_data *timings;
|
||||
};
|
||||
@ -67,8 +66,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb,
|
||||
container_of(nb, struct i2c_hid_of_goodix, nb);
|
||||
int ret = NOTIFY_OK;
|
||||
|
||||
mutex_lock(&ihid_goodix->regulator_mutex);
|
||||
|
||||
switch (event) {
|
||||
case REGULATOR_EVENT_PRE_DISABLE:
|
||||
gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
|
||||
@ -87,8 +84,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb,
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ihid_goodix->regulator_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -102,8 +97,6 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client,
|
||||
if (!ihid_goodix)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&ihid_goodix->regulator_mutex);
|
||||
|
||||
ihid_goodix->ops.power_up = goodix_i2c_hid_power_up;
|
||||
ihid_goodix->ops.power_down = goodix_i2c_hid_power_down;
|
||||
|
||||
@ -130,25 +123,28 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client,
|
||||
* long. Holding the controller in reset apparently draws extra
|
||||
* power.
|
||||
*/
|
||||
mutex_lock(&ihid_goodix->regulator_mutex);
|
||||
ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify;
|
||||
ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb);
|
||||
if (ret) {
|
||||
mutex_unlock(&ihid_goodix->regulator_mutex);
|
||||
if (ret)
|
||||
return dev_err_probe(&client->dev, ret,
|
||||
"regulator notifier request failed\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* If someone else is holding the regulator on (or the regulator is
|
||||
* an always-on one) we might never be told to deassert reset. Do it
|
||||
* now. Here we'll assume that someone else might have _just
|
||||
* barely_ turned the regulator on so we'll do the full
|
||||
* "post_power_delay" just in case.
|
||||
* now... and temporarily bump the regulator reference count just to
|
||||
* make sure it is impossible for this to race with our own notifier!
|
||||
* We also assume that someone else might have _just barely_ turned
|
||||
* the regulator on so we'll do the full "post_power_delay" just in
|
||||
* case.
|
||||
*/
|
||||
if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd))
|
||||
if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) {
|
||||
ret = regulator_enable(ihid_goodix->vdd);
|
||||
if (ret)
|
||||
return ret;
|
||||
goodix_i2c_hid_deassert_reset(ihid_goodix, true);
|
||||
mutex_unlock(&ihid_goodix->regulator_mutex);
|
||||
regulator_disable(ihid_goodix->vdd);
|
||||
}
|
||||
|
||||
return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user