crypto: qat - Use alternative reset methods depending on the specific device
authorConor McLoughlin <conor.mcloughlin@intel.com>
Mon, 4 Jul 2016 15:26:00 +0000 (16:26 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Tue, 5 Jul 2016 15:05:25 +0000 (23:05 +0800)
Different product families will use FLR or SBR.
Virtual Function devices have no reset method.

Signed-off-by: Conor McLoughlin <conor.mcloughlin@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.c
drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.c
drivers/crypto/qat/qat_common/adf_accel_devices.h
drivers/crypto/qat/qat_common/adf_aer.c
drivers/crypto/qat/qat_common/adf_common_drv.h
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c

index c5bd5a9abc4d23e5cce0f7ddaedff8c95f2e98d8..6bc68bc00d76c8e0a6e6f6e2a4819ce0aa88dd61 100644 (file)
@@ -229,6 +229,7 @@ void adf_init_hw_data_c3xxx(struct adf_hw_device_data *hw_data)
        hw_data->get_arb_mapping = adf_get_arbiter_mapping;
        hw_data->enable_ints = adf_enable_ints;
        hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms;
+       hw_data->reset_device = adf_reset_flr;
        hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION;
 }
 
index 879e04cae714c3e291791e0600e83bff595f8e32..618cec360b39cc31f905f65985e4bece104b094f 100644 (file)
@@ -239,6 +239,7 @@ void adf_init_hw_data_c62x(struct adf_hw_device_data *hw_data)
        hw_data->get_arb_mapping = adf_get_arbiter_mapping;
        hw_data->enable_ints = adf_enable_ints;
        hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms;
+       hw_data->reset_device = adf_reset_flr;
        hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION;
 }
 
index 5a07208ce778209ef7397c7f628cc7fbbede4791..e8822536530b99666f2f5137c25b36f7b451fe06 100644 (file)
@@ -176,6 +176,7 @@ struct adf_hw_device_data {
        void (*disable_iov)(struct adf_accel_dev *accel_dev);
        void (*enable_ints)(struct adf_accel_dev *accel_dev);
        int (*enable_vf2pf_comms)(struct adf_accel_dev *accel_dev);
+       void (*reset_device)(struct adf_accel_dev *accel_dev);
        const char *fw_name;
        const char *fw_mmp_name;
        uint32_t fuses;
index 7bfb57f1bcb52cac01a19f21b518bc9cc2ae9d62..2839fccdd84beefccb4736759c1ca994369773d6 100644 (file)
@@ -82,18 +82,12 @@ struct adf_reset_dev_data {
        struct work_struct reset_work;
 };
 
-void adf_dev_restore(struct adf_accel_dev *accel_dev)
+void adf_reset_sbr(struct adf_accel_dev *accel_dev)
 {
        struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
        struct pci_dev *parent = pdev->bus->self;
        uint16_t bridge_ctl = 0;
 
-       if (accel_dev->is_vf)
-               return;
-
-       dev_info(&GET_DEV(accel_dev), "Resetting device qat_dev%d\n",
-                accel_dev->accel_id);
-
        if (!parent)
                parent = pdev;
 
@@ -101,6 +95,8 @@ void adf_dev_restore(struct adf_accel_dev *accel_dev)
                dev_info(&GET_DEV(accel_dev),
                         "Transaction still in progress. Proceeding\n");
 
+       dev_info(&GET_DEV(accel_dev), "Secondary bus reset\n");
+
        pci_read_config_word(parent, PCI_BRIDGE_CONTROL, &bridge_ctl);
        bridge_ctl |= PCI_BRIDGE_CTL_BUS_RESET;
        pci_write_config_word(parent, PCI_BRIDGE_CONTROL, bridge_ctl);
@@ -108,8 +104,40 @@ void adf_dev_restore(struct adf_accel_dev *accel_dev)
        bridge_ctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
        pci_write_config_word(parent, PCI_BRIDGE_CONTROL, bridge_ctl);
        msleep(100);
-       pci_restore_state(pdev);
-       pci_save_state(pdev);
+}
+EXPORT_SYMBOL_GPL(adf_reset_sbr);
+
+void adf_reset_flr(struct adf_accel_dev *accel_dev)
+{
+       struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+       u16 control = 0;
+       int pos = 0;
+
+       dev_info(&GET_DEV(accel_dev), "Function level reset\n");
+       pos = pci_pcie_cap(pdev);
+       if (!pos) {
+               dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
+               return;
+       }
+       pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &control);
+       control |= PCI_EXP_DEVCTL_BCR_FLR;
+       pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, control);
+       msleep(100);
+}
+EXPORT_SYMBOL_GPL(adf_reset_flr);
+
+void adf_dev_restore(struct adf_accel_dev *accel_dev)
+{
+       struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+       struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+
+       if (hw_device->reset_device) {
+               dev_info(&GET_DEV(accel_dev), "Resetting device qat_dev%d\n",
+                        accel_dev->accel_id);
+               hw_device->reset_device(accel_dev);
+               pci_restore_state(pdev);
+               pci_save_state(pdev);
+       }
 }
 
 static void adf_device_reset_worker(struct work_struct *work)
index 75faa39bc8d04f14b915fe956246008bcf110c4a..980e07475012043ece2c2447307a5818cb53b2c0 100644 (file)
@@ -141,6 +141,8 @@ int adf_ae_stop(struct adf_accel_dev *accel_dev);
 
 int adf_enable_aer(struct adf_accel_dev *accel_dev, struct pci_driver *adf);
 void adf_disable_aer(struct adf_accel_dev *accel_dev);
+void adf_reset_sbr(struct adf_accel_dev *accel_dev);
+void adf_reset_flr(struct adf_accel_dev *accel_dev);
 void adf_dev_restore(struct adf_accel_dev *accel_dev);
 int adf_init_aer(void);
 void adf_exit_aer(void);
index 6e1d5e1855262e50631b2896420ad16cccbc8ca3..1dfcab317bedee7aef63597091b7d191d089306b 100644 (file)
@@ -252,6 +252,7 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
        hw_data->get_arb_mapping = adf_get_arbiter_mapping;
        hw_data->enable_ints = adf_enable_ints;
        hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms;
+       hw_data->reset_device = adf_reset_sbr;
        hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION;
 }