Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22e4dda0 authored by Allan, Bruce W's avatar Allan, Bruce W Committed by Herbert Xu
Browse files

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).

Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 8a45ac12
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -148,6 +148,11 @@ struct adf_hw_device_data {
	int (*alloc_irq)(struct adf_accel_dev *accel_dev);
	int (*alloc_irq)(struct adf_accel_dev *accel_dev);
	void (*free_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);
	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;
	const char *fw_name;
	uint32_t pci_dev_id;
	uint32_t pci_dev_id;
	uint32_t fuses;
	uint32_t fuses;
+4 −3
Original line number Original line Diff line number Diff line
@@ -125,8 +125,9 @@ static void adf_device_reset_worker(struct work_struct *work)


	adf_dev_restarting_notify(accel_dev);
	adf_dev_restarting_notify(accel_dev);
	adf_dev_stop(accel_dev);
	adf_dev_stop(accel_dev);
	adf_dev_shutdown(accel_dev);
	adf_dev_restore(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 */
		/* The device hanged and we can't restart it so stop here */
		dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
		dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
		kfree(reset_data);
		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;
	struct adf_reset_dev_data *reset_data;


	if (adf_dev_started(accel_dev) &&
	if (!adf_dev_started(accel_dev) ||
	    !test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
	    test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
		return 0;
		return 0;


	set_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
	set_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+2 −0
Original line number Original line Diff line number Diff line
@@ -50,6 +50,7 @@
#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include "adf_accel_devices.h"
#include "adf_accel_devices.h"
#include "adf_cfg.h"
#include "adf_cfg.h"
#include "adf_common_drv.h"


static DEFINE_MUTEX(qat_cfg_read_lock);
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);
	down_write(&dev_cfg_data->lock);
	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
	adf_cfg_section_del_all(&dev_cfg_data->sec_list);
	up_write(&dev_cfg_data->lock);
	up_write(&dev_cfg_data->lock);
	clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
}
}


/**
/**
+1 −1
Original line number Original line Diff line number Diff line
@@ -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_init(struct adf_accel_dev *accel_dev);
int adf_dev_start(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_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);
int adf_ctl_dev_register(void);
void adf_ctl_dev_unregister(void);
void adf_ctl_dev_unregister(void);
+6 −1
Original line number Original line Diff line number Diff line
@@ -282,6 +282,8 @@ static int adf_ctl_stop_devices(uint32_t id)
			if (adf_dev_stop(accel_dev)) {
			if (adf_dev_stop(accel_dev)) {
				pr_err("QAT: Failed to stop qat_dev%d\n", id);
				pr_err("QAT: Failed to stop qat_dev%d\n", id);
				ret = -EFAULT;
				ret = -EFAULT;
			} else {
				adf_dev_shutdown(accel_dev);
			}
			}
		}
		}
	}
	}
@@ -343,6 +345,8 @@ static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
	if (!adf_dev_started(accel_dev)) {
	if (!adf_dev_started(accel_dev)) {
		pr_info("QAT: Starting acceleration device qat_dev%d.\n",
		pr_info("QAT: Starting acceleration device qat_dev%d.\n",
			ctl_data->device_id);
			ctl_data->device_id);
		ret = adf_dev_init(accel_dev);
		if (!ret)
			ret = adf_dev_start(accel_dev);
			ret = adf_dev_start(accel_dev);
	} else {
	} else {
		pr_info("QAT: Acceleration device qat_dev%d already started.\n",
		pr_info("QAT: Acceleration device qat_dev%d already started.\n",
@@ -351,6 +355,7 @@ static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
	if (ret) {
	if (ret) {
		pr_err("QAT: Failed to start qat_dev%d\n", ctl_data->device_id);
		pr_err("QAT: Failed to start qat_dev%d\n", ctl_data->device_id);
		adf_dev_stop(accel_dev);
		adf_dev_stop(accel_dev);
		adf_dev_shutdown(accel_dev);
	}
	}
out:
out:
	kfree(ctl_data);
	kfree(ctl_data);
Loading