[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: Ke Wei <kewei@marvell.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
1fce5e5da0
commit
4e52fc0a0a
1 changed files with 45 additions and 31 deletions
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue