diff options
Diffstat (limited to 'drivers/scsi/isci/task.c')
-rw-r--r-- | drivers/scsi/isci/task.c | 158 |
1 files changed, 30 insertions, 128 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index f5a3f7d2bdab..374254ede9d4 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c | |||
@@ -96,8 +96,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, | |||
96 | __func__, task, response, status); | 96 | __func__, task, response, status); |
97 | 97 | ||
98 | task->lldd_task = NULL; | 98 | task->lldd_task = NULL; |
99 | 99 | task->task_done(task); | |
100 | isci_execpath_callback(ihost, task, task->task_done); | ||
101 | break; | 100 | break; |
102 | 101 | ||
103 | case isci_perform_aborted_io_completion: | 102 | case isci_perform_aborted_io_completion: |
@@ -117,8 +116,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, | |||
117 | "%s: Error - task = %p, response=%d, " | 116 | "%s: Error - task = %p, response=%d, " |
118 | "status=%d\n", | 117 | "status=%d\n", |
119 | __func__, task, response, status); | 118 | __func__, task, response, status); |
120 | 119 | sas_task_abort(task); | |
121 | isci_execpath_callback(ihost, task, sas_task_abort); | ||
122 | break; | 120 | break; |
123 | 121 | ||
124 | default: | 122 | default: |
@@ -249,46 +247,6 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
249 | return 0; | 247 | return 0; |
250 | } | 248 | } |
251 | 249 | ||
252 | static enum sci_status isci_sata_management_task_request_build(struct isci_request *ireq) | ||
253 | { | ||
254 | struct isci_tmf *isci_tmf; | ||
255 | enum sci_status status; | ||
256 | |||
257 | if (!test_bit(IREQ_TMF, &ireq->flags)) | ||
258 | return SCI_FAILURE; | ||
259 | |||
260 | isci_tmf = isci_request_access_tmf(ireq); | ||
261 | |||
262 | switch (isci_tmf->tmf_code) { | ||
263 | |||
264 | case isci_tmf_sata_srst_high: | ||
265 | case isci_tmf_sata_srst_low: { | ||
266 | struct host_to_dev_fis *fis = &ireq->stp.cmd; | ||
267 | |||
268 | memset(fis, 0, sizeof(*fis)); | ||
269 | |||
270 | fis->fis_type = 0x27; | ||
271 | fis->flags &= ~0x80; | ||
272 | fis->flags &= 0xF0; | ||
273 | if (isci_tmf->tmf_code == isci_tmf_sata_srst_high) | ||
274 | fis->control |= ATA_SRST; | ||
275 | else | ||
276 | fis->control &= ~ATA_SRST; | ||
277 | break; | ||
278 | } | ||
279 | /* other management commnd go here... */ | ||
280 | default: | ||
281 | return SCI_FAILURE; | ||
282 | } | ||
283 | |||
284 | /* core builds the protocol specific request | ||
285 | * based on the h2d fis. | ||
286 | */ | ||
287 | status = sci_task_request_construct_sata(ireq); | ||
288 | |||
289 | return status; | ||
290 | } | ||
291 | |||
292 | static struct isci_request *isci_task_request_build(struct isci_host *ihost, | 250 | static struct isci_request *isci_task_request_build(struct isci_host *ihost, |
293 | struct isci_remote_device *idev, | 251 | struct isci_remote_device *idev, |
294 | u16 tag, struct isci_tmf *isci_tmf) | 252 | u16 tag, struct isci_tmf *isci_tmf) |
@@ -328,13 +286,6 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |||
328 | return NULL; | 286 | return NULL; |
329 | } | 287 | } |
330 | 288 | ||
331 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { | ||
332 | isci_tmf->proto = SAS_PROTOCOL_SATA; | ||
333 | status = isci_sata_management_task_request_build(ireq); | ||
334 | |||
335 | if (status != SCI_SUCCESS) | ||
336 | return NULL; | ||
337 | } | ||
338 | return ireq; | 289 | return ireq; |
339 | } | 290 | } |
340 | 291 | ||
@@ -873,53 +824,20 @@ static int isci_task_send_lu_reset_sas( | |||
873 | return ret; | 824 | return ret; |
874 | } | 825 | } |
875 | 826 | ||
876 | static int isci_task_send_lu_reset_sata(struct isci_host *ihost, | 827 | int isci_task_lu_reset(struct domain_device *dev, u8 *lun) |
877 | struct isci_remote_device *idev, u8 *lun) | ||
878 | { | ||
879 | int ret = TMF_RESP_FUNC_FAILED; | ||
880 | struct isci_tmf tmf; | ||
881 | |||
882 | /* Send the soft reset to the target */ | ||
883 | #define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */ | ||
884 | isci_task_build_tmf(&tmf, isci_tmf_sata_srst_high, NULL, NULL); | ||
885 | |||
886 | ret = isci_task_execute_tmf(ihost, idev, &tmf, ISCI_SRST_TIMEOUT_MS); | ||
887 | |||
888 | if (ret != TMF_RESP_FUNC_COMPLETE) { | ||
889 | dev_dbg(&ihost->pdev->dev, | ||
890 | "%s: Assert SRST failed (%p) = %x", | ||
891 | __func__, idev, ret); | ||
892 | |||
893 | /* Return the failure so that the LUN reset is escalated | ||
894 | * to a target reset. | ||
895 | */ | ||
896 | } | ||
897 | return ret; | ||
898 | } | ||
899 | |||
900 | /** | ||
901 | * isci_task_lu_reset() - This function is one of the SAS Domain Template | ||
902 | * functions. This is one of the Task Management functoins called by libsas, | ||
903 | * to reset the given lun. Note the assumption that while this call is | ||
904 | * executing, no I/O will be sent by the host to the device. | ||
905 | * @lun: This parameter specifies the lun to be reset. | ||
906 | * | ||
907 | * status, zero indicates success. | ||
908 | */ | ||
909 | int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) | ||
910 | { | 828 | { |
911 | struct isci_host *isci_host = dev_to_ihost(domain_device); | 829 | struct isci_host *isci_host = dev_to_ihost(dev); |
912 | struct isci_remote_device *isci_device; | 830 | struct isci_remote_device *isci_device; |
913 | unsigned long flags; | 831 | unsigned long flags; |
914 | int ret; | 832 | int ret; |
915 | 833 | ||
916 | spin_lock_irqsave(&isci_host->scic_lock, flags); | 834 | spin_lock_irqsave(&isci_host->scic_lock, flags); |
917 | isci_device = isci_lookup_device(domain_device); | 835 | isci_device = isci_lookup_device(dev); |
918 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | 836 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); |
919 | 837 | ||
920 | dev_dbg(&isci_host->pdev->dev, | 838 | dev_dbg(&isci_host->pdev->dev, |
921 | "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", | 839 | "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", |
922 | __func__, domain_device, isci_host, isci_device); | 840 | __func__, dev, isci_host, isci_device); |
923 | 841 | ||
924 | if (!isci_device) { | 842 | if (!isci_device) { |
925 | /* If the device is gone, stop the escalations. */ | 843 | /* If the device is gone, stop the escalations. */ |
@@ -928,11 +846,11 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) | |||
928 | ret = TMF_RESP_FUNC_COMPLETE; | 846 | ret = TMF_RESP_FUNC_COMPLETE; |
929 | goto out; | 847 | goto out; |
930 | } | 848 | } |
931 | set_bit(IDEV_EH, &isci_device->flags); | ||
932 | 849 | ||
933 | /* Send the task management part of the reset. */ | 850 | /* Send the task management part of the reset. */ |
934 | if (sas_protocol_ata(domain_device->tproto)) { | 851 | if (dev_is_sata(dev)) { |
935 | ret = isci_task_send_lu_reset_sata(isci_host, isci_device, lun); | 852 | sas_ata_schedule_reset(dev); |
853 | ret = TMF_RESP_FUNC_COMPLETE; | ||
936 | } else | 854 | } else |
937 | ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun); | 855 | ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun); |
938 | 856 | ||
@@ -1062,9 +980,6 @@ int isci_task_abort_task(struct sas_task *task) | |||
1062 | "%s: dev = %p, task = %p, old_request == %p\n", | 980 | "%s: dev = %p, task = %p, old_request == %p\n", |
1063 | __func__, isci_device, task, old_request); | 981 | __func__, isci_device, task, old_request); |
1064 | 982 | ||
1065 | if (isci_device) | ||
1066 | set_bit(IDEV_EH, &isci_device->flags); | ||
1067 | |||
1068 | /* Device reset conditions signalled in task_state_flags are the | 983 | /* Device reset conditions signalled in task_state_flags are the |
1069 | * responsbility of libsas to observe at the start of the error | 984 | * responsbility of libsas to observe at the start of the error |
1070 | * handler thread. | 985 | * handler thread. |
@@ -1332,29 +1247,35 @@ isci_task_request_complete(struct isci_host *ihost, | |||
1332 | } | 1247 | } |
1333 | 1248 | ||
1334 | static int isci_reset_device(struct isci_host *ihost, | 1249 | static int isci_reset_device(struct isci_host *ihost, |
1250 | struct domain_device *dev, | ||
1335 | struct isci_remote_device *idev) | 1251 | struct isci_remote_device *idev) |
1336 | { | 1252 | { |
1337 | struct sas_phy *phy = sas_find_local_phy(idev->domain_dev); | ||
1338 | enum sci_status status; | ||
1339 | unsigned long flags; | ||
1340 | int rc; | 1253 | int rc; |
1254 | unsigned long flags; | ||
1255 | enum sci_status status; | ||
1256 | struct sas_phy *phy = sas_get_local_phy(dev); | ||
1257 | struct isci_port *iport = dev->port->lldd_port; | ||
1341 | 1258 | ||
1342 | dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); | 1259 | dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); |
1343 | 1260 | ||
1344 | spin_lock_irqsave(&ihost->scic_lock, flags); | 1261 | spin_lock_irqsave(&ihost->scic_lock, flags); |
1345 | status = sci_remote_device_reset(idev); | 1262 | status = sci_remote_device_reset(idev); |
1346 | if (status != SCI_SUCCESS) { | 1263 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
1347 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
1348 | 1264 | ||
1265 | if (status != SCI_SUCCESS) { | ||
1349 | dev_dbg(&ihost->pdev->dev, | 1266 | dev_dbg(&ihost->pdev->dev, |
1350 | "%s: sci_remote_device_reset(%p) returned %d!\n", | 1267 | "%s: sci_remote_device_reset(%p) returned %d!\n", |
1351 | __func__, idev, status); | 1268 | __func__, idev, status); |
1352 | 1269 | rc = TMF_RESP_FUNC_FAILED; | |
1353 | return TMF_RESP_FUNC_FAILED; | 1270 | goto out; |
1354 | } | 1271 | } |
1355 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
1356 | 1272 | ||
1357 | rc = sas_phy_reset(phy, true); | 1273 | if (scsi_is_sas_phy_local(phy)) { |
1274 | struct isci_phy *iphy = &ihost->phys[phy->number]; | ||
1275 | |||
1276 | rc = isci_port_perform_hard_reset(ihost, iport, iphy); | ||
1277 | } else | ||
1278 | rc = sas_phy_reset(phy, !dev_is_sata(dev)); | ||
1358 | 1279 | ||
1359 | /* Terminate in-progress I/O now. */ | 1280 | /* Terminate in-progress I/O now. */ |
1360 | isci_remote_device_nuke_requests(ihost, idev); | 1281 | isci_remote_device_nuke_requests(ihost, idev); |
@@ -1371,7 +1292,8 @@ static int isci_reset_device(struct isci_host *ihost, | |||
1371 | } | 1292 | } |
1372 | 1293 | ||
1373 | dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev); | 1294 | dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev); |
1374 | 1295 | out: | |
1296 | sas_put_local_phy(phy); | ||
1375 | return rc; | 1297 | return rc; |
1376 | } | 1298 | } |
1377 | 1299 | ||
@@ -1386,35 +1308,15 @@ int isci_task_I_T_nexus_reset(struct domain_device *dev) | |||
1386 | idev = isci_lookup_device(dev); | 1308 | idev = isci_lookup_device(dev); |
1387 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 1309 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
1388 | 1310 | ||
1389 | if (!idev || !test_bit(IDEV_EH, &idev->flags)) { | ||
1390 | ret = TMF_RESP_FUNC_COMPLETE; | ||
1391 | goto out; | ||
1392 | } | ||
1393 | |||
1394 | ret = isci_reset_device(ihost, idev); | ||
1395 | out: | ||
1396 | isci_put_device(idev); | ||
1397 | return ret; | ||
1398 | } | ||
1399 | |||
1400 | int isci_bus_reset_handler(struct scsi_cmnd *cmd) | ||
1401 | { | ||
1402 | struct domain_device *dev = sdev_to_domain_dev(cmd->device); | ||
1403 | struct isci_host *ihost = dev_to_ihost(dev); | ||
1404 | struct isci_remote_device *idev; | ||
1405 | unsigned long flags; | ||
1406 | int ret; | ||
1407 | |||
1408 | spin_lock_irqsave(&ihost->scic_lock, flags); | ||
1409 | idev = isci_lookup_device(dev); | ||
1410 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
1411 | |||
1412 | if (!idev) { | 1311 | if (!idev) { |
1312 | /* XXX: need to cleanup any ireqs targeting this | ||
1313 | * domain_device | ||
1314 | */ | ||
1413 | ret = TMF_RESP_FUNC_COMPLETE; | 1315 | ret = TMF_RESP_FUNC_COMPLETE; |
1414 | goto out; | 1316 | goto out; |
1415 | } | 1317 | } |
1416 | 1318 | ||
1417 | ret = isci_reset_device(ihost, idev); | 1319 | ret = isci_reset_device(ihost, dev, idev); |
1418 | out: | 1320 | out: |
1419 | isci_put_device(idev); | 1321 | isci_put_device(idev); |
1420 | return ret; | 1322 | return ret; |