]> git.dujemihanovic.xyz Git - linux.git/commitdiff
HID: amd_sfh: Add interrupt handler to process interrupts
authorBasavaraj Natikar <Basavaraj.Natikar@amd.com>
Tue, 8 Feb 2022 12:21:12 +0000 (17:51 +0530)
committerJiri Kosina <jkosina@suse.cz>
Mon, 14 Feb 2022 15:28:51 +0000 (16:28 +0100)
On newer AMD platforms with SFH, it is observed that random interrupts
get generated on the SFH hardware and until this is cleared the firmware
sensor processing is stalled, resulting in no data been received to
driver side.

Add routines to handle these interrupts, so that firmware operations are
not stalled.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h

index 7236b223fb68eab6789ac546d427426dbd2de0cb..19fa734a9a793a7e86c1913b67a50a93be671f53 100644 (file)
@@ -106,6 +106,30 @@ static void amd_sfh_clear_intr(struct amd_mp2_dev *privdata)
                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;
@@ -210,6 +234,7 @@ 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);
 }
 
@@ -219,6 +244,7 @@ static const struct amd_mp2_ops amd_sfh_ops_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 = {
@@ -244,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;
@@ -280,6 +314,12 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
 
        mp2_select_ops(privdata);
 
+       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);
index 61de09ba51242eec7b798a5a7aebed0b2444477c..97b99861fae251a542cb8a13dddd1a86c6de7fc2 100644 (file)
@@ -142,5 +142,6 @@ struct amd_mp2_ops {
         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