[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 <yuxiangl@marvell.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
Родитель
b89e8f539f
Коммит
a4632aae8b
|
@ -48,7 +48,7 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
tmp = mr32(MVS_PCS);
|
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);
|
tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT);
|
||||||
else
|
else
|
||||||
tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2);
|
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;
|
u32 reg, tmp;
|
||||||
|
|
||||||
if (!(mvi->flags & MVF_FLAG_SOC)) {
|
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, ®);
|
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, ®);
|
||||||
else
|
else
|
||||||
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, ®);
|
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);
|
reg = mr32(MVS_PHY_CTL);
|
||||||
|
|
||||||
tmp = reg;
|
tmp = reg;
|
||||||
if (phy_id < 4)
|
if (phy_id < MVS_SOC_PORTS)
|
||||||
tmp |= (1U << phy_id) << PCTL_LINK_OFFS;
|
tmp |= (1U << phy_id) << PCTL_LINK_OFFS;
|
||||||
else
|
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 (!(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);
|
pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
|
||||||
mdelay(10);
|
mdelay(10);
|
||||||
pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, reg);
|
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;
|
tmp &= ~PHYEV_RDY_CH;
|
||||||
mvs_write_port_irq_stat(mvi, phy_id, tmp);
|
mvs_write_port_irq_stat(mvi, phy_id, tmp);
|
||||||
tmp = mvs_read_phy_ctl(mvi, phy_id);
|
tmp = mvs_read_phy_ctl(mvi, phy_id);
|
||||||
if (hard == 1)
|
if (hard == MVS_HARD_RESET)
|
||||||
tmp |= PHY_RST_HARD;
|
tmp |= PHY_RST_HARD;
|
||||||
else if (hard == 0)
|
else if (hard == MVS_SOFT_RESET)
|
||||||
tmp |= PHY_RST;
|
tmp |= PHY_RST;
|
||||||
mvs_write_phy_ctl(mvi, phy_id, tmp);
|
mvs_write_phy_ctl(mvi, phy_id, tmp);
|
||||||
if (hard) {
|
if (hard) {
|
||||||
|
@ -346,7 +346,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
|
||||||
|
|
||||||
mvs_64xx_enable_xmt(mvi, i);
|
mvs_64xx_enable_xmt(mvi, i);
|
||||||
|
|
||||||
mvs_64xx_phy_reset(mvi, i, 1);
|
mvs_64xx_phy_reset(mvi, i, MVS_HARD_RESET);
|
||||||
msleep(500);
|
msleep(500);
|
||||||
mvs_64xx_detect_porttype(mvi, i);
|
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;
|
tmp |= lrmax;
|
||||||
}
|
}
|
||||||
mvs_write_phy_ctl(mvi, phy_id, tmp);
|
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)
|
static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi)
|
||||||
|
|
|
@ -389,7 +389,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
|
||||||
mvs_phy_hacks(mvi);
|
mvs_phy_hacks(mvi);
|
||||||
|
|
||||||
/* set LED blink when IO*/
|
/* 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 = mr32(MVS_PA_VSR_PORT);
|
||||||
tmp &= 0xFFFF00FF;
|
tmp &= 0xFFFF00FF;
|
||||||
tmp |= 0x00003300;
|
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_config_reg_from_hba(mvi, i);
|
||||||
mvs_94xx_phy_enable(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);
|
msleep(500);
|
||||||
mvs_94xx_detect_porttype(mvi, i);
|
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)
|
static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx)
|
||||||
{
|
{
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
mvs_cw32(mvi, 0x300 + (slot_idx >> 3), 1 << (slot_idx % 32));
|
tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3));
|
||||||
do {
|
if (tmp && 1 << (slot_idx % 32)) {
|
||||||
tmp = mvs_cr32(mvi, 0x300 + (slot_idx >> 3));
|
mv_printk("command active %08X, slot [%x].\n", tmp, slot_idx);
|
||||||
} while (tmp & 1 << (slot_idx % 32));
|
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,
|
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;
|
void __iomem *regs = mvi->regs;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
mvs_94xx_clear_srs_irq(mvi, 0, 1);
|
||||||
|
|
||||||
if (type == PORT_TYPE_SATA) {
|
tmp = mr32(MVS_INT_STAT);
|
||||||
tmp = mr32(MVS_INT_STAT_SRS_0) | (1U << tfs);
|
mw32(MVS_INT_STAT, tmp | CINT_CI_STOP);
|
||||||
mw32(MVS_INT_STAT_SRS_0, tmp);
|
|
||||||
}
|
|
||||||
mw32(MVS_INT_STAT, CINT_CI_STOP);
|
|
||||||
tmp = mr32(MVS_PCS) | 0xFF00;
|
tmp = mr32(MVS_PCS) | 0xFF00;
|
||||||
mw32(MVS_PCS, tmp);
|
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,
|
void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
|
||||||
struct sas_phy_linkrates *rates)
|
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)
|
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)
|
static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time)
|
||||||
{
|
{
|
||||||
void __iomem *regs = mvi->regs;
|
void __iomem *regs = mvi->regs;
|
||||||
|
|
|
@ -109,6 +109,7 @@ enum hw_registers {
|
||||||
MVS_P4_VSR_DATA = 0x254, /* phy4 VSR data */
|
MVS_P4_VSR_DATA = 0x254, /* phy4 VSR data */
|
||||||
MVS_PA_VSR_ADDR = 0x290, /* All port VSR addr */
|
MVS_PA_VSR_ADDR = 0x290, /* All port VSR addr */
|
||||||
MVS_PA_VSR_PORT = 0x294, /* All port VSR data */
|
MVS_PA_VSR_PORT = 0x294, /* All port VSR data */
|
||||||
|
MVS_COMMAND_ACTIVE = 0x300,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pci_cfg_registers {
|
enum pci_cfg_registers {
|
||||||
|
@ -132,6 +133,7 @@ enum sas_sata_vsp_regs {
|
||||||
VSR_PHY_MODE9 = 0x09 * 4, /* Test */
|
VSR_PHY_MODE9 = 0x09 * 4, /* Test */
|
||||||
VSR_PHY_MODE10 = 0x0A * 4, /* Power */
|
VSR_PHY_MODE10 = 0x0A * 4, /* Power */
|
||||||
VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */
|
VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */
|
||||||
|
VSR_PHY_ACT_LED = 0x0C * 4, /* Activity LED control */
|
||||||
|
|
||||||
VSR_PHY_FFE_CONTROL = 0x10C,
|
VSR_PHY_FFE_CONTROL = 0x10C,
|
||||||
VSR_PHY_DFE_UPDATE_CRTL = 0x110,
|
VSR_PHY_DFE_UPDATE_CRTL = 0x110,
|
||||||
|
|
|
@ -395,9 +395,10 @@ enum mvs_info_flags {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mvs_event_flags {
|
enum mvs_event_flags {
|
||||||
PHY_PLUG_EVENT = (3U),
|
PHY_PLUG_EVENT = (3U),
|
||||||
PHY_PLUG_IN = (1U << 0), /* phy plug in */
|
PHY_PLUG_IN = (1U << 0), /* phy plug in */
|
||||||
PHY_PLUG_OUT = (1U << 1), /* phy plug out */
|
PHY_PLUG_OUT = (1U << 1), /* phy plug out */
|
||||||
|
EXP_BRCT_CHG = (1U << 2), /* broadcast change */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mvs_port_type {
|
enum mvs_port_type {
|
||||||
|
|
|
@ -39,15 +39,15 @@ int interrupt_coalescing = 0x80;
|
||||||
static struct scsi_transport_template *mvs_stt;
|
static struct scsi_transport_template *mvs_stt;
|
||||||
struct kmem_cache *mvs_task_list_cache;
|
struct kmem_cache *mvs_task_list_cache;
|
||||||
static const struct mvs_chip_info mvs_chips[] = {
|
static const struct mvs_chip_info mvs_chips[] = {
|
||||||
[chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
|
[chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
|
||||||
[chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
|
[chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
|
||||||
[chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, },
|
[chip_6485] = { 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, },
|
||||||
[chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
|
[chip_9180] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
|
||||||
[chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
|
[chip_9480] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
|
||||||
[chip_9445] = { 1, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, },
|
[chip_9445] = { 1, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
|
||||||
[chip_9485] = { 2, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, },
|
[chip_9485] = { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
|
||||||
[chip_1300] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
|
[chip_1300] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
|
||||||
[chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
|
[chip_1320] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device_attribute *mvst_host_attrs[];
|
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;
|
((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr;
|
||||||
|
|
||||||
shost->transportt = mvs_stt;
|
shost->transportt = mvs_stt;
|
||||||
shost->max_id = 128;
|
shost->max_id = MVS_MAX_DEVICES;
|
||||||
shost->max_lun = ~0;
|
shost->max_lun = ~0;
|
||||||
shost->max_channel = 1;
|
shost->max_channel = 1;
|
||||||
shost->max_cmd_len = 16;
|
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;
|
can_queue = MVS_CHIP_SLOT_SZ;
|
||||||
|
|
||||||
sha->lldd_queue_size = can_queue;
|
sha->lldd_queue_size = can_queue;
|
||||||
|
shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG);
|
||||||
shost->can_queue = can_queue;
|
shost->can_queue = can_queue;
|
||||||
mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
|
mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
|
||||||
sha->core.shost = mvi->shost;
|
sha->core.shost = mvi->shost;
|
||||||
|
|
|
@ -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);
|
tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id);
|
||||||
if (tmp & PHY_RST_HARD)
|
if (tmp & PHY_RST_HARD)
|
||||||
break;
|
break;
|
||||||
MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1);
|
MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_HARD_RESET);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PHY_FUNC_LINK_RESET:
|
case PHY_FUNC_LINK_RESET:
|
||||||
MVS_CHIP_DISP->phy_enable(mvi, phy_id);
|
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;
|
break;
|
||||||
|
|
||||||
case PHY_FUNC_DISABLE:
|
case PHY_FUNC_DISABLE:
|
||||||
|
@ -1758,12 +1758,63 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
|
||||||
return stat;
|
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,
|
static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
|
||||||
u32 slot_idx)
|
u32 slot_idx)
|
||||||
{
|
{
|
||||||
struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
|
struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
|
||||||
int stat;
|
int stat;
|
||||||
u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
|
u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
|
||||||
|
u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response + 1));
|
||||||
u32 tfs = 0;
|
u32 tfs = 0;
|
||||||
enum mvs_port_type type = PORT_TYPE_SAS;
|
enum mvs_port_type type = PORT_TYPE_SAS;
|
||||||
|
|
||||||
|
@ -1775,8 +1826,19 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
|
||||||
stat = SAM_STAT_CHECK_CONDITION;
|
stat = SAM_STAT_CHECK_CONDITION;
|
||||||
switch (task->task_proto) {
|
switch (task->task_proto) {
|
||||||
case SAS_PROTOCOL_SSP:
|
case SAS_PROTOCOL_SSP:
|
||||||
|
{
|
||||||
stat = SAS_ABORTED_TASK;
|
stat = SAS_ABORTED_TASK;
|
||||||
|
if ((err_dw0 & NO_DEST) || err_dw1 & bit(31)) {
|
||||||
|
struct ssp_response_iu *iu = slot->response +
|
||||||
|
sizeof(struct mvs_err_info);
|
||||||
|
mvs_fill_ssp_resp_iu(iu, NOT_READY, 0x04, 01);
|
||||||
|
sas_ssp_task_response(mvi->dev, task, iu);
|
||||||
|
stat = SAM_STAT_CHECK_CONDITION;
|
||||||
|
}
|
||||||
|
if (err_dw1 & bit(31))
|
||||||
|
mv_printk("reuse same slot, retry command.\n");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SAS_PROTOCOL_SMP:
|
case SAS_PROTOCOL_SMP:
|
||||||
stat = SAM_STAT_CHECK_CONDITION;
|
stat = SAM_STAT_CHECK_CONDITION;
|
||||||
break;
|
break;
|
||||||
|
@ -1974,13 +2036,13 @@ static void mvs_work_queue(struct work_struct *work)
|
||||||
struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);
|
struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);
|
||||||
struct mvs_info *mvi = mwq->mvi;
|
struct mvs_info *mvi = mwq->mvi;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
u32 phy_no = (unsigned long) mwq->data;
|
||||||
|
struct sas_ha_struct *sas_ha = mvi->sas;
|
||||||
|
struct mvs_phy *phy = &mvi->phy[phy_no];
|
||||||
|
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
||||||
|
|
||||||
spin_lock_irqsave(&mvi->lock, flags);
|
spin_lock_irqsave(&mvi->lock, flags);
|
||||||
if (mwq->handler & PHY_PLUG_EVENT) {
|
if (mwq->handler & PHY_PLUG_EVENT) {
|
||||||
u32 phy_no = (unsigned long) mwq->data;
|
|
||||||
struct sas_ha_struct *sas_ha = mvi->sas;
|
|
||||||
struct mvs_phy *phy = &mvi->phy[phy_no];
|
|
||||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
|
||||||
|
|
||||||
if (phy->phy_event & PHY_PLUG_OUT) {
|
if (phy->phy_event & PHY_PLUG_OUT) {
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
@ -2002,6 +2064,11 @@ static void mvs_work_queue(struct work_struct *work)
|
||||||
mv_dprintk("phy%d Attached Device\n", phy_no);
|
mv_dprintk("phy%d Attached Device\n", phy_no);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (mwq->handler & EXP_BRCT_CHG) {
|
||||||
|
phy->phy_event &= ~EXP_BRCT_CHG;
|
||||||
|
sas_ha->notify_port_event(sas_phy,
|
||||||
|
PORTE_BROADCAST_RCVD);
|
||||||
|
mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
|
||||||
}
|
}
|
||||||
list_del(&mwq->entry);
|
list_del(&mwq->entry);
|
||||||
spin_unlock_irqrestore(&mvi->lock, flags);
|
spin_unlock_irqrestore(&mvi->lock, flags);
|
||||||
|
@ -2037,7 +2104,7 @@ static void mvs_sig_time_out(unsigned long tphy)
|
||||||
if (&mvi->phy[phy_no] == phy) {
|
if (&mvi->phy[phy_no] == phy) {
|
||||||
mv_dprintk("Get signature time out, reset phy %d\n",
|
mv_dprintk("Get signature time out, reset phy %d\n",
|
||||||
phy_no+mvi->id*mvi->chip->n_phy);
|
phy_no+mvi->id*mvi->chip->n_phy);
|
||||||
MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1);
|
MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_HARD_RESET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2045,9 +2112,7 @@ static void mvs_sig_time_out(unsigned long tphy)
|
||||||
void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
|
void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
|
||||||
{
|
{
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
struct sas_ha_struct *sas_ha = mvi->sas;
|
|
||||||
struct mvs_phy *phy = &mvi->phy[phy_no];
|
struct mvs_phy *phy = &mvi->phy[phy_no];
|
||||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
|
||||||
|
|
||||||
phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no);
|
phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no);
|
||||||
mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy,
|
mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy,
|
||||||
|
@ -2086,7 +2151,7 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
|
||||||
phy_no);
|
phy_no);
|
||||||
else
|
else
|
||||||
MVS_CHIP_DISP->phy_reset(mvi,
|
MVS_CHIP_DISP->phy_reset(mvi,
|
||||||
phy_no, 0);
|
phy_no, MVS_SOFT_RESET);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2118,14 +2183,14 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
|
||||||
}
|
}
|
||||||
mvs_update_phyinfo(mvi, phy_no, 0);
|
mvs_update_phyinfo(mvi, phy_no, 0);
|
||||||
if (phy->phy_type & PORT_TYPE_SAS) {
|
if (phy->phy_type & PORT_TYPE_SAS) {
|
||||||
MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2);
|
MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_PHY_TUNE);
|
||||||
mdelay(10);
|
mdelay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
mvs_bytes_dmaed(mvi, phy_no);
|
mvs_bytes_dmaed(mvi, phy_no);
|
||||||
/* whether driver is going to handle hot plug */
|
/* whether driver is going to handle hot plug */
|
||||||
if (phy->phy_event & PHY_PLUG_OUT) {
|
if (phy->phy_event & PHY_PLUG_OUT) {
|
||||||
mvs_port_notify_formed(sas_phy, 0);
|
mvs_port_notify_formed(&phy->sas_phy, 0);
|
||||||
phy->phy_event &= ~PHY_PLUG_OUT;
|
phy->phy_event &= ~PHY_PLUG_OUT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2135,9 +2200,8 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
|
||||||
} else if (phy->irq_status & PHYEV_BROAD_CH) {
|
} else if (phy->irq_status & PHYEV_BROAD_CH) {
|
||||||
mv_dprintk("port %d broadcast change.\n",
|
mv_dprintk("port %d broadcast change.\n",
|
||||||
phy_no + mvi->id*mvi->chip->n_phy);
|
phy_no + mvi->id*mvi->chip->n_phy);
|
||||||
/* exception for Samsung disk drive*/
|
mvs_handle_event(mvi, (void *)(unsigned long)phy_no,
|
||||||
mdelay(1000);
|
EXP_BRCT_CHG);
|
||||||
sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
|
|
||||||
}
|
}
|
||||||
MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
|
MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,11 @@ enum dev_status {
|
||||||
MVS_DEV_EH = 0x1,
|
MVS_DEV_EH = 0x1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum dev_reset {
|
||||||
|
MVS_SOFT_RESET = 0,
|
||||||
|
MVS_HARD_RESET = 1,
|
||||||
|
MVS_PHY_TUNE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct mvs_info;
|
struct mvs_info;
|
||||||
|
|
||||||
|
@ -176,9 +181,11 @@ struct mvs_chip_info {
|
||||||
u32 fis_offs;
|
u32 fis_offs;
|
||||||
u32 fis_count;
|
u32 fis_count;
|
||||||
u32 srs_sz;
|
u32 srs_sz;
|
||||||
|
u32 sg_width;
|
||||||
u32 slot_width;
|
u32 slot_width;
|
||||||
const struct mvs_dispatch *dispatch;
|
const struct mvs_dispatch *dispatch;
|
||||||
};
|
};
|
||||||
|
#define MVS_MAX_SG (1U << mvi->chip->sg_width)
|
||||||
#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width)
|
#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width)
|
||||||
#define MVS_RX_FISL_SZ \
|
#define MVS_RX_FISL_SZ \
|
||||||
(mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100))
|
(mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче