* [GIT PATCH 0/5] isci updates for 3.2
@ 2011-09-29 1:47 Dan Williams
2011-09-29 1:47 ` [PATCH 1/5] isci: atapi support Dan Williams
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Dan Williams @ 2011-09-29 1:47 UTC (permalink / raw)
To: JBottomley; +Cc: dmilburn, dave.jiang, hare, linux-scsi
This series functionally depends on the pending libsas fix for ata lun
scanning. For convenience those updates have been queued to
"git://github.com:djbw/linux.git libsas".
The following changes since commit 7705375e944ea94be7941b740efd0a77bb109cb1:
libsas: remove unused ata_task_resp fields (2011-09-28 18:06:10 -0700)
are available in the git repository at:
git://github.com:djbw/linux.git isci
The prominent update in this set is atapi support. The rest are small
bug fixes and feature enhancements. More error handling and command
termination fixes are in the works.
Dan Williams (2):
isci: atapi support
isci: export phy events via ->lldd_control_phy()
Jeff Skirvin (3):
isci: SATA/STP I/O is only returned in the normal path to libsas
isci: fix decode of DONE_CRC_ERR TC completion status
isci: The port state should be set to stopping on the last phy.
drivers/scsi/aic94xx/aic94xx_scb.c | 1 +
drivers/scsi/isci/phy.c | 11 ++
drivers/scsi/isci/port.c | 2 +-
drivers/scsi/isci/remote_device.c | 24 +++
drivers/scsi/isci/remote_device.h | 9 +
drivers/scsi/isci/request.c | 330 +++++++++++++++++++++++++++++++++--
drivers/scsi/isci/request.h | 28 +++-
drivers/scsi/isci/task.h | 19 ++
drivers/scsi/libsas/sas_init.c | 13 +-
drivers/scsi/libsas/sas_scsi_host.c | 2 +-
drivers/scsi/mvsas/mv_sas.c | 2 +-
drivers/scsi/pm8001/pm8001_sas.c | 2 +-
include/scsi/libsas.h | 5 +
include/scsi/sas.h | 1 +
14 files changed, 424 insertions(+), 25 deletions(-)
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/5] isci: atapi support
2011-09-29 1:47 [GIT PATCH 0/5] isci updates for 3.2 Dan Williams
@ 2011-09-29 1:47 ` Dan Williams
2011-09-29 13:45 ` Jeff Garzik
2011-10-01 1:49 ` Dan Williams
2011-09-29 1:47 ` [PATCH 2/5] isci: SATA/STP I/O is only returned in the normal path to libsas Dan Williams
` (5 subsequent siblings)
6 siblings, 2 replies; 10+ messages in thread
From: Dan Williams @ 2011-09-29 1:47 UTC (permalink / raw)
To: JBottomley; +Cc: Maciej Trela, dmilburn, dave.jiang, hare, linux-scsi
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>
---
drivers/scsi/isci/remote_device.c | 24 +++
drivers/scsi/isci/remote_device.h | 9 +
drivers/scsi/isci/request.c | 327 ++++++++++++++++++++++++++++++++++-
drivers/scsi/isci/request.h | 28 +++
drivers/scsi/libsas/sas_scsi_host.c | 2
include/scsi/libsas.h | 5 +
6 files changed, 379 insertions(+), 16 deletions(-)
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index b6e6368..fbf9ce2 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)
}
}
+/*
+ * called once the remote node context has transisitioned to a ready
+ * state (after suspending RX and/or TX due to early D2H fis)
+ */
+static void atapi_remote_device_resume_done(void *_dev)
+{
+ struct isci_remote_device *idev = _dev;
+ struct isci_request *ireq = idev->working_request;
+
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+}
+
enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
u32 event_code)
{
@@ -432,6 +444,16 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
if (status != SCI_SUCCESS)
return status;
+ if (state == SCI_STP_DEV_ATAPI_ERROR) {
+ /* For ATAPI error state resume the RNC right away. */
+ if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
+ scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
+ return sci_remote_node_context_resume(&idev->rnc,
+ atapi_remote_device_resume_done,
+ idev);
+ }
+ }
+
if (state == SCI_STP_DEV_IDLE) {
/* 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,
case SCI_STP_DEV_CMD:
case SCI_STP_DEV_NCQ:
case SCI_STP_DEV_NCQ_ERROR:
+ case SCI_STP_DEV_ATAPI_ERROR:
status = common_complete_io(iport, idev, ireq);
if (status != SCI_SUCCESS)
break;
@@ -1020,6 +1043,7 @@ static const struct sci_base_state sci_remote_device_state_table[] = {
[SCI_STP_DEV_NCQ_ERROR] = {
.enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter,
},
+ [SCI_STP_DEV_ATAPI_ERROR] = { },
[SCI_STP_DEV_AWAIT_RESET] = { },
[SCI_SMP_DEV_IDLE] = {
.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 57ccfc3..e1747ea 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -244,6 +244,15 @@ enum sci_remote_device_states {
SCI_STP_DEV_NCQ_ERROR,
/**
+ * This is the ATAPI error state for the STP ATAPI remote device.
+ * This state is entered when ATAPI device sends error status FIS
+ * without data while the device object is in CMD state.
+ * A suspension event is expected in this state.
+ * The device object will resume right away.
+ */
+ SCI_STP_DEV_ATAPI_ERROR,
+
+ /**
* This is the READY substate indicates the device is waiting for the RESET task
* coming to be recovered from certain hardware specific error.
*/
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index b5d3a8c..2bf072f 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,
}
}
+static void sci_atapi_construct(struct isci_request *ireq)
+{
+ struct host_to_dev_fis *h2d_fis = &ireq->stp.cmd;
+ struct sas_task *task;
+
+ /* To simplify the implementation we take advantage of the
+ * silicon's partial acceleration of atapi protocol (dma data
+ * transfers), so we promote all commands to dma protocol. This
+ * breaks compatibility with ATA_HORKAGE_ATAPI_MOD16_DMA drives.
+ */
+ h2d_fis->features |= ATAPI_PKT_DMA;
+
+ scu_stp_raw_request_construct_task_context(ireq);
+
+ task = isci_request_access_task(ireq);
+ if (task->data_dir == DMA_NONE)
+ task->total_xfer_len = 0;
+ /* clear the response so we can detect arrivial of an
+ * unsolicited h2d fis
+ */
+ ireq->stp.rsp.fis_type = 0;
+}
static enum sci_status
sci_io_request_construct_sata(struct isci_request *ireq,
@@ -491,6 +513,7 @@ sci_io_request_construct_sata(struct isci_request *ireq,
{
enum sci_status status = SCI_SUCCESS;
struct sas_task *task = isci_request_access_task(ireq);
+ struct domain_device *dev = ireq->target_device->domain_dev;
/* check for management protocols */
if (ireq->ttype == tmf_task) {
@@ -519,6 +542,13 @@ sci_io_request_construct_sata(struct isci_request *ireq,
}
+ /* ATAPI */
+ if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
+ task->ata_task.fis.command == ATA_CMD_PACKET) {
+ sci_atapi_construct(ireq);
+ return SCI_SUCCESS;
+ }
+
/* non data */
if (task->data_dir == DMA_NONE) {
scu_stp_raw_request_construct_task_context(ireq);
@@ -627,7 +657,7 @@ enum sci_status sci_task_request_construct_sata(struct isci_request *ireq)
/**
* sci_req_tx_bytes - bytes transferred when reply underruns request
- * @sci_req: request that was terminated early
+ * @ireq: request that was terminated early
*/
#define SCU_TASK_CONTEXT_SRAM 0x200000
static u32 sci_req_tx_bytes(struct isci_request *ireq)
@@ -729,6 +759,10 @@ sci_io_request_terminate(struct isci_request *ireq)
case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED:
case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG:
case SCI_REQ_STP_SOFT_RESET_WAIT_D2H:
+ case SCI_REQ_ATAPI_WAIT_H2D:
+ case SCI_REQ_ATAPI_WAIT_PIO_SETUP:
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ case SCI_REQ_ATAPI_WAIT_TC_COMP:
sci_change_state(&ireq->sm, SCI_REQ_ABORTING);
return SCI_SUCCESS;
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
{
struct isci_stp_request *stp_req = &ireq->stp.req;
struct scu_sgl_element_pair *sgl_pair;
+ enum sci_status status = SCI_SUCCESS;
struct scu_sgl_element *sgl;
- enum sci_status status;
u32 offset;
u32 len = 0;
@@ -1249,7 +1283,7 @@ static enum sci_status sci_stp_request_pio_data_out_transmit_data(struct isci_re
*/
static enum sci_status
sci_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req,
- u8 *data_buf, u32 len)
+ u8 *data_buf, u32 len)
{
struct isci_request *ireq;
u8 *src_addr;
@@ -1423,6 +1457,128 @@ static enum sci_status sci_stp_request_udma_general_frame_handler(struct isci_re
return status;
}
+static enum sci_status process_unsolicited_fis(struct isci_request *ireq,
+ u32 frame_index)
+{
+ struct isci_host *ihost = ireq->owning_controller;
+ enum sci_status status;
+ struct dev_to_host_fis *frame_header;
+ u32 *frame_buffer;
+
+ status = sci_unsolicited_frame_control_get_header(&ihost->uf_control,
+ frame_index,
+ (void **)&frame_header);
+
+ if (status != SCI_SUCCESS)
+ return status;
+
+ if (frame_header->fis_type != FIS_REGD2H) {
+ dev_err(&ireq->isci_host->pdev->dev,
+ "%s ERROR: invalid fis type 0x%X\n",
+ __func__, frame_header->fis_type);
+ return SCI_FAILURE;
+ }
+
+ sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
+ frame_index,
+ (void **)&frame_buffer);
+
+ sci_controller_copy_sata_response(&ireq->stp.rsp,
+ (u32 *)frame_header,
+ frame_buffer);
+
+ /* Frame has been decoded return it to the controller */
+ sci_controller_release_frame(ihost, frame_index);
+
+ return status;
+}
+
+static enum sci_status atapi_d2h_reg_frame_handler(struct isci_request *ireq,
+ u32 frame_index)
+{
+ struct sas_task *task = isci_request_access_task(ireq);
+ enum sci_status status;
+
+ status = process_unsolicited_fis(ireq, frame_index);
+
+ if (status == SCI_SUCCESS) {
+ if (ireq->stp.rsp.status & ATA_ERR)
+ status = SCI_IO_FAILURE_RESPONSE_VALID;
+ } else {
+ status = SCI_IO_FAILURE_RESPONSE_VALID;
+ }
+
+ if (status != SCI_SUCCESS) {
+ ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
+ ireq->sci_status = status;
+ } else {
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ }
+
+ /* the d2h ufi is the end of non-data commands */
+ if (task->data_dir == DMA_NONE)
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+
+ return status;
+}
+
+static void scu_atapi_reconstruct_raw_frame_task_context(struct isci_request *ireq)
+{
+ struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev);
+ void *atapi_cdb = ireq->ttype_ptr.io_task_ptr->ata_task.atapi_packet;
+ struct scu_task_context *task_context = ireq->tc;
+
+ /* fill in the SCU Task Context for a DATA fis containing CDB in Raw Frame
+ * type. The TC for previous Packet fis was already there, we only need to
+ * change the H2D fis content.
+ */
+ memset(&ireq->stp.cmd, 0, sizeof(struct host_to_dev_fis));
+ memcpy(((u8 *)&ireq->stp.cmd + sizeof(u32)), atapi_cdb, ATAPI_CDB_LEN);
+ memset(&(task_context->type.stp), 0, sizeof(struct stp_task_context));
+ task_context->type.stp.fis_type = FIS_DATA;
+ task_context->transfer_length_bytes = dev->cdb_len;
+}
+
+static void scu_atapi_construct_task_context(struct isci_request *ireq)
+{
+ struct ata_device *dev = sas_to_ata_dev(ireq->target_device->domain_dev);
+ struct sas_task *task = isci_request_access_task(ireq);
+ struct scu_task_context *task_context = ireq->tc;
+ int cdb_len = dev->cdb_len;
+
+ /* reference: SSTL 1.13.4.2
+ * task_type, sata_direction
+ */
+ if (task->data_dir == DMA_TO_DEVICE) {
+ task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
+ task_context->sata_direction = 0;
+ } else {
+ /* todo: for NO_DATA command, we need to send out raw frame. */
+ task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
+ task_context->sata_direction = 1;
+ }
+
+ memset(&task_context->type.stp, 0, sizeof(task_context->type.stp));
+ task_context->type.stp.fis_type = FIS_DATA;
+
+ memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd));
+ memcpy(&ireq->stp.cmd.lbal, task->ata_task.atapi_packet, cdb_len);
+ task_context->ssp_command_iu_length = cdb_len / sizeof(u32);
+
+ /* task phase is set to TX_CMD */
+ task_context->task_phase = 0x1;
+
+ /* retry counter */
+ task_context->stp_retry_count = 0;
+
+ /* data transfer size. */
+ task_context->transfer_length_bytes = task->total_xfer_len;
+
+ /* setup sgl */
+ sci_request_build_sgl(ireq);
+}
+
enum sci_status
sci_io_request_frame_handler(struct isci_request *ireq,
u32 frame_index)
@@ -1833,6 +1989,24 @@ sci_io_request_frame_handler(struct isci_request *ireq,
return status;
}
+ case SCI_REQ_ATAPI_WAIT_PIO_SETUP: {
+ struct sas_task *task = isci_request_access_task(ireq);
+
+ sci_controller_release_frame(ihost, frame_index);
+ ireq->target_device->working_request = ireq;
+ if (task->data_dir == DMA_NONE) {
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_TC_COMP);
+ scu_atapi_reconstruct_raw_frame_task_context(ireq);
+ } else {
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H);
+ scu_atapi_construct_task_context(ireq);
+ }
+
+ sci_controller_continue_io(ireq);
+ return SCI_SUCCESS;
+ }
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ return atapi_d2h_reg_frame_handler(ireq, frame_index);
case SCI_REQ_ABORTING:
/*
* TODO: Is it even possible to get an unsolicited frame in the
@@ -1964,6 +2138,112 @@ stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq,
return SCI_SUCCESS;
}
+static enum sci_status atapi_raw_completion(struct isci_request *ireq, u32 completion_code,
+ enum sci_base_request_states next)
+{
+ enum sci_status status = SCI_SUCCESS;
+
+ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+ case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ sci_change_state(&ireq->sm, next);
+ break;
+ default:
+ /* All other completion status cause the IO to be complete.
+ * If a NAK was received, then it is up to the user to retry
+ * the request.
+ */
+ ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
+ ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
+
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+ }
+
+ return status;
+}
+
+static enum sci_status atapi_data_tc_completion_handler(struct isci_request *ireq,
+ u32 completion_code)
+{
+ struct isci_remote_device *idev = ireq->target_device;
+ struct dev_to_host_fis *d2h = &ireq->stp.rsp;
+ enum sci_status status = SCI_SUCCESS;
+
+ switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
+ case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+
+ case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): {
+ u16 len = sci_req_tx_bytes(ireq);
+
+ /* likely non-error data underrrun, workaround missing
+ * d2h frame from the controller
+ */
+ if (d2h->fis_type != FIS_REGD2H) {
+ d2h->fis_type = FIS_REGD2H;
+ d2h->flags = (1 << 6);
+ d2h->status = 0x50;
+ d2h->error = 0;
+ d2h->lbal = 0;
+ d2h->byte_count_low = len & 0xff;
+ d2h->byte_count_high = len >> 8;
+ d2h->device = 0xa0;
+ d2h->lbal_exp = 0;
+ d2h->lbam_exp = 0;
+ d2h->lbah_exp = 0;
+ d2h->_r_a = 0;
+ d2h->sector_count = 0x3;
+ d2h->sector_count_exp = 0;
+ d2h->_r_b = 0;
+ d2h->_r_c = 0;
+ d2h->_r_d = 0;
+ }
+
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS_IO_DONE_EARLY;
+ status = ireq->sci_status;
+
+ /* the hw will have suspended the rnc, so complete the
+ * request upon pending resume
+ */
+ sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR);
+ break;
+ }
+ case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
+ /* In this case, there is no UF coming after.
+ * compelte the IO now.
+ */
+ ireq->scu_status = SCU_TASK_DONE_GOOD;
+ ireq->sci_status = SCI_SUCCESS;
+ sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
+ break;
+
+ default:
+ if (d2h->fis_type == FIS_REGD2H) {
+ /* UF received change the device state to ATAPI_ERROR */
+ status = ireq->sci_status;
+ sci_change_state(&idev->sm, SCI_STP_DEV_ATAPI_ERROR);
+ } else {
+ /* If receiving any non-sucess TC status, no UF
+ * received yet, then an UF for the status fis
+ * is coming after (XXX: suspect this is
+ * actually a protocol error or a bug like the
+ * DONE_UNEXP_FIS case)
+ */
+ ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE;
+ ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID;
+
+ sci_change_state(&ireq->sm, SCI_REQ_ATAPI_WAIT_D2H);
+ }
+ break;
+ }
+
+ return status;
+}
+
enum sci_status
sci_io_request_tc_completion(struct isci_request *ireq,
u32 completion_code)
@@ -2015,6 +2295,17 @@ sci_io_request_tc_completion(struct isci_request *ireq,
return request_aborting_state_tc_event(ireq,
completion_code);
+ case SCI_REQ_ATAPI_WAIT_H2D:
+ return atapi_raw_completion(ireq, completion_code,
+ SCI_REQ_ATAPI_WAIT_PIO_SETUP);
+
+ case SCI_REQ_ATAPI_WAIT_TC_COMP:
+ return atapi_raw_completion(ireq, completion_code,
+ SCI_REQ_ATAPI_WAIT_D2H);
+
+ case SCI_REQ_ATAPI_WAIT_D2H:
+ return atapi_data_tc_completion_handler(ireq, completion_code);
+
default:
dev_warn(&ihost->pdev->dev,
"%s: SCIC IO Request given task completion "
@@ -2421,6 +2712,8 @@ static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_
*/
if (fis->status & ATA_DF)
ts->stat = SAS_PROTO_RESPONSE;
+ else if (fis->status & ATA_ERR)
+ ts->stat = SAM_STAT_CHECK_CONDITION;
else
ts->stat = SAM_STAT_GOOD;
@@ -2791,6 +3084,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
{
struct isci_request *ireq = container_of(sm, typeof(*ireq), sm);
struct domain_device *dev = ireq->target_device->domain_dev;
+ enum sci_base_request_states state;
struct sas_task *task;
/* XXX as hch said always creating an internal sas_task for tmf
@@ -2802,26 +3096,29 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
* substates
*/
if (!task && dev->dev_type == SAS_END_DEV) {
- sci_change_state(sm, SCI_REQ_TASK_WAIT_TC_COMP);
+ state = SCI_REQ_TASK_WAIT_TC_COMP;
} else if (!task &&
(isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high ||
isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) {
- sci_change_state(sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED);
+ state = SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED;
} else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
- sci_change_state(sm, SCI_REQ_SMP_WAIT_RESP);
+ state = SCI_REQ_SMP_WAIT_RESP;
} else if (task && sas_protocol_ata(task->task_proto) &&
!task->ata_task.use_ncq) {
- u32 state;
-
- if (task->data_dir == DMA_NONE)
+ if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
+ task->ata_task.fis.command == ATA_CMD_PACKET) {
+ state = SCI_REQ_ATAPI_WAIT_H2D;
+ } else if (task->data_dir == DMA_NONE) {
state = SCI_REQ_STP_NON_DATA_WAIT_H2D;
- else if (task->ata_task.dma_xfer)
+ } else if (task->ata_task.dma_xfer) {
state = SCI_REQ_STP_UDMA_WAIT_TC_COMP;
- else /* PIO */
+ } else /* PIO */ {
state = SCI_REQ_STP_PIO_WAIT_H2D;
-
- sci_change_state(sm, state);
+ }
+ } else {
+ BUG();
}
+ sci_change_state(sm, state);
}
static void sci_request_completed_state_enter(struct sci_base_state_machine *sm)
@@ -2913,6 +3210,10 @@ static const struct sci_base_state sci_request_state_table[] = {
[SCI_REQ_TASK_WAIT_TC_RESP] = { },
[SCI_REQ_SMP_WAIT_RESP] = { },
[SCI_REQ_SMP_WAIT_TC_COMP] = { },
+ [SCI_REQ_ATAPI_WAIT_H2D] = { },
+ [SCI_REQ_ATAPI_WAIT_PIO_SETUP] = { },
+ [SCI_REQ_ATAPI_WAIT_D2H] = { },
+ [SCI_REQ_ATAPI_WAIT_TC_COMP] = { },
[SCI_REQ_COMPLETED] = {
.enter_state = sci_request_completed_state_enter,
},
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
index 7a1d5a9..1fd4f07 100644
--- a/drivers/scsi/isci/request.h
+++ b/drivers/scsi/isci/request.h
@@ -96,7 +96,6 @@ enum sci_request_protocol {
* to wait for another fis or if the transfer is complete. Upon
* receipt of a d2h fis this will be the status field of that fis.
* @sgl - track pio transfer progress as we iterate through the sgl
- * @device_cdb_len - atapi device advertises it's transfer constraints at setup
*/
struct isci_stp_request {
u32 pio_len;
@@ -107,7 +106,6 @@ struct isci_stp_request {
u8 set;
u32 offset;
} sgl;
- u32 device_cdb_len;
};
struct isci_request {
@@ -252,6 +250,32 @@ enum sci_base_request_states {
SCI_REQ_STP_PIO_DATA_OUT,
/*
+ * While in this state the IO request object is waiting for the TC
+ * completion notification for the H2D Register FIS
+ */
+ SCI_REQ_ATAPI_WAIT_H2D,
+
+ /*
+ * While in this state the IO request object is waiting for either a
+ * PIO Setup.
+ */
+ SCI_REQ_ATAPI_WAIT_PIO_SETUP,
+
+ /*
+ * The non-data IO transit to this state in this state after receiving
+ * TC completion. While in this state IO request object is waiting for
+ * D2H status frame as UF.
+ */
+ SCI_REQ_ATAPI_WAIT_D2H,
+
+ /*
+ * When transmitting raw frames hardware reports task context completion
+ * after every frame submission, so in the non-accelerated case we need
+ * to expect the completion for the "cdb" frame.
+ */
+ SCI_REQ_ATAPI_WAIT_TC_COMP,
+
+ /*
* The AWAIT_TC_COMPLETION sub-state indicates that the started raw
* task management request is waiting for the transmission of the
* 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 ebd1417..b2c4a77 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)
struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
if (dev_is_sata(dev))
- dev->sata_dev.ap->link.device[0].class = ATA_DEV_NONE;
+ sas_to_ata_dev(dev)->class = ATA_DEV_NONE;
}
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 0d78bfa..6d5185c 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -383,6 +383,11 @@ sdev_to_domain_dev(struct scsi_device *sdev) {
return starget_to_domain_dev(sdev->sdev_target);
}
+static inline struct ata_device *sas_to_ata_dev(struct domain_device *dev)
+{
+ return &dev->sata_dev.ap->link.device[0];
+}
+
static inline struct domain_device *
cmd_to_domain_dev(struct scsi_cmnd *cmd)
{
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/5] isci: SATA/STP I/O is only returned in the normal path to libsas
2011-09-29 1:47 [GIT PATCH 0/5] isci updates for 3.2 Dan Williams
2011-09-29 1:47 ` [PATCH 1/5] isci: atapi support Dan Williams
@ 2011-09-29 1:47 ` Dan Williams
2011-09-29 1:47 ` [PATCH 3/5] isci: fix decode of DONE_CRC_ERR TC completion status Dan Williams
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Dan Williams @ 2011-09-29 1:47 UTC (permalink / raw)
To: JBottomley; +Cc: dmilburn, dave.jiang, hare, linux-scsi, Jeff Skirvin
From: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Since libsas has it's own means to escalate SATA/STP device error
handling depending on task status codes, return all SATA/STP I/O
on the normal path.
i.e. skip sas_task_abort() and let sas_ata_task_done() disposition the
qc. Longer term we want to audit non-essential calls to
sas_task_abort().
Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/isci/task.h | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index 4a7fa90..15b18d1 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -286,6 +286,25 @@ isci_task_set_completion_status(
task->task_status.resp = response;
task->task_status.stat = status;
+ switch (task->task_proto) {
+
+ case SAS_PROTOCOL_SATA:
+ case SAS_PROTOCOL_STP:
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+
+ if (task_notification_selection
+ == isci_perform_error_io_completion) {
+ /* SATA/STP I/O has it's own means of scheduling device
+ * error handling on the normal path.
+ */
+ task_notification_selection
+ = isci_perform_normal_io_completion;
+ }
+ break;
+ default:
+ break;
+ }
+
switch (task_notification_selection) {
case isci_perform_error_io_completion:
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/5] isci: fix decode of DONE_CRC_ERR TC completion status
2011-09-29 1:47 [GIT PATCH 0/5] isci updates for 3.2 Dan Williams
2011-09-29 1:47 ` [PATCH 1/5] isci: atapi support Dan Williams
2011-09-29 1:47 ` [PATCH 2/5] isci: SATA/STP I/O is only returned in the normal path to libsas Dan Williams
@ 2011-09-29 1:47 ` Dan Williams
2011-09-29 1:47 ` [PATCH 4/5] isci: The port state should be set to stopping on the last phy Dan Williams
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Dan Williams @ 2011-09-29 1:47 UTC (permalink / raw)
To: JBottomley; +Cc: dmilburn, dave.jiang, hare, linux-scsi, Jeff Skirvin
From: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
DONE_CRC_ERR is not a RNC suspension condition, so do not change the
state to expect the incoming suspension notification.
Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
[djbw: dropped DONE_CMD_LL_R_ERR change]
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/isci/request.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 2bf072f..d431564 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -2072,10 +2072,9 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
- case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
sci_remote_device_suspend(ireq->target_device,
SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
- /* Fall through to the default case */
+ /* Fall through to the default case */
default:
/* All other completion status cause the IO to be complete. */
ireq->scu_status = SCU_NORMALIZE_COMPLETION_STATUS(completion_code);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/5] isci: The port state should be set to stopping on the last phy.
2011-09-29 1:47 [GIT PATCH 0/5] isci updates for 3.2 Dan Williams
` (2 preceding siblings ...)
2011-09-29 1:47 ` [PATCH 3/5] isci: fix decode of DONE_CRC_ERR TC completion status Dan Williams
@ 2011-09-29 1:47 ` Dan Williams
2011-09-29 1:48 ` [PATCH 5/5] isci: export phy events via ->lldd_control_phy() Dan Williams
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Dan Williams @ 2011-09-29 1:47 UTC (permalink / raw)
To: JBottomley; +Cc: dmilburn, dave.jiang, hare, linux-scsi, Jeff Skirvin
From: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Fixes a bug where any phy removed from the port set the port
state to "stopping" - do this only when the last phy removed
from the port.
Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/isci/port.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 8f6f9b7..8e59c88 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -294,8 +294,8 @@ static void isci_port_link_down(struct isci_host *isci_host,
__func__, isci_device);
set_bit(IDEV_GONE, &isci_device->flags);
}
+ isci_port_change_state(isci_port, isci_stopping);
}
- isci_port_change_state(isci_port, isci_stopping);
}
/* Notify libsas of the borken link, this will trigger calls to our
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/5] isci: export phy events via ->lldd_control_phy()
2011-09-29 1:47 [GIT PATCH 0/5] isci updates for 3.2 Dan Williams
` (3 preceding siblings ...)
2011-09-29 1:47 ` [PATCH 4/5] isci: The port state should be set to stopping on the last phy Dan Williams
@ 2011-09-29 1:48 ` Dan Williams
2011-09-29 2:12 ` [GIT PATCH 0/5] isci updates for 3.2 Williams, Dan J
2011-10-01 1:55 ` Dan Williams
6 siblings, 0 replies; 10+ messages in thread
From: Dan Williams @ 2011-09-29 1:48 UTC (permalink / raw)
To: JBottomley; +Cc: dmilburn, Sreeram Patnam, dave.jiang, hare, linux-scsi
Allow the sas-transport-class to update events for local phys via a new
PHY_FUNC_GET_EVENTS command to ->lldd_control_phy(). Fixup drivers that
are not prepared for new enum phy_func values, and unify
->lldd_control_phy() error codes.
These are the SAS defined phy events that are reported in a
smp-report-phy-error-log command:
* /sys/class/sas_phy/<phyX>/invalid_dword_count
* /sys/class/sas_phy/<phyX>/running_disparity_error_count
* /sys/class/sas_phy/<phyX>/loss_of_dword_sync_count
* /sys/class/sas_phy/<phyX>/phy_reset_problem_count
Cc: Sreeram Patnam <sreeram.patnam@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/aic94xx/aic94xx_scb.c | 1 +
drivers/scsi/isci/phy.c | 11 +++++++++++
drivers/scsi/libsas/sas_init.c | 13 +++++++++----
drivers/scsi/mvsas/mv_sas.c | 2 +-
drivers/scsi/pm8001/pm8001_sas.c | 2 +-
include/scsi/sas.h | 1 +
6 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 2959327..fdac7c2 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -906,6 +906,7 @@ int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg)
switch (func) {
case PHY_FUNC_CLEAR_ERROR_LOG:
+ case PHY_FUNC_GET_EVENTS:
return -ENOSYS;
case PHY_FUNC_SET_LINK_RATE:
rates = arg;
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index 430fc8f..ab48bb1 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -1313,6 +1313,17 @@ int isci_phy_control(struct asd_sas_phy *sas_phy,
ret = isci_port_perform_hard_reset(ihost, iport, iphy);
break;
+ case PHY_FUNC_GET_EVENTS: {
+ struct scu_link_layer_registers __iomem *r;
+ struct sas_phy *phy = sas_phy->phy;
+
+ r = iphy->link_layer_registers;
+ phy->running_disparity_error_count = readl(&r->running_disparity_error_count);
+ phy->loss_of_dword_sync_count = readl(&r->loss_of_sync_error_count);
+ phy->phy_reset_problem_count = readl(&r->phy_reset_problem_count);
+ phy->invalid_dword_count = readl(&r->invalid_dword_counter);
+ break;
+ }
default:
dev_dbg(&ihost->pdev->dev,
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index dd56ea8..d81c3b1 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -177,10 +177,15 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
static int sas_get_linkerrors(struct sas_phy *phy)
{
- if (scsi_is_sas_phy_local(phy))
- /* FIXME: we have no local phy stats
- * gathering at this time */
- return -EINVAL;
+ if (scsi_is_sas_phy_local(phy)) {
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+ struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
+ struct sas_internal *i =
+ to_sas_internal(sas_ha->core.shost->transportt);
+
+ return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL);
+ }
return sas_smp_get_phy_events(phy);
}
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index f2ac01f..5672bd7 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -214,7 +214,7 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
break;
case PHY_FUNC_RELEASE_SPINUP_HOLD:
default:
- rc = -EOPNOTSUPP;
+ rc = -ENOSYS;
}
msleep(200);
return rc;
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 9068f12..2d5494e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -210,7 +210,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id);
break;
default:
- rc = -EOPNOTSUPP;
+ rc = -ENOSYS;
}
msleep(300);
return rc;
diff --git a/include/scsi/sas.h b/include/scsi/sas.h
index a3001ad..be6a36c 100644
--- a/include/scsi/sas.h
+++ b/include/scsi/sas.h
@@ -121,6 +121,7 @@ enum phy_func {
PHY_FUNC_TX_SATA_PS_SIGNAL,
PHY_FUNC_RELEASE_SPINUP_HOLD = 0x10, /* LOCAL PORT ONLY! */
PHY_FUNC_SET_LINK_RATE,
+ PHY_FUNC_GET_EVENTS,
};
/* SAS LLDD would need to report only _very_few_ of those, like BROADCAST.
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [GIT PATCH 0/5] isci updates for 3.2
2011-09-29 1:47 [GIT PATCH 0/5] isci updates for 3.2 Dan Williams
` (4 preceding siblings ...)
2011-09-29 1:48 ` [PATCH 5/5] isci: export phy events via ->lldd_control_phy() Dan Williams
@ 2011-09-29 2:12 ` Williams, Dan J
2011-10-01 1:55 ` Dan Williams
6 siblings, 0 replies; 10+ messages in thread
From: Williams, Dan J @ 2011-09-29 2:12 UTC (permalink / raw)
To: JBottomley; +Cc: dmilburn, dave.jiang, hare, linux-scsi
...need to fix up the git urls.
On Wed, Sep 28, 2011 at 6:47 PM, Dan Williams <dan.j.williams@intel.com> wrote:
> This series functionally depends on the pending libsas fix for ata lun
> scanning. For convenience those updates have been queued to
> "git://github.com:djbw/linux.git libsas".
git://github.com/djbw/linux.git libsas
> The following changes since commit 7705375e944ea94be7941b740efd0a77bb109cb1:
>
> libsas: remove unused ata_task_resp fields (2011-09-28 18:06:10 -0700)
>
> are available in the git repository at:
> git://github.com:djbw/linux.git isci
git://github.com/djbw/linux.git isci
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/5] isci: atapi support
2011-09-29 1:47 ` [PATCH 1/5] isci: atapi support Dan Williams
@ 2011-09-29 13:45 ` Jeff Garzik
2011-10-01 1:49 ` Dan Williams
1 sibling, 0 replies; 10+ messages in thread
From: Jeff Garzik @ 2011-09-29 13:45 UTC (permalink / raw)
To: Dan Williams
Cc: JBottomley, Maciej Trela, dmilburn, dave.jiang, hare, linux-scsi
On 09/28/2011 09:47 PM, Dan Williams wrote:
> 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>
> ---
> drivers/scsi/isci/remote_device.c | 24 +++
> drivers/scsi/isci/remote_device.h | 9 +
> drivers/scsi/isci/request.c | 327 ++++++++++++++++++++++++++++++++++-
> drivers/scsi/isci/request.h | 28 +++
> drivers/scsi/libsas/sas_scsi_host.c | 2
> include/scsi/libsas.h | 5 +
> 6 files changed, 379 insertions(+), 16 deletions(-)
Acked-by: Jeff Garzik <jgarzik@redhat.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/5] isci: atapi support
2011-09-29 1:47 ` [PATCH 1/5] isci: atapi support Dan Williams
2011-09-29 13:45 ` Jeff Garzik
@ 2011-10-01 1:49 ` Dan Williams
1 sibling, 0 replies; 10+ messages in thread
From: Dan Williams @ 2011-10-01 1:49 UTC (permalink / raw)
To: JBottomley
Cc: Maciej Trela, dmilburn, dave.jiang, hare, linux-scsi, Jeff Garzik
On Wed, Sep 28, 2011 at 6:47 PM, Dan Williams <dan.j.williams@intel.com> wrote:
> 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>
> ---
> drivers/scsi/isci/remote_device.c | 24 +++
> drivers/scsi/isci/remote_device.h | 9 +
> drivers/scsi/isci/request.c | 327 ++++++++++++++++++++++++++++++++++-
> drivers/scsi/isci/request.h | 28 +++
> drivers/scsi/libsas/sas_scsi_host.c | 2
> include/scsi/libsas.h | 5 +
> 6 files changed, 379 insertions(+), 16 deletions(-)
>
[..]
> diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
> index b5d3a8c..2bf072f 100644
> --- a/drivers/scsi/isci/request.c
> +++ b/drivers/scsi/isci/request.c
[..]
> @@ -2802,26 +3096,29 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
> * substates
> */
> if (!task && dev->dev_type == SAS_END_DEV) {
> - sci_change_state(sm, SCI_REQ_TASK_WAIT_TC_COMP);
> + state = SCI_REQ_TASK_WAIT_TC_COMP;
> } else if (!task &&
> (isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_high ||
> isci_request_access_tmf(ireq)->tmf_code == isci_tmf_sata_srst_low)) {
> - sci_change_state(sm, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED);
> + state = SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED;
> } else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
> - sci_change_state(sm, SCI_REQ_SMP_WAIT_RESP);
> + state = SCI_REQ_SMP_WAIT_RESP;
> } else if (task && sas_protocol_ata(task->task_proto) &&
> !task->ata_task.use_ncq) {
> - u32 state;
> -
> - if (task->data_dir == DMA_NONE)
> + if (dev->sata_dev.command_set == ATAPI_COMMAND_SET &&
> + task->ata_task.fis.command == ATA_CMD_PACKET) {
> + state = SCI_REQ_ATAPI_WAIT_H2D;
> + } else if (task->data_dir == DMA_NONE) {
> state = SCI_REQ_STP_NON_DATA_WAIT_H2D;
> - else if (task->ata_task.dma_xfer)
> + } else if (task->ata_task.dma_xfer) {
> state = SCI_REQ_STP_UDMA_WAIT_TC_COMP;
> - else /* PIO */
> + } else /* PIO */ {
> state = SCI_REQ_STP_PIO_WAIT_H2D;
> -
> - sci_change_state(sm, state);
> + }
> + } else {
> + BUG();
Unfortunately this was part of a last minute "cleanup" that missed the
fact that SSP and STP-NCQ commands are fully accelerated and do not
have a substate. To prevent this mistake in the future I changed this
to:
@@ -3106,7 +3106,8 @@ static void
sci_request_started_state_enter(struct sci_base_state_machine *sm)
state = SCI_REQ_STP_PIO_WAIT_H2D;
}
} else {
- BUG();
+ /* SSP or NCQ are fully accelerated, no substates */
+ return;
}
sci_change_state(sm, state);
}
A v2 will be posted shortly and the github branch will be updated.
--
Dan
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [GIT PATCH 0/5] isci updates for 3.2
2011-09-29 1:47 [GIT PATCH 0/5] isci updates for 3.2 Dan Williams
` (5 preceding siblings ...)
2011-09-29 2:12 ` [GIT PATCH 0/5] isci updates for 3.2 Williams, Dan J
@ 2011-10-01 1:55 ` Dan Williams
6 siblings, 0 replies; 10+ messages in thread
From: Dan Williams @ 2011-10-01 1:55 UTC (permalink / raw)
To: JBottomley; +Cc: dmilburn, dave.jiang, hare, linux-scsi
On Wed, Sep 28, 2011 at 6:47 PM, Dan Williams <dan.j.williams@intel.com> wrote:
> This series functionally depends on the pending libsas fix for ata lun
> scanning. For convenience those updates have been queued to
> "git://github.com:djbw/linux.git libsas".
>
> The following changes since commit 7705375e944ea94be7941b740efd0a77bb109cb1:
>
> libsas: remove unused ata_task_resp fields (2011-09-28 18:06:10 -0700)
>
> are available in the git repository at:
> git://github.com:djbw/linux.git isci
>
> The prominent update in this set is atapi support. The rest are small
> bug fixes and feature enhancements. More error handling and command
> termination fixes are in the works.
>
Reflowed with the fixed version of the atapi patch.
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index cb3dd6e..565a9f0 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -3106,7 +3106,8 @@ static void
sci_request_started_state_enter(struct sci_base_state_machine *sm)
state = SCI_REQ_STP_PIO_WAIT_H2D;
}
} else {
- BUG();
+ /* SSP or NCQ are fully accelerated, no substates */
+ return;
}
sci_change_state(sm, state);
}
New diffstat below.
The following changes since commit a265fbf9a7c4321a71394bdce22da2be119fdba1:
libsas: set rphy sas_address and device type correctly (2011-09-30
18:35:16 -0700)
are available in the git repository at:
git://github.com/djbw/linux.git isci
Dan Williams (2):
isci: atapi support
isci: export phy events via ->lldd_control_phy()
Jeff Skirvin (3):
isci: SATA/STP I/O is only returned in the normal path to libsas
isci: fix decode of DONE_CRC_ERR TC completion status
isci: The port state should be set to stopping on the last phy.
drivers/scsi/aic94xx/aic94xx_scb.c | 1 +
drivers/scsi/isci/phy.c | 11 ++
drivers/scsi/isci/port.c | 2 +-
drivers/scsi/isci/remote_device.c | 24 +++
drivers/scsi/isci/remote_device.h | 9 +
drivers/scsi/isci/request.c | 331 +++++++++++++++++++++++++++++++++--
drivers/scsi/isci/request.h | 28 +++-
drivers/scsi/isci/task.h | 19 ++
drivers/scsi/libsas/sas_init.c | 13 +-
drivers/scsi/libsas/sas_scsi_host.c | 2 +-
drivers/scsi/mvsas/mv_sas.c | 2 +-
drivers/scsi/pm8001/pm8001_sas.c | 2 +-
include/scsi/libsas.h | 5 +
include/scsi/sas.h | 1 +
14 files changed, 425 insertions(+), 25 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-10-01 1:55 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-29 1:47 [GIT PATCH 0/5] isci updates for 3.2 Dan Williams
2011-09-29 1:47 ` [PATCH 1/5] isci: atapi support Dan Williams
2011-09-29 13:45 ` Jeff Garzik
2011-10-01 1:49 ` Dan Williams
2011-09-29 1:47 ` [PATCH 2/5] isci: SATA/STP I/O is only returned in the normal path to libsas Dan Williams
2011-09-29 1:47 ` [PATCH 3/5] isci: fix decode of DONE_CRC_ERR TC completion status Dan Williams
2011-09-29 1:47 ` [PATCH 4/5] isci: The port state should be set to stopping on the last phy Dan Williams
2011-09-29 1:48 ` [PATCH 5/5] isci: export phy events via ->lldd_control_phy() Dan Williams
2011-09-29 2:12 ` [GIT PATCH 0/5] isci updates for 3.2 Williams, Dan J
2011-10-01 1:55 ` Dan Williams
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox