3/3: Handle REQ_TASK_ABORT in aic94xx
PATCH 1/1 3/3: Handle REQ_TASK_ABORT in aic94xx
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.
--
drivers/scsi/aic94xx/aic94xx_scb.c +66 -17
@@ -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(structsas_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(structbreak ; } - +out:asd_invalidate_edb (ascb, edb); }
Quoted 77 lines · --- "Darrick J. Wong
This patch straightens out the code that distinguishes the various escb opcodes in
escb_tasklet_completeso that they can be handled correctly. It also provides all the necessary code to create a workqueue item that tells libsas to abort asas_task.Signed-off-by Darrick J. Wong <[email protected]>--
drivers/scsi/aic94xx/aic94xx_scb.c +46
-0@@ -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;
drivers/scsi/aic94xx/aic94xx_scb.c static void escb_tasklet_complete(struct · line 426
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_scb.c +10
-0+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
Quoted 49 lines
drivers/scsi/aic94xx/aic94xx_scb.c +10
-18+ } +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(structsas_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(structbreak ; } - +out:asd_invalidate_edb (ascb, edb); } -To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html