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)
static void __devinit mvs_64xx_phy_hacks(struct mvs_info *mvi)
{
void __iomem *regs = mvi->regs;
int i;
mvs_phy_hacks(mvi);
if (!(mvi->flags & MVF_FLAG_SOC)) {
/* TEST - for phy decoding error, adjust voltage levels */
mw32(MVS_P0_VSR_ADDR + 0, 0x8);
mw32(MVS_P0_VSR_DATA + 0, 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);
for (i = 0; i < MVS_SOC_PORTS; i++) {
mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE8);
mvs_write_port_vsr_data(mvi, i, 0x2F0);
}
} else {
int i;
/* disable auto port detection */
mw32(MVS_GBL_PORT_TYPE, 0);
for (i = 0; i < mvi->chip->n_phy; i++) {
......@@ -321,6 +314,11 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
/* init phys */
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 */
mw32(MVS_GBL_PORT_TYPE, MODE_AUTO_DET_EN);
......@@ -394,13 +392,17 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
/* reset CMD queue */
tmp = mr32(MVS_PCS);
tmp |= PCS_CMD_RST;
tmp &= ~PCS_SELF_CLEAR;
mw32(MVS_PCS, tmp);
/* 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.
*/
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;
mw32(MVS_INT_COAL_TMOUT, tmp);
......
......@@ -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)
{
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 &= ~PHYEV_RDY_CH;
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)
mvs_write_phy_ctl(mvi, phy_id, tmp);
do {
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 {
mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_STAT);
tmp = mvs_read_port_vsr_data(mvi, phy_id);
tmp = mvs_read_phy_ctl(mvi, phy_id);
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)
mvs_94xx_phy_disable(mvi, i);
/* set phy local SAS address */
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_config_reg_from_hba(mvi, i);
......@@ -459,7 +469,6 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
*/
cctl = mr32(MVS_CTL);
cctl |= CCTL_ENDIAN_CMD;
cctl |= CCTL_ENDIAN_DATA;
cctl &= ~CCTL_ENDIAN_OPEN;
cctl |= CCTL_ENDIAN_RSP;
mw32_f(MVS_CTL, cctl);
......@@ -467,13 +476,17 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
/* reset CMD queue */
tmp = mr32(MVS_PCS);
tmp |= PCS_CMD_RST;
tmp &= ~PCS_SELF_CLEAR;
mw32(MVS_PCS, tmp);
/* 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.
*/
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;
mw32(MVS_INT_COAL_TMOUT, tmp);
......@@ -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)
{
void __iomem *regs = mvi->regs;
u32 tmp;
u8 reg_set = *tfs;
if (*tfs == MVS_ID_NOT_MAPPED)
return;
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);
tmp = mr32(MVS_INT_STAT_SRS_0) & (u32)mvi->sata_reg_set;
if (tmp)
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);
}
else
w_reg_set_enable(reg_set, (u32)(mvi->sata_reg_set >> 32));
*tfs = MVS_ID_NOT_MAPPED;
......@@ -707,7 +712,7 @@ static u8 mvs_94xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs)
return 0;
i = mv_ffc64(mvi->sata_reg_set);
if (i > 32) {
if (i >= 32) {
mvi->sata_reg_set |= bit(i);
w_reg_set_enable(i, (u32)(mvi->sata_reg_set >> 32));
*tfs = i;
......@@ -726,9 +731,12 @@ static void mvs_94xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
int i;
struct scatterlist *sg;
struct mvs_prd *buf_prd = prd;
struct mvs_prd_imt im_len;
*(u32 *)&im_len = 0;
for_each_sg(scatter, sg, nr, i) {
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++;
}
}
......@@ -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++) {
mvs_write_port_cfg_addr(mvi, port_id,
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);
}
......@@ -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++) {
mvs_write_port_cfg_addr(mvi, port_id,
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",
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,
int i;
struct mvs_prd *buf_prd = prd;
dma_addr_t buf_dma;
struct mvs_prd_imt im_len;
*(u32 *)&im_len = 0;
buf_prd += from;
#define PRD_CHAINED_ENTRY 0x01
if ((mvi->pdev->revision == VANIR_A0_REV) ||
(mvi->pdev->revision == VANIR_B0_REV))
buf_dma = (phy_mask <= 0x08) ?
......@@ -933,10 +945,16 @@ void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
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;
for (i = from; i < MAX_SG_ENTRY; i++, ++buf_prd) {
if (i == MAX_SG_ENTRY - 1) {
buf_prd->addr = cpu_to_le64(virt_to_phys(buf_prd - 1));
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 {
enum chip_register_bits {
PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 8),
PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (12),
PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0x7 << 12),
PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (16),
PHY_NEG_SPP_PHYS_LINK_RATE_MASK =
(0x3 << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
};
......@@ -219,17 +219,24 @@ union reg_phy_cfg {
#define MAX_SG_ENTRY 255
struct mvs_prd_imt {
#ifndef __BIG_ENDIAN
__le32 len:22;
u8 _r_a:2;
u8 misc_ctl: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 {
/* 64-bit buffer address */
__le64 addr;
/* 22-bit length */
struct mvs_prd_imt im_len;
__le32 im_len;
} __attribute__ ((packed));
/*
......
......@@ -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 */
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)
......
......@@ -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;
phy->mvi = mvi;
phy->port = NULL;
init_timer(&phy->timer);
sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0;
sas_phy->class = SAS;
......@@ -366,7 +367,7 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
const struct pci_device_id *ent,
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);
mvi = kzalloc(sizeof(*mvi) +
......
This diff is collapsed.
......@@ -417,7 +417,8 @@ struct mvs_info {
struct mvs_prv_info{
u8 n_host;
u8 n_phy;
u16 reserve;
u8 scan_finished;
u8 reserve;
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