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

Commit 4e52fc0a authored by Ke Wei's avatar Ke Wei Committed by James Bottomley
Browse files

[SCSI] mvsas: check hd whether unplugged



if unplugged, driver's queuecommand function will return SAS_PHY_DOWN.
task->lldd_task is used for saving its slot info.

Signed-off-by: default avatarKe Wei <kewei@marvell.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 1fce5e5d
Loading
Loading
Loading
Loading
+45 −31
Original line number Original line Diff line number Diff line
@@ -1784,15 +1784,19 @@ static u8 mvs_assign_reg_set(struct mvs_info *mvi, struct mvs_port *port)
	return MVS_ID_NOT_MAPPED;
	return MVS_ID_NOT_MAPPED;
}
}


static u32 mvs_get_ncq_tag(struct sas_task *task)
static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag)
{
{
	u32 tag = 0;
	struct ata_queued_cmd *qc = task->uldd_task;
	struct ata_queued_cmd *qc = task->uldd_task;


	if (qc)
	if (qc) {
		tag = qc->tag;
		if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
			qc->tf.command == ATA_CMD_FPDMA_READ) {
			*tag = qc->tag;
			return 1;
		}
	}


	return tag;
	return 0;
}
}


static int mvs_task_prep_ata(struct mvs_info *mvi,
static int mvs_task_prep_ata(struct mvs_info *mvi,
@@ -1836,11 +1840,9 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
	hdr->flags = cpu_to_le32(flags);
	hdr->flags = cpu_to_le32(flags);


	/* FIXME: the low order order 5 bits for the TAG if enable NCQ */
	/* FIXME: the low order order 5 bits for the TAG if enable NCQ */
	if (task->ata_task.use_ncq) {
	if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr->tags))
		hdr->tags = cpu_to_le32(mvs_get_ncq_tag(task));
		task->ata_task.fis.sector_count |= hdr->tags << 3;
		/*Fill in task file */
	else
		task->ata_task.fis.sector_count = hdr->tags << 3;
	} else
		hdr->tags = cpu_to_le32(tag);
		hdr->tags = cpu_to_le32(tag);
	hdr->data_len = cpu_to_le32(task->total_xfer_len);
	hdr->data_len = cpu_to_le32(task->total_xfer_len);


@@ -1933,13 +1935,16 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
	u32 flags;
	u32 flags;
	u32 resp_len, req_len, i, tag = tei->tag;
	u32 resp_len, req_len, i, tag = tei->tag;
	const u32 max_resp_len = SB_RFB_MAX;
	const u32 max_resp_len = SB_RFB_MAX;
	u8 phy_mask;


	slot = &mvi->slot_info[tag];
	slot = &mvi->slot_info[tag];


	phy_mask = (port->wide_port_phymap) ? port->wide_port_phymap :
		task->dev->port->phy_mask;
	slot->tx = mvi->tx_prod;
	slot->tx = mvi->tx_prod;
	mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
	mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
				(TXQ_CMD_SSP << TXQ_CMD_SHIFT) |
				(TXQ_CMD_SSP << TXQ_CMD_SHIFT) |
				(port->wide_port_phymap << TXQ_PHY_SHIFT));
				(phy_mask << TXQ_PHY_SHIFT));


	flags = MCH_RETRY;
	flags = MCH_RETRY;
	if (task->ssp_task.enable_first_burst) {
	if (task->ssp_task.enable_first_burst) {
@@ -2040,22 +2045,32 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags)
	void __iomem *regs = mvi->regs;
	void __iomem *regs = mvi->regs;
	struct mvs_task_exec_info tei;
	struct mvs_task_exec_info tei;
	struct sas_task *t = task;
	struct sas_task *t = task;
	struct mvs_slot_info *slot;
	u32 tag = 0xdeadbeef, rc, n_elem = 0;
	u32 tag = 0xdeadbeef, rc, n_elem = 0;
	unsigned long flags;
	unsigned long flags;
	u32 n = num, pass = 0;
	u32 n = num, pass = 0;


	spin_lock_irqsave(&mvi->lock, flags);
	spin_lock_irqsave(&mvi->lock, flags);

	do {
	do {
		dev = t->dev;
		tei.port = &mvi->port[dev->port->id];
		tei.port = &mvi->port[dev->port->id];


		if (!tei.port->port_attached) {
		if (!tei.port->port_attached) {
			if (sas_protocol_ata(t->task_proto)) {
				rc = SAS_PHY_DOWN;
				goto out_done;
			} else {
				struct task_status_struct *ts = &t->task_status;
				struct task_status_struct *ts = &t->task_status;
				ts->resp = SAS_TASK_UNDELIVERED;
				ts->stat = SAS_PHY_DOWN;
				ts->stat = SAS_PHY_DOWN;
				t->task_done(t);
				t->task_done(t);
			rc = 0;
				if (n > 1)
			goto exec_exit;
					t = list_entry(t->list.next,
							struct sas_task, list);
				continue;
			}
		}
		}

		if (!sas_protocol_ata(t->task_proto)) {
		if (!sas_protocol_ata(t->task_proto)) {
			if (t->num_scatter) {
			if (t->num_scatter) {
				n_elem = pci_map_sg(mvi->pdev, t->scatter,
				n_elem = pci_map_sg(mvi->pdev, t->scatter,
@@ -2074,9 +2089,10 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags)
		if (rc)
		if (rc)
			goto err_out;
			goto err_out;


		mvi->slot_info[tag].task = t;
		slot = &mvi->slot_info[tag];
		mvi->slot_info[tag].n_elem = n_elem;
		t->lldd_task = NULL;
		memset(mvi->slot_info[tag].buf, 0, MVS_SLOT_BUF_SZ);
		slot->n_elem = n_elem;
		memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
		tei.task = t;
		tei.task = t;
		tei.hdr = &mvi->slot[tag];
		tei.hdr = &mvi->slot[tag];
		tei.tag = tag;
		tei.tag = tag;
@@ -2105,28 +2121,26 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags)
		if (rc)
		if (rc)
			goto err_out_tag;
			goto err_out_tag;


		slot->task = t;
		slot->port = tei.port;
		t->lldd_task = (void *) slot;
		list_add_tail(&slot->list, &slot->port->list);
		/* TODO: select normal or high priority */
		/* TODO: select normal or high priority */


		spin_lock(&t->task_state_lock);
		spin_lock(&t->task_state_lock);
		t->task_state_flags |= SAS_TASK_AT_INITIATOR;
		t->task_state_flags |= SAS_TASK_AT_INITIATOR;
		spin_unlock(&t->task_state_lock);
		spin_unlock(&t->task_state_lock);


		if (n == 1) {
			spin_unlock_irqrestore(&mvi->lock, flags);
			mw32(TX_PROD_IDX, mvi->tx_prod);
		}
		mvs_hba_memory_dump(mvi, tag, t->task_proto);
		mvs_hba_memory_dump(mvi, tag, t->task_proto);


		++pass;
		++pass;
		mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
		mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);

		if (n > 1)
		if (n == 1)
			break;

			t = list_entry(t->list.next, struct sas_task, list);
			t = list_entry(t->list.next, struct sas_task, list);
	} while (--n);
	} while (--n);


	return 0;
	rc = 0;
	goto out_done;


err_out_tag:
err_out_tag:
	mvs_tag_free(mvi, tag);
	mvs_tag_free(mvi, tag);
@@ -2136,7 +2150,7 @@ err_out:
		if (n_elem)
		if (n_elem)
			pci_unmap_sg(mvi->pdev, t->scatter, n_elem,
			pci_unmap_sg(mvi->pdev, t->scatter, n_elem,
				     t->data_dir);
				     t->data_dir);
exec_exit:
out_done:
	if (pass)
	if (pass)
		mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
		mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
	spin_unlock_irqrestore(&mvi->lock, flags);
	spin_unlock_irqrestore(&mvi->lock, flags);