Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43a5ab15 authored by Dan Williams's avatar Dan Williams Committed by James Bottomley
Browse files

[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: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 92776991
Loading
Loading
Loading
Loading
+5 −190
Original line number Original line Diff line number Diff line
@@ -666,11 +666,6 @@ sci_io_request_construct_sata(struct isci_request *ireq,
	if (test_bit(IREQ_TMF, &ireq->flags)) {
	if (test_bit(IREQ_TMF, &ireq->flags)) {
		struct isci_tmf *tmf = isci_request_access_tmf(ireq);
		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,
		dev_err(&ireq->owning_controller->pdev->dev,
			"%s: Request 0x%p received un-handled SAT "
			"%s: Request 0x%p received un-handled SAT "
			"management protocol 0x%x.\n",
			"management protocol 0x%x.\n",
@@ -678,7 +673,6 @@ sci_io_request_construct_sata(struct isci_request *ireq,


		return SCI_FAILURE;
		return SCI_FAILURE;
	}
	}
	}


	if (!sas_protocol_ata(task->task_proto)) {
	if (!sas_protocol_ata(task->task_proto)) {
		dev_err(&ireq->owning_controller->pdev->dev,
		dev_err(&ireq->owning_controller->pdev->dev,
@@ -774,34 +768,6 @@ static enum sci_status sci_io_request_construct_basic_sata(struct isci_request *
	return status;
	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
 * sci_req_tx_bytes - bytes transferred when reply underruns request
 * @ireq: request that was terminated early
 * @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_WAIT_FRAME:
	case SCI_REQ_STP_PIO_DATA_IN:
	case SCI_REQ_STP_PIO_DATA_IN:
	case SCI_REQ_STP_PIO_DATA_OUT:
	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_H2D:
	case SCI_REQ_ATAPI_WAIT_PIO_SETUP:
	case SCI_REQ_ATAPI_WAIT_PIO_SETUP:
	case SCI_REQ_ATAPI_WAIT_D2H:
	case SCI_REQ_ATAPI_WAIT_D2H:
@@ -2085,59 +2048,6 @@ sci_io_request_frame_handler(struct isci_request *ireq,
		return status;
		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: {
	case SCI_REQ_ATAPI_WAIT_PIO_SETUP: {
		struct sas_task *task = isci_request_access_task(ireq);
		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;
	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,
static enum sci_status atapi_raw_completion(struct isci_request *ireq, u32 completion_code,
						  enum sci_base_request_states next)
						  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:
	case SCI_REQ_STP_PIO_DATA_OUT:
		return pio_data_out_tx_done_tc_event(ireq, completion_code);
		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:
	case SCI_REQ_ABORTING:
		return request_aborting_state_tc_event(ireq,
		return request_aborting_state_tc_event(ireq,
						       completion_code);
						       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) {
	if (!task && dev->dev_type == SAS_END_DEV) {
		state = 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)) {
		state = SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED;
	} else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
	} else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
		state = SCI_REQ_SMP_WAIT_RESP;
		state = SCI_REQ_SMP_WAIT_RESP;
	} else if (task && sas_protocol_ata(task->task_proto) &&
	} 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;
	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[] = {
static const struct sci_base_state sci_request_state_table[] = {
	[SCI_REQ_INIT] = { },
	[SCI_REQ_INIT] = { },
	[SCI_REQ_CONSTRUCTED] = { },
	[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_PIO_DATA_OUT] = { },
	[SCI_REQ_STP_UDMA_WAIT_TC_COMP] = { },
	[SCI_REQ_STP_UDMA_WAIT_TC_COMP] = { },
	[SCI_REQ_STP_UDMA_WAIT_D2H] = { },
	[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_COMP] = { },
	[SCI_REQ_TASK_WAIT_TC_RESP] = { },
	[SCI_REQ_TASK_WAIT_TC_RESP] = { },
	[SCI_REQ_SMP_WAIT_RESP] = { },
	[SCI_REQ_SMP_WAIT_RESP] = { },
+1 −8
Original line number Original line Diff line number Diff line
@@ -211,10 +211,6 @@ enum sci_base_request_states {
	SCI_REQ_STP_NON_DATA_WAIT_H2D,
	SCI_REQ_STP_NON_DATA_WAIT_H2D,
	SCI_REQ_STP_NON_DATA_WAIT_D2H,
	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
	 * While in this state the IO request object is waiting for the TC
	 * completion notification for the H2D Register FIS
	 * completion notification for the H2D Register FIS
@@ -446,10 +442,7 @@ sci_task_request_construct(struct isci_host *ihost,
			    struct isci_remote_device *idev,
			    struct isci_remote_device *idev,
			    u16 io_tag,
			    u16 io_tag,
			    struct isci_request *ireq);
			    struct isci_request *ireq);
enum sci_status
enum sci_status sci_task_request_construct_ssp(struct isci_request *ireq);
sci_task_request_construct_ssp(struct isci_request *ireq);
enum sci_status
sci_task_request_construct_sata(struct isci_request *ireq);
void sci_smp_request_copy_response(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)
static inline int isci_task_is_ncq_recovery(struct sas_task *task)
+7 −86
Original line number Original line Diff line number Diff line
@@ -247,46 +247,6 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
	return 0;
	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,
static struct isci_request *isci_task_request_build(struct isci_host *ihost,
						    struct isci_remote_device *idev,
						    struct isci_remote_device *idev,
						    u16 tag, struct isci_tmf *isci_tmf)
						    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;
			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;
	return ireq;
}
}


@@ -871,53 +824,20 @@ static int isci_task_send_lu_reset_sas(
	return ret;
	return ret;
}
}


static int isci_task_send_lu_reset_sata(struct isci_host *ihost,
int isci_task_lu_reset(struct domain_device *dev, u8 *lun)
				 struct isci_remote_device *idev, u8 *lun)
{
{
	int ret = TMF_RESP_FUNC_FAILED;
	struct isci_host *isci_host = dev_to_ihost(dev);
	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_remote_device *isci_device;
	struct isci_remote_device *isci_device;
	unsigned long flags;
	unsigned long flags;
	int ret;
	int ret;


	spin_lock_irqsave(&isci_host->scic_lock, flags);
	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);
	spin_unlock_irqrestore(&isci_host->scic_lock, flags);


	dev_dbg(&isci_host->pdev->dev,
	dev_dbg(&isci_host->pdev->dev,
		"%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
		"%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 (!isci_device) {
		/* If the device is gone, stop the escalations. */
		/* 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);
	set_bit(IDEV_EH, &isci_device->flags);


	/* Send the task management part of the reset. */
	/* Send the task management part of the reset. */
	if (sas_protocol_ata(domain_device->tproto)) {
	if (dev_is_sata(dev)) {
		ret = isci_task_send_lu_reset_sata(isci_host, isci_device, lun);
		sas_ata_schedule_reset(dev);
		ret = TMF_RESP_FUNC_COMPLETE;
	} else
	} else
		ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun);
		ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun);


+0 −2
Original line number Original line Diff line number Diff line
@@ -86,8 +86,6 @@ enum isci_tmf_function_codes {
	isci_tmf_func_none      = 0,
	isci_tmf_func_none      = 0,
	isci_tmf_ssp_task_abort = TMF_ABORT_TASK,
	isci_tmf_ssp_task_abort = TMF_ABORT_TASK,
	isci_tmf_ssp_lun_reset  = TMF_LU_RESET,
	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
 * struct isci_tmf - This class represents the task management object which
+2 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/scatterlist.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/async.h>
#include <linux/async.h>
#include <linux/export.h>


#include <scsi/sas_ata.h>
#include <scsi/sas_ata.h>
#include "sas_internal.h"
#include "sas_internal.h"
@@ -757,6 +758,7 @@ void sas_ata_schedule_reset(struct domain_device *dev)
	ata_port_schedule_eh(ap);
	ata_port_schedule_eh(ap);
	spin_unlock_irqrestore(ap->lock, flags);
	spin_unlock_irqrestore(ap->lock, flags);
}
}
EXPORT_SYMBOL_GPL(sas_ata_schedule_reset);


void sas_ata_wait_eh(struct domain_device *dev)
void sas_ata_wait_eh(struct domain_device *dev)
{
{