diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-12-09 08:20:44 +0100 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-29 22:13:40 +0100 |
commit | 43a5ab151f0268459c4368292c2ddb2266b8f243 (patch) | |
tree | e8ee97e0d49bc0c454ca90f16a836fd01830b11f /drivers/scsi | |
parent | [SCSI] isci: fix interpretation of "hard" reset (diff) | |
download | linux-43a5ab151f0268459c4368292c2ddb2266b8f243.tar.xz linux-43a5ab151f0268459c4368292c2ddb2266b8f243.zip |
[SCSI] isci: stop interpreting ->lldd_lu_reset() as an ata soft-reset
Driving resets from libsas-eh is pre-mature as libata will make a
decision about performing a softreset. Currently libata determines
whether to perform a softreset based on ata_eh_followup_srst_needed(),
and none of those conditions apply to isci.
Remove the srst implementation and translate ->lldd_lu_reset() for ata
devices as a request to drive a reset via libata-eh.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/isci/request.c | 195 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 9 | ||||
-rw-r--r-- | drivers/scsi/isci/task.c | 93 | ||||
-rw-r--r-- | drivers/scsi/isci/task.h | 2 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 2 |
5 files changed, 15 insertions, 286 deletions
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 788daeedc89f..1a39ce50529d 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -666,18 +666,12 @@ sci_io_request_construct_sata(struct isci_request *ireq, if (test_bit(IREQ_TMF, &ireq->flags)) { struct isci_tmf *tmf = isci_request_access_tmf(ireq); - if (tmf->tmf_code == isci_tmf_sata_srst_high || - tmf->tmf_code == isci_tmf_sata_srst_low) { - scu_stp_raw_request_construct_task_context(ireq); - return SCI_SUCCESS; - } else { - dev_err(&ireq->owning_controller->pdev->dev, - "%s: Request 0x%p received un-handled SAT " - "management protocol 0x%x.\n", - __func__, ireq, tmf->tmf_code); + dev_err(&ireq->owning_controller->pdev->dev, + "%s: Request 0x%p received un-handled SAT " + "management protocol 0x%x.\n", + __func__, ireq, tmf->tmf_code); - return SCI_FAILURE; - } + return SCI_FAILURE; } if (!sas_protocol_ata(task->task_proto)) { @@ -774,34 +768,6 @@ static enum sci_status sci_io_request_construct_basic_sata(struct isci_request * return status; } -enum sci_status sci_task_request_construct_sata(struct isci_request *ireq) -{ - enum sci_status status = SCI_SUCCESS; - - /* check for management protocols */ - if (test_bit(IREQ_TMF, &ireq->flags)) { - struct isci_tmf *tmf = isci_request_access_tmf(ireq); - - if (tmf->tmf_code == isci_tmf_sata_srst_high || - tmf->tmf_code == isci_tmf_sata_srst_low) { - scu_stp_raw_request_construct_task_context(ireq); - } else { - dev_err(&ireq->owning_controller->pdev->dev, - "%s: Request 0x%p received un-handled SAT " - "Protocol 0x%x.\n", - __func__, ireq, tmf->tmf_code); - - return SCI_FAILURE; - } - } - - if (status != SCI_SUCCESS) - return status; - sci_change_state(&ireq->sm, SCI_REQ_CONSTRUCTED); - - return status; -} - /** * sci_req_tx_bytes - bytes transferred when reply underruns request * @ireq: request that was terminated early @@ -903,9 +869,6 @@ sci_io_request_terminate(struct isci_request *ireq) case SCI_REQ_STP_PIO_WAIT_FRAME: case SCI_REQ_STP_PIO_DATA_IN: case SCI_REQ_STP_PIO_DATA_OUT: - 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: @@ -2085,59 +2048,6 @@ sci_io_request_frame_handler(struct isci_request *ireq, return status; } - case SCI_REQ_STP_SOFT_RESET_WAIT_D2H: { - 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) { - dev_err(&ihost->pdev->dev, - "%s: SCIC IO Request 0x%p could not get frame " - "header for frame index %d, status %x\n", - __func__, - stp_req, - frame_index, - status); - return status; - } - - switch (frame_header->fis_type) { - case FIS_REGD2H: - sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, - frame_index, - (void **)&frame_buffer); - - sci_controller_copy_sata_response(&ireq->stp.rsp, - frame_header, - frame_buffer); - - /* The command has completed with error */ - ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; - ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; - break; - - default: - dev_warn(&ihost->pdev->dev, - "%s: IO Request:0x%p Frame Id:%d protocol " - "violation occurred\n", - __func__, - stp_req, - frame_index); - - ireq->scu_status = SCU_TASK_DONE_UNEXP_FIS; - ireq->sci_status = SCI_FAILURE_PROTOCOL_VIOLATION; - break; - } - - sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); - - /* Frame has been decoded return it to the controller */ - sci_controller_release_frame(ihost, frame_index); - - return status; - } case SCI_REQ_ATAPI_WAIT_PIO_SETUP: { struct sas_task *task = isci_request_access_task(ireq); @@ -2235,57 +2145,6 @@ static enum sci_status stp_request_udma_await_tc_event(struct isci_request *ireq return status; } -static enum sci_status -stp_request_soft_reset_await_h2d_asserted_tc_event(struct isci_request *ireq, - u32 completion_code) -{ - 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, SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG); - 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 SCI_SUCCESS; -} - -static enum sci_status -stp_request_soft_reset_await_h2d_diagnostic_tc_event(struct isci_request *ireq, - u32 completion_code) -{ - 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, SCI_REQ_STP_SOFT_RESET_WAIT_D2H); - 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 SCI_SUCCESS; -} - static enum sci_status atapi_raw_completion(struct isci_request *ireq, u32 completion_code, enum sci_base_request_states next) { @@ -2431,14 +2290,6 @@ sci_io_request_tc_completion(struct isci_request *ireq, case SCI_REQ_STP_PIO_DATA_OUT: return pio_data_out_tx_done_tc_event(ireq, completion_code); - case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED: - return stp_request_soft_reset_await_h2d_asserted_tc_event(ireq, - completion_code); - - case SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG: - return stp_request_soft_reset_await_h2d_diagnostic_tc_event(ireq, - completion_code); - case SCI_REQ_ABORTING: return request_aborting_state_tc_event(ireq, completion_code); @@ -3212,10 +3063,6 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm) */ if (!task && dev->dev_type == SAS_END_DEV) { 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)) { - state = SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED; } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { state = SCI_REQ_SMP_WAIT_RESP; } else if (task && sas_protocol_ata(task->task_proto) && @@ -3272,31 +3119,6 @@ static void sci_stp_request_started_pio_await_h2d_completion_enter(struct sci_ba ireq->target_device->working_request = ireq; } -static void sci_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(struct sci_base_state_machine *sm) -{ - struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - - ireq->target_device->working_request = ireq; -} - -static void sci_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(struct sci_base_state_machine *sm) -{ - struct isci_request *ireq = container_of(sm, typeof(*ireq), sm); - struct scu_task_context *tc = ireq->tc; - struct host_to_dev_fis *h2d_fis; - enum sci_status status; - - /* Clear the SRST bit */ - h2d_fis = &ireq->stp.cmd; - h2d_fis->control = 0; - - /* Clear the TC control bit */ - tc->control_frame = 0; - - status = sci_controller_continue_io(ireq); - WARN_ONCE(status != SCI_SUCCESS, "isci: continue io failure\n"); -} - static const struct sci_base_state sci_request_state_table[] = { [SCI_REQ_INIT] = { }, [SCI_REQ_CONSTRUCTED] = { }, @@ -3315,13 +3137,6 @@ static const struct sci_base_state sci_request_state_table[] = { [SCI_REQ_STP_PIO_DATA_OUT] = { }, [SCI_REQ_STP_UDMA_WAIT_TC_COMP] = { }, [SCI_REQ_STP_UDMA_WAIT_D2H] = { }, - [SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED] = { - .enter_state = sci_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, - }, - [SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG] = { - .enter_state = sci_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, - }, - [SCI_REQ_STP_SOFT_RESET_WAIT_D2H] = { }, [SCI_REQ_TASK_WAIT_TC_COMP] = { }, [SCI_REQ_TASK_WAIT_TC_RESP] = { }, [SCI_REQ_SMP_WAIT_RESP] = { }, diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index be38933dd6df..bcf2f37f23e1 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h @@ -211,10 +211,6 @@ enum sci_base_request_states { SCI_REQ_STP_NON_DATA_WAIT_H2D, SCI_REQ_STP_NON_DATA_WAIT_D2H, - SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED, - SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG, - SCI_REQ_STP_SOFT_RESET_WAIT_D2H, - /* * While in this state the IO request object is waiting for the TC * completion notification for the H2D Register FIS @@ -446,10 +442,7 @@ sci_task_request_construct(struct isci_host *ihost, struct isci_remote_device *idev, u16 io_tag, struct isci_request *ireq); -enum sci_status -sci_task_request_construct_ssp(struct isci_request *ireq); -enum sci_status -sci_task_request_construct_sata(struct isci_request *ireq); +enum sci_status sci_task_request_construct_ssp(struct isci_request *ireq); void sci_smp_request_copy_response(struct isci_request *ireq); static inline int isci_task_is_ncq_recovery(struct sas_task *task) diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c4d324ccee11..3f04e97128a6 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -247,46 +247,6 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) return 0; } -static enum sci_status isci_sata_management_task_request_build(struct isci_request *ireq) -{ - struct isci_tmf *isci_tmf; - enum sci_status status; - - if (!test_bit(IREQ_TMF, &ireq->flags)) - return SCI_FAILURE; - - isci_tmf = isci_request_access_tmf(ireq); - - switch (isci_tmf->tmf_code) { - - case isci_tmf_sata_srst_high: - case isci_tmf_sata_srst_low: { - struct host_to_dev_fis *fis = &ireq->stp.cmd; - - memset(fis, 0, sizeof(*fis)); - - fis->fis_type = 0x27; - fis->flags &= ~0x80; - fis->flags &= 0xF0; - if (isci_tmf->tmf_code == isci_tmf_sata_srst_high) - fis->control |= ATA_SRST; - else - fis->control &= ~ATA_SRST; - break; - } - /* other management commnd go here... */ - default: - return SCI_FAILURE; - } - - /* core builds the protocol specific request - * based on the h2d fis. - */ - status = sci_task_request_construct_sata(ireq); - - return status; -} - static struct isci_request *isci_task_request_build(struct isci_host *ihost, struct isci_remote_device *idev, u16 tag, struct isci_tmf *isci_tmf) @@ -326,13 +286,6 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, return NULL; } - if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { - isci_tmf->proto = SAS_PROTOCOL_SATA; - status = isci_sata_management_task_request_build(ireq); - - if (status != SCI_SUCCESS) - return NULL; - } return ireq; } @@ -871,53 +824,20 @@ static int isci_task_send_lu_reset_sas( return ret; } -static int isci_task_send_lu_reset_sata(struct isci_host *ihost, - struct isci_remote_device *idev, u8 *lun) +int isci_task_lu_reset(struct domain_device *dev, u8 *lun) { - int ret = TMF_RESP_FUNC_FAILED; - struct isci_tmf tmf; - - /* Send the soft reset to the target */ - #define ISCI_SRST_TIMEOUT_MS 25000 /* 25 second timeout. */ - isci_task_build_tmf(&tmf, isci_tmf_sata_srst_high, NULL, NULL); - - ret = isci_task_execute_tmf(ihost, idev, &tmf, ISCI_SRST_TIMEOUT_MS); - - if (ret != TMF_RESP_FUNC_COMPLETE) { - dev_dbg(&ihost->pdev->dev, - "%s: Assert SRST failed (%p) = %x", - __func__, idev, ret); - - /* Return the failure so that the LUN reset is escalated - * to a target reset. - */ - } - return ret; -} - -/** - * isci_task_lu_reset() - This function is one of the SAS Domain Template - * functions. This is one of the Task Management functoins called by libsas, - * to reset the given lun. Note the assumption that while this call is - * executing, no I/O will be sent by the host to the device. - * @lun: This parameter specifies the lun to be reset. - * - * status, zero indicates success. - */ -int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) -{ - struct isci_host *isci_host = dev_to_ihost(domain_device); + struct isci_host *isci_host = dev_to_ihost(dev); struct isci_remote_device *isci_device; unsigned long flags; int ret; spin_lock_irqsave(&isci_host->scic_lock, flags); - isci_device = isci_lookup_device(domain_device); + isci_device = isci_lookup_device(dev); spin_unlock_irqrestore(&isci_host->scic_lock, flags); dev_dbg(&isci_host->pdev->dev, "%s: domain_device=%p, isci_host=%p; isci_device=%p\n", - __func__, domain_device, isci_host, isci_device); + __func__, dev, isci_host, isci_device); if (!isci_device) { /* If the device is gone, stop the escalations. */ @@ -929,8 +849,9 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun) set_bit(IDEV_EH, &isci_device->flags); /* Send the task management part of the reset. */ - if (sas_protocol_ata(domain_device->tproto)) { - ret = isci_task_send_lu_reset_sata(isci_host, isci_device, lun); + if (dev_is_sata(dev)) { + sas_ata_schedule_reset(dev); + ret = TMF_RESP_FUNC_COMPLETE; } else ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun); diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index bb472c339523..5ba00c3081f4 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -86,8 +86,6 @@ enum isci_tmf_function_codes { isci_tmf_func_none = 0, isci_tmf_ssp_task_abort = TMF_ABORT_TASK, isci_tmf_ssp_lun_reset = TMF_LU_RESET, - isci_tmf_sata_srst_high = TMF_LU_RESET + 0x100, /* Non SCSI */ - isci_tmf_sata_srst_low = TMF_LU_RESET + 0x101 /* Non SCSI */ }; /** * struct isci_tmf - This class represents the task management object which diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 0cb538f8478a..37a9e73870d4 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -24,6 +24,7 @@ #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/async.h> +#include <linux/export.h> #include <scsi/sas_ata.h> #include "sas_internal.h" @@ -757,6 +758,7 @@ void sas_ata_schedule_reset(struct domain_device *dev) ata_port_schedule_eh(ap); spin_unlock_irqrestore(ap->lock, flags); } +EXPORT_SYMBOL_GPL(sas_ata_schedule_reset); void sas_ata_wait_eh(struct domain_device *dev) { |