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

Commit f456393e authored by Darrick J. Wong's avatar Darrick J. Wong Committed by James Bottomley
Browse files

[SCSI] libsas: modify error handler to use scsi_eh_* functions



This patch adds an EH done queue to sas_ha, converts the error handling
strategy function and the sas_scsi_task_done functions in libsas to use
the scsi_eh_* commands for error'd commands, and adds checks for the
INITIATOR_ABORTED flag so that we do the right thing if a sas_task has
been aborted by the initiator.

Signed-off-by: default avatarDarrick J. Wong <djwong@us.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent b4d38e38
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -112,6 +112,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
		}
		}
	}
	}


	INIT_LIST_HEAD(&sas_ha->eh_done_q);

	return 0;
	return 0;


Undo_ports:
Undo_ports:
+25 −4
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
#include <scsi/scsi_transport_sas.h>
#include "../scsi_sas_internal.h"
#include "../scsi_sas_internal.h"
@@ -46,6 +47,7 @@ static void sas_scsi_task_done(struct sas_task *task)
{
{
	struct task_status_struct *ts = &task->task_status;
	struct task_status_struct *ts = &task->task_status;
	struct scsi_cmnd *sc = task->uldd_task;
	struct scsi_cmnd *sc = task->uldd_task;
	struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host);
	unsigned ts_flags = task->task_state_flags;
	unsigned ts_flags = task->task_state_flags;
	int hs = 0, stat = 0;
	int hs = 0, stat = 0;


@@ -116,7 +118,7 @@ static void sas_scsi_task_done(struct sas_task *task)
	sas_free_task(task);
	sas_free_task(task);
	/* This is very ugly but this is how SCSI Core works. */
	/* This is very ugly but this is how SCSI Core works. */
	if (ts_flags & SAS_TASK_STATE_ABORTED)
	if (ts_flags & SAS_TASK_STATE_ABORTED)
		scsi_finish_command(sc);
		scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q);
	else
	else
		sc->scsi_done(sc);
		sc->scsi_done(sc);
}
}
@@ -307,6 +309,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
		spin_unlock_irqrestore(&core->task_queue_lock, flags);
		spin_unlock_irqrestore(&core->task_queue_lock, flags);
	}
	}


	spin_lock_irqsave(&task->task_state_lock, flags);
	if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
		spin_unlock_irqrestore(&task->task_state_lock, flags);
		SAS_DPRINTK("%s: task 0x%p already aborted\n",
			    __FUNCTION__, task);
		return TASK_IS_ABORTED;
	}
	spin_unlock_irqrestore(&task->task_state_lock, flags);

	for (i = 0; i < 5; i++) {
	for (i = 0; i < 5; i++) {
		SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
		SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
		res = si->dft->lldd_abort_task(task);
		res = si->dft->lldd_abort_task(task);
@@ -409,13 +420,16 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
	SAS_DPRINTK("going over list...\n");
	SAS_DPRINTK("going over list...\n");
	list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
	list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
		struct sas_task *task = TO_SAS_TASK(cmd);
		struct sas_task *task = TO_SAS_TASK(cmd);
		list_del_init(&cmd->eh_entry);


		if (!task) {
			SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
			continue;
		}
		SAS_DPRINTK("trying to find task 0x%p\n", task);
		SAS_DPRINTK("trying to find task 0x%p\n", task);
		list_del_init(&cmd->eh_entry);
		res = sas_scsi_find_task(task);
		res = sas_scsi_find_task(task);


		cmd->eh_eflags = 0;
		cmd->eh_eflags = 0;
		shost->host_failed--;


		switch (res) {
		switch (res) {
		case TASK_IS_DONE:
		case TASK_IS_DONE:
@@ -491,6 +505,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
		}
		}
	}
	}
out:
out:
	scsi_eh_flush_done_q(&ha->eh_done_q);
	SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
	SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
	return;
	return;
clear_q:
clear_q:
@@ -508,12 +523,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
	unsigned long flags;
	unsigned long flags;


	if (!task) {
	if (!task) {
		SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
		SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n",
			    cmd, task);
			    cmd, task);
		return EH_HANDLED;
		return EH_HANDLED;
	}
	}


	spin_lock_irqsave(&task->task_state_lock, flags);
	spin_lock_irqsave(&task->task_state_lock, flags);
	if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
		spin_unlock_irqrestore(&task->task_state_lock, flags);
		SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: "
			    "EH_NOT_HANDLED\n", cmd, task);
		return EH_NOT_HANDLED;
	}
	if (task->task_state_flags & SAS_TASK_STATE_DONE) {
	if (task->task_state_flags & SAS_TASK_STATE_DONE) {
		spin_unlock_irqrestore(&task->task_state_lock, flags);
		spin_unlock_irqrestore(&task->task_state_lock, flags);
		SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
		SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
+6 −3
Original line number Original line Diff line number Diff line
@@ -338,6 +338,8 @@ struct sas_ha_struct {
	void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event);
	void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event);


	void *lldd_ha;		  /* not touched by sas class code */
	void *lldd_ha;		  /* not touched by sas class code */

	struct list_head eh_done_q;
};
};


#define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata)
#define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata)
@@ -533,6 +535,7 @@ struct sas_task {
#define SAS_TASK_STATE_PENDING      1
#define SAS_TASK_STATE_PENDING      1
#define SAS_TASK_STATE_DONE         2
#define SAS_TASK_STATE_DONE         2
#define SAS_TASK_STATE_ABORTED      4
#define SAS_TASK_STATE_ABORTED      4
#define SAS_TASK_INITIATOR_ABORTED  8


static inline struct sas_task *sas_alloc_task(gfp_t flags)
static inline struct sas_task *sas_alloc_task(gfp_t flags)
{
{