Commit 84fbd0ce authored by Xiangliang Yu's avatar Xiangliang Yu Committed by James Bottomley

[SCSI] mvsas: misc improvements

Change code to match HBA datasheet.
Change code to make it readable.
Add support big endian for mvs_prd_imt.
Add cpu_to_le32 and cpu_to_le64 to use on addr.
Add scan_finished for structure mvs_prv_info.
Signed-off-by: default avatarXiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent a4632aae
...@@ -58,24 +58,17 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id) ...@@ -58,24 +58,17 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
static void __devinit mvs_64xx_phy_hacks(struct mvs_info *mvi) static void __devinit mvs_64xx_phy_hacks(struct mvs_info *mvi)
{ {
void __iomem *regs = mvi->regs; void __iomem *regs = mvi->regs;
int i;
mvs_phy_hacks(mvi); mvs_phy_hacks(mvi);
if (!(mvi->flags & MVF_FLAG_SOC)) { if (!(mvi->flags & MVF_FLAG_SOC)) {
/* TEST - for phy decoding error, adjust voltage levels */ /* TEST - for phy decoding error, adjust voltage levels */
mw32(MVS_P0_VSR_ADDR + 0, 0x8); for (i = 0; i < MVS_SOC_PORTS; i++) {
mw32(MVS_P0_VSR_DATA + 0, 0x2F0); mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE8);
mvs_write_port_vsr_data(mvi, i, 0x2F0);
mw32(MVS_P0_VSR_ADDR + 8, 0x8); }
mw32(MVS_P0_VSR_DATA + 8, 0x2F0);
mw32(MVS_P0_VSR_ADDR + 16, 0x8);
mw32(MVS_P0_VSR_DATA + 16, 0x2F0);
mw32(MVS_P0_VSR_ADDR + 24, 0x8);
mw32(MVS_P0_VSR_DATA + 24, 0x2F0);
} else { } else {
int i;
/* disable auto port detection */ /* disable auto port detection */
mw32(MVS_GBL_PORT_TYPE, 0); mw32(MVS_GBL_PORT_TYPE, 0);
for (i = 0; i < mvi->chip->n_phy; i++) { for (i = 0; i < mvi->chip->n_phy; i++) {
...@@ -321,6 +314,11 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi) ...@@ -321,6 +314,11 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
/* init phys */ /* init phys */
mvs_64xx_phy_hacks(mvi); mvs_64xx_phy_hacks(mvi);
tmp = mvs_cr32(mvi, CMD_PHY_MODE_21);
tmp &= 0x0000ffff;
tmp |= 0x00fa0000;
mvs_cw32(mvi, CMD_PHY_MODE_21, tmp);
/* enable auto port detection */ /* enable auto port detection */
mw32(MVS_GBL_PORT_TYPE, MODE_AUTO_DET_EN); mw32(MVS_GBL_PORT_TYPE, MODE_AUTO_DET_EN);
...@@ -394,13 +392,17 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi) ...@@ -394,13 +392,17 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
/* reset CMD queue */ /* reset CMD queue */
tmp = mr32(MVS_PCS); tmp = mr32(MVS_PCS);
tmp |= PCS_CMD_RST; tmp |= PCS_CMD_RST;
tmp &= ~PCS_SELF_CLEAR;
mw32(MVS_PCS, tmp); mw32(MVS_PCS, tmp);
/* interrupt coalescing may cause missing HW interrput in some case, /* interrupt coalescing may cause missing HW interrput in some case,
* and the max count is 0x1ff, while our max slot is 0x200, * and the max count is 0x1ff, while our max slot is 0x200,
* it will make count 0. * it will make count 0.
*/ */
tmp = 0; tmp = 0;
mw32(MVS_INT_COAL, tmp); 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 | interrupt_coalescing; tmp = 0x10000 | interrupt_coalescing;
mw32(MVS_INT_COAL_TMOUT, tmp); mw32(MVS_INT_COAL_TMOUT, tmp);
......
...@@ -271,7 +271,14 @@ static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id) ...@@ -271,7 +271,14 @@ static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard) static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
{ {
u32 tmp; u32 tmp;
u32 delay = 5000;
if (hard == MVS_PHY_TUNE) {
mvs_write_port_cfg_addr(mvi, phy_id, PHYR_SATA_CTL);
tmp = mvs_read_port_cfg_data(mvi, phy_id);
mvs_write_port_cfg_data(mvi, phy_id, tmp|0x20000000);
mvs_write_port_cfg_data(mvi, phy_id, tmp|0x100000);
return;
}
tmp = mvs_read_port_irq_stat(mvi, phy_id); tmp = mvs_read_port_irq_stat(mvi, phy_id);
tmp &= ~PHYEV_RDY_CH; tmp &= ~PHYEV_RDY_CH;
mvs_write_port_irq_stat(mvi, phy_id, tmp); mvs_write_port_irq_stat(mvi, phy_id, tmp);
...@@ -281,12 +288,15 @@ static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard) ...@@ -281,12 +288,15 @@ static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
mvs_write_phy_ctl(mvi, phy_id, tmp); mvs_write_phy_ctl(mvi, phy_id, tmp);
do { do {
tmp = mvs_read_phy_ctl(mvi, phy_id); tmp = mvs_read_phy_ctl(mvi, phy_id);
} while (tmp & PHY_RST_HARD); udelay(10);
delay--;
} while ((tmp & PHY_RST_HARD) && delay);
if (!delay)
mv_dprintk("phy hard reset failed.\n");
} else { } else {
mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_STAT); tmp = mvs_read_phy_ctl(mvi, phy_id);
tmp = mvs_read_port_vsr_data(mvi, phy_id);
tmp |= PHY_RST; tmp |= PHY_RST;
mvs_write_port_vsr_data(mvi, phy_id, tmp); mvs_write_phy_ctl(mvi, phy_id, tmp);
} }
} }
...@@ -413,7 +423,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) ...@@ -413,7 +423,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
mvs_94xx_phy_disable(mvi, i); mvs_94xx_phy_disable(mvi, i);
/* set phy local SAS address */ /* set phy local SAS address */
mvs_set_sas_addr(mvi, i, CONFIG_ID_FRAME3, CONFIG_ID_FRAME4, mvs_set_sas_addr(mvi, i, CONFIG_ID_FRAME3, CONFIG_ID_FRAME4,
(mvi->phy[i].dev_sas_addr)); cpu_to_le64(mvi->phy[i].dev_sas_addr));
mvs_94xx_enable_xmt(mvi, i); mvs_94xx_enable_xmt(mvi, i);
mvs_94xx_config_reg_from_hba(mvi, i); mvs_94xx_config_reg_from_hba(mvi, i);
...@@ -459,7 +469,6 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) ...@@ -459,7 +469,6 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
*/ */
cctl = mr32(MVS_CTL); cctl = mr32(MVS_CTL);
cctl |= CCTL_ENDIAN_CMD; cctl |= CCTL_ENDIAN_CMD;
cctl |= CCTL_ENDIAN_DATA;
cctl &= ~CCTL_ENDIAN_OPEN; cctl &= ~CCTL_ENDIAN_OPEN;
cctl |= CCTL_ENDIAN_RSP; cctl |= CCTL_ENDIAN_RSP;
mw32_f(MVS_CTL, cctl); mw32_f(MVS_CTL, cctl);
...@@ -467,13 +476,17 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) ...@@ -467,13 +476,17 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
/* reset CMD queue */ /* reset CMD queue */
tmp = mr32(MVS_PCS); tmp = mr32(MVS_PCS);
tmp |= PCS_CMD_RST; tmp |= PCS_CMD_RST;
tmp &= ~PCS_SELF_CLEAR;
mw32(MVS_PCS, tmp); mw32(MVS_PCS, tmp);
/* interrupt coalescing may cause missing HW interrput in some case, /* interrupt coalescing may cause missing HW interrput in some case,
* and the max count is 0x1ff, while our max slot is 0x200, * and the max count is 0x1ff, while our max slot is 0x200,
* it will make count 0. * it will make count 0.
*/ */
tmp = 0; tmp = 0;
mw32(MVS_INT_COAL, tmp); 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 | interrupt_coalescing; tmp = 0x10000 | interrupt_coalescing;
mw32(MVS_INT_COAL_TMOUT, tmp); mw32(MVS_INT_COAL_TMOUT, tmp);
...@@ -674,24 +687,16 @@ static void mvs_94xx_non_spec_ncq_error(struct mvs_info *mvi) ...@@ -674,24 +687,16 @@ static void mvs_94xx_non_spec_ncq_error(struct mvs_info *mvi)
static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs) static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs)
{ {
void __iomem *regs = mvi->regs; void __iomem *regs = mvi->regs;
u32 tmp;
u8 reg_set = *tfs; u8 reg_set = *tfs;
if (*tfs == MVS_ID_NOT_MAPPED) if (*tfs == MVS_ID_NOT_MAPPED)
return; return;
mvi->sata_reg_set &= ~bit(reg_set); mvi->sata_reg_set &= ~bit(reg_set);
if (reg_set < 32) { if (reg_set < 32)
w_reg_set_enable(reg_set, (u32)mvi->sata_reg_set); w_reg_set_enable(reg_set, (u32)mvi->sata_reg_set);
tmp = mr32(MVS_INT_STAT_SRS_0) & (u32)mvi->sata_reg_set; else
if (tmp) w_reg_set_enable(reg_set, (u32)(mvi->sata_reg_set >> 32));
mw32(MVS_INT_STAT_SRS_0, tmp);
} else {
w_reg_set_enable(reg_set, mvi->sata_reg_set);
tmp = mr32(MVS_INT_STAT_SRS_1) & mvi->sata_reg_set;
if (tmp)
mw32(MVS_INT_STAT_SRS_1, tmp);
}
*tfs = MVS_ID_NOT_MAPPED; *tfs = MVS_ID_NOT_MAPPED;
...@@ -707,7 +712,7 @@ static u8 mvs_94xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs) ...@@ -707,7 +712,7 @@ static u8 mvs_94xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs)
return 0; return 0;
i = mv_ffc64(mvi->sata_reg_set); i = mv_ffc64(mvi->sata_reg_set);
if (i > 32) { if (i >= 32) {
mvi->sata_reg_set |= bit(i); mvi->sata_reg_set |= bit(i);
w_reg_set_enable(i, (u32)(mvi->sata_reg_set >> 32)); w_reg_set_enable(i, (u32)(mvi->sata_reg_set >> 32));
*tfs = i; *tfs = i;
...@@ -726,9 +731,12 @@ static void mvs_94xx_make_prd(struct scatterlist *scatter, int nr, void *prd) ...@@ -726,9 +731,12 @@ static void mvs_94xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
int i; int i;
struct scatterlist *sg; struct scatterlist *sg;
struct mvs_prd *buf_prd = prd; struct mvs_prd *buf_prd = prd;
struct mvs_prd_imt im_len;
*(u32 *)&im_len = 0;
for_each_sg(scatter, sg, nr, i) { for_each_sg(scatter, sg, nr, i) {
buf_prd->addr = cpu_to_le64(sg_dma_address(sg)); buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
buf_prd->im_len.len = cpu_to_le32(sg_dma_len(sg)); im_len.len = sg_dma_len(sg);
buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
buf_prd++; buf_prd++;
} }
} }
...@@ -751,7 +759,7 @@ static void mvs_94xx_get_dev_identify_frame(struct mvs_info *mvi, int port_id, ...@@ -751,7 +759,7 @@ static void mvs_94xx_get_dev_identify_frame(struct mvs_info *mvi, int port_id,
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
mvs_write_port_cfg_addr(mvi, port_id, mvs_write_port_cfg_addr(mvi, port_id,
CONFIG_ID_FRAME0 + i * 4); CONFIG_ID_FRAME0 + i * 4);
id_frame[i] = mvs_read_port_cfg_data(mvi, port_id); id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
} }
memcpy(id, id_frame, 28); memcpy(id, id_frame, 28);
} }
...@@ -766,7 +774,7 @@ static void mvs_94xx_get_att_identify_frame(struct mvs_info *mvi, int port_id, ...@@ -766,7 +774,7 @@ static void mvs_94xx_get_att_identify_frame(struct mvs_info *mvi, int port_id,
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
mvs_write_port_cfg_addr(mvi, port_id, mvs_write_port_cfg_addr(mvi, port_id,
CONFIG_ATT_ID_FRAME0 + i * 4); CONFIG_ATT_ID_FRAME0 + i * 4);
id_frame[i] = mvs_read_port_cfg_data(mvi, port_id); id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
mv_dprintk("94xx phy %d atta frame %d %x.\n", mv_dprintk("94xx phy %d atta frame %d %x.\n",
port_id + mvi->id * mvi->chip->n_phy, i, id_frame[i]); port_id + mvi->id * mvi->chip->n_phy, i, id_frame[i]);
} }
...@@ -924,8 +932,12 @@ void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, ...@@ -924,8 +932,12 @@ void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
int i; int i;
struct mvs_prd *buf_prd = prd; struct mvs_prd *buf_prd = prd;
dma_addr_t buf_dma; dma_addr_t buf_dma;
struct mvs_prd_imt im_len;
*(u32 *)&im_len = 0;
buf_prd += from; buf_prd += from;
#define PRD_CHAINED_ENTRY 0x01
if ((mvi->pdev->revision == VANIR_A0_REV) || if ((mvi->pdev->revision == VANIR_A0_REV) ||
(mvi->pdev->revision == VANIR_B0_REV)) (mvi->pdev->revision == VANIR_B0_REV))
buf_dma = (phy_mask <= 0x08) ? buf_dma = (phy_mask <= 0x08) ?
...@@ -933,10 +945,16 @@ void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, ...@@ -933,10 +945,16 @@ void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
else else
return; return;
for (i = 0; i < MAX_SG_ENTRY - from; i++) { for (i = from; i < MAX_SG_ENTRY; i++, ++buf_prd) {
buf_prd->addr = cpu_to_le64(buf_dma); if (i == MAX_SG_ENTRY - 1) {
buf_prd->im_len.len = cpu_to_le32(buf_len); buf_prd->addr = cpu_to_le64(virt_to_phys(buf_prd - 1));
++buf_prd; im_len.len = 2;
im_len.misc_ctl = PRD_CHAINED_ENTRY;
} else {
buf_prd->addr = cpu_to_le64(buf_dma);
im_len.len = buf_len;
}
buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
} }
} }
......
...@@ -142,8 +142,8 @@ enum sas_sata_vsp_regs { ...@@ -142,8 +142,8 @@ enum sas_sata_vsp_regs {
enum chip_register_bits { enum chip_register_bits {
PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8), PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8), PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 12),
PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (12), PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (16),
PHY_NEG_SPP_PHYS_LINK_RATE_MASK = PHY_NEG_SPP_PHYS_LINK_RATE_MASK =
(0x3 << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET), (0x3 << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
}; };
...@@ -219,17 +219,24 @@ union reg_phy_cfg { ...@@ -219,17 +219,24 @@ union reg_phy_cfg {
#define MAX_SG_ENTRY 255 #define MAX_SG_ENTRY 255
struct mvs_prd_imt { struct mvs_prd_imt {
#ifndef __BIG_ENDIAN
__le32 len:22; __le32 len:22;
u8 _r_a:2; u8 _r_a:2;
u8 misc_ctl:4; u8 misc_ctl:4;
u8 inter_sel:4; u8 inter_sel:4;
#else
u32 inter_sel:4;
u32 misc_ctl:4;
u32 _r_a:2;
u32 len:22;
#endif
}; };
struct mvs_prd { struct mvs_prd {
/* 64-bit buffer address */ /* 64-bit buffer address */
__le64 addr; __le64 addr;
/* 22-bit length */ /* 22-bit length */
struct mvs_prd_imt im_len; __le32 im_len;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* /*
......
...@@ -184,18 +184,6 @@ static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi) ...@@ -184,18 +184,6 @@ static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
/* not to halt for different port op during wideport link change */ /* not to halt for different port op during wideport link change */
mvs_cw32(mvi, CMD_APP_ERR_CONFIG, 0xffefbf7d); mvs_cw32(mvi, CMD_APP_ERR_CONFIG, 0xffefbf7d);
/* workaround for Seagate disk not-found OOB sequence, recv
* COMINIT before sending out COMWAKE */
tmp = mvs_cr32(mvi, CMD_PHY_MODE_21);
tmp &= 0x0000ffff;
tmp |= 0x00fa0000;
mvs_cw32(mvi, CMD_PHY_MODE_21, tmp);
tmp = mvs_cr32(mvi, CMD_PHY_TIMER);
tmp &= 0x1fffffff;
tmp |= (2U << 29); /* 8 ms retry */
mvs_cw32(mvi, CMD_PHY_TIMER, tmp);
} }
static inline void mvs_int_sata(struct mvs_info *mvi) static inline void mvs_int_sata(struct mvs_info *mvi)
......
...@@ -104,6 +104,7 @@ static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id) ...@@ -104,6 +104,7 @@ static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
struct asd_sas_phy *sas_phy = &phy->sas_phy; struct asd_sas_phy *sas_phy = &phy->sas_phy;
phy->mvi = mvi; phy->mvi = mvi;
phy->port = NULL;
init_timer(&phy->timer); init_timer(&phy->timer);
sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0; sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0;
sas_phy->class = SAS; sas_phy->class = SAS;
...@@ -366,7 +367,7 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev, ...@@ -366,7 +367,7 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
const struct pci_device_id *ent, const struct pci_device_id *ent,
struct Scsi_Host *shost, unsigned int id) struct Scsi_Host *shost, unsigned int id)
{ {
struct mvs_info *mvi; struct mvs_info *mvi = NULL;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
mvi = kzalloc(sizeof(*mvi) + mvi = kzalloc(sizeof(*mvi) +
......
This diff is collapsed.
...@@ -417,7 +417,8 @@ struct mvs_info { ...@@ -417,7 +417,8 @@ struct mvs_info {
struct mvs_prv_info{ struct mvs_prv_info{
u8 n_host; u8 n_host;
u8 n_phy; u8 n_phy;
u16 reserve; u8 scan_finished;
u8 reserve;
struct mvs_info *mvi[2]; struct mvs_info *mvi[2];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment