public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] 3/3: Handle REQ_TASK_ABORT in aic94xx
@ 2006-10-30 23:18 Darrick J. Wong
  2006-10-31  7:53 ` Luben Tuikov
  0 siblings, 1 reply; 2+ messages in thread
From: Darrick J. Wong @ 2006-10-30 23:18 UTC (permalink / raw)
  To: linux-scsi, Linux Kernel Mailing List; +Cc: Alexis Bruemmer

This patch straightens out the code that distinguishes the various escb
opcodes in escb_tasklet_complete so that they can be handled correctly. 
It also provides all the necessary code to create a workqueue item that
tells libsas to abort a sas_task.

Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>

--

diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 7ee49b5..1911c5d 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -25,6 +25,7 @@
  */
 
 #include <linux/pci.h>
+#include <scsi/scsi_host.h>
 
 #include "aic94xx.h"
 #include "aic94xx_reg.h"
@@ -342,6 +343,18 @@ void asd_invalidate_edb(struct asd_ascb 
 	}
 }
 
+/* start up the ABORT TASK tmf... */
+static void task_kill_later(struct asd_ascb *ascb)
+{
+	struct asd_ha_struct *asd_ha = ascb->ha;
+	struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
+	struct Scsi_Host *shost = sas_ha->core.shost;
+	struct sas_task *task = ascb->uldd_task;
+
+	INIT_WORK(&task->abort_work, (void (*)(void *))sas_task_abort, task);
+	queue_work(shost->work_q, &task->abort_work);
+}
+
 static void escb_tasklet_complete(struct asd_ascb *ascb,
 				  struct done_list_struct *dl)
 {
@@ -368,6 +381,58 @@ static void escb_tasklet_complete(struct
 			    ascb->scb->header.opcode);
 	}
 
+	/* Catch these before we mask off the sb_opcode bits */
+	switch (sb_opcode) {
+	case REQ_TASK_ABORT: {
+		struct asd_ascb *a, *b;
+		u16 tc_abort;
+
+		tc_abort = *((u16*)(&dl->status_block[1]));
+		tc_abort = le16_to_cpu(tc_abort);
+
+		ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
+			    __FUNCTION__, dl->status_block[3]);
+
+		/* Find the pending task and abort it. */
+		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list)
+			if (a->tc_index == tc_abort) {
+				task_kill_later(a);
+				break;
+			}
+		goto out;
+	}
+	case REQ_DEVICE_RESET: {
+		struct asd_ascb *a, *b;
+		u16 conn_handle;
+
+		conn_handle = *((u16*)(&dl->status_block[1]));
+		conn_handle = le16_to_cpu(conn_handle);
+
+		ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__,
+			    dl->status_block[3]);
+
+		/* Kill all pending tasks and reset the device */
+		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
+			struct sas_task *task = a->uldd_task;
+			struct domain_device *dev = task->dev;
+			u16 x;
+
+			x = *((u16*)(&dev->lldd_dev));
+			if (x == conn_handle)
+				task_kill_later(a);
+		}
+
+		/* FIXME: Reset device port (huh?) */
+		goto out;
+	}
+	case SIGNAL_NCQ_ERROR:
+		ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __FUNCTION__);
+		goto out;
+	case CLEAR_NCQ_ERROR:
+		ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __FUNCTION__);
+		goto out;
+	}
+
 	sb_opcode &= ~DL_PHY_MASK;
 
 	switch (sb_opcode) {
@@ -397,22 +462,6 @@ static void escb_tasklet_complete(struct
 		sas_phy_disconnected(sas_phy);
 		sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT);
 		break;
-	case REQ_TASK_ABORT:
-		ASD_DPRINTK("%s: phy%d: REQ_TASK_ABORT\n", __FUNCTION__,
-			    phy_id);
-		break;
-	case REQ_DEVICE_RESET:
-		ASD_DPRINTK("%s: phy%d: REQ_DEVICE_RESET\n", __FUNCTION__,
-			    phy_id);
-		break;
-	case SIGNAL_NCQ_ERROR:
-		ASD_DPRINTK("%s: phy%d: SIGNAL_NCQ_ERROR\n", __FUNCTION__,
-			    phy_id);
-		break;
-	case CLEAR_NCQ_ERROR:
-		ASD_DPRINTK("%s: phy%d: CLEAR_NCQ_ERROR\n", __FUNCTION__,
-			    phy_id);
-		break;
 	default:
 		ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__,
 			    phy_id, sb_opcode);
@@ -432,7 +481,7 @@ static void escb_tasklet_complete(struct
 
 		break;
 	}
-
+out:
 	asd_invalidate_edb(ascb, edb);
 }
 

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] 3/3: Handle REQ_TASK_ABORT in aic94xx
  2006-10-30 23:18 [PATCH] 3/3: Handle REQ_TASK_ABORT in aic94xx Darrick J. Wong
@ 2006-10-31  7:53 ` Luben Tuikov
  0 siblings, 0 replies; 2+ messages in thread
From: Luben Tuikov @ 2006-10-31  7:53 UTC (permalink / raw)
  To: Darrick J. Wong, linux-scsi, Linux Kernel Mailing List; +Cc: Alexis Bruemmer

