diff options
author | Ke Wei <kewei@marvell.com> | 2008-03-27 02:54:50 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-03-28 13:31:25 -0400 |
commit | 4e52fc0a0a2ec2158691efba3f149f6416481255 (patch) | |
tree | 4f954e28a7dfc19fd7cb249b6eb31a0ea8939600 /drivers | |
parent | 1fce5e5da03b18505179882be27cc697f24d6b58 (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')
-rw-r--r-- | drivers/scsi/mvsas.c | 76 |
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 | ||
1787 | static u32 mvs_get_ncq_tag(struct sas_task *task) | 1787 | static 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 | ||
1798 | static int mvs_task_prep_ata(struct mvs_info *mvi, | 1802 | static 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 | ||
2131 | err_out_tag: | 2145 | err_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); |
2139 | exec_exit: | 2153 | out_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); |