Skip to content

Commit

Permalink
[SCSI] mvsas: misc improvements
Browse files Browse the repository at this point in the history
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: Xiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Xiangliang Yu authored and James Bottomley committed Jul 26, 2011
1 parent a4632aa commit 84fbd0c
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 113 deletions.
28 changes: 15 additions & 13 deletions drivers/scsi/mvsas/mv_64xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
72 changes: 45 additions & 27 deletions drivers/scsi/mvsas/mv_94xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -459,21 +469,24 @@ 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);

/* 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);
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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++;
}
}
Expand All @@ -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);
}
Expand All @@ -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]);
}
Expand Down Expand Up @@ -924,19 +932,29 @@ 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) ?
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;
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);
}
}

Expand Down
13 changes: 10 additions & 3 deletions drivers/scsi/mvsas/mv_94xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
};
Expand Down Expand Up @@ -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));

/*
Expand Down
12 changes: 0 additions & 12 deletions drivers/scsi/mvsas/mv_chips.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion drivers/scsi/mvsas/mv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) +
Expand Down
Loading

0 comments on commit 84fbd0c

Please sign in to comment.