Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] mvsas: Add new macros and functions

Add new macros: MVS_SOFT_RESET, MVS_HARD_RESET, MVS_PHY_TUNE,
MVS_COMMAND_ACTIVE, EXP_BRCT_CHG, MVS_MAX_SG
Add new member sg_width in struct mvs_chip_info
Use macros rather than magic number
Add new functions: mvs_fill_ssp_resp_iu, mvs_set_sense,
mvs_94xx_clear_srs_irq, mvs_94xx_phy_set_link_rate

Signed-off-by: Xiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

Xiangliang Yu and committed by
James Bottomley
a4632aae b89e8f53

+169 -56
+9 -9
drivers/scsi/mvsas/mv_64xx.c
··· 48 48 u32 tmp; 49 49 50 50 tmp = mr32(MVS_PCS); 51 - if (mvi->chip->n_phy <= 4) 51 + if (mvi->chip->n_phy <= MVS_SOC_PORTS) 52 52 tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT); 53 53 else 54 54 tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2); ··· 95 95 u32 reg, tmp; 96 96 97 97 if (!(mvi->flags & MVF_FLAG_SOC)) { 98 - if (phy_id < 4) 98 + if (phy_id < MVS_SOC_PORTS) 99 99 pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &reg); 100 100 else 101 101 pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &reg); ··· 104 104 reg = mr32(MVS_PHY_CTL); 105 105 106 106 tmp = reg; 107 - if (phy_id < 4) 107 + if (phy_id < MVS_SOC_PORTS) 108 108 tmp |= (1U << phy_id) << PCTL_LINK_OFFS; 109 109 else 110 - tmp |= (1U << (phy_id - 4)) << PCTL_LINK_OFFS; 110 + tmp |= (1U << (phy_id - MVS_SOC_PORTS)) << PCTL_LINK_OFFS; 111 111 112 112 if (!(mvi->flags & MVF_FLAG_SOC)) { 113 - if (phy_id < 4) { 113 + if (phy_id < MVS_SOC_PORTS) { 114 114 pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp); 115 115 mdelay(10); 116 116 pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, reg); ··· 133 133 tmp &= ~PHYEV_RDY_CH; 134 134 mvs_write_port_irq_stat(mvi, phy_id, tmp); 135 135 tmp = mvs_read_phy_ctl(mvi, phy_id); 136 - if (hard == 1) 136 + if (hard == MVS_HARD_RESET) 137 137 tmp |= PHY_RST_HARD; 138 - else if (hard == 0) 138 + else if (hard == MVS_SOFT_RESET) 139 139 tmp |= PHY_RST; 140 140 mvs_write_phy_ctl(mvi, phy_id, tmp); 141 141 if (hard) { ··· 346 346 347 347 mvs_64xx_enable_xmt(mvi, i); 348 348 349 - mvs_64xx_phy_reset(mvi, i, 1); 349 + mvs_64xx_phy_reset(mvi, i, MVS_HARD_RESET); 350 350 msleep(500); 351 351 mvs_64xx_detect_porttype(mvi, i); 352 352 } ··· 661 661 tmp |= lrmax; 662 662 } 663 663 mvs_write_phy_ctl(mvi, phy_id, tmp); 664 - mvs_64xx_phy_reset(mvi, phy_id, 1); 664 + mvs_64xx_phy_reset(mvi, phy_id, MVS_HARD_RESET); 665 665 } 666 666 667 667 static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi)
+59 -21
drivers/scsi/mvsas/mv_94xx.c
··· 389 389 mvs_phy_hacks(mvi); 390 390 391 391 /* set LED blink when IO*/ 392 - mw32(MVS_PA_VSR_ADDR, 0x00000030); 392 + mw32(MVS_PA_VSR_ADDR, VSR_PHY_ACT_LED); 393 393 tmp = mr32(MVS_PA_VSR_PORT); 394 394 tmp &= 0xFFFF00FF; 395 395 tmp |= 0x00003300; ··· 419 419 mvs_94xx_config_reg_from_hba(mvi, i); 420 420 mvs_94xx_phy_enable(mvi, i); 421 421 422 - mvs_94xx_phy_reset(mvi, i, 1); 422 + mvs_94xx_phy_reset(mvi, i, PHY_RST_HARD); 423 423 msleep(500); 424 424 mvs_94xx_detect_porttype(mvi, i); 425 425 } ··· 585 585 static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx) 586 586 { 587 587 u32 tmp; 588 - mvs_cw32(mvi, 0x300 + (slot_idx >> 3), 1 << (slot_idx % 32)); 589 - do { 590 - tmp = mvs_cr32(mvi, 0x300 + (slot_idx >> 3)); 591 - } while (tmp & 1 << (slot_idx % 32)); 588 + tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3)); 589 + if (tmp && 1 << (slot_idx % 32)) { 590 + mv_printk("command active %08X, slot [%x].\n", tmp, slot_idx); 591 + mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3), 592 + 1 << (slot_idx % 32)); 593 + do { 594 + tmp = mvs_cr32(mvi, 595 + MVS_COMMAND_ACTIVE + (slot_idx >> 3)); 596 + } while (tmp & 1 << (slot_idx % 32)); 597 + } 598 + } 599 + 600 + void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all) 601 + { 602 + void __iomem *regs = mvi->regs; 603 + u32 tmp; 604 + 605 + if (clear_all) { 606 + tmp = mr32(MVS_INT_STAT_SRS_0); 607 + if (tmp) { 608 + mv_dprintk("check SRS 0 %08X.\n", tmp); 609 + mw32(MVS_INT_STAT_SRS_0, tmp); 610 + } 611 + tmp = mr32(MVS_INT_STAT_SRS_1); 612 + if (tmp) { 613 + mv_dprintk("check SRS 1 %08X.\n", tmp); 614 + mw32(MVS_INT_STAT_SRS_1, tmp); 615 + } 616 + } else { 617 + if (reg_set > 31) 618 + tmp = mr32(MVS_INT_STAT_SRS_1); 619 + else 620 + tmp = mr32(MVS_INT_STAT_SRS_0); 621 + 622 + if (tmp & (1 << (reg_set % 32))) { 623 + mv_dprintk("register set 0x%x was stopped.\n", reg_set); 624 + if (reg_set > 31) 625 + mw32(MVS_INT_STAT_SRS_1, 1 << (reg_set % 32)); 626 + else 627 + mw32(MVS_INT_STAT_SRS_0, 1 << (reg_set % 32)); 628 + } 629 + } 592 630 } 593 631 594 632 static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type, ··· 634 596 { 635 597 void __iomem *regs = mvi->regs; 636 598 u32 tmp; 599 + mvs_94xx_clear_srs_irq(mvi, 0, 1); 637 600 638 - if (type == PORT_TYPE_SATA) { 639 - tmp = mr32(MVS_INT_STAT_SRS_0) | (1U << tfs); 640 - mw32(MVS_INT_STAT_SRS_0, tmp); 641 - } 642 - mw32(MVS_INT_STAT, CINT_CI_STOP); 601 + tmp = mr32(MVS_INT_STAT); 602 + mw32(MVS_INT_STAT, tmp | CINT_CI_STOP); 643 603 tmp = mr32(MVS_PCS) | 0xFF00; 644 604 mw32(MVS_PCS, tmp); 645 605 } ··· 830 794 void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, 831 795 struct sas_phy_linkrates *rates) 832 796 { 833 - /* TODO */ 797 + u32 lrmax = 0; 798 + u32 tmp; 799 + 800 + tmp = mvs_read_phy_ctl(mvi, phy_id); 801 + lrmax = (rates->maximum_linkrate - SAS_LINK_RATE_1_5_GBPS) << 12; 802 + 803 + if (lrmax) { 804 + tmp &= ~(0x3 << 12); 805 + tmp |= lrmax; 806 + } 807 + mvs_write_phy_ctl(mvi, phy_id, tmp); 808 + mvs_94xx_phy_reset(mvi, phy_id, PHY_RST_HARD); 834 809 } 835 810 836 811 static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi) ··· 938 891 buf_prd->im_len.len = cpu_to_le32(buf_len); 939 892 ++buf_prd; 940 893 } 941 - } 942 - 943 - /* 944 - * FIXME JEJB: temporary nop clear_srs_irq to make 94xx still work 945 - * with 64xx fixes 946 - */ 947 - static void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, 948 - u8 clear_all) 949 - { 950 894 } 951 895 952 896 static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time)
+2
drivers/scsi/mvsas/mv_94xx.h
··· 109 109 MVS_P4_VSR_DATA = 0x254, /* phy4 VSR data */ 110 110 MVS_PA_VSR_ADDR = 0x290, /* All port VSR addr */ 111 111 MVS_PA_VSR_PORT = 0x294, /* All port VSR data */ 112 + MVS_COMMAND_ACTIVE = 0x300, 112 113 }; 113 114 114 115 enum pci_cfg_registers { ··· 133 132 VSR_PHY_MODE9 = 0x09 * 4, /* Test */ 134 133 VSR_PHY_MODE10 = 0x0A * 4, /* Power */ 135 134 VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */ 135 + VSR_PHY_ACT_LED = 0x0C * 4, /* Activity LED control */ 136 136 137 137 VSR_PHY_FFE_CONTROL = 0x10C, 138 138 VSR_PHY_DFE_UPDATE_CRTL = 0x110,
+2 -1
drivers/scsi/mvsas/mv_defs.h
··· 395 395 }; 396 396 397 397 enum mvs_event_flags { 398 - PHY_PLUG_EVENT = (3U), 398 + PHY_PLUG_EVENT = (3U), 399 399 PHY_PLUG_IN = (1U << 0), /* phy plug in */ 400 400 PHY_PLUG_OUT = (1U << 1), /* phy plug out */ 401 + EXP_BRCT_CHG = (1U << 2), /* broadcast change */ 401 402 }; 402 403 403 404 enum mvs_port_type {
+11 -10
drivers/scsi/mvsas/mv_init.c
··· 39 39 static struct scsi_transport_template *mvs_stt; 40 40 struct kmem_cache *mvs_task_list_cache; 41 41 static const struct mvs_chip_info mvs_chips[] = { 42 - [chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, 43 - [chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, 44 - [chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, }, 45 - [chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, 46 - [chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, 47 - [chip_9445] = { 1, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, }, 48 - [chip_9485] = { 2, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, }, 49 - [chip_1300] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, 50 - [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, 42 + [chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, 43 + [chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, 44 + [chip_6485] = { 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, }, 45 + [chip_9180] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, 46 + [chip_9480] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, 47 + [chip_9445] = { 1, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, }, 48 + [chip_9485] = { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, }, 49 + [chip_1300] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, 50 + [chip_1320] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, 51 51 }; 52 52 53 53 struct device_attribute *mvst_host_attrs[]; ··· 466 466 ((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr; 467 467 468 468 shost->transportt = mvs_stt; 469 - shost->max_id = 128; 469 + shost->max_id = MVS_MAX_DEVICES; 470 470 shost->max_lun = ~0; 471 471 shost->max_channel = 1; 472 472 shost->max_cmd_len = 16; ··· 512 512 can_queue = MVS_CHIP_SLOT_SZ; 513 513 514 514 sha->lldd_queue_size = can_queue; 515 + shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG); 515 516 shost->can_queue = can_queue; 516 517 mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE; 517 518 sha->core.shost = mvi->shost;
+79 -15
drivers/scsi/mvsas/mv_sas.c
··· 203 203 tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id); 204 204 if (tmp & PHY_RST_HARD) 205 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 207 break; 208 208 209 209 case PHY_FUNC_LINK_RESET: 210 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 212 break; 213 213 214 214 case PHY_FUNC_DISABLE: ··· 1758 1758 return stat; 1759 1759 } 1760 1760 1761 + void 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 + 1800 + void 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 + 1761 1811 static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, 1762 1812 u32 slot_idx) 1763 1813 { 1764 1814 struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; 1765 1815 int stat; 1766 1816 u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response)); 1817 + u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response + 1)); 1767 1818 u32 tfs = 0; 1768 1819 enum mvs_port_type type = PORT_TYPE_SAS; 1769 1820 ··· 1826 1775 stat = SAM_STAT_CHECK_CONDITION; 1827 1776 switch (task->task_proto) { 1828 1777 case SAS_PROTOCOL_SSP: 1778 + { 1829 1779 stat = SAS_ABORTED_TASK; 1780 + if ((err_dw0 & NO_DEST) || err_dw1 & bit(31)) { 1781 + struct ssp_response_iu *iu = slot->response + 1782 + sizeof(struct mvs_err_info); 1783 + mvs_fill_ssp_resp_iu(iu, NOT_READY, 0x04, 01); 1784 + sas_ssp_task_response(mvi->dev, task, iu); 1785 + stat = SAM_STAT_CHECK_CONDITION; 1786 + } 1787 + if (err_dw1 & bit(31)) 1788 + mv_printk("reuse same slot, retry command.\n"); 1830 1789 break; 1790 + } 1831 1791 case SAS_PROTOCOL_SMP: 1832 1792 stat = SAM_STAT_CHECK_CONDITION; 1833 1793 break; ··· 2036 1974 struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q); 2037 1975 struct mvs_info *mvi = mwq->mvi; 2038 1976 unsigned long flags; 1977 + u32 phy_no = (unsigned long) mwq->data; 1978 + struct sas_ha_struct *sas_ha = mvi->sas; 1979 + struct mvs_phy *phy = &mvi->phy[phy_no]; 1980 + struct asd_sas_phy *sas_phy = &phy->sas_phy; 2039 1981 2040 1982 spin_lock_irqsave(&mvi->lock, flags); 2041 1983 if (mwq->handler & PHY_PLUG_EVENT) { 2042 - u32 phy_no = (unsigned long) mwq->data; 2043 - struct sas_ha_struct *sas_ha = mvi->sas; 2044 - struct mvs_phy *phy = &mvi->phy[phy_no]; 2045 - struct asd_sas_phy *sas_phy = &phy->sas_phy; 2046 1984 2047 1985 if (phy->phy_event & PHY_PLUG_OUT) { 2048 1986 u32 tmp; ··· 2064 2002 mv_dprintk("phy%d Attached Device\n", phy_no); 2065 2003 } 2066 2004 } 2005 + } else if (mwq->handler & EXP_BRCT_CHG) { 2006 + phy->phy_event &= ~EXP_BRCT_CHG; 2007 + sas_ha->notify_port_event(sas_phy, 2008 + PORTE_BROADCAST_RCVD); 2009 + mv_dprintk("phy%d Got Broadcast Change\n", phy_no); 2067 2010 } 2068 2011 list_del(&mwq->entry); 2069 2012 spin_unlock_irqrestore(&mvi->lock, flags); ··· 2104 2037 if (&mvi->phy[phy_no] == phy) { 2105 2038 mv_dprintk("Get signature time out, reset phy %d\n", 2106 2039 phy_no+mvi->id*mvi->chip->n_phy); 2107 - MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1); 2040 + MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_HARD_RESET); 2108 2041 } 2109 2042 } 2110 2043 } ··· 2112 2045 void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) 2113 2046 { 2114 2047 u32 tmp; 2115 - struct sas_ha_struct *sas_ha = mvi->sas; 2116 2048 struct mvs_phy *phy = &mvi->phy[phy_no]; 2117 - struct asd_sas_phy *sas_phy = &phy->sas_phy; 2118 2049 2119 2050 phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no); 2120 2051 mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy, ··· 2151 2086 phy_no); 2152 2087 else 2153 2088 MVS_CHIP_DISP->phy_reset(mvi, 2154 - phy_no, 0); 2089 + phy_no, MVS_SOFT_RESET); 2155 2090 return; 2156 2091 } 2157 2092 } ··· 2183 2118 } 2184 2119 mvs_update_phyinfo(mvi, phy_no, 0); 2185 2120 if (phy->phy_type & PORT_TYPE_SAS) { 2186 - MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2); 2121 + MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_PHY_TUNE); 2187 2122 mdelay(10); 2188 2123 } 2189 2124 2190 2125 mvs_bytes_dmaed(mvi, phy_no); 2191 2126 /* whether driver is going to handle hot plug */ 2192 2127 if (phy->phy_event & PHY_PLUG_OUT) { 2193 - mvs_port_notify_formed(sas_phy, 0); 2128 + mvs_port_notify_formed(&phy->sas_phy, 0); 2194 2129 phy->phy_event &= ~PHY_PLUG_OUT; 2195 2130 } 2196 2131 } else { ··· 2200 2135 } else if (phy->irq_status & PHYEV_BROAD_CH) { 2201 2136 mv_dprintk("port %d broadcast change.\n", 2202 2137 phy_no + mvi->id*mvi->chip->n_phy); 2203 - /* exception for Samsung disk drive*/ 2204 - mdelay(1000); 2205 - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); 2138 + mvs_handle_event(mvi, (void *)(unsigned long)phy_no, 2139 + EXP_BRCT_CHG); 2206 2140 } 2207 2141 MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status); 2208 2142 }
+7
drivers/scsi/mvsas/mv_sas.h
··· 96 96 MVS_DEV_EH = 0x1, 97 97 }; 98 98 99 + enum dev_reset { 100 + MVS_SOFT_RESET = 0, 101 + MVS_HARD_RESET = 1, 102 + MVS_PHY_TUNE = 2, 103 + }; 99 104 100 105 struct mvs_info; 101 106 ··· 181 176 u32 fis_offs; 182 177 u32 fis_count; 183 178 u32 srs_sz; 179 + u32 sg_width; 184 180 u32 slot_width; 185 181 const struct mvs_dispatch *dispatch; 186 182 }; 183 + #define MVS_MAX_SG (1U << mvi->chip->sg_width) 187 184 #define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width) 188 185 #define MVS_RX_FISL_SZ \ 189 186 (mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100))