diff options
Diffstat (limited to 'drivers/scsi/sata_nv.c')
-rw-r--r-- | drivers/scsi/sata_nv.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index c0cf52cb975a..bbbb55eeb73a 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c | |||
@@ -29,6 +29,12 @@ | |||
29 | * NV-specific details such as register offsets, SATA phy location, | 29 | * NV-specific details such as register offsets, SATA phy location, |
30 | * hotplug info, etc. | 30 | * hotplug info, etc. |
31 | * | 31 | * |
32 | * 0.10 | ||
33 | * - Fixed spurious interrupts issue seen with the Maxtor 6H500F0 500GB | ||
34 | * drive. Also made the check_hotplug() callbacks return whether there | ||
35 | * was a hotplug interrupt or not. This was not the source of the | ||
36 | * spurious interrupts, but is the right thing to do anyway. | ||
37 | * | ||
32 | * 0.09 | 38 | * 0.09 |
33 | * - Fixed bug introduced by 0.08's MCP51 and MCP55 support. | 39 | * - Fixed bug introduced by 0.08's MCP51 and MCP55 support. |
34 | * | 40 | * |
@@ -124,10 +130,10 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | |||
124 | static void nv_host_stop (struct ata_host_set *host_set); | 130 | static void nv_host_stop (struct ata_host_set *host_set); |
125 | static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); | 131 | static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); |
126 | static void nv_disable_hotplug(struct ata_host_set *host_set); | 132 | static void nv_disable_hotplug(struct ata_host_set *host_set); |
127 | static void nv_check_hotplug(struct ata_host_set *host_set); | 133 | static int nv_check_hotplug(struct ata_host_set *host_set); |
128 | static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); | 134 | static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); |
129 | static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); | 135 | static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); |
130 | static void nv_check_hotplug_ck804(struct ata_host_set *host_set); | 136 | static int nv_check_hotplug_ck804(struct ata_host_set *host_set); |
131 | 137 | ||
132 | enum nv_host_type | 138 | enum nv_host_type |
133 | { | 139 | { |
@@ -176,7 +182,7 @@ struct nv_host_desc | |||
176 | enum nv_host_type host_type; | 182 | enum nv_host_type host_type; |
177 | void (*enable_hotplug)(struct ata_probe_ent *probe_ent); | 183 | void (*enable_hotplug)(struct ata_probe_ent *probe_ent); |
178 | void (*disable_hotplug)(struct ata_host_set *host_set); | 184 | void (*disable_hotplug)(struct ata_host_set *host_set); |
179 | void (*check_hotplug)(struct ata_host_set *host_set); | 185 | int (*check_hotplug)(struct ata_host_set *host_set); |
180 | 186 | ||
181 | }; | 187 | }; |
182 | static struct nv_host_desc nv_device_tbl[] = { | 188 | static struct nv_host_desc nv_device_tbl[] = { |
@@ -309,12 +315,16 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, | |||
309 | qc = ata_qc_from_tag(ap, ap->active_tag); | 315 | qc = ata_qc_from_tag(ap, ap->active_tag); |
310 | if (qc && (!(qc->tf.ctl & ATA_NIEN))) | 316 | if (qc && (!(qc->tf.ctl & ATA_NIEN))) |
311 | handled += ata_host_intr(ap, qc); | 317 | handled += ata_host_intr(ap, qc); |
318 | else | ||
319 | // No request pending? Clear interrupt status | ||
320 | // anyway, in case there's one pending. | ||
321 | ap->ops->check_status(ap); | ||
312 | } | 322 | } |
313 | 323 | ||
314 | } | 324 | } |
315 | 325 | ||
316 | if (host->host_desc->check_hotplug) | 326 | if (host->host_desc->check_hotplug) |
317 | host->host_desc->check_hotplug(host_set); | 327 | handled += host->host_desc->check_hotplug(host_set); |
318 | 328 | ||
319 | spin_unlock_irqrestore(&host_set->lock, flags); | 329 | spin_unlock_irqrestore(&host_set->lock, flags); |
320 | 330 | ||
@@ -497,7 +507,7 @@ static void nv_disable_hotplug(struct ata_host_set *host_set) | |||
497 | outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); | 507 | outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); |
498 | } | 508 | } |
499 | 509 | ||
500 | static void nv_check_hotplug(struct ata_host_set *host_set) | 510 | static int nv_check_hotplug(struct ata_host_set *host_set) |
501 | { | 511 | { |
502 | u8 intr_status; | 512 | u8 intr_status; |
503 | 513 | ||
@@ -522,7 +532,11 @@ static void nv_check_hotplug(struct ata_host_set *host_set) | |||
522 | if (intr_status & NV_INT_STATUS_SDEV_REMOVED) | 532 | if (intr_status & NV_INT_STATUS_SDEV_REMOVED) |
523 | printk(KERN_WARNING "nv_sata: " | 533 | printk(KERN_WARNING "nv_sata: " |
524 | "Secondary device removed\n"); | 534 | "Secondary device removed\n"); |
535 | |||
536 | return 1; | ||
525 | } | 537 | } |
538 | |||
539 | return 0; | ||
526 | } | 540 | } |
527 | 541 | ||
528 | static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) | 542 | static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) |
@@ -560,7 +574,7 @@ static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) | |||
560 | pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); | 574 | pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); |
561 | } | 575 | } |
562 | 576 | ||
563 | static void nv_check_hotplug_ck804(struct ata_host_set *host_set) | 577 | static int nv_check_hotplug_ck804(struct ata_host_set *host_set) |
564 | { | 578 | { |
565 | u8 intr_status; | 579 | u8 intr_status; |
566 | 580 | ||
@@ -585,7 +599,11 @@ static void nv_check_hotplug_ck804(struct ata_host_set *host_set) | |||
585 | if (intr_status & NV_INT_STATUS_SDEV_REMOVED) | 599 | if (intr_status & NV_INT_STATUS_SDEV_REMOVED) |
586 | printk(KERN_WARNING "nv_sata: " | 600 | printk(KERN_WARNING "nv_sata: " |
587 | "Secondary device removed\n"); | 601 | "Secondary device removed\n"); |
602 | |||
603 | return 1; | ||
588 | } | 604 | } |
605 | |||
606 | return 0; | ||
589 | } | 607 | } |
590 | 608 | ||
591 | static int __init nv_init(void) | 609 | static int __init nv_init(void) |