diff options
author | Xiangliang Yu <yuxiangl@marvell.com> | 2011-05-24 10:36:02 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-26 02:36:11 -0400 |
commit | a4632aae8b662b1f32fe3fc558a813cd5c3daae6 (patch) | |
tree | a88ee045018877314d76b9cb99e3e837b78d5565 /drivers/scsi/mvsas | |
parent | b89e8f539ff8bcf2a1464578fa91cb96cc433fc3 (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.c | 18 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_94xx.c | 80 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_94xx.h | 2 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_defs.h | 3 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_init.c | 21 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.c | 94 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.h | 7 |
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, ®); | 99 | pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, ®); |
100 | else | 100 | else |
101 | pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, ®); | 101 | 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) | |||
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 | ||
667 | static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi) | 667 | static 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) | |||
585 | static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx) | 585 | static 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 | |||
600 | void 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 | ||
594 | static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type, | 632 | 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 | { | 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, | |||
794 | void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, | 830 | void 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 | ||
800 | static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi) | 847 | 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 | } | 940 | } |
894 | } | 941 | } |
895 | 942 | ||
896 | /* | ||
897 | * FIXME JEJB: temporary nop clear_srs_irq to make 94xx still work | ||
898 | * with 64xx fixes | ||
899 | */ | ||
900 | static void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, | ||
901 | u8 clear_all) | ||
902 | { | ||
903 | } | ||
904 | |||
905 | static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time) | 943 | static 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 | ||
114 | enum pci_cfg_registers { | 115 | enum 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 | ||
397 | enum mvs_event_flags { | 397 | enum 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 | ||
403 | enum mvs_port_type { | 404 | enum 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; | |||
39 | static struct scsi_transport_template *mvs_stt; | 39 | static struct scsi_transport_template *mvs_stt; |
40 | struct kmem_cache *mvs_task_list_cache; | 40 | struct kmem_cache *mvs_task_list_cache; |
41 | static const struct mvs_chip_info mvs_chips[] = { | 41 | static 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 | ||
53 | struct device_attribute *mvst_host_attrs[]; | 53 | struct 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 | ||
1761 | void 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 | |||
1800 | void 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 | |||
1761 | static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, | 1811 | static 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) | |||
2045 | void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) | 2112 | void 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 | ||
99 | enum dev_reset { | ||
100 | MVS_SOFT_RESET = 0, | ||
101 | MVS_HARD_RESET = 1, | ||
102 | MVS_PHY_TUNE = 2, | ||
103 | }; | ||
99 | 104 | ||
100 | struct mvs_info; | 105 | struct 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)) |