--- "Darrick J. Wong" <djwong@us.ibm.com> wrote:
> This patch straightens out the code that distinguishes the various escb
> opcodes in escb_tasklet_complete so that they can be handled correctly. 
> It also provides all the necessary code to create a workqueue item that
> tells libsas to abort a sas_task.
> 
> Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
> 
> --
> 
> diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
> index 7ee49b5..1911c5d 100644
> --- a/drivers/scsi/aic94xx/aic94xx_scb.c
> +++ b/drivers/scsi/aic94xx/aic94xx_scb.c
> @@ -25,6 +25,7 @@
>   */
>  
>  #include <linux/pci.h>
> +#include <scsi/scsi_host.h>
>  
>  #include "aic94xx.h"
>  #include "aic94xx_reg.h"
> @@ -342,6 +343,18 @@ void asd_invalidate_edb(struct asd_ascb 
>  	}
>  }
>  
> +/* start up the ABORT TASK tmf... */
> +static void task_kill_later(struct asd_ascb *ascb)
> +{
> +	struct asd_ha_struct *asd_ha = ascb->ha;
> +	struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
> +	struct Scsi_Host *shost = sas_ha->core.shost;
> +	struct sas_task *task = ascb->uldd_task;
> +
> +	INIT_WORK(&task->abort_work, (void (*)(void *))sas_task_abort, task);
> +	queue_work(shost->work_q, &task->abort_work);
> +}
> +
>  static void escb_tasklet_complete(struct asd_ascb *ascb,
>  				  struct done_list_struct *dl)
>  {
> @@ -368,6 +381,58 @@ static void escb_tasklet_complete(struct
>  			    ascb->scb->header.opcode);
>  	}
>  
> +	/* Catch these before we mask off the sb_opcode bits */
> +	switch (sb_opcode) {
> +	case REQ_TASK_ABORT: {
> +		struct asd_ascb *a, *b;
> +		u16 tc_abort;
> +
> +		tc_abort = *((u16*)(&dl->status_block[1]));
> +		tc_abort = le16_to_cpu(tc_abort);
> +
> +		ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
> +			    __FUNCTION__, dl->status_block[3]);
> +
> +		/* Find the pending task and abort it. */
> +		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list)
> +			if (a->tc_index == tc_abort) {
> +				task_kill_later(a);
> +				break;
> +			}
> +		goto out;
> +	}
> +	case REQ_DEVICE_RESET: {
> +		struct asd_ascb *a, *b;
> +		u16 conn_handle;
> +
> +		conn_handle = *((u16*)(&dl->status_block[1]));
> +		conn_handle = le16_to_cpu(conn_handle);
> +
> +		ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__,
> +			    dl->status_block[3]);
> +
> +		/* Kill all pending tasks and reset the device */
> +		list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
> +			struct sas_task *task = a->uldd_task;
> +			struct domain_device *dev = task->dev;
> +			u16 x;
> +
> +			x = *((u16*)(&dev->lldd_dev));
> +			if (x == conn_handle)
> +				task_kill_later(a);
> +		}
> +
> +		/* FIXME: Reset device port (huh?) */
> +		goto out;

"huh?" -- LOL, that's a very funny comment.

Good luck!
   Luben

> +	}
> +	case SIGNAL_NCQ_ERROR:
> +		ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __FUNCTION__);
> +		goto out;
> +	case CLEAR_NCQ_ERROR:
> +		ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __FUNCTION__);
> +		goto out;
> +	}
> +
>  	sb_opcode &= ~DL_PHY_MASK;
>  
>  	switch (sb_opcode) {
> @@ -397,22 +462,6 @@ static void escb_tasklet_complete(struct
>  		sas_phy_disconnected(sas_phy);
>  		sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT);
>  		break;
> -	case REQ_TASK_ABORT:
> -		ASD_DPRINTK("%s: phy%d: REQ_TASK_ABORT\n", __FUNCTION__,
> -			    phy_id);
> -		break;
> -	case REQ_DEVICE_RESET:
> -		ASD_DPRINTK("%s: phy%d: REQ_DEVICE_RESET\n", __FUNCTION__,
> -			    phy_id);
> -		break;
> -	case SIGNAL_NCQ_ERROR:
> -		ASD_DPRINTK("%s: phy%d: SIGNAL_NCQ_ERROR\n", __FUNCTION__,
> -			    phy_id);
> -		break;
> -	case CLEAR_NCQ_ERROR:
> -		ASD_DPRINTK("%s: phy%d: CLEAR_NCQ_ERROR\n", __FUNCTION__,
> -			    phy_id);
> -		break;
>  	default:
>  		ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__,
>  			    phy_id, sb_opcode);
> @@ -432,7 +481,7 @@ static void escb_tasklet_complete(struct
>  
>  		break;
>  	}
> -
> +out:
>  	asd_invalidate_edb(ascb, edb);
>  }
>  
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2006-10-31  7:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-30 23:18 [PATCH] 3/3: Handle REQ_TASK_ABORT in aic94xx Darrick J. Wong
2006-10-31  7:53 ` Luben Tuikov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox