crypto: qat - fix device reset flow
PATCH 1/1 crypto: qat - fix device reset flow
When the device needs a reset, e.g. when an uncorrectable PCIe AER event occurs, various services/data structures need to be cleaned up, the hardware reset and the services/data structures initialized and started. The code to perform the cleanup and initialization was not performed when a device reset was done.
This patch moves some of the initialization code out of the .probe entry- point into a separate function that is now called during probe as well as after the hardware has been reset. Similarly, a new function is added for first cleaning up these services/data structures prior to resetting. The new functions are adf_dev_init() and adf_dev_shutdown(), respectively, for which there are already prototypes but no actual functions just yet and are now called when the device is reset and during probe/cleanup of the driver. The down and up flows via ioctl calls has similarly been updated.
In addition, there are two other bugs in the reset flow - one in the logic for determining whether to schedule a device reset upon receiving an uncorrectable AER event which prevents the reset flow from being initiated, and another with clearing the status bit indicating a device is configured (when resetting the device the configuration remains across the reset so the bit should not be cleared, otherwise, the necessary services will not be re-started in adf_dev_start() after the reset - clear the bit only when actually deleting the configuration).
---
drivers/crypto/qat/qat_common/adf_accel_devices.h | 5 + drivers/crypto/qat/qat_common/adf_aer.c | 7 +- drivers/crypto/qat/qat_common/adf_cfg.c | 2 drivers/crypto/qat/qat_common/adf_common_drv.h | 2 drivers/crypto/qat/qat_common/adf_ctl_drv.c | 7 +- drivers/crypto/qat/qat_common/adf_init.c | 91 ++++++++++++++++++-- .../crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 19 ++++ drivers/crypto/qat/qat_dh895xcc/adf_drv.c | 42 ++------- 8 files changed, 128 insertions(+), 47 deletions(-)
drivers/crypto/qat/qat_common/adf_accel_devices.h +5 -0
@@ -148,6 +148,11 @@ struct adf_hw_device_data {int (*alloc_irq)(struct adf_accel_dev *accel_dev);void (*free_irq)(struct adf_accel_dev *accel_dev);void (*enable_error_correction)(struct adf_accel_dev *accel_dev); +int (*init_admin_comms)(struct adf_accel_dev *accel_dev); +void (*exit_admin_comms)(struct adf_accel_dev *accel_dev); +int (*init_arb)(struct adf_accel_dev *accel_dev); +void (*exit_arb)(struct adf_accel_dev *accel_dev); +void (*enable_ints)(struct adf_accel_dev *accel_dev);const char *fw_name;uint32_t pci_dev_id;uint32_t fuses;
drivers/crypto/qat/qat_common/adf_aer.c +4 -3
@@ -125,8 +125,9 @@ static void adf_device_reset_worker(struct work_struct *work)adf_dev_restarting_notify (accel_dev);adf_dev_stop (accel_dev); +adf_dev_shutdown (accel_dev);adf_dev_restore (accel_dev); -if (adf_dev_start (accel_dev)) { +if (adf_dev_init (accel_dev) ||adf_dev_start (accel_dev)) {/* The device hanged and we can't restart it so stop here */ dev_err (&GET_DEV (accel_dev),"Restart device failed\n" );kfree (reset_data);
@@ -148,8 +149,8 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev, {struct adf_reset_dev_data *reset_data; -if (adf_dev_started (accel_dev) && - !test_bit (ADF_STATUS_RESTARTING , &accel_dev->status)) +if (!adf_dev_started (accel_dev) || +test_bit (ADF_STATUS_RESTARTING , &accel_dev->status))return 0 ;set_bit (ADF_STATUS_RESTARTING , &accel_dev->status);
drivers/crypto/qat/qat_common/adf_cfg.c +2 -0
@@ -50,6 +50,7 @@#include <linux/seq_file.h> #include "adf_accel_devices.h" #include "adf_cfg.h" +#include "adf_common_drv.h" static DEFINE_MUTEX (qat_cfg_read_lock);
@@ -159,6 +160,7 @@ void adf_cfg_del_all(struct adf_accel_dev *accel_dev)down_write (&dev_cfg_data->lock);adf_cfg_section_del_all (&dev_cfg_data->sec_list);up_write (&dev_cfg_data->lock); +clear_bit (ADF_STATUS_CONFIGURED , &accel_dev->status); }/**
drivers/crypto/qat/qat_common/adf_common_drv.h +1 -1
@@ -93,7 +93,7 @@ int adf_service_unregister(struct service_hndl *service);int adf_dev_init (struct adf_accel_dev *accel_dev);int adf_dev_start (struct adf_accel_dev *accel_dev);int adf_dev_stop (struct adf_accel_dev *accel_dev); -int adf_dev_shutdown (struct adf_accel_dev *accel_dev); +void adf_dev_shutdown (struct adf_accel_dev *accel_dev);int adf_ctl_dev_register (void );void adf_ctl_dev_unregister (void );
drivers/crypto/qat/qat_common/adf_ctl_drv.c +6 -1
@@ -282,6 +282,8 @@ static int adf_ctl_stop_devices(uint32_t id)if (adf_dev_stop (accel_dev)) {pr_err ("QAT: Failed to stop qat_dev%d\n" , id); ret = -EFAULT ; + }else { +adf_dev_shutdown (accel_dev); } } }
@@ -343,7 +345,9 @@ static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,if (!adf_dev_started (accel_dev)) {pr_info ("QAT: Starting acceleration device qat_dev%d.\n" , ctl_data->device_id); - ret =adf_dev_start (accel_dev); + ret =adf_dev_init (accel_dev); +if (!ret) + ret =adf_dev_start (accel_dev); }else {pr_info ("QAT: Acceleration device qat_dev%d already started.\n" , ctl_data->device_id);
@@ -351,6 +355,7 @@ static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,if (ret) {pr_err ("QAT: Failed to start qat_dev%d\n" , ctl_data->device_id);adf_dev_stop (accel_dev); +adf_dev_shutdown (accel_dev); } out:kfree (ctl_data);
drivers/crypto/qat/qat_common/adf_init.c +80 -11
141 lines not on this page · raw message
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c +19 -0
@@ -46,6 +46,7 @@*/ #include <adf_accel_devices.h> #include "adf_dh895xcc_hw_data.h" +#include "adf_common_drv.h" #include "adf_drv.h" /* Worker thread to service arbiter mappings based on dev SKUs */
@@ -182,6 +183,19 @@ static void adf_enable_error_correction(struct adf_accel_dev *accel_dev) } } +static void adf_enable_ints (struct adf_accel_dev *accel_dev) +{ +void __iomem *addr; + + addr = (&GET_BARS (accel_dev)[ADF_DH895XCC_PMISC_BAR ])->virt_addr; + +/* Enable bundle and misc interrupts */ +ADF_CSR_WR (addr,ADF_DH895XCC_SMIAPF0_MASK_OFFSET , +ADF_DH895XCC_SMIA0_MASK ); +ADF_CSR_WR (addr,ADF_DH895XCC_SMIAPF1_MASK_OFFSET , +ADF_DH895XCC_SMIA1_MASK ); +} +void adf_init_hw_data_dh895xcc (struct adf_hw_device_data *hw_data) { hw_data->dev_class = &dh895xcc_class;
@@ -206,6 +220,11 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data) hw_data->get_misc_bar_id = get_misc_bar_id; hw_data->get_sku = get_sku; hw_data->fw_name =ADF_DH895XCC_FW ; + hw_data->init_admin_comms = adf_init_admin_comms; + hw_data->exit_admin_comms = adf_exit_admin_comms; + hw_data->init_arb = adf_init_arb; + hw_data->exit_arb = adf_exit_arb; + hw_data->enable_ints = adf_enable_ints; }void adf_clean_hw_data_dh895xcc (struct adf_hw_device_data *hw_data)
drivers/crypto/qat/qat_dh895xcc/adf_drv.c +11 -31
85 lines not on this page · raw message
Herbert Xu
maintainerQuoted 5 lines · Bruce W
When the device needs a reset, e.g. when an uncorrectable PCIe AER event occurs, various services/data structures need to be cleaned up, the hardware reset and the services/data structures initialized and started. The code to perform the cleanup and initialization was not performed when a device reset was done.
All five qat patches applied. Thanks!
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt