From 534ff10104427ccad071ef87ae7017d47d08e50b Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Tue, 24 May 2011 22:26:50 +0800 Subject: [SCSI] mvsas: Add support for Non specific NCQ error interrupt Signed-off-by: Xiangliang Yu Signed-off-by: James Bottomley --- drivers/scsi/mvsas/mv_64xx.c | 1 + drivers/scsi/mvsas/mv_94xx.c | 32 +++++++++++++++++++++++++++++++- drivers/scsi/mvsas/mv_chips.h | 3 +++ drivers/scsi/mvsas/mv_defs.h | 1 + drivers/scsi/mvsas/mv_sas.c | 14 ++++++++++++++ drivers/scsi/mvsas/mv_sas.h | 2 ++ 6 files changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c index 13c960481391..0e13e6441da7 100644 --- a/drivers/scsi/mvsas/mv_64xx.c +++ b/drivers/scsi/mvsas/mv_64xx.c @@ -811,5 +811,6 @@ const struct mvs_dispatch mvs_64xx_dispatch = { #ifndef DISABLE_HOTPLUG_DMA_FIX mvs_64xx_fix_dma, #endif + NULL, }; diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 78162c3c36e6..9d60c7c19b32 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -249,7 +249,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) /* enable completion queue interrupt */ tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP | - CINT_DMA_PCIE); + CINT_DMA_PCIE | CINT_NON_SPEC_NCQ_ERROR); tmp |= CINT_PHY_MASK; mw32(MVS_INT_MASK, tmp); @@ -367,6 +367,35 @@ static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type, mw32(MVS_PCS, tmp); } +static void mvs_94xx_non_spec_ncq_error(struct mvs_info *mvi) +{ + void __iomem *regs = mvi->regs; + u32 err_0, err_1; + u8 i; + struct mvs_device *device; + + err_0 = mr32(MVS_NON_NCQ_ERR_0); + err_1 = mr32(MVS_NON_NCQ_ERR_1); + + mv_dprintk("non specific ncq error err_0:%x,err_1:%x.\n", + err_0, err_1); + for (i = 0; i < 32; i++) { + if (err_0 & bit(i)) { + device = mvs_find_dev_by_reg_set(mvi, i); + if (device) + mvs_release_task(mvi, device->sas_device); + } + if (err_1 & bit(i)) { + device = mvs_find_dev_by_reg_set(mvi, i+32); + if (device) + mvs_release_task(mvi, device->sas_device); + } + } + + mw32(MVS_NON_NCQ_ERR_0, err_0); + mw32(MVS_NON_NCQ_ERR_1, err_1); +} + static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs) { void __iomem *regs = mvi->regs; @@ -679,5 +708,6 @@ const struct mvs_dispatch mvs_94xx_dispatch = { #ifndef DISABLE_HOTPLUG_DMA_FIX mvs_94xx_fix_dma, #endif + mvs_94xx_non_spec_ncq_error, }; diff --git a/drivers/scsi/mvsas/mv_chips.h b/drivers/scsi/mvsas/mv_chips.h index 1753a6fc42d0..4519f809a8df 100644 --- a/drivers/scsi/mvsas/mv_chips.h +++ b/drivers/scsi/mvsas/mv_chips.h @@ -223,6 +223,9 @@ static inline void mvs_int_full(struct mvs_info *mvi) mvs_int_port(mvi, i, tmp); } + if (stat & CINT_NON_SPEC_NCQ_ERROR) + MVS_CHIP_DISP->non_spec_ncq_error(mvi); + if (stat & CINT_SRS) mvs_int_sata(mvi); diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h index bc00c940743c..9202bc68801d 100644 --- a/drivers/scsi/mvsas/mv_defs.h +++ b/drivers/scsi/mvsas/mv_defs.h @@ -144,6 +144,7 @@ enum hw_register_bits { CINT_DMA_PCIE = (1U << 27), /* DMA to PCIE timeout */ CINT_MEM = (1U << 26), /* int mem parity err */ CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */ + CINT_NON_SPEC_NCQ_ERROR = (1U << 25), /* Non specific NCQ error */ CINT_SRS = (1U << 3), /* SRS event */ CINT_CI_STOP = (1U << 1), /* cmd issue stopped */ CINT_DONE = (1U << 0), /* cmd completion */ diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 0ef27425c447..aaa475a3eda6 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -253,6 +253,20 @@ int mvs_find_dev_phyno(struct domain_device *dev, int *phyno) return num; } +struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi, + u8 reg_set) +{ + u32 dev_no; + for (dev_no = 0; dev_no < MVS_MAX_DEVICES; dev_no++) { + if (mvi->devices[dev_no].taskfileset == MVS_ID_NOT_MAPPED) + continue; + + if (mvi->devices[dev_no].taskfileset == reg_set) + return &mvi->devices[dev_no]; + } + return NULL; +} + static inline void mvs_free_reg_set(struct mvs_info *mvi, struct mvs_device *dev) { diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 1367d8b9350d..f96100d7aee1 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -170,6 +170,7 @@ struct mvs_dispatch { #ifndef DISABLE_HOTPLUG_DMA_FIX void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd); #endif + void (*non_spec_ncq_error)(struct mvs_info *mvi); }; @@ -416,5 +417,6 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events); void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); int mvs_int_rx(struct mvs_info *mvi, bool self_clear); void mvs_hexdump(u32 size, u8 *data, u32 baseaddr); +struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi, u8 reg_set); #endif -- cgit v1.2.3 From f1f82a919d7fff21ee8c0ef4b9731fb38f2a65db Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Tue, 24 May 2011 22:28:31 +0800 Subject: [SCSI] mvsas: add support for 94xx phy tuning and multiple revisions Add 94xx phy tuning to aid manufacturing. Add support for 94xx multiple revisions: A0, B0, C0, C1, C2. Signed-off-by: Xiangliang Yu Signed-off-by: James Bottomley --- drivers/scsi/mvsas/mv_94xx.c | 267 ++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/mvsas/mv_94xx.h | 58 ++++++++++ drivers/scsi/mvsas/mv_init.c | 3 + drivers/scsi/mvsas/mv_sas.h | 68 +++++++++++ 4 files changed, 382 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 9d60c7c19b32..3f2ad934c917 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -48,6 +48,216 @@ static void mvs_94xx_detect_porttype(struct mvs_info *mvi, int i) } } +void set_phy_tuning(struct mvs_info *mvi, int phy_id, + struct phy_tuning phy_tuning) +{ + u32 tmp, setting_0 = 0, setting_1 = 0; + u8 i; + + /* Remap information for B0 chip: + * + * R0Ch -> R118h[15:0] (Adapted DFE F3 - F5 coefficient) + * R0Dh -> R118h[31:16] (Generation 1 Setting 0) + * R0Eh -> R11Ch[15:0] (Generation 1 Setting 1) + * R0Fh -> R11Ch[31:16] (Generation 2 Setting 0) + * R10h -> R120h[15:0] (Generation 2 Setting 1) + * R11h -> R120h[31:16] (Generation 3 Setting 0) + * R12h -> R124h[15:0] (Generation 3 Setting 1) + * R13h -> R124h[31:16] (Generation 4 Setting 0 (Reserved)) + */ + + /* A0 has a different set of registers */ + if (mvi->pdev->revision == VANIR_A0_REV) + return; + + for (i = 0; i < 3; i++) { + /* loop 3 times, set Gen 1, Gen 2, Gen 3 */ + switch (i) { + case 0: + setting_0 = GENERATION_1_SETTING; + setting_1 = GENERATION_1_2_SETTING; + break; + case 1: + setting_0 = GENERATION_1_2_SETTING; + setting_1 = GENERATION_2_3_SETTING; + break; + case 2: + setting_0 = GENERATION_2_3_SETTING; + setting_1 = GENERATION_3_4_SETTING; + break; + } + + /* Set: + * + * Transmitter Emphasis Enable + * Transmitter Emphasis Amplitude + * Transmitter Amplitude + */ + mvs_write_port_vsr_addr(mvi, phy_id, setting_0); + tmp = mvs_read_port_vsr_data(mvi, phy_id); + tmp &= ~(0xFBE << 16); + tmp |= (((phy_tuning.trans_emp_en << 11) | + (phy_tuning.trans_emp_amp << 7) | + (phy_tuning.trans_amp << 1)) << 16); + mvs_write_port_vsr_data(mvi, phy_id, tmp); + + /* Set Transmitter Amplitude Adjust */ + mvs_write_port_vsr_addr(mvi, phy_id, setting_1); + tmp = mvs_read_port_vsr_data(mvi, phy_id); + tmp &= ~(0xC000); + tmp |= (phy_tuning.trans_amp_adj << 14); + mvs_write_port_vsr_data(mvi, phy_id, tmp); + } +} + +void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id, + struct ffe_control ffe) +{ + u32 tmp; + + /* Don't run this if A0/B0 */ + if ((mvi->pdev->revision == VANIR_A0_REV) + || (mvi->pdev->revision == VANIR_B0_REV)) + return; + + /* FFE Resistor and Capacitor */ + /* R10Ch DFE Resolution Control/Squelch and FFE Setting + * + * FFE_FORCE [7] + * FFE_RES_SEL [6:4] + * FFE_CAP_SEL [3:0] + */ + mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_FFE_CONTROL); + tmp = mvs_read_port_vsr_data(mvi, phy_id); + tmp &= ~0xFF; + + /* Read from HBA_Info_Page */ + tmp |= ((0x1 << 7) | + (ffe.ffe_rss_sel << 4) | + (ffe.ffe_cap_sel << 0)); + + mvs_write_port_vsr_data(mvi, phy_id, tmp); + + /* R064h PHY Mode Register 1 + * + * DFE_DIS 18 + */ + mvs_write_port_vsr_addr(mvi, phy_id, VSR_REF_CLOCK_CRTL); + tmp = mvs_read_port_vsr_data(mvi, phy_id); + tmp &= ~0x40001; + /* Hard coding */ + /* No defines in HBA_Info_Page */ + tmp |= (0 << 18); + mvs_write_port_vsr_data(mvi, phy_id, tmp); + + /* R110h DFE F0-F1 Coefficient Control/DFE Update Control + * + * DFE_UPDATE_EN [11:6] + * DFE_FX_FORCE [5:0] + */ + mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_DFE_UPDATE_CRTL); + tmp = mvs_read_port_vsr_data(mvi, phy_id); + tmp &= ~0xFFF; + /* Hard coding */ + /* No defines in HBA_Info_Page */ + tmp |= ((0x3F << 6) | (0x0 << 0)); + mvs_write_port_vsr_data(mvi, phy_id, tmp); + + /* R1A0h Interface and Digital Reference Clock Control/Reserved_50h + * + * FFE_TRAIN_EN 3 + */ + mvs_write_port_vsr_addr(mvi, phy_id, VSR_REF_CLOCK_CRTL); + tmp = mvs_read_port_vsr_data(mvi, phy_id); + tmp &= ~0x8; + /* Hard coding */ + /* No defines in HBA_Info_Page */ + tmp |= (0 << 3); + mvs_write_port_vsr_data(mvi, phy_id, tmp); +} + +/*Notice: this function must be called when phy is disabled*/ +void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate) +{ + union reg_phy_cfg phy_cfg, phy_cfg_tmp; + mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2); + phy_cfg_tmp.v = mvs_read_port_vsr_data(mvi, phy_id); + phy_cfg.v = 0; + phy_cfg.u.disable_phy = phy_cfg_tmp.u.disable_phy; + phy_cfg.u.sas_support = 1; + phy_cfg.u.sata_support = 1; + phy_cfg.u.sata_host_mode = 1; + + switch (rate) { + case 0x0: + /* support 1.5 Gbps */ + phy_cfg.u.speed_support = 1; + phy_cfg.u.snw_3_support = 0; + phy_cfg.u.tx_lnk_parity = 1; + phy_cfg.u.tx_spt_phs_lnk_rate = 0x30; + break; + case 0x1: + + /* support 1.5, 3.0 Gbps */ + phy_cfg.u.speed_support = 3; + phy_cfg.u.tx_spt_phs_lnk_rate = 0x3c; + phy_cfg.u.tx_lgcl_lnk_rate = 0x08; + break; + case 0x2: + default: + /* support 1.5, 3.0, 6.0 Gbps */ + phy_cfg.u.speed_support = 7; + phy_cfg.u.snw_3_support = 1; + phy_cfg.u.tx_lnk_parity = 1; + phy_cfg.u.tx_spt_phs_lnk_rate = 0x3f; + phy_cfg.u.tx_lgcl_lnk_rate = 0x09; + break; + } + mvs_write_port_vsr_data(mvi, phy_id, phy_cfg.v); +} + +static void __devinit +mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id) +{ + u32 temp; + temp = (u32)(*(u32 *)&mvi->hba_info_param.phy_tuning[phy_id]); + if (temp == 0xFFFFFFFFL) { + mvi->hba_info_param.phy_tuning[phy_id].trans_emp_amp = 0x6; + mvi->hba_info_param.phy_tuning[phy_id].trans_amp = 0x1A; + mvi->hba_info_param.phy_tuning[phy_id].trans_amp_adj = 0x3; + } + + temp = (u8)(*(u8 *)&mvi->hba_info_param.ffe_ctl[phy_id]); + if (temp == 0xFFL) { + switch (mvi->pdev->revision) { + case VANIR_A0_REV: + case VANIR_B0_REV: + mvi->hba_info_param.ffe_ctl[phy_id].ffe_rss_sel = 0x7; + mvi->hba_info_param.ffe_ctl[phy_id].ffe_cap_sel = 0x7; + break; + case VANIR_C0_REV: + case VANIR_C1_REV: + case VANIR_C2_REV: + default: + mvi->hba_info_param.ffe_ctl[phy_id].ffe_rss_sel = 0x7; + mvi->hba_info_param.ffe_ctl[phy_id].ffe_cap_sel = 0xC; + break; + } + } + + temp = (u8)(*(u8 *)&mvi->hba_info_param.phy_rate[phy_id]); + if (temp == 0xFFL) + /*set default phy_rate = 6Gbps*/ + mvi->hba_info_param.phy_rate[phy_id] = 0x2; + + set_phy_tuning(mvi, phy_id, + mvi->hba_info_param.phy_tuning[phy_id]); + set_phy_ffe_tuning(mvi, phy_id, + mvi->hba_info_param.ffe_ctl[phy_id]); + set_phy_rate(mvi, phy_id, + mvi->hba_info_param.phy_rate[phy_id]); +} + static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id) { void __iomem *regs = mvi->regs; @@ -90,12 +300,25 @@ static void mvs_94xx_phy_disable(struct mvs_info *mvi, u32 phy_id) static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id) { - mvs_write_port_vsr_addr(mvi, phy_id, 0x1B4); - mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1); - mvs_write_port_vsr_addr(mvi, phy_id, 0x104); - mvs_write_port_vsr_data(mvi, phy_id, 0x00018080); + u32 tmp; + u8 revision = 0; + + revision = mvi->pdev->revision; + if (revision == VANIR_A0_REV) { + mvs_write_port_vsr_addr(mvi, phy_id, CMD_HOST_RD_DATA); + mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1); + } + if (revision == VANIR_B0_REV) { + mvs_write_port_vsr_addr(mvi, phy_id, CMD_APP_MEM_CTL); + mvs_write_port_vsr_data(mvi, phy_id, 0x08001006); + mvs_write_port_vsr_addr(mvi, phy_id, CMD_HOST_RD_DATA); + mvs_write_port_vsr_data(mvi, phy_id, 0x0000705f); + } + mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2); - mvs_write_port_vsr_data(mvi, phy_id, 0x00207fff); + tmp = mvs_read_port_vsr_data(mvi, phy_id); + tmp |= bit(0); + mvs_write_port_vsr_data(mvi, phy_id, tmp & 0xfd7fffff); } static int __devinit mvs_94xx_init(struct mvs_info *mvi) @@ -103,7 +326,9 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) void __iomem *regs = mvi->regs; int i; u32 tmp, cctl; + u8 revision; + revision = mvi->pdev->revision; mvs_show_pcie_usage(mvi); if (mvi->flags & MVF_FLAG_SOC) { tmp = mr32(MVS_PHY_CTL); @@ -133,6 +358,28 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) msleep(100); } + /* disable Multiplexing, enable phy implemented */ + mw32(MVS_PORTS_IMP, 0xFF); + + if (revision == VANIR_A0_REV) { + mw32(MVS_PA_VSR_ADDR, CMD_CMWK_OOB_DET); + mw32(MVS_PA_VSR_PORT, 0x00018080); + } + mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE2); + if (revision == VANIR_A0_REV || revision == VANIR_B0_REV) + /* set 6G/3G/1.5G, multiplexing, without SSC */ + mw32(MVS_PA_VSR_PORT, 0x0084d4fe); + else + /* set 6G/3G/1.5G, multiplexing, with and without SSC */ + mw32(MVS_PA_VSR_PORT, 0x0084fffe); + + if (revision == VANIR_B0_REV) { + mw32(MVS_PA_VSR_ADDR, CMD_APP_MEM_CTL); + mw32(MVS_PA_VSR_PORT, 0x08001006); + mw32(MVS_PA_VSR_ADDR, CMD_HOST_RD_DATA); + mw32(MVS_PA_VSR_PORT, 0x0000705f); + } + /* reset control */ mw32(MVS_PCS, 0); /* MVS_PCS */ mw32(MVS_STP_REG_SET_0, 0); @@ -141,15 +388,6 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) /* init phys */ mvs_phy_hacks(mvi); - /* disable Multiplexing, enable phy implemented */ - mw32(MVS_PORTS_IMP, 0xFF); - - - mw32(MVS_PA_VSR_ADDR, 0x00000104); - mw32(MVS_PA_VSR_PORT, 0x00018080); - mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE8); - mw32(MVS_PA_VSR_PORT, 0x0084ffff); - /* set LED blink when IO*/ mw32(MVS_PA_VSR_ADDR, 0x00000030); tmp = mr32(MVS_PA_VSR_PORT); @@ -178,6 +416,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) (mvi->phy[i].dev_sas_addr)); mvs_94xx_enable_xmt(mvi, i); + mvs_94xx_config_reg_from_hba(mvi, i); mvs_94xx_phy_enable(mvi, i); mvs_94xx_phy_reset(mvi, i, 1); diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h index 8835befe2c0e..33af2a1fb729 100644 --- a/drivers/scsi/mvsas/mv_94xx.h +++ b/drivers/scsi/mvsas/mv_94xx.h @@ -30,6 +30,14 @@ #define MAX_LINK_RATE SAS_LINK_RATE_6_0_GBPS +enum VANIR_REVISION_ID { + VANIR_A0_REV = 0xA0, + VANIR_B0_REV = 0x01, + VANIR_C0_REV = 0x02, + VANIR_C1_REV = 0x03, + VANIR_C2_REV = 0xC2, +}; + enum hw_registers { MVS_GBL_CTL = 0x04, /* global control */ MVS_GBL_INT_STAT = 0x00, /* global irq status */ @@ -126,6 +134,10 @@ enum sas_sata_vsp_regs { VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */ VSR_PHY_VS0 = 0x0C * 4, /* Vednor Specific 0 */ VSR_PHY_VS1 = 0x0D * 4, /* Vednor Specific 1 */ + + VSR_PHY_FFE_CONTROL = 0x10C, + VSR_PHY_DFE_UPDATE_CRTL = 0x110, + VSR_REF_CLOCK_CRTL = 0x1A0, }; enum chip_register_bits { @@ -169,6 +181,41 @@ enum pci_interrupt_cause { IRQ_PCIE_ERR = (1 << 31), }; +union reg_phy_cfg { + u32 v; + struct { + u32 phy_reset:1; + u32 sas_support:1; + u32 sata_support:1; + u32 sata_host_mode:1; + /* + * bit 2: 6Gbps support + * bit 1: 3Gbps support + * bit 0: 1.5Gbps support + */ + u32 speed_support:3; + u32 snw_3_support:1; + u32 tx_lnk_parity:1; + /* + * bit 5: G1 (1.5Gbps) Without SSC + * bit 4: G1 (1.5Gbps) with SSC + * bit 3: G2 (3.0Gbps) Without SSC + * bit 2: G2 (3.0Gbps) with SSC + * bit 1: G3 (6.0Gbps) without SSC + * bit 0: G3 (6.0Gbps) with SSC + */ + u32 tx_spt_phs_lnk_rate:6; + /* 8h: 1.5Gbps 9h: 3Gbps Ah: 6Gbps */ + u32 tx_lgcl_lnk_rate:4; + u32 tx_ssc_type:1; + u32 sata_spin_up_spt:1; + u32 sata_spin_up_en:1; + u32 bypass_oob:1; + u32 disable_phy:1; + u32 rsvd:8; + } u; +}; + #define MAX_SG_ENTRY 255 struct mvs_prd_imt { @@ -185,6 +232,17 @@ struct mvs_prd { struct mvs_prd_imt im_len; } __attribute__ ((packed)); +/* + * these registers are accessed through port vendor + * specific address/data registers + */ +enum sas_sata_phy_regs { + GENERATION_1_SETTING = 0x118, + GENERATION_1_2_SETTING = 0x11C, + GENERATION_2_3_SETTING = 0x120, + GENERATION_3_4_SETTING = 0x124, +}; + #define SPI_CTRL_REG_94XX 0xc800 #define SPI_ADDR_REG_94XX 0xc804 #define SPI_WR_DATA_REG_94XX 0xc808 diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 90b636611cde..9f1cccc2a3ed 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -569,6 +569,9 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev, goto err_out_regions; } + memset(&mvi->hba_info_param, 0xFF, + sizeof(struct hba_info_page)); + mvs_init_sas_add(mvi); mvi->instance = nhost; diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index f96100d7aee1..ccd622f7f841 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -250,6 +250,73 @@ struct mvs_device { u16 reserved; }; +/* Generate PHY tunning parameters */ +struct phy_tuning { + /* 1 bit, transmitter emphasis enable */ + u8 trans_emp_en:1; + /* 4 bits, transmitter emphasis amplitude */ + u8 trans_emp_amp:4; + /* 3 bits, reserved space */ + u8 Reserved_2bit_1:3; + /* 5 bits, transmitter amplitude */ + u8 trans_amp:5; + /* 2 bits, transmitter amplitude adjust */ + u8 trans_amp_adj:2; + /* 1 bit, reserved space */ + u8 resv_2bit_2:1; + /* 2 bytes, reserved space */ + u8 reserved[2]; +}; + +struct ffe_control { + /* 4 bits, FFE Capacitor Select (value range 0~F) */ + u8 ffe_cap_sel:4; + /* 3 bits, FFE Resistor Select (value range 0~7) */ + u8 ffe_rss_sel:3; + /* 1 bit reserve*/ + u8 reserved:1; +}; + +/* + * HBA_Info_Page is saved in Flash/NVRAM, total 256 bytes. + * The data area is valid only Signature="MRVL". + * If any member fills with 0xFF, the member is invalid. + */ +struct hba_info_page { + /* Dword 0 */ + /* 4 bytes, structure signature,should be "MRVL" at first initial */ + u8 signature[4]; + + /* Dword 1-13 */ + u32 reserved1[13]; + + /* Dword 14-29 */ + /* 64 bytes, SAS address for each port */ + u64 sas_addr[8]; + + /* Dword 30-31 */ + /* 8 bytes for vanir 8 port PHY FFE seeting + * BIT 0~3 : FFE Capacitor select(value range 0~F) + * BIT 4~6 : FFE Resistor select(value range 0~7) + * BIT 7: reserve. + */ + + struct ffe_control ffe_ctl[8]; + /* Dword 32 -43 */ + u32 reserved2[12]; + + /* Dword 44-45 */ + /* 8 bytes, 0: 1.5G, 1: 3.0G, should be 0x01 at first initial */ + u8 phy_rate[8]; + + /* Dword 46-53 */ + /* 32 bytes, PHY tuning parameters for each PHY*/ + struct phy_tuning phy_tuning[8]; + + /* Dword 54-63 */ + u32 reserved3[10]; +}; /* total 256 bytes */ + struct mvs_slot_info { struct list_head entry; union { @@ -338,6 +405,7 @@ struct mvs_info { u32 flashsectSize; void *addon; + struct hba_info_page hba_info_param; struct mvs_device devices[MVS_MAX_DEVICES]; #ifndef DISABLE_HOTPLUG_DMA_FIX void *bulk_buffer; -- cgit v1.2.3 From 83c7b61cf49c2659829050fec240601415c7f9d9 Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Tue, 24 May 2011 22:31:47 +0800 Subject: [SCSI] mvsas: Add driver version and interrupt coalescing to device attributes in sysfs Signed-off-by: Xiangliang Yu Signed-off-by: James Bottomley --- drivers/scsi/mvsas/mv_64xx.c | 25 ++++++++++++++- drivers/scsi/mvsas/mv_94xx.c | 26 ++++++++++++++- drivers/scsi/mvsas/mv_init.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/mvsas/mv_sas.h | 2 ++ 4 files changed, 126 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c index 0e13e6441da7..c88b8a7ed398 100644 --- a/drivers/scsi/mvsas/mv_64xx.c +++ b/drivers/scsi/mvsas/mv_64xx.c @@ -402,7 +402,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi) tmp = 0; mw32(MVS_INT_COAL, tmp); - tmp = 0x100; + tmp = 0x10000 | interrupt_coalescing; mw32(MVS_INT_COAL_TMOUT, tmp); /* ladies and gentlemen, start your engines */ @@ -758,6 +758,28 @@ void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd) } #endif +static void mvs_64xx_tune_interrupt(struct mvs_info *mvi, u32 time) +{ + void __iomem *regs = mvi->regs; + u32 tmp = 0; + /* interrupt coalescing may cause missing HW interrput in some case, + * and the max count is 0x1ff, while our max slot is 0x200, + * it will make count 0. + */ + if (time == 0) { + mw32(MVS_INT_COAL, 0); + mw32(MVS_INT_COAL_TMOUT, 0x10000); + } else { + if (MVS_CHIP_SLOT_SZ > 0x1ff) + mw32(MVS_INT_COAL, 0x1ff|COAL_EN); + else + mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN); + + tmp = 0x10000 | time; + mw32(MVS_INT_COAL_TMOUT, tmp); + } +} + const struct mvs_dispatch mvs_64xx_dispatch = { "mv64xx", mvs_64xx_init, @@ -811,6 +833,7 @@ const struct mvs_dispatch mvs_64xx_dispatch = { #ifndef DISABLE_HOTPLUG_DMA_FIX mvs_64xx_fix_dma, #endif + mvs_64xx_tune_interrupt, NULL, }; diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 3f2ad934c917..e589f31cb2b4 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -475,7 +475,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) tmp = 0; mw32(MVS_INT_COAL, tmp); - tmp = 0x100; + tmp = 0x10000 | interrupt_coalescing; mw32(MVS_INT_COAL_TMOUT, tmp); /* ladies and gentlemen, start your engines */ @@ -894,6 +894,29 @@ static void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, { } +static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time) +{ + void __iomem *regs = mvi->regs; + u32 tmp = 0; + /* interrupt coalescing may cause missing HW interrput in some case, + * and the max count is 0x1ff, while our max slot is 0x200, + * it will make count 0. + */ + if (time == 0) { + mw32(MVS_INT_COAL, 0); + mw32(MVS_INT_COAL_TMOUT, 0x10000); + } else { + if (MVS_CHIP_SLOT_SZ > 0x1ff) + mw32(MVS_INT_COAL, 0x1ff|COAL_EN); + else + mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN); + + tmp = 0x10000 | time; + mw32(MVS_INT_COAL_TMOUT, tmp); + } + +} + const struct mvs_dispatch mvs_94xx_dispatch = { "mv94xx", mvs_94xx_init, @@ -947,6 +970,7 @@ const struct mvs_dispatch mvs_94xx_dispatch = { #ifndef DISABLE_HOTPLUG_DMA_FIX mvs_94xx_fix_dma, #endif + mvs_94xx_tune_interrupt, mvs_94xx_non_spec_ncq_error, }; diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 9f1cccc2a3ed..531093ddc418 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -34,6 +34,8 @@ MODULE_PARM_DESC(collector, "\n" "\tThe mvsas SAS LLDD supports both modes.\n" "\tDefault: 1 (Direct Mode).\n"); +int interrupt_coalescing = 0x80; + static struct scsi_transport_template *mvs_stt; struct kmem_cache *mvs_task_list_cache; static const struct mvs_chip_info mvs_chips[] = { @@ -48,6 +50,8 @@ static const struct mvs_chip_info mvs_chips[] = { [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, }; +struct device_attribute *mvst_host_attrs[]; + #define SOC_SAS_NUM 2 #define SG_MX 64 @@ -74,6 +78,7 @@ static struct scsi_host_template mvs_sht = { .slave_alloc = mvs_slave_alloc, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, + .shost_attrs = mvst_host_attrs, }; static struct sas_domain_function_template mvs_transport_ops = { @@ -706,6 +711,70 @@ static struct pci_driver mvs_pci_driver = { .remove = __devexit_p(mvs_pci_remove), }; +static ssize_t +mvs_show_driver_version(struct device *cdev, + struct device_attribute *attr, char *buffer) +{ + return snprintf(buffer, PAGE_SIZE, "%s\n", DRV_VERSION); +} + +static DEVICE_ATTR(driver_version, + S_IRUGO, + mvs_show_driver_version, + NULL); + +static ssize_t +mvs_store_interrupt_coalescing(struct device *cdev, + struct device_attribute *attr, + const char *buffer, size_t size) +{ + int val = 0; + struct mvs_info *mvi = NULL; + struct Scsi_Host *shost = class_to_shost(cdev); + struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); + u8 i, core_nr; + if (buffer == NULL) + return size; + + if (sscanf(buffer, "%d", &val) != 1) + return -EINVAL; + + if (val >= 0x10000) { + mv_dprintk("interrupt coalescing timer %d us is" + "too long\n", val); + return strlen(buffer); + } + + interrupt_coalescing = val; + + core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; + mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0]; + + if (unlikely(!mvi)) + return -EINVAL; + + for (i = 0; i < core_nr; i++) { + mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; + if (MVS_CHIP_DISP->tune_interrupt) + MVS_CHIP_DISP->tune_interrupt(mvi, + interrupt_coalescing); + } + mv_dprintk("set interrupt coalescing time to %d us\n", + interrupt_coalescing); + return strlen(buffer); +} + +static ssize_t mvs_show_interrupt_coalescing(struct device *cdev, + struct device_attribute *attr, char *buffer) +{ + return snprintf(buffer, PAGE_SIZE, "%d\n", interrupt_coalescing); +} + +static DEVICE_ATTR(interrupt_coalescing, + S_IRUGO|S_IWUSR, + mvs_show_interrupt_coalescing, + mvs_store_interrupt_coalescing); + /* task handler */ struct task_struct *mvs_th; static int __init mvs_init(void) @@ -742,6 +811,12 @@ static void __exit mvs_exit(void) kmem_cache_destroy(mvs_task_list_cache); } +struct device_attribute *mvst_host_attrs[] = { + &dev_attr_driver_version, + &dev_attr_interrupt_coalescing, + NULL, +}; + module_init(mvs_init); module_exit(mvs_exit); diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index ccd622f7f841..089ef1ef3865 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -64,6 +64,7 @@ #endif #define MV_MAX_U32 0xffffffff +extern int interrupt_coalescing; extern struct mvs_tgt_initiator mvs_tgt; extern struct mvs_info *tgt_mvi; extern const struct mvs_dispatch mvs_64xx_dispatch; @@ -170,6 +171,7 @@ struct mvs_dispatch { #ifndef DISABLE_HOTPLUG_DMA_FIX void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd); #endif + void (*tune_interrupt)(struct mvs_info *mvi, u32 time); void (*non_spec_ncq_error)(struct mvs_info *mvi); }; -- cgit v1.2.3 From 8882f081329a82737b7471b97e59ce8c407f6655 Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Tue, 24 May 2011 22:33:11 +0800 Subject: [SCSI] mvsas: fix 94xx hotplug issue Fix 94xx A0/B0 revision hotplug issue. Remove unused macro: DISABLE_HOTPLUG_DMA_FIX Signed-off-by: Xiangliang Yu Signed-off-by: James Bottomley --- drivers/scsi/mvsas/mv_64xx.c | 9 ++++----- drivers/scsi/mvsas/mv_94xx.c | 16 +++++++++++----- drivers/scsi/mvsas/mv_init.c | 15 +++++++++++---- drivers/scsi/mvsas/mv_sas.c | 28 ++++++++++++---------------- drivers/scsi/mvsas/mv_sas.h | 9 ++++----- 5 files changed, 42 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c index c88b8a7ed398..b02dd800af38 100644 --- a/drivers/scsi/mvsas/mv_64xx.c +++ b/drivers/scsi/mvsas/mv_64xx.c @@ -744,11 +744,13 @@ int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) return -1; } -#ifndef DISABLE_HOTPLUG_DMA_FIX -void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd) +void mvs_64xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, + int buf_len, int from, void *prd) { int i; struct mvs_prd *buf_prd = prd; + dma_addr_t buf_dma = mvi->bulk_buffer_dma; + buf_prd += from; for (i = 0; i < MAX_SG_ENTRY - from; i++) { buf_prd->addr = cpu_to_le64(buf_dma); @@ -756,7 +758,6 @@ void mvs_64xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd) ++buf_prd; } } -#endif static void mvs_64xx_tune_interrupt(struct mvs_info *mvi, u32 time) { @@ -830,9 +831,7 @@ const struct mvs_dispatch mvs_64xx_dispatch = { mvs_64xx_spi_buildcmd, mvs_64xx_spi_issuecmd, mvs_64xx_spi_waitdataready, -#ifndef DISABLE_HOTPLUG_DMA_FIX mvs_64xx_fix_dma, -#endif mvs_64xx_tune_interrupt, NULL, }; diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index e589f31cb2b4..ef3c9012df46 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -871,19 +871,27 @@ int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) return -1; } -#ifndef DISABLE_HOTPLUG_DMA_FIX -void mvs_94xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd) +void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, + int buf_len, int from, void *prd) { int i; struct mvs_prd *buf_prd = prd; + dma_addr_t buf_dma; buf_prd += from; + + if ((mvi->pdev->revision == VANIR_A0_REV) || + (mvi->pdev->revision == VANIR_B0_REV)) + buf_dma = (phy_mask <= 0x08) ? + mvi->bulk_buffer_dma : mvi->bulk_buffer_dma1; + else + return; + for (i = 0; i < MAX_SG_ENTRY - from; i++) { buf_prd->addr = cpu_to_le64(buf_dma); buf_prd->im_len.len = cpu_to_le32(buf_len); ++buf_prd; } } -#endif /* * FIXME JEJB: temporary nop clear_srs_irq to make 94xx still work @@ -967,9 +975,7 @@ const struct mvs_dispatch mvs_94xx_dispatch = { mvs_94xx_spi_buildcmd, mvs_94xx_spi_issuecmd, mvs_94xx_spi_waitdataready, -#ifndef DISABLE_HOTPLUG_DMA_FIX mvs_94xx_fix_dma, -#endif mvs_94xx_tune_interrupt, mvs_94xx_non_spec_ncq_error, }; diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 531093ddc418..b111ae2ec489 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -153,11 +153,13 @@ static void mvs_free(struct mvs_info *mvi) dma_free_coherent(mvi->dev, sizeof(*mvi->slot) * slot_nr, mvi->slot, mvi->slot_dma); -#ifndef DISABLE_HOTPLUG_DMA_FIX + if (mvi->bulk_buffer) dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE, mvi->bulk_buffer, mvi->bulk_buffer_dma); -#endif + if (mvi->bulk_buffer1) + dma_free_coherent(mvi->dev, TRASH_BUCKET_SIZE, + mvi->bulk_buffer1, mvi->bulk_buffer_dma1); MVS_CHIP_DISP->chip_iounmap(mvi); if (mvi->shost) @@ -278,13 +280,18 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) goto err_out; memset(mvi->slot, 0, sizeof(*mvi->slot) * slot_nr); -#ifndef DISABLE_HOTPLUG_DMA_FIX mvi->bulk_buffer = dma_alloc_coherent(mvi->dev, TRASH_BUCKET_SIZE, &mvi->bulk_buffer_dma, GFP_KERNEL); if (!mvi->bulk_buffer) goto err_out; -#endif + + mvi->bulk_buffer1 = dma_alloc_coherent(mvi->dev, + TRASH_BUCKET_SIZE, + &mvi->bulk_buffer_dma1, GFP_KERNEL); + if (!mvi->bulk_buffer1) + goto err_out; + sprintf(pool_name, "%s%d", "mvs_dma_pool", mvi->id); mvi->dma_pool = pci_pool_create(pool_name, mvi->pdev, MVS_SLOT_BUF_SZ, 16, 0); if (!mvi->dma_pool) { diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index aaa475a3eda6..4585dc018ad1 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -630,14 +630,11 @@ static int mvs_task_prep_ata(struct mvs_info *mvi, (mvi_dev->taskfileset << TXQ_SRS_SHIFT); mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q); -#ifndef DISABLE_HOTPLUG_DMA_FIX if (task->data_dir == DMA_FROM_DEVICE) flags = (MVS_CHIP_DISP->prd_count() << MCH_PRD_LEN_SHIFT); else flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); -#else - flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); -#endif + if (task->ata_task.use_ncq) flags |= MCH_FPDMA; if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { @@ -729,11 +726,11 @@ static int mvs_task_prep_ata(struct mvs_info *mvi, /* fill in PRD (scatter/gather) table, if any */ MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); -#ifndef DISABLE_HOTPLUG_DMA_FIX + if (task->data_dir == DMA_FROM_DEVICE) - MVS_CHIP_DISP->dma_fix(mvi->bulk_buffer_dma, + MVS_CHIP_DISP->dma_fix(mvi, sas_port->phy_mask, TRASH_BUCKET_SIZE, tei->n_elem, buf_prd); -#endif + return 0; } @@ -1283,6 +1280,13 @@ static u32 mvs_is_sig_fis_received(u32 irq_status) return irq_status & PHYEV_SIG_FIS; } +static void mvs_sig_remove_timer(struct mvs_phy *phy) +{ + if (phy->timer.function) + del_timer(&phy->timer); + phy->timer.function = NULL; +} + void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st) { struct mvs_phy *phy = &mvi->phy[i]; @@ -1305,6 +1309,7 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st) if (phy->phy_type & PORT_TYPE_SATA) { phy->identify.target_port_protocols = SAS_PROTOCOL_STP; if (mvs_is_sig_fis_received(phy->irq_status)) { + mvs_sig_remove_timer(phy); phy->phy_attached = 1; phy->att_dev_sas_addr = i + mvi->id * mvi->chip->n_phy; @@ -1322,7 +1327,6 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st) tmp | PHYEV_SIG_FIS); phy->phy_attached = 0; phy->phy_type &= ~PORT_TYPE_SATA; - MVS_CHIP_DISP->phy_reset(mvi, i, 0); goto out_done; } } else if (phy->phy_type & PORT_TYPE_SAS @@ -2193,13 +2197,6 @@ static void mvs_sig_time_out(unsigned long tphy) } } -static void mvs_sig_remove_timer(struct mvs_phy *phy) -{ - if (phy->timer.function) - del_timer(&phy->timer); - phy->timer.function = NULL; -} - void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) { u32 tmp; @@ -2263,7 +2260,6 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) } if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) { phy->phy_status = mvs_is_phy_ready(mvi, phy_no); - mvs_sig_remove_timer(phy); mv_dprintk("notify plug in on phy[%d]\n", phy_no); if (phy->phy_status) { mdelay(10); diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 089ef1ef3865..5cfa4cc18f2d 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -168,9 +168,8 @@ struct mvs_dispatch { ); int (*spi_issuecmd)(struct mvs_info *mvi, u32 cmd); int (*spi_waitdataready)(struct mvs_info *mvi, u32 timeout); -#ifndef DISABLE_HOTPLUG_DMA_FIX - void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd); -#endif + void (*dma_fix)(struct mvs_info *mvi, u32 phy_mask, + int buf_len, int from, void *prd); void (*tune_interrupt)(struct mvs_info *mvi, u32 time); void (*non_spec_ncq_error)(struct mvs_info *mvi); @@ -409,11 +408,11 @@ struct mvs_info { void *addon; struct hba_info_page hba_info_param; struct mvs_device devices[MVS_MAX_DEVICES]; -#ifndef DISABLE_HOTPLUG_DMA_FIX void *bulk_buffer; dma_addr_t bulk_buffer_dma; + void *bulk_buffer1; + dma_addr_t bulk_buffer_dma1; #define TRASH_BUCKET_SIZE 0x20000 -#endif void *dma_pool; struct mvs_slot_info slot_info[0]; }; -- cgit v1.2.3 From b89e8f539ff8bcf2a1464578fa91cb96cc433fc3 Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Tue, 24 May 2011 22:35:09 +0800 Subject: [SCSI] mvsas: Remove unused macros, variables and functions Remove unused macros: VSR_PHY_VS0, VSR_PHY_VS1, MVS_SLOTS, MVS_CAN_QUEUE, MVS_MSI, SG_MX, _MV_DUMP, MV_DISABLE_NCQ Remove unused variables for mvs_info: irq, exp_req, cmd_size Remove unused functions: mvs_get_sas_addr, mvs_hexdump, mvs_hba_sb_dump, mvs_hab_memory_dump, mvs_hba_cq_dump Signed-off-by: Xiangliang Yu Signed-off-by: James Bottomley --- drivers/scsi/mvsas/mv_64xx.c | 1 - drivers/scsi/mvsas/mv_94xx.c | 1 - drivers/scsi/mvsas/mv_94xx.h | 2 - drivers/scsi/mvsas/mv_defs.h | 5 +- drivers/scsi/mvsas/mv_init.c | 24 ++++--- drivers/scsi/mvsas/mv_sas.c | 163 ++----------------------------------------- drivers/scsi/mvsas/mv_sas.h | 13 +--- 7 files changed, 20 insertions(+), 189 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c index b02dd800af38..96bde3448c7d 100644 --- a/drivers/scsi/mvsas/mv_64xx.c +++ b/drivers/scsi/mvsas/mv_64xx.c @@ -803,7 +803,6 @@ const struct mvs_dispatch mvs_64xx_dispatch = { mvs_write_port_irq_stat, mvs_read_port_irq_mask, mvs_write_port_irq_mask, - mvs_get_sas_addr, mvs_64xx_command_active, mvs_64xx_clear_srs_irq, mvs_64xx_issue_stop, diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index ef3c9012df46..5b25f1b7fa52 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -947,7 +947,6 @@ const struct mvs_dispatch mvs_94xx_dispatch = { mvs_write_port_irq_stat, mvs_read_port_irq_mask, mvs_write_port_irq_mask, - mvs_get_sas_addr, mvs_94xx_command_active, mvs_94xx_clear_srs_irq, mvs_94xx_issue_stop, diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h index 33af2a1fb729..723fd0adf1c6 100644 --- a/drivers/scsi/mvsas/mv_94xx.h +++ b/drivers/scsi/mvsas/mv_94xx.h @@ -132,8 +132,6 @@ enum sas_sata_vsp_regs { VSR_PHY_MODE9 = 0x09 * 4, /* Test */ VSR_PHY_MODE10 = 0x0A * 4, /* Power */ VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */ - VSR_PHY_VS0 = 0x0C * 4, /* Vednor Specific 0 */ - VSR_PHY_VS1 = 0x0D * 4, /* Vednor Specific 1 */ VSR_PHY_FFE_CONTROL = 0x10C, VSR_PHY_DFE_UPDATE_CRTL = 0x110, diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h index 9202bc68801d..e39629d874b5 100644 --- a/drivers/scsi/mvsas/mv_defs.h +++ b/drivers/scsi/mvsas/mv_defs.h @@ -43,7 +43,6 @@ enum chip_flavors { /* driver compile-time configuration */ enum driver_configuration { - MVS_SLOTS = 512, /* command slots */ MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */ MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */ /* software requires power-of-2 @@ -56,8 +55,7 @@ enum driver_configuration { MVS_SSP_CMD_SZ = 64, /* SSP command table buffer size */ MVS_ATA_CMD_SZ = 96, /* SATA command table buffer size */ MVS_OAF_SZ = 64, /* Open address frame buffer size */ - MVS_QUEUE_SIZE = 32, /* Support Queue depth */ - MVS_CAN_QUEUE = MVS_SLOTS - 2, /* SCSI Queue depth */ + MVS_QUEUE_SIZE = 64, /* Support Queue depth */ MVS_SOC_CAN_QUEUE = MVS_SOC_SLOTS - 2, }; @@ -392,7 +390,6 @@ enum sas_cmd_port_registers { }; enum mvs_info_flags { - MVF_MSI = (1U << 0), /* MSI is enabled */ MVF_PHY_PWR_FIX = (1U << 1), /* bug workaround */ MVF_FLAG_SOC = (1U << 2), /* SoC integrated controllers */ }; diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index b111ae2ec489..a7815f9c63bc 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -53,7 +53,6 @@ static const struct mvs_chip_info mvs_chips[] = { struct device_attribute *mvst_host_attrs[]; #define SOC_SAS_NUM 2 -#define SG_MX 64 static struct scsi_host_template mvs_sht = { .module = THIS_MODULE, @@ -70,7 +69,7 @@ static struct scsi_host_template mvs_sht = { .can_queue = 1, .cmd_per_lun = 1, .this_id = -1, - .sg_tablesize = SG_MX, + .sg_tablesize = SG_ALL, .max_sectors = SCSI_DEFAULT_MAX_SECTORS, .use_clustering = ENABLE_CLUSTERING, .eh_device_reset_handler = sas_eh_device_reset_handler, @@ -133,7 +132,7 @@ static void mvs_free(struct mvs_info *mvi) if (mvi->flags & MVF_FLAG_SOC) slot_nr = MVS_SOC_SLOTS; else - slot_nr = MVS_SLOTS; + slot_nr = MVS_CHIP_SLOT_SZ; if (mvi->dma_pool) pci_pool_destroy(mvi->dma_pool); @@ -166,6 +165,7 @@ static void mvs_free(struct mvs_info *mvi) scsi_host_put(mvi->shost); list_for_each_entry(mwq, &mvi->wq_list, entry) cancel_delayed_work(&mwq->work_q); + kfree(mvi->tags); kfree(mvi); } @@ -232,7 +232,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) if (mvi->flags & MVF_FLAG_SOC) slot_nr = MVS_SOC_SLOTS; else - slot_nr = MVS_SLOTS; + slot_nr = MVS_CHIP_SLOT_SZ; spin_lock_init(&mvi->lock); for (i = 0; i < mvi->chip->n_phy; i++) { @@ -369,8 +369,9 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev, struct mvs_info *mvi; struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); - mvi = kzalloc(sizeof(*mvi) + MVS_SLOTS * sizeof(struct mvs_slot_info), - GFP_KERNEL); + mvi = kzalloc(sizeof(*mvi) + + (1L << mvs_chips[ent->driver_data].slot_width) * + sizeof(struct mvs_slot_info), GFP_KERNEL); if (!mvi) return NULL; @@ -379,7 +380,6 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev, mvi->chip_id = ent->driver_data; mvi->chip = &mvs_chips[mvi->chip_id]; INIT_LIST_HEAD(&mvi->wq_list); - mvi->irq = pdev->irq; ((struct mvs_prv_info *)sha->lldd_ha)->mvi[id] = mvi; ((struct mvs_prv_info *)sha->lldd_ha)->n_phy = mvi->chip->n_phy; @@ -391,6 +391,10 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev, tasklet_init(&mv_tasklet, mvs_tasklet, (unsigned long)sha); #endif + mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL); + if (!mvi->tags) + goto err_out; + if (MVS_CHIP_DISP->chip_ioremap(mvi)) goto err_out; if (!mvs_alloc(mvi, shost)) @@ -505,11 +509,11 @@ static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost, if (mvi->flags & MVF_FLAG_SOC) can_queue = MVS_SOC_CAN_QUEUE; else - can_queue = MVS_CAN_QUEUE; + can_queue = MVS_CHIP_SLOT_SZ; sha->lldd_queue_size = can_queue; shost->can_queue = can_queue; - mvi->shost->cmd_per_lun = MVS_SLOTS/sha->num_phys; + mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE; sha->core.shost = mvi->shost; } @@ -650,7 +654,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev) scsi_remove_host(mvi->shost); MVS_CHIP_DISP->interrupt_disable(mvi); - free_irq(mvi->irq, sha); + free_irq(mvi->pdev->irq, sha); for (i = 0; i < core_nr; i++) { mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; mvs_free(mvi); diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 4585dc018ad1..7bd0ee3ed2d6 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -38,7 +38,7 @@ static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag) void mvs_tag_clear(struct mvs_info *mvi, u32 tag) { - void *bitmap = &mvi->tags; + void *bitmap = mvi->tags; clear_bit(tag, bitmap); } @@ -49,14 +49,14 @@ void mvs_tag_free(struct mvs_info *mvi, u32 tag) void mvs_tag_set(struct mvs_info *mvi, unsigned int tag) { - void *bitmap = &mvi->tags; + void *bitmap = mvi->tags; set_bit(tag, bitmap); } inline int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out) { unsigned int index, tag; - void *bitmap = &mvi->tags; + void *bitmap = mvi->tags; index = find_first_zero_bit(bitmap, mvi->tags_num); tag = index; @@ -74,126 +74,6 @@ void mvs_tag_init(struct mvs_info *mvi) mvs_tag_clear(mvi, i); } -void mvs_hexdump(u32 size, u8 *data, u32 baseaddr) -{ - u32 i; - u32 run; - u32 offset; - - offset = 0; - while (size) { - printk(KERN_DEBUG"%08X : ", baseaddr + offset); - if (size >= 16) - run = 16; - else - run = size; - size -= run; - for (i = 0; i < 16; i++) { - if (i < run) - printk(KERN_DEBUG"%02X ", (u32)data[i]); - else - printk(KERN_DEBUG" "); - } - printk(KERN_DEBUG": "); - for (i = 0; i < run; i++) - printk(KERN_DEBUG"%c", - isalnum(data[i]) ? data[i] : '.'); - printk(KERN_DEBUG"\n"); - data = &data[16]; - offset += run; - } - printk(KERN_DEBUG"\n"); -} - -#if (_MV_DUMP > 1) -static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag, - enum sas_protocol proto) -{ - u32 offset; - struct mvs_slot_info *slot = &mvi->slot_info[tag]; - - offset = slot->cmd_size + MVS_OAF_SZ + - MVS_CHIP_DISP->prd_size() * slot->n_elem; - dev_printk(KERN_DEBUG, mvi->dev, "+---->Status buffer[%d] :\n", - tag); - mvs_hexdump(32, (u8 *) slot->response, - (u32) slot->buf_dma + offset); -} -#endif - -static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, - enum sas_protocol proto) -{ -#if (_MV_DUMP > 1) - u32 sz, w_ptr; - u64 addr; - struct mvs_slot_info *slot = &mvi->slot_info[tag]; - - /*Delivery Queue */ - sz = MVS_CHIP_SLOT_SZ; - w_ptr = slot->tx; - addr = mvi->tx_dma; - dev_printk(KERN_DEBUG, mvi->dev, - "Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr); - dev_printk(KERN_DEBUG, mvi->dev, - "Delivery Queue Base Address=0x%llX (PA)" - "(tx_dma=0x%llX), Entry=%04d\n", - addr, (unsigned long long)mvi->tx_dma, w_ptr); - mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]), - (u32) mvi->tx_dma + sizeof(u32) * w_ptr); - /*Command List */ - addr = mvi->slot_dma; - dev_printk(KERN_DEBUG, mvi->dev, - "Command List Base Address=0x%llX (PA)" - "(slot_dma=0x%llX), Header=%03d\n", - addr, (unsigned long long)slot->buf_dma, tag); - dev_printk(KERN_DEBUG, mvi->dev, "Command Header[%03d]:\n", tag); - /*mvs_cmd_hdr */ - mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]), - (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr)); - /*1.command table area */ - dev_printk(KERN_DEBUG, mvi->dev, "+---->Command Table :\n"); - mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma); - /*2.open address frame area */ - dev_printk(KERN_DEBUG, mvi->dev, "+---->Open Address Frame :\n"); - mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size, - (u32) slot->buf_dma + slot->cmd_size); - /*3.status buffer */ - mvs_hba_sb_dump(mvi, tag, proto); - /*4.PRD table */ - dev_printk(KERN_DEBUG, mvi->dev, "+---->PRD table :\n"); - mvs_hexdump(MVS_CHIP_DISP->prd_size() * slot->n_elem, - (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ, - (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ); -#endif -} - -static void mvs_hba_cq_dump(struct mvs_info *mvi) -{ -#if (_MV_DUMP > 2) - u64 addr; - void __iomem *regs = mvi->regs; - u32 entry = mvi->rx_cons + 1; - u32 rx_desc = le32_to_cpu(mvi->rx[entry]); - - /*Completion Queue */ - addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO); - dev_printk(KERN_DEBUG, mvi->dev, "Completion Task = 0x%p\n", - mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task); - dev_printk(KERN_DEBUG, mvi->dev, - "Completion List Base Address=0x%llX (PA), " - "CQ_Entry=%04d, CQ_WP=0x%08X\n", - addr, entry - 1, mvi->rx[0]); - mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc), - mvi->rx_dma + sizeof(u32) * entry); -#endif -} - -void mvs_get_sas_addr(void *buf, u32 buflen) -{ - /*memcpy(buf, "\x50\x05\x04\x30\x11\xab\x64\x40", 8);*/ -} - struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev) { unsigned long i = 0, j = 0, hi = 0; @@ -421,13 +301,6 @@ int mvs_slave_configure(struct scsi_device *sdev) if (ret) return ret; if (dev_is_sata(dev)) { - /* may set PIO mode */ - #if MV_DISABLE_NCQ - struct ata_port *ap = dev->sata_dev.ap; - struct ata_device *adev = ap->link.device; - adev->flags |= ATA_DFLAG_NCQ_OFF; - scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1); - #endif } return 0; } @@ -475,10 +348,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi, void *buf_prd; struct mvs_slot_info *slot = &mvi->slot_info[tag]; u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); -#if _MV_DUMP - u8 *buf_cmd; - void *from; -#endif + /* * DMA-map SMP request, response buffers */ @@ -510,15 +380,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi, buf_tmp = slot->buf; buf_tmp_dma = slot->buf_dma; -#if _MV_DUMP - buf_cmd = buf_tmp; - hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); - buf_tmp += req_len; - buf_tmp_dma += req_len; - slot->cmd_size = req_len; -#else hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req)); -#endif /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ buf_oaf = buf_tmp; @@ -567,12 +429,6 @@ static int mvs_task_prep_smp(struct mvs_info *mvi, /* fill in PRD (scatter/gather) table, if any */ MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); -#if _MV_DUMP - /* copy cmd table */ - from = kmap_atomic(sg_page(sg_req), KM_IRQ0); - memcpy(buf_cmd, from + sg_req->offset, req_len); - kunmap_atomic(from, KM_IRQ0); -#endif return 0; err_out_2: @@ -668,9 +524,6 @@ static int mvs_task_prep_ata(struct mvs_info *mvi, buf_tmp += MVS_ATA_CMD_SZ; buf_tmp_dma += MVS_ATA_CMD_SZ; -#if _MV_DUMP - slot->cmd_size = MVS_ATA_CMD_SZ; -#endif /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ /* used for STP. unused for SATA? */ @@ -788,9 +641,6 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi, buf_tmp += MVS_SSP_CMD_SZ; buf_tmp_dma += MVS_SSP_CMD_SZ; -#if _MV_DUMP - slot->cmd_size = MVS_SSP_CMD_SZ; -#endif /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ buf_oaf = buf_tmp; @@ -997,7 +847,6 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf task->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock(&task->task_state_lock); - mvs_hba_memory_dump(mvi, tag, task->task_proto); mvi_dev->running_req++; ++(*pass); mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); @@ -1963,8 +1812,6 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) void *to; enum exec_status sts; - if (mvi->exp_req) - mvi->exp_req--; if (unlikely(!task || !task->lldd_task || !task->dev)) return -1; @@ -1972,8 +1819,6 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) dev = task->dev; mvi_dev = dev->lldd_dev; - mvs_hba_cq_dump(mvi); - spin_lock(&task->task_state_lock); task->task_state_flags &= ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 5cfa4cc18f2d..4f8caaf748f1 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -48,12 +48,8 @@ #define DRV_NAME "mvsas" #define DRV_VERSION "0.8.2" -#define _MV_DUMP 0 #define MVS_ID_NOT_MAPPED 0x7f -/* #define DISABLE_HOTPLUG_DMA_FIX */ -// #define MAX_EXP_RUNNING_REQ 2 #define WIDE_PORT_MAX_PHY 4 -#define MV_DISABLE_NCQ 0 #define mv_printk(fmt, arg ...) \ printk(KERN_DEBUG"%s %d:" fmt, __FILE__, __LINE__, ## arg) #ifdef MV_DEBUG @@ -131,7 +127,6 @@ struct mvs_dispatch { u32 (*read_port_irq_mask)(struct mvs_info *mvi, u32 port); void (*write_port_irq_mask)(struct mvs_info *mvi, u32 port, u32 val); - void (*get_sas_addr)(void *buf, u32 buflen); void (*command_active)(struct mvs_info *mvi, u32 slot_idx); void (*clear_srs_irq)(struct mvs_info *mvi, u8 reg_set, u8 clear_all); void (*issue_stop)(struct mvs_info *mvi, enum mvs_port_type type, @@ -333,9 +328,6 @@ struct mvs_slot_info { */ void *buf; dma_addr_t buf_dma; -#if _MV_DUMP - u32 cmd_size; -#endif void *response; struct mvs_port *port; struct mvs_device *device; @@ -389,12 +381,10 @@ struct mvs_info { const struct mvs_chip_info *chip; int tags_num; - DECLARE_BITMAP(tags, MVS_SLOTS); + unsigned long *tags; /* further per-slot information */ struct mvs_phy phy[MVS_MAX_PHYS]; struct mvs_port port[MVS_MAX_PHYS]; - u32 irq; - u32 exp_req; u32 id; u64 sata_reg_set; struct list_head *hba_list; @@ -485,7 +475,6 @@ void mvs_do_release_task(struct mvs_info *mvi, int phy_no, void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events); void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); int mvs_int_rx(struct mvs_info *mvi, bool self_clear); -void mvs_hexdump(u32 size, u8 *data, u32 baseaddr); struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi, u8 reg_set); #endif -- cgit v1.2.3 From a4632aae8b662b1f32fe3fc558a813cd5c3daae6 Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Tue, 24 May 2011 22:36:02 +0800 Subject: [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 Signed-off-by: James Bottomley --- drivers/scsi/mvsas/mv_64xx.c | 18 ++++----- drivers/scsi/mvsas/mv_94xx.c | 80 +++++++++++++++++++++++++++---------- drivers/scsi/mvsas/mv_94xx.h | 2 + drivers/scsi/mvsas/mv_defs.h | 3 +- drivers/scsi/mvsas/mv_init.c | 21 +++++----- drivers/scsi/mvsas/mv_sas.c | 94 +++++++++++++++++++++++++++++++++++++------- drivers/scsi/mvsas/mv_sas.h | 7 ++++ 7 files changed, 169 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c index 96bde3448c7d..702c767ee46f 100644 --- a/drivers/scsi/mvsas/mv_64xx.c +++ b/drivers/scsi/mvsas/mv_64xx.c @@ -48,7 +48,7 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id) u32 tmp; tmp = mr32(MVS_PCS); - if (mvi->chip->n_phy <= 4) + if (mvi->chip->n_phy <= MVS_SOC_PORTS) tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT); else tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2); @@ -95,7 +95,7 @@ static void mvs_64xx_stp_reset(struct mvs_info *mvi, u32 phy_id) u32 reg, tmp; if (!(mvi->flags & MVF_FLAG_SOC)) { - if (phy_id < 4) + if (phy_id < MVS_SOC_PORTS) pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, ®); else pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, ®); @@ -104,13 +104,13 @@ static void mvs_64xx_stp_reset(struct mvs_info *mvi, u32 phy_id) reg = mr32(MVS_PHY_CTL); tmp = reg; - if (phy_id < 4) + if (phy_id < MVS_SOC_PORTS) tmp |= (1U << phy_id) << PCTL_LINK_OFFS; else - tmp |= (1U << (phy_id - 4)) << PCTL_LINK_OFFS; + tmp |= (1U << (phy_id - MVS_SOC_PORTS)) << PCTL_LINK_OFFS; if (!(mvi->flags & MVF_FLAG_SOC)) { - if (phy_id < 4) { + if (phy_id < MVS_SOC_PORTS) { pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp); mdelay(10); pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, reg); @@ -133,9 +133,9 @@ static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard) tmp &= ~PHYEV_RDY_CH; mvs_write_port_irq_stat(mvi, phy_id, tmp); tmp = mvs_read_phy_ctl(mvi, phy_id); - if (hard == 1) + if (hard == MVS_HARD_RESET) tmp |= PHY_RST_HARD; - else if (hard == 0) + else if (hard == MVS_SOFT_RESET) tmp |= PHY_RST; mvs_write_phy_ctl(mvi, phy_id, tmp); if (hard) { @@ -346,7 +346,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi) mvs_64xx_enable_xmt(mvi, i); - mvs_64xx_phy_reset(mvi, i, 1); + mvs_64xx_phy_reset(mvi, i, MVS_HARD_RESET); msleep(500); mvs_64xx_detect_porttype(mvi, i); } @@ -661,7 +661,7 @@ void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, tmp |= lrmax; } mvs_write_phy_ctl(mvi, phy_id, tmp); - mvs_64xx_phy_reset(mvi, phy_id, 1); + mvs_64xx_phy_reset(mvi, phy_id, MVS_HARD_RESET); } static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi) diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 5b25f1b7fa52..a0ec4aaa24a2 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -389,7 +389,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) mvs_phy_hacks(mvi); /* set LED blink when IO*/ - mw32(MVS_PA_VSR_ADDR, 0x00000030); + mw32(MVS_PA_VSR_ADDR, VSR_PHY_ACT_LED); tmp = mr32(MVS_PA_VSR_PORT); tmp &= 0xFFFF00FF; tmp |= 0x00003300; @@ -419,7 +419,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) mvs_94xx_config_reg_from_hba(mvi, i); mvs_94xx_phy_enable(mvi, i); - mvs_94xx_phy_reset(mvi, i, 1); + mvs_94xx_phy_reset(mvi, i, PHY_RST_HARD); msleep(500); mvs_94xx_detect_porttype(mvi, i); } @@ -585,10 +585,48 @@ static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat) static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx) { u32 tmp; - mvs_cw32(mvi, 0x300 + (slot_idx >> 3), 1 << (slot_idx % 32)); - do { - tmp = mvs_cr32(mvi, 0x300 + (slot_idx >> 3)); - } while (tmp & 1 << (slot_idx % 32)); + tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3)); + if (tmp && 1 << (slot_idx % 32)) { + mv_printk("command active %08X, slot [%x].\n", tmp, slot_idx); + mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3), + 1 << (slot_idx % 32)); + do { + tmp = mvs_cr32(mvi, + MVS_COMMAND_ACTIVE + (slot_idx >> 3)); + } while (tmp & 1 << (slot_idx % 32)); + } +} + +void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all) +{ + void __iomem *regs = mvi->regs; + u32 tmp; + + if (clear_all) { + tmp = mr32(MVS_INT_STAT_SRS_0); + if (tmp) { + mv_dprintk("check SRS 0 %08X.\n", tmp); + mw32(MVS_INT_STAT_SRS_0, tmp); + } + tmp = mr32(MVS_INT_STAT_SRS_1); + if (tmp) { + mv_dprintk("check SRS 1 %08X.\n", tmp); + mw32(MVS_INT_STAT_SRS_1, tmp); + } + } else { + if (reg_set > 31) + tmp = mr32(MVS_INT_STAT_SRS_1); + else + tmp = mr32(MVS_INT_STAT_SRS_0); + + if (tmp & (1 << (reg_set % 32))) { + mv_dprintk("register set 0x%x was stopped.\n", reg_set); + if (reg_set > 31) + mw32(MVS_INT_STAT_SRS_1, 1 << (reg_set % 32)); + else + mw32(MVS_INT_STAT_SRS_0, 1 << (reg_set % 32)); + } + } } static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type, @@ -596,12 +634,10 @@ static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type, { void __iomem *regs = mvi->regs; u32 tmp; + mvs_94xx_clear_srs_irq(mvi, 0, 1); - if (type == PORT_TYPE_SATA) { - tmp = mr32(MVS_INT_STAT_SRS_0) | (1U << tfs); - mw32(MVS_INT_STAT_SRS_0, tmp); - } - mw32(MVS_INT_STAT, CINT_CI_STOP); + tmp = mr32(MVS_INT_STAT); + mw32(MVS_INT_STAT, tmp | CINT_CI_STOP); tmp = mr32(MVS_PCS) | 0xFF00; mw32(MVS_PCS, tmp); } @@ -794,7 +830,18 @@ static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i, void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, struct sas_phy_linkrates *rates) { - /* TODO */ + u32 lrmax = 0; + u32 tmp; + + tmp = mvs_read_phy_ctl(mvi, phy_id); + lrmax = (rates->maximum_linkrate - SAS_LINK_RATE_1_5_GBPS) << 12; + + if (lrmax) { + tmp &= ~(0x3 << 12); + tmp |= lrmax; + } + mvs_write_phy_ctl(mvi, phy_id, tmp); + mvs_94xx_phy_reset(mvi, phy_id, PHY_RST_HARD); } static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi) @@ -893,15 +940,6 @@ void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, } } -/* - * FIXME JEJB: temporary nop clear_srs_irq to make 94xx still work - * with 64xx fixes - */ -static void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, - u8 clear_all) -{ -} - static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time) { void __iomem *regs = mvi->regs; diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h index 723fd0adf1c6..6fc2c105c9d7 100644 --- a/drivers/scsi/mvsas/mv_94xx.h +++ b/drivers/scsi/mvsas/mv_94xx.h @@ -109,6 +109,7 @@ enum hw_registers { MVS_P4_VSR_DATA = 0x254, /* phy4 VSR data */ MVS_PA_VSR_ADDR = 0x290, /* All port VSR addr */ MVS_PA_VSR_PORT = 0x294, /* All port VSR data */ + MVS_COMMAND_ACTIVE = 0x300, }; enum pci_cfg_registers { @@ -132,6 +133,7 @@ enum sas_sata_vsp_regs { VSR_PHY_MODE9 = 0x09 * 4, /* Test */ VSR_PHY_MODE10 = 0x0A * 4, /* Power */ VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */ + VSR_PHY_ACT_LED = 0x0C * 4, /* Activity LED control */ VSR_PHY_FFE_CONTROL = 0x10C, VSR_PHY_DFE_UPDATE_CRTL = 0x110, diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h index e39629d874b5..1927e1bbb8eb 100644 --- a/drivers/scsi/mvsas/mv_defs.h +++ b/drivers/scsi/mvsas/mv_defs.h @@ -395,9 +395,10 @@ enum mvs_info_flags { }; enum mvs_event_flags { - PHY_PLUG_EVENT = (3U), + PHY_PLUG_EVENT = (3U), PHY_PLUG_IN = (1U << 0), /* phy plug in */ PHY_PLUG_OUT = (1U << 1), /* phy plug out */ + EXP_BRCT_CHG = (1U << 2), /* broadcast change */ }; enum mvs_port_type { diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index a7815f9c63bc..bf7d90cfbcfc 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -39,15 +39,15 @@ int interrupt_coalescing = 0x80; static struct scsi_transport_template *mvs_stt; struct kmem_cache *mvs_task_list_cache; static const struct mvs_chip_info mvs_chips[] = { - [chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, - [chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, - [chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, }, - [chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, - [chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, - [chip_9445] = { 1, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, }, - [chip_9485] = { 2, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, }, - [chip_1300] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, - [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, + [chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, + [chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, + [chip_6485] = { 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, }, + [chip_9180] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, + [chip_9480] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, + [chip_9445] = { 1, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, }, + [chip_9485] = { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, }, + [chip_1300] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, }, + [chip_1320] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, }, }; struct device_attribute *mvst_host_attrs[]; @@ -466,7 +466,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost, ((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr; shost->transportt = mvs_stt; - shost->max_id = 128; + shost->max_id = MVS_MAX_DEVICES; shost->max_lun = ~0; shost->max_channel = 1; shost->max_cmd_len = 16; @@ -512,6 +512,7 @@ static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost, can_queue = MVS_CHIP_SLOT_SZ; sha->lldd_queue_size = can_queue; + shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG); shost->can_queue = can_queue; mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE; sha->core.shost = mvi->shost; 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, tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id); if (tmp & PHY_RST_HARD) break; - MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1); + MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_HARD_RESET); break; case PHY_FUNC_LINK_RESET: MVS_CHIP_DISP->phy_enable(mvi, phy_id); - MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0); + MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_SOFT_RESET); break; case PHY_FUNC_DISABLE: @@ -1758,12 +1758,63 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task, return stat; } +void mvs_set_sense(u8 *buffer, int len, int d_sense, + int key, int asc, int ascq) +{ + memset(buffer, 0, len); + + if (d_sense) { + /* Descriptor format */ + if (len < 4) { + mv_printk("Length %d of sense buffer too small to " + "fit sense %x:%x:%x", len, key, asc, ascq); + } + + buffer[0] = 0x72; /* Response Code */ + if (len > 1) + buffer[1] = key; /* Sense Key */ + if (len > 2) + buffer[2] = asc; /* ASC */ + if (len > 3) + buffer[3] = ascq; /* ASCQ */ + } else { + if (len < 14) { + mv_printk("Length %d of sense buffer too small to " + "fit sense %x:%x:%x", len, key, asc, ascq); + } + + buffer[0] = 0x70; /* Response Code */ + if (len > 2) + buffer[2] = key; /* Sense Key */ + if (len > 7) + buffer[7] = 0x0a; /* Additional Sense Length */ + if (len > 12) + buffer[12] = asc; /* ASC */ + if (len > 13) + buffer[13] = ascq; /* ASCQ */ + } + + return; +} + +void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu, + u8 key, u8 asc, u8 asc_q) +{ + iu->datapres = 2; + iu->response_data_len = 0; + iu->sense_data_len = 17; + iu->status = 02; + mvs_set_sense(iu->sense_data, 17, 0, + key, asc, asc_q); +} + static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, u32 slot_idx) { struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; int stat; u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response)); + u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response + 1)); u32 tfs = 0; enum mvs_port_type type = PORT_TYPE_SAS; @@ -1775,8