diff options
Diffstat (limited to 'drivers/ata/sata_sil24.c')
-rw-r--r-- | drivers/ata/sata_sil24.c | 341 |
1 files changed, 277 insertions, 64 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 233e88693395..b0619278454a 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/libata.h> | 30 | #include <linux/libata.h> |
31 | 31 | ||
32 | #define DRV_NAME "sata_sil24" | 32 | #define DRV_NAME "sata_sil24" |
33 | #define DRV_VERSION "1.0" | 33 | #define DRV_VERSION "1.1" |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Port request block (PRB) 32 bytes | 36 | * Port request block (PRB) 32 bytes |
@@ -168,7 +168,7 @@ enum { | |||
168 | 168 | ||
169 | DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | | 169 | DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | |
170 | PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG | | 170 | PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG | |
171 | PORT_IRQ_UNK_FIS, | 171 | PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_NOTIFY, |
172 | 172 | ||
173 | /* bits[27:16] are unmasked (raw) */ | 173 | /* bits[27:16] are unmasked (raw) */ |
174 | PORT_IRQ_RAW_SHIFT = 16, | 174 | PORT_IRQ_RAW_SHIFT = 16, |
@@ -237,8 +237,9 @@ enum { | |||
237 | /* host flags */ | 237 | /* host flags */ |
238 | SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 238 | SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
239 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | 239 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | |
240 | ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY | | 240 | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | |
241 | ATA_FLAG_ACPI_SATA, | 241 | ATA_FLAG_AN | ATA_FLAG_PMP, |
242 | SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY, | ||
242 | SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ | 243 | SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ |
243 | 244 | ||
244 | IRQ_STAT_4PORTS = 0xf, | 245 | IRQ_STAT_4PORTS = 0xf, |
@@ -322,6 +323,7 @@ struct sil24_port_priv { | |||
322 | union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ | 323 | union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ |
323 | dma_addr_t cmd_block_dma; /* DMA base addr for them */ | 324 | dma_addr_t cmd_block_dma; /* DMA base addr for them */ |
324 | struct ata_taskfile tf; /* Cached taskfile registers */ | 325 | struct ata_taskfile tf; /* Cached taskfile registers */ |
326 | int do_port_rst; | ||
325 | }; | 327 | }; |
326 | 328 | ||
327 | static void sil24_dev_config(struct ata_device *dev); | 329 | static void sil24_dev_config(struct ata_device *dev); |
@@ -329,9 +331,12 @@ static u8 sil24_check_status(struct ata_port *ap); | |||
329 | static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); | 331 | static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); |
330 | static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); | 332 | static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); |
331 | static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); | 333 | static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); |
334 | static int sil24_qc_defer(struct ata_queued_cmd *qc); | ||
332 | static void sil24_qc_prep(struct ata_queued_cmd *qc); | 335 | static void sil24_qc_prep(struct ata_queued_cmd *qc); |
333 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); | 336 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); |
334 | static void sil24_irq_clear(struct ata_port *ap); | 337 | static void sil24_irq_clear(struct ata_port *ap); |
338 | static void sil24_pmp_attach(struct ata_port *ap); | ||
339 | static void sil24_pmp_detach(struct ata_port *ap); | ||
335 | static void sil24_freeze(struct ata_port *ap); | 340 | static void sil24_freeze(struct ata_port *ap); |
336 | static void sil24_thaw(struct ata_port *ap); | 341 | static void sil24_thaw(struct ata_port *ap); |
337 | static void sil24_error_handler(struct ata_port *ap); | 342 | static void sil24_error_handler(struct ata_port *ap); |
@@ -340,6 +345,7 @@ static int sil24_port_start(struct ata_port *ap); | |||
340 | static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 345 | static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
341 | #ifdef CONFIG_PM | 346 | #ifdef CONFIG_PM |
342 | static int sil24_pci_device_resume(struct pci_dev *pdev); | 347 | static int sil24_pci_device_resume(struct pci_dev *pdev); |
348 | static int sil24_port_resume(struct ata_port *ap); | ||
343 | #endif | 349 | #endif |
344 | 350 | ||
345 | static const struct pci_device_id sil24_pci_tbl[] = { | 351 | static const struct pci_device_id sil24_pci_tbl[] = { |
@@ -384,8 +390,6 @@ static struct scsi_host_template sil24_sht = { | |||
384 | }; | 390 | }; |
385 | 391 | ||
386 | static const struct ata_port_operations sil24_ops = { | 392 | static const struct ata_port_operations sil24_ops = { |
387 | .port_disable = ata_port_disable, | ||
388 | |||
389 | .dev_config = sil24_dev_config, | 393 | .dev_config = sil24_dev_config, |
390 | 394 | ||
391 | .check_status = sil24_check_status, | 395 | .check_status = sil24_check_status, |
@@ -394,22 +398,28 @@ static const struct ata_port_operations sil24_ops = { | |||
394 | 398 | ||
395 | .tf_read = sil24_tf_read, | 399 | .tf_read = sil24_tf_read, |
396 | 400 | ||
401 | .qc_defer = sil24_qc_defer, | ||
397 | .qc_prep = sil24_qc_prep, | 402 | .qc_prep = sil24_qc_prep, |
398 | .qc_issue = sil24_qc_issue, | 403 | .qc_issue = sil24_qc_issue, |
399 | 404 | ||
400 | .irq_clear = sil24_irq_clear, | 405 | .irq_clear = sil24_irq_clear, |
401 | .irq_on = ata_dummy_irq_on, | ||
402 | .irq_ack = ata_dummy_irq_ack, | ||
403 | 406 | ||
404 | .scr_read = sil24_scr_read, | 407 | .scr_read = sil24_scr_read, |
405 | .scr_write = sil24_scr_write, | 408 | .scr_write = sil24_scr_write, |
406 | 409 | ||
410 | .pmp_attach = sil24_pmp_attach, | ||
411 | .pmp_detach = sil24_pmp_detach, | ||
412 | |||
407 | .freeze = sil24_freeze, | 413 | .freeze = sil24_freeze, |
408 | .thaw = sil24_thaw, | 414 | .thaw = sil24_thaw, |
409 | .error_handler = sil24_error_handler, | 415 | .error_handler = sil24_error_handler, |
410 | .post_internal_cmd = sil24_post_internal_cmd, | 416 | .post_internal_cmd = sil24_post_internal_cmd, |
411 | 417 | ||
412 | .port_start = sil24_port_start, | 418 | .port_start = sil24_port_start, |
419 | |||
420 | #ifdef CONFIG_PM | ||
421 | .port_resume = sil24_port_resume, | ||
422 | #endif | ||
413 | }; | 423 | }; |
414 | 424 | ||
415 | /* | 425 | /* |
@@ -424,6 +434,7 @@ static const struct ata_port_info sil24_port_info[] = { | |||
424 | { | 434 | { |
425 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | | 435 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | |
426 | SIL24_FLAG_PCIX_IRQ_WOC, | 436 | SIL24_FLAG_PCIX_IRQ_WOC, |
437 | .link_flags = SIL24_COMMON_LFLAGS, | ||
427 | .pio_mask = 0x1f, /* pio0-4 */ | 438 | .pio_mask = 0x1f, /* pio0-4 */ |
428 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 439 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
429 | .udma_mask = ATA_UDMA5, /* udma0-5 */ | 440 | .udma_mask = ATA_UDMA5, /* udma0-5 */ |
@@ -432,6 +443,7 @@ static const struct ata_port_info sil24_port_info[] = { | |||
432 | /* sil_3132 */ | 443 | /* sil_3132 */ |
433 | { | 444 | { |
434 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), | 445 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), |
446 | .link_flags = SIL24_COMMON_LFLAGS, | ||
435 | .pio_mask = 0x1f, /* pio0-4 */ | 447 | .pio_mask = 0x1f, /* pio0-4 */ |
436 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 448 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
437 | .udma_mask = ATA_UDMA5, /* udma0-5 */ | 449 | .udma_mask = ATA_UDMA5, /* udma0-5 */ |
@@ -440,6 +452,7 @@ static const struct ata_port_info sil24_port_info[] = { | |||
440 | /* sil_3131/sil_3531 */ | 452 | /* sil_3131/sil_3531 */ |
441 | { | 453 | { |
442 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), | 454 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), |
455 | .link_flags = SIL24_COMMON_LFLAGS, | ||
443 | .pio_mask = 0x1f, /* pio0-4 */ | 456 | .pio_mask = 0x1f, /* pio0-4 */ |
444 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 457 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
445 | .udma_mask = ATA_UDMA5, /* udma0-5 */ | 458 | .udma_mask = ATA_UDMA5, /* udma0-5 */ |
@@ -456,7 +469,7 @@ static int sil24_tag(int tag) | |||
456 | 469 | ||
457 | static void sil24_dev_config(struct ata_device *dev) | 470 | static void sil24_dev_config(struct ata_device *dev) |
458 | { | 471 | { |
459 | void __iomem *port = dev->ap->ioaddr.cmd_addr; | 472 | void __iomem *port = dev->link->ap->ioaddr.cmd_addr; |
460 | 473 | ||
461 | if (dev->cdb_len == 16) | 474 | if (dev->cdb_len == 16) |
462 | writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); | 475 | writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); |
@@ -520,19 +533,78 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | |||
520 | *tf = pp->tf; | 533 | *tf = pp->tf; |
521 | } | 534 | } |
522 | 535 | ||
536 | static void sil24_config_port(struct ata_port *ap) | ||
537 | { | ||
538 | void __iomem *port = ap->ioaddr.cmd_addr; | ||
539 | |||
540 | /* configure IRQ WoC */ | ||
541 | if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) | ||
542 | writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); | ||
543 | else | ||
544 | writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); | ||
545 | |||
546 | /* zero error counters. */ | ||
547 | writel(0x8000, port + PORT_DECODE_ERR_THRESH); | ||
548 | writel(0x8000, port + PORT_CRC_ERR_THRESH); | ||
549 | writel(0x8000, port + PORT_HSHK_ERR_THRESH); | ||
550 | writel(0x0000, port + PORT_DECODE_ERR_CNT); | ||
551 | writel(0x0000, port + PORT_CRC_ERR_CNT); | ||
552 | writel(0x0000, port + PORT_HSHK_ERR_CNT); | ||
553 | |||
554 | /* always use 64bit activation */ | ||
555 | writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); | ||
556 | |||
557 | /* clear port multiplier enable and resume bits */ | ||
558 | writel(PORT_CS_PMP_EN | PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR); | ||
559 | } | ||
560 | |||
561 | static void sil24_config_pmp(struct ata_port *ap, int attached) | ||
562 | { | ||
563 | void __iomem *port = ap->ioaddr.cmd_addr; | ||
564 | |||
565 | if (attached) | ||
566 | writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT); | ||
567 | else | ||
568 | writel(PORT_CS_PMP_EN, port + PORT_CTRL_CLR); | ||
569 | } | ||
570 | |||
571 | static void sil24_clear_pmp(struct ata_port *ap) | ||
572 | { | ||
573 | void __iomem *port = ap->ioaddr.cmd_addr; | ||
574 | int i; | ||
575 | |||
576 | writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR); | ||
577 | |||
578 | for (i = 0; i < SATA_PMP_MAX_PORTS; i++) { | ||
579 | void __iomem *pmp_base = port + PORT_PMP + i * PORT_PMP_SIZE; | ||
580 | |||
581 | writel(0, pmp_base + PORT_PMP_STATUS); | ||
582 | writel(0, pmp_base + PORT_PMP_QACTIVE); | ||
583 | } | ||
584 | } | ||
585 | |||
523 | static int sil24_init_port(struct ata_port *ap) | 586 | static int sil24_init_port(struct ata_port *ap) |
524 | { | 587 | { |
525 | void __iomem *port = ap->ioaddr.cmd_addr; | 588 | void __iomem *port = ap->ioaddr.cmd_addr; |
589 | struct sil24_port_priv *pp = ap->private_data; | ||
526 | u32 tmp; | 590 | u32 tmp; |
527 | 591 | ||
592 | /* clear PMP error status */ | ||
593 | if (ap->nr_pmp_links) | ||
594 | sil24_clear_pmp(ap); | ||
595 | |||
528 | writel(PORT_CS_INIT, port + PORT_CTRL_STAT); | 596 | writel(PORT_CS_INIT, port + PORT_CTRL_STAT); |
529 | ata_wait_register(port + PORT_CTRL_STAT, | 597 | ata_wait_register(port + PORT_CTRL_STAT, |
530 | PORT_CS_INIT, PORT_CS_INIT, 10, 100); | 598 | PORT_CS_INIT, PORT_CS_INIT, 10, 100); |
531 | tmp = ata_wait_register(port + PORT_CTRL_STAT, | 599 | tmp = ata_wait_register(port + PORT_CTRL_STAT, |
532 | PORT_CS_RDY, 0, 10, 100); | 600 | PORT_CS_RDY, 0, 10, 100); |
533 | 601 | ||
534 | if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) | 602 | if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) { |
603 | pp->do_port_rst = 1; | ||
604 | ap->link.eh_context.i.action |= ATA_EH_HARDRESET; | ||
535 | return -EIO; | 605 | return -EIO; |
606 | } | ||
607 | |||
536 | return 0; | 608 | return 0; |
537 | } | 609 | } |
538 | 610 | ||
@@ -583,9 +655,10 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp, | |||
583 | return rc; | 655 | return rc; |
584 | } | 656 | } |
585 | 657 | ||
586 | static int sil24_do_softreset(struct ata_port *ap, unsigned int *class, | 658 | static int sil24_do_softreset(struct ata_link *link, unsigned int *class, |
587 | int pmp, unsigned long deadline) | 659 | int pmp, unsigned long deadline) |
588 | { | 660 | { |
661 | struct ata_port *ap = link->ap; | ||
589 | unsigned long timeout_msec = 0; | 662 | unsigned long timeout_msec = 0; |
590 | struct ata_taskfile tf; | 663 | struct ata_taskfile tf; |
591 | const char *reason; | 664 | const char *reason; |
@@ -593,7 +666,7 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class, | |||
593 | 666 | ||
594 | DPRINTK("ENTER\n"); | 667 | DPRINTK("ENTER\n"); |
595 | 668 | ||
596 | if (ata_port_offline(ap)) { | 669 | if (ata_link_offline(link)) { |
597 | DPRINTK("PHY reports no device\n"); | 670 | DPRINTK("PHY reports no device\n"); |
598 | *class = ATA_DEV_NONE; | 671 | *class = ATA_DEV_NONE; |
599 | goto out; | 672 | goto out; |
@@ -609,7 +682,7 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class, | |||
609 | if (time_after(deadline, jiffies)) | 682 | if (time_after(deadline, jiffies)) |
610 | timeout_msec = jiffies_to_msecs(deadline - jiffies); | 683 | timeout_msec = jiffies_to_msecs(deadline - jiffies); |
611 | 684 | ||
612 | ata_tf_init(ap->device, &tf); /* doesn't really matter */ | 685 | ata_tf_init(link->device, &tf); /* doesn't really matter */ |
613 | rc = sil24_exec_polled_cmd(ap, pmp, &tf, 0, PRB_CTRL_SRST, | 686 | rc = sil24_exec_polled_cmd(ap, pmp, &tf, 0, PRB_CTRL_SRST, |
614 | timeout_msec); | 687 | timeout_msec); |
615 | if (rc == -EBUSY) { | 688 | if (rc == -EBUSY) { |
@@ -631,29 +704,54 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class, | |||
631 | return 0; | 704 | return 0; |
632 | 705 | ||
633 | err: | 706 | err: |
634 | ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); | 707 | ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason); |
635 | return -EIO; | 708 | return -EIO; |
636 | } | 709 | } |
637 | 710 | ||
638 | static int sil24_softreset(struct ata_port *ap, unsigned int *class, | 711 | static int sil24_softreset(struct ata_link *link, unsigned int *class, |
639 | unsigned long deadline) | 712 | unsigned long deadline) |
640 | { | 713 | { |
641 | return sil24_do_softreset(ap, class, 0, deadline); | 714 | return sil24_do_softreset(link, class, SATA_PMP_CTRL_PORT, deadline); |
642 | } | 715 | } |
643 | 716 | ||
644 | static int sil24_hardreset(struct ata_port *ap, unsigned int *class, | 717 | static int sil24_hardreset(struct ata_link *link, unsigned int *class, |
645 | unsigned long deadline) | 718 | unsigned long deadline) |
646 | { | 719 | { |
720 | struct ata_port *ap = link->ap; | ||
647 | void __iomem *port = ap->ioaddr.cmd_addr; | 721 | void __iomem *port = ap->ioaddr.cmd_addr; |
722 | struct sil24_port_priv *pp = ap->private_data; | ||
723 | int did_port_rst = 0; | ||
648 | const char *reason; | 724 | const char *reason; |
649 | int tout_msec, rc; | 725 | int tout_msec, rc; |
650 | u32 tmp; | 726 | u32 tmp; |
651 | 727 | ||
728 | retry: | ||
729 | /* Sometimes, DEV_RST is not enough to recover the controller. | ||
730 | * This happens often after PM DMA CS errata. | ||
731 | */ | ||
732 | if (pp->do_port_rst) { | ||
733 | ata_port_printk(ap, KERN_WARNING, "controller in dubious " | ||
734 | "state, performing PORT_RST\n"); | ||
735 | |||
736 | writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT); | ||
737 | msleep(10); | ||
738 | writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR); | ||
739 | ata_wait_register(port + PORT_CTRL_STAT, PORT_CS_RDY, 0, | ||
740 | 10, 5000); | ||
741 | |||
742 | /* restore port configuration */ | ||
743 | sil24_config_port(ap); | ||
744 | sil24_config_pmp(ap, ap->nr_pmp_links); | ||
745 | |||
746 | pp->do_port_rst = 0; | ||
747 | did_port_rst = 1; | ||
748 | } | ||
749 | |||
652 | /* sil24 does the right thing(tm) without any protection */ | 750 | /* sil24 does the right thing(tm) without any protection */ |
653 | sata_set_spd(ap); | 751 | sata_set_spd(link); |
654 | 752 | ||
655 | tout_msec = 100; | 753 | tout_msec = 100; |
656 | if (ata_port_online(ap)) | 754 | if (ata_link_online(link)) |
657 | tout_msec = 5000; | 755 | tout_msec = 5000; |
658 | 756 | ||
659 | writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); | 757 | writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); |
@@ -663,14 +761,14 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class, | |||
663 | /* SStatus oscillates between zero and valid status after | 761 | /* SStatus oscillates between zero and valid status after |
664 | * DEV_RST, debounce it. | 762 | * DEV_RST, debounce it. |
665 | */ | 763 | */ |
666 | rc = sata_phy_debounce(ap, sata_deb_timing_long, deadline); | 764 | rc = sata_link_debounce(link, sata_deb_timing_long, deadline); |
667 | if (rc) { | 765 | if (rc) { |
668 | reason = "PHY debouncing failed"; | 766 | reason = "PHY debouncing failed"; |
669 | goto err; | 767 | goto err; |
670 | } | 768 | } |
671 | 769 | ||
672 | if (tmp & PORT_CS_DEV_RST) { | 770 | if (tmp & PORT_CS_DEV_RST) { |
673 | if (ata_port_offline(ap)) | 771 | if (ata_link_offline(link)) |
674 | return 0; | 772 | return 0; |
675 | reason = "link not ready"; | 773 | reason = "link not ready"; |
676 | goto err; | 774 | goto err; |
@@ -685,7 +783,12 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class, | |||
685 | return -EAGAIN; | 783 | return -EAGAIN; |
686 | 784 | ||
687 | err: | 785 | err: |
688 | ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); | 786 | if (!did_port_rst) { |
787 | pp->do_port_rst = 1; | ||
788 | goto retry; | ||
789 | } | ||
790 | |||
791 | ata_link_printk(link, KERN_ERR, "hardreset failed (%s)\n", reason); | ||
689 | return -EIO; | 792 | return -EIO; |
690 | } | 793 | } |
691 | 794 | ||
@@ -705,6 +808,38 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc, | |||
705 | } | 808 | } |
706 | } | 809 | } |
707 | 810 | ||
811 | static int sil24_qc_defer(struct ata_queued_cmd *qc) | ||
812 | { | ||
813 | struct ata_link *link = qc->dev->link; | ||
814 | struct ata_port *ap = link->ap; | ||
815 | u8 prot = qc->tf.protocol; | ||
816 | int is_atapi = (prot == ATA_PROT_ATAPI || | ||
817 | prot == ATA_PROT_ATAPI_NODATA || | ||
818 | prot == ATA_PROT_ATAPI_DMA); | ||
819 | |||
820 | /* ATAPI commands completing with CHECK_SENSE cause various | ||
821 | * weird problems if other commands are active. PMP DMA CS | ||
822 | * errata doesn't cover all and HSM violation occurs even with | ||
823 | * only one other device active. Always run an ATAPI command | ||
824 | * by itself. | ||
825 | */ | ||
826 | if (unlikely(ap->excl_link)) { | ||
827 | if (link == ap->excl_link) { | ||
828 | if (ap->nr_active_links) | ||
829 | return ATA_DEFER_PORT; | ||
830 | qc->flags |= ATA_QCFLAG_CLEAR_EXCL; | ||
831 | } else | ||
832 | return ATA_DEFER_PORT; | ||
833 | } else if (unlikely(is_atapi)) { | ||
834 | ap->excl_link = link; | ||
835 | if (ap->nr_active_links) | ||
836 | return ATA_DEFER_PORT; | ||
837 | qc->flags |= ATA_QCFLAG_CLEAR_EXCL; | ||
838 | } | ||
839 | |||
840 | return ata_std_qc_defer(qc); | ||
841 | } | ||
842 | |||
708 | static void sil24_qc_prep(struct ata_queued_cmd *qc) | 843 | static void sil24_qc_prep(struct ata_queued_cmd *qc) |
709 | { | 844 | { |
710 | struct ata_port *ap = qc->ap; | 845 | struct ata_port *ap = qc->ap; |
@@ -748,7 +883,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) | |||
748 | } | 883 | } |
749 | 884 | ||
750 | prb->ctrl = cpu_to_le16(ctrl); | 885 | prb->ctrl = cpu_to_le16(ctrl); |
751 | ata_tf_to_fis(&qc->tf, 0, 1, prb->fis); | 886 | ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, prb->fis); |
752 | 887 | ||
753 | if (qc->flags & ATA_QCFLAG_DMAMAP) | 888 | if (qc->flags & ATA_QCFLAG_DMAMAP) |
754 | sil24_fill_sg(qc, sge); | 889 | sil24_fill_sg(qc, sge); |
@@ -777,6 +912,39 @@ static void sil24_irq_clear(struct ata_port *ap) | |||
777 | /* unused */ | 912 | /* unused */ |
778 | } | 913 | } |
779 | 914 | ||
915 | static void sil24_pmp_attach(struct ata_port *ap) | ||
916 | { | ||
917 | sil24_config_pmp(ap, 1); | ||
918 | sil24_init_port(ap); | ||
919 | } | ||
920 | |||
921 | static void sil24_pmp_detach(struct ata_port *ap) | ||
922 | { | ||
923 | sil24_init_port(ap); | ||
924 | sil24_config_pmp(ap, 0); | ||
925 | } | ||
926 | |||
927 | static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class, | ||
928 | unsigned long deadline) | ||
929 | { | ||
930 | return sil24_do_softreset(link, class, link->pmp, deadline); | ||
931 | } | ||
932 | |||
933 | static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class, | ||
934 | unsigned long deadline) | ||
935 | { | ||
936 | int rc; | ||
937 | |||
938 | rc = sil24_init_port(link->ap); | ||
939 | if (rc) { | ||
940 | ata_link_printk(link, KERN_ERR, | ||
941 | "hardreset failed (port not ready)\n"); | ||
942 | return rc; | ||
943 | } | ||
944 | |||
945 | return sata_pmp_std_hardreset(link, class, deadline); | ||
946 | } | ||
947 | |||
780 | static void sil24_freeze(struct ata_port *ap) | 948 | static void sil24_freeze(struct ata_port *ap) |
781 | { | 949 | { |
782 | void __iomem *port = ap->ioaddr.cmd_addr; | 950 | void __iomem *port = ap->ioaddr.cmd_addr; |
@@ -804,8 +972,10 @@ static void sil24_error_intr(struct ata_port *ap) | |||
804 | { | 972 | { |
805 | void __iomem *port = ap->ioaddr.cmd_addr; | 973 | void __iomem *port = ap->ioaddr.cmd_addr; |
806 | struct sil24_port_priv *pp = ap->private_data; | 974 | struct sil24_port_priv *pp = ap->private_data; |
807 | struct ata_eh_info *ehi = &ap->eh_info; | 975 | struct ata_queued_cmd *qc = NULL; |
808 | int freeze = 0; | 976 | struct ata_link *link; |
977 | struct ata_eh_info *ehi; | ||
978 | int abort = 0, freeze = 0; | ||
809 | u32 irq_stat; | 979 | u32 irq_stat; |
810 | 980 | ||
811 | /* on error, we need to clear IRQ explicitly */ | 981 | /* on error, we need to clear IRQ explicitly */ |
@@ -813,10 +983,17 @@ static void sil24_error_intr(struct ata_port *ap) | |||
813 | writel(irq_stat, port + PORT_IRQ_STAT); | 983 | writel(irq_stat, port + PORT_IRQ_STAT); |
814 | 984 | ||
815 | /* first, analyze and record host port events */ | 985 | /* first, analyze and record host port events */ |
986 | link = &ap->link; | ||
987 | ehi = &link->eh_info; | ||
816 | ata_ehi_clear_desc(ehi); | 988 | ata_ehi_clear_desc(ehi); |
817 | 989 | ||
818 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); | 990 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); |
819 | 991 | ||
992 | if (irq_stat & PORT_IRQ_SDB_NOTIFY) { | ||
993 | ata_ehi_push_desc(ehi, "SDB notify"); | ||
994 | sata_async_notification(ap); | ||
995 | } | ||
996 | |||
820 | if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) { | 997 | if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) { |
821 | ata_ehi_hotplugged(ehi); | 998 | ata_ehi_hotplugged(ehi); |
822 | ata_ehi_push_desc(ehi, "%s", | 999 | ata_ehi_push_desc(ehi, "%s", |
@@ -836,8 +1013,44 @@ static void sil24_error_intr(struct ata_port *ap) | |||
836 | if (irq_stat & PORT_IRQ_ERROR) { | 1013 | if (irq_stat & PORT_IRQ_ERROR) { |
837 | struct sil24_cerr_info *ci = NULL; | 1014 | struct sil24_cerr_info *ci = NULL; |
838 | unsigned int err_mask = 0, action = 0; | 1015 | unsigned int err_mask = 0, action = 0; |
839 | struct ata_queued_cmd *qc; | 1016 | u32 context, cerr; |
840 | u32 cerr; | 1017 | int pmp; |
1018 | |||
1019 | abort = 1; | ||
1020 | |||
1021 | /* DMA Context Switch Failure in Port Multiplier Mode | ||
1022 | * errata. If we have active commands to 3 or more | ||
1023 | * devices, any error condition on active devices can | ||
1024 | * corrupt DMA context switching. | ||
1025 | */ | ||
1026 | if (ap->nr_active_links >= 3) { | ||
1027 | ehi->err_mask |= AC_ERR_OTHER; | ||
1028 | ehi->action |= ATA_EH_HARDRESET; | ||
1029 | ata_ehi_push_desc(ehi, "PMP DMA CS errata"); | ||
1030 | pp->do_port_rst = 1; | ||
1031 | freeze = 1; | ||
1032 | } | ||
1033 | |||
1034 | /* find out the offending link and qc */ | ||
1035 | if (ap->nr_pmp_links) { | ||
1036 | context = readl(port + PORT_CONTEXT); | ||
1037 | pmp = (context >> 5) & 0xf; | ||
1038 | |||
1039 | if (pmp < ap->nr_pmp_links) { | ||
1040 | link = &ap->pmp_link[pmp]; | ||
1041 | ehi = &link->eh_info; | ||
1042 | qc = ata_qc_from_tag(ap, link->active_tag); | ||
1043 | |||
1044 | ata_ehi_clear_desc(ehi); | ||
1045 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", | ||
1046 | irq_stat); | ||
1047 | } else { | ||
1048 | err_mask |= AC_ERR_HSM; | ||
1049 | action |= ATA_EH_HARDRESET; | ||
1050 | freeze = 1; | ||
1051 | } | ||
1052 | } else | ||
1053 | qc = ata_qc_from_tag(ap, link->active_tag); | ||
841 | 1054 | ||
842 | /* analyze CMD_ERR */ | 1055 | /* analyze CMD_ERR */ |
843 | cerr = readl(port + PORT_CMD_ERR); | 1056 | cerr = readl(port + PORT_CMD_ERR); |
@@ -856,7 +1069,6 @@ static void sil24_error_intr(struct ata_port *ap) | |||
856 | } | 1069 | } |
857 | 1070 | ||
858 | /* record error info */ | 1071 | /* record error info */ |
859 | qc = ata_qc_from_tag(ap, ap->active_tag); | ||
860 | if (qc) { | 1072 | if (qc) { |
861 | sil24_read_tf(ap, qc->tag, &pp->tf); | 1073 | sil24_read_tf(ap, qc->tag, &pp->tf); |
862 | qc->err_mask |= err_mask; | 1074 | qc->err_mask |= err_mask; |
@@ -864,13 +1076,21 @@ static void sil24_error_intr(struct ata_port *ap) | |||
864 | ehi->err_mask |= err_mask; | 1076 | ehi->err_mask |= err_mask; |
865 | 1077 | ||
866 | ehi->action |= action; | 1078 | ehi->action |= action; |
1079 | |||
1080 | /* if PMP, resume */ | ||
1081 | if (ap->nr_pmp_links) | ||
1082 | writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT); | ||
867 | } | 1083 | } |
868 | 1084 | ||
869 | /* freeze or abort */ | 1085 | /* freeze or abort */ |
870 | if (freeze) | 1086 | if (freeze) |
871 | ata_port_freeze(ap); | 1087 | ata_port_freeze(ap); |
872 | else | 1088 | else if (abort) { |
873 | ata_port_abort(ap); | 1089 | if (qc) |
1090 | ata_link_abort(qc->dev->link); | ||
1091 | else | ||
1092 | ata_port_abort(ap); | ||
1093 | } | ||
874 | } | 1094 | } |
875 | 1095 | ||
876 | static void sil24_finish_qc(struct ata_queued_cmd *qc) | 1096 | static void sil24_finish_qc(struct ata_queued_cmd *qc) |
@@ -910,7 +1130,7 @@ static inline void sil24_host_intr(struct ata_port *ap) | |||
910 | if (rc > 0) | 1130 | if (rc > 0) |
911 | return; | 1131 | return; |
912 | if (rc < 0) { | 1132 | if (rc < 0) { |
913 | struct ata_eh_info *ehi = &ap->eh_info; | 1133 | struct ata_eh_info *ehi = &ap->link.eh_info; |
914 | ehi->err_mask |= AC_ERR_HSM; | 1134 | ehi->err_mask |= AC_ERR_HSM; |
915 | ehi->action |= ATA_EH_SOFTRESET; | 1135 | ehi->action |= ATA_EH_SOFTRESET; |
916 | ata_port_freeze(ap); | 1136 | ata_port_freeze(ap); |
@@ -921,7 +1141,7 @@ static inline void sil24_host_intr(struct ata_port *ap) | |||
921 | if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit()) | 1141 | if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit()) |
922 | ata_port_printk(ap, KERN_INFO, "spurious interrupt " | 1142 | ata_port_printk(ap, KERN_INFO, "spurious interrupt " |
923 | "(slot_stat 0x%x active_tag %d sactive 0x%x)\n", | 1143 | "(slot_stat 0x%x active_tag %d sactive 0x%x)\n", |
924 | slot_stat, ap->active_tag, ap->sactive); | 1144 | slot_stat, ap->link.active_tag, ap->link.sactive); |
925 | } | 1145 | } |
926 | 1146 | ||
927 | static irqreturn_t sil24_interrupt(int irq, void *dev_instance) | 1147 | static irqreturn_t sil24_interrupt(int irq, void *dev_instance) |
@@ -963,16 +1183,18 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance) | |||
963 | 1183 | ||
964 | static void sil24_error_handler(struct ata_port *ap) | 1184 | static void sil24_error_handler(struct ata_port *ap) |
965 | { | 1185 | { |
966 | struct ata_eh_context *ehc = &ap->eh_context; | 1186 | struct sil24_port_priv *pp = ap->private_data; |
967 | 1187 | ||
968 | if (sil24_init_port(ap)) { | 1188 | if (sil24_init_port(ap)) |
969 | ata_eh_freeze_port(ap); | 1189 | ata_eh_freeze_port(ap); |
970 | ehc->i.action |= ATA_EH_HARDRESET; | ||
971 | } | ||
972 | 1190 | ||
973 | /* perform recovery */ | 1191 | /* perform recovery */ |
974 | ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, | 1192 | sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, |
975 | ata_std_postreset); | 1193 | ata_std_postreset, sata_pmp_std_prereset, |
1194 | sil24_pmp_softreset, sil24_pmp_hardreset, | ||
1195 | sata_pmp_std_postreset); | ||
1196 | |||
1197 | pp->do_port_rst = 0; | ||
976 | } | 1198 | } |
977 | 1199 | ||
978 | static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) | 1200 | static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) |
@@ -980,8 +1202,8 @@ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) | |||
980 | struct ata_port *ap = qc->ap; | 1202 | struct ata_port *ap = qc->ap; |
981 | 1203 | ||
982 | /* make DMA engine forget about the failed command */ | 1204 | /* make DMA engine forget about the failed command */ |
983 | if (qc->flags & ATA_QCFLAG_FAILED) | 1205 | if ((qc->flags & ATA_QCFLAG_FAILED) && sil24_init_port(ap)) |
984 | sil24_init_port(ap); | 1206 | ata_eh_freeze_port(ap); |
985 | } | 1207 | } |
986 | 1208 | ||
987 | static int sil24_port_start(struct ata_port *ap) | 1209 | static int sil24_port_start(struct ata_port *ap) |
@@ -1019,7 +1241,6 @@ static int sil24_port_start(struct ata_port *ap) | |||
1019 | static void sil24_init_controller(struct ata_host *host) | 1241 | static void sil24_init_controller(struct ata_host *host) |
1020 | { | 1242 | { |
1021 | void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; | 1243 | void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; |
1022 | void __iomem *port_base = host->iomap[SIL24_PORT_BAR]; | ||
1023 | u32 tmp; | 1244 | u32 tmp; |
1024 | int i; | 1245 | int i; |
1025 | 1246 | ||
@@ -1031,7 +1252,8 @@ static void sil24_init_controller(struct ata_host *host) | |||
1031 | 1252 | ||
1032 | /* init ports */ | 1253 | /* init ports */ |
1033 | for (i = 0; i < host->n_ports; i++) { | 1254 | for (i = 0; i < host->n_ports; i++) { |
1034 | void __iomem *port = port_base + i * PORT_REGS_SIZE; | 1255 | struct ata_port *ap = host->ports[i]; |
1256 | void __iomem *port = ap->ioaddr.cmd_addr; | ||
1035 | 1257 | ||
1036 | /* Initial PHY setting */ | 1258 | /* Initial PHY setting */ |
1037 | writel(0x20c, port + PORT_PHY_CFG); | 1259 | writel(0x20c, port + PORT_PHY_CFG); |
@@ -1048,26 +1270,8 @@ static void sil24_init_controller(struct ata_host *host) | |||
1048 | "failed to clear port RST\n"); | 1270 | "failed to clear port RST\n"); |
1049 | } | 1271 | } |
1050 | 1272 | ||
1051 | /* Configure IRQ WoC */ | 1273 | /* configure port */ |
1052 | if (host->ports[0]->flags & SIL24_FLAG_PCIX_IRQ_WOC) | 1274 | sil24_config_port(ap); |
1053 | writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); | ||
1054 | else | ||
1055 | writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); | ||
1056 | |||
1057 | /* Zero error counters. */ | ||
1058 | writel(0x8000, port + PORT_DECODE_ERR_THRESH); | ||
1059 | writel(0x8000, port + PORT_CRC_ERR_THRESH); | ||
1060 | writel(0x8000, port + PORT_HSHK_ERR_THRESH); | ||
1061 | writel(0x0000, port + PORT_DECODE_ERR_CNT); | ||
1062 | writel(0x0000, port + PORT_CRC_ERR_CNT); | ||
1063 | writel(0x0000, port + PORT_HSHK_ERR_CNT); | ||
1064 | |||
1065 | /* Always use 64bit activation */ | ||
1066 | writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); | ||
1067 | |||
1068 | /* Clear port multiplier enable and resume bits */ | ||
1069 | writel(PORT_CS_PMP_EN | PORT_CS_PMP_RESUME, | ||
1070 | port + PORT_CTRL_CLR); | ||
1071 | } | 1275 | } |
1072 | 1276 | ||
1073 | /* Turn on interrupts */ | 1277 | /* Turn on interrupts */ |
@@ -1118,12 +1322,15 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1118 | host->iomap = iomap; | 1322 | host->iomap = iomap; |
1119 | 1323 | ||
1120 | for (i = 0; i < host->n_ports; i++) { | 1324 | for (i = 0; i < host->n_ports; i++) { |
1121 | void __iomem *port = iomap[SIL24_PORT_BAR] + i * PORT_REGS_SIZE; | 1325 | struct ata_port *ap = host->ports[i]; |
1326 | size_t offset = ap->port_no * PORT_REGS_SIZE; | ||
1327 | void __iomem *port = iomap[SIL24_PORT_BAR] + offset; | ||
1122 | 1328 | ||
1123 | host->ports[i]->ioaddr.cmd_addr = port; | 1329 | host->ports[i]->ioaddr.cmd_addr = port; |
1124 | host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL; | 1330 | host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL; |
1125 | 1331 | ||
1126 | ata_std_ports(&host->ports[i]->ioaddr); | 1332 | ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host"); |
1333 | ata_port_pbar_desc(ap, SIL24_PORT_BAR, offset, "port"); | ||
1127 | } | 1334 | } |
1128 | 1335 | ||
1129 | /* configure and activate the device */ | 1336 | /* configure and activate the device */ |
@@ -1179,6 +1386,12 @@ static int sil24_pci_device_resume(struct pci_dev *pdev) | |||
1179 | 1386 | ||
1180 | return 0; | 1387 | return 0; |
1181 | } | 1388 | } |
1389 | |||
1390 | static int sil24_port_resume(struct ata_port *ap) | ||
1391 | { | ||
1392 | sil24_config_pmp(ap, ap->nr_pmp_links); | ||
1393 | return 0; | ||
1394 | } | ||
1182 | #endif | 1395 | #endif |
1183 | 1396 | ||
1184 | static int __init sil24_init(void) | 1397 | static int __init sil24_init(void) |