aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mvsas/mv_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mvsas/mv_sas.c')
-rw-r--r--drivers/scsi/mvsas/mv_sas.c94
1 files changed, 79 insertions, 15 deletions
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 7bd0ee3ed2d6..38b47918c047 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -203,12 +203,12 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
203 tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id); 203 tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id);
204 if (tmp & PHY_RST_HARD) 204 if (tmp & PHY_RST_HARD)
205 break; 205 break;
206 MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1); 206 MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_HARD_RESET);
207 break; 207 break;
208 208
209 case PHY_FUNC_LINK_RESET: 209 case PHY_FUNC_LINK_RESET:
210 MVS_CHIP_DISP->phy_enable(mvi, phy_id); 210 MVS_CHIP_DISP->phy_enable(mvi, phy_id);
211 MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0); 211 MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_SOFT_RESET);
212 break; 212 break;
213 213
214 case PHY_FUNC_DISABLE: 214 case PHY_FUNC_DISABLE:
@@ -1758,12 +1758,63 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
1758 return stat; 1758 return stat;
1759} 1759}
1760 1760
1761void mvs_set_sense(u8 *buffer, int len, int d_sense,
1762 int key, int asc, int ascq)
1763{
1764 memset(buffer, 0, len);
1765
1766 if (d_sense) {
1767 /* Descriptor format */
1768 if (len < 4) {
1769 mv_printk("Length %d of sense buffer too small to "
1770 "fit sense %x:%x:%x", len, key, asc, ascq);
1771 }
1772
1773 buffer[0] = 0x72; /* Response Code */
1774 if (len > 1)
1775 buffer[1] = key; /* Sense Key */
1776 if (len > 2)
1777 buffer[2] = asc; /* ASC */
1778 if (len > 3)
1779 buffer[3] = ascq; /* ASCQ */
1780 } else {
1781 if (len < 14) {
1782 mv_printk("Length %d of sense buffer too small to "
1783 "fit sense %x:%x:%x", len, key, asc, ascq);
1784 }
1785
1786 buffer[0] = 0x70; /* Response Code */
1787 if (len > 2)
1788 buffer[2] = key; /* Sense Key */
1789 if (len > 7)
1790 buffer[7] = 0x0a; /* Additional Sense Length */
1791 if (len > 12)
1792 buffer[12] = asc; /* ASC */
1793 if (len > 13)
1794 buffer[13] = ascq; /* ASCQ */
1795 }
1796
1797 return;
1798}
1799
1800void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu,
1801 u8 key, u8 asc, u8 asc_q)
1802{
1803 iu->datapres = 2;
1804 iu->response_data_len = 0;
1805 iu->sense_data_len = 17;
1806 iu->status = 02;
1807 mvs_set_sense(iu->sense_data, 17, 0,
1808 key, asc, asc_q);
1809}
1810
1761static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, 1811static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
1762 u32 slot_idx) 1812 u32 slot_idx)
1763{ 1813{
1764 struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; 1814 struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
1765 int stat; 1815 int stat;
1766 u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response)); 1816 u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
1817 u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response + 1));
1767 u32 tfs = 0; 1818 u32 tfs = 0;
1768 enum mvs_port_type type = PORT_TYPE_SAS; 1819 enum mvs_port_type type = PORT_TYPE_SAS;
1769 1820
@@ -1775,8 +1826,19 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
1775 stat = SAM_STAT_CHECK_CONDITION; 1826 stat = SAM_STAT_CHECK_CONDITION;
1776 switch (task->task_proto) { 1827 switch (task->task_proto) {
1777 case SAS_PROTOCOL_SSP: 1828 case SAS_PROTOCOL_SSP:
1829 {
1778 stat = SAS_ABORTED_TASK; 1830 stat = SAS_ABORTED_TASK;
1831 if ((err_dw0 & NO_DEST) || err_dw1 & bit(31)) {
1832 struct ssp_response_iu *iu = slot->response +
1833 sizeof(struct mvs_err_info);
1834 mvs_fill_ssp_resp_iu(iu, NOT_READY, 0x04, 01);
1835 sas_ssp_task_response(mvi->dev, task, iu);
1836 stat = SAM_STAT_CHECK_CONDITION;
1837 }
1838 if (err_dw1 & bit(31))
1839 mv_printk("reuse same slot, retry command.\n");
1779 break; 1840 break;
1841 }
1780 case SAS_PROTOCOL_SMP: 1842 case SAS_PROTOCOL_SMP:
1781 stat = SAM_STAT_CHECK_CONDITION; 1843 stat = SAM_STAT_CHECK_CONDITION;
1782 break; 1844 break;
@@ -1974,13 +2036,13 @@ static void mvs_work_queue(struct work_struct *work)
1974 struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q); 2036 struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);
1975 struct mvs_info *mvi = mwq->mvi; 2037 struct mvs_info *mvi = mwq->mvi;
1976 unsigned long flags; 2038 unsigned long flags;
2039 u32 phy_no = (unsigned long) mwq->data;
2040 struct sas_ha_struct *sas_ha = mvi->sas;
2041 struct mvs_phy *phy = &mvi->phy[phy_no];
2042 struct asd_sas_phy *sas_phy = &phy->sas_phy;
1977 2043
1978 spin_lock_irqsave(&mvi->lock, flags); 2044 spin_lock_irqsave(&mvi->lock, flags);
1979 if (mwq->handler & PHY_PLUG_EVENT) { 2045 if (mwq->handler & PHY_PLUG_EVENT) {
1980 u32 phy_no = (unsigned long) mwq->data;
1981 struct sas_ha_struct *sas_ha = mvi->sas;
1982 struct mvs_phy *phy = &mvi->phy[phy_no];
1983 struct asd_sas_phy *sas_phy = &phy->sas_phy;
1984 2046
1985 if (phy->phy_event & PHY_PLUG_OUT) { 2047 if (phy->phy_event & PHY_PLUG_OUT) {
1986 u32 tmp; 2048 u32 tmp;
@@ -2002,6 +2064,11 @@ static void mvs_work_queue(struct work_struct *work)
2002 mv_dprintk("phy%d Attached Device\n", phy_no); 2064 mv_dprintk("phy%d Attached Device\n", phy_no);
2003 } 2065 }
2004 } 2066 }
2067 } else if (mwq->handler & EXP_BRCT_CHG) {
2068 phy->phy_event &= ~EXP_BRCT_CHG;
2069 sas_ha->notify_port_event(sas_phy,
2070 PORTE_BROADCAST_RCVD);
2071 mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
2005 } 2072 }
2006 list_del(&mwq->entry); 2073 list_del(&mwq->entry);
2007 spin_unlock_irqrestore(&mvi->lock, flags); 2074 spin_unlock_irqrestore(&mvi->lock, flags);
@@ -2037,7 +2104,7 @@ static void mvs_sig_time_out(unsigned long tphy)
2037 if (&mvi->phy[phy_no] == phy) { 2104 if (&mvi->phy[phy_no] == phy) {
2038 mv_dprintk("Get signature time out, reset phy %d\n", 2105 mv_dprintk("Get signature time out, reset phy %d\n",
2039 phy_no+mvi->id*mvi->chip->n_phy); 2106 phy_no+mvi->id*mvi->chip->n_phy);
2040 MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1); 2107 MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_HARD_RESET);
2041 } 2108 }
2042 } 2109 }
2043} 2110}
@@ -2045,9 +2112,7 @@ static void mvs_sig_time_out(unsigned long tphy)
2045void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) 2112void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
2046{ 2113{
2047 u32 tmp; 2114 u32 tmp;
2048 struct sas_ha_struct *sas_ha = mvi->sas;
2049 struct mvs_phy *phy = &mvi->phy[phy_no]; 2115 struct mvs_phy *phy = &mvi->phy[phy_no];
2050 struct asd_sas_phy *sas_phy = &phy->sas_phy;
2051 2116
2052 phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no); 2117 phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no);
2053 mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy, 2118 mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy,
@@ -2086,7 +2151,7 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
2086 phy_no); 2151 phy_no);
2087 else 2152 else
2088 MVS_CHIP_DISP->phy_reset(mvi, 2153 MVS_CHIP_DISP->phy_reset(mvi,
2089 phy_no, 0); 2154 phy_no, MVS_SOFT_RESET);
2090 return; 2155 return;
2091 } 2156 }
2092 } 2157 }
@@ -2118,14 +2183,14 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
2118 } 2183 }
2119 mvs_update_phyinfo(mvi, phy_no, 0); 2184 mvs_update_phyinfo(mvi, phy_no, 0);
2120 if (phy->phy_type & PORT_TYPE_SAS) { 2185 if (phy->phy_type & PORT_TYPE_SAS) {
2121 MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2); 2186 MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_PHY_TUNE);
2122 mdelay(10); 2187 mdelay(10);
2123 } 2188 }
2124 2189
2125 mvs_bytes_dmaed(mvi, phy_no); 2190 mvs_bytes_dmaed(mvi, phy_no);
2126 /* whether driver is going to handle hot plug */ 2191 /* whether driver is going to handle hot plug */
2127 if (phy->phy_event & PHY_PLUG_OUT) { 2192 if (phy->phy_event & PHY_PLUG_OUT) {
2128 mvs_port_notify_formed(sas_phy, 0); 2193 mvs_port_notify_formed(&phy->sas_phy, 0);
2129 phy->phy_event &= ~PHY_PLUG_OUT; 2194 phy->phy_event &= ~PHY_PLUG_OUT;
2130 } 2195 }
2131 } else { 2196 } else {
@@ -2135,9 +2200,8 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
2135 } else if (phy->irq_status & PHYEV_BROAD_CH) { 2200 } else if (phy->irq_status & PHYEV_BROAD_CH) {
2136 mv_dprintk("port %d broadcast change.\n", 2201 mv_dprintk("port %d broadcast change.\n",
2137 phy_no + mvi->id*mvi->chip->n_phy); 2202 phy_no + mvi->id*mvi->chip->n_phy);
2138 /* exception for Samsung disk drive*/ 2203 mvs_handle_event(mvi, (void *)(unsigned long)phy_no,
2139 mdelay(1000); 2204 EXP_BRCT_CHG);
2140 sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
2141 } 2205 }
2142 MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status); 2206 MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
2143} 2207}