Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
@@ -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);
+45 −27
Original line number Diff line number Diff line
@@ -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++) {
	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);
		buf_prd->im_len.len = cpu_to_le32(buf_len);
		++buf_prd;
			im_len.len = buf_len;
		}
		buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
	}
}

+10 −3
Original line number Diff line number Diff line
@@ -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));

/*
+0 −12
Original line number Diff line number Diff line
@@ -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)
+2 −1
Original line number Diff line number Diff line
@@ -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) +
Loading