diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-09-30 21:52:19 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-10-02 14:20:03 -0400 |
commit | b50102d3e9a43a75379407c2080f696f61cb286b (patch) | |
tree | b37eb5ed05f2228842c54cdac455f00ec846746e | |
parent | 4f3f812dd3b638d0c92661122dcccd6aaef66bfb (diff) |
[SCSI] isci: atapi support
Based on original implementation from Jiangbi Liu and Maciej Trela.
ATAPI transfers happen in two-to-three stages. The two stage atapi
commands are those that include a dma data transfer. The data transfer
portion of these operations is handled by the hardware packet-dma
acceleration. The three-stage commands do not have a data transfer and
are handled without hardware assistance in raw frame mode.
stage1: transmit host-to-device fis to notify the device of an incoming
atapi cdb. Upon reception of the pio-setup-fis repost the task_context
to perform the dma transfer of the cdb+data (go to stage3), or repost
the task_context to transmit the cdb as a raw frame (go to stage 2).
stage2: wait for hardware notification of the cdb transmission and then
go to stage 3.
stage3: wait for the arrival of the terminating device-to-host fis and
terminate the command.
To keep the implementation simple we only support ATAPI packet-dma
protocol (for commands with data) to avoid needing to handle the data
transfer manually (like we do for SATA-PIO). This may affect
compatibility for a small number of devices (see
ATA_HORKAGE_ATAPI_MOD16_DMA).
If the data-transfer underruns, or encounters an error the
device-to-host fis is expected to arrive in the unsolicited frame queue
to pass to libata for disposition. However, in the DONE_UNEXP_FIS (data
underrun) case it appears we need to craft a response. In the
DONE_REG_ERR case we do receive the UF and propagate it to libsas.
Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 24 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.h | 9 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 328 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 28 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 2 | ||||
-rw-r--r-- | include/scsi/libsas.h | 5 |
6 files changed, 380 insertions, 16 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index b6e6368c2665..fbf9ce28c3f5 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
@@ -386,6 +386,18 @@ static bool is_remote_device_ready(struct isci_remote_device *idev) | |||
386 | } | 386 | } |
387 | } | 387 | } |
388 | 388 | ||
389 | /* | ||
390 | * called once the remote node context has transisitioned to a ready | ||
391 | * state (after suspending RX and/or TX due to early D2H fis) | ||
392 | */ | ||
393 | static void atapi_remote_device_resume_done(void *_dev) | ||
394 | { | ||
395 | struct isci_remote_device *idev = _dev; | ||
396 | struct isci_request *ireq = idev->working_request; | ||
397 | |||
398 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); | ||
399 | } | ||
400 | |||
389 | enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev, | 401 | enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev, |
390 | u32 event_code) | 402 | u32 event_code) |
391 | { | 403 | { |
@@ -432,6 +444,16 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev, | |||
432 | if (status != SCI_SUCCESS) | 444 | if (status != SCI_SUCCESS) |
433 | return status; | 445 | return status; |
434 | 446 | ||
447 | if (state == SCI_STP_DEV_ATAPI_ERROR) { | ||
448 | /* For ATAPI error state resume the RNC right away. */ | ||
449 | if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX || | ||
450 | scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { | ||
451 | return sci_remote_node_context_resume(&idev->rnc, | ||
452 | atapi_remote_device_resume_done, | ||
453 | idev); | ||
454 | } | ||
455 | } | ||
456 | |||
435 | if (state == SCI_STP_DEV_IDLE) { | 457 | if (state == SCI_STP_DEV_IDLE) { |
436 | 458 | ||
437 | /* We pick up suspension events to handle specifically to this | 459 | /* We pick up suspension events to handle specifically to this |
@@ -625,6 +647,7 @@ enum sci_status sci_remote_device_complete_io(struct isci_host *ihost, | |||
625 | case SCI_STP_DEV_CMD: | 647 | case SCI_STP_DEV_CMD: |
626 | case SCI_STP_DEV_NCQ: | 648 | case SCI_STP_DEV_NCQ: |
627 | case SCI_STP_DEV_NCQ_ERROR: | 649 | case SCI_STP_DEV_NCQ_ERROR: |
650 | case SCI_STP_DEV_ATAPI_ERROR: | ||
628 | status = common_complete_io(iport, idev, ireq); | 651 | status = common_complete_io(iport, idev, ireq); |
629 | if (status != SCI_SUCCESS) | 652 | if (status != SCI_SUCCESS) |
630 | break; | 653 | break; |
@@ -1020,6 +1043,7 @@ static const struct sci_base_state sci_remote_device_state_table[] = { | |||
1020 | [SCI_STP_DEV_NCQ_ERROR] = { | 1043 | [SCI_STP_DEV_NCQ_ERROR] = { |
1021 | .enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter, | 1044 | .enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter, |
1022 | }, | 1045 | }, |
1046 | [SCI_STP_DEV_ATAPI_ERROR] = { }, | ||
1023 | [SCI_STP_DEV_AWAIT_RESET] = { }, | 1047 | [SCI_STP_DEV_AWAIT_RESET] = { }, |
1024 | [SCI_SMP_DEV_IDLE] = { | 1048 | [SCI_SMP_DEV_IDLE] = { |
1025 | .enter_state = sci_smp_remote_device_ready_idle_substate_enter, | 1049 | .enter_state = sci_smp_remote_device_ready_idle_substate_enter, |
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 57ccfc3d6ad3..e1747ea0d0ea 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h | |||
@@ -244,6 +244,15 @@ enum sci_remote_device_states { | |||
244 | SCI_STP_DEV_NCQ_ERROR, | 244 | SCI_STP_DEV_NCQ_ERROR, |
245 | 245 | ||
246 | /** | 246 | /** |
247 | * This is the ATAPI error state for the STP ATAPI remote device. | ||
248 | * This state is entered when ATAPI device sends error status FIS | ||
249 | * without data while the device object is in CMD state. | ||
250 | * A suspension event is expected in this state. | ||
251 | * The device object will resume right away. | ||
252 | */ | ||
253 | SCI_STP_DEV_ATAPI_ERROR, | ||
254 | |||
255 | /** | ||
247 | * This is the READY substate indicates the device is waiting for the RESET task | 256 | * This is the READY substate indicates the device is waiting for the RESET task |
248 | * coming to be recovered from certain hardware specific error. | 257 | * coming to be recovered from certain hardware specific error. |
249 | */ | 258 | */ |
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 225b196800a2..23a55043a923 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -481,7 +481,29 @@ static void sci_stp_optimized_request_construct(struct isci_request *ireq, | |||
481 | } | 481 | } |
482 | } | 482 | } |
483 | 483 | ||
484 | static void sci_atapi_construct(struct isci_request *ireq) | ||
485 | { | ||
486 | struct host_to_dev_fis *h2d_fis = &ireq->stp.cmd; | ||
487 | struct sas_task *task; | ||
488 | |||
489 | /* To simplify the implementation we take advantage of the | ||
490 | * silicon's partial acceleration of atapi protocol (dma data | ||
491 | * transfers), so we promote all commands to dma protocol. This | ||
492 | * breaks compatibility with ATA_HORKAGE_ATAPI_MOD16_DMA drives. | ||
493 | */ | ||
494 | h2d_fis->features |= ATAPI_PKT_DMA; | ||
495 | |||
496 | scu_stp_raw_request_construct_task_context(ireq); | ||
497 | |||
498 | task = isci_request_access_task(ireq); | ||
499 | if (task->data_dir == DMA_NONE) | ||
500 | task->total_xfer_len = 0; | ||
484 | 501 | ||
502 | /* clear the response so we can detect arrivial of an | ||
503 | * unsolicited h2d fis | ||
504 | */ | ||
505 | ireq->stp.rsp.fis_type = 0; | ||
506 | } | ||
485 | 507 | ||
486 | static enum sci_status | 508 | static enum sci_status |
487 | sci_io_request_construct_sata(struct isci_request *ireq, | 509 | sci_io_request_construct_sata(struct isci_request *ireq, |
@@ -491,6 +513,7 @@ sci_io_request_construct_sata(struct isci_request *ireq, | |||
491 | { | 513 | { |
492 | enum sci_status status = SCI_SUCCESS; | 514 | enum sci_status status = SCI_SUCCESS; |
493 | struct sas_task *task = isci_request_access_task(ireq); | 515 | struct sas_task *task = isci_request_access_task(ireq); |
516 | struct domain_device *dev = ireq->target_device->domain_dev; | ||
494 | 517 | ||
495 | /* check for management protocols */ | 518 | /* check for management protocols */ |
496 | if (ireq->ttype == tmf_task) { | 519 | if (ireq->ttype == tmf_task) { |
@@ -519,6 +542,13 @@ sci_io_request_construct_sata(struct isci_request *ireq, | |||
519 | 542 | ||
520 | } | 543 | } |
521 | 544 | ||
545 | /* ATAPI */ | ||
546 | if (dev->sata_dev.command_set == ATAPI_COMMAND_SET && | ||
547 | task->ata_task.fis.command == ATA_CMD_PACKET) { | ||
548 | sci_atapi_construct(ireq); | ||
549 | return SCI_SUCCESS; | ||
550 | } | ||
551 | |||
522 | /* non data */ | 552 | /* non data */ |
523 | if (task->data_dir == DMA_NONE) { | 553 | if (task->data_dir == DMA_NONE) { |
524 | scu_stp_raw_request_construct_task_context(ireq); | 554 | scu_stp_raw_request_construct_task_context(ireq); |
@@ -627,7 +657,7 @@ enum sci_status sci_task_request_construct_sata(struct isci_request *ireq) | |||
627 | 657 | ||
628 | /** | 658 | /** |
629 | * sci_req_tx_bytes - bytes transferred when reply underruns request | 659 | * sci_req_tx_bytes - bytes transferred when reply underruns request |
630 | * @sci_req: request that was terminated early | 660 | * @ireq: request that was terminated early |
631 | */ | 661 | */ |
632 | #define SCU_TASK_CONTEXT_SRAM 0x200000 | 662 | #define SCU_TASK_CONTEXT_SRAM 0x200000 |
633 | static u32 sci_req_tx_bytes(struct isci_request *ireq) | 663 | static u32 sci_req_tx_bytes(struct isci_request *ireq) |
@@ -729,6 +759,10 @@ sci_io_request_terminate(struct isci_request *ireq) | |||
729 | case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED: | 759 | case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED: |
730 | case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG: | 760 | case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG: |
731 | case SCI_REQ_STP_SOFT_RESET_WAIT_D2H: | 761 | case SCI_REQ_STP_SOFT_RESET_WAIT_D2H: |
762 | case SCI_REQ_ATAPI_WAIT_H2D: | ||
763 | case SCI_REQ_ATAPI_WAIT_PIO_SETUP: | ||
764 | case SCI_REQ_ATAPI_WAIT_D2H: | ||
765 | case SCI_REQ_ATAPI_WAIT_TC_COMP: | ||
732 | sci_change_state(&ireq->sm, SCI_REQ_ABORTING); | 766 | sci_change_state(&ireq->sm, SCI_REQ_ABORTING); |
733 | return SCI_SUCCESS; | 767 | return SCI_SUCCESS; |
734 | case SCI_REQ_TASK_WAIT_TC_RESP: | 768 | case SCI_REQ_TASK_WAIT_TC_RESP: |
@@ -1194,8 +1228,8 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re | |||
1194 | { | 1228 | { |
1195 | struct isci_stp_request *stp_req = &ireq->stp.req; | 1229 | struct isci_stp_request *stp_req = &ireq->stp.req; |
1196 | struct scu_sgl_element_pair *sgl_pair; | 1230 | struct scu_sgl_element_pair *sgl_pair; |
1231 | enum sci_status status = SCI_SUCCESS; | ||
1197 | struct scu_sgl_element *sgl; | 1232 | struct scu_sgl_element *sgl; |
1198 | enum sci_status status; | ||
1199 | u32 offset; | 1233 | u32 offset; |
1200 | u32 len = 0; | 1234 | u32 len = 0; |
1201 | 1235 | ||
@@ -1249,7 +1283,7 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re | |||
1249 | */ | 1283 | */ |
1250 | static enum sci_status | 1284 | static enum sci_status |
1251 | sci_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req, | 1285 | sci_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req, |
1252 | u8 *data_buf, u32 len) | 1286 | u8 *data_buf, u32 len) |
1253 | { | 1287 | { |
1254 | struct isci_request *ireq; | 1288 | struct isci_request *ireq; |
1255 | u8 *src_addr; | 1289 | u8 *src_addr; |
@@ -1423,6 +1457,128 @@ static enum sci_status sci_stp_request_udma_general_frame_handler(struct isci_re | |||
1423 | return status; | 1457 | return status; |
1424 | } | 1458 | } |
1425 | 1459 | ||
1460 | static enum sci_status process_unsolicited_fis(struct isci_request *ireq, | ||
1461 | u32 frame_index) | ||
1462 | { | ||
1463 | struct isci_host *ihost = ireq->owning_controller; | ||
1464 | enum sci_status status; | ||
1465 | struct dev_to_host_fis *frame_header; | ||
1466 | u32 *frame_buffer; | ||
1467 | |||
1468 | status = sci_unsolicited_frame_control_get_header(&ihost->uf_control, | ||
1469 | frame_index, | ||
1470 | (void **)&frame_header); | ||
1471 | |||
1472 | if (status != SCI_SUCCESS) | ||
1473 | return status; | ||
1474 | |||
1475 | if (frame_header->fis_type != FIS_REGD2H) { | ||
1476 | dev_err(&ireq->isci_host->pdev->dev, | ||
1477 | "%s ERROR: invalid fis type 0x%X\n", | ||
1478 | __func__, frame_header->fis_type); | ||
1479 | return SCI_FAILURE; | ||
1480 | } | ||
1481 | |||
1482 | sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, | ||
1483 | frame_index, | ||
1484 | (void **)&frame_buffer); | ||
1485 | |||
1486 | sci_controller_copy_sata_response(&ireq->stp.rsp, | ||
1487 | (u32 *)frame_header, | ||
1488 | frame_buffer); | ||
1489 | |||
1490 | /* Frame has been decoded return it to the controller */ | ||
1491 | sci_controller_release_frame(ihost, frame_index); | ||
1492 | |||
1493 | return status; | ||
1494 | } | ||
1495 | |||
1496 | static enum sci_status atapi_d2h_reg_frame_handler(struct isci_request *ireq, | ||
1497 | u32 frame_index) | ||
1498 | { | ||
1499 | struct sas_task *task = isci_request_access_task(ireq); | ||
1500 | enum sci_status status; | ||
1501 | |||
1502 | status = process_unsolicited_fis(ireq, frame_index); | ||
1503 | |||
1504 | if (status == SCI_SUCCESS) { | ||
1505 | if (ireq->stp.rsp.status & ATA_ERR) | ||
1506 | status = SCI_IO_FAILURE_RESPONSE_VALID; | ||
1507 | } else { | ||
1508 | status = SCI_IO_FAILURE_RESPONSE_VALID; | ||
1509 | } | ||
1510 | |||
1511 | if (status != SCI_SUCCESS) { | ||
1512 | ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; | ||
1513 | ireq->sci_status = status; | ||
1514 | } else { | ||
1515 | ireq->scu_status = SCU_TASK_DONE_GOOD; | ||
1516 | ireq->sci_status = SCI_SUCCESS; | ||
1517 | } | ||
1518 | |||
1519 | /* the d2h ufi is the end of non-data commands */ | ||
1520 | if (task->data_dir == DMA_NONE) | ||
1521 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); | ||
1522 | |||
1523 | return status; | ||
1524 | } | ||
1525 | |||
1526 | static void scu_atapi_reconstruct_raw_frame_task_context(struct isci_request *ireq) | ||
1527 | { | ||
1528 | struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev); | ||
1529 | void *atapi_cdb = ireq->ttype_ptr.io_task_ptr->ata_task.atapi_packet; | ||
1530 | struct scu_task_context *task_context = ireq->tc; | ||
1531 | |||
1532 | /* fill in the SCU Task Context for a DATA fis containing CDB in Raw Frame | ||
1533 | * type. The TC for previous Packet fis was already there, we only need to | ||
1534 | * change the H2D fis content. | ||
1535 | */ | ||
1536 | memset(&ireq->stp.cmd, 0, sizeof(struct host_to_dev_fis)); | ||
1537 | memcpy(((u8 *)&ireq->stp.cmd + sizeof(u32)), atapi_cdb, ATAPI_CDB_LEN); | ||
1538 | memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context)); | ||
1539 | task_context->type.stp.fis_type = FIS_DATA; | ||
1540 | task_context->transfer_length_bytes = dev->cdb_len; | ||
1541 | } | ||
1542 | |||
1543 | static void scu_atapi_construct_task_context(struct isci_request *ireq) | ||
1544 | { | ||
1545 | struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev); | ||
1546 | struct sas_task *task = isci_request_access_task(ireq); | ||
1547 | struct scu_task_context *task_context = ireq->tc; | ||
1548 | int cdb_len = dev->cdb_len; | ||
1549 | |||
1550 | /* reference: SSTL 1.13.4.2 | ||
1551 | * task_type, sata_direction | ||
1552 | */ | ||
1553 | if (task->data_dir == DMA_TO_DEVICE) { | ||
1554 | task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT; | ||
1555 | task_context->sata_direction = 0; | ||
1556 | } else { | ||
1557 | /* todo: for NO_DATA command, we need to send out raw frame. */ | ||
1558 | task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN; | ||
1559 | task_context->sata_direction = 1; | ||
1560 | } | ||
1561 | |||
1562 | memset(&task_context->type.stp, 0, sizeof(task_context->type.stp)); | ||
1563 | task_context->type.stp.fis_type = FIS_DATA; | ||
1564 | |||
1565 | memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd)); | ||
1566 | memcpy(&ireq->stp.cmd.lbal, task->ata_task.atapi_packet, cdb_len); | ||
1567 | task_context->ssp_command_iu_length = cdb_len / sizeof(u32); | ||
1568 | |||
1569 | /* task phase is set to TX_CMD */ | ||
1570 | task_context->task_phase = 0x1; | ||
1571 | |||
1572 | /* retry counter */ | ||
1573 | task_context->stp_retry_count = 0; | ||
1574 | |||
1575 | /* data transfer size. */ | ||
1576 | task_context->transfer_length_bytes = task->total_xfer_len; | ||
1577 | |||
1578 | /* setup sgl */ | ||
1579 | sci_request_build_sgl(ireq); | ||
1580 | } | ||
1581 | |||
1426 | enum sci_status | 1582 | enum sci_status |
1427 | sci_io_request_frame_handler(struct isci_request *ireq, | 1583 | sci_io_request_frame_handler(struct isci_request *ireq, |
1428 | u32 frame_index) | 1584 | u32 frame_index) |
@@ -1835,6 +1991,24 @@ sci_io_request_frame_handler(struct isci_request *ireq, | |||
1835 | 1991 | ||
1836 | return status; | 1992 | return status; |
1837 | } | 1993 | } |
1994 | case SCI_REQ_ATAPI_WAIT_PIO_SETUP: { | ||
1995 | struct sas_task *task = isci_request_access_task(ireq); | ||
1996 | |||
1997 | sci_controller_release_frame(ihost, frame_index); | ||
1998 | ireq->target_device->working_request = ireq; | ||
1999 | if (task->data_dir == DMA_NONE) { | ||
2000 | sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_TC_COMP); | ||
2001 | scu_atapi_reconstruct_raw_frame_task_context(ireq); | ||
2002 | } else { | ||
2003 | sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H); | ||
2004 | scu_atapi_construct_task_context(ireq); | ||
2005 | } | ||
2006 | |||
2007 | sci_controller_continue_io(ireq); | ||
2008 | return SCI_SUCCESS; | ||
2009 | } | ||
2010 | case SCI_REQ_ATAPI_WAIT_D2H: | ||
2011 | return atapi_d2h_reg_frame_handler(ireq, frame_index); | ||
1838 | case SCI_REQ_ABORTING: | 2012 | case SCI_REQ_ABORTING: |
1839 | /* | 2013 | /* |
1840 | * TODO: Is it even possible to get an unsolicited frame in the | 2014 | * TODO: Is it even possible to get an unsolicited frame in the |
@@ -1966,6 +2140,112 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq, | |||
1966 | return SCI_SUCCESS; | 2140 | return SCI_SUCCESS; |
1967 | } | 2141 | } |
1968 | 2142 | ||
2143 | static enum sci_status atapi_raw_completion(struct isci_request *ireq, u32 completion_code, | ||
2144 | enum sci_base_request_states next) | ||
2145 | { | ||
2146 | enum sci_status status = SCI_SUCCESS; | ||
2147 | |||
2148 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
2149 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
2150 | ireq->scu_status = SCU_TASK_DONE_GOOD; | ||
2151 | ireq->sci_status = SCI_SUCCESS; | ||
2152 | sci_change_state(&ireq->sm, next); | ||
2153 | break; | ||
2154 | default: | ||
2155 | /* All other completion status cause the IO to be complete. | ||
2156 | * If a NAK was received, then it is up to the user to retry | ||
2157 | * the request. | ||
2158 | */ | ||
2159 | ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code); | ||
2160 | ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; | ||
2161 | |||
2162 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); | ||
2163 | break; | ||
2164 | } | ||
2165 | |||
2166 | return status; | ||
2167 | } | ||
2168 | |||
2169 | static enum sci_status atapi_data_tc_completion_handler(struct isci_request *ireq, | ||
2170 | u32 completion_code) | ||
2171 | { | ||
2172 | struct isci_remote_device *idev = ireq->target_device; | ||
2173 | struct dev_to_host_fis *d2h = &ireq->stp.rsp; | ||
2174 | enum sci_status status = SCI_SUCCESS; | ||
2175 | |||
2176 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
2177 | case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): | ||
2178 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); | ||
2179 | break; | ||
2180 | |||
2181 | case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): { | ||
2182 | u16 len = sci_req_tx_bytes(ireq); | ||
2183 | |||
2184 | /* likely non-error data underrrun, workaround missing | ||
2185 | * d2h frame from the controller | ||
2186 | */ | ||
2187 | if (d2h->fis_type != FIS_REGD2H) { | ||
2188 | d2h->fis_type = FIS_REGD2H; | ||
2189 | d2h->flags = (1 << 6); | ||
2190 | d2h->status = 0x50; | ||
2191 | d2h->error = 0; | ||
2192 | d2h->lbal = 0; | ||
2193 | d2h->byte_count_low = len & 0xff; | ||
2194 | d2h->byte_count_high = len >> 8; | ||
2195 | d2h->device = 0xa0; | ||
2196 | d2h->lbal_exp = 0; | ||
2197 | d2h->lbam_exp = 0; | ||
2198 | d2h->lbah_exp = 0; | ||
2199 | d2h->_r_a = 0; | ||
2200 | d2h->sector_count = 0x3; | ||
2201 | d2h->sector_count_exp = 0; | ||
2202 | d2h->_r_b = 0; | ||
2203 | d2h->_r_c = 0; | ||
2204 | d2h->_r_d = 0; | ||
2205 | } | ||
2206 | |||
2207 | ireq->scu_status = SCU_TASK_DONE_GOOD; | ||
2208 | ireq->sci_status = SCI_SUCCESS_IO_DONE_EARLY; | ||
2209 | status = ireq->sci_status; | ||
2210 | |||
2211 | /* the hw will have suspended the rnc, so complete the | ||
2212 | * request upon pending resume | ||
2213 | */ | ||
2214 | sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR); | ||
2215 | break; | ||
2216 | } | ||
2217 | case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT): | ||
2218 | /* In this case, there is no UF coming after. | ||
2219 | * compelte the IO now. | ||
2220 | */ | ||
2221 | ireq->scu_status = SCU_TASK_DONE_GOOD; | ||
2222 | ireq->sci_status = SCI_SUCCESS; | ||
2223 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); | ||
2224 | break; | ||
2225 | |||
2226 | default: | ||
2227 | if (d2h->fis_type == FIS_REGD2H) { | ||
2228 | /* UF received change the device state to ATAPI_ERROR */ | ||
2229 | status = ireq->sci_status; | ||
2230 | sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR); | ||
2231 | } else { | ||
2232 | /* If receiving any non-sucess TC status, no UF | ||
2233 | * received yet, then an UF for the status fis | ||
2234 | * is coming after (XXX: suspect this is | ||
2235 | * actually a protocol error or a bug like the | ||
2236 | * DONE_UNEXP_FIS case) | ||
2237 | */ | ||
2238 | ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; | ||
2239 | ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; | ||
2240 | |||
2241 | sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H); | ||
2242 | } | ||
2243 | break; | ||
2244 | } | ||
2245 | |||
2246 | return status; | ||
2247 | } | ||
2248 | |||
1969 | enum sci_status | 2249 | enum sci_status |
1970 | sci_io_request_tc_completion(struct isci_request *ireq, | 2250 | sci_io_request_tc_completion(struct isci_request *ireq, |
1971 | u32 completion_code) | 2251 | u32 completion_code) |
@@ -2017,6 +2297,17 @@ sci_io_request_tc_completion(struct isci_request *ireq, | |||
2017 | return request_aborting_state_tc_event(ireq, | 2297 | return request_aborting_state_tc_event(ireq, |
2018 | completion_code); | 2298 | completion_code); |
2019 | 2299 | ||
2300 | case SCI_REQ_ATAPI_WAIT_H2D: | ||
2301 | return atapi_raw_completion(ireq, completion_code, | ||
2302 | SCI_REQ_ATAPI_WAIT_PIO_SETUP); | ||
2303 | |||
2304 | case SCI_REQ_ATAPI_WAIT_TC_COMP: | ||
2305 | return atapi_raw_completion(ireq, completion_code, | ||
2306 | SCI_REQ_ATAPI_WAIT_D2H); | ||
2307 | |||
2308 | case SCI_REQ_ATAPI_WAIT_D2H: | ||
2309 | return atapi_data_tc_completion_handler(ireq, completion_code); | ||
2310 | |||
2020 | default: | 2311 | default: |
2021 | dev_warn(&ihost->pdev->dev, | 2312 | dev_warn(&ihost->pdev->dev, |
2022 | "%s: SCIC IO Request given task completion " | 2313 | "%s: SCIC IO Request given task completion " |
@@ -2423,6 +2714,8 @@ static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_ | |||
2423 | */ | 2714 | */ |
2424 | if (fis->status & ATA_DF) | 2715 | if (fis->status & ATA_DF) |
2425 | ts->stat = SAS_PROTO_RESPONSE; | 2716 | ts->stat = SAS_PROTO_RESPONSE; |
2717 | else if (fis->status & ATA_ERR) | ||
2718 | ts->stat = SAM_STAT_CHECK_CONDITION; | ||
2426 | else | 2719 | else |
2427 | ts->stat = SAM_STAT_GOOD; | 2720 | ts->stat = SAM_STAT_GOOD; |
2428 | 2721 | ||
@@ -2782,6 +3075,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm) | |||
2782 | { | 3075 | { |
2783 | struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); | 3076 | struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); |
2784 | struct domain_device *dev = ireq->target_device->domain_dev; | 3077 | struct domain_device *dev = ireq->target_device->domain_dev; |
3078 | enum sci_base_request_states state; | ||
2785 | struct sas_task *task; | 3079 | struct sas_task *task; |
2786 | 3080 | ||
2787 | /* XXX as hch said always creating an internal sas_task for tmf | 3081 | /* XXX as hch said always creating an internal sas_task for tmf |
@@ -2793,26 +3087,30 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm) | |||
2793 | * substates | 3087 | * substates |
2794 | */ | 3088 | */ |
2795 | if (!task && dev->dev_type == SAS_END_DEV) { | 3089 | if (!task && dev->dev_type == SAS_END_DEV) { |
2796 | sci_change_state(sm, SCI_REQ_TASK_WAIT_TC_COMP); | 3090 | state = SCI_REQ_TASK_WAIT_TC_COMP; |
2797 | } else if (!task && | 3091 | } else if (!task && |
2798 | (isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high || | 3092 | (isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high || |
2799 | isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) { | 3093 | isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) { |
2800 | sci_change_state(sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED); | 3094 | state = SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED; |
2801 | } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { | 3095 | } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { |
2802 | sci_change_state(sm, SCI_REQ_SMP_WAIT_RESP); | 3096 | state = SCI_REQ_SMP_WAIT_RESP; |
2803 | } else if (task && sas_protocol_ata(task->task_proto) && | 3097 | } else if (task && sas_protocol_ata(task->task_proto) && |
2804 | !task->ata_task.use_ncq) { | 3098 | !task->ata_task.use_ncq) { |
2805 | u32 state; | 3099 | if (dev->sata_dev.command_set == ATAPI_COMMAND_SET && |
2806 | 3100 | task->ata_task.fis.command == ATA_CMD_PACKET) { | |
2807 | if (task->data_dir == DMA_NONE) | 3101 | state = SCI_REQ_ATAPI_WAIT_H2D; |
3102 | } else if (task->data_dir == DMA_NONE) { | ||
2808 | state = SCI_REQ_STP_NON_DATA_WAIT_H2D; | 3103 | state = SCI_REQ_STP_NON_DATA_WAIT_H2D; |
2809 | else if (task->ata_task.dma_xfer) | 3104 | } else if (task->ata_task.dma_xfer) { |
2810 | state = SCI_REQ_STP_UDMA_WAIT_TC_COMP; | 3105 | state = SCI_REQ_STP_UDMA_WAIT_TC_COMP; |
2811 | else /* PIO */ | 3106 | } else /* PIO */ { |
2812 | state = SCI_REQ_STP_PIO_WAIT_H2D; | 3107 | state = SCI_REQ_STP_PIO_WAIT_H2D; |
2813 | 3108 | } | |
2814 | sci_change_state(sm, state); | 3109 | } else { |
3110 | /* SSP or NCQ are fully accelerated, no substates */ | ||
3111 | return; | ||
2815 | } | 3112 | } |
3113 | sci_change_state(sm, state); | ||
2816 | } | 3114 | } |
2817 | 3115 | ||
2818 | static void sci_request_completed_state_enter(struct sci_base_state_machine *sm) | 3116 | static void sci_request_completed_state_enter(struct sci_base_state_machine *sm) |
@@ -2904,6 +3202,10 @@ static const struct sci_base_state sci_request_state_table[] = { | |||
2904 | [SCI_REQ_TASK_WAIT_TC_RESP] = { }, | 3202 | [SCI_REQ_TASK_WAIT_TC_RESP] = { }, |
2905 | [SCI_REQ_SMP_WAIT_RESP] = { }, | 3203 | [SCI_REQ_SMP_WAIT_RESP] = { }, |
2906 | [SCI_REQ_SMP_WAIT_TC_COMP] = { }, | 3204 | [SCI_REQ_SMP_WAIT_TC_COMP] = { }, |
3205 | [SCI_REQ_ATAPI_WAIT_H2D] = { }, | ||
3206 | [SCI_REQ_ATAPI_WAIT_PIO_SETUP] = { }, | ||
3207 | [SCI_REQ_ATAPI_WAIT_D2H] = { }, | ||
3208 | [SCI_REQ_ATAPI_WAIT_TC_COMP] = { }, | ||
2907 | [SCI_REQ_COMPLETED] = { | 3209 | [SCI_REQ_COMPLETED] = { |
2908 | .enter_state = sci_request_completed_state_enter, | 3210 | .enter_state = sci_request_completed_state_enter, |
2909 | }, | 3211 | }, |
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 58d70b6606ef..f720b97b7bb5 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h | |||
@@ -96,7 +96,6 @@ enum sci_request_protocol { | |||
96 | * to wait for another fis or if the transfer is complete. Upon | 96 | * to wait for another fis or if the transfer is complete. Upon |
97 | * receipt of a d2h fis this will be the status field of that fis. | 97 | * receipt of a d2h fis this will be the status field of that fis. |
98 | * @sgl - track pio transfer progress as we iterate through the sgl | 98 | * @sgl - track pio transfer progress as we iterate through the sgl |
99 | * @device_cdb_len - atapi device advertises it's transfer constraints at setup | ||
100 | */ | 99 | */ |
101 | struct isci_stp_request { | 100 | struct isci_stp_request { |
102 | u32 pio_len; | 101 | u32 pio_len; |
@@ -107,7 +106,6 @@ struct isci_stp_request { | |||
107 | u8 set; | 106 | u8 set; |
108 | u32 offset; | 107 | u32 offset; |
109 | } sgl; | 108 | } sgl; |
110 | u32 device_cdb_len; | ||
111 | }; | 109 | }; |
112 | 110 | ||
113 | struct isci_request { | 111 | struct isci_request { |
@@ -249,6 +247,32 @@ enum sci_base_request_states { | |||
249 | SCI_REQ_STP_PIO_DATA_OUT, | 247 | SCI_REQ_STP_PIO_DATA_OUT, |
250 | 248 | ||
251 | /* | 249 | /* |
250 | * While in this state the IO request object is waiting for the TC | ||
251 | * completion notification for the H2D Register FIS | ||
252 | */ | ||
253 | SCI_REQ_ATAPI_WAIT_H2D, | ||
254 | |||
255 | /* | ||
256 | * While in this state the IO request object is waiting for either a | ||
257 | * PIO Setup. | ||
258 | */ | ||
259 | SCI_REQ_ATAPI_WAIT_PIO_SETUP, | ||
260 | |||
261 | /* | ||
262 | * The non-data IO transit to this state in this state after receiving | ||
263 | * TC completion. While in this state IO request object is waiting for | ||
264 | * D2H status frame as UF. | ||
265 | */ | ||
266 | SCI_REQ_ATAPI_WAIT_D2H, | ||
267 | |||
268 | /* | ||
269 | * When transmitting raw frames hardware reports task context completion | ||
270 | * after every frame submission, so in the non-accelerated case we need | ||
271 | * to expect the completion for the "cdb" frame. | ||
272 | */ | ||
273 | SCI_REQ_ATAPI_WAIT_TC_COMP, | ||
274 | |||
275 | /* | ||
252 | * The AWAIT_TC_COMPLETION sub-state indicates that the started raw | 276 | * The AWAIT_TC_COMPLETION sub-state indicates that the started raw |
253 | * task management request is waiting for the transmission of the | 277 | * task management request is waiting for the transmission of the |
254 | * initial frame (i.e. command, task, etc.). | 278 | * initial frame (i.e. command, task, etc.). |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index ebd1417339e9..b2c4a7731656 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -801,7 +801,7 @@ void sas_slave_destroy(struct scsi_device *scsi_dev) | |||
801 | struct domain_device *dev = sdev_to_domain_dev(scsi_dev); | 801 | struct domain_device *dev = sdev_to_domain_dev(scsi_dev); |
802 | 802 | ||
803 | if (dev_is_sata(dev)) | 803 | if (dev_is_sata(dev)) |
804 | dev->sata_dev.ap->link.device[0].class = ATA_DEV_NONE; | 804 | sas_to_ata_dev(dev)->class = ATA_DEV_NONE; |
805 | } | 805 | } |
806 | 806 | ||
807 | int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason) | 807 | int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason) |
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index d455fa96dc8c..c4b7cd0b85e5 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
@@ -389,6 +389,11 @@ sdev_to_domain_dev(struct scsi_device *sdev) { | |||
389 | return starget_to_domain_dev(sdev->sdev_target); | 389 | return starget_to_domain_dev(sdev->sdev_target); |
390 | } | 390 | } |
391 | 391 | ||
392 | static inline struct ata_device *sas_to_ata_dev(struct domain_device *dev) | ||
393 | { | ||
394 | return &dev->sata_dev.ap->link.device[0]; | ||
395 | } | ||
396 | |||
392 | static inline struct domain_device * | 397 | static inline struct domain_device * |
393 | cmd_to_domain_dev(struct scsi_cmnd *cmd) | 398 | cmd_to_domain_dev(struct scsi_cmnd *cmd) |
394 | { | 399 | { |