aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mvsas
diff options
context:
space:
mode:
authorXiangliang Yu <yuxiangl@marvell.com>2011-05-24 10:36:02 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-07-26 02:36:11 -0400
commita4632aae8b662b1f32fe3fc558a813cd5c3daae6 (patch)
treea88ee045018877314d76b9cb99e3e837b78d5565 /drivers/scsi/mvsas
parentb89e8f539ff8bcf2a1464578fa91cb96cc433fc3 (diff)
[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>
Diffstat (limited to 'drivers/scsi/mvsas')
-rw-r--r--drivers/scsi/mvsas/mv_64xx.c18
-rw-r--r--drivers/scsi/mvsas/mv_94xx.c80
-rw-r--r--drivers/scsi/mvsas/mv_94xx.h2
-rw-r--r--drivers/scsi/mvsas/mv_defs.h3
-rw-r--r--drivers/scsi/mvsas/mv_init.c21
-rw-r--r--drivers/scsi/mvsas/mv_sas.c94
-rw-r--r--drivers/scsi/mvsas/mv_sas.h7
7 files changed, 169 insertions, 56 deletions
diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c
index 96bde3448c7d..702c767ee46f 100644
--- a/drivers/scsi/mvsas/mv_64xx.c
+++ b/drivers/scsi/mvsas/mv_64xx.c
@@ -48,7 +48,7 @@ static void __devinit mvs_64xx_enable_xmt(struct mvs_info *mvi, int phy_id)
48 u32 tmp; 48 u32 tmp;
49 49
50 tmp = mr32(MVS_PCS); 50 tmp = mr32(MVS_PCS);
51 if (mvi->chip->n_phy <= 4) 51 if (mvi->chip->n_phy <= MVS_SOC_PORTS)
52 tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT); 52 tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT);
53 else 53 else
54 tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2); 54 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 u32 reg, tmp; 95 u32 reg, tmp;
96 96
97 if (!(mvi->flags & MVF_FLAG_SOC)) { 97 if (!(mvi->flags & MVF_FLAG_SOC)) {
98 if (phy_id < 4) 98 if (phy_id < MVS_SOC_PORTS)
99 pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &reg); 99 pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &reg);
100 else 100 else
101 pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &reg); 101 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 reg = mr32(MVS_PHY_CTL); 104 reg = mr32(MVS_PHY_CTL);
105 105
106 tmp = reg; 106 tmp = reg;
107 if (phy_id < 4) 107 if (phy_id < MVS_SOC_PORTS)
108 tmp |= (1U << phy_id) << PCTL_LINK_OFFS; 108 tmp |= (1U << phy_id) << PCTL_LINK_OFFS;
109 else 109 else
110 tmp |= (1U << (phy_id - 4)) << PCTL_LINK_OFFS; 110 tmp |= (1U << (phy_id - MVS_SOC_PORTS)) << PCTL_LINK_OFFS;
111 111
112 if (!(mvi->flags & MVF_FLAG_SOC)) { 112 if (!(mvi->flags & MVF_FLAG_SOC)) {
113 if (phy_id < 4) { 113 if (phy_id < MVS_SOC_PORTS) {
114 pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp); 114 pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
115 mdelay(10); 115 mdelay(10);
116 pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, reg); 116 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 tmp &= ~PHYEV_RDY_CH; 133 tmp &= ~PHYEV_RDY_CH;
134 mvs_write_port_irq_stat(mvi, phy_id, tmp); 134 mvs_write_port_irq_stat(mvi, phy_id, tmp);
135 tmp = mvs_read_phy_ctl(mvi, phy_id); 135 tmp = mvs_read_phy_ctl(mvi, phy_id);
136 if (hard == 1) 136 if (hard == MVS_HARD_RESET)
137 tmp |= PHY_RST_HARD; 137 tmp |= PHY_RST_HARD;
138 else if (hard == 0) 138 else if (hard == MVS_SOFT_RESET)
139 tmp |= PHY_RST; 139 tmp |= PHY_RST;
140 mvs_write_phy_ctl(mvi, phy_id, tmp); 140 mvs_write_phy_ctl(mvi, phy_id, tmp);
141 if (hard) { 141 if (hard) {
@@ -346,7 +346,7 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
346 346
347 mvs_64xx_enable_xmt(mvi, i); 347 mvs_64xx_enable_xmt(mvi, i);
348 348
349 mvs_64xx_phy_reset(mvi, i, 1); 349 mvs_64xx_phy_reset(mvi, i, MVS_HARD_RESET);
350 msleep(500); 350 msleep(500);
351 mvs_64xx_detect_porttype(mvi, i); 351 mvs_64xx_detect_porttype(mvi, i);
352 } 352 }
@@ -661,7 +661,7 @@ void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
661 tmp |= lrmax; 661 tmp |= lrmax;
662 } 662 }
663 mvs_write_phy_ctl(mvi, phy_id, tmp); 663 mvs_write_phy_ctl(mvi, phy_id, tmp);
664 mvs_64xx_phy_reset(mvi, phy_id, 1); 664 mvs_64xx_phy_reset(mvi, phy_id, MVS_HARD_RESET);
665} 665}
666 666
667static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi) 667static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi)
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
index 5b25f1b7fa52..a0ec4aaa24a2 100644
--- a/drivers/scsi/mvsas/mv_94xx.c
+++ b/drivers/scsi/mvsas/mv_94xx.c
@@ -389,7 +389,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
389 mvs_phy_hacks(mvi); 389 mvs_phy_hacks(mvi);
390 390
391 /* set LED blink when IO*/ 391 /* set LED blink when IO*/
392 mw32(MVS_PA_VSR_ADDR, 0x00000030); 392 mw32(MVS_PA_VSR_ADDR, VSR_PHY_ACT_LED);
393 tmp = mr32(MVS_PA_VSR_PORT); 393 tmp = mr32(MVS_PA_VSR_PORT);
394 tmp &= 0xFFFF00FF; 394 tmp &= 0xFFFF00FF;
395 tmp |= 0x00003300; 395 tmp |= 0x00003300;
@@ -419,7 +419,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
419 mvs_94xx_config_reg_from_hba(mvi, i); 419 mvs_94xx_config_reg_from_hba(mvi, i);
420 mvs_94xx_phy_enable(mvi, i); 420 mvs_94xx_phy_enable(mvi, i);
421 421
422 mvs_94xx_phy_reset(mvi, i, 1); 422 mvs_94xx_phy_reset(mvi, i, PHY_RST_HARD);
423 msleep(500); 423 msleep(500);
424 mvs_94xx_detect_porttype(mvi, i); 424 mvs_94xx_detect_porttype(mvi, i);
425 } 425 }
@@ -585,10 +585,48 @@ static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat)
585static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx) 585static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx)
586{ 586{
587 u32 tmp; 587 u32 tmp;
588 mvs_cw32(mvi, 0x300 + (slot_idx >> 3), 1 << (slot_idx % 32)); 588 tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3));
589 do { 589 if (tmp && 1 << (slot_idx % 32)) {
590 tmp = mvs_cr32(mvi, 0x300 + (slot_idx >> 3)); 590 mv_printk("command active %08X, slot [%x].\n", tmp, slot_idx);
591 } while (tmp & 1 << (slot_idx % 32)); 591 mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3),
592 1 << (slot_idx % 32));
593 do {
594 tmp = mvs_cr32(mvi,
595 MVS_COMMAND_ACTIVE + (slot_idx >> 3));
596 } while (tmp & 1 << (slot_idx % 32));
597 }
598}
599
600void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
601{
602 void __iomem *regs = mvi->regs;
603 u32 tmp;
604
605 if (clear_all) {
606 tmp = mr32(MVS_INT_STAT_SRS_0);
607 if (tmp) {
608 mv_dprintk("check SRS 0 %08X.\n", tmp);
609 mw32(MVS_INT_STAT_SRS_0, tmp);
610 }
611 tmp = mr32(MVS_INT_STAT_SRS_1);
612 if (tmp) {
613 mv_dprintk("check SRS 1 %08X.\n", tmp);
614 mw32(MVS_INT_STAT_SRS_1, tmp);
615 }
616 } else {
617 if (reg_set > 31)
618 tmp = mr32(MVS_INT_STAT_SRS_1);
619 else
620 tmp = mr32(MVS_INT_STAT_SRS_0);
621
622 if (tmp & (1 << (reg_set % 32))) {
623 mv_dprintk("register set 0x%x was stopped.\n", reg_set);
624 if (reg_set > 31)
625 mw32(MVS_INT_STAT_SRS_1, 1 << (reg_set % 32));
626 else
627 mw32(MVS_INT_STAT_SRS_0, 1 << (reg_set % 32));
628 }
629 }
592} 630}
593 631
594static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type, 632static 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{ 634{
597 void __iomem *regs = mvi->regs; 635 void __iomem *regs = mvi->regs;
598 u32 tmp; 636 u32 tmp;
637 mvs_94xx_clear_srs_irq(mvi, 0, 1);
599 638
600 if (type == PORT_TYPE_SATA) { 639 tmp = mr32(MVS_INT_STAT);
601 tmp = mr32(MVS_INT_STAT_SRS_0) | (1U << tfs); 640 mw32(MVS_INT_STAT, tmp | CINT_CI_STOP);
602 mw32(MVS_INT_STAT_SRS_0, tmp);
603 }
604 mw32(MVS_INT_STAT, CINT_CI_STOP);
605 tmp = mr32(MVS_PCS) | 0xFF00; 641 tmp = mr32(MVS_PCS) | 0xFF00;
606 mw32(MVS_PCS, tmp); 642 mw32(MVS_PCS, tmp);
607} 643}
@@ -794,7 +830,18 @@ static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i,
794void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, 830void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
795 struct sas_phy_linkrates *rates) 831 struct sas_phy_linkrates *rates)
796{ 832{
797 /* TODO */ 833 u32 lrmax = 0;
834 u32 tmp;
835
836 tmp = mvs_read_phy_ctl(mvi, phy_id);
837 lrmax = (rates->maximum_linkrate - SAS_LINK_RATE_1_5_GBPS) << 12;
838
839 if (lrmax) {
840 tmp &= ~(0x3 << 12);
841 tmp |= lrmax;
842 }
843 mvs_write_phy_ctl(mvi, phy_id, tmp);
844 mvs_94xx_phy_reset(mvi, phy_id, PHY_RST_HARD);
798} 845}
799 846
800static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi) 847static 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 } 940 }
894} 941}
895 942
896/*
897 * FIXME JEJB: temporary nop clear_srs_irq to make 94xx still work
898 * with 64xx fixes
899 */
900static void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set,
901 u8 clear_all)
902{
903}
904
905static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time) 943static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time)
906{ 944{
907 void __iomem *regs = mvi->regs; 945 void __iomem *regs = mvi->regs;
diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h
index 723fd0adf1c6..6fc2c105c9d7 100644
--- a/drivers/scsi/mvsas/mv_94xx.h
+++ b/drivers/scsi/mvsas/mv_94xx.h
@@ -109,6 +109,7 @@ enum hw_registers {
109 MVS_P4_VSR_DATA = 0x254, /* phy4 VSR data */ 109 MVS_P4_VSR_DATA = 0x254, /* phy4 VSR data */
110 MVS_PA_VSR_ADDR = 0x290, /* All port VSR addr */ 110 MVS_PA_VSR_ADDR = 0x290, /* All port VSR addr */
111 MVS_PA_VSR_PORT = 0x294, /* All port VSR data */ 111 MVS_PA_VSR_PORT = 0x294, /* All port VSR data */
112 MVS_COMMAND_ACTIVE = 0x300,
112}; 113};
113 114
114enum pci_cfg_registers { 115enum pci_cfg_registers {
@@ -132,6 +133,7 @@ enum sas_sata_vsp_regs {
132 VSR_PHY_MODE9 = 0x09 * 4, /* Test */ 133 VSR_PHY_MODE9 = 0x09 * 4, /* Test */
133 VSR_PHY_MODE10 = 0x0A * 4, /* Power */ 134 VSR_PHY_MODE10 = 0x0A * 4, /* Power */
134 VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */ 135 VSR_PHY_MODE11 = 0x0B * 4, /* Phy Mode */
136 VSR_PHY_ACT_LED = 0x0C * 4, /* Activity LED control */
135 137
136 VSR_PHY_FFE_CONTROL = 0x10C, 138 VSR_PHY_FFE_CONTROL = 0x10C,
137 VSR_PHY_DFE_UPDATE_CRTL = 0x110, 139 VSR_PHY_DFE_UPDATE_CRTL = 0x110,
diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h
index e39629d874b5..1927e1bbb8eb 100644
--- a/drivers/scsi/mvsas/mv_defs.h
+++ b/drivers/scsi/mvsas/mv_defs.h
@@ -395,9 +395,10 @@ enum mvs_info_flags {
395}; 395};
396 396
397enum mvs_event_flags { 397enum mvs_event_flags {
398 PHY_PLUG_EVENT = (3U), 398 PHY_PLUG_EVENT = (3U),
399 PHY_PLUG_IN = (1U << 0), /* phy plug in */ 399 PHY_PLUG_IN = (1U << 0), /* phy plug in */
400 PHY_PLUG_OUT = (1U << 1), /* phy plug out */ 400 PHY_PLUG_OUT = (1U << 1), /* phy plug out */
401 EXP_BRCT_CHG = (1U << 2), /* broadcast change */
401}; 402};
402 403
403enum mvs_port_type { 404enum mvs_port_type {
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index a7815f9c63bc..bf7d90cfbcfc 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -39,15 +39,15 @@ int interrupt_coalescing = 0x80;
39static struct scsi_transport_template *mvs_stt; 39static struct scsi_transport_template *mvs_stt;
40struct kmem_cache *mvs_task_list_cache; 40struct kmem_cache *mvs_task_list_cache;
41static const struct mvs_chip_info mvs_chips[] = { 41static const struct mvs_chip_info mvs_chips[] = {
42 [chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, 42 [chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
43 [chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, 43 [chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
44 [chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, }, 44 [chip_6485] = { 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, },
45 [chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, 45 [chip_9180] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
46 [chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, 46 [chip_9480] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
47 [chip_9445] = { 1, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, }, 47 [chip_9445] = { 1, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
48 [chip_9485] = { 2, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, }, 48 [chip_9485] = { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
49 [chip_1300] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, 49 [chip_1300] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
50 [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, 50 [chip_1320] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
51}; 51};
52 52
53struct device_attribute *mvst_host_attrs[]; 53struct device_attribute *mvst_host_attrs[];
@@ -466,7 +466,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
466 ((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr; 466 ((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr;
467 467
468 shost->transportt = mvs_stt; 468 shost->transportt = mvs_stt;
469 shost->max_id = 128; 469 shost->max_id = MVS_MAX_DEVICES;
470 shost->max_lun = ~0; 470 shost->max_lun = ~0;
471 shost->max_channel = 1; 471 shost->max_channel = 1;
472 shost->max_cmd_len = 16; 472 shost->max_cmd_len = 16;
@@ -512,6 +512,7 @@ static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
512 can_queue = MVS_CHIP_SLOT_SZ; 512 can_queue = MVS_CHIP_SLOT_SZ;
513 513
514 sha->lldd_queue_size = can_queue; 514 sha->lldd_queue_size = can_queue;
515 shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG);
515 shost->can_queue = can_queue; 516 shost->can_queue = can_queue;
516 mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE; 517 mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
517 sha->core.shost = mvi->shost; 518 sha->core.shost = mvi->shost;
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 7bd0ee3ed2d6..38b47918c047 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -203,12 +203,12 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
203 tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id); 203 tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id);
204 if (tmp & PHY_RST_HARD) 204 if (tmp & PHY_RST_HARD)
205 break; 205 break;
206 MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1); 206 MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_HARD_RESET);
207 break; 207 break;
208 208
209 case PHY_FUNC_LINK_RESET: 209 case PHY_FUNC_LINK_RESET:
210 MVS_CHIP_DISP->phy_enable(mvi, phy_id); 210 MVS_CHIP_DISP->phy_enable(mvi, phy_id);
211 MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0); 211 MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_SOFT_RESET);
212 break; 212 break;
213 213
214 case PHY_FUNC_DISABLE: 214 case PHY_FUNC_DISABLE:
@@ -1758,12 +1758,63 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
1758 return stat; 1758 return stat;
1759} 1759}
1760 1760
1761void mvs_set_sense(u8 *buffer, int len, int d_sense,
1762 int key, int asc, int ascq)
1763{
1764 memset(buffer, 0, len);
1765
1766 if (d_sense) {
1767 /* Descriptor format */
1768 if (len < 4) {
1769 mv_printk("Length %d of sense buffer too small to "
1770 "fit sense %x:%x:%x", len, key, asc, ascq);
1771 }
1772
1773 buffer[0] = 0x72; /* Response Code */
1774 if (len > 1)
1775 buffer[1] = key; /* Sense Key */
1776 if (len > 2)
1777 buffer[2] = asc; /* ASC */
1778 if (len > 3)
1779 buffer[3] = ascq; /* ASCQ */
1780 } else {
1781 if (len < 14) {
1782 mv_printk("Length %d of sense buffer too small to "
1783 "fit sense %x:%x:%x", len, key, asc, ascq);
1784 }
1785
1786 buffer[0] = 0x70; /* Response Code */
1787 if (len > 2)
1788 buffer[2] = key; /* Sense Key */
1789 if (len > 7)
1790 buffer[7] = 0x0a; /* Additional Sense Length */
1791 if (len > 12)
1792 buffer[12] = asc; /* ASC */
1793 if (len > 13)
1794 buffer[13] = ascq; /* ASCQ */
1795 }
1796
1797 return;
1798}
1799
1800void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu,
1801 u8 key, u8 asc, u8 asc_q)
1802{
1803 iu->datapres = 2;
1804 iu->response_data_len = 0;
1805 iu->sense_data_len = 17;
1806 iu->status = 02;
1807 mvs_set_sense(iu->sense_data, 17, 0,
1808 key, asc, asc_q);
1809}
1810
1761static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, 1811static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
1762 u32 slot_idx) 1812 u32 slot_idx)
1763{ 1813{
1764 struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; 1814 struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
1765 int stat; 1815 int stat;
1766 u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response)); 1816 u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
1817 u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response + 1));
1767 u32 tfs = 0; 1818 u32 tfs = 0;
1768 enum mvs_port_type type = PORT_TYPE_SAS; 1819 enum mvs_port_type type = PORT_TYPE_SAS;
1769 1820
@@ -1775,8 +1826,19 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
1775 stat = SAM_STAT_CHECK_CONDITION; 1826 stat = SAM_STAT_CHECK_CONDITION;
1776 switch (task->task_proto) { 1827 switch (task->task_proto) {
1777 case SAS_PROTOCOL_SSP: 1828 case SAS_PROTOCOL_SSP:
1829 {
1778 stat = SAS_ABORTED_TASK; 1830 stat = SAS_ABORTED_TASK;
1831 if ((err_dw0 & NO_DEST) || err_dw1 & bit(31)) {
1832 struct ssp_response_iu *iu = slot->response +
1833 sizeof(struct mvs_err_info);
1834 mvs_fill_ssp_resp_iu(iu, NOT_READY, 0x04, 01);
1835 sas_ssp_task_response(mvi->dev, task, iu);
1836 stat = SAM_STAT_CHECK_CONDITION;
1837 }
1838 if (err_dw1 & bit(31))
1839 mv_printk("reuse same slot, retry command.\n");
1779 break; 1840 break;
1841 }
1780 case SAS_PROTOCOL_SMP: 1842 case SAS_PROTOCOL_SMP:
1781 stat = SAM_STAT_CHECK_CONDITION; 1843 stat = SAM_STAT_CHECK_CONDITION;
1782 break; 1844 break;
@@ -1974,13 +2036,13 @@ static void mvs_work_queue(struct work_struct *work)
1974 struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q); 2036 struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);
1975 struct mvs_info *mvi = mwq->mvi; 2037 struct mvs_info *mvi = mwq->mvi;
1976 unsigned long flags; 2038 unsigned long flags;
2039 u32 phy_no = (unsigned long) mwq->data;
2040 struct sas_ha_struct *sas_ha = mvi->sas;
2041 struct mvs_phy *phy = &mvi->phy[phy_no];
2042 struct asd_sas_phy *sas_phy = &phy->sas_phy;
1977 2043
1978 spin_lock_irqsave(&mvi->lock, flags); 2044 spin_lock_irqsave(&mvi->lock, flags);
1979 if (mwq->handler & PHY_PLUG_EVENT) { 2045 if (mwq->handler & PHY_PLUG_EVENT) {
1980 u32 phy_no = (unsigned long) mwq->data;
1981 struct sas_ha_struct *sas_ha = mvi->sas;
1982 struct mvs_phy *phy = &mvi->phy[phy_no];
1983 struct asd_sas_phy *sas_phy = &phy->sas_phy;
1984 2046
1985 if (phy->phy_event & PHY_PLUG_OUT) { 2047 if (phy->phy_event & PHY_PLUG_OUT) {
1986 u32 tmp; 2048 u32 tmp;
@@ -2002,6 +2064,11 @@ static void mvs_work_queue(struct work_struct *work)
2002 mv_dprintk("phy%d Attached Device\n", phy_no); 2064 mv_dprintk("phy%d Attached Device\n", phy_no);
2003 } 2065 }
2004 } 2066 }
2067 } else if (mwq->handler & EXP_BRCT_CHG) {
2068 phy->phy_event &= ~EXP_BRCT_CHG;
2069 sas_ha->notify_port_event(sas_phy,
2070 PORTE_BROADCAST_RCVD);
2071 mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
2005 } 2072 }
2006 list_del(&mwq->entry); 2073 list_del(&mwq->entry);
2007 spin_unlock_irqrestore(&mvi->lock, flags); 2074 spin_unlock_irqrestore(&mvi->lock, flags);
@@ -2037,7 +2104,7 @@ static void mvs_sig_time_out(unsigned long tphy)
2037 if (&mvi->phy[phy_no] == phy) { 2104 if (&mvi->phy[phy_no] == phy) {
2038 mv_dprintk("Get signature time out, reset phy %d\n", 2105 mv_dprintk("Get signature time out, reset phy %d\n",
2039 phy_no+mvi->id*mvi->chip->n_phy); 2106 phy_no+mvi->id*mvi->chip->n_phy);
2040 MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1); 2107 MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_HARD_RESET);
2041 } 2108 }
2042 } 2109 }
2043} 2110}
@@ -2045,9 +2112,7 @@ static void mvs_sig_time_out(unsigned long tphy)
2045void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) 2112void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
2046{ 2113{
2047 u32 tmp; 2114 u32 tmp;
2048 struct sas_ha_struct *sas_ha = mvi->sas;
2049 struct mvs_phy *phy = &mvi->phy[phy_no]; 2115 struct mvs_phy *phy = &mvi->phy[phy_no];
2050 struct asd_sas_phy *sas_phy = &phy->sas_phy;
2051 2116
2052 phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no); 2117 phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no);
2053 mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy, 2118 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 phy_no); 2151 phy_no);
2087 else 2152 else
2088 MVS_CHIP_DISP->phy_reset(mvi, 2153 MVS_CHIP_DISP->phy_reset(mvi,
2089 phy_no, 0); 2154 phy_no, MVS_SOFT_RESET);
2090 return; 2155 return;
2091 } 2156 }
2092 } 2157 }
@@ -2118,14 +2183,14 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
2118 } 2183 }
2119 mvs_update_phyinfo(mvi, phy_no, 0); 2184 mvs_update_phyinfo(mvi, phy_no, 0);
2120 if (phy->phy_type & PORT_TYPE_SAS) { 2185 if (phy->phy_type & PORT_TYPE_SAS) {
2121 MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2); 2186 MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_PHY_TUNE);
2122 mdelay(10); 2187 mdelay(10);
2123 } 2188 }
2124 2189
2125 mvs_bytes_dmaed(mvi, phy_no); 2190 mvs_bytes_dmaed(mvi, phy_no);
2126 /* whether driver is going to handle hot plug */ 2191 /* whether driver is going to handle hot plug */
2127 if (phy->phy_event & PHY_PLUG_OUT) { 2192 if (phy->phy_event & PHY_PLUG_OUT) {
2128 mvs_port_notify_formed(sas_phy, 0); 2193 mvs_port_notify_formed(&phy->sas_phy, 0);
2129 phy->phy_event &= ~PHY_PLUG_OUT; 2194 phy->phy_event &= ~PHY_PLUG_OUT;
2130 } 2195 }
2131 } else { 2196 } else {
@@ -2135,9 +2200,8 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
2135 } else if (phy->irq_status & PHYEV_BROAD_CH) { 2200 } else if (phy->irq_status & PHYEV_BROAD_CH) {
2136 mv_dprintk("port %d broadcast change.\n", 2201 mv_dprintk("port %d broadcast change.\n",
2137 phy_no + mvi->id*mvi->chip->n_phy); 2202 phy_no + mvi->id*mvi->chip->n_phy);
2138 /* exception for Samsung disk drive*/ 2203 mvs_handle_event(mvi, (void *)(unsigned long)phy_no,
2139 mdelay(1000); 2204 EXP_BRCT_CHG);
2140 sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
2141 } 2205 }
2142 MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status); 2206 MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
2143} 2207}
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index 4f8caaf748f1..428b00a36482 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -96,6 +96,11 @@ enum dev_status {
96 MVS_DEV_EH = 0x1, 96 MVS_DEV_EH = 0x1,
97}; 97};
98 98
99enum dev_reset {
100 MVS_SOFT_RESET = 0,
101 MVS_HARD_RESET = 1,
102 MVS_PHY_TUNE = 2,
103};
99 104
100struct mvs_info; 105struct mvs_info;
101 106
@@ -176,9 +181,11 @@ struct mvs_chip_info {
176 u32 fis_offs; 181 u32 fis_offs;
177 u32 fis_count; 182 u32 fis_count;
178 u32 srs_sz; 183 u32 srs_sz;
184 u32 sg_width;
179 u32 slot_width; 185 u32 slot_width;
180 const struct mvs_dispatch *dispatch; 186 const struct mvs_dispatch *dispatch;
181}; 187};
188#define MVS_MAX_SG (1U << mvi->chip->sg_width)
182#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width) 189#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width)
183#define MVS_RX_FISL_SZ \ 190#define MVS_RX_FISL_SZ \
184 (mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100)) 191 (mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100))