diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 04:28:13 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 04:28:13 -0500 |
commit | 99b3738fbf17208ac474420fa6b7e4b0c0c2b9ed (patch) | |
tree | 6f977546112ccbd617ef40ae38a1ca558d71bce9 /drivers/scsi/sata_mv.c | |
parent | 332b5a52f2f96bc2d13bbe594a430318c0ee4425 (diff) | |
parent | 8a19ac89edbe9b702c10fd2039b8cb2db4644a5f (diff) |
Merge branch 'upstream'
Diffstat (limited to 'drivers/scsi/sata_mv.c')
-rw-r--r-- | drivers/scsi/sata_mv.c | 223 |
1 files changed, 210 insertions, 13 deletions
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 0042c7840d80..5b36a23455de 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <asm/io.h> | 37 | #include <asm/io.h> |
38 | 38 | ||
39 | #define DRV_NAME "sata_mv" | 39 | #define DRV_NAME "sata_mv" |
40 | #define DRV_VERSION "0.5" | 40 | #define DRV_VERSION "0.6" |
41 | 41 | ||
42 | enum { | 42 | enum { |
43 | /* BAR's are enumerated in terms of pci_resource_start() terms */ | 43 | /* BAR's are enumerated in terms of pci_resource_start() terms */ |
@@ -228,7 +228,9 @@ enum { | |||
228 | MV_HP_ERRATA_50XXB2 = (1 << 2), | 228 | MV_HP_ERRATA_50XXB2 = (1 << 2), |
229 | MV_HP_ERRATA_60X1B2 = (1 << 3), | 229 | MV_HP_ERRATA_60X1B2 = (1 << 3), |
230 | MV_HP_ERRATA_60X1C0 = (1 << 4), | 230 | MV_HP_ERRATA_60X1C0 = (1 << 4), |
231 | MV_HP_50XX = (1 << 5), | 231 | MV_HP_ERRATA_XX42A0 = (1 << 5), |
232 | MV_HP_50XX = (1 << 6), | ||
233 | MV_HP_GEN_IIE = (1 << 7), | ||
232 | 234 | ||
233 | /* Port private flags (pp_flags) */ | 235 | /* Port private flags (pp_flags) */ |
234 | MV_PP_FLAG_EDMA_EN = (1 << 0), | 236 | MV_PP_FLAG_EDMA_EN = (1 << 0), |
@@ -237,6 +239,9 @@ enum { | |||
237 | 239 | ||
238 | #define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX) | 240 | #define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX) |
239 | #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) | 241 | #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) |
242 | #define IS_GEN_I(hpriv) IS_50XX(hpriv) | ||
243 | #define IS_GEN_II(hpriv) IS_60XX(hpriv) | ||
244 | #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) | ||
240 | 245 | ||
241 | enum { | 246 | enum { |
242 | /* Our DMA boundary is determined by an ePRD being unable to handle | 247 | /* Our DMA boundary is determined by an ePRD being unable to handle |
@@ -255,6 +260,8 @@ enum chip_type { | |||
255 | chip_5080, | 260 | chip_5080, |
256 | chip_604x, | 261 | chip_604x, |
257 | chip_608x, | 262 | chip_608x, |
263 | chip_6042, | ||
264 | chip_7042, | ||
258 | }; | 265 | }; |
259 | 266 | ||
260 | /* Command ReQuest Block: 32B */ | 267 | /* Command ReQuest Block: 32B */ |
@@ -265,6 +272,14 @@ struct mv_crqb { | |||
265 | u16 ata_cmd[11]; | 272 | u16 ata_cmd[11]; |
266 | }; | 273 | }; |
267 | 274 | ||
275 | struct mv_crqb_iie { | ||
276 | u32 addr; | ||
277 | u32 addr_hi; | ||
278 | u32 flags; | ||
279 | u32 len; | ||
280 | u32 ata_cmd[4]; | ||
281 | }; | ||
282 | |||
268 | /* Command ResPonse Block: 8B */ | 283 | /* Command ResPonse Block: 8B */ |
269 | struct mv_crpb { | 284 | struct mv_crpb { |
270 | u16 id; | 285 | u16 id; |
@@ -328,6 +343,7 @@ static void mv_host_stop(struct ata_host_set *host_set); | |||
328 | static int mv_port_start(struct ata_port *ap); | 343 | static int mv_port_start(struct ata_port *ap); |
329 | static void mv_port_stop(struct ata_port *ap); | 344 | static void mv_port_stop(struct ata_port *ap); |
330 | static void mv_qc_prep(struct ata_queued_cmd *qc); | 345 | static void mv_qc_prep(struct ata_queued_cmd *qc); |
346 | static void mv_qc_prep_iie(struct ata_queued_cmd *qc); | ||
331 | static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); | 347 | static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); |
332 | static irqreturn_t mv_interrupt(int irq, void *dev_instance, | 348 | static irqreturn_t mv_interrupt(int irq, void *dev_instance, |
333 | struct pt_regs *regs); | 349 | struct pt_regs *regs); |
@@ -430,6 +446,33 @@ static const struct ata_port_operations mv6_ops = { | |||
430 | .host_stop = mv_host_stop, | 446 | .host_stop = mv_host_stop, |
431 | }; | 447 | }; |
432 | 448 | ||
449 | static const struct ata_port_operations mv_iie_ops = { | ||
450 | .port_disable = ata_port_disable, | ||
451 | |||
452 | .tf_load = ata_tf_load, | ||
453 | .tf_read = ata_tf_read, | ||
454 | .check_status = ata_check_status, | ||
455 | .exec_command = ata_exec_command, | ||
456 | .dev_select = ata_std_dev_select, | ||
457 | |||
458 | .phy_reset = mv_phy_reset, | ||
459 | |||
460 | .qc_prep = mv_qc_prep_iie, | ||
461 | .qc_issue = mv_qc_issue, | ||
462 | |||
463 | .eng_timeout = mv_eng_timeout, | ||
464 | |||
465 | .irq_handler = mv_interrupt, | ||
466 | .irq_clear = mv_irq_clear, | ||
467 | |||
468 | .scr_read = mv_scr_read, | ||
469 | .scr_write = mv_scr_write, | ||
470 | |||
471 | .port_start = mv_port_start, | ||
472 | .port_stop = mv_port_stop, | ||
473 | .host_stop = mv_host_stop, | ||
474 | }; | ||
475 | |||
433 | static const struct ata_port_info mv_port_info[] = { | 476 | static const struct ata_port_info mv_port_info[] = { |
434 | { /* chip_504x */ | 477 | { /* chip_504x */ |
435 | .sht = &mv_sht, | 478 | .sht = &mv_sht, |
@@ -467,6 +510,21 @@ static const struct ata_port_info mv_port_info[] = { | |||
467 | .udma_mask = 0x7f, /* udma0-6 */ | 510 | .udma_mask = 0x7f, /* udma0-6 */ |
468 | .port_ops = &mv6_ops, | 511 | .port_ops = &mv6_ops, |
469 | }, | 512 | }, |
513 | { /* chip_6042 */ | ||
514 | .sht = &mv_sht, | ||
515 | .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), | ||
516 | .pio_mask = 0x1f, /* pio0-4 */ | ||
517 | .udma_mask = 0x7f, /* udma0-6 */ | ||
518 | .port_ops = &mv_iie_ops, | ||
519 | }, | ||
520 | { /* chip_7042 */ | ||
521 | .sht = &mv_sht, | ||
522 | .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS | | ||
523 | MV_FLAG_DUAL_HC), | ||
524 | .pio_mask = 0x1f, /* pio0-4 */ | ||
525 | .udma_mask = 0x7f, /* udma0-6 */ | ||
526 | .port_ops = &mv_iie_ops, | ||
527 | }, | ||
470 | }; | 528 | }; |
471 | 529 | ||
472 | static const struct pci_device_id mv_pci_tbl[] = { | 530 | static const struct pci_device_id mv_pci_tbl[] = { |
@@ -477,6 +535,7 @@ static const struct pci_device_id mv_pci_tbl[] = { | |||
477 | 535 | ||
478 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, | 536 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, |
479 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x}, | 537 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x}, |
538 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6042), 0, 0, chip_6042}, | ||
480 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x}, | 539 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x}, |
481 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x}, | 540 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x}, |
482 | 541 | ||
@@ -510,6 +569,12 @@ static const struct mv_hw_ops mv6xxx_ops = { | |||
510 | }; | 569 | }; |
511 | 570 | ||
512 | /* | 571 | /* |
572 | * module options | ||
573 | */ | ||
574 | static int msi; /* Use PCI msi; either zero (off, default) or non-zero */ | ||
575 | |||
576 | |||
577 | /* | ||
513 | * Functions | 578 | * Functions |
514 | */ | 579 | */ |
515 | 580 | ||
@@ -767,6 +832,33 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) | |||
767 | dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); | 832 | dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); |
768 | } | 833 | } |
769 | 834 | ||
835 | static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio) | ||
836 | { | ||
837 | u32 cfg = readl(port_mmio + EDMA_CFG_OFS); | ||
838 | |||
839 | /* set up non-NCQ EDMA configuration */ | ||
840 | cfg &= ~0x1f; /* clear queue depth */ | ||
841 | cfg &= ~EDMA_CFG_NCQ; /* clear NCQ mode */ | ||
842 | cfg &= ~(1 << 9); /* disable equeue */ | ||
843 | |||
844 | if (IS_GEN_I(hpriv)) | ||
845 | cfg |= (1 << 8); /* enab config burst size mask */ | ||
846 | |||
847 | else if (IS_GEN_II(hpriv)) | ||
848 | cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN; | ||
849 | |||
850 | else if (IS_GEN_IIE(hpriv)) { | ||
851 | cfg |= (1 << 23); /* dis RX PM port mask */ | ||
852 | cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */ | ||
853 | cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */ | ||
854 | cfg |= (1 << 18); /* enab early completion */ | ||
855 | cfg |= (1 << 17); /* enab host q cache */ | ||
856 | cfg |= (1 << 22); /* enab cutthrough */ | ||
857 | } | ||
858 | |||
859 | writelfl(cfg, port_mmio + EDMA_CFG_OFS); | ||
860 | } | ||
861 | |||
770 | /** | 862 | /** |
771 | * mv_port_start - Port specific init/start routine. | 863 | * mv_port_start - Port specific init/start routine. |
772 | * @ap: ATA channel to manipulate | 864 | * @ap: ATA channel to manipulate |
@@ -780,6 +872,7 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) | |||
780 | static int mv_port_start(struct ata_port *ap) | 872 | static int mv_port_start(struct ata_port *ap) |
781 | { | 873 | { |
782 | struct device *dev = ap->host_set->dev; | 874 | struct device *dev = ap->host_set->dev; |
875 | struct mv_host_priv *hpriv = ap->host_set->private_data; | ||
783 | struct mv_port_priv *pp; | 876 | struct mv_port_priv *pp; |
784 | void __iomem *port_mmio = mv_ap_base(ap); | 877 | void __iomem *port_mmio = mv_ap_base(ap); |
785 | void *mem; | 878 | void *mem; |
@@ -823,17 +916,26 @@ static int mv_port_start(struct ata_port *ap) | |||
823 | pp->sg_tbl = mem; | 916 | pp->sg_tbl = mem; |
824 | pp->sg_tbl_dma = mem_dma; | 917 | pp->sg_tbl_dma = mem_dma; |
825 | 918 | ||
826 | writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT | | 919 | mv_edma_cfg(hpriv, port_mmio); |
827 | EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS); | ||
828 | 920 | ||
829 | writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); | 921 | writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); |
830 | writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, | 922 | writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, |
831 | port_mmio + EDMA_REQ_Q_IN_PTR_OFS); | 923 | port_mmio + EDMA_REQ_Q_IN_PTR_OFS); |
832 | 924 | ||
833 | writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); | 925 | if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) |
834 | writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); | 926 | writelfl(pp->crqb_dma & 0xffffffff, |
927 | port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); | ||
928 | else | ||
929 | writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); | ||
835 | 930 | ||
836 | writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); | 931 | writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); |
932 | |||
933 | if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) | ||
934 | writelfl(pp->crpb_dma & 0xffffffff, | ||
935 | port_mmio + EDMA_RSP_Q_IN_PTR_OFS); | ||
936 | else | ||
937 | writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); | ||
938 | |||
837 | writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, | 939 | writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, |
838 | port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); | 940 | port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); |
839 | 941 | ||
@@ -954,9 +1056,8 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) | |||
954 | struct ata_taskfile *tf; | 1056 | struct ata_taskfile *tf; |
955 | u16 flags = 0; | 1057 | u16 flags = 0; |
956 | 1058 | ||
957 | if (ATA_PROT_DMA != qc->tf.protocol) { | 1059 | if (ATA_PROT_DMA != qc->tf.protocol) |
958 | return; | 1060 | return; |
959 | } | ||
960 | 1061 | ||
961 | /* the req producer index should be the same as we remember it */ | 1062 | /* the req producer index should be the same as we remember it */ |
962 | assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> | 1063 | assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> |
@@ -965,9 +1066,8 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) | |||
965 | 1066 | ||
966 | /* Fill in command request block | 1067 | /* Fill in command request block |
967 | */ | 1068 | */ |
968 | if (!(qc->tf.flags & ATA_TFLAG_WRITE)) { | 1069 | if (!(qc->tf.flags & ATA_TFLAG_WRITE)) |
969 | flags |= CRQB_FLAG_READ; | 1070 | flags |= CRQB_FLAG_READ; |
970 | } | ||
971 | assert(MV_MAX_Q_DEPTH > qc->tag); | 1071 | assert(MV_MAX_Q_DEPTH > qc->tag); |
972 | flags |= qc->tag << CRQB_TAG_SHIFT; | 1072 | flags |= qc->tag << CRQB_TAG_SHIFT; |
973 | 1073 | ||
@@ -1022,9 +1122,76 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) | |||
1022 | mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0); | 1122 | mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0); |
1023 | mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */ | 1123 | mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */ |
1024 | 1124 | ||
1025 | if (!(qc->flags & ATA_QCFLAG_DMAMAP)) { | 1125 | if (!(qc->flags & ATA_QCFLAG_DMAMAP)) |
1126 | return; | ||
1127 | mv_fill_sg(qc); | ||
1128 | } | ||
1129 | |||
1130 | /** | ||
1131 | * mv_qc_prep_iie - Host specific command preparation. | ||
1132 | * @qc: queued command to prepare | ||
1133 | * | ||
1134 | * This routine simply redirects to the general purpose routine | ||
1135 | * if command is not DMA. Else, it handles prep of the CRQB | ||
1136 | * (command request block), does some sanity checking, and calls | ||
1137 | * the SG load routine. | ||
1138 | * | ||
1139 | * LOCKING: | ||
1140 | * Inherited from caller. | ||
1141 | */ | ||
1142 | static void mv_qc_prep_iie(struct ata_queued_cmd *qc) | ||
1143 | { | ||
1144 | struct ata_port *ap = qc->ap; | ||
1145 | struct mv_port_priv *pp = ap->private_data; | ||
1146 | struct mv_crqb_iie *crqb; | ||
1147 | struct ata_taskfile *tf; | ||
1148 | u32 flags = 0; | ||
1149 | |||
1150 | if (ATA_PROT_DMA != qc->tf.protocol) | ||
1151 | return; | ||
1152 | |||
1153 | /* the req producer index should be the same as we remember it */ | ||
1154 | assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> | ||
1155 | EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == | ||
1156 | pp->req_producer); | ||
1157 | |||
1158 | /* Fill in Gen IIE command request block | ||
1159 | */ | ||
1160 | if (!(qc->tf.flags & ATA_TFLAG_WRITE)) | ||
1161 | flags |= CRQB_FLAG_READ; | ||
1162 | |||
1163 | assert(MV_MAX_Q_DEPTH > qc->tag); | ||
1164 | flags |= qc->tag << CRQB_TAG_SHIFT; | ||
1165 | |||
1166 | crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer]; | ||
1167 | crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); | ||
1168 | crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); | ||
1169 | crqb->flags = cpu_to_le32(flags); | ||
1170 | |||
1171 | tf = &qc->tf; | ||
1172 | crqb->ata_cmd[0] = cpu_to_le32( | ||
1173 | (tf->command << 16) | | ||
1174 | (tf->feature << 24) | ||
1175 | ); | ||
1176 | crqb->ata_cmd[1] = cpu_to_le32( | ||
1177 | (tf->lbal << 0) | | ||
1178 | (tf->lbam << 8) | | ||
1179 | (tf->lbah << 16) | | ||
1180 | (tf->device << 24) | ||
1181 | ); | ||
1182 | crqb->ata_cmd[2] = cpu_to_le32( | ||
1183 | (tf->hob_lbal << 0) | | ||
1184 | (tf->hob_lbam << 8) | | ||
1185 | (tf->hob_lbah << 16) | | ||
1186 | (tf->hob_feature << 24) | ||
1187 | ); | ||
1188 | crqb->ata_cmd[3] = cpu_to_le32( | ||
1189 | (tf->nsect << 0) | | ||
1190 | (tf->hob_nsect << 8) | ||
1191 | ); | ||
1192 | |||
1193 | if (!(qc->flags & ATA_QCFLAG_DMAMAP)) | ||
1026 | return; | 1194 | return; |
1027 | } | ||
1028 | mv_fill_sg(qc); | 1195 | mv_fill_sg(qc); |
1029 | } | 1196 | } |
1030 | 1197 | ||
@@ -1673,6 +1840,12 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | |||
1673 | m2 |= hpriv->signal[port].pre; | 1840 | m2 |= hpriv->signal[port].pre; |
1674 | m2 &= ~(1 << 16); | 1841 | m2 &= ~(1 << 16); |
1675 | 1842 | ||
1843 | /* according to mvSata 3.6.1, some IIE values are fixed */ | ||
1844 | if (IS_GEN_IIE(hpriv)) { | ||
1845 | m2 &= ~0xC30FF01F; | ||
1846 | m2 |= 0x0000900F; | ||
1847 | } | ||
1848 | |||
1676 | writel(m2, port_mmio + PHY_MODE2); | 1849 | writel(m2, port_mmio + PHY_MODE2); |
1677 | } | 1850 | } |
1678 | 1851 | ||
@@ -1977,6 +2150,27 @@ static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv, | |||
1977 | } | 2150 | } |
1978 | break; | 2151 | break; |
1979 | 2152 | ||
2153 | case chip_7042: | ||
2154 | case chip_6042: | ||
2155 | hpriv->ops = &mv6xxx_ops; | ||
2156 | |||
2157 | hp_flags |= MV_HP_GEN_IIE; | ||
2158 | |||
2159 | switch (rev_id) { | ||
2160 | case 0x0: | ||
2161 | hp_flags |= MV_HP_ERRATA_XX42A0; | ||
2162 | break; | ||
2163 | case 0x1: | ||
2164 | hp_flags |= MV_HP_ERRATA_60X1C0; | ||
2165 | break; | ||
2166 | default: | ||
2167 | dev_printk(KERN_WARNING, &pdev->dev, | ||
2168 | "Applying 60X1C0 workarounds to unknown rev\n"); | ||
2169 | hp_flags |= MV_HP_ERRATA_60X1C0; | ||
2170 | break; | ||
2171 | } | ||
2172 | break; | ||
2173 | |||
1980 | default: | 2174 | default: |
1981 | printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); | 2175 | printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); |
1982 | return 1; | 2176 | return 1; |
@@ -2180,7 +2374,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2180 | } | 2374 | } |
2181 | 2375 | ||
2182 | /* Enable interrupts */ | 2376 | /* Enable interrupts */ |
2183 | if (pci_enable_msi(pdev) == 0) { | 2377 | if (msi && pci_enable_msi(pdev) == 0) { |
2184 | hpriv->hp_flags |= MV_HP_FLAG_MSI; | 2378 | hpriv->hp_flags |= MV_HP_FLAG_MSI; |
2185 | } else { | 2379 | } else { |
2186 | pci_intx(pdev, 1); | 2380 | pci_intx(pdev, 1); |
@@ -2235,5 +2429,8 @@ MODULE_LICENSE("GPL"); | |||
2235 | MODULE_DEVICE_TABLE(pci, mv_pci_tbl); | 2429 | MODULE_DEVICE_TABLE(pci, mv_pci_tbl); |
2236 | MODULE_VERSION(DRV_VERSION); | 2430 | MODULE_VERSION(DRV_VERSION); |
2237 | 2431 | ||
2432 | module_param(msi, int, 0444); | ||
2433 | MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); | ||
2434 | |||
2238 | module_init(mv_init); | 2435 | module_init(mv_init); |
2239 | module_exit(mv_exit); | 2436 | module_exit(mv_exit); |