diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2009-10-02 12:45:59 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2009-10-02 12:45:59 +1000 |
commit | 862e23f59a1838846f3254cd25f26868812db9d9 (patch) | |
tree | ecf7b3073d02e199dad8996a5953fc0fe4f2b732 | |
parent | 295cf4ace24c534d653d478335a4d0c4d8140650 (diff) | |
parent | 15addcb9e65e9b7a9df5978ee7f105ce2afee257 (diff) |
Merge remote branch 'scsi-post-merge/master'
Conflicts:
MAINTAINERS
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe.h
drivers/scsi/libfc/fc_elsct.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/pmcraid.c
drivers/scsi/pmcraid.h
include/scsi/fc_encode.h
include/scsi/libfc.h
kernel/sysctl.c
-rw-r--r-- | drivers/ata/ahci.c | 54 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.c | 99 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 78 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 5 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 36 | ||||
-rw-r--r-- | include/linux/libata.h | 2 |
8 files changed, 206 insertions, 72 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index acd1162712b1..a8f830f0cef3 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -45,6 +45,7 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> #include <linux/libata.h> +#include <linux/blk-iopoll.h> #define DRV_NAME "ahci" #define DRV_VERSION "3.0" @@ -2114,7 +2115,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) ata_port_abort(ap); } -static void ahci_port_intr(struct ata_port *ap) +static int ahci_port_intr(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); struct ata_eh_info *ehi = &ap->link.eh_info; @@ -2144,7 +2145,7 @@ static void ahci_port_intr(struct ata_port *ap) if (unlikely(status & PORT_IRQ_ERROR)) { ahci_error_intr(ap, status); - return; + return 0; } if (status & PORT_IRQ_SDB_FIS) { @@ -2185,7 +2186,43 @@ static void ahci_port_intr(struct ata_port *ap) ehi->err_mask |= AC_ERR_HSM; ehi->action |= ATA_EH_RESET; ata_port_freeze(ap); + rc = 0; + } + + return rc; +} + +static void ap_irq_disable(struct ata_port *ap) +{ + void __iomem *port_mmio = ahci_port_base(ap); + + writel(0, port_mmio + PORT_IRQ_MASK); +} + +static void ap_irq_enable(struct ata_port *ap) +{ + void __iomem *port_mmio = ahci_port_base(ap); + struct ahci_port_priv *pp = ap->private_data; + + writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); +} + +static int ahci_iopoll(struct blk_iopoll *iop, int budget) +{ + struct ata_port *ap = container_of(iop, struct ata_port, iopoll); + unsigned long flags; + int ret; + + spin_lock_irqsave(&ap->host->lock, flags); + ret = ahci_port_intr(ap); + spin_unlock_irqrestore(&ap->host->lock, flags); + + if (ret < budget) { + blk_iopoll_complete(iop); + ap_irq_enable(ap); } + + return ret; } static irqreturn_t ahci_interrupt(int irq, void *dev_instance) @@ -2218,7 +2255,12 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) ap = host->ports[i]; if (ap) { - ahci_port_intr(ap); + if (!blk_iopoll_enabled) + ahci_port_intr(ap); + else if (!blk_iopoll_sched_prep(&ap->iopoll)) { + ap_irq_disable(ap); + blk_iopoll_sched(&ap->iopoll); + } VPRINTK("port %u\n", i); } else { VPRINTK("port %u (no irq)\n", i); @@ -2352,6 +2394,8 @@ static void ahci_pmp_detach(struct ata_port *ap) static int ahci_port_resume(struct ata_port *ap) { + blk_iopoll_enable(&ap->iopoll); + ahci_power_up(ap); ahci_start_port(ap); @@ -2482,6 +2526,8 @@ static int ahci_port_start(struct ata_port *ap) ap->private_data = pp; + blk_iopoll_init(&ap->iopoll, 32, ahci_iopoll); + /* engage engines, captain */ return ahci_port_resume(ap); } @@ -2495,6 +2541,8 @@ static void ahci_port_stop(struct ata_port *ap) rc = ahci_deinit_port(ap, &emsg); if (rc) ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc); + + blk_iopoll_disable(&ap->iopoll); } static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 610e914abe6c..33d8bac31847 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -114,6 +114,9 @@ module_param_call(mpt_fwfault_debug, param_set_int, param_get_int, MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault" " and halt Firmware on fault - (default=0)"); +static int mpt_iopoll_w = 32; +module_param(mpt_iopoll_w, int, 0); +MODULE_PARM_DESC(mpt_iopoll_w, " blk iopoll budget (default=32"); #ifdef MFCNT @@ -515,6 +518,44 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) mb(); } +static void mpt_irq_disable(MPT_ADAPTER *ioc) +{ + CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + CHIPREG_READ32(&ioc->chip->IntStatus); +} + +static void mpt_irq_enable(MPT_ADAPTER *ioc) +{ + CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); +} + +static inline void __mpt_handle_irq(MPT_ADAPTER *ioc, u32 pa) +{ + if (pa & MPI_ADDRESS_REPLY_A_BIT) + mpt_reply(ioc, pa); + else + mpt_turbo_reply(ioc, pa); +} + +static int mpt_handle_irq(MPT_ADAPTER *ioc, unsigned int budget) +{ + int nr = 0; + u32 pa; + + /* + * Drain the reply FIFO! + */ + while ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) != 0xffffffff) { + nr++; + __mpt_handle_irq(ioc, pa); + if (nr == budget) + break; + } + + return nr; +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. @@ -536,23 +577,48 @@ static irqreturn_t mpt_interrupt(int irq, void *bus_id) { MPT_ADAPTER *ioc = bus_id; - u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); + int nr = 0; + + if (!blk_iopoll_enabled) + nr = mpt_handle_irq(ioc, -1U); + else if (!blk_iopoll_sched_prep(&ioc->iopoll)) { + mpt_irq_disable(ioc); + ioc->iopoll.data =CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); + blk_iopoll_sched(&ioc->iopoll); + nr = 1; + } else { + /* + * Not really handled, but it will be by iopoll. + */ + nr = 1; + } - if (pa == 0xFFFFFFFF) - return IRQ_NONE; + if (nr) + return IRQ_HANDLED; - /* - * Drain the reply FIFO! - */ - do { - if (pa & MPI_ADDRESS_REPLY_A_BIT) - mpt_reply(ioc, pa); - else - mpt_turbo_reply(ioc, pa); - pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); - } while (pa != 0xFFFFFFFF); + return IRQ_NONE; +} - return IRQ_HANDLED; +static int mpt_iopoll(struct blk_iopoll *iop, int budget) +{ + MPT_ADAPTER *ioc = container_of(iop, MPT_ADAPTER, iopoll); + int ret = 0; + u32 pa; + + pa = iop->data; + iop->data = 0xffffffff; + if (pa != 0xffffffff) { + __mpt_handle_irq(ioc, pa); + ret = 1; + } + + ret += mpt_handle_irq(ioc, budget - ret); + if (ret < budget) { + blk_iopoll_complete(iop); + mpt_irq_enable(ioc); + } + + return ret; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2087,6 +2153,7 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state) /* Clear any lingering interrupt */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + blk_iopoll_disable(&ioc->iopoll); free_irq(ioc->pci_irq, ioc); if (ioc->msi_enable) pci_disable_msi(ioc->pcidev); @@ -2352,6 +2419,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ret = -EBUSY; goto out; } + blk_iopoll_init(&ioc->iopoll, mpt_iopoll_w, mpt_iopoll); + blk_iopoll_enable(&ioc->iopoll); irq_allocated = 1; ioc->pci_irq = ioc->pcidev->irq; pci_set_master(ioc->pcidev); /* ?? */ @@ -2544,6 +2613,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) out: if ((ret != 0) && irq_allocated) { + blk_iopoll_disable(&ioc->iopoll); free_irq(ioc->pci_irq, ioc); if (ioc->msi_enable) pci_disable_msi(ioc->pcidev); @@ -2752,6 +2822,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) mpt_adapter_disable(ioc); if (ioc->pci_irq != -1) { + blk_iopoll_disable(&ioc->iopoll); free_irq(ioc->pci_irq, ioc); if (ioc->msi_enable) pci_disable_msi(ioc->pcidev); diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 8dd4d219e433..eb000e07e03e 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -52,6 +52,7 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/mutex.h> +#include <linux/blk-iopoll.h> #include "lsi/mpi_type.h" #include "lsi/mpi.h" /* Fusion MPI(nterface) basic defs */ @@ -764,6 +765,8 @@ typedef struct _MPT_ADAPTER struct workqueue_struct *reset_work_q; struct delayed_work fault_reset_work; + struct blk_iopoll iopoll; + u8 sg_addr_size; u8 in_rescan; u8 SGE_size; diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index cca8e4ab0372..cb2eca4c26d8 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -377,6 +377,24 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) return ptr + sizeof(struct qla2xxx_mq_chain); } +static void +qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval) +{ + struct qla_hw_data *ha = vha->hw; + + if (rval != QLA_SUCCESS) { + qla_printk(KERN_WARNING, ha, + "Failed to dump firmware (%x)!!!\n", rval); + ha->fw_dumped = 0; + } else { + qla_printk(KERN_INFO, ha, + "Firmware dump saved to temp buffer (%ld/%p).\n", + vha->host_no, ha->fw_dump); + ha->fw_dumped = 1; + qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP); + } +} + /** * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. * @ha: HA context @@ -530,17 +548,7 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) if (rval == QLA_SUCCESS) qla2xxx_copy_queues(ha, nxt); - if (rval != QLA_SUCCESS) { - qla_printk(KERN_WARNING, ha, - "Failed to dump firmware (%x)!!!\n", rval); - ha->fw_dumped = 0; - - } else { - qla_printk(KERN_INFO, ha, - "Firmware dump saved to temp buffer (%ld/%p).\n", - base_vha->host_no, ha->fw_dump); - ha->fw_dumped = 1; - } + qla2xxx_dump_post_process(base_vha, rval); qla2300_fw_dump_failed: if (!hardware_locked) @@ -737,17 +745,7 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) if (rval == QLA_SUCCESS) qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]); - if (rval != QLA_SUCCESS) { - qla_printk(KERN_WARNING, ha, - "Failed to dump firmware (%x)!!!\n", rval); - ha->fw_dumped = 0; - - } else { - qla_printk(KERN_INFO, ha, - "Firmware dump saved to temp buffer (%ld/%p).\n", - base_vha->host_no, ha->fw_dump); - ha->fw_dumped = 1; - } + qla2xxx_dump_post_process(base_vha, rval); qla2100_fw_dump_failed: if (!hardware_locked) @@ -984,17 +982,7 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) qla24xx_copy_eft(ha, nxt); qla24xx_fw_dump_failed_0: - if (rval != QLA_SUCCESS) { - qla_printk(KERN_WARNING, ha, - "Failed to dump firmware (%x)!!!\n", rval); - ha->fw_dumped = 0; - - } else { - qla_printk(KERN_INFO, ha, - "Firmware dump saved to temp buffer (%ld/%p).\n", - base_vha->host_no, ha->fw_dump); - ha->fw_dumped = 1; - } + qla2xxx_dump_post_process(base_vha, rval); qla24xx_fw_dump_failed: if (!hardware_locked) @@ -1305,17 +1293,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) } qla25xx_fw_dump_failed_0: - if (rval != QLA_SUCCESS) { - qla_printk(KERN_WARNING, ha, - "Failed to dump firmware (%x)!!!\n", rval); - ha->fw_dumped = 0; - - } else { - qla_printk(KERN_INFO, ha, - "Firmware dump saved to temp buffer (%ld/%p).\n", - base_vha->host_no, ha->fw_dump); - ha->fw_dumped = 1; - } + qla2xxx_dump_post_process(base_vha, rval); qla25xx_fw_dump_failed: if (!hardware_locked) @@ -1628,17 +1606,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) } qla81xx_fw_dump_failed_0: - if (rval != QLA_SUCCESS) { - qla_printk(KERN_WARNING, ha, - "Failed to dump firmware (%x)!!!\n", rval); - ha->fw_dumped = 0; - - } else { - qla_printk(KERN_INFO, ha, - "Firmware dump saved to temp buffer (%ld/%p).\n", - base_vha->host_no, ha->fw_dump); - ha->fw_dumped = 1; - } + qla2xxx_dump_post_process(base_vha, rval); qla81xx_fw_dump_failed: if (!hardware_locked) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 215061861794..d8ce31040b51 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2123,6 +2123,7 @@ enum qla_work_type { QLA_EVT_ASYNC_LOGIN_DONE, QLA_EVT_ASYNC_LOGOUT, QLA_EVT_ASYNC_LOGOUT_DONE, + QLA_EVT_UEVENT, }; @@ -2146,6 +2147,10 @@ struct qla_work_evt { #define QLA_LOGIO_LOGIN_RETRIED BIT_0 u16 data[2]; } logio; + struct { + u32 code; +#define QLA_UEVENT_CODE_FW_DUMP 0 + } uevent; } u; }; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f3d1d1afa95b..14e0562851cb 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -92,6 +92,7 @@ extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *, fc_port_t *, uint16_t *); +extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b79fca7d461b..64ff1470e184 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/kthread.h> #include <linux/mutex.h> +#include <linux/kobject.h> #include <scsi/scsi_tcq.h> #include <scsi/scsicam.h> @@ -2653,6 +2654,38 @@ qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE); qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); +int +qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code) +{ + struct qla_work_evt *e; + + e = qla2x00_alloc_work(vha, QLA_EVT_UEVENT); + if (!e) + return QLA_FUNCTION_FAILED; + + e->u.uevent.code = code; + return qla2x00_post_work(vha, e); +} + +static void +qla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code) +{ + char event_string[40]; + char *envp[] = { event_string, NULL }; + + switch (code) { + case QLA_UEVENT_CODE_FW_DUMP: + snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld", + vha->host_no); + break; + default: + /* do nothing */ + break; + } + kobject_uevent_env(&(&vha->hw->pdev->driver->driver)->owner->mkobj.kobj, + KOBJ_CHANGE, envp); +} + void qla2x00_do_work(struct scsi_qla_host *vha) { @@ -2690,6 +2723,9 @@ qla2x00_do_work(struct scsi_qla_host *vha) qla2x00_async_logout_done(vha, e->u.logio.fcport, e->u.logio.data); break; + case QLA_EVT_UEVENT: + qla2x00_uevent_emit(vha, e->u.uevent.code); + break; } if (e->flags & QLA_EVT_FLAG_FREE) kfree(e); diff --git a/include/linux/libata.h b/include/linux/libata.h index 76319bf03e37..5bdd34433d8e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -37,6 +37,7 @@ #include <scsi/scsi_host.h> #include <linux/acpi.h> #include <linux/cdrom.h> +#include <linux/blk-iopoll.h> /* * Define if arch has non-standard setup. This is a _PCI_ standard @@ -763,6 +764,7 @@ struct ata_port { #endif /* owned by EH */ u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; + struct blk_iopoll iopoll; }; /* The following initializer overrides a method to NULL whether one of |