aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Garry <john.garry@huawei.com>2016-02-25 04:42:11 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-02-29 21:00:03 -0500
commitcac9b2a21789b7354b0e616892c7d193e8167277 (patch)
tree0722e49651185b3481c91225c221e20d8d7e2f66
parent1af1b8088907dc8ed024df95c0ba0f7ef39a9fea (diff)
hisi_sas: add hisi_sas_slot_abort()
Add a function to abort a slot (task) in the target device and then cleanup and complete the task. The function is called from work queue context as it cannot be called from the context where it is triggered (interrupt). Flag hisi_sas_slot.abort is added as the flag used in the slot error handler to indicate whether the slot needs to be aborted in the sdev prior to cleanup and finish. Signed-off-by: John Garry <john.garry@huawei.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h2
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c42
2 files changed, 44 insertions, 0 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 02da7e4f9eb6..c92e65b989a6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -112,6 +112,7 @@ struct hisi_sas_slot {
112 int cmplt_queue; 112 int cmplt_queue;
113 int cmplt_queue_slot; 113 int cmplt_queue_slot;
114 int idx; 114 int idx;
115 int abort;
115 void *cmd_hdr; 116 void *cmd_hdr;
116 dma_addr_t cmd_hdr_dma; 117 dma_addr_t cmd_hdr_dma;
117 void *status_buffer; 118 void *status_buffer;
@@ -120,6 +121,7 @@ struct hisi_sas_slot {
120 dma_addr_t command_table_dma; 121 dma_addr_t command_table_dma;
121 struct hisi_sas_sge_page *sge_page; 122 struct hisi_sas_sge_page *sge_page;
122 dma_addr_t sge_page_dma; 123 dma_addr_t sge_page_dma;
124 struct work_struct abort_slot;
123}; 125};
124 126
125struct hisi_sas_tmf_task { 127struct hisi_sas_tmf_task {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 58ca336c9509..e51612f7f933 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -15,6 +15,9 @@
15#define DEV_IS_GONE(dev) \ 15#define DEV_IS_GONE(dev) \
16 ((!dev) || (dev->dev_type == SAS_PHY_UNUSED)) 16 ((!dev) || (dev->dev_type == SAS_PHY_UNUSED))
17 17
18static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
19 u8 *lun, struct hisi_sas_tmf_task *tmf);
20
18static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device) 21static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
19{ 22{
20 return device->port->ha->lldd_ha; 23 return device->port->ha->lldd_ha;
@@ -113,6 +116,44 @@ static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
113 return hisi_hba->hw->prep_stp(hisi_hba, slot); 116 return hisi_hba->hw->prep_stp(hisi_hba, slot);
114} 117}
115 118
119/*
120 * This function will issue an abort TMF regardless of whether the
121 * task is in the sdev or not. Then it will do the task complete
122 * cleanup and callbacks.
123 */
124static void hisi_sas_slot_abort(struct work_struct *work)
125{
126 struct hisi_sas_slot *abort_slot =
127 container_of(work, struct hisi_sas_slot, abort_slot);
128 struct sas_task *task = abort_slot->task;
129 struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
130 struct scsi_cmnd *cmnd = task->uldd_task;
131 struct hisi_sas_tmf_task tmf_task;
132 struct domain_device *device = task->dev;
133 struct hisi_sas_device *sas_dev = device->lldd_dev;
134 struct scsi_lun lun;
135 struct device *dev = &hisi_hba->pdev->dev;
136 int tag = abort_slot->idx;
137
138 if (!(task->task_proto & SAS_PROTOCOL_SSP)) {
139 dev_err(dev, "cannot abort slot for non-ssp task\n");
140 goto out;
141 }
142
143 int_to_scsilun(cmnd->device->lun, &lun);
144 tmf_task.tmf = TMF_ABORT_TASK;
145 tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
146
147 hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task);
148out:
149 /* Do cleanup for this task */
150 hisi_sas_slot_task_free(hisi_hba, task, abort_slot);
151 if (task->task_done)
152 task->task_done(task);
153 if (sas_dev && sas_dev->running_req)
154 sas_dev->running_req--;
155}
156
116static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, 157static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
117 int is_tmf, struct hisi_sas_tmf_task *tmf, 158 int is_tmf, struct hisi_sas_tmf_task *tmf,
118 int *pass) 159 int *pass)
@@ -206,6 +247,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
206 slot->task = task; 247 slot->task = task;
207 slot->port = port; 248 slot->port = port;
208 task->lldd_task = slot; 249 task->lldd_task = slot;
250 INIT_WORK(&slot->abort_slot, hisi_sas_slot_abort);
209 251
210 slot->status_buffer = dma_pool_alloc(hisi_hba->status_buffer_pool, 252 slot->status_buffer = dma_pool_alloc(hisi_hba->status_buffer_pool,
211 GFP_ATOMIC, 253 GFP_ATOMIC,