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

Commit ed8a72d1 authored by Jeff Skirvin's avatar Jeff Skirvin Committed by Dan Williams
Browse files

isci: Qualify when the host lock is managed for STP/SATA callbacks.



In the case of internal discovery related STP/SATA I/O started
through sas_execute_task the host lock is not taken by libsas before
calling lldd_execute_task, so the lock should not be managed before
calling back to libsas through task->task_done or sas_task_abort.

Signed-off-by: default avatarJeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 26e953bc
Loading
Loading
Loading
Loading
+4 −16
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <scsi/sas_ata.h>
#include "isci.h"
#include "scic_remote_device.h"
#include "scic_io_request.h"
@@ -452,22 +451,11 @@ int isci_request_execute(
			task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
			spin_unlock_irqrestore(&task->task_state_lock, flags);

			/* Cause this task to be scheduled in the SCSI error handler
			* thread.
			/* Cause this task to be scheduled in the SCSI error
			* handler thread.
			*/
			if (dev_is_sata(task->dev)) {
				/* Since we are still in the submit path, and since
				* libsas takes the host lock on behalf of SATA
				* devices before I/O starts, we need to unlock
				* before we can put the task in the error path.
				*/
				raw_local_irq_save(flags);
				spin_unlock(isci_host->shost->host_lock);
				sas_task_abort(task);
				spin_lock(isci_host->shost->host_lock);
				raw_local_irq_restore(flags);
			} else
				sas_task_abort(task);
			isci_execpath_callback(isci_host, task,
					       sas_task_abort);

			/* Change the status, since we are holding
			* the I/O until it is managed by the SCSI
+0 −1
Original line number Diff line number Diff line
@@ -299,7 +299,6 @@ int isci_task_send_lu_reset_sata(
{
	struct isci_tmf tmf;
	int ret = TMF_RESP_FUNC_FAILED;
	unsigned long flags;

	/* Send the soft reset to the target */
	#define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */
+9 −20
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@

#include <linux/completion.h>
#include <linux/irqflags.h>
#include <scsi/sas_ata.h>
#include "scic_task_request.h"
#include "scic_remote_device.h"
#include "scic_io_request.h"
@@ -93,26 +92,13 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task,
		case isci_perform_normal_io_completion:
			/* Normal notification (task_done) */
			dev_dbg(&ihost->pdev->dev,
				"%s: Normal - task = %p, response=%d, status=%d\n",
				"%s: Normal - task = %p, response=%d, "
				"status=%d\n",
				__func__, task, response, status);

			task->lldd_task = NULL;
			if (dev_is_sata(task->dev)) {
				/* Since we are still in the submit path, and since
				* libsas takes the host lock on behalf of SATA
				* devices before I/O starts, we need to unlock
				* before we can call back and report the I/O
				* submission error.
				*/
				unsigned long flags;

				raw_local_irq_save(flags);
				spin_unlock(ihost->shost->host_lock);
				task->task_done(task);
				spin_lock(ihost->shost->host_lock);
				raw_local_irq_restore(flags);
			} else
				task->task_done(task);
			isci_execpath_callback(ihost, task, task->task_done);
			break;

		case isci_perform_aborted_io_completion:
@@ -120,16 +106,19 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task,
			* abort path.
			*/
			dev_warn(&ihost->pdev->dev,
				 "%s: Aborted - task = %p, response=%d, status=%d\n",
				 "%s: Aborted - task = %p, response=%d, "
				"status=%d\n",
				 __func__, task, response, status);
			break;

		case isci_perform_error_io_completion:
			/* Use sas_task_abort */
			dev_warn(&ihost->pdev->dev,
				 "%s: Error - task = %p, response=%d, status=%d\n",
				 "%s: Error - task = %p, response=%d, "
				"status=%d\n",
				 __func__, task, response, status);
			sas_task_abort(task);

			isci_execpath_callback(ihost, task, sas_task_abort);
			break;

		default:
+37 −0
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@
#if !defined(_ISCI_TASK_H_)
#define _ISCI_TASK_H_

#include <scsi/sas_ata.h>

struct isci_request;
struct isci_host;

@@ -332,5 +334,40 @@ isci_task_set_completion_status(
	return task_notification_selection;

}
/**
* isci_execpath_callback() - This function is called from the task
* execute path when the task needs to callback libsas about the submit-time
* task failure.  The callback occurs either through the task's done function
* or through sas_task_abort.  In the case of regular non-discovery SATA/STP I/O
* requests, libsas takes the host lock before calling execute task.  Therefore
* in this situation the host lock must be managed before calling the func.
*
* @ihost: This parameter is the controller to which the I/O request was sent.
* @task: This parameter is the I/O request.
* @func: This parameter is the function to call in the correct context.
* @status: This parameter is the status code for the completed task.
*
*/
static inline void isci_execpath_callback(
	struct isci_host *ihost,
	struct sas_task  *task,
	void (*func)(struct sas_task *))
{
	unsigned long flags;

	if (dev_is_sata(task->dev) && task->uldd_task) {
		/* Since we are still in the submit path, and since
		* libsas takes the host lock on behalf of SATA
		* devices before I/O starts (in the non-discovery case),
		* we need to unlock before we can call the callback function.
		*/
		raw_local_irq_save(flags);
		spin_unlock(ihost->shost->host_lock);
		func(task);
		spin_lock(ihost->shost->host_lock);
		raw_local_irq_restore(flags);
	} else
		func(task);
}

#endif /* !defined(_SCI_TASK_H_) */