aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-09-02 23:44:57 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:39 -0400
commit7a234aff3d83728fd83cf19df32d3df52566d2ac (patch)
treed991844bf7a7882eacd72a57a1465b25dc55e95d
parent05027adccc09401a7e31d5ef51040dc75ab03c22 (diff)
ahci: reimplement port_map handling
Reimplement port_map handling such that 1. Non-zero PORTS_IMPL value is always examined and used if consistent with cap.n_ports. 2. When PI and cat.n_ports are inconsistent, honor cap.n_ports and force port_map to be ((1 << cap.n_ports) - 1). 3. There were two separate places dealing with port_map. Unify them to one. As all newer ahci chips seem to get PI correct and older ones usually have zero PI. Controllers with holes in PI are very unlikely to screw up PI, so #2 makes more sense than following inconsistent PI. Without this change, not setting ATA_FLAG_HONOR_PI when it's needed results in weird detection failure. This changed logic should be able to handle all known cases correctly automatically. Verified on ICH6 (reports 0 PI), ICH8 (with holes in port_map), ICH9, JMB360 and JMB363. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/ahci.c89
1 files changed, 39 insertions, 50 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 518c51830357..57cc3e73a7e2 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -77,11 +77,10 @@ enum {
77 RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ 77 RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
78 78
79 board_ahci = 0, 79 board_ahci = 0,
80 board_ahci_pi = 1, 80 board_ahci_vt8251 = 1,
81 board_ahci_vt8251 = 2, 81 board_ahci_ign_iferr = 2,
82 board_ahci_ign_iferr = 3, 82 board_ahci_sb600 = 3,
83 board_ahci_sb600 = 4, 83 board_ahci_mv = 4,
84 board_ahci_mv = 5,
85 84
86 /* global controller registers */ 85 /* global controller registers */
87 HOST_CAP = 0x00, /* host capabilities */ 86 HOST_CAP = 0x00, /* host capabilities */
@@ -170,7 +169,6 @@ enum {
170 /* ap->flags bits */ 169 /* ap->flags bits */
171 AHCI_FLAG_NO_NCQ = (1 << 24), 170 AHCI_FLAG_NO_NCQ = (1 << 24),
172 AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ 171 AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */
173 AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
174 AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */ 172 AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
175 AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */ 173 AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
176 AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */ 174 AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */
@@ -332,14 +330,6 @@ static const struct ata_port_info ahci_port_info[] = {
332 .udma_mask = ATA_UDMA6, 330 .udma_mask = ATA_UDMA6,
333 .port_ops = &ahci_ops, 331 .port_ops = &ahci_ops,
334 }, 332 },
335 /* board_ahci_pi */
336 {
337 .flags = AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
338 .link_flags = AHCI_LFLAG_COMMON,
339 .pio_mask = 0x1f, /* pio0-4 */
340 .udma_mask = ATA_UDMA6,
341 .port_ops = &ahci_ops,
342 },
343 /* board_ahci_vt8251 */ 333 /* board_ahci_vt8251 */
344 { 334 {
345 .flags = AHCI_FLAG_COMMON | AHCI_FLAG_NO_NCQ, 335 .flags = AHCI_FLAG_COMMON | AHCI_FLAG_NO_NCQ,
@@ -371,8 +361,8 @@ static const struct ata_port_info ahci_port_info[] = {
371 .sht = &ahci_sht, 361 .sht = &ahci_sht,
372 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 362 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
373 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | 363 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
374 AHCI_FLAG_HONOR_PI | AHCI_FLAG_NO_NCQ | 364 AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI |
375 AHCI_FLAG_NO_MSI | AHCI_FLAG_MV_PATA, 365 AHCI_FLAG_MV_PATA,
376 .link_flags = AHCI_LFLAG_COMMON, 366 .link_flags = AHCI_LFLAG_COMMON,
377 .pio_mask = 0x1f, /* pio0-4 */ 367 .pio_mask = 0x1f, /* pio0-4 */
378 .udma_mask = ATA_UDMA6, 368 .udma_mask = ATA_UDMA6,
@@ -392,23 +382,23 @@ static const struct pci_device_id ahci_pci_tbl[] = {
392 { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 382 { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
393 { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 383 { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
394 { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 384 { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
395 { PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */ 385 { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
396 { PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */ 386 { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
397 { PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */ 387 { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
398 { PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */ 388 { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
399 { PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */ 389 { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
400 { PCI_VDEVICE(INTEL, 0x2922), board_ahci_pi }, /* ICH9 */ 390 { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
401 { PCI_VDEVICE(INTEL, 0x2923), board_ahci_pi }, /* ICH9 */ 391 { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
402 { PCI_VDEVICE(INTEL, 0x2924), board_ahci_pi }, /* ICH9 */ 392 { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
403 { PCI_VDEVICE(INTEL, 0x2925), board_ahci_pi }, /* ICH9 */ 393 { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
404 { PCI_VDEVICE(INTEL, 0x2927), board_ahci_pi }, /* ICH9 */ 394 { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
405 { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */ 395 { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
406 { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */ 396 { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
407 { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */ 397 { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
408 { PCI_VDEVICE(INTEL, 0x292c), board_ahci_pi }, /* ICH9M */ 398 { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
409 { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */ 399 { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
410 { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */ 400 { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
411 { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */ 401 { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
412 402
413 /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 403 /* JMicron 360/1/3/5/6, match class to avoid IDE function */
414 { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 404 { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -562,16 +552,6 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
562 cap &= ~HOST_CAP_NCQ; 552 cap &= ~HOST_CAP_NCQ;
563 } 553 }
564 554
565 /* fixup zero port_map */
566 if (!port_map) {
567 port_map = (1 << ahci_nr_ports(cap)) - 1;
568 dev_printk(KERN_WARNING, &pdev->dev,
569 "PORTS_IMPL is zero, forcing 0x%x\n", port_map);
570
571 /* write the fixed up value to the PI register */
572 hpriv->saved_port_map = port_map;
573 }
574
575 /* 555 /*
576 * Temporary Marvell 6145 hack: PATA port presence 556 * Temporary Marvell 6145 hack: PATA port presence
577 * is asserted through the standard AHCI port 557 * is asserted through the standard AHCI port
@@ -587,7 +567,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
587 } 567 }
588 568
589 /* cross check port_map and cap.n_ports */ 569 /* cross check port_map and cap.n_ports */
590 if (pi->flags & AHCI_FLAG_HONOR_PI) { 570 if (port_map) {
591 u32 tmp_port_map = port_map; 571 u32 tmp_port_map = port_map;
592 int n_ports = ahci_nr_ports(cap); 572 int n_ports = ahci_nr_ports(cap);
593 573
@@ -598,17 +578,26 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
598 } 578 }
599 } 579 }
600 580
601 /* Whine if inconsistent. No need to update cap. 581 /* If n_ports and port_map are inconsistent, whine and
602 * port_map is used to determine number of ports. 582 * clear port_map and let it be generated from n_ports.
603 */ 583 */
604 if (n_ports || tmp_port_map) 584 if (n_ports || tmp_port_map) {
605 dev_printk(KERN_WARNING, &pdev->dev, 585 dev_printk(KERN_WARNING, &pdev->dev,
606 "nr_ports (%u) and implemented port map " 586 "nr_ports (%u) and implemented port map "
607 "(0x%x) don't match\n", 587 "(0x%x) don't match, using nr_ports\n",
608 ahci_nr_ports(cap), port_map); 588 ahci_nr_ports(cap), port_map);
609 } else { 589 port_map = 0;
610 /* fabricate port_map from cap.nr_ports */ 590 }
591 }
592
593 /* fabricate port_map from cap.nr_ports */
594 if (!port_map) {
611 port_map = (1 << ahci_nr_ports(cap)) - 1; 595 port_map = (1 << ahci_nr_ports(cap)) - 1;
596 dev_printk(KERN_WARNING, &pdev->dev,
597 "forcing PORTS_IMPL to 0x%x\n", port_map);
598
599 /* write the fixed up value to the PI register */
600 hpriv->saved_port_map = port_map;
612 } 601 }
613 602
614 /* record values to use during operation */ 603 /* record values to use during operation */