aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_nv.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-05-10 15:41:30 -0400
committerJeff Garzik <jgarzik@redhat.com>2010-05-17 22:49:02 -0400
commit3e4ec3443f70fbe144799ccf0b1c3797f78d1715 (patch)
treecfb297e42075baacbbabfb6034e3e7c9a44c73b2 /drivers/ata/sata_nv.c
parentc7a8209f766961eea4cfc6f22d2d6e06ef63546c (diff)
libata: kill ATA_FLAG_DISABLED
ATA_FLAG_DISABLED is only used by drivers which don't use ->error_handler framework and is largely broken. Its only meaningful function is to make irq handlers skip processing if the flag is set, which is largely useless and even harmful as it makes those ports more likely to cause IRQ storms. Kill ATA_FLAG_DISABLED and makes the callers disable attached devices instead. ata_port_probe() and ata_port_disable() which manipulate the flag are also killed. This simplifies condition check in IRQ handlers. While updating IRQ handlers, remove ap NULL check as libata guarantees consecutive port allocation (unoccupied ports are initialized with dummies) and long-obsolete ATA_QCFLAG_ACTIVE check (checked by ata_qc_from_tag()). Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/sata_nv.c')
-rw-r--r--drivers/ata/sata_nv.c236
1 files changed, 114 insertions, 122 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 9d3dbc8a1184..20cc510595db 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -933,107 +933,108 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
933 933
934 for (i = 0; i < host->n_ports; i++) { 934 for (i = 0; i < host->n_ports; i++) {
935 struct ata_port *ap = host->ports[i]; 935 struct ata_port *ap = host->ports[i];
936 struct nv_adma_port_priv *pp = ap->private_data;
937 void __iomem *mmio = pp->ctl_block;
938 u16 status;
939 u32 gen_ctl;
940 u32 notifier, notifier_error;
941
936 notifier_clears[i] = 0; 942 notifier_clears[i] = 0;
937 943
938 if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { 944 /* if ADMA is disabled, use standard ata interrupt handler */
939 struct nv_adma_port_priv *pp = ap->private_data; 945 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
940 void __iomem *mmio = pp->ctl_block; 946 u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
941 u16 status; 947 >> (NV_INT_PORT_SHIFT * i);
942 u32 gen_ctl; 948 handled += nv_host_intr(ap, irq_stat);
943 u32 notifier, notifier_error; 949 continue;
944 950 }
945 /* if ADMA is disabled, use standard ata interrupt handler */
946 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
947 u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
948 >> (NV_INT_PORT_SHIFT * i);
949 handled += nv_host_intr(ap, irq_stat);
950 continue;
951 }
952 951
953 /* if in ATA register mode, check for standard interrupts */ 952 /* if in ATA register mode, check for standard interrupts */
954 if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) { 953 if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
955 u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804) 954 u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
956 >> (NV_INT_PORT_SHIFT * i); 955 >> (NV_INT_PORT_SHIFT * i);
957 if (ata_tag_valid(ap->link.active_tag)) 956 if (ata_tag_valid(ap->link.active_tag))
958 /** NV_INT_DEV indication seems unreliable at times 957 /** NV_INT_DEV indication seems unreliable
959 at least in ADMA mode. Force it on always when a 958 at times at least in ADMA mode. Force it
960 command is active, to prevent losing interrupts. */ 959 on always when a command is active, to
961 irq_stat |= NV_INT_DEV; 960 prevent losing interrupts. */
962 handled += nv_host_intr(ap, irq_stat); 961 irq_stat |= NV_INT_DEV;
963 } 962 handled += nv_host_intr(ap, irq_stat);
963 }
964
965 notifier = readl(mmio + NV_ADMA_NOTIFIER);
966 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
967 notifier_clears[i] = notifier | notifier_error;
968
969 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
970
971 if (!NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
972 !notifier_error)
973 /* Nothing to do */
974 continue;
975
976 status = readw(mmio + NV_ADMA_STAT);
977
978 /*
979 * Clear status. Ensure the controller sees the
980 * clearing before we start looking at any of the CPB
981 * statuses, so that any CPB completions after this
982 * point in the handler will raise another interrupt.
983 */
984 writew(status, mmio + NV_ADMA_STAT);
985 readw(mmio + NV_ADMA_STAT); /* flush posted write */
986 rmb();
987
988 handled++; /* irq handled if we got here */
964 989
965 notifier = readl(mmio + NV_ADMA_NOTIFIER); 990 /* freeze if hotplugged or controller error */
966 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); 991 if (unlikely(status & (NV_ADMA_STAT_HOTPLUG |
967 notifier_clears[i] = notifier | notifier_error; 992 NV_ADMA_STAT_HOTUNPLUG |
968 993 NV_ADMA_STAT_TIMEOUT |
969 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); 994 NV_ADMA_STAT_SERROR))) {
970 995 struct ata_eh_info *ehi = &ap->link.eh_info;
971 if (!NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && 996
972 !notifier_error) 997 ata_ehi_clear_desc(ehi);
973 /* Nothing to do */ 998 __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status);
974 continue; 999 if (status & NV_ADMA_STAT_TIMEOUT) {
975 1000 ehi->err_mask |= AC_ERR_SYSTEM;
976 status = readw(mmio + NV_ADMA_STAT); 1001 ata_ehi_push_desc(ehi, "timeout");
977 1002 } else if (status & NV_ADMA_STAT_HOTPLUG) {
978 /* Clear status. Ensure the controller sees the clearing before we start 1003 ata_ehi_hotplugged(ehi);
979 looking at any of the CPB statuses, so that any CPB completions after 1004 ata_ehi_push_desc(ehi, "hotplug");
980 this point in the handler will raise another interrupt. */ 1005 } else if (status & NV_ADMA_STAT_HOTUNPLUG) {
981 writew(status, mmio + NV_ADMA_STAT); 1006 ata_ehi_hotplugged(ehi);
982 readw(mmio + NV_ADMA_STAT); /* flush posted write */ 1007 ata_ehi_push_desc(ehi, "hot unplug");
983 rmb(); 1008 } else if (status & NV_ADMA_STAT_SERROR) {
984 1009 /* let EH analyze SError and figure out cause */
985 handled++; /* irq handled if we got here */ 1010 ata_ehi_push_desc(ehi, "SError");
986 1011 } else
987 /* freeze if hotplugged or controller error */ 1012 ata_ehi_push_desc(ehi, "unknown");
988 if (unlikely(status & (NV_ADMA_STAT_HOTPLUG | 1013 ata_port_freeze(ap);
989 NV_ADMA_STAT_HOTUNPLUG | 1014 continue;
990 NV_ADMA_STAT_TIMEOUT | 1015 }
991 NV_ADMA_STAT_SERROR))) { 1016
992 struct ata_eh_info *ehi = &ap->link.eh_info; 1017 if (status & (NV_ADMA_STAT_DONE |
993 1018 NV_ADMA_STAT_CPBERR |
994 ata_ehi_clear_desc(ehi); 1019 NV_ADMA_STAT_CMD_COMPLETE)) {
995 __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status); 1020 u32 check_commands = notifier_clears[i];
996 if (status & NV_ADMA_STAT_TIMEOUT) { 1021 int pos, error = 0;
997 ehi->err_mask |= AC_ERR_SYSTEM; 1022
998 ata_ehi_push_desc(ehi, "timeout"); 1023 if (status & NV_ADMA_STAT_CPBERR) {
999 } else if (status & NV_ADMA_STAT_HOTPLUG) { 1024 /* check all active commands */
1000 ata_ehi_hotplugged(ehi); 1025 if (ata_tag_valid(ap->link.active_tag))
1001 ata_ehi_push_desc(ehi, "hotplug"); 1026 check_commands = 1 <<
1002 } else if (status & NV_ADMA_STAT_HOTUNPLUG) { 1027 ap->link.active_tag;
1003 ata_ehi_hotplugged(ehi); 1028 else
1004 ata_ehi_push_desc(ehi, "hot unplug"); 1029 check_commands = ap->link.sactive;
1005 } else if (status & NV_ADMA_STAT_SERROR) {
1006 /* let libata analyze SError and figure out the cause */
1007 ata_ehi_push_desc(ehi, "SError");
1008 } else
1009 ata_ehi_push_desc(ehi, "unknown");
1010 ata_port_freeze(ap);
1011 continue;
1012 } 1030 }
1013 1031
1014 if (status & (NV_ADMA_STAT_DONE | 1032 /* check CPBs for completed commands */
1015 NV_ADMA_STAT_CPBERR | 1033 while ((pos = ffs(check_commands)) && !error) {
1016 NV_ADMA_STAT_CMD_COMPLETE)) { 1034 pos--;
1017 u32 check_commands = notifier_clears[i]; 1035 error = nv_adma_check_cpb(ap, pos,
1018 int pos, error = 0;
1019
1020 if (status & NV_ADMA_STAT_CPBERR) {
1021 /* Check all active commands */
1022 if (ata_tag_valid(ap->link.active_tag))
1023 check_commands = 1 <<
1024 ap->link.active_tag;
1025 else
1026 check_commands = ap->
1027 link.sactive;
1028 }
1029
1030 /** Check CPBs for completed commands */
1031 while ((pos = ffs(check_commands)) && !error) {
1032 pos--;
1033 error = nv_adma_check_cpb(ap, pos,
1034 notifier_error & (1 << pos)); 1036 notifier_error & (1 << pos));
1035 check_commands &= ~(1 << pos); 1037 check_commands &= ~(1 << pos);
1036 }
1037 } 1038 }
1038 } 1039 }
1039 } 1040 }
@@ -1498,22 +1499,19 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
1498 spin_lock_irqsave(&host->lock, flags); 1499 spin_lock_irqsave(&host->lock, flags);
1499 1500
1500 for (i = 0; i < host->n_ports; i++) { 1501 for (i = 0; i < host->n_ports; i++) {
1501 struct ata_port *ap; 1502 struct ata_port *ap = host->ports[i];
1502 1503 struct ata_queued_cmd *qc;
1503 ap = host->ports[i];
1504 if (ap &&
1505 !(ap->flags & ATA_FLAG_DISABLED)) {
1506 struct ata_queued_cmd *qc;
1507 1504
1508 qc = ata_qc_from_tag(ap, ap->link.active_tag); 1505 qc = ata_qc_from_tag(ap, ap->link.active_tag);
1509 if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) 1506 if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
1510 handled += ata_sff_host_intr(ap, qc); 1507 handled += ata_sff_host_intr(ap, qc);
1511 else 1508 } else {
1512 // No request pending? Clear interrupt status 1509 /*
1513 // anyway, in case there's one pending. 1510 * No request pending? Clear interrupt status
1514 ap->ops->sff_check_status(ap); 1511 * anyway, in case there's one pending.
1512 */
1513 ap->ops->sff_check_status(ap);
1515 } 1514 }
1516
1517 } 1515 }
1518 1516
1519 spin_unlock_irqrestore(&host->lock, flags); 1517 spin_unlock_irqrestore(&host->lock, flags);
@@ -1526,11 +1524,7 @@ static irqreturn_t nv_do_interrupt(struct ata_host *host, u8 irq_stat)
1526 int i, handled = 0; 1524 int i, handled = 0;
1527 1525
1528 for (i = 0; i < host->n_ports; i++) { 1526 for (i = 0; i < host->n_ports; i++) {
1529 struct ata_port *ap = host->ports[i]; 1527 handled += nv_host_intr(host->ports[i], irq_stat);
1530
1531 if (ap && !(ap->flags & ATA_FLAG_DISABLED))
1532 handled += nv_host_intr(ap, irq_stat);
1533
1534 irq_stat >>= NV_INT_PORT_SHIFT; 1528 irq_stat >>= NV_INT_PORT_SHIFT;
1535 } 1529 }
1536 1530
@@ -2380,16 +2374,14 @@ static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance)
2380 for (i = 0; i < host->n_ports; i++) { 2374 for (i = 0; i < host->n_ports; i++) {
2381 struct ata_port *ap = host->ports[i]; 2375 struct ata_port *ap = host->ports[i];
2382 2376
2383 if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { 2377 if (ap->link.sactive) {
2384 if (ap->link.sactive) { 2378 nv_swncq_host_interrupt(ap, (u16)irq_stat);
2385 nv_swncq_host_interrupt(ap, (u16)irq_stat); 2379 handled = 1;
2386 handled = 1; 2380 } else {
2387 } else { 2381 if (irq_stat) /* reserve Hotplug */
2388 if (irq_stat) /* reserve Hotplug */ 2382 nv_swncq_irq_clear(ap, 0xfff0);
2389 nv_swncq_irq_clear(ap, 0xfff0);
2390 2383
2391 handled += nv_host_intr(ap, (u8)irq_stat); 2384 handled += nv_host_intr(ap, (u8)irq_stat);
2392 }
2393 } 2385 }
2394 irq_stat >>= NV_INT_PORT_SHIFT_MCP55; 2386 irq_stat >>= NV_INT_PORT_SHIFT_MCP55;
2395 } 2387 }