diff options
Diffstat (limited to 'drivers/scsi/isci/task.c')
-rw-r--r-- | drivers/scsi/isci/task.c | 100 |
1 files changed, 80 insertions, 20 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 20112cd5b646..5d962b6b03eb 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c | |||
@@ -61,7 +61,6 @@ | |||
61 | #include "remote_node_context.h" | 61 | #include "remote_node_context.h" |
62 | #include "isci.h" | 62 | #include "isci.h" |
63 | #include "request.h" | 63 | #include "request.h" |
64 | #include "sata.h" | ||
65 | #include "task.h" | 64 | #include "task.h" |
66 | #include "host.h" | 65 | #include "host.h" |
67 | 66 | ||
@@ -238,6 +237,46 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
238 | return 0; | 237 | return 0; |
239 | } | 238 | } |
240 | 239 | ||
240 | static enum sci_status isci_sata_management_task_request_build(struct isci_request *ireq) | ||
241 | { | ||
242 | struct isci_tmf *isci_tmf; | ||
243 | enum sci_status status; | ||
244 | |||
245 | if (tmf_task != ireq->ttype) | ||
246 | return SCI_FAILURE; | ||
247 | |||
248 | isci_tmf = isci_request_access_tmf(ireq); | ||
249 | |||
250 | switch (isci_tmf->tmf_code) { | ||
251 | |||
252 | case isci_tmf_sata_srst_high: | ||
253 | case isci_tmf_sata_srst_low: { | ||
254 | struct host_to_dev_fis *fis = &ireq->stp.cmd; | ||
255 | |||
256 | memset(fis, 0, sizeof(*fis)); | ||
257 | |||
258 | fis->fis_type = 0x27; | ||
259 | fis->flags &= ~0x80; | ||
260 | fis->flags &= 0xF0; | ||
261 | if (isci_tmf->tmf_code == isci_tmf_sata_srst_high) | ||
262 | fis->control |= ATA_SRST; | ||
263 | else | ||
264 | fis->control &= ~ATA_SRST; | ||
265 | break; | ||
266 | } | ||
267 | /* other management commnd go here... */ | ||
268 | default: | ||
269 | return SCI_FAILURE; | ||
270 | } | ||
271 | |||
272 | /* core builds the protocol specific request | ||
273 | * based on the h2d fis. | ||
274 | */ | ||
275 | status = sci_task_request_construct_sata(ireq); | ||
276 | |||
277 | return status; | ||
278 | } | ||
279 | |||
241 | static struct isci_request *isci_task_request_build(struct isci_host *ihost, | 280 | static struct isci_request *isci_task_request_build(struct isci_host *ihost, |
242 | struct isci_remote_device *idev, | 281 | struct isci_remote_device *idev, |
243 | u16 tag, struct isci_tmf *isci_tmf) | 282 | u16 tag, struct isci_tmf *isci_tmf) |
@@ -287,9 +326,9 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |||
287 | return ireq; | 326 | return ireq; |
288 | } | 327 | } |
289 | 328 | ||
290 | int isci_task_execute_tmf(struct isci_host *ihost, | 329 | static int isci_task_execute_tmf(struct isci_host *ihost, |
291 | struct isci_remote_device *idev, | 330 | struct isci_remote_device *idev, |
292 | struct isci_tmf *tmf, unsigned long timeout_ms) | 331 | struct isci_tmf *tmf, unsigned long timeout_ms) |
293 | { | 332 | { |
294 | DECLARE_COMPLETION_ONSTACK(completion); | 333 | DECLARE_COMPLETION_ONSTACK(completion); |
295 | enum sci_task_status status = SCI_TASK_FAILURE; | 334 | enum sci_task_status status = SCI_TASK_FAILURE; |
@@ -401,13 +440,12 @@ int isci_task_execute_tmf(struct isci_host *ihost, | |||
401 | return ret; | 440 | return ret; |
402 | } | 441 | } |
403 | 442 | ||
404 | void isci_task_build_tmf( | 443 | static void isci_task_build_tmf(struct isci_tmf *tmf, |
405 | struct isci_tmf *tmf, | 444 | enum isci_tmf_function_codes code, |
406 | enum isci_tmf_function_codes code, | 445 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, |
407 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, | 446 | struct isci_tmf *, |
408 | struct isci_tmf *, | 447 | void *), |
409 | void *), | 448 | void *cb_data) |
410 | void *cb_data) | ||
411 | { | 449 | { |
412 | memset(tmf, 0, sizeof(*tmf)); | 450 | memset(tmf, 0, sizeof(*tmf)); |
413 | 451 | ||
@@ -416,16 +454,14 @@ void isci_task_build_tmf( | |||
416 | tmf->cb_data = cb_data; | 454 | tmf->cb_data = cb_data; |
417 | } | 455 | } |
418 | 456 | ||
419 | static void isci_task_build_abort_task_tmf( | 457 | static void isci_task_build_abort_task_tmf(struct isci_tmf *tmf, |
420 | struct isci_tmf *tmf, | 458 | enum isci_tmf_function_codes code, |
421 | enum isci_tmf_function_codes code, | 459 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, |
422 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, | 460 | struct isci_tmf *, |
423 | struct isci_tmf *, | 461 | void *), |
424 | void *), | 462 | struct isci_request *old_request) |
425 | struct isci_request *old_request) | ||
426 | { | 463 | { |
427 | isci_task_build_tmf(tmf, code, tmf_sent_cb, | 464 | isci_task_build_tmf(tmf, code, tmf_sent_cb, old_request); |
428 | (void *)old_request); | ||
429 | tmf->io_tag = old_request->io_tag; | 465 | tmf->io_tag = old_request->io_tag; |
430 | } | 466 | } |
431 | 467 | ||
@@ -804,6 +840,30 @@ static int isci_task_send_lu_reset_sas( | |||
804 | return ret; | 840 | return ret; |
805 | } | 841 | } |
806 | 842 | ||
843 | static int isci_task_send_lu_reset_sata(struct isci_host *ihost, | ||
844 | struct isci_remote_device *idev, u8 *lun) | ||
845 | { | ||
846 | int ret = TMF_RESP_FUNC_FAILED; | ||
847 | struct isci_tmf tmf; | ||
848 | |||
849 | /* Send the soft reset to the target */ | ||
850 | #define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */ | ||
851 | isci_task_build_tmf(&tmf, isci_tmf_sata_srst_high, NULL, NULL); | ||
852 | |||
853 | ret = isci_task_execute_tmf(ihost, idev, &tmf, ISCI_SRST_TIMEOUT_MS); | ||
854 | |||
855 | if (ret != TMF_RESP_FUNC_COMPLETE) { | ||
856 | dev_warn(&ihost->pdev->dev, | ||
857 | "%s: Assert SRST failed (%p) = %x", | ||
858 | __func__, idev, ret); | ||
859 | |||
860 | /* Return the failure so that the LUN reset is escalated | ||
861 | * to a target reset. | ||
862 | */ | ||
863 | } | ||
864 | return ret; | ||
865 | } | ||
866 | |||
807 | /** | 867 | /** |
808 | * isci_task_lu_reset() - This function is one of the SAS Domain Template | 868 | * isci_task_lu_reset() - This function is one of the SAS Domain Template |
809 | * functions. This is one of the Task Management functoins called by libsas, | 869 | * functions. This is one of the Task Management functoins called by libsas, |