aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mvsas.c
diff options
context:
space:
mode:
authorKe Wei <kewei@marvell.com>2008-03-27 02:54:50 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-03-28 13:31:25 -0400
commit4e52fc0a0a2ec2158691efba3f149f6416481255 (patch)
tree4f954e28a7dfc19fd7cb249b6eb31a0ea8939600 /drivers/scsi/mvsas.c
parent1fce5e5da03b18505179882be27cc697f24d6b58 (diff)
[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>
Diffstat (limited to 'drivers/scsi/mvsas.c')
-rw-r--r--drivers/scsi/mvsas.c76
1 files changed, 45 insertions, 31 deletions
diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c
index f302970f6f2d..ebfe1649443a 100644
--- a/drivers/scsi/mvsas.c
+++ b/drivers/scsi/mvsas.c
@@ -1784,15 +1784,19 @@ static u8 mvs_assign_reg_set(struct mvs_info *mvi, struct mvs_port *port)
1784 return MVS_ID_NOT_MAPPED; 1784 return MVS_ID_NOT_MAPPED;
1785} 1785}
1786 1786
1787static u32 mvs_get_ncq_tag(struct sas_task *task) 1787static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag)
1788{ 1788{
1789 u32 tag = 0;
1790 struct ata_queued_cmd *qc = task->uldd_task; 1789 struct ata_queued_cmd *qc = task->uldd_task;
1791 1790
1792 if (qc) 1791 if (qc) {
1793 tag = qc->tag; 1792 if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
1793 qc->tf.command == ATA_CMD_FPDMA_READ) {
1794 *tag = qc->tag;
1795 return 1;
1796 }
1797 }
1794 1798
1795 return tag; 1799 return 0;
1796} 1800}
1797 1801
1798static int mvs_task_prep_ata(struct mvs_info *mvi, 1802static int mvs_task_prep_ata(struct mvs_info *mvi,
@@ -1836,11 +1840,9 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
1836 hdr->flags = cpu_to_le32(flags); 1840 hdr->flags = cpu_to_le32(flags);
1837 1841
1838 /* FIXME: the low order order 5 bits for the TAG if enable NCQ */ 1842 /* FIXME: the low order order 5 bits for the TAG if enable NCQ */
1839 if (task->ata_task.use_ncq) { 1843 if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr->tags))
1840 hdr->tags = cpu_to_le32(mvs_get_ncq_tag(task)); 1844 task->ata_task.fis.sector_count |= hdr->tags << 3;
1841 /*Fill in task file */ 1845 else
1842 task->ata_task.fis.sector_count = hdr->tags << 3;
1843 } else
1844 hdr->tags = cpu_to_le32(tag); 1846 hdr->tags = cpu_to_le32(tag);
1845 hdr->data_len = cpu_to_le32(task->total_xfer_len); 1847 hdr->data_len = cpu_to_le32(task->total_xfer_len);
1846 1848
@@ -1933,13 +1935,16 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
1933 u32 flags; 1935 u32 flags;
1934 u32 resp_len, req_len, i, tag = tei->tag; 1936 u32 resp_len, req_len, i, tag = tei->tag;
1935 const u32 max_resp_len = SB_RFB_MAX; 1937 const u32 max_resp_len = SB_RFB_MAX;
1938 u8 phy_mask;
1936 1939
1937 slot = &mvi->slot_info[tag]; 1940 slot = &mvi->slot_info[tag];
1938 1941
1942 phy_mask = (port->wide_port_phymap) ? port->wide_port_phymap :
1943 task->dev->port->phy_mask;
1939 slot->tx = mvi->tx_prod; 1944 slot->tx = mvi->tx_prod;
1940 mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag | 1945 mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
1941 (TXQ_CMD_SSP << TXQ_CMD_SHIFT) | 1946 (TXQ_CMD_SSP << TXQ_CMD_SHIFT) |
1942 (port->wide_port_phymap << TXQ_PHY_SHIFT)); 1947 (phy_mask << TXQ_PHY_SHIFT));
1943 1948
1944 flags = MCH_RETRY; 1949 flags = MCH_RETRY;
1945 if (task->ssp_task.enable_first_burst) { 1950 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)
2040 void __iomem *regs = mvi->regs; 2045 void __iomem *regs = mvi->regs;
2041 struct mvs_task_exec_info tei; 2046 struct mvs_task_exec_info tei;
2042 struct sas_task *t = task; 2047 struct sas_task *t = task;
2048 struct mvs_slot_info *slot;
2043 u32 tag = 0xdeadbeef, rc, n_elem = 0; 2049 u32 tag = 0xdeadbeef, rc, n_elem = 0;
2044 unsigned long flags; 2050 unsigned long flags;
2045 u32 n = num, pass = 0; 2051 u32 n = num, pass = 0;
2046 2052
2047 spin_lock_irqsave(&mvi->lock, flags); 2053 spin_lock_irqsave(&mvi->lock, flags);
2048
2049 do { 2054 do {
2055 dev = t->dev;
2050 tei.port = &mvi->port[dev->port->id]; 2056 tei.port = &mvi->port[dev->port->id];
2051 2057
2052 if (!tei.port->port_attached) { 2058 if (!tei.port->port_attached) {
2053 struct task_status_struct *ts = &t->task_status; 2059 if (sas_protocol_ata(t->task_proto)) {
2054 ts->stat = SAS_PHY_DOWN; 2060 rc = SAS_PHY_DOWN;
2055 t->task_done(t); 2061 goto out_done;
2056 rc = 0; 2062 } else {
2057 goto exec_exit; 2063 struct task_status_struct *ts = &t->task_status;
2064 ts->resp = SAS_TASK_UNDELIVERED;
2065 ts->stat = SAS_PHY_DOWN;
2066 t->task_done(t);
2067 if (n > 1)
2068 t = list_entry(t->list.next,
2069 struct sas_task, list);
2070 continue;
2071 }
2058 } 2072 }
2073
2059 if (!sas_protocol_ata(t->task_proto)) { 2074 if (!sas_protocol_ata(t->task_proto)) {
2060 if (t->num_scatter) { 2075 if (t->num_scatter) {
2061 n_elem = pci_map_sg(mvi->pdev, t->scatter, 2076 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)
2074 if (rc) 2089 if (rc)
2075 goto err_out; 2090 goto err_out;
2076 2091
2077 mvi->slot_info[tag].task = t; 2092 slot = &mvi->slot_info[tag];
2078 mvi->slot_info[tag].n_elem = n_elem; 2093 t->lldd_task = NULL;
2079 memset(mvi->slot_info[tag].buf, 0, MVS_SLOT_BUF_SZ); 2094 slot->n_elem = n_elem;
2095 memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
2080 tei.task = t; 2096 tei.task = t;
2081 tei.hdr = &mvi->slot[tag]; 2097 tei.hdr = &mvi->slot[tag];
2082 tei.tag = tag; 2098 tei.tag = tag;
@@ -2105,28 +2121,26 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags)
2105 if (rc) 2121 if (rc)
2106 goto err_out_tag; 2122 goto err_out_tag;
2107 2123
2124 slot->task = t;
2125 slot->port = tei.port;
2126 t->lldd_task = (void *) slot;
2127 list_add_tail(&slot->list, &slot->port->list);
2108 /* TODO: select normal or high priority */ 2128 /* TODO: select normal or high priority */
2109 2129
2110 spin_lock(&t->task_state_lock); 2130 spin_lock(&t->task_state_lock);
2111 t->task_state_flags |= SAS_TASK_AT_INITIATOR; 2131 t->task_state_flags |= SAS_TASK_AT_INITIATOR;
2112 spin_unlock(&t->task_state_lock); 2132 spin_unlock(&t->task_state_lock);
2113 2133
2114 if (n == 1) {
2115 spin_unlock_irqrestore(&mvi->lock, flags);
2116 mw32(TX_PROD_IDX, mvi->tx_prod);
2117 }
2118 mvs_hba_memory_dump(mvi, tag, t->task_proto); 2134 mvs_hba_memory_dump(mvi, tag, t->task_proto);
2119 2135
2120 ++pass; 2136 ++pass;
2121 mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); 2137 mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
2122 2138 if (n > 1)
2123 if (n == 1) 2139 t = list_entry(t->list.next, struct sas_task, list);
2124 break;
2125
2126 t = list_entry(t->list.next, struct sas_task, list);
2127 } while (--n); 2140 } while (--n);
2128 2141
2129 return 0; 2142 rc = 0;
2143 goto out_done;
2130 2144
2131err_out_tag: 2145err_out_tag:
2132 mvs_tag_free(mvi, tag); 2146 mvs_tag_free(mvi, tag);
@@ -2136,7 +2150,7 @@ err_out:
2136 if (n_elem) 2150 if (n_elem)
2137 pci_unmap_sg(mvi->pdev, t->scatter, n_elem, 2151 pci_unmap_sg(mvi->pdev, t->scatter, n_elem,
2138 t->data_dir); 2152 t->data_dir);
2139exec_exit: 2153out_done:
2140 if (pass) 2154 if (pass)
2141 mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); 2155 mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
2142 spin_unlock_irqrestore(&mvi->lock, flags); 2156 spin_unlock_irqrestore(&mvi->lock, flags);