diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-05 02:58:32 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-05 02:58:32 -0400 |
| commit | 67846b30171cc4d706125f630193a76a26bb334a (patch) | |
| tree | 5ba70c2b68086f471686eb1e56e38436eaf73416 | |
| parent | 643736a58d2668af94aee05670c5e9ae76e7b85f (diff) | |
libata: add ata_ratelimit(), use it in AHCI driver irq handler
| -rw-r--r-- | drivers/scsi/ahci.c | 31 | ||||
| -rw-r--r-- | drivers/scsi/libata-core.c | 23 | ||||
| -rw-r--r-- | include/linux/libata.h | 2 |
3 files changed, 50 insertions, 6 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index c2c8fa828e24..5ec866b00479 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c | |||
| @@ -672,17 +672,36 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * | |||
| 672 | 672 | ||
| 673 | for (i = 0; i < host_set->n_ports; i++) { | 673 | for (i = 0; i < host_set->n_ports; i++) { |
| 674 | struct ata_port *ap; | 674 | struct ata_port *ap; |
| 675 | u32 tmp; | ||
| 676 | 675 | ||
| 677 | VPRINTK("port %u\n", i); | 676 | if (!(irq_stat & (1 << i))) |
| 677 | continue; | ||
| 678 | |||
| 678 | ap = host_set->ports[i]; | 679 | ap = host_set->ports[i]; |
| 679 | tmp = irq_stat & (1 << i); | 680 | if (ap) { |
| 680 | if (tmp && ap) { | ||
| 681 | struct ata_queued_cmd *qc; | 681 | struct ata_queued_cmd *qc; |
| 682 | qc = ata_qc_from_tag(ap, ap->active_tag); | 682 | qc = ata_qc_from_tag(ap, ap->active_tag); |
| 683 | if (ahci_host_intr(ap, qc)) | 683 | if (!ahci_host_intr(ap, qc)) |
| 684 | irq_ack |= (1 << i); | 684 | if (ata_ratelimit()) { |
| 685 | struct pci_dev *pdev = | ||
| 686 | to_pci_dev(ap->host_set->dev); | ||
| 687 | printk(KERN_WARNING | ||
| 688 | "ahci(%s): unhandled interrupt on port %u\n", | ||
| 689 | pci_name(pdev), i); | ||
| 690 | } | ||
| 691 | |||
| 692 | VPRINTK("port %u\n", i); | ||
| 693 | } else { | ||
| 694 | VPRINTK("port %u (no irq)\n", i); | ||
| 695 | if (ata_ratelimit()) { | ||
| 696 | struct pci_dev *pdev = | ||
| 697 | to_pci_dev(ap->host_set->dev); | ||
| 698 | printk(KERN_WARNING | ||
| 699 | "ahci(%s): interrupt on disabled port %u\n", | ||
| 700 | pci_name(pdev), i); | ||
| 701 | } | ||
| 685 | } | 702 | } |
| 703 | |||
| 704 | irq_ack |= (1 << i); | ||
| 686 | } | 705 | } |
| 687 | 706 | ||
| 688 | if (irq_ack) { | 707 | if (irq_ack) { |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f0894bfa908b..ceffaef37d17 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include <linux/completion.h> | 48 | #include <linux/completion.h> |
| 49 | #include <linux/suspend.h> | 49 | #include <linux/suspend.h> |
| 50 | #include <linux/workqueue.h> | 50 | #include <linux/workqueue.h> |
| 51 | #include <linux/jiffies.h> | ||
| 51 | #include <scsi/scsi.h> | 52 | #include <scsi/scsi.h> |
| 52 | #include "scsi.h" | 53 | #include "scsi.h" |
| 53 | #include "scsi_priv.h" | 54 | #include "scsi_priv.h" |
| @@ -4688,6 +4689,27 @@ static void __exit ata_exit(void) | |||
| 4688 | module_init(ata_init); | 4689 | module_init(ata_init); |
| 4689 | module_exit(ata_exit); | 4690 | module_exit(ata_exit); |
| 4690 | 4691 | ||
| 4692 | static unsigned long ratelimit_time; | ||
| 4693 | static spinlock_t ata_ratelimit_lock = SPIN_LOCK_UNLOCKED; | ||
| 4694 | |||
| 4695 | int ata_ratelimit(void) | ||
| 4696 | { | ||
| 4697 | int rc; | ||
| 4698 | unsigned long flags; | ||
| 4699 | |||
| 4700 | spin_lock_irqsave(&ata_ratelimit_lock, flags); | ||
| 4701 | |||
| 4702 | if (time_after(jiffies, ratelimit_time)) { | ||
| 4703 | rc = 1; | ||
| 4704 | ratelimit_time = jiffies + (HZ/5); | ||
| 4705 | } else | ||
| 4706 | rc = 0; | ||
| 4707 | |||
| 4708 | spin_unlock_irqrestore(&ata_ratelimit_lock, flags); | ||
| 4709 | |||
| 4710 | return rc; | ||
| 4711 | } | ||
| 4712 | |||
| 4691 | /* | 4713 | /* |
| 4692 | * libata is essentially a library of internal helper functions for | 4714 | * libata is essentially a library of internal helper functions for |
| 4693 | * low-level ATA host controller drivers. As such, the API/ABI is | 4715 | * low-level ATA host controller drivers. As such, the API/ABI is |
| @@ -4729,6 +4751,7 @@ EXPORT_SYMBOL_GPL(sata_phy_reset); | |||
| 4729 | EXPORT_SYMBOL_GPL(__sata_phy_reset); | 4751 | EXPORT_SYMBOL_GPL(__sata_phy_reset); |
| 4730 | EXPORT_SYMBOL_GPL(ata_bus_reset); | 4752 | EXPORT_SYMBOL_GPL(ata_bus_reset); |
| 4731 | EXPORT_SYMBOL_GPL(ata_port_disable); | 4753 | EXPORT_SYMBOL_GPL(ata_port_disable); |
| 4754 | EXPORT_SYMBOL_GPL(ata_ratelimit); | ||
| 4732 | EXPORT_SYMBOL_GPL(ata_scsi_ioctl); | 4755 | EXPORT_SYMBOL_GPL(ata_scsi_ioctl); |
| 4733 | EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); | 4756 | EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); |
| 4734 | EXPORT_SYMBOL_GPL(ata_scsi_error); | 4757 | EXPORT_SYMBOL_GPL(ata_scsi_error); |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 4d45179872cc..7929cfc9318d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -410,6 +410,8 @@ extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmn | |||
| 410 | extern int ata_scsi_error(struct Scsi_Host *host); | 410 | extern int ata_scsi_error(struct Scsi_Host *host); |
| 411 | extern int ata_scsi_release(struct Scsi_Host *host); | 411 | extern int ata_scsi_release(struct Scsi_Host *host); |
| 412 | extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); | 412 | extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); |
| 413 | extern int ata_ratelimit(void); | ||
| 414 | |||
| 413 | /* | 415 | /* |
| 414 | * Default driver ops implementations | 416 | * Default driver ops implementations |
| 415 | */ | 417 | */ |
