Commit a4632aae authored by Xiangliang Yu's avatar Xiangliang Yu Committed by James Bottomley

[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: default avatarXiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent b89e8f53
...@@ -48,7 +48,7 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id) ...@@ -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) ...@@ -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, &reg); pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &reg);
else else
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &reg); pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &reg);
...@@ -104,13 +104,13 @@ static void mvs_64xx_stp_reset(struct mvs_info *mvi, u32 phy_id) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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 { ...@@ -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))
......
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