From d8d1f30b95a635dbd610dcc5eb641aca8f4768cf Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Thu, 10 Jun 2010 23:31:35 -0700 Subject: net-next: remove useless union keyword remove useless union keyword in rtable, rt6_info and dn_route. Since there is only one member in a union, the union keyword isn't useful. Signed-off-by: Changli Gao Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/scsi/cxgb3i/cxgb3i_offload.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index a175be9c496f..3b6a06eebf7f 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c @@ -1587,7 +1587,7 @@ cxgb3i_find_dev(struct net_device *dev, __be32 ipaddr) err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl); if (!err) - return (&rt->u.dst)->dev; + return (&rt->dst)->dev; return NULL; } @@ -1649,7 +1649,7 @@ int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn, c3cn->saddr.sin_addr.s_addr = rt->rt_src; /* now commit destination to connection */ - c3cn->dst_cache = &rt->u.dst; + c3cn->dst_cache = &rt->dst; /* try to establish an offloaded connection */ dev = cxgb3_egress_dev(c3cn->dst_cache->dev, c3cn, 0); -- cgit v1.2.3 From 732bee7af3102cad811fb047dee8d15966efe569 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 11 Jun 2010 12:16:59 +0200 Subject: fix typos concerning "hierarchy" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Jiri Kosina --- arch/arm/mach-omap2/dpll3xxx.c | 2 +- arch/microblaze/Makefile | 2 +- drivers/infiniband/hw/cxgb3/iwch_qp.c | 4 ++-- drivers/infiniband/hw/cxgb4/qp.c | 4 ++-- drivers/scsi/libfc/fc_lport.c | 6 +++--- drivers/scsi/libfc/fc_rport.c | 2 +- drivers/scsi/scsi_transport_fc.c | 2 +- kernel/cpuset.c | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/scsi') diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index b32ccd954a1b..ed8d330522f1 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -463,7 +463,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) } if (!ret) { /* - * Switch the parent clock in the heirarchy, and make sure + * Switch the parent clock in the hierarchy, and make sure * that the new parent's usecount is correct. Note: we * enable the new parent before disabling the old to avoid * any unnecessary hardware disable->enable transitions. diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 72f6e8583746..592c7079de88 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile @@ -25,7 +25,7 @@ ifeq (,$(findstring spartan2,$(CONFIG_XILINX_MICROBLAZE0_FAMILY))) ifeq ($(CPU_MAJOR),3) CPUFLAGS-1 += -mno-xl-soft-mul else - # USE_HW_MUL can be 0, 1, or 2, defining a heirarchy of HW Mul support. + # USE_HW_MUL can be 0, 1, or 2, defining a hierarchy of HW Mul support. CPUFLAGS-$(subst 1,,$(CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL)) += -mxl-multiply-high CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL) += -mno-xl-soft-mul endif diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index ae47bfd22bd5..9bbb65bba67e 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c @@ -816,7 +816,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag) atomic_inc(&qhp->refcnt); spin_unlock_irqrestore(&qhp->lock, *flag); - /* locking heirarchy: cq lock first, then qp lock. */ + /* locking hierarchy: cq lock first, then qp lock. */ spin_lock_irqsave(&rchp->lock, *flag); spin_lock(&qhp->lock); cxio_flush_hw_cq(&rchp->cq); @@ -827,7 +827,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag) if (flushed) (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); - /* locking heirarchy: cq lock first, then qp lock. */ + /* locking hierarchy: cq lock first, then qp lock. */ spin_lock_irqsave(&schp->lock, *flag); spin_lock(&qhp->lock); cxio_flush_hw_cq(&schp->cq); diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 83a01dc0c4c1..b321835dcf6e 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -899,7 +899,7 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp, atomic_inc(&qhp->refcnt); spin_unlock_irqrestore(&qhp->lock, *flag); - /* locking heirarchy: cq lock first, then qp lock. */ + /* locking hierarchy: cq lock first, then qp lock. */ spin_lock_irqsave(&rchp->lock, *flag); spin_lock(&qhp->lock); c4iw_flush_hw_cq(&rchp->cq); @@ -910,7 +910,7 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp, if (flushed) (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); - /* locking heirarchy: cq lock first, then qp lock. */ + /* locking hierarchy: cq lock first, then qp lock. */ spin_lock_irqsave(&schp->lock, *flag); spin_lock(&qhp->lock); c4iw_flush_hw_cq(&schp->cq); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 79c9e3ccd341..ef32b065a47f 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -32,11 +32,11 @@ * invalid SID. We also need to ensure that states don't change unexpectedly * while processing another state. * - * HEIRARCHY + * HIERARCHY * - * The following heirarchy defines the locking rules. A greater lock + * The following hierarchy defines the locking rules. A greater lock * may be held before acquiring a lesser lock, but a lesser lock should never - * be held while attempting to acquire a greater lock. Here is the heirarchy- + * be held while attempting to acquire a greater lock. Here is the hierarchy- * * lport > disc, lport > rport, disc > rport * diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 39e440f0f54a..2aa599340106 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -34,7 +34,7 @@ * The rport should never hold the rport mutex and then attempt to acquire * either the lport or disc mutexes. The rport's mutex is considered lesser * than both the lport's mutex and the disc mutex. Refer to fc_lport.c for - * more comments on the heirarchy. + * more comments on the hierarchy. * * The locking strategy is similar to the lport's strategy. The lock protects * the rport's states and is held and released by the entry points to the rport diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 06813789145c..edb6b362a8fa 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -965,7 +965,7 @@ static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR, /* * Note: in the target show function we recognize when the remote - * port is in the heirarchy and do not allow the driver to get + * port is in the hierarchy and do not allow the driver to get * involved in sysfs functions. The driver only gets involved if * it's the "old" style that doesn't use rports. */ diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 9a50c5f6e727..1a109788592f 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -105,7 +105,7 @@ struct cpuset { /* for custom sched domain */ int relax_domain_level; - /* used for walking a cpuset heirarchy */ + /* used for walking a cpuset hierarchy */ struct list_head stack_list; }; -- cgit v1.2.3 From 65155b3708137fabee865dc4da822763c0c41208 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 11 Jun 2010 12:17:01 +0200 Subject: fix typos concerning "management" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Jiri Kosina --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 2 +- drivers/media/dvb/siano/smscoreapi.c | 2 +- drivers/net/benet/be_hw.h | 2 +- drivers/scsi/fcoe/fcoe.c | 4 ++-- drivers/scsi/mpt2sas/mpt2sas_base.h | 2 +- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 4 ++-- drivers/scsi/pm8001/pm8001_hwi.c | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 2 +- drivers/scsi/qla2xxx/qla_nx.h | 2 +- include/linux/ide.h | 2 +- include/linux/if_link.h | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index f8fbbc67a406..7745394c3e63 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1013,7 +1013,7 @@ int vmw_gmr_id_alloc(struct vmw_private *dev_priv, uint32_t *p_id) } /* - * Stream managment + * Stream management */ static void vmw_stream_destroy(struct vmw_resource *res) diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index 0c87a3c3899a..a19f649666d5 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c @@ -1297,7 +1297,7 @@ int smsclient_sendrequest(struct smscore_client_t *client, EXPORT_SYMBOL_GPL(smsclient_sendrequest); -/* old GPIO managments implementation */ +/* old GPIO managements implementation */ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, struct smscore_config_gpio *pinconfig) { diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 063026de4957..3f1b7c3965bb 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -52,7 +52,7 @@ */ #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ -/********* Power managment (WOL) **********/ +/********* Power management (WOL) **********/ #define PCICFG_PM_CONTROL_OFFSET 0x44 #define PCICFG_PM_CONTROL_MASK 0x108 /* bits 3 & 8 */ diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 9276121db1ef..bc39542481a4 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2452,7 +2452,7 @@ module_exit(fcoe_exit); * @fp: response frame, or error encoded in a pointer (timeout) * @arg: pointer the the fcoe_ctlr structure * - * This handles MAC address managment for FCoE, then passes control on to + * This handles MAC address management for FCoE, then passes control on to * the libfc FLOGI response handler. */ static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) @@ -2484,7 +2484,7 @@ done: * @fp: response frame, or error encoded in a pointer (timeout) * @arg: pointer the the fcoe_ctlr structure * - * This handles MAC address managment for FCoE, then passes control on to + * This handles MAC address management for FCoE, then passes control on to * the libfc LOGO response handler. */ static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index b4afe431ac1e..41c29a86e834 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -474,7 +474,7 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); * @shost_recovery: host reset in progress * @ioc_reset_in_progress_lock: * @ioc_link_reset_in_progress: phy/hard reset in progress - * @ignore_loginfos: ignore loginfos during task managment + * @ignore_loginfos: ignore loginfos during task management * @remove_host: flag for when driver unloads, to avoid sending dev resets * @wait_for_port_enable_to_complete: * @msix_enable: flag indicating msix is enabled diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index c5ff26a2a51d..06d645a36f1b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2979,7 +2979,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) /* host recovery or link resets sent via IOCTLs */ if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) return SCSI_MLQUEUE_HOST_BUSY; - /* device busy with task managment */ + /* device busy with task management */ else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy) return SCSI_MLQUEUE_DEVICE_BUSY; /* device has been deleted */ @@ -6845,7 +6845,7 @@ _scsih_init(void) /* queuecommand callback hander */ scsi_io_cb_idx = mpt2sas_base_register_callback_handler(_scsih_io_done); - /* task managment callback handler */ + /* task management callback handler */ tm_cb_idx = mpt2sas_base_register_callback_handler(_scsih_tm_done); /* base internal commands callback handler */ diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 5ff8261c5d67..0e05e8a22167 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -4152,7 +4152,7 @@ static int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, } /** - * pm8001_chip_ssp_tm_req - built the task managment command. + * pm8001_chip_ssp_tm_req - built the task management command. * @pm8001_ha: our hba card information. * @ccb: the ccb information. * @tmf: task management function. diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 8ef945365412..782b30d0eea1 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1129,7 +1129,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32( MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF)); fcp_cmnd->task_attribute = 0; - fcp_cmnd->task_managment = 0; + fcp_cmnd->task_management = 0; cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */ diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index f8f99a5ea532..1b44d013f151 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -832,7 +832,7 @@ struct fcp_cmnd { struct scsi_lun lun; uint8_t crn; uint8_t task_attribute; - uint8_t task_managment; + uint8_t task_management; uint8_t additional_cdb_len; uint8_t cdb[260]; /* 256 for CDB len and 4 for FCP_DL */ }; diff --git a/include/linux/ide.h b/include/linux/ide.h index 3239d1c10acb..c2c598ed4eed 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -458,7 +458,7 @@ enum { IDE_DFLAG_DOORLOCKING = (1 << 15), /* disallow DMA */ IDE_DFLAG_NODMA = (1 << 16), - /* powermanagment told us not to do anything, so sleep nicely */ + /* powermanagement told us not to do anything, so sleep nicely */ IDE_DFLAG_BLOCKED = (1 << 17), /* sleeping & sleep field valid */ IDE_DFLAG_SLEEPING = (1 << 18), diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 85c812db5a3f..9d8f0807daed 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -233,7 +233,7 @@ enum macvlan_mode { MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ }; -/* SR-IOV virtual function managment section */ +/* SR-IOV virtual function management section */ enum { IFLA_VF_INFO_UNSPEC, -- cgit v1.2.3 From 421f91d21ad6f799dc7b489bb33cc560ccc56f98 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 11 Jun 2010 12:17:00 +0200 Subject: fix typos concerning "initiali[zs]e" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Jiri Kosina --- arch/arm/mach-msm/acpuclock-arm11.c | 4 ++-- arch/arm/mach-u300/gpio.c | 2 +- arch/arm/plat-s3c24xx/clock.c | 2 +- arch/arm/plat-samsung/clock.c | 2 +- arch/h8300/kernel/timer/itu.c | 2 +- arch/h8300/kernel/timer/timer16.c | 2 +- arch/h8300/kernel/timer/timer8.c | 2 +- arch/ia64/kvm/kvm-ia64.c | 6 +++--- arch/ia64/sn/kernel/setup.c | 2 +- arch/sparc/boot/btfixupprep.c | 4 ++-- arch/x86/kernel/apic/apic.c | 2 +- arch/x86/kernel/head32.c | 2 +- drivers/crypto/amcc/crypto4xx_reg_def.h | 2 +- drivers/dma/at_hdmac.c | 2 +- drivers/gpu/drm/savage/savage_bci.c | 2 +- drivers/ide/ide-gd.c | 2 +- drivers/infiniband/hw/ehca/hcp_if.h | 2 +- drivers/input/misc/ad714x.c | 2 +- drivers/media/video/ov511.c | 2 +- drivers/media/video/zoran/zoran.h | 2 +- drivers/media/video/zoran/zr36050.c | 2 +- drivers/media/video/zoran/zr36060.c | 2 +- drivers/message/fusion/mptbase.c | 4 ++-- drivers/mtd/nand/denali.c | 2 +- drivers/net/3c527.c | 4 ++-- drivers/net/appletalk/ipddp.c | 2 +- drivers/net/hp100.c | 2 +- drivers/net/ibm_newemac/core.c | 2 +- drivers/net/ksz884x.c | 2 +- drivers/net/ll_temac_main.c | 2 +- drivers/net/tulip/dmfe.c | 20 ++++++++++---------- drivers/net/wimax/i2400m/control.c | 2 +- drivers/parisc/ccio-dma.c | 4 ++-- drivers/pcmcia/sa11xx_base.c | 2 +- drivers/scsi/advansys.c | 2 +- drivers/scsi/aic94xx/aic94xx_seq.c | 4 ++-- drivers/scsi/bfa/vport.c | 2 +- drivers/scsi/pm8001/pm8001_hwi.c | 2 +- drivers/scsi/qla4xxx/ql4_init.c | 2 +- drivers/serial/sn_console.c | 6 +++--- drivers/staging/comedi/drivers/usbdux.c | 2 +- drivers/staging/octeon/cvmx-cmd-queue.c | 6 +++--- drivers/staging/pohmelfs/inode.c | 2 +- drivers/staging/rt2860/common/cmm_wpa.c | 4 ++-- drivers/staging/rtl8192e/r8190_rtl8256.c | 6 +++--- drivers/usb/serial/kl5kusb105.c | 2 +- drivers/usb/wusbcore/wusbhc.c | 2 +- drivers/uwb/wlp/wss-lc.c | 2 +- drivers/video/carminefb.c | 2 +- drivers/video/tgafb.c | 2 +- fs/befs/linuxvfs.c | 2 +- fs/ecryptfs/crypto.c | 2 +- fs/ext4/extents.c | 2 +- fs/ext4/super.c | 2 +- fs/freevxfs/vxfs_super.c | 2 +- fs/ocfs2/super.c | 2 +- fs/reiserfs/inode.c | 2 +- lib/random32.c | 2 +- net/netfilter/ipvs/ip_vs_lblc.c | 2 +- net/netfilter/ipvs/ip_vs_lblcr.c | 2 +- net/sctp/associola.c | 2 +- net/sctp/protocol.c | 2 +- security/smack/smack_lsm.c | 2 +- sound/pci/trident/trident_main.c | 2 +- sound/soc/fsl/mpc8610_hpcd.c | 2 +- sound/soc/soc-core.c | 2 +- 66 files changed, 90 insertions(+), 90 deletions(-) (limited to 'drivers/scsi') diff --git a/arch/arm/mach-msm/acpuclock-arm11.c b/arch/arm/mach-msm/acpuclock-arm11.c index af5e85b91d02..f060a3959a75 100644 --- a/arch/arm/mach-msm/acpuclock-arm11.c +++ b/arch/arm/mach-msm/acpuclock-arm11.c @@ -98,7 +98,7 @@ struct clkctl_acpu_speed { /* * ACPU speed table. Complete table is shown but certain speeds are commented - * out to optimized speed switching. Initalize loops_per_jiffy to 0. + * out to optimized speed switching. Initialize loops_per_jiffy to 0. * * Table stepping up/down is optimized for 256mhz jumps while staying on the * same PLL. @@ -494,7 +494,7 @@ uint32_t acpuclk_get_switch_time(void) * Clock driver initialization *---------------------------------------------------------------------------*/ -/* Initalize the lpj field in the acpu_freq_tbl. */ +/* Initialize the lpj field in the acpu_freq_tbl. */ static void __init lpj_init(void) { int i; diff --git a/arch/arm/mach-u300/gpio.c b/arch/arm/mach-u300/gpio.c index 5f61fd45a0c8..d92790140fe5 100644 --- a/arch/arm/mach-u300/gpio.c +++ b/arch/arm/mach-u300/gpio.c @@ -523,7 +523,7 @@ static void gpio_set_initial_values(void) /* * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED' - * to output and 'GPIO_IN' to input for each port. And initalize + * to output and 'GPIO_IN' to input for each port. And initialize * default value on outputs. */ for (i = 0; i < U300_GPIO_NUM_PORTS; i++) { diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c index 8474d05274bd..931d26d1a54b 100644 --- a/arch/arm/plat-s3c24xx/clock.c +++ b/arch/arm/plat-s3c24xx/clock.c @@ -43,7 +43,7 @@ #include #include -/* initalise all the clocks */ +/* initialise all the clocks */ void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, unsigned long hclk, diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c index 8bf79f3efdfb..90a20512d68d 100644 --- a/arch/arm/plat-samsung/clock.c +++ b/arch/arm/plat-samsung/clock.c @@ -391,7 +391,7 @@ void __init s3c_disable_clocks(struct clk *clkp, int nr_clks) (clkp->enable)(clkp, 0); } -/* initalise all the clocks */ +/* initialise all the clocks */ int __init s3c24xx_register_baseclocks(unsigned long xtal) { diff --git a/arch/h8300/kernel/timer/itu.c b/arch/h8300/kernel/timer/itu.c index 4883ba7103a8..a2ae5e952137 100644 --- a/arch/h8300/kernel/timer/itu.c +++ b/arch/h8300/kernel/timer/itu.c @@ -73,7 +73,7 @@ void __init h8300_timer_setup(void) setup_irq(ITUIRQ, &itu_irq); - /* initalize timer */ + /* initialize timer */ ctrl_outb(0, TSTR); ctrl_outb(CCLR0 | div, ITUBASE + TCR); ctrl_outb(0x01, ITUBASE + TIER); diff --git a/arch/h8300/kernel/timer/timer16.c b/arch/h8300/kernel/timer/timer16.c index 042dbb53f3fb..ae0d38161139 100644 --- a/arch/h8300/kernel/timer/timer16.c +++ b/arch/h8300/kernel/timer/timer16.c @@ -68,7 +68,7 @@ void __init h8300_timer_setup(void) setup_irq(_16IRQ, &timer16_irq); - /* initalize timer */ + /* initialize timer */ ctrl_outb(0, TSTR); ctrl_outb(CCLR0 | div, _16BASE + TCR); ctrl_outw(cnt, _16BASE + GRA); diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c index 38be0cabef0d..3946c0fa8374 100644 --- a/arch/h8300/kernel/timer/timer8.c +++ b/arch/h8300/kernel/timer/timer8.c @@ -94,7 +94,7 @@ void __init h8300_timer_setup(void) ctrl_bclr(0, MSTPCRL) #endif - /* initalize timer */ + /* initialize timer */ ctrl_outw(cnt, _8BASE + TCORA); ctrl_outw(0x0000, _8BASE + _8TCSR); ctrl_outw((CMIEA|CCLR_CMA|CKS2) << 8 | div, diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 7f3c0a2e60cd..29afd9a252ff 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -1234,7 +1234,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) p_ctx->cr[2] = (unsigned long)kvm_vmm_info->vmm_ivt; p_ctx->cr[8] = 0x3c; - /*Initilize region register*/ + /*Initialize region register*/ p_ctx->rr[0] = 0x30; p_ctx->rr[1] = 0x30; p_ctx->rr[2] = 0x30; @@ -1243,7 +1243,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) p_ctx->rr[5] = 0x30; p_ctx->rr[7] = 0x30; - /*Initilize branch register 0*/ + /*Initialize branch register 0*/ p_ctx->br[0] = *(unsigned long *)kvm_vmm_info->vmm_entry; vcpu->arch.vmm_rr = kvm->arch.vmm_init_rr; @@ -1702,7 +1702,7 @@ static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info, BUG_ON(!module); if (!kvm_vmm_base) { - printk("kvm: kvm area hasn't been initilized yet!!\n"); + printk("kvm: kvm area hasn't been initialized yet!!\n"); return -EFAULT; } diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index d00dfc180021..dbc4cbecb5ed 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -507,7 +507,7 @@ static void __init sn_init_pdas(char **cmdline_p) cnodeid_t cnode; /* - * Allocate & initalize the nodepda for each node. + * Allocate & initialize the nodepda for each node. */ for_each_online_node(cnode) { nodepdaindr[cnode] = diff --git a/arch/sparc/boot/btfixupprep.c b/arch/sparc/boot/btfixupprep.c index bbf91b9c3d39..b60491102237 100644 --- a/arch/sparc/boot/btfixupprep.c +++ b/arch/sparc/boot/btfixupprep.c @@ -216,7 +216,7 @@ main1: switch (buffer[nbase+3]) { case 'f': if (initval) { - fprintf(stderr, "Cannot use pre-initalized fixups for calls\n%s\n", buffer); + fprintf(stderr, "Cannot use pre-initialized fixups for calls\n%s\n", buffer); exit(1); } if (!strcmp (sect, "__ksymtab")) { @@ -273,7 +273,7 @@ main1: break; case 'i': if (initval) { - fprintf(stderr, "Cannot use pre-initalized fixups for INT\n%s\n", buffer); + fprintf(stderr, "Cannot use pre-initialized fixups for INT\n%s\n", buffer); exit(1); } if (strncmp (buffer + mode+9, "HI22 ", 10) && strncmp (buffer + mode+9, "LO10 ", 10)) { diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index e5a4a1e01618..192cd7ee35cc 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -459,7 +459,7 @@ static void lapic_timer_broadcast(const struct cpumask *mask) } /* - * Setup the local APIC timer for this CPU. Copy the initilized values + * Setup the local APIC timer for this CPU. Copy the initialized values * of the boot CPU and register the clock event in the framework. */ static void __cpuinit setup_APIC_timer(void) diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index b2e246037392..784360c0625c 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -20,7 +20,7 @@ static void __init i386_default_early_setup(void) { - /* Initilize 32bit specific setup functions */ + /* Initialize 32bit specific setup functions */ x86_init.resources.probe_roms = probe_roms; x86_init.resources.reserve_resources = i386_reserve_resources; x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc; diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h index 7d4edb002619..5f5fbc0716ff 100644 --- a/drivers/crypto/amcc/crypto4xx_reg_def.h +++ b/drivers/crypto/amcc/crypto4xx_reg_def.h @@ -113,7 +113,7 @@ #define CRYPTO4XX_PRNG_LFSR_H 0x00070034 /** - * Initilize CRYPTO ENGINE registers, and memory bases. + * Initialize CRYPTO ENGINE registers, and memory bases. */ #define PPC4XX_PDR_POLL 0x3ff #define PPC4XX_OUTPUT_THRESHOLD 2 diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 278cf5bceef2..308ab320e20b 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -69,7 +69,7 @@ static struct at_desc *atc_first_queued(struct at_dma_chan *atchan) } /** - * atc_alloc_descriptor - allocate and return an initilized descriptor + * atc_alloc_descriptor - allocate and return an initialized descriptor * @chan: the channel to allocate descriptors for * @gfp_flags: GFP allocation flags * diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index 2d0c9ca484c5..fa05cda8c98f 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -552,7 +552,7 @@ int savage_driver_load(struct drm_device *dev, unsigned long chipset) /* - * Initalize mappings. On Savage4 and SavageIX the alignment + * Initialize mappings. On Savage4 and SavageIX the alignment * and size of the aperture is not suitable for automatic MTRR setup * in drm_addmap. Therefore we add them manually before the maps are * initialized, and tear them down on last close. diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index c32d83996ae1..27d9fe08d80b 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c @@ -92,7 +92,7 @@ static void ide_disk_release(struct device *dev) /* * On HPA drives the capacity needs to be - * reinitilized on resume otherwise the disk + * reinitialized on resume otherwise the disk * can not be used and a hard reset is required */ static void ide_gd_resume(ide_drive_t *drive) diff --git a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h index 39c1c3618ec7..a46e514c367b 100644 --- a/drivers/infiniband/hw/ehca/hcp_if.h +++ b/drivers/infiniband/hw/ehca/hcp_if.h @@ -49,7 +49,7 @@ #include "hipz_hw.h" /* - * hipz_h_alloc_resource_eq allocates EQ resources in HW and FW, initalize + * hipz_h_alloc_resource_eq allocates EQ resources in HW and FW, initialize * resources, create the empty EQPT (ring). */ u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c index 0fe27baf5e72..c431d09e401a 100644 --- a/drivers/input/misc/ad714x.c +++ b/drivers/input/misc/ad714x.c @@ -1118,7 +1118,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, if (error) goto err_free_mem; - /* initilize and request sw/hw resources */ + /* initialize and request sw/hw resources */ ad714x_hw_init(ad714x); mutex_init(&ad714x->mutex); diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index a10912097b7a..78a6eb698b0a 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -4808,7 +4808,7 @@ ov7xx0_configure(struct usb_ov511 *ov) return -1; if (init_ov_sensor(ov) >= 0) { - PDEBUG(1, "OV7xx0 sensor initalized (method 1)"); + PDEBUG(1, "OV7xx0 sensor initialized (method 1)"); } else { /* Reset the 76xx */ if (i2c_w(ov, 0x12, 0x80) < 0) diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 8997add1248e..307e847fe1cd 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -391,7 +391,7 @@ struct zoran { struct mutex resource_lock; /* prevent evil stuff */ - u8 initialized; /* flag if zoran has been correctly initalized */ + u8 initialized; /* flag if zoran has been correctly initialized */ int user; /* number of current users */ struct card_info card; struct tvnorm *timing; diff --git a/drivers/media/video/zoran/zr36050.c b/drivers/media/video/zoran/zr36050.c index 639dd87c663f..e1985609af4b 100644 --- a/drivers/media/video/zoran/zr36050.c +++ b/drivers/media/video/zoran/zr36050.c @@ -236,7 +236,7 @@ zr36050_pushit (struct zr36050 *ptr, Could be variable, but until it's not needed it they are just fixed to save memory. Otherwise expand zr36050 structure with arrays, push the values to - it and initalize from there, as e.g. the linux zr36057/60 driver does it. + it and initialize from there, as e.g. the linux zr36057/60 driver does it. ========================================================================= */ static const char zr36050_dqt[0x86] = { diff --git a/drivers/media/video/zoran/zr36060.c b/drivers/media/video/zoran/zr36060.c index 008746ff7746..5e4f57cbf314 100644 --- a/drivers/media/video/zoran/zr36060.c +++ b/drivers/media/video/zoran/zr36060.c @@ -227,7 +227,7 @@ zr36060_pushit (struct zr36060 *ptr, Could be variable, but until it's not needed it they are just fixed to save memory. Otherwise expand zr36060 structure with arrays, push the values to - it and initalize from there, as e.g. the linux zr36057/60 driver does it. + it and initialize from there, as e.g. the linux zr36057/60 driver does it. ========================================================================= */ static const char zr36060_dqt[0x86] = { diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a6a57011ba6c..14d162fb8a2a 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1794,7 +1794,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->sh = NULL; ioc->cached_fw = NULL; - /* Initilize SCSI Config Data structure + /* Initialize SCSI Config Data structure */ memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); @@ -2471,7 +2471,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { /* - * Initalize link list for inactive raid volumes. + * Initialize link list for inactive raid volumes. */ mutex_init(&ioc->raid_data.inactive_list_mutex); INIT_LIST_HEAD(&ioc->raid_data.inactive_list); diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index ca03428b59cc..3dfda9cc677d 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1836,7 +1836,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { .pattern = mirror_pattern, }; -/* initalize driver data structures */ +/* initialize driver data structures */ void denali_drv_init(struct denali_nand_info *denali) { denali->idx = 0; diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 38395dfa4963..70705d1306b9 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -729,14 +729,14 @@ static void mc32_halt_transceiver(struct net_device *dev) * mc32_load_rx_ring - load the ring of receive buffers * @dev: 3c527 to build the ring for * - * This initalises the on-card and driver datastructures to + * This initialises the on-card and driver datastructures to * the point where mc32_start_transceiver() can be called. * * The card sets up the receive ring for us. We are required to use the * ring it provides, although the size of the ring is configurable. * * We allocate an sk_buff for each ring entry in turn and - * initalise its house-keeping info. At the same time, we read + * initialise its house-keeping info. At the same time, we read * each 'next' pointer in our rx_ring array. This reduces slow * shared-memory reads and makes it easy to access predecessor * descriptors. diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c index 79636ee35829..0362c8d31a08 100644 --- a/drivers/net/appletalk/ipddp.c +++ b/drivers/net/appletalk/ipddp.c @@ -80,7 +80,7 @@ static struct net_device * __init ipddp_init(void) if (version_printed++ == 0) printk(version); - /* Initalize the device structure. */ + /* Initialize the device structure. */ dev->netdev_ops = &ipddp_netdev_ops; dev->type = ARPHRD_IPDDP; /* IP over DDP tunnel */ diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 68e5ac8832ad..dfc787fa8b17 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -1071,7 +1071,7 @@ static void hp100_mmuinit(struct net_device *dev) if (lp->mode == 1) hp100_init_pdls(dev); - /* Go to performance page and initalize isr and imr registers */ + /* Go to performance page and initialize isr and imr registers */ hp100_page(PERFORMANCE); hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ hp100_outw(0xffff, IRQ_STATUS); /* ack IRQ */ diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 2484e9e6c1ed..6a45f8f3a0c7 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -1044,7 +1044,7 @@ static int emac_change_mtu(struct net_device *ndev, int new_mtu) DBG(dev, "change_mtu(%d)" NL, new_mtu); if (netif_running(ndev)) { - /* Check if we really need to reinitalize RX ring */ + /* Check if we really need to reinitialize RX ring */ if (emac_rx_skb_size(ndev->mtu) != emac_rx_skb_size(new_mtu)) ret = emac_resize_rx_ring(dev, new_mtu); } diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index c80ca64277b2..c02ce1ab6571 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c @@ -6812,7 +6812,7 @@ static int stp; static int fast_aging; /** - * netdev_init - initalize network device. + * netdev_init - initialize network device. * @dev: Network device. * * This function initializes the network device. diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index b59b24d667f0..0ace2a46d31c 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -449,7 +449,7 @@ static u32 temac_setoptions(struct net_device *ndev, u32 options) return (0); } -/* Initilize temac */ +/* Initialize temac */ static void temac_device_reset(struct net_device *ndev) { struct temac_local *lp = netdev_priv(ndev); diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 29e6c63d39fd..0bc4f3030a80 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -589,7 +589,7 @@ static int dmfe_open(struct DEVICE *dev) db->dm910x_chk_mode = 1; /* Enter the check mode */ } - /* Initilize DM910X board */ + /* Initialize DM910X board */ dmfe_init_dm910x(dev); /* Active System Interface */ @@ -606,9 +606,9 @@ static int dmfe_open(struct DEVICE *dev) } -/* Initilize DM910X board +/* Initialize DM910X board * Reset DM910X board - * Initilize TX/Rx descriptor chain structure + * Initialize TX/Rx descriptor chain structure * Send the set-up frame * Enable Tx/Rx machine */ @@ -649,7 +649,7 @@ static void dmfe_init_dm910x(struct DEVICE *dev) if ( !(db->media_mode & DMFE_AUTO) ) db->op_mode = db->media_mode; /* Force Mode */ - /* Initiliaze Transmit/Receive decriptor and CR3/4 */ + /* Initialize Transmit/Receive decriptor and CR3/4 */ dmfe_descriptor_init(db, ioaddr); /* Init CR6 to program DM910x operation */ @@ -1288,7 +1288,7 @@ static void dmfe_timer(unsigned long data) * Stop DM910X board * Free Tx/Rx allocated memory * Reset DM910X board - * Re-initilize DM910X board + * Re-initialize DM910X board */ static void dmfe_dynamic_reset(struct DEVICE *dev) @@ -1316,7 +1316,7 @@ static void dmfe_dynamic_reset(struct DEVICE *dev) netif_carrier_off(dev); db->wait_reset = 0; - /* Re-initilize DM910X board */ + /* Re-initialize DM910X board */ dmfe_init_dm910x(dev); /* Restart upper layer interface */ @@ -1447,7 +1447,7 @@ static void update_cr6(u32 cr6_data, unsigned long ioaddr) /* * Send a setup frame for DM9132 - * This setup frame initilize DM910X address filter mode + * This setup frame initialize DM910X address filter mode */ static void dm9132_id_table(struct DEVICE *dev) @@ -1489,7 +1489,7 @@ static void dm9132_id_table(struct DEVICE *dev) /* * Send a setup frame for DM9102/DM9102A - * This setup frame initilize DM910X address filter mode + * This setup frame initialize DM910X address filter mode */ static void send_filter_frame(struct DEVICE *dev) @@ -2142,7 +2142,7 @@ static int dmfe_resume(struct pci_dev *pci_dev) pci_set_power_state(pci_dev, PCI_D0); pci_restore_state(pci_dev); - /* Re-initilize DM910X board */ + /* Re-initialize DM910X board */ dmfe_init_dm910x(dev); /* Disable WOL */ @@ -2196,7 +2196,7 @@ MODULE_PARM_DESC(SF_mode, "Davicom DM9xxx special function " /* Description: * when user used insmod to add module, system invoked init_module() - * to initilize and register. + * to initialize and register. */ static int __init dmfe_init_module(void) diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index d86e8f31e7fc..7f48e040c3be 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -50,7 +50,7 @@ * * ROADMAP * - * i2400m_dev_initalize() Called by i2400m_dev_start() + * i2400m_dev_initialize() Called by i2400m_dev_start() * i2400m_set_init_config() * i2400m_cmd_get_state() * i2400m_dev_shutdown() Called by i2400m_dev_stop() diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index f511e70d454c..75a80e46b391 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1241,10 +1241,10 @@ static struct parisc_driver ccio_driver = { }; /** - * ccio_ioc_init - Initalize the I/O Controller + * ccio_ioc_init - Initialize the I/O Controller * @ioc: The I/O Controller. * - * Initalize the I/O Controller which includes setting up the + * Initialize the I/O Controller which includes setting up the * I/O Page Directory, the resource map, and initalizing the * U2/Uturn chip into virtual mode. */ diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index fa28d8911b00..0c62fe31a40e 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c @@ -231,7 +231,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, sinfo->nskt = nr; - /* Initiliaze processor specific parameters */ + /* Initialize processor specific parameters */ for (i = 0; i < nr; i++) { skt = &sinfo->skt[i]; diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 7f87979da22d..0ec3da6f3e12 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -9717,7 +9717,7 @@ static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) asc_dvc->bug_fix_cntl = 0; asc_dvc->pci_fix_asyn_xfer = 0; asc_dvc->pci_fix_asyn_xfer_always = 0; - /* asc_dvc->init_state initalized in AscInitGetConfig(). */ + /* asc_dvc->init_state initialized in AscInitGetConfig(). */ asc_dvc->sdtr_done = 0; asc_dvc->cur_total_qng = 0; asc_dvc->is_in_int = 0; diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index d01dcc62b39a..74374618010c 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -588,7 +588,7 @@ static void asd_init_cseq_mdp(struct asd_ha_struct *asd_ha) * asd_init_cseq_scratch -- setup and init CSEQ * @asd_ha: pointer to host adapter structure * - * Setup and initialize Central sequencers. Initialiaze the mode + * Setup and initialize Central sequencers. Initialize the mode * independent and dependent scratch page to the default settings. */ static void asd_init_cseq_scratch(struct asd_ha_struct *asd_ha) @@ -782,7 +782,7 @@ static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq) asd_write_reg_word(asd_ha, LmSEQ_OOB_INT_ENABLES(lseq), 0); /* * Set the desired interval between transmissions of the NOTIFY - * (ENABLE SPINUP) primitive. Must be initilized to val - 1. + * (ENABLE SPINUP) primitive. Must be initialized to val - 1. */ asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_TIMEOUT(lseq), ASD_NOTIFY_TIMEOUT - 1); diff --git a/drivers/scsi/bfa/vport.c b/drivers/scsi/bfa/vport.c index 27cd619a227a..e2720c8a6661 100644 --- a/drivers/scsi/bfa/vport.c +++ b/drivers/scsi/bfa/vport.c @@ -789,7 +789,7 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) switch (status) { case BFA_STATUS_OK: /* - * Initialiaze the V-Port fields + * Initialize the V-Port fields */ __vport_fcid(vport) = bfa_lps_get_pid(vport->lps); vport->vport_stats.fdisc_accepts++; diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 0e05e8a22167..e81efac25fa4 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1082,7 +1082,7 @@ static void pm8001_hw_chip_rst(struct pm8001_hba_info *pm8001_ha) } /** - * pm8001_chip_iounmap - which maped when initilized. + * pm8001_chip_iounmap - which maped when initialized. * @pm8001_ha: our hba card information */ static void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha) diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 5510df8a7fa6..cd3043265a6d 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -183,7 +183,7 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) **/ static int qla4xxx_init_local_data(struct scsi_qla_host *ha) { - /* Initilize aen queue */ + /* Initialize aen queue */ ha->aen_q_count = MAX_AEN_ENTRIES; return qla4xxx_get_firmware_status(ha); diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 9794e0cd3dcc..7e5e5efea4e2 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -470,7 +470,7 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags) } if (port->sc_port.state) { - /* The serial_core stuffs are initilized, use them */ + /* The serial_core stuffs are initialized, use them */ tty = port->sc_port.state->port.tty; } else { @@ -551,11 +551,11 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw) BUG_ON(!port->sc_is_asynch); if (port->sc_port.state) { - /* We're initilized, using serial core infrastructure */ + /* We're initialized, using serial core infrastructure */ xmit = &port->sc_port.state->xmit; } else { /* Probably sn_sal_switch_to_asynch has been run but serial core isn't - * initilized yet. Just return. Writes are going through + * initialized yet. Just return. Writes are going through * sn_sal_console_write (due to register_console) at this time. */ return; diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 8942ae45708d..e7271685f235 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2087,7 +2087,7 @@ static int usbdux_pwm_start(struct comedi_device *dev, if (ret < 0) return ret; - /* initalise the buffer */ + /* initialise the buffer */ for (i = 0; i < this_usbduxsub->sizePwmBuf; i++) ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0; diff --git a/drivers/staging/octeon/cvmx-cmd-queue.c b/drivers/staging/octeon/cvmx-cmd-queue.c index 976227b01273..e9809d375162 100644 --- a/drivers/staging/octeon/cvmx-cmd-queue.c +++ b/drivers/staging/octeon/cvmx-cmd-queue.c @@ -140,21 +140,21 @@ cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id, if (qstate->base_ptr_div128) { if (max_depth != (int)qstate->max_depth) { cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " - "Queue already initalized with different " + "Queue already initialized with different " "max_depth (%d).\n", (int)qstate->max_depth); return CVMX_CMD_QUEUE_INVALID_PARAM; } if (fpa_pool != qstate->fpa_pool) { cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " - "Queue already initalized with different " + "Queue already initialized with different " "FPA pool (%u).\n", qstate->fpa_pool); return CVMX_CMD_QUEUE_INVALID_PARAM; } if ((pool_size >> 3) - 1 != qstate->pool_size_m1) { cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " - "Queue already initalized with different " + "Queue already initialized with different " "FPA pool size (%u).\n", (qstate->pool_size_m1 + 1) << 3); return CVMX_CMD_QUEUE_INVALID_PARAM; diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index 63275529ff55..fe8b093fb616 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c @@ -848,7 +848,7 @@ static void pohmelfs_destroy_inode(struct inode *inode) } /* - * ->alloc_inode() callback. Allocates inode and initilizes private data. + * ->alloc_inode() callback. Allocates inode and initializes private data. */ static struct inode *pohmelfs_alloc_inode(struct super_block *sb) { diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c index 94e119faaa71..e1ead76b907d 100644 --- a/drivers/staging/rt2860/common/cmm_wpa.c +++ b/drivers/staging/rt2860/common/cmm_wpa.c @@ -427,7 +427,7 @@ void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd, /* ========================================================================== Description: - This is a function to initilize 4-way handshake + This is a function to initialize 4-way handshake Return: @@ -867,7 +867,7 @@ void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd, ========================================================================== Description: When receiving the last packet of 4-way pairwisekey handshake. - Initilize 2-way groupkey handshake following. + Initialize 2-way groupkey handshake following. Return: ========================================================================== */ diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.c b/drivers/staging/rtl8192e/r8190_rtl8256.c index 1bd054d42f24..eff47f9cddb9 100644 --- a/drivers/staging/rtl8192e/r8190_rtl8256.c +++ b/drivers/staging/rtl8192e/r8190_rtl8256.c @@ -501,13 +501,13 @@ SetRFPowerState8190( if((priv->ieee80211->eRFPowerState == eRfOff) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) { // The current RF state is OFF and the RF OFF level is halting the NIC, re-initialize the NIC. bool rtstatus = true; - u32 InitilizeCount = 3; + u32 InitializeCount = 3; do { - InitilizeCount--; + InitializeCount--; priv->RegRfOff = false; rtstatus = NicIFEnableNIC(dev); - }while( (rtstatus != true) &&(InitilizeCount >0) ); + }while( (rtstatus != true) &&(InitializeCount >0) ); if(rtstatus != true) { diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index cdbe8bf7f674..e8a65ce45a2f 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -261,7 +261,7 @@ static int klsi_105_startup(struct usb_serial *serial) spin_lock_init(&priv->lock); - /* priv->termios is left uninitalized until port opening */ + /* priv->termios is left uninitialized until port opening */ init_waitqueue_head(&serial->port[i]->write_wait); } diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/usb/wusbcore/wusbhc.c index eab86e4bc770..2054d4ee9774 100644 --- a/drivers/usb/wusbcore/wusbhc.c +++ b/drivers/usb/wusbcore/wusbhc.c @@ -26,7 +26,7 @@ * the one that requires (phase B, wusbhc_b_{create,destroy}). * * This is so because usb_add_hcd() will start the HC, and thus, all - * the HC specific stuff has to be already initialiazed (like sysfs + * the HC specific stuff has to be already initialized (like sysfs * thingies). */ #include diff --git a/drivers/uwb/wlp/wss-lc.c b/drivers/uwb/wlp/wss-lc.c index 90accdd54c07..a005d2a03b5d 100644 --- a/drivers/uwb/wlp/wss-lc.c +++ b/drivers/uwb/wlp/wss-lc.c @@ -180,7 +180,7 @@ error_kobject_register: * If memory was allocated for the kobject's name then it will * be freed by the kobject system during this time. * - * The EDA cache is removed and reinitilized when the WSS is removed. We + * The EDA cache is removed and reinitialized when the WSS is removed. We * thus loose knowledge of members of this WSS at that time and need not do * it here. */ diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c index d8345fcc4fe3..6b19136aa181 100644 --- a/drivers/video/carminefb.c +++ b/drivers/video/carminefb.c @@ -432,7 +432,7 @@ static int init_hardware(struct carmine_hw *hw) u32 loops; u32 ret; - /* Initalize Carmine */ + /* Initialize Carmine */ /* Sets internal clock */ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, CARMINE_DFLT_IP_CLOCK_ENABLE); diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 1b3b1c718e80..aba7686b1a32 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -305,7 +305,7 @@ tgafb_set_par(struct fb_info *info) TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG); TGA_WRITE_REG(par, vtimings, TGA_VERT_REG); - /* Initalise RAMDAC. */ + /* Initialise RAMDAC. */ if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) { /* Init BT485 RAMDAC registers. */ diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 34ddda888e63..dc39d2824885 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -436,7 +436,7 @@ befs_init_inodecache(void) init_once); if (befs_inode_cachep == NULL) { printk(KERN_ERR "befs_init_inodecache: " - "Couldn't initalize inode slabcache\n"); + "Couldn't initialize inode slabcache\n"); return -ENOMEM; } diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 1cc087635a5e..a2e3b562e65d 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -762,7 +762,7 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, /** * ecryptfs_init_crypt_ctx - * @crypt_stat: Uninitilized crypt stats structure + * @crypt_stat: Uninitialized crypt stats structure * * Initialize the crypto context. * diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 236b834b4ca8..146f1f6a9203 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2918,7 +2918,7 @@ fix_extent_len: * One of more index blocks maybe needed if the extent tree grow after * the unintialized extent split. To prevent ENOSPC occur at the IO * complete, we need to split the uninitialized extent before DIO submit - * the IO. The uninitilized extent called at this time will be split + * the IO. The uninitialized extent called at this time will be split * into three uninitialized extent(at most). After IO complete, the part * being filled will be convert to initialized by the end_io callback function * via ext4_convert_unwritten_extents(). diff --git a/fs/ext4/super.c b/fs/ext4/super.c index e14d22c170d5..8d7539c9d778 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3008,7 +3008,7 @@ no_journal: ext4_ext_init(sb); err = ext4_mb_init(sb, needs_recovery); if (err) { - ext4_msg(sb, KERN_ERR, "failed to initalize mballoc (%d)", + ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)", err); goto failed_mount4; } diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 1e8af939b3e4..5132c99b1ca2 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -135,7 +135,7 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) } /** - * vxfs_read_super - read superblock into memory and initalize filesystem + * vxfs_read_super - read superblock into memory and initialize filesystem * @sbp: VFS superblock (to fill) * @dp: fs private mount data * @silent: do not complain loudly when sth is wrong diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 2c26ce251cb3..812f10233b10 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -2476,7 +2476,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb) kfree(osb->slot_recovery_generations); /* FIXME * This belongs in journal shutdown, but because we have to - * allocate osb->journal at the start of ocfs2_initalize_osb(), + * allocate osb->journal at the start of ocfs2_initialize_osb(), * we free it here. */ kfree(osb->journal); diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 0f22fdaf54ac..29db72203bde 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1221,7 +1221,7 @@ static void init_inode(struct inode *inode, struct treepath *path) inode_set_bytes(inode, to_real_used_space(inode, inode->i_blocks, SD_V2_SIZE)); - /* read persistent inode attributes from sd and initalise + /* read persistent inode attributes from sd and initialise generic inode flags from them */ REISERFS_I(inode)->i_attrs = sd_v2_attrs(sd); sd_attrs_to_i_attrs(sd_v2_attrs(sd), inode); diff --git a/lib/random32.c b/lib/random32.c index 217d5c4b666d..556d5ffe1106 100644 --- a/lib/random32.c +++ b/lib/random32.c @@ -131,7 +131,7 @@ core_initcall(random32_init); /* * Generate better values after random number generator - * is fully initalized. + * is fully initialized. */ static int __init random32_reseed(void) { diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 94a45213faa6..9323f8944199 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -11,7 +11,7 @@ * Changes: * Martin Hamilton : fixed the terrible locking bugs * *lock(tbl->lock) ==> *lock(&tbl->lock) - * Wensong Zhang : fixed the uninitilized tbl->lock bug + * Wensong Zhang : fixed the uninitialized tbl->lock bug * Wensong Zhang : added doing full expiration check to * collect stale entries of 24+ hours when * no partial expire check in a half hour diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index 535dc2b419d8..dbeed8ea421a 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -386,7 +386,7 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr, ip_vs_addr_copy(dest->af, &en->addr, daddr); en->lastuse = jiffies; - /* initilize its dest set */ + /* initialize its dest set */ atomic_set(&(en->set.size), 0); INIT_LIST_HEAD(&en->set.list); rwlock_init(&en->set.lock); diff --git a/net/sctp/associola.c b/net/sctp/associola.c index e41feff19e43..0b85e5256434 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -172,7 +172,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = (unsigned long)sp->autoclose * HZ; - /* Initilizes the timers */ + /* Initializes the timers */ for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) setup_timer(&asoc->timers[i], sctp_timer_events[i], (unsigned long)asoc); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 182749867c72..0f41b05bd4d6 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1162,7 +1162,7 @@ SCTP_STATIC __init int sctp_init(void) /* Set the pressure threshold to be a fraction of global memory that * is up to 1/2 at 256 MB, decreasing toward zero with the amount of * memory, with a floor of 128 pages. - * Note this initalizes the data in sctpv6_prot too + * Note this initializes the data in sctpv6_prot too * Unabashedly stolen from tcp_init */ nr_pages = totalram_pages - totalhigh_pages; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0f2fc480fc61..276bdc7325e5 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3227,7 +3227,7 @@ static __init int smack_init(void) cred = (struct cred *) current->cred; cred->security = &smack_known_floor.smk_known; - /* initilize the smack_know_list */ + /* initialize the smack_know_list */ init_smack_know_list(); /* * Initialize locks diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 6d943f6f6b70..2870a4fdc130 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -1055,7 +1055,7 @@ static int snd_trident_capture_prepare(struct snd_pcm_substream *substream) spin_lock_irq(&trident->reg_lock); - // Initilize the channel and set channel Mode + // Initialize the channel and set channel Mode outb(0, TRID_REG(trident, LEGACY_DMAR15)); // Set DMA channel operation mode register diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 83de1c81c8c4..604a91fa31bc 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -46,7 +46,7 @@ struct mpc8610_hpcd_data { }; /** - * mpc8610_hpcd_machine_probe: initalize the board + * mpc8610_hpcd_machine_probe: initialize the board * * This function is called when platform_device_add() is called. It is used * to initialize the board-specific hardware. diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 998569d60330..e048e0910099 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1307,7 +1307,7 @@ cpu_dai_err: } /* - * Attempt to initialise any uninitalised cards. Must be called with + * Attempt to initialise any uninitialised cards. Must be called with * client_mutex. */ static void snd_soc_instantiate_cards(void) -- cgit v1.2.3 From 1636f8ac2b08410df4766449f7c86b912443cd99 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 18 Jun 2010 11:09:58 -0600 Subject: sparc/of: Move of_device fields into struct pdev_archdata This patch moves SPARC architecture specific data members out of struct of_device and into the pdev_archdata structure. The reason for this change is to unify the struct of_device definition amongst all the architectures. It also remvoes the .sysdata, .slot, .portid and .clock_freq properties because they aren't actually used by anything. A subsequent patch will replace struct of_device entirely with struct platform_device and the of_platform support code will share common routines with the platform bus (but the bus instances themselves can remain separate). This patch also adds 'struct resources *resource' and num_resources to match the fields defined in struct platform_device. After this change, 'struct platform_device' can be used as a drop-in replacement for 'struct of_platform'. This change is in preparation for merging the of_platform_bus_type with the platform_bus_type. Signed-off-by: Grant Likely Acked-by: David S. Miller Cc: Stephen Rothwell --- arch/sparc/include/asm/device.h | 5 +++++ arch/sparc/include/asm/floppy_64.h | 4 ++-- arch/sparc/include/asm/of_device.h | 11 +++-------- arch/sparc/include/asm/parport.h | 4 ++-- arch/sparc/kernel/of_device_32.c | 28 ++++++++++++---------------- arch/sparc/kernel/of_device_64.c | 24 ++++++++++-------------- arch/sparc/kernel/of_device_common.c | 4 ++-- arch/sparc/kernel/pci.c | 2 +- arch/sparc/kernel/pci_psycho.c | 8 ++++---- arch/sparc/kernel/pci_sabre.c | 8 ++++---- arch/sparc/kernel/pci_schizo.c | 20 ++++++++++---------- arch/sparc/kernel/power.c | 2 +- drivers/atm/fore200e.c | 2 +- drivers/input/serio/i8042-sparcio.h | 8 ++++---- drivers/net/myri_sbus.c | 2 +- drivers/net/niu.c | 6 +++--- drivers/net/sunbmac.c | 2 +- drivers/net/sunhme.c | 6 +++--- drivers/net/sunlance.c | 2 +- drivers/net/sunqe.c | 6 +++--- drivers/parport/parport_sunbpp.c | 2 +- drivers/sbus/char/bbc_i2c.c | 6 +++--- drivers/sbus/char/uctrl.c | 2 +- drivers/scsi/qlogicpti.c | 4 ++-- drivers/scsi/sun_esp.c | 2 +- drivers/serial/sunhv.c | 4 ++-- drivers/serial/sunsab.c | 2 +- drivers/serial/sunsu.c | 2 +- drivers/serial/sunzilog.c | 10 +++++----- drivers/watchdog/cpwd.c | 2 +- sound/sparc/amd7930.c | 2 +- sound/sparc/cs4231.c | 14 +++++++------- sound/sparc/dbri.c | 2 +- 33 files changed, 100 insertions(+), 108 deletions(-) (limited to 'drivers/scsi') diff --git a/arch/sparc/include/asm/device.h b/arch/sparc/include/asm/device.h index d4c452147412..f9740d065fe7 100644 --- a/arch/sparc/include/asm/device.h +++ b/arch/sparc/include/asm/device.h @@ -6,6 +6,8 @@ #ifndef _ASM_SPARC_DEVICE_H #define _ASM_SPARC_DEVICE_H +#include + struct device_node; struct of_device; @@ -18,6 +20,9 @@ struct dev_archdata { }; struct pdev_archdata { + struct resource resource[PROMREG_MAX]; + unsigned int irqs[PROMINTR_MAX]; + int num_irqs; }; #endif /* _ASM_SPARC_DEVICE_H */ diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h index 8fac3ab22f36..4f5bde638f72 100644 --- a/arch/sparc/include/asm/floppy_64.h +++ b/arch/sparc/include/asm/floppy_64.h @@ -567,7 +567,7 @@ static unsigned long __init sun_floppy_init(void) } if (op) { floppy_op = op; - FLOPPY_IRQ = op->irqs[0]; + FLOPPY_IRQ = op->archdata.irqs[0]; } else { struct device_node *ebus_dp; void __iomem *auxio_reg; @@ -593,7 +593,7 @@ static unsigned long __init sun_floppy_init(void) if (state_prop && !strncmp(state_prop, "disabled", 8)) return 0; - FLOPPY_IRQ = op->irqs[0]; + FLOPPY_IRQ = op->archdata.irqs[0]; /* Make sure the high density bit is set, some systems * (most notably Ultra5/Ultra10) come up with it clear. diff --git a/arch/sparc/include/asm/of_device.h b/arch/sparc/include/asm/of_device.h index f320246a0586..6d1844a547b4 100644 --- a/arch/sparc/include/asm/of_device.h +++ b/arch/sparc/include/asm/of_device.h @@ -15,15 +15,10 @@ struct of_device { struct device dev; - struct resource resource[PROMREG_MAX]; - unsigned int irqs[PROMINTR_MAX]; - int num_irqs; + u32 num_resources; + struct resource *resource; - void *sysdata; - - int slot; - int portid; - int clock_freq; + struct pdev_archdata archdata; }; extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index c333b8d0949b..0c34a8792fc7 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h @@ -116,7 +116,7 @@ static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id parent = op->dev.of_node->parent; if (!strcmp(parent->name, "dma")) { p = parport_pc_probe_port(base, base + 0x400, - op->irqs[0], PARPORT_DMA_NOFIFO, + op->archdata.irqs[0], PARPORT_DMA_NOFIFO, op->dev.parent->parent, 0); if (!p) return -ENOMEM; @@ -166,7 +166,7 @@ static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id 0, PTR_LPT_REG_DIR); p = parport_pc_probe_port(base, base + 0x400, - op->irqs[0], + op->archdata.irqs[0], slot, op->dev.parent, 0); diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c index 47e63f1e719c..331de91ad2bc 100644 --- a/arch/sparc/kernel/of_device_32.c +++ b/arch/sparc/kernel/of_device_32.c @@ -267,6 +267,8 @@ static void __init build_device_resources(struct of_device *op, /* Conver to num-entries. */ num_reg /= na + ns; + op->resource = op->archdata.resource; + op->num_resources = num_reg; for (index = 0; index < num_reg; index++) { struct resource *r = &op->resource[index]; u32 addr[OF_MAX_ADDR_CELLS]; @@ -349,27 +351,21 @@ static struct of_device * __init scan_one_device(struct device_node *dp, op->dev.of_node = dp; - op->clock_freq = of_getintprop_default(dp, "clock-frequency", - (25*1000*1000)); - op->portid = of_getintprop_default(dp, "upa-portid", -1); - if (op->portid == -1) - op->portid = of_getintprop_default(dp, "portid", -1); - intr = of_get_property(dp, "intr", &len); if (intr) { - op->num_irqs = len / sizeof(struct linux_prom_irqs); - for (i = 0; i < op->num_irqs; i++) - op->irqs[i] = intr[i].pri; + op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs); + for (i = 0; i < op->archdata.num_irqs; i++) + op->archdata.irqs[i] = intr[i].pri; } else { const unsigned int *irq = of_get_property(dp, "interrupts", &len); if (irq) { - op->num_irqs = len / sizeof(unsigned int); - for (i = 0; i < op->num_irqs; i++) - op->irqs[i] = irq[i]; + op->archdata.num_irqs = len / sizeof(unsigned int); + for (i = 0; i < op->archdata.num_irqs; i++) + op->archdata.irqs[i] = irq[i]; } else { - op->num_irqs = 0; + op->archdata.num_irqs = 0; } } if (sparc_cpu_model == sun4d) { @@ -411,8 +407,8 @@ static struct of_device * __init scan_one_device(struct device_node *dp, goto build_resources; } - for (i = 0; i < op->num_irqs; i++) { - int this_irq = op->irqs[i]; + for (i = 0; i < op->archdata.num_irqs; i++) { + int this_irq = op->archdata.irqs[i]; int sbusl = pil_to_sbus[this_irq]; if (sbusl) @@ -420,7 +416,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, (sbusl << 2) + slot); - op->irqs[i] = this_irq; + op->archdata.irqs[i] = this_irq; } } diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 1dae8079f728..5e8cbb942d3d 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -344,6 +344,8 @@ static void __init build_device_resources(struct of_device *op, num_reg = PROMREG_MAX; } + op->resource = op->archdata.resource; + op->num_resources = num_reg; for (index = 0; index < num_reg; index++) { struct resource *r = &op->resource[index]; u32 addr[OF_MAX_ADDR_CELLS]; @@ -644,31 +646,25 @@ static struct of_device * __init scan_one_device(struct device_node *dp, op->dev.of_node = dp; - op->clock_freq = of_getintprop_default(dp, "clock-frequency", - (25*1000*1000)); - op->portid = of_getintprop_default(dp, "upa-portid", -1); - if (op->portid == -1) - op->portid = of_getintprop_default(dp, "portid", -1); - irq = of_get_property(dp, "interrupts", &len); if (irq) { - op->num_irqs = len / 4; + op->archdata.num_irqs = len / 4; /* Prevent overrunning the op->irqs[] array. */ - if (op->num_irqs > PROMINTR_MAX) { + if (op->archdata.num_irqs > PROMINTR_MAX) { printk(KERN_WARNING "%s: Too many irqs (%d), " "limiting to %d.\n", - dp->full_name, op->num_irqs, PROMINTR_MAX); - op->num_irqs = PROMINTR_MAX; + dp->full_name, op->archdata.num_irqs, PROMINTR_MAX); + op->archdata.num_irqs = PROMINTR_MAX; } - memcpy(op->irqs, irq, op->num_irqs * 4); + memcpy(op->archdata.irqs, irq, op->archdata.num_irqs * 4); } else { - op->num_irqs = 0; + op->archdata.num_irqs = 0; } build_device_resources(op, parent); - for (i = 0; i < op->num_irqs; i++) - op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]); + for (i = 0; i < op->archdata.num_irqs; i++) + op->archdata.irqs[i] = build_one_device_irq(op, parent, op->archdata.irqs[i]); op->dev.parent = parent; op->dev.bus = &of_platform_bus_type; diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c index 10c6c36a6e75..016c947d4cae 100644 --- a/arch/sparc/kernel/of_device_common.c +++ b/arch/sparc/kernel/of_device_common.c @@ -35,10 +35,10 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index) { struct of_device *op = of_find_device_by_node(node); - if (!op || index >= op->num_irqs) + if (!op || index >= op->archdata.num_irqs) return 0; - return op->irqs[index]; + return op->archdata.irqs[index]; } EXPORT_SYMBOL(irq_of_parse_and_map); diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 8a8363adb8bd..1523290db0a1 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -340,7 +340,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->hdr_type = PCI_HEADER_TYPE_NORMAL; dev->rom_base_reg = PCI_ROM_ADDRESS; - dev->irq = sd->op->irqs[0]; + dev->irq = sd->op->archdata.irqs[0]; if (dev->irq == 0xffffffff) dev->irq = PCI_IRQ_NONE; } diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c index 558a70512824..93011e6e7ddc 100644 --- a/arch/sparc/kernel/pci_psycho.c +++ b/arch/sparc/kernel/pci_psycho.c @@ -302,23 +302,23 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) * 5: POWER MANAGEMENT */ - if (op->num_irqs < 6) + if (op->archdata.num_irqs < 6) return; /* We really mean to ignore the return result here. Two * PCI controller share the same interrupt numbers and * drive the same front-end hardware. */ - err = request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, + err = request_irq(op->archdata.irqs[1], psycho_ue_intr, IRQF_SHARED, "PSYCHO_UE", pbm); - err = request_irq(op->irqs[2], psycho_ce_intr, IRQF_SHARED, + err = request_irq(op->archdata.irqs[2], psycho_ce_intr, IRQF_SHARED, "PSYCHO_CE", pbm); /* This one, however, ought not to fail. We can just warn * about it since the system can still operate properly even * if this fails. */ - err = request_irq(op->irqs[0], psycho_pcierr_intr, IRQF_SHARED, + err = request_irq(op->archdata.irqs[0], psycho_pcierr_intr, IRQF_SHARED, "PSYCHO_PCIERR", pbm); if (err) printk(KERN_WARNING "%s: Could not register PCIERR, " diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c index 6dad8e3b7506..99c6dba7d4fd 100644 --- a/arch/sparc/kernel/pci_sabre.c +++ b/arch/sparc/kernel/pci_sabre.c @@ -329,7 +329,7 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) * 2: CE ERR * 3: POWER FAIL */ - if (op->num_irqs < 4) + if (op->archdata.num_irqs < 4) return; /* We clear the error bits in the appropriate AFSR before @@ -341,7 +341,7 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE), base + SABRE_UE_AFSR); - err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); + err = request_irq(op->archdata.irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); if (err) printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", pbm->name, err); @@ -351,11 +351,11 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) base + SABRE_CE_AFSR); - err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); + err = request_irq(op->archdata.irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); if (err) printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", pbm->name, err); - err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, + err = request_irq(op->archdata.irqs[0], psycho_pcierr_intr, 0, "SABRE_PCIERR", pbm); if (err) printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 97a1ae2e1c02..9041dae7aaca 100644 --- a/arch/sparc/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c @@ -857,14 +857,14 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) */ if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) { - err = request_irq(op->irqs[1], schizo_ue_intr, 0, + err = request_irq(op->archdata.irqs[1], schizo_ue_intr, 0, "TOMATILLO_UE", pbm); if (err) printk(KERN_WARNING "%s: Could not register UE, " "err=%d\n", pbm->name, err); } if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) { - err = request_irq(op->irqs[2], schizo_ce_intr, 0, + err = request_irq(op->archdata.irqs[2], schizo_ce_intr, 0, "TOMATILLO_CE", pbm); if (err) printk(KERN_WARNING "%s: Could not register CE, " @@ -872,10 +872,10 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) } err = 0; if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) { - err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, + err = request_irq(op->archdata.irqs[0], schizo_pcierr_intr, 0, "TOMATILLO_PCIERR", pbm); } else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) { - err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, + err = request_irq(op->archdata.irqs[0], schizo_pcierr_intr, 0, "TOMATILLO_PCIERR", pbm); } if (err) @@ -883,7 +883,7 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) "err=%d\n", pbm->name, err); if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) { - err = request_irq(op->irqs[3], schizo_safarierr_intr, 0, + err = request_irq(op->archdata.irqs[3], schizo_safarierr_intr, 0, "TOMATILLO_SERR", pbm); if (err) printk(KERN_WARNING "%s: Could not register SERR, " @@ -952,14 +952,14 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) */ if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) { - err = request_irq(op->irqs[1], schizo_ue_intr, 0, + err = request_irq(op->archdata.irqs[1], schizo_ue_intr, 0, "SCHIZO_UE", pbm); if (err) printk(KERN_WARNING "%s: Could not register UE, " "err=%d\n", pbm->name, err); } if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) { - err = request_irq(op->irqs[2], schizo_ce_intr, 0, + err = request_irq(op->archdata.irqs[2], schizo_ce_intr, 0, "SCHIZO_CE", pbm); if (err) printk(KERN_WARNING "%s: Could not register CE, " @@ -967,10 +967,10 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) } err = 0; if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) { - err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, + err = request_irq(op->archdata.irqs[0], schizo_pcierr_intr, 0, "SCHIZO_PCIERR", pbm); } else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) { - err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, + err = request_irq(op->archdata.irqs[0], schizo_pcierr_intr, 0, "SCHIZO_PCIERR", pbm); } if (err) @@ -978,7 +978,7 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) "err=%d\n", pbm->name, err); if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) { - err = request_irq(op->irqs[3], schizo_safarierr_intr, 0, + err = request_irq(op->archdata.irqs[3], schizo_safarierr_intr, 0, "SCHIZO_SERR", pbm); if (err) printk(KERN_WARNING "%s: Could not register SERR, " diff --git a/arch/sparc/kernel/power.c b/arch/sparc/kernel/power.c index 168d4cb63f5b..1cfee577f6b5 100644 --- a/arch/sparc/kernel/power.c +++ b/arch/sparc/kernel/power.c @@ -36,7 +36,7 @@ static int __devinit has_button_interrupt(unsigned int irq, struct device_node * static int __devinit power_probe(struct of_device *op, const struct of_device_id *match) { struct resource *res = &op->resource[0]; - unsigned int irq= op->irqs[0]; + unsigned int irq = op->archdata.irqs[0]; power_reg = of_ioremap(res, 0, 0x4, "power"); diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index da8f176c051e..38df87b198d5 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -2657,7 +2657,7 @@ static int __devinit fore200e_sba_probe(struct of_device *op, fore200e->bus = bus; fore200e->bus_dev = op; - fore200e->irq = op->irqs[0]; + fore200e->irq = op->archdata.irqs[0]; fore200e->phys_base = op->resource[0].start; sprintf(fore200e->name, "%s-%d", bus->model_name, index); diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index 04e32f2d1241..c7d50ff43fca 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -58,9 +58,9 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev if (!strcmp(dp->name, OBP_PS2KBD_NAME1) || !strcmp(dp->name, OBP_PS2KBD_NAME2)) { struct of_device *kbd = of_find_device_by_node(dp); - unsigned int irq = kbd->irqs[0]; + unsigned int irq = kbd->archdata.irqs[0]; if (irq == 0xffffffff) - irq = op->irqs[0]; + irq = op->archdata.irqs[0]; i8042_kbd_irq = irq; kbd_iobase = of_ioremap(&kbd->resource[0], 0, 8, "kbd"); @@ -68,9 +68,9 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev } else if (!strcmp(dp->name, OBP_PS2MS_NAME1) || !strcmp(dp->name, OBP_PS2MS_NAME2)) { struct of_device *ms = of_find_device_by_node(dp); - unsigned int irq = ms->irqs[0]; + unsigned int irq = ms->archdata.irqs[0]; if (irq == 0xffffffff) - irq = op->irqs[0]; + irq = op->archdata.irqs[0]; i8042_aux_irq = irq; } diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 1a57c3da1f49..370d3c17f24c 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -1079,7 +1079,7 @@ static int __devinit myri_sbus_probe(struct of_device *op, const struct of_devic mp->dev = dev; dev->watchdog_timeo = 5*HZ; - dev->irq = op->irqs[0]; + dev->irq = op->archdata.irqs[0]; dev->netdev_ops = &myri_ops; /* Register interrupt handler now. */ diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 63e8e3893bd6..5dd50b6ae776 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -9119,12 +9119,12 @@ static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) if (!int_prop) return -ENODEV; - for (i = 0; i < op->num_irqs; i++) { + for (i = 0; i < op->archdata.num_irqs; i++) { ldg_num_map[i] = int_prop[i]; - np->ldg[i].irq = op->irqs[i]; + np->ldg[i].irq = op->archdata.irqs[i]; } - np->num_ldg = op->num_irqs; + np->num_ldg = op->archdata.num_irqs; return 0; #else diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 367e96f317d4..0b10d24de051 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -1201,7 +1201,7 @@ static int __devinit bigmac_ether_init(struct of_device *op, dev->watchdog_timeo = 5*HZ; /* Finish net device registration. */ - dev->irq = bp->bigmac_op->irqs[0]; + dev->irq = bp->bigmac_op->archdata.irqs[0]; dev->dma = 0; if (register_netdev(dev)) { diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 3d9650b8d38f..0a63ebef86a0 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2561,7 +2561,7 @@ static int __init quattro_sbus_register_irqs(void) if (skip) continue; - err = request_irq(op->irqs[0], + err = request_irq(op->archdata.irqs[0], quattro_sbus_interrupt, IRQF_SHARED, "Quattro", qp); @@ -2590,7 +2590,7 @@ static void quattro_sbus_free_irqs(void) if (skip) continue; - free_irq(op->irqs[0], qp); + free_irq(op->archdata.irqs[0], qp); } } #endif /* CONFIG_SBUS */ @@ -2790,7 +2790,7 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) /* Happy Meal can do it all... */ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; - dev->irq = op->irqs[0]; + dev->irq = op->archdata.irqs[0]; #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) /* Hook up SBUS register/descriptor accessors. */ diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 7d9c33dd9d1a..c6bfdad6c0c8 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1474,7 +1474,7 @@ no_link_test: dev->ethtool_ops = &sparc_lance_ethtool_ops; dev->netdev_ops = &sparc_lance_ops; - dev->irq = op->irqs[0]; + dev->irq = op->archdata.irqs[0]; /* We cannot sleep if the chip is busy during a * multicast list update event, because such events diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 72b579c8d812..446517487084 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -803,7 +803,7 @@ static struct sunqec * __devinit get_qec(struct of_device *child) qec_init_once(qecp, op); - if (request_irq(op->irqs[0], qec_interrupt, + if (request_irq(op->archdata.irqs[0], qec_interrupt, IRQF_SHARED, "qec", (void *) qecp)) { printk(KERN_ERR "qec: Can't register irq.\n"); goto fail; @@ -901,7 +901,7 @@ static int __devinit qec_ether_init(struct of_device *op) SET_NETDEV_DEV(dev, &op->dev); dev->watchdog_timeo = 5*HZ; - dev->irq = op->irqs[0]; + dev->irq = op->archdata.irqs[0]; dev->dma = 0; dev->ethtool_ops = &qe_ethtool_ops; dev->netdev_ops = &qec_ops; @@ -999,7 +999,7 @@ static void __exit qec_exit(void) struct sunqec *next = root_qec_dev->next_module; struct of_device *op = root_qec_dev->op; - free_irq(op->irqs[0], (void *) root_qec_dev); + free_irq(op->archdata.irqs[0], (void *) root_qec_dev); of_iounmap(&op->resource[0], root_qec_dev->gregs, GLOB_REG_SIZE); kfree(root_qec_dev); diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 9a5b4b894161..3cdfe96e8999 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -295,7 +295,7 @@ static int __devinit bpp_probe(struct of_device *op, const struct of_device_id * void __iomem *base; struct parport *p; - irq = op->irqs[0]; + irq = op->archdata.irqs[0]; base = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "sunbpp"); diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 8bfdd63a1fcb..40d7a1fc69af 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -317,7 +317,7 @@ static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int inde bp->waiting = 0; init_waitqueue_head(&bp->wq); - if (request_irq(op->irqs[0], bbc_i2c_interrupt, + if (request_irq(op->archdata.irqs[0], bbc_i2c_interrupt, IRQF_SHARED, "bbc_i2c", bp)) goto fail; @@ -373,7 +373,7 @@ static int __devinit bbc_i2c_probe(struct of_device *op, err = bbc_envctrl_init(bp); if (err) { - free_irq(op->irqs[0], bp); + free_irq(op->archdata.irqs[0], bp); if (bp->i2c_bussel_reg) of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1); if (bp->i2c_control_regs) @@ -392,7 +392,7 @@ static int __devexit bbc_i2c_remove(struct of_device *op) bbc_envctrl_cleanup(bp); - free_irq(op->irqs[0], bp); + free_irq(op->archdata.irqs[0], bp); if (bp->i2c_bussel_reg) of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 5f253665a1da..b8b40e9eca79 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -367,7 +367,7 @@ static int __devinit uctrl_probe(struct of_device *op, goto out_free; } - p->irq = op->irqs[0]; + p->irq = op->archdata.irqs[0]; err = request_irq(p->irq, uctrl_interrupt, 0, "uctrl", p); if (err) { printk(KERN_ERR "uctrl: Unable to register irq.\n"); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index ca5c15c779cf..3f5b5411e6bc 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -729,7 +729,7 @@ static int __devinit qpti_register_irq(struct qlogicpti *qpti) { struct of_device *op = qpti->op; - qpti->qhost->irq = qpti->irq = op->irqs[0]; + qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; /* We used to try various overly-clever things to * reduce the interrupt processing overhead on @@ -1302,7 +1302,7 @@ static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_devic /* Sometimes Antares cards come up not completely * setup, and we get a report of a zero IRQ. */ - if (op->irqs[0] == 0) + if (op->archdata.irqs[0] == 0) return -ENODEV; host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index 386dd9d602b6..ddc221acd14c 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c @@ -116,7 +116,7 @@ static int __devinit esp_sbus_register_irq(struct esp *esp) struct Scsi_Host *host = esp->host; struct of_device *op = esp->dev; - host->irq = op->irqs[0]; + host->irq = op->archdata.irqs[0]; return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); } diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 890f91742962..36e244867dd8 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -525,7 +525,7 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m unsigned long minor; int err; - if (op->irqs[0] == 0xffffffff) + if (op->archdata.irqs[0] == 0xffffffff) return -ENODEV; port = kzalloc(sizeof(struct uart_port), GFP_KERNEL); @@ -557,7 +557,7 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m port->membase = (unsigned char __iomem *) __pa(port); - port->irq = op->irqs[0]; + port->irq = op->archdata.irqs[0]; port->dev = &op->dev; diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 5e81bc6b48b0..0a7dd6841ff8 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -969,7 +969,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up, return -ENOMEM; up->regs = (union sab82532_async_regs __iomem *) up->port.membase; - up->port.irq = op->irqs[0]; + up->port.irq = op->archdata.irqs[0]; up->port.fifosize = SAB82532_XMIT_FIFO_SIZE; up->port.iotype = UPIO_MEM; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 234459c2f012..56d891acf29e 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1443,7 +1443,7 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m return -ENOMEM; } - up->port.irq = op->irqs[0]; + up->port.irq = op->archdata.irqs[0]; up->port.dev = &op->dev; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index f9a24f4ebb34..fcbe20d48039 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1426,7 +1426,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m rp = sunzilog_chip_regs[inst]; if (zilog_irq == -1) - zilog_irq = op->irqs[0]; + zilog_irq = op->archdata.irqs[0]; up = &sunzilog_port_table[inst * 2]; @@ -1434,7 +1434,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m up[0].port.mapbase = op->resource[0].start + 0x00; up[0].port.membase = (void __iomem *) &rp->channelA; up[0].port.iotype = UPIO_MEM; - up[0].port.irq = op->irqs[0]; + up[0].port.irq = op->archdata.irqs[0]; up[0].port.uartclk = ZS_CLOCK; up[0].port.fifosize = 1; up[0].port.ops = &sunzilog_pops; @@ -1451,7 +1451,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m up[1].port.mapbase = op->resource[0].start + 0x04; up[1].port.membase = (void __iomem *) &rp->channelB; up[1].port.iotype = UPIO_MEM; - up[1].port.irq = op->irqs[0]; + up[1].port.irq = op->archdata.irqs[0]; up[1].port.uartclk = ZS_CLOCK; up[1].port.fifosize = 1; up[1].port.ops = &sunzilog_pops; @@ -1492,12 +1492,12 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m "is a %s\n", dev_name(&op->dev), (unsigned long long) up[0].port.mapbase, - op->irqs[0], sunzilog_type(&up[0].port)); + op->archdata.irqs[0], sunzilog_type(&up[0].port)); printk(KERN_INFO "%s: Mouse at MMIO 0x%llx (irq = %d) " "is a %s\n", dev_name(&op->dev), (unsigned long long) up[1].port.mapbase, - op->irqs[0], sunzilog_type(&up[1].port)); + op->archdata.irqs[0], sunzilog_type(&up[1].port)); kbm_inst++; } diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index d62b9ce8f773..8c03fd71693e 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -545,7 +545,7 @@ static int __devinit cpwd_probe(struct of_device *op, goto out; } - p->irq = op->irqs[0]; + p->irq = op->archdata.irqs[0]; spin_lock_init(&p->lock); diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 71221fd20944..43c63d441087 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -1010,7 +1010,7 @@ static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_de struct snd_amd7930 *amd; int err, irq; - irq = op->irqs[0]; + irq = op->archdata.irqs[0]; if (dev_num >= SNDRV_CARDS) return -ENODEV; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index fb4c6f2f29e5..f7f05c246303 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1832,14 +1832,14 @@ static int __devinit snd_cs4231_sbus_create(struct snd_card *card, chip->c_dma.request = sbus_dma_request; chip->c_dma.address = sbus_dma_addr; - if (request_irq(op->irqs[0], snd_cs4231_sbus_interrupt, + if (request_irq(op->archdata.irqs[0], snd_cs4231_sbus_interrupt, IRQF_SHARED, "cs4231", chip)) { snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n", - dev, op->irqs[0]); + dev, op->archdata.irqs[0]); snd_cs4231_sbus_free(chip); return -EBUSY; } - chip->irq[0] = op->irqs[0]; + chip->irq[0] = op->archdata.irqs[0]; if (snd_cs4231_probe(chip) < 0) { snd_cs4231_sbus_free(chip); @@ -1870,7 +1870,7 @@ static int __devinit cs4231_sbus_probe(struct of_device *op, const struct of_dev card->shortname, rp->flags & 0xffL, (unsigned long long)rp->start, - op->irqs[0]); + op->archdata.irqs[0]); err = snd_cs4231_sbus_create(card, op, dev); if (err < 0) { @@ -1979,12 +1979,12 @@ static int __devinit snd_cs4231_ebus_create(struct snd_card *card, chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback; chip->c_dma.ebus_info.client_cookie = chip; - chip->c_dma.ebus_info.irq = op->irqs[0]; + chip->c_dma.ebus_info.irq = op->archdata.irqs[0]; strcpy(chip->p_dma.ebus_info.name, "cs4231(play)"); chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback; chip->p_dma.ebus_info.client_cookie = chip; - chip->p_dma.ebus_info.irq = op->irqs[1]; + chip->p_dma.ebus_info.irq = op->archdata.irqs[1]; chip->p_dma.prepare = _ebus_dma_prepare; chip->p_dma.enable = _ebus_dma_enable; @@ -2060,7 +2060,7 @@ static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_dev sprintf(card->longname, "%s at 0x%llx, irq %d", card->shortname, op->resource[0].start, - op->irqs[0]); + op->archdata.irqs[0]); err = snd_cs4231_ebus_create(card, op, dev); if (err < 0) { diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 1557bf132e73..491ce71c84b6 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2608,7 +2608,7 @@ static int __devinit dbri_probe(struct of_device *op, const struct of_device_id return -ENOENT; } - irq = op->irqs[0]; + irq = op->archdata.irqs[0]; if (irq <= 0) { printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev); return -ENODEV; -- cgit v1.2.3 From 28172739f0a276eb8d6ca917b3974c2edb036da3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 7 Jul 2010 14:58:56 -0700 Subject: net: fix 64 bit counters on 32 bit arches There is a small possibility that a reader gets incorrect values on 32 bit arches. SNMP applications could catch incorrect counters when a 32bit high part is changed by another stats consumer/provider. One way to solve this is to add a rtnl_link_stats64 param to all ndo_get_stats64() methods, and also add such a parameter to dev_get_stats(). Rule is that we are not allowed to use dev->stats64 as a temporary storage for 64bit stats, but a caller provided area (usually on stack) Old drivers (only providing get_stats() method) need no changes. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- arch/s390/appldata/appldata_net_sum.c | 3 +- drivers/net/bonding/bond_main.c | 64 ++++++++++++++--------------- drivers/net/ixgbe/ixgbe_ethtool.c | 8 ++-- drivers/net/loopback.c | 4 +- drivers/net/macvlan.c | 6 +-- drivers/net/sfc/efx.c | 3 +- drivers/net/sfc/ethtool.c | 3 +- drivers/parisc/led.c | 3 +- drivers/scsi/fcoe/fcoe.c | 3 +- drivers/staging/batman-adv/hard-interface.c | 3 +- drivers/usb/gadget/rndis.c | 3 +- include/linux/netdevice.h | 12 ++++-- net/8021q/vlan_dev.c | 6 +-- net/8021q/vlanproc.c | 3 +- net/bridge/br_device.c | 4 +- net/core/dev.c | 25 +++++++---- net/core/net-sysfs.c | 4 +- net/core/rtnetlink.c | 3 +- 18 files changed, 89 insertions(+), 71 deletions(-) (limited to 'drivers/scsi') diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index 9a9586f4103f..f02e89ce4df1 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c @@ -85,7 +85,8 @@ static void appldata_get_net_sum_data(void *data) rcu_read_lock(); for_each_netdev_rcu(&init_net, dev) { - const struct net_device_stats *stats = dev_get_stats(dev); + struct rtnl_link_stats64 temp; + const struct net_device_stats *stats = dev_get_stats(dev, &temp); rx_packets += stats->rx_packets; tx_packets += stats->tx_packets; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a95a41b74b4e..9bb9bfa225b6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3804,51 +3804,49 @@ static int bond_close(struct net_device *bond_dev) return 0; } -static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev) +static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, + struct rtnl_link_stats64 *stats) { struct bonding *bond = netdev_priv(bond_dev); - struct rtnl_link_stats64 *stats = &bond_dev->stats64; - struct rtnl_link_stats64 local_stats; + struct rtnl_link_stats64 temp; struct slave *slave; int i; - memset(&local_stats, 0, sizeof(local_stats)); + memset(stats, 0, sizeof(*stats)); read_lock_bh(&bond->lock); bond_for_each_slave(bond, slave, i) { const struct rtnl_link_stats64 *sstats = - dev_get_stats(slave->dev); - - local_stats.rx_packets += sstats->rx_packets; - local_stats.rx_bytes += sstats->rx_bytes; - local_stats.rx_errors += sstats->rx_errors; - local_stats.rx_dropped += sstats->rx_dropped; - - local_stats.tx_packets += sstats->tx_packets; - local_stats.tx_bytes += sstats->tx_bytes; - local_stats.tx_errors += sstats->tx_errors; - local_stats.tx_dropped += sstats->tx_dropped; - - local_stats.multicast += sstats->multicast; - local_stats.collisions += sstats->collisions; - - local_stats.rx_length_errors += sstats->rx_length_errors; - local_stats.rx_over_errors += sstats->rx_over_errors; - local_stats.rx_crc_errors += sstats->rx_crc_errors; - local_stats.rx_frame_errors += sstats->rx_frame_errors; - local_stats.rx_fifo_errors += sstats->rx_fifo_errors; - local_stats.rx_missed_errors += sstats->rx_missed_errors; - - local_stats.tx_aborted_errors += sstats->tx_aborted_errors; - local_stats.tx_carrier_errors += sstats->tx_carrier_errors; - local_stats.tx_fifo_errors += sstats->tx_fifo_errors; - local_stats.tx_heartbeat_errors += sstats->tx_heartbeat_errors; - local_stats.tx_window_errors += sstats->tx_window_errors; + dev_get_stats(slave->dev, &temp); + + stats->rx_packets += sstats->rx_packets; + stats->rx_bytes += sstats->rx_bytes; + stats->rx_errors += sstats->rx_errors; + stats->rx_dropped += sstats->rx_dropped; + + stats->tx_packets += sstats->tx_packets; + stats->tx_bytes += sstats->tx_bytes; + stats->tx_errors += sstats->tx_errors; + stats->tx_dropped += sstats->tx_dropped; + + stats->multicast += sstats->multicast; + stats->collisions += sstats->collisions; + + stats->rx_length_errors += sstats->rx_length_errors; + stats->rx_over_errors += sstats->rx_over_errors; + stats->rx_crc_errors += sstats->rx_crc_errors; + stats->rx_frame_errors += sstats->rx_frame_errors; + stats->rx_fifo_errors += sstats->rx_fifo_errors; + stats->rx_missed_errors += sstats->rx_missed_errors; + + stats->tx_aborted_errors += sstats->tx_aborted_errors; + stats->tx_carrier_errors += sstats->tx_carrier_errors; + stats->tx_fifo_errors += sstats->tx_fifo_errors; + stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; + stats->tx_window_errors += sstats->tx_window_errors; } - memcpy(stats, &local_stats, sizeof(struct net_device_stats)); - read_unlock_bh(&bond->lock); return stats; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index b35ef36741ef..da54b38bb480 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -55,7 +55,7 @@ struct ixgbe_stats { offsetof(struct ixgbe_adapter, m) #define IXGBE_NETDEV_STAT(m) NETDEV_STATS, \ sizeof(((struct net_device *)0)->m), \ - offsetof(struct net_device, m) + offsetof(struct net_device, m) - offsetof(struct net_device, stats) static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"rx_packets", IXGBE_NETDEV_STAT(stats.rx_packets)}, @@ -998,16 +998,18 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, struct ixgbe_adapter *adapter = netdev_priv(netdev); u64 *queue_stat; int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64); + struct rtnl_link_stats64 temp; + const struct rtnl_link_stats64 *net_stats; int j, k; int i; char *p = NULL; ixgbe_update_stats(adapter); - dev_get_stats(netdev); + net_stats = dev_get_stats(netdev, &temp); for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { switch (ixgbe_gstrings_stats[i].type) { case NETDEV_STATS: - p = (char *) netdev + + p = (char *) net_stats + ixgbe_gstrings_stats[i].stat_offset; break; case IXGBE_STATS: diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 4dd0510d7a99..9a0996795321 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -98,10 +98,10 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } -static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev) +static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) { const struct pcpu_lstats __percpu *pcpu_lstats; - struct rtnl_link_stats64 *stats = &dev->stats64; u64 bytes = 0; u64 packets = 0; u64 drops = 0; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index e6d626e78515..6112f1498940 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -431,12 +431,12 @@ static void macvlan_uninit(struct net_device *dev) free_percpu(vlan->rx_stats); } -static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev) +static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) { - struct rtnl_link_stats64 *stats = &dev->stats64; struct macvlan_dev *vlan = netdev_priv(dev); - dev_txq_stats_fold(dev, &dev->stats); + dev_txq_stats_fold(dev, (struct net_device_stats *)stats); if (vlan->rx_stats) { struct macvlan_rx_stats *p, accum = {0}; diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 35b3f2922e5c..ba674c5ca29e 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1533,11 +1533,10 @@ static int efx_net_stop(struct net_device *net_dev) } /* Context: process, dev_base_lock or RTNL held, non-blocking. */ -static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev) +static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_mac_stats *mac_stats = &efx->mac_stats; - struct rtnl_link_stats64 *stats = &net_dev->stats64; spin_lock_bh(&efx->stats_lock); efx->type->update_stats(efx); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 3b8b0a062749..fd19d6ab97a2 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -469,12 +469,13 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, struct efx_mac_stats *mac_stats = &efx->mac_stats; struct efx_ethtool_stat *stat; struct efx_channel *channel; + struct rtnl_link_stats64 temp; int i; EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS); /* Update MAC and NIC statistics */ - dev_get_stats(net_dev); + dev_get_stats(net_dev, &temp); /* Fill detailed statistics buffer */ for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) { diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 188bc8496a26..18dff43b8bd2 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -355,12 +355,13 @@ static __inline__ int led_get_net_activity(void) rcu_read_lock(); for_each_netdev_rcu(&init_net, dev) { const struct net_device_stats *stats; + struct rtnl_link_stats64 temp; struct in_device *in_dev = __in_dev_get_rcu(dev); if (!in_dev || !in_dev->ifa_list) continue; if (ipv4_is_loopback(in_dev->ifa_list->ifa_local)) continue; - stats = dev_get_stats(dev); + stats = dev_get_stats(dev, &temp); rx_total += stats->rx_packets; tx_total += stats->tx_packets; } diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 44a07593de56..1a429ed6da9d 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2653,6 +2653,7 @@ static void fcoe_get_lesb(struct fc_lport *lport, u32 lfc, vlfc, mdac; struct fcoe_dev_stats *devst; struct fcoe_fc_els_lesb *lesb; + struct rtnl_link_stats64 temp; struct net_device *netdev = fcoe_netdev(lport); lfc = 0; @@ -2669,7 +2670,7 @@ static void fcoe_get_lesb(struct fc_lport *lport, lesb->lesb_link_fail = htonl(lfc); lesb->lesb_vlink_fail = htonl(vlfc); lesb->lesb_miss_fka = htonl(mdac); - lesb->lesb_fcs_error = htonl(dev_get_stats(netdev)->rx_crc_errors); + lesb->lesb_fcs_error = htonl(dev_get_stats(netdev, &temp)->rx_crc_errors); } /** diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 5ede9c255094..96c86c873011 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -440,6 +440,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct batman_packet *batman_packet; struct batman_if *batman_if; struct net_device_stats *stats; + struct rtnl_link_stats64 temp; int ret; skb = skb_share_check(skb, GFP_ATOMIC); @@ -468,7 +469,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (batman_if->if_status != IF_ACTIVE) goto err_free; - stats = (struct net_device_stats *)dev_get_stats(skb->dev); + stats = (struct net_device_stats *)dev_get_stats(skb->dev, &temp); if (stats) { stats->rx_packets++; stats->rx_bytes += skb->len; diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index fb69b01c8f3a..020fa5a25fda 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -171,6 +171,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, int i, count; rndis_query_cmplt_type *resp; struct net_device *net; + struct rtnl_link_stats64 temp; const struct rtnl_link_stats64 *stats; if (!r) return -ENOMEM; @@ -194,7 +195,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, resp->InformationBufferOffset = cpu_to_le32 (16); net = rndis_per_dev_params[configNr].dev; - stats = dev_get_stats(net); + stats = dev_get_stats(net, &temp); switch (OID) { diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4d27368674db..60de65316fdb 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -666,7 +666,8 @@ struct netdev_rx_queue { * Callback uses when the transmitter has not made any progress * for dev->watchdog ticks. * - * struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev); + * struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev + * struct rtnl_link_stats64 *storage); * struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); * Called when a user wants to get the network device usage * statistics. Drivers must do one of the following: @@ -733,7 +734,8 @@ struct net_device_ops { struct neigh_parms *); void (*ndo_tx_timeout) (struct net_device *dev); - struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev); + struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev, + struct rtnl_link_stats64 *storage); struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); void (*ndo_vlan_rx_register)(struct net_device *dev, @@ -2139,8 +2141,10 @@ extern void netdev_features_change(struct net_device *dev); /* Load a device via the kmod */ extern void dev_load(struct net *net, const char *name); extern void dev_mcast_init(void); -extern const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev); -extern void dev_txq_stats_fold(const struct net_device *dev, struct net_device_stats *stats); +extern const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, + struct rtnl_link_stats64 *storage); +extern void dev_txq_stats_fold(const struct net_device *dev, + struct net_device_stats *stats); extern int netdev_max_backlog; extern int netdev_tstamp_prequeue; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index c6456cb842fa..7865a4ce5250 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -803,11 +803,9 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev) return dev_ethtool_get_flags(vlan->real_dev); } -static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev) +static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { - struct rtnl_link_stats64 *stats = &dev->stats64; - - dev_txq_stats_fold(dev, &dev->stats); + dev_txq_stats_fold(dev, (struct net_device_stats *)stats); if (vlan_dev_info(dev)->vlan_rx_stats) { struct vlan_rx_stats *p, accum = {0}; diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index df56f5ce887c..80e280f56686 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -278,6 +278,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) { struct net_device *vlandev = (struct net_device *) seq->private; const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); + struct rtnl_link_stats64 temp; const struct rtnl_link_stats64 *stats; static const char fmt[] = "%30s %12lu\n"; static const char fmt64[] = "%30s %12llu\n"; @@ -286,7 +287,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) if (!is_vlan_dev(vlandev)) return 0; - stats = dev_get_stats(vlandev); + stats = dev_get_stats(vlandev, &temp); seq_printf(seq, "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", vlandev->name, dev_info->vlan_id, diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index edf639e96281..075c435ad22d 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -98,10 +98,10 @@ static int br_dev_stop(struct net_device *dev) return 0; } -static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev) +static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) { struct net_bridge *br = netdev_priv(dev); - struct rtnl_link_stats64 *stats = &dev->stats64; struct br_cpu_netstats tmp, sum = { 0 }; unsigned int cpu; diff --git a/net/core/dev.c b/net/core/dev.c index 93b8929fa21d..92482d7a87a9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3703,7 +3703,8 @@ void dev_seq_stop(struct seq_file *seq, void *v) static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) { - const struct rtnl_link_stats64 *stats = dev_get_stats(dev); + struct rtnl_link_stats64 temp; + const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp); seq_printf(seq, "%6s: %7llu %7llu %4llu %4llu %4llu %5llu %10llu %9llu " "%8llu %7llu %4llu %4llu %4llu %5llu %7llu %10llu\n", @@ -5281,23 +5282,29 @@ EXPORT_SYMBOL(dev_txq_stats_fold); /** * dev_get_stats - get network device statistics * @dev: device to get statistics from + * @storage: place to store stats * * Get network statistics from device. The device driver may provide * its own method by setting dev->netdev_ops->get_stats64 or * dev->netdev_ops->get_stats; otherwise the internal statistics * structure is used. */ -const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev) +const struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, + struct rtnl_link_stats64 *storage) { const struct net_device_ops *ops = dev->netdev_ops; - if (ops->ndo_get_stats64) - return ops->ndo_get_stats64(dev); - if (ops->ndo_get_stats) - return (struct rtnl_link_stats64 *)ops->ndo_get_stats(dev); - - dev_txq_stats_fold(dev, &dev->stats); - return &dev->stats64; + if (ops->ndo_get_stats64) { + memset(storage, 0, sizeof(*storage)); + return ops->ndo_get_stats64(dev, storage); + } + if (ops->ndo_get_stats) { + memcpy(storage, ops->ndo_get_stats(dev), sizeof(*storage)); + return storage; + } + memcpy(storage, &dev->stats, sizeof(*storage)); + dev_txq_stats_fold(dev, (struct net_device_stats *)storage); + return storage; } EXPORT_SYMBOL(dev_get_stats); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index ea3bb4c3b87d..914f42b0f039 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -330,7 +330,9 @@ static ssize_t netstat_show(const struct device *d, read_lock(&dev_base_lock); if (dev_isalive(dev)) { - const struct rtnl_link_stats64 *stats = dev_get_stats(dev); + struct rtnl_link_stats64 temp; + const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp); + ret = sprintf(buf, fmt_u64, *(u64 *)(((u8 *) stats) + offset)); } read_unlock(&dev_base_lock); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e645778e9b7e..5e773ea2201d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -791,6 +791,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, { struct ifinfomsg *ifm; struct nlmsghdr *nlh; + struct rtnl_link_stats64 temp; const struct rtnl_link_stats64 *stats; struct nlattr *attr; @@ -847,7 +848,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, if (attr == NULL) goto nla_put_failure; - stats = dev_get_stats(dev); + stats = dev_get_stats(dev, &temp); copy_rtnl_link_stats(nla_data(attr), stats); attr = nla_reserve(skb, IFLA_STATS64, -- cgit v1.2.3 From 698f93159a735bd29a8767c9f60d9b2d75870f8e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 2 Jul 2010 20:41:51 +0200 Subject: fix comment/printk typos concerning "already" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Jiri Kosina --- drivers/block/drbd/drbd_receiver.c | 2 +- drivers/isdn/hardware/mISDN/avmfritz.c | 2 +- drivers/isdn/hardware/mISDN/hfcmulti.c | 4 ++-- drivers/isdn/hardware/mISDN/hfcpci.c | 2 +- drivers/isdn/hardware/mISDN/mISDNinfineon.c | 2 +- drivers/isdn/hardware/mISDN/speedfax.c | 2 +- drivers/isdn/hardware/mISDN/w6692.c | 2 +- drivers/isdn/hisax/callc.c | 2 +- drivers/isdn/hisax/tei.c | 2 +- drivers/isdn/mISDN/tei.c | 2 +- drivers/media/video/zoran/zoran_device.c | 2 +- drivers/scsi/bfa/bfa_ioim.c | 2 +- drivers/usb/host/fhci-sched.c | 2 +- kernel/time/tick-broadcast.c | 2 +- net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index dff48701b84d..ec1711f7c5c5 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1087,7 +1087,7 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev, } else { epoch->flags = 0; atomic_set(&epoch->epoch_size, 0); - /* atomic_set(&epoch->active, 0); is alrady zero */ + /* atomic_set(&epoch->active, 0); is already zero */ if (rv == FE_STILL_LIVE) rv = FE_RECYCLED; } diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index d4215369bb59..472a2af79446 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -1116,7 +1116,7 @@ fritz_remove_pci(struct pci_dev *pdev) release_card(card); else if (debug) - pr_info("%s: drvdata allready removed\n", __func__); + pr_info("%s: drvdata already removed\n", __func__); } static struct pci_device_id fcpci_ids[] __devinitdata = { diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 095ed76ebe80..d3171954fa45 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -4268,7 +4268,7 @@ init_card(struct hfc_multi *hc) goto error; /* * Finally enable IRQ output - * this is only allowed, if an IRQ routine is allready + * this is only allowed, if an IRQ routine is already * established for this HFC, so don't do that earlier */ spin_lock_irqsave(&hc->lock, flags); @@ -5212,7 +5212,7 @@ static void __devexit hfc_remove_pci(struct pci_dev *pdev) spin_unlock_irqrestore(&HFClock, flags); } else { if (debug) - printk(KERN_DEBUG "%s: drvdata allready removed\n", + printk(KERN_DEBUG "%s: drvdata already removed\n", __func__); } } diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 5940a2c12074..65ded0576013 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -1773,7 +1773,7 @@ init_card(struct hfc_pci *hc) inithfcpci(hc); /* * Finally enable IRQ output - * this is only allowed, if an IRQ routine is allready + * this is only allowed, if an IRQ routine is already * established for this HFC, so don't do that earlier */ enable_hwirq(hc); diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c index f5b3d2b26a08..4975976e93ac 100644 --- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c @@ -1150,7 +1150,7 @@ inf_remove(struct pci_dev *pdev) if (card) release_card(card); else - pr_debug("%s: drvdata allready removed\n", __func__); + pr_debug("%s: drvdata already removed\n", __func__); } static struct pci_driver infineon_driver = { diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c index d097a4e40e2b..9e07246bb9e7 100644 --- a/drivers/isdn/hardware/mISDN/speedfax.c +++ b/drivers/isdn/hardware/mISDN/speedfax.c @@ -484,7 +484,7 @@ sfax_remove_pci(struct pci_dev *pdev) if (card) release_card(card); else - pr_debug("%s: drvdata allready removed\n", __func__); + pr_debug("%s: drvdata already removed\n", __func__); } static struct pci_device_id sfaxpci_ids[] __devinitdata = { diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 31f9d71fb22f..9e84870b971c 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -1402,7 +1402,7 @@ w6692_remove_pci(struct pci_dev *pdev) release_card(card); else if (debug) - pr_notice("%s: drvdata allready removed\n", __func__); + pr_notice("%s: drvdata already removed\n", __func__); } static struct pci_device_id w6692_ids[] = { diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index f58ded8f403f..f150330b5a23 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -1172,7 +1172,7 @@ CallcFreeChan(struct IsdnCardState *csta) kfree(csta->channel[i].b_st); csta->channel[i].b_st = NULL; } else - printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i); + printk(KERN_WARNING "CallcFreeChan b_st ch%d already freed\n", i); if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { release_d_st(csta->channel + i); } else diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c index f4cb178b0666..842f9c9e875d 100644 --- a/drivers/isdn/hisax/tei.c +++ b/drivers/isdn/hisax/tei.c @@ -130,7 +130,7 @@ tei_id_request(struct FsmInst *fi, int event, void *arg) if (st->l2.tei != -1) { st->ma.tei_m.printdebug(&st->ma.tei_m, - "assign request for allready asigned tei %d", + "assign request for already asigned tei %d", st->l2.tei); return; } diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index 34e898fe2f4f..1b85d9d27496 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -457,7 +457,7 @@ tei_id_request(struct FsmInst *fi, int event, void *arg) if (tm->l2->tei != GROUP_TEI) { tm->tei_m.printdebug(&tm->tei_m, - "assign request for allready assigned tei %d", + "assign request for already assigned tei %d", tm->l2->tei); return; } diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index e6ad4b205611..6f846abee3e4 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -484,7 +484,7 @@ zr36057_overlay (struct zoran *zr, zr->overlay_settings.format); /* Start and length of each line MUST be 4-byte aligned. - * This should be allready checked before the call to this routine. + * This should be already checked before the call to this routine. * All error messages are internal driver checking only! */ /* video display top and bottom registers */ diff --git a/drivers/scsi/bfa/bfa_ioim.c b/drivers/scsi/bfa/bfa_ioim.c index 687f3d6e252b..3d2eac104308 100644 --- a/drivers/scsi/bfa/bfa_ioim.c +++ b/drivers/scsi/bfa/bfa_ioim.c @@ -488,7 +488,7 @@ bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_ABORT: /** - * IO is alraedy being cleaned up implicitly + * IO is already being cleaned up implicitly */ ioim->io_cbfn = __bfa_cb_ioim_abort; break; diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 4f2cbdcc0273..a42ef380e917 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c @@ -125,7 +125,7 @@ void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt) /* * Flush all transmitted packets from BDs * This routine is called when disabling the USB port to flush all - * transmissions that are allready scheduled in the BDs + * transmissions that are already scheduled in the BDs */ void fhci_flush_all_transmissions(struct fhci_usb *usb) { diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index b3bafd5fc66d..48b2761b5668 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -188,7 +188,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) /* * Setup the next period for devices, which do not have * periodic mode. We read dev->next_event first and add to it - * when the event alrady expired. clockevents_program_event() + * when the event already expired. clockevents_program_event() * sets dev->next_event only when the event is really * programmed to the device. */ diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 6fb890187de0..4dc8805154ee 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -201,7 +201,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, int offset, end; if (fq->q.last_in & INET_FRAG_COMPLETE) { - pr_debug("Allready completed\n"); + pr_debug("Already completed\n"); goto err; } -- cgit v1.2.3 From a7ce2e0d04b1a6ee8056e7fea5ea96566d33a6f4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 12 Jul 2010 17:15:44 +0200 Subject: fix comnment/printk typos concerning "empty" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Jiri Kosina --- Documentation/scsi/ChangeLog.lpfc | 2 +- arch/arm/plat-mxc/dma-mx1-mx2.c | 2 +- drivers/scsi/aic7xxx_old/aic7xxx.seq | 2 +- drivers/serial/nwpserial.c | 2 +- sound/usb/pcm.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/Documentation/scsi/ChangeLog.lpfc b/Documentation/scsi/ChangeLog.lpfc index e759e92e286d..337c924cc81f 100644 --- a/Documentation/scsi/ChangeLog.lpfc +++ b/Documentation/scsi/ChangeLog.lpfc @@ -807,7 +807,7 @@ Changes from 20040908 to 20040920 lpfc_disc_done/lpfc_do_dpc cleanup - lpfc_disc_done can return void - move lpfc_do_dpc and lpfc_disc_done to lpfc_hbadisc.c - remove checking of list emptiness before calling lpfc_disc_done, - it handles the emtpy list case just fine and the additional + it handles the empty list case just fine and the additional instructions cost less then the bustlocked spinlock operations. * Integrated patch from Christoph Hellwig: This adds a new 64bit counter instead, brd_no isn't reused anymore. Also some tiny diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c index 3765ac0d671a..68988af19b1c 100644 --- a/arch/arm/plat-mxc/dma-mx1-mx2.c +++ b/arch/arm/plat-mxc/dma-mx1-mx2.c @@ -310,7 +310,7 @@ imx_dma_setup_sg(int channel, imxdma->resbytes = dma_length; if (!sg || !sgcount) { - printk(KERN_ERR "imxdma%d: imx_dma_setup_sg epty sg list\n", + printk(KERN_ERR "imxdma%d: imx_dma_setup_sg empty sg list\n", channel); return -EINVAL; } diff --git a/drivers/scsi/aic7xxx_old/aic7xxx.seq b/drivers/scsi/aic7xxx_old/aic7xxx.seq index f6fc4b75b5a5..5997e7c3a191 100644 --- a/drivers/scsi/aic7xxx_old/aic7xxx.seq +++ b/drivers/scsi/aic7xxx_old/aic7xxx.seq @@ -615,7 +615,7 @@ ultra2_dmafifoflush: * went empty and the next bit of data is copied from * the SCSI fifo into the PCI fifo. It should only * come on when both FIFOs (meaning the entire FIFO - * chain) are emtpy. Since it can take up to 4 cycles + * chain) are empty. Since it can take up to 4 cycles * for new data to be copied from the SCSI fifo into * the PCI fifo, testing for FIFOEMP status for 4 * extra times gives the needed time for any diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c index 3c02fa96f282..e65b0d9202a5 100644 --- a/drivers/serial/nwpserial.c +++ b/drivers/serial/nwpserial.c @@ -81,7 +81,7 @@ nwpserial_console_write(struct console *co, const char *s, unsigned int count) uart_console_write(&up->port, s, count, nwpserial_console_putchar); - /* wait for transmitter to become emtpy */ + /* wait for transmitter to become empty */ while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0) cpu_relax(); diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 456829882f40..3634cedf9306 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -636,7 +636,7 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params, min_datainterval = min(min_datainterval, fp->datainterval); } if (min_datainterval == 0xff) { - hwc_debug(" --> get emtpy\n"); + hwc_debug(" --> get empty\n"); it->empty = 1; return -EINVAL; } -- cgit v1.2.3 From 501af8d110f1fca597ff61c8611d018360ff9bf7 Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Mon, 28 Jun 2010 15:55:04 +0400 Subject: scsi: bfa: use ARRAY_SIZE Change sizeof(x) / sizeof(*x) to ARRAY_SIZE(x). Signed-off-by: Kulikov Vasiliy Signed-off-by: Jiri Kosina --- drivers/scsi/bfa/bfa_core.c | 2 +- drivers/scsi/bfa/bfa_fcs.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 3a7b3f88932f..d84550636add 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -335,7 +335,7 @@ bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids) {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT}, }; - *npciids = sizeof(__pciids) / sizeof(__pciids[0]); + *npciids = ARRAY_SIZE(__pciids); *pciids = __pciids; } diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index 3516172c597c..153cb2a3ffe3 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -86,7 +86,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, bfa_attach_fcs(bfa); fcbuild_init(); - for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { + for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { mod = &fcs_modules[i]; if (mod->attach) mod->attach(fcs); @@ -102,7 +102,7 @@ bfa_fcs_init(struct bfa_fcs_s *fcs) int i; struct bfa_fcs_mod_s *mod; - for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { + for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { mod = &fcs_modules[i]; if (mod->modinit) mod->modinit(fcs); @@ -163,13 +163,11 @@ void bfa_fcs_exit(struct bfa_fcs_s *fcs) { struct bfa_fcs_mod_s *mod; - int nmods, i; + int i; bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs); - nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]); - - for (i = 0; i < nmods; i++) { + for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { mod = &fcs_modules[i]; if (mod->modexit) { -- cgit v1.2.3 From 7156fffaaa15aeb0e0247736eff0a86f75f49f81 Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Mon, 28 Jun 2010 15:55:12 +0400 Subject: libfc: use ARRAY_SIZE Change sizeof(x) / sizeof(*x) to ARRAY_SIZE(x). Signed-off-by: Kulikov Vasiliy Signed-off-by: Jiri Kosina --- drivers/scsi/libfc/fc_exch.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 104e0fba7c43..ca52bfa4a1ec 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -219,8 +219,6 @@ static void fc_exch_els_rrq(struct fc_seq *, struct fc_frame *); */ static char *fc_exch_rctl_names[] = FC_RCTL_NAMES_INIT; -#define FC_TABLE_SIZE(x) (sizeof(x) / sizeof(x[0])) - /** * fc_exch_name_lookup() - Lookup name by opcode * @op: Opcode to be looked up @@ -249,7 +247,7 @@ static inline const char *fc_exch_name_lookup(unsigned int op, char **table, static const char *fc_exch_rctl_name(unsigned int op) { return fc_exch_name_lookup(op, fc_exch_rctl_names, - FC_TABLE_SIZE(fc_exch_rctl_names)); + ARRAY_SIZE(fc_exch_rctl_names)); } /** -- cgit v1.2.3 From 1ab1d63a85cee2545272f63a7644e9f855cb65d0 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 24 Jun 2010 15:14:37 -0600 Subject: of/platform: remove all of_bus_type and of_platform_bus_type references Both of_bus_type and of_platform_bus_type are just #define aliases for the platform bus. This patch removes all references to them and switches to the of_register_platform_driver()/of_unregister_platform_driver() API for registering. Subsequent patches will convert each user of of_register_platform_driver() into plain platform_drivers without the of_platform_driver shim. At which point the of_register_platform_driver()/of_unregister_platform_driver() functions can be removed. Signed-off-by: Grant Likely Acked-by: David S. Miller --- arch/microblaze/kernel/of_platform.c | 3 +-- arch/powerpc/kernel/of_platform.c | 3 +-- arch/sparc/include/asm/of_platform.h | 2 -- arch/sparc/include/asm/parport.h | 4 +--- arch/sparc/kernel/apc.c | 2 +- arch/sparc/kernel/auxio_64.c | 2 +- arch/sparc/kernel/central.c | 4 ++-- arch/sparc/kernel/chmc.c | 4 ++-- arch/sparc/kernel/of_device_common.c | 2 +- arch/sparc/kernel/pci_fire.c | 2 +- arch/sparc/kernel/pci_psycho.c | 2 +- arch/sparc/kernel/pci_sabre.c | 2 +- arch/sparc/kernel/pci_schizo.c | 2 +- arch/sparc/kernel/pci_sun4v.c | 2 +- arch/sparc/kernel/pmc.c | 2 +- arch/sparc/kernel/power.c | 2 +- arch/sparc/kernel/time_32.c | 2 +- arch/sparc/kernel/time_64.c | 6 +++--- drivers/atm/fore200e.c | 6 +++--- drivers/char/hw_random/n2-drv.c | 4 ++-- drivers/crypto/n2_core.c | 10 +++++----- drivers/hwmon/ultra45_env.c | 4 ++-- drivers/input/misc/sparcspkr.c | 12 +++++------- drivers/input/serio/i8042-sparcio.h | 5 ++--- drivers/mtd/maps/sun_uflash.c | 4 ++-- drivers/net/ibm_newemac/core.c | 4 ++-- drivers/net/myri_sbus.c | 4 ++-- drivers/net/niu.c | 6 +++--- drivers/net/sunbmac.c | 4 ++-- drivers/net/sunhme.c | 4 ++-- drivers/net/sunlance.c | 4 ++-- drivers/net/sunqe.c | 4 ++-- drivers/parport/parport_sunbpp.c | 4 ++-- drivers/sbus/char/bbc_i2c.c | 4 ++-- drivers/sbus/char/display7seg.c | 4 ++-- drivers/sbus/char/envctrl.c | 4 ++-- drivers/sbus/char/flash.c | 4 ++-- drivers/sbus/char/uctrl.c | 4 ++-- drivers/scsi/qlogicpti.c | 4 ++-- drivers/scsi/sun_esp.c | 4 ++-- drivers/serial/sunhv.c | 4 ++-- drivers/serial/sunsab.c | 4 ++-- drivers/serial/sunsu.c | 2 +- drivers/serial/sunzilog.c | 6 +++--- drivers/video/bw2.c | 4 ++-- drivers/video/cg14.c | 4 ++-- drivers/video/cg3.c | 4 ++-- drivers/video/cg6.c | 4 ++-- drivers/video/ffb.c | 4 ++-- drivers/video/leo.c | 4 ++-- drivers/video/p9100.c | 4 ++-- drivers/video/sunxvr1000.c | 4 ++-- drivers/video/tcx.c | 4 ++-- drivers/watchdog/cpwd.c | 4 ++-- drivers/watchdog/riowd.c | 4 ++-- include/linux/of_platform.h | 6 ------ sound/sparc/amd7930.c | 4 ++-- sound/sparc/cs4231.c | 4 ++-- sound/sparc/dbri.c | 4 ++-- 59 files changed, 109 insertions(+), 124 deletions(-) (limited to 'drivers/scsi') diff --git a/arch/microblaze/kernel/of_platform.c b/arch/microblaze/kernel/of_platform.c index fb2866104331..80c9c493cb25 100644 --- a/arch/microblaze/kernel/of_platform.c +++ b/arch/microblaze/kernel/of_platform.c @@ -57,8 +57,7 @@ struct of_device *of_find_device_by_node(struct device_node *np) { struct device *dev; - dev = bus_find_device(&of_platform_bus_type, - NULL, np, of_dev_node_match); + dev = bus_find_device(&platform_bus_type, NULL, np, of_dev_node_match); if (dev) return to_of_device(dev); return NULL; diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index d3497cd81e8a..b093d4b1f09c 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -61,8 +61,7 @@ struct of_device *of_find_device_by_node(struct device_node *np) { struct device *dev; - dev = bus_find_device(&of_platform_bus_type, - NULL, np, of_dev_node_match); + dev = bus_find_device(&platform_bus_type, NULL, np, of_dev_node_match); if (dev) return to_of_device(dev); return NULL; diff --git a/arch/sparc/include/asm/of_platform.h b/arch/sparc/include/asm/of_platform.h index 90da99059f83..26540ddfc511 100644 --- a/arch/sparc/include/asm/of_platform.h +++ b/arch/sparc/include/asm/of_platform.h @@ -13,6 +13,4 @@ * */ -#define of_bus_type of_platform_bus_type /* for compatibility */ - #endif diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index 0c34a8792fc7..4891fbce1114 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h @@ -243,9 +243,7 @@ static struct of_platform_driver ecpp_driver = { static int parport_pc_find_nonpci_ports(int autoirq, int autodma) { - of_register_driver(&ecpp_driver, &of_bus_type); - - return 0; + return of_register_platform_driver(&ecpp_driver); } #endif /* !(_ASM_SPARC64_PARPORT_H */ diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index b27476caa133..c471251cd3f1 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -184,7 +184,7 @@ static struct of_platform_driver apc_driver = { static int __init apc_init(void) { - return of_register_driver(&apc_driver, &of_bus_type); + return of_register_platform_driver(&apc_driver); } /* This driver is not critical to the boot process diff --git a/arch/sparc/kernel/auxio_64.c b/arch/sparc/kernel/auxio_64.c index ddc84128b3c2..46ba58a8510f 100644 --- a/arch/sparc/kernel/auxio_64.c +++ b/arch/sparc/kernel/auxio_64.c @@ -142,7 +142,7 @@ static struct of_platform_driver auxio_driver = { static int __init auxio_init(void) { - return of_register_driver(&auxio_driver, &of_platform_bus_type); + return of_register_platform_driver(&auxio_driver); } /* Must be after subsys_initcall() so that busses are probed. Must diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c index 434335f65823..b6080c39ed4b 100644 --- a/arch/sparc/kernel/central.c +++ b/arch/sparc/kernel/central.c @@ -265,8 +265,8 @@ static struct of_platform_driver fhc_driver = { static int __init sunfire_init(void) { - (void) of_register_driver(&fhc_driver, &of_platform_bus_type); - (void) of_register_driver(&clock_board_driver, &of_platform_bus_type); + (void) of_register_platform_driver(&fhc_driver); + (void) of_register_platform_driver(&clock_board_driver); return 0; } diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c index 870cb65b3f21..04bb7df9f716 100644 --- a/arch/sparc/kernel/chmc.c +++ b/arch/sparc/kernel/chmc.c @@ -848,7 +848,7 @@ static int __init us3mc_init(void) ret = register_dimm_printer(us3mc_dimm_printer); if (!ret) { - ret = of_register_driver(&us3mc_driver, &of_bus_type); + ret = of_register_platform_driver(&us3mc_driver); if (ret) unregister_dimm_printer(us3mc_dimm_printer); } @@ -859,7 +859,7 @@ static void __exit us3mc_cleanup(void) { if (us3mc_platform()) { unregister_dimm_printer(us3mc_dimm_printer); - of_unregister_driver(&us3mc_driver); + of_unregister_platform_driver(&us3mc_driver); } } diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c index 01f380c7995c..2a5c639e4c3f 100644 --- a/arch/sparc/kernel/of_device_common.c +++ b/arch/sparc/kernel/of_device_common.c @@ -21,7 +21,7 @@ static int node_match(struct device *dev, void *data) struct of_device *of_find_device_by_node(struct device_node *dp) { - struct device *dev = bus_find_device(&of_platform_bus_type, NULL, + struct device *dev = bus_find_device(&platform_bus_type, NULL, dp, node_match); if (dev) diff --git a/arch/sparc/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c index 51cfa09e392a..885f10b742e2 100644 --- a/arch/sparc/kernel/pci_fire.c +++ b/arch/sparc/kernel/pci_fire.c @@ -518,7 +518,7 @@ static struct of_platform_driver fire_driver = { static int __init fire_init(void) { - return of_register_driver(&fire_driver, &of_bus_type); + return of_register_platform_driver(&fire_driver); } subsys_initcall(fire_init); diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c index 93011e6e7ddc..71550a7aacd8 100644 --- a/arch/sparc/kernel/pci_psycho.c +++ b/arch/sparc/kernel/pci_psycho.c @@ -612,7 +612,7 @@ static struct of_platform_driver psycho_driver = { static int __init psycho_init(void) { - return of_register_driver(&psycho_driver, &of_bus_type); + return of_register_platform_driver(&psycho_driver); } subsys_initcall(psycho_init); diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c index 99c6dba7d4fd..2d7bf30552dd 100644 --- a/arch/sparc/kernel/pci_sabre.c +++ b/arch/sparc/kernel/pci_sabre.c @@ -606,7 +606,7 @@ static struct of_platform_driver sabre_driver = { static int __init sabre_init(void) { - return of_register_driver(&sabre_driver, &of_bus_type); + return of_register_platform_driver(&sabre_driver); } subsys_initcall(sabre_init); diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 9041dae7aaca..04f29c46bfa0 100644 --- a/arch/sparc/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c @@ -1501,7 +1501,7 @@ static struct of_platform_driver schizo_driver = { static int __init schizo_init(void) { - return of_register_driver(&schizo_driver, &of_bus_type); + return of_register_platform_driver(&schizo_driver); } subsys_initcall(schizo_init); diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index a24af6f7e17f..18ee8b6f4036 100644 --- a/arch/sparc/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c @@ -1019,7 +1019,7 @@ static struct of_platform_driver pci_sun4v_driver = { static int __init pci_sun4v_init(void) { - return of_register_driver(&pci_sun4v_driver, &of_bus_type); + return of_register_platform_driver(&pci_sun4v_driver); } subsys_initcall(pci_sun4v_init); diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 9589d8b9b0c1..a4c73edc8975 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -89,7 +89,7 @@ static struct of_platform_driver pmc_driver = { static int __init pmc_init(void) { - return of_register_driver(&pmc_driver, &of_bus_type); + return of_register_platform_driver(&pmc_driver); } /* This driver is not critical to the boot process diff --git a/arch/sparc/kernel/power.c b/arch/sparc/kernel/power.c index 1cfee577f6b5..abc194ed5a78 100644 --- a/arch/sparc/kernel/power.c +++ b/arch/sparc/kernel/power.c @@ -70,7 +70,7 @@ static struct of_platform_driver power_driver = { static int __init power_init(void) { - return of_register_driver(&power_driver, &of_platform_bus_type); + return of_register_platform_driver(&power_driver); } device_initcall(power_init); diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index e404b063be2c..5dc20216952e 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -189,7 +189,7 @@ static struct of_platform_driver clock_driver = { /* Probe for the mostek real time clock chip. */ static int __init clock_init(void) { - return of_register_driver(&clock_driver, &of_platform_bus_type); + return of_register_platform_driver(&clock_driver); } /* Must be after subsys_initcall() so that busses are probed. Must * be before device_initcall() because things like the RTC driver diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 21e9fcae0668..2423b336a717 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -586,9 +586,9 @@ static int __init clock_init(void) if (tlb_type == hypervisor) return platform_device_register(&rtc_sun4v_device); - (void) of_register_driver(&rtc_driver, &of_platform_bus_type); - (void) of_register_driver(&mostek_driver, &of_platform_bus_type); - (void) of_register_driver(&bq4802_driver, &of_platform_bus_type); + (void) of_register_platform_driver(&rtc_driver); + (void) of_register_platform_driver(&mostek_driver); + (void) of_register_platform_driver(&bq4802_driver); return 0; } diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 38df87b198d5..b7385e077717 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -2795,7 +2795,7 @@ static int __init fore200e_module_init(void) printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n"); #ifdef CONFIG_SBUS - err = of_register_driver(&fore200e_sba_driver, &of_bus_type); + err = of_register_platform_driver(&fore200e_sba_driver); if (err) return err; #endif @@ -2806,7 +2806,7 @@ static int __init fore200e_module_init(void) #ifdef CONFIG_SBUS if (err) - of_unregister_driver(&fore200e_sba_driver); + of_unregister_platform_driver(&fore200e_sba_driver); #endif return err; @@ -2818,7 +2818,7 @@ static void __exit fore200e_module_cleanup(void) pci_unregister_driver(&fore200e_pca_driver); #endif #ifdef CONFIG_SBUS - of_unregister_driver(&fore200e_sba_driver); + of_unregister_platform_driver(&fore200e_sba_driver); #endif } diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 0f9cbf1aaf15..d8a4ca87987d 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -762,12 +762,12 @@ static struct of_platform_driver n2rng_driver = { static int __init n2rng_init(void) { - return of_register_driver(&n2rng_driver, &of_bus_type); + return of_register_platform_driver(&n2rng_driver); } static void __exit n2rng_exit(void) { - of_unregister_driver(&n2rng_driver); + of_unregister_platform_driver(&n2rng_driver); } module_init(n2rng_init); diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 23163fda5035..34ac8ac8aaec 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -2070,20 +2070,20 @@ static struct of_platform_driver n2_mau_driver = { static int __init n2_init(void) { - int err = of_register_driver(&n2_crypto_driver, &of_bus_type); + int err = of_register_platform_driver(&n2_crypto_driver); if (!err) { - err = of_register_driver(&n2_mau_driver, &of_bus_type); + err = of_register_platform_driver(&n2_mau_driver); if (err) - of_unregister_driver(&n2_crypto_driver); + of_unregister_platform_driver(&n2_crypto_driver); } return err; } static void __exit n2_exit(void) { - of_unregister_driver(&n2_mau_driver); - of_unregister_driver(&n2_crypto_driver); + of_unregister_platform_driver(&n2_mau_driver); + of_unregister_platform_driver(&n2_crypto_driver); } module_init(n2_init); diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index 5da5942cf970..89643261ccdb 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c @@ -311,12 +311,12 @@ static struct of_platform_driver env_driver = { static int __init env_init(void) { - return of_register_driver(&env_driver, &of_bus_type); + return of_register_platform_driver(&env_driver); } static void __exit env_exit(void) { - of_unregister_driver(&env_driver); + of_unregister_platform_driver(&env_driver); } module_init(env_init); diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index 1dacae4b43f0..f3bb92e9755f 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -353,14 +353,12 @@ static struct of_platform_driver grover_beep_driver = { static int __init sparcspkr_init(void) { - int err = of_register_driver(&bbc_beep_driver, - &of_platform_bus_type); + int err = of_register_platform_driver(&bbc_beep_driver); if (!err) { - err = of_register_driver(&grover_beep_driver, - &of_platform_bus_type); + err = of_register_platform_driver(&grover_beep_driver); if (err) - of_unregister_driver(&bbc_beep_driver); + of_unregister_platform_driver(&bbc_beep_driver); } return err; @@ -368,8 +366,8 @@ static int __init sparcspkr_init(void) static void __exit sparcspkr_exit(void) { - of_unregister_driver(&bbc_beep_driver); - of_unregister_driver(&grover_beep_driver); + of_unregister_platform_driver(&bbc_beep_driver); + of_unregister_platform_driver(&grover_beep_driver); } module_init(sparcspkr_init); diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index c7d50ff43fca..cb2a24b94746 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -116,8 +116,7 @@ static int __init i8042_platform_init(void) if (!kbd_iobase) return -ENODEV; } else { - int err = of_register_driver(&sparc_i8042_driver, - &of_bus_type); + int err = of_register_platform_driver(&sparc_i8042_driver); if (err) return err; @@ -141,7 +140,7 @@ static inline void i8042_platform_exit(void) struct device_node *root = of_find_node_by_path("/"); if (strcmp(root->name, "SUNW,JavaStation-1")) - of_unregister_driver(&sparc_i8042_driver); + of_unregister_platform_driver(&sparc_i8042_driver); } #else /* !CONFIG_PCI */ diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 0391c2527bd7..8984236a8d0a 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -160,12 +160,12 @@ static struct of_platform_driver uflash_driver = { static int __init uflash_init(void) { - return of_register_driver(&uflash_driver, &of_bus_type); + return of_register_platform_driver(&uflash_driver); } static void __exit uflash_exit(void) { - of_unregister_driver(&uflash_driver); + of_unregister_platform_driver(&uflash_driver); } module_init(uflash_init); diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index b150c102ca5a..f10476fb2623 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2339,11 +2339,11 @@ static int __devinit emac_wait_deps(struct emac_instance *dev) deps[EMAC_DEP_MDIO_IDX].phandle = dev->mdio_ph; if (dev->blist && dev->blist > emac_boot_list) deps[EMAC_DEP_PREV_IDX].phandle = 0xffffffffu; - bus_register_notifier(&of_platform_bus_type, &emac_of_bus_notifier); + bus_register_notifier(&platform_bus_type, &emac_of_bus_notifier); wait_event_timeout(emac_probe_wait, emac_check_deps(dev, deps), EMAC_PROBE_DEP_TIMEOUT); - bus_unregister_notifier(&of_platform_bus_type, &emac_of_bus_notifier); + bus_unregister_notifier(&platform_bus_type, &emac_of_bus_notifier); err = emac_check_deps(dev, deps) ? 0 : -ENODEV; for (i = 0; i < EMAC_DEP_COUNT; i++) { if (deps[i].node) diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 370d3c17f24c..04e552aa14ec 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -1172,12 +1172,12 @@ static struct of_platform_driver myri_sbus_driver = { static int __init myri_sbus_init(void) { - return of_register_driver(&myri_sbus_driver, &of_bus_type); + return of_register_platform_driver(&myri_sbus_driver); } static void __exit myri_sbus_exit(void) { - of_unregister_driver(&myri_sbus_driver); + of_unregister_platform_driver(&myri_sbus_driver); } module_init(myri_sbus_init); diff --git a/drivers/net/niu.c b/drivers/net/niu.c index f6ecf6180f72..8cb2b30eccae 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -10251,14 +10251,14 @@ static int __init niu_init(void) niu_debug = netif_msg_init(debug, NIU_MSG_DEFAULT); #ifdef CONFIG_SPARC64 - err = of_register_driver(&niu_of_driver, &of_bus_type); + err = of_register_platform_driver(&niu_of_driver); #endif if (!err) { err = pci_register_driver(&niu_pci_driver); #ifdef CONFIG_SPARC64 if (err) - of_unregister_driver(&niu_of_driver); + of_unregister_platform_driver(&niu_of_driver); #endif } @@ -10269,7 +10269,7 @@ static void __exit niu_exit(void) { pci_unregister_driver(&niu_pci_driver); #ifdef CONFIG_SPARC64 - of_unregister_driver(&niu_of_driver); + of_unregister_platform_driver(&niu_of_driver); #endif } diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 0b10d24de051..09c071bd6ad4 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -1301,12 +1301,12 @@ static struct of_platform_driver bigmac_sbus_driver = { static int __init bigmac_init(void) { - return of_register_driver(&bigmac_sbus_driver, &of_bus_type); + return of_register_platform_driver(&bigmac_sbus_driver); } static void __exit bigmac_exit(void) { - of_unregister_driver(&bigmac_sbus_driver); + of_unregister_platform_driver(&bigmac_sbus_driver); } module_init(bigmac_init); diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 0a63ebef86a0..eec443f64079 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -3304,7 +3304,7 @@ static int __init happy_meal_sbus_init(void) { int err; - err = of_register_driver(&hme_sbus_driver, &of_bus_type); + err = of_register_platform_driver(&hme_sbus_driver); if (!err) err = quattro_sbus_register_irqs(); @@ -3313,7 +3313,7 @@ static int __init happy_meal_sbus_init(void) static void happy_meal_sbus_exit(void) { - of_unregister_driver(&hme_sbus_driver); + of_unregister_platform_driver(&hme_sbus_driver); quattro_sbus_free_irqs(); while (qfe_sbus_list) { diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index c6bfdad6c0c8..ee364fa75634 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1558,12 +1558,12 @@ static struct of_platform_driver sunlance_sbus_driver = { /* Find all the lance cards on the system and initialize them */ static int __init sparc_lance_init(void) { - return of_register_driver(&sunlance_sbus_driver, &of_bus_type); + return of_register_platform_driver(&sunlance_sbus_driver); } static void __exit sparc_lance_exit(void) { - of_unregister_driver(&sunlance_sbus_driver); + of_unregister_platform_driver(&sunlance_sbus_driver); } module_init(sparc_lance_init); diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 446517487084..5f84a5dadedd 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -988,12 +988,12 @@ static struct of_platform_driver qec_sbus_driver = { static int __init qec_init(void) { - return of_register_driver(&qec_sbus_driver, &of_bus_type); + return of_register_platform_driver(&qec_sbus_driver); } static void __exit qec_exit(void) { - of_unregister_driver(&qec_sbus_driver); + of_unregister_platform_driver(&qec_sbus_driver); while (root_qec_dev) { struct sunqec *next = root_qec_dev->next_module; diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 3cdfe96e8999..210a6441a066 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -393,12 +393,12 @@ static struct of_platform_driver bpp_sbus_driver = { static int __init parport_sunbpp_init(void) { - return of_register_driver(&bpp_sbus_driver, &of_bus_type); + return of_register_platform_driver(&bpp_sbus_driver); } static void __exit parport_sunbpp_exit(void) { - of_unregister_driver(&bpp_sbus_driver); + of_unregister_platform_driver(&bpp_sbus_driver); } MODULE_AUTHOR("Derrick J Brashear"); diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 40d7a1fc69af..3e89c313e98d 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -425,12 +425,12 @@ static struct of_platform_driver bbc_i2c_driver = { static int __init bbc_i2c_init(void) { - return of_register_driver(&bbc_i2c_driver, &of_bus_type); + return of_register_platform_driver(&bbc_i2c_driver); } static void __exit bbc_i2c_exit(void) { - of_unregister_driver(&bbc_i2c_driver); + of_unregister_platform_driver(&bbc_i2c_driver); } module_init(bbc_i2c_init); diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 7baf1b644039..8fd362e7fa65 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -277,12 +277,12 @@ static struct of_platform_driver d7s_driver = { static int __init d7s_init(void) { - return of_register_driver(&d7s_driver, &of_bus_type); + return of_register_platform_driver(&d7s_driver); } static void __exit d7s_exit(void) { - of_unregister_driver(&d7s_driver); + of_unregister_platform_driver(&d7s_driver); } module_init(d7s_init); diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index c8166ecf5276..2c76f700265b 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1142,12 +1142,12 @@ static struct of_platform_driver envctrl_driver = { static int __init envctrl_init(void) { - return of_register_driver(&envctrl_driver, &of_bus_type); + return of_register_platform_driver(&envctrl_driver); } static void __exit envctrl_exit(void) { - of_unregister_driver(&envctrl_driver); + of_unregister_platform_driver(&envctrl_driver); } module_init(envctrl_init); diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 368d66294d83..d79f386c3486 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -218,12 +218,12 @@ static struct of_platform_driver flash_driver = { static int __init flash_init(void) { - return of_register_driver(&flash_driver, &of_bus_type); + return of_register_platform_driver(&flash_driver); } static void __exit flash_cleanup(void) { - of_unregister_driver(&flash_driver); + of_unregister_platform_driver(&flash_driver); } module_init(flash_init); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index b8b40e9eca79..57f0612bb013 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -437,12 +437,12 @@ static struct of_platform_driver uctrl_driver = { static int __init uctrl_init(void) { - return of_register_driver(&uctrl_driver, &of_bus_type); + return of_register_platform_driver(&uctrl_driver); } static void __exit uctrl_exit(void) { - of_unregister_driver(&uctrl_driver); + of_unregister_platform_driver(&uctrl_driver); } module_init(uctrl_init); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 3f5b5411e6bc..53d7ed0dc169 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -1467,12 +1467,12 @@ static struct of_platform_driver qpti_sbus_driver = { static int __init qpti_init(void) { - return of_register_driver(&qpti_sbus_driver, &of_bus_type); + return of_register_platform_driver(&qpti_sbus_driver); } static void __exit qpti_exit(void) { - of_unregister_driver(&qpti_sbus_driver); + of_unregister_platform_driver(&qpti_sbus_driver); } MODULE_DESCRIPTION("QlogicISP SBUS driver"); diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index ddc221acd14c..89ba6fe02f80 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c @@ -644,12 +644,12 @@ static struct of_platform_driver esp_sbus_driver = { static int __init sunesp_init(void) { - return of_register_driver(&esp_sbus_driver, &of_bus_type); + return of_register_platform_driver(&esp_sbus_driver); } static void __exit sunesp_exit(void) { - of_unregister_driver(&esp_sbus_driver); + of_unregister_platform_driver(&esp_sbus_driver); } MODULE_DESCRIPTION("Sun ESP SCSI driver"); diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 36e244867dd8..a779e22d213e 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -644,12 +644,12 @@ static int __init sunhv_init(void) if (tlb_type != hypervisor) return -ENODEV; - return of_register_driver(&hv_driver, &of_bus_type); + return of_register_platform_driver(&hv_driver); } static void __exit sunhv_exit(void) { - of_unregister_driver(&hv_driver); + of_unregister_platform_driver(&hv_driver); } module_init(sunhv_init); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 0a7dd6841ff8..9845fb1cfb1f 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -1130,12 +1130,12 @@ static int __init sunsab_init(void) } } - return of_register_driver(&sab_driver, &of_bus_type); + return of_register_platform_driver(&sab_driver); } static void __exit sunsab_exit(void) { - of_unregister_driver(&sab_driver); + of_unregister_platform_driver(&sab_driver); if (sunsab_reg.nr) { sunserial_unregister_minors(&sunsab_reg, sunsab_reg.nr); } diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 5deafc8180b5..3cdf74822db5 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1586,7 +1586,7 @@ static int __init sunsu_init(void) return err; } - err = of_register_driver(&su_driver, &of_bus_type); + err = of_register_platform_driver(&su_driver); if (err && num_uart) sunserial_unregister_minors(&sunsu_reg, num_uart); diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index fcbe20d48039..d1e6bcb59546 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1576,7 +1576,7 @@ static int __init sunzilog_init(void) goto out_free_tables; } - err = of_register_driver(&zs_driver, &of_bus_type); + err = of_register_platform_driver(&zs_driver); if (err) goto out_unregister_uart; @@ -1604,7 +1604,7 @@ out: return err; out_unregister_driver: - of_unregister_driver(&zs_driver); + of_unregister_platform_driver(&zs_driver); out_unregister_uart: if (num_sunzilog) { @@ -1619,7 +1619,7 @@ out_free_tables: static void __exit sunzilog_exit(void) { - of_unregister_driver(&zs_driver); + of_unregister_platform_driver(&zs_driver); if (zilog_irq != -1) { struct uart_sunzilog_port *up = sunzilog_irq_chain; diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 09f1b9b462f4..c7796637bafd 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -390,12 +390,12 @@ static int __init bw2_init(void) if (fb_get_options("bw2fb", NULL)) return -ENODEV; - return of_register_driver(&bw2_driver, &of_bus_type); + return of_register_platform_driver(&bw2_driver); } static void __exit bw2_exit(void) { - of_unregister_driver(&bw2_driver); + of_unregister_platform_driver(&bw2_driver); } module_init(bw2_init); diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index e5dc2241194f..d09fde8beb69 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -610,12 +610,12 @@ static int __init cg14_init(void) if (fb_get_options("cg14fb", NULL)) return -ENODEV; - return of_register_driver(&cg14_driver, &of_bus_type); + return of_register_platform_driver(&cg14_driver); } static void __exit cg14_exit(void) { - of_unregister_driver(&cg14_driver); + of_unregister_platform_driver(&cg14_driver); } module_init(cg14_init); diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 558d73a948a0..64aa29809fb9 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -477,12 +477,12 @@ static int __init cg3_init(void) if (fb_get_options("cg3fb", NULL)) return -ENODEV; - return of_register_driver(&cg3_driver, &of_bus_type); + return of_register_platform_driver(&cg3_driver); } static void __exit cg3_exit(void) { - of_unregister_driver(&cg3_driver); + of_unregister_platform_driver(&cg3_driver); } module_init(cg3_init); diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 480d761a27a8..2389a719dcc7 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -870,12 +870,12 @@ static int __init cg6_init(void) if (fb_get_options("cg6fb", NULL)) return -ENODEV; - return of_register_driver(&cg6_driver, &of_bus_type); + return of_register_platform_driver(&cg6_driver); } static void __exit cg6_exit(void) { - of_unregister_driver(&cg6_driver); + of_unregister_platform_driver(&cg6_driver); } module_init(cg6_init); diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 95c0227f47fc..f6ecfab296d3 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -1067,12 +1067,12 @@ static int __init ffb_init(void) if (fb_get_options("ffb", NULL)) return -ENODEV; - return of_register_driver(&ffb_driver, &of_bus_type); + return of_register_platform_driver(&ffb_driver); } static void __exit ffb_exit(void) { - of_unregister_driver(&ffb_driver); + of_unregister_platform_driver(&ffb_driver); } module_init(ffb_init); diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 9e8bf7d5e249..ad677637ffbb 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -677,12 +677,12 @@ static int __init leo_init(void) if (fb_get_options("leofb", NULL)) return -ENODEV; - return of_register_driver(&leo_driver, &of_bus_type); + return of_register_platform_driver(&leo_driver); } static void __exit leo_exit(void) { - of_unregister_driver(&leo_driver); + of_unregister_platform_driver(&leo_driver); } module_init(leo_init); diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 6552751e81aa..688b055abab2 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -367,12 +367,12 @@ static int __init p9100_init(void) if (fb_get_options("p9100fb", NULL)) return -ENODEV; - return of_register_driver(&p9100_driver, &of_bus_type); + return of_register_platform_driver(&p9100_driver); } static void __exit p9100_exit(void) { - of_unregister_driver(&p9100_driver); + of_unregister_platform_driver(&p9100_driver); } module_init(p9100_init); diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c index 489b44e8db81..7288934c0d49 100644 --- a/drivers/video/sunxvr1000.c +++ b/drivers/video/sunxvr1000.c @@ -213,12 +213,12 @@ static int __init gfb_init(void) if (fb_get_options("gfb", NULL)) return -ENODEV; - return of_register_driver(&gfb_driver, &of_bus_type); + return of_register_platform_driver(&gfb_driver); } static void __exit gfb_exit(void) { - of_unregister_driver(&gfb_driver); + of_unregister_platform_driver(&gfb_driver); } module_init(gfb_init); diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index cc039b33d2d8..f375e0db6776 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -526,12 +526,12 @@ static int __init tcx_init(void) if (fb_get_options("tcxfb", NULL)) return -ENODEV; - return of_register_driver(&tcx_driver, &of_bus_type); + return of_register_platform_driver(&tcx_driver); } static void __exit tcx_exit(void) { - of_unregister_driver(&tcx_driver); + of_unregister_platform_driver(&tcx_driver); } module_init(tcx_init); diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 8c03fd71693e..30a2512fd52e 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -688,12 +688,12 @@ static struct of_platform_driver cpwd_driver = { static int __init cpwd_init(void) { - return of_register_driver(&cpwd_driver, &of_bus_type); + return of_register_platform_driver(&cpwd_driver); } static void __exit cpwd_exit(void) { - of_unregister_driver(&cpwd_driver); + of_unregister_platform_driver(&cpwd_driver); } module_init(cpwd_init); diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 5dceeddc8859..4082b4ace1fc 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -250,12 +250,12 @@ static struct of_platform_driver riowd_driver = { static int __init riowd_init(void) { - return of_register_driver(&riowd_driver, &of_bus_type); + return of_register_platform_driver(&riowd_driver); } static void __exit riowd_exit(void) { - of_unregister_driver(&riowd_driver); + of_unregister_platform_driver(&riowd_driver); } module_init(riowd_init); diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 133ecf31a60f..429513ae8f6e 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -19,12 +19,6 @@ #include #include -/* - * of_platform_bus_type isn't it's own bus anymore. It's now just an alias - * for the platform bus. - */ -#define of_platform_bus_type platform_bus_type - extern const struct of_device_id of_default_bus_ids[]; /* diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 43c63d441087..9eb1a4e0363b 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -1075,7 +1075,7 @@ static struct of_platform_driver amd7930_sbus_driver = { static int __init amd7930_init(void) { - return of_register_driver(&amd7930_sbus_driver, &of_bus_type); + return of_register_platform_driver(&amd7930_sbus_driver); } static void __exit amd7930_exit(void) @@ -1092,7 +1092,7 @@ static void __exit amd7930_exit(void) amd7930_list = NULL; - of_unregister_driver(&amd7930_sbus_driver); + of_unregister_platform_driver(&amd7930_sbus_driver); } module_init(amd7930_init); diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index f7f05c246303..68570ee2c9bb 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -2120,12 +2120,12 @@ static struct of_platform_driver cs4231_driver = { static int __init cs4231_init(void) { - return of_register_driver(&cs4231_driver, &of_bus_type); + return of_register_platform_driver(&cs4231_driver); } static void __exit cs4231_exit(void) { - of_unregister_driver(&cs4231_driver); + of_unregister_platform_driver(&cs4231_driver); } module_init(cs4231_init); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 491ce71c84b6..c421901c48d0 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2699,12 +2699,12 @@ static struct of_platform_driver dbri_sbus_driver = { /* Probe for the dbri chip and then attach the driver. */ static int __init dbri_init(void) { - return of_register_driver(&dbri_sbus_driver, &of_bus_type); + return of_register_platform_driver(&dbri_sbus_driver); } static void __exit dbri_exit(void) { - of_unregister_driver(&dbri_sbus_driver); + of_unregister_platform_driver(&dbri_sbus_driver); } module_init(dbri_init); -- cgit v1.2.3 From d334aa79786a878e90af5b5c1b14109c1df85820 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Thu, 22 Apr 2010 10:47:40 -0600 Subject: [SCSI] mpt2sas: DIF Type 2 Protection Support Adding DIF Type 2 protection support, as well as turning on 32 byte cdb's, and setting the cdb length for > 16 byte in the SCSI_IO->control parameter. Signed-off-by: Martin Petersen Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 4 ++-- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index b4afe431ac1e..0f41fcd4e52b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -69,11 +69,11 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation " #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "05.100.00.02" +#define MPT2SAS_DRIVER_VERSION "05.100.00.03" #define MPT2SAS_MAJOR_VERSION 05 #define MPT2SAS_MINOR_VERSION 100 #define MPT2SAS_BUILD_VERSION 00 -#define MPT2SAS_RELEASE_VERSION 02 +#define MPT2SAS_RELEASE_VERSION 03 /* * Set MPT2SAS_SG_DEPTH value based on user input. diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index c5ff26a2a51d..456ea7c3b099 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2858,9 +2858,7 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) unsigned char prot_op = scsi_get_prot_op(scmd); unsigned char prot_type = scsi_get_prot_type(scmd); - if (prot_type == SCSI_PROT_DIF_TYPE0 || - prot_type == SCSI_PROT_DIF_TYPE2 || - prot_op == SCSI_PROT_NORMAL) + if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL) return; if (prot_op == SCSI_PROT_READ_STRIP) @@ -2882,7 +2880,13 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; mpi_request->CDB.EEDP32.PrimaryReferenceTag = cpu_to_be32(scsi_get_lba(scmd)); + break; + + case SCSI_PROT_DIF_TYPE2: + eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | + MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | + MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; break; case SCSI_PROT_DIF_TYPE3: @@ -3013,7 +3017,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; /* Make sure Device is not raid volume */ if (!_scsih_is_raid(&scmd->device->sdev_gendev) && - sas_is_tlr_enabled(scmd->device)) + sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32) mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd); @@ -3025,6 +3029,8 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t)); _scsih_setup_eedp(scmd, mpi_request); + if (scmd->cmd_len == 32) + mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; if (sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) @@ -6567,7 +6573,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ioc->delayed_tr_list); /* init shost parameters */ - shost->max_cmd_len = 16; + shost->max_cmd_len = 32; shost->max_lun = max_lun; shost->transportt = mpt2sas_transport_template; shost->unique_id = ioc->id; @@ -6580,7 +6586,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION - | SHOST_DIF_TYPE3_PROTECTION); + | SHOST_DIF_TYPE2_PROTECTION | SHOST_DIF_TYPE3_PROTECTION); scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); /* event thread */ -- cgit v1.2.3 From 1db90ea239b85479daedb978ea2f0a61776f074f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 27 May 2010 14:33:47 +0200 Subject: [SCSI] hptiop: Eliminate a NULL pointer dereference The end of the function is reachable both when host is and is not NULL. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ expression E,E1; identifier f; statement S1,S2,S3; @@ if ((E == NULL && ...) || ...) { ... when != if (...) S1 else S2 when != E = E1 * E->f ... when any return ...; } else S3 // Signed-off-by: Julia Lawall Signed-off-by: James Bottomley --- drivers/scsi/hptiop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 645f7cdf21ab..0729f150b33a 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1157,7 +1157,7 @@ free_pci_regions: disable_pci_device: pci_disable_device(pcidev); - dprintk("scsi%d: hptiop_probe fail\n", host->host_no); + dprintk("scsi%d: hptiop_probe fail\n", host ? host->host_no : 0); return -ENODEV; } -- cgit v1.2.3 From 55c06c7171f63aaac1f9009729d1cb5107fa0626 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:12:46 -0500 Subject: [SCSI] hpsa: save pdev pointer in per hba structure early to avoid passing it around so much. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 75 +++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 37 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index c016426b31b2..d6f897016e24 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3209,8 +3209,7 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) * controllers that are capable. If not, we use IO-APIC mode. */ -static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, - struct pci_dev *pdev, u32 board_id) +static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, u32 board_id) { #ifdef CONFIG_PCI_MSI int err; @@ -3223,9 +3222,9 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, (board_id == 0x40800E11) || (board_id == 0x40820E11) || (board_id == 0x40830E11)) goto default_int_mode; - if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { - dev_info(&pdev->dev, "MSIX\n"); - err = pci_enable_msix(pdev, hpsa_msix_entries, 4); + if (pci_find_capability(h->pdev, PCI_CAP_ID_MSIX)) { + dev_info(&h->pdev->dev, "MSIX\n"); + err = pci_enable_msix(h->pdev, hpsa_msix_entries, 4); if (!err) { h->intr[0] = hpsa_msix_entries[0].vector; h->intr[1] = hpsa_msix_entries[1].vector; @@ -3235,29 +3234,29 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, return; } if (err > 0) { - dev_warn(&pdev->dev, "only %d MSI-X vectors " + dev_warn(&h->pdev->dev, "only %d MSI-X vectors " "available\n", err); goto default_int_mode; } else { - dev_warn(&pdev->dev, "MSI-X init failed %d\n", + dev_warn(&h->pdev->dev, "MSI-X init failed %d\n", err); goto default_int_mode; } } - if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { - dev_info(&pdev->dev, "MSI\n"); - if (!pci_enable_msi(pdev)) + if (pci_find_capability(h->pdev, PCI_CAP_ID_MSI)) { + dev_info(&h->pdev->dev, "MSI\n"); + if (!pci_enable_msi(h->pdev)) h->msi_vector = 1; else - dev_warn(&pdev->dev, "MSI init failed\n"); + dev_warn(&h->pdev->dev, "MSI init failed\n"); } default_int_mode: #endif /* CONFIG_PCI_MSI */ /* if we get here we're going to use the default interrupt mode */ - h->intr[PERF_MODE_INT] = pdev->irq; + h->intr[PERF_MODE_INT] = h->pdev->irq; } -static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) +static int __devinit hpsa_pci_init(struct ctlr_info *h) { ushort subsystem_vendor_id, subsystem_device_id, command; u32 board_id, scratchpad = 0; @@ -3267,8 +3266,8 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) u32 trans_offset; int i, prod_index, err; - subsystem_vendor_id = pdev->subsystem_vendor; - subsystem_device_id = pdev->subsystem_device; + subsystem_vendor_id = h->pdev->subsystem_vendor; + subsystem_device_id = h->pdev->subsystem_device; board_id = (((u32) (subsystem_device_id << 16) & 0xffff0000) | subsystem_vendor_id); @@ -3282,7 +3281,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) prod_index--; if (subsystem_vendor_id != PCI_VENDOR_ID_HP || !hpsa_allow_any) { - dev_warn(&pdev->dev, "unrecognized board ID:" + dev_warn(&h->pdev->dev, "unrecognized board ID:" " 0x%08lx, ignoring.\n", (unsigned long) board_id); return -ENODEV; @@ -3291,41 +3290,42 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) /* check to see if controller has been disabled * BEFORE trying to enable it */ - (void)pci_read_config_word(pdev, PCI_COMMAND, &command); + (void)pci_read_config_word(h->pdev, PCI_COMMAND, &command); if (!(command & 0x02)) { - dev_warn(&pdev->dev, "controller appears to be disabled\n"); + dev_warn(&h->pdev->dev, "controller appears to be disabled\n"); return -ENODEV; } - err = pci_enable_device(pdev); + err = pci_enable_device(h->pdev); if (err) { - dev_warn(&pdev->dev, "unable to enable PCI device\n"); + dev_warn(&h->pdev->dev, "unable to enable PCI device\n"); return err; } - err = pci_request_regions(pdev, "hpsa"); + err = pci_request_regions(h->pdev, "hpsa"); if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources, aborting\n"); + dev_err(&h->pdev->dev, + "cannot obtain PCI resources, aborting\n"); return err; } /* If the kernel supports MSI/MSI-X we will try to enable that, * else we use the IO-APIC interrupt assigned to us by system ROM. */ - hpsa_interrupt_mode(h, pdev, board_id); + hpsa_interrupt_mode(h, board_id); /* find the memory BAR */ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) + if (pci_resource_flags(h->pdev, i) & IORESOURCE_MEM) break; } if (i == DEVICE_COUNT_RESOURCE) { - dev_warn(&pdev->dev, "no memory BAR found\n"); + dev_warn(&h->pdev->dev, "no memory BAR found\n"); err = -ENODEV; goto err_out_free_res; } - h->paddr = pci_resource_start(pdev, i); /* addressing mode bits + h->paddr = pci_resource_start(h->pdev, i); /* addressing mode bits * already removed */ @@ -3339,7 +3339,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS); } if (scratchpad != HPSA_FIRMWARE_READY) { - dev_warn(&pdev->dev, "board not ready, timed out.\n"); + dev_warn(&h->pdev->dev, "board not ready, timed out.\n"); err = -ENODEV; goto err_out_free_res; } @@ -3347,20 +3347,20 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) /* get the address index number */ cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET); cfg_base_addr &= (u32) 0x0000ffff; - cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr); + cfg_base_addr_index = find_PCI_BAR_index(h->pdev, cfg_base_addr); if (cfg_base_addr_index == -1) { - dev_warn(&pdev->dev, "cannot find cfg_base_addr_index\n"); + dev_warn(&h->pdev->dev, "cannot find cfg_base_addr_index\n"); err = -ENODEV; goto err_out_free_res; } cfg_offset = readl(h->vaddr + SA5_CTMEM_OFFSET); - h->cfgtable = remap_pci_mem(pci_resource_start(pdev, + h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev, cfg_base_addr_index) + cfg_offset, sizeof(h->cfgtable)); /* Find performant mode table. */ trans_offset = readl(&(h->cfgtable->TransMethodOffset)); - h->transtable = remap_pci_mem(pci_resource_start(pdev, + h->transtable = remap_pci_mem(pci_resource_start(h->pdev, cfg_base_addr_index)+cfg_offset+trans_offset, sizeof(*h->transtable)); @@ -3392,7 +3392,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) (readb(&h->cfgtable->Signature[1]) != 'I') || (readb(&h->cfgtable->Signature[2]) != 'S') || (readb(&h->cfgtable->Signature[3]) != 'S')) { - dev_warn(&pdev->dev, "not a valid CISS config table\n"); + dev_warn(&h->pdev->dev, "not a valid CISS config table\n"); err = -ENODEV; goto err_out_free_res; } @@ -3434,11 +3434,12 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev) } #ifdef HPSA_DEBUG - print_cfg_table(&pdev->dev, h->cfgtable); + print_cfg_table(&h->pdev->dev, h->cfgtable); #endif /* HPSA_DEBUG */ if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { - dev_warn(&pdev->dev, "unable to get board into simple mode\n"); + dev_warn(&h->pdev->dev, + "unable to get board into simple mode\n"); err = -ENODEV; goto err_out_free_res; } @@ -3449,7 +3450,7 @@ err_out_free_res: * Deliberately omit pci_disable_device(): it does something nasty to * Smart Array controllers that pci_enable_device does not undo */ - pci_release_regions(pdev); + pci_release_regions(h->pdev); return err; } @@ -3507,17 +3508,17 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, if (!h) return -ENOMEM; + h->pdev = pdev; h->busy_initializing = 1; INIT_HLIST_HEAD(&h->cmpQ); INIT_HLIST_HEAD(&h->reqQ); - rc = hpsa_pci_init(h, pdev); + rc = hpsa_pci_init(h); if (rc != 0) goto clean1; sprintf(h->devname, "hpsa%d", number_of_controllers); h->ctlr = number_of_controllers; number_of_controllers++; - h->pdev = pdev; /* configure PCI DMA stuff */ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); -- cgit v1.2.3 From e5c880d1d5923c341ac7ba537fb1e6b73c5977a2 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:12:52 -0500 Subject: [SCSI] hpsa: factor out hpsa_lookup_board_id Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 58 ++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index d6f897016e24..b6c6e7f88fa4 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3256,37 +3256,44 @@ default_int_mode: h->intr[PERF_MODE_INT] = h->pdev->irq; } +static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id) +{ + int i; + u32 subsystem_vendor_id, subsystem_device_id; + + subsystem_vendor_id = pdev->subsystem_vendor; + subsystem_device_id = pdev->subsystem_device; + *board_id = ((subsystem_device_id << 16) & 0xffff0000) | + subsystem_vendor_id; + + for (i = 0; i < ARRAY_SIZE(products); i++) + if (*board_id == products[i].board_id) + return i; + + if (subsystem_vendor_id != PCI_VENDOR_ID_HP || !hpsa_allow_any) { + dev_warn(&pdev->dev, "unrecognized board ID: " + "0x%08x, ignoring.\n", *board_id); + return -ENODEV; + } + return ARRAY_SIZE(products) - 1; /* generic unknown smart array */ +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { - ushort subsystem_vendor_id, subsystem_device_id, command; - u32 board_id, scratchpad = 0; + ushort command; + u32 scratchpad = 0; u64 cfg_offset; u32 cfg_base_addr; u64 cfg_base_addr_index; u32 trans_offset; int i, prod_index, err; - subsystem_vendor_id = h->pdev->subsystem_vendor; - subsystem_device_id = h->pdev->subsystem_device; - board_id = (((u32) (subsystem_device_id << 16) & 0xffff0000) | - subsystem_vendor_id); - - for (i = 0; i < ARRAY_SIZE(products); i++) - if (board_id == products[i].board_id) - break; - - prod_index = i; + prod_index = hpsa_lookup_board_id(h->pdev, &h->board_id); + if (prod_index < 0) + return -ENODEV; + h->product_name = products[prod_index].product_name; + h->access = *(products[prod_index].access); - if (prod_index == ARRAY_SIZE(products)) { - prod_index--; - if (subsystem_vendor_id != PCI_VENDOR_ID_HP || - !hpsa_allow_any) { - dev_warn(&h->pdev->dev, "unrecognized board ID:" - " 0x%08lx, ignoring.\n", - (unsigned long) board_id); - return -ENODEV; - } - } /* check to see if controller has been disabled * BEFORE trying to enable it */ @@ -3312,7 +3319,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) /* If the kernel supports MSI/MSI-X we will try to enable that, * else we use the IO-APIC interrupt assigned to us by system ROM. */ - hpsa_interrupt_mode(h, board_id); + hpsa_interrupt_mode(h, h->board_id); /* find the memory BAR */ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { @@ -3364,7 +3371,6 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) cfg_base_addr_index)+cfg_offset+trans_offset, sizeof(*h->transtable)); - h->board_id = board_id; h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements)); @@ -3383,8 +3389,6 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) h->chainsize = 0; } - h->product_name = products[prod_index].product_name; - h->access = *(products[prod_index].access); /* Allow room for some ioctls */ h->nr_cmds = h->max_commands - 4; @@ -3410,7 +3414,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) * An ASIC bug may result in a prefetch beyond * physical memory. */ - if (board_id == 0x3225103C) { + if (h->board_id == 0x3225103C) { u32 dma_prefetch; dma_prefetch = readl(h->vaddr + I2O_DMA1_CFG); dma_prefetch |= 0x8000; -- cgit v1.2.3 From 85bdbabbd97ff797f91e6ec839ab053776bc72b4 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:12:57 -0500 Subject: [SCSI] hpsa: factor out hpsa_board_disabled Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b6c6e7f88fa4..4233b932ef55 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3278,9 +3278,16 @@ static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id) return ARRAY_SIZE(products) - 1; /* generic unknown smart array */ } +static inline bool hpsa_board_disabled(struct pci_dev *pdev) +{ + u16 command; + + (void) pci_read_config_word(pdev, PCI_COMMAND, &command); + return ((command & PCI_COMMAND_MEMORY) == 0); +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { - ushort command; u32 scratchpad = 0; u64 cfg_offset; u32 cfg_base_addr; @@ -3294,15 +3301,10 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) h->product_name = products[prod_index].product_name; h->access = *(products[prod_index].access); - /* check to see if controller has been disabled - * BEFORE trying to enable it - */ - (void)pci_read_config_word(h->pdev, PCI_COMMAND, &command); - if (!(command & 0x02)) { + if (hpsa_board_disabled(h->pdev)) { dev_warn(&h->pdev->dev, "controller appears to be disabled\n"); return -ENODEV; } - err = pci_enable_device(h->pdev); if (err) { dev_warn(&h->pdev->dev, "unable to enable PCI device\n"); -- cgit v1.2.3 From 6b3f4c52b29eee17285a6cd57071c9ac7736d172 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:02 -0500 Subject: [SCSI] hpsa: remove redundant board_id parameter from hpsa_interrupt_mode and delete duplicated comment Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4233b932ef55..66b7dcfb7276 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3209,7 +3209,7 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) * controllers that are capable. If not, we use IO-APIC mode. */ -static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, u32 board_id) +static void __devinit hpsa_interrupt_mode(struct ctlr_info *h) { #ifdef CONFIG_PCI_MSI int err; @@ -3218,9 +3218,8 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h, u32 board_id) }; /* Some boards advertise MSI but don't really support it */ - if ((board_id == 0x40700E11) || - (board_id == 0x40800E11) || - (board_id == 0x40820E11) || (board_id == 0x40830E11)) + if ((h->board_id == 0x40700E11) || (h->board_id == 0x40800E11) || + (h->board_id == 0x40820E11) || (h->board_id == 0x40830E11)) goto default_int_mode; if (pci_find_capability(h->pdev, PCI_CAP_ID_MSIX)) { dev_info(&h->pdev->dev, "MSIX\n"); @@ -3317,11 +3316,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) "cannot obtain PCI resources, aborting\n"); return err; } - - /* If the kernel supports MSI/MSI-X we will try to enable that, - * else we use the IO-APIC interrupt assigned to us by system ROM. - */ - hpsa_interrupt_mode(h, h->board_id); + hpsa_interrupt_mode(h); /* find the memory BAR */ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { -- cgit v1.2.3 From 3a7774ceb89f02f78e269b5c900096b066b66c3c Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:07 -0500 Subject: [SCSI] hpsa: factor out hpsa_find_memory_BAR Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 66b7dcfb7276..0582f2fc11f0 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3285,6 +3285,23 @@ static inline bool hpsa_board_disabled(struct pci_dev *pdev) return ((command & PCI_COMMAND_MEMORY) == 0); } +static int __devinit hpsa_pci_find_memory_BAR(struct ctlr_info *h, + unsigned long *memory_bar) +{ + int i; + + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) + if (pci_resource_flags(h->pdev, i) & IORESOURCE_MEM) { + /* addressing mode bits already removed */ + *memory_bar = pci_resource_start(h->pdev, i); + dev_dbg(&h->pdev->dev, "memory BAR = %lx\n", + *memory_bar); + return 0; + } + dev_warn(&h->pdev->dev, "no memory BAR found\n"); + return -ENODEV; +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { u32 scratchpad = 0; @@ -3317,22 +3334,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) return err; } hpsa_interrupt_mode(h); - - /* find the memory BAR */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - if (pci_resource_flags(h->pdev, i) & IORESOURCE_MEM) - break; - } - if (i == DEVICE_COUNT_RESOURCE) { - dev_warn(&h->pdev->dev, "no memory BAR found\n"); - err = -ENODEV; + err = hpsa_pci_find_memory_BAR(h, &h->paddr); + if (err) goto err_out_free_res; - } - - h->paddr = pci_resource_start(h->pdev, i); /* addressing mode bits - * already removed - */ - h->vaddr = remap_pci_mem(h->paddr, 0x250); /* Wait for the board to become ready. */ -- cgit v1.2.3 From 2c4c8c8b662286230a798c60408d217aeab55f7f Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:12 -0500 Subject: [SCSI] hpsa: factor out hpsa_wait_for_board_ready Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0582f2fc11f0..66c4fc306f2c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3302,9 +3302,23 @@ static int __devinit hpsa_pci_find_memory_BAR(struct ctlr_info *h, return -ENODEV; } +static int __devinit hpsa_wait_for_board_ready(struct ctlr_info *h) +{ + int i; + u32 scratchpad; + + for (i = 0; i < HPSA_BOARD_READY_ITERATIONS; i++) { + scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); + if (scratchpad == HPSA_FIRMWARE_READY) + return 0; + msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS); + } + dev_warn(&h->pdev->dev, "board not ready, timed out.\n"); + return -ENODEV; +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { - u32 scratchpad = 0; u64 cfg_offset; u32 cfg_base_addr; u64 cfg_base_addr_index; @@ -3339,18 +3353,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) goto err_out_free_res; h->vaddr = remap_pci_mem(h->paddr, 0x250); - /* Wait for the board to become ready. */ - for (i = 0; i < HPSA_BOARD_READY_ITERATIONS; i++) { - scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); - if (scratchpad == HPSA_FIRMWARE_READY) - break; - msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS); - } - if (scratchpad != HPSA_FIRMWARE_READY) { - dev_warn(&h->pdev->dev, "board not ready, timed out.\n"); - err = -ENODEV; + err = hpsa_wait_for_board_ready(h); + if (err) goto err_out_free_res; - } /* get the address index number */ cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET); -- cgit v1.2.3 From 77c4495c17d7508bdef1cfd2c3c933ff5379908b Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:17 -0500 Subject: [SCSI] hpsa: factor out hpsa_find_cfgtables Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 66c4fc306f2c..cb0cc0993b9c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3317,12 +3317,39 @@ static int __devinit hpsa_wait_for_board_ready(struct ctlr_info *h) return -ENODEV; } -static int __devinit hpsa_pci_init(struct ctlr_info *h) +static int __devinit hpsa_find_cfgtables(struct ctlr_info *h) { u64 cfg_offset; u32 cfg_base_addr; u64 cfg_base_addr_index; u32 trans_offset; + + /* get the address index number */ + cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET); + cfg_base_addr &= (u32) 0x0000ffff; + cfg_base_addr_index = find_PCI_BAR_index(h->pdev, cfg_base_addr); + if (cfg_base_addr_index == -1) { + dev_warn(&h->pdev->dev, "cannot find cfg_base_addr_index\n"); + return -ENODEV; + } + cfg_offset = readl(h->vaddr + SA5_CTMEM_OFFSET); + h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev, + cfg_base_addr_index) + cfg_offset, + sizeof(h->cfgtable)); + if (!h->cfgtable) + return -ENOMEM; + /* Find performant mode table. */ + trans_offset = readl(&(h->cfgtable->TransMethodOffset)); + h->transtable = remap_pci_mem(pci_resource_start(h->pdev, + cfg_base_addr_index)+cfg_offset+trans_offset, + sizeof(*h->transtable)); + if (!h->transtable) + return -ENOMEM; + return 0; +} + +static int __devinit hpsa_pci_init(struct ctlr_info *h) +{ int i, prod_index, err; prod_index = hpsa_lookup_board_id(h->pdev, &h->board_id); @@ -3356,26 +3383,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) err = hpsa_wait_for_board_ready(h); if (err) goto err_out_free_res; - - /* get the address index number */ - cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET); - cfg_base_addr &= (u32) 0x0000ffff; - cfg_base_addr_index = find_PCI_BAR_index(h->pdev, cfg_base_addr); - if (cfg_base_addr_index == -1) { - dev_warn(&h->pdev->dev, "cannot find cfg_base_addr_index\n"); - err = -ENODEV; + err = hpsa_find_cfgtables(h); + if (err) goto err_out_free_res; - } - - cfg_offset = readl(h->vaddr + SA5_CTMEM_OFFSET); - h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev, - cfg_base_addr_index) + cfg_offset, - sizeof(h->cfgtable)); - /* Find performant mode table. */ - trans_offset = readl(&(h->cfgtable->TransMethodOffset)); - h->transtable = remap_pci_mem(pci_resource_start(h->pdev, - cfg_base_addr_index)+cfg_offset+trans_offset, - sizeof(*h->transtable)); h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements)); -- cgit v1.2.3 From 204892e9717790cd17689aaebf2790a477492734 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:22 -0500 Subject: [SCSI] hpsa: fix leak of ioremapped memory in hpsa_pci_init error path. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index cb0cc0993b9c..4983f3452dc4 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3379,7 +3379,10 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) if (err) goto err_out_free_res; h->vaddr = remap_pci_mem(h->paddr, 0x250); - + if (!h->vaddr) { + err = -ENOMEM; + goto err_out_free_res; + } err = hpsa_wait_for_board_ready(h); if (err) goto err_out_free_res; @@ -3466,6 +3469,12 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) return 0; err_out_free_res: + if (h->transtable) + iounmap(h->transtable); + if (h->cfgtable) + iounmap(h->cfgtable); + if (h->vaddr) + iounmap(h->vaddr); /* * Deliberately omit pci_disable_device(): it does something nasty to * Smart Array controllers that pci_enable_device does not undo @@ -3684,6 +3693,8 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev) hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */ hpsa_shutdown(pdev); iounmap(h->vaddr); + iounmap(h->transtable); + iounmap(h->cfgtable); hpsa_free_sg_chain_blocks(h); pci_free_consistent(h->pdev, h->nr_cmds * sizeof(struct CommandList), -- cgit v1.2.3 From b93d7536eaa1206ad4a00ad8ea700ff0bd75a0da Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:27 -0500 Subject: [SCSI] hpsa: hpsa factor out hpsa_find_board_params Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4983f3452dc4..dcbe54b1dfba 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3348,6 +3348,30 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h) return 0; } +/* Interrogate the hardware for some limits: + * max commands, max SG elements without chaining, and with chaining, + * SG chain block size, etc. + */ +static void __devinit hpsa_find_board_params(struct ctlr_info *h) +{ + h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); + h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */ + h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements)); + /* + * Limit in-command s/g elements to 32 save dma'able memory. + * Howvever spec says if 0, use 31 + */ + h->max_cmd_sg_entries = 31; + if (h->maxsgentries > 512) { + h->max_cmd_sg_entries = 32; + h->chainsize = h->maxsgentries - h->max_cmd_sg_entries + 1; + h->maxsgentries--; /* save one for chain pointer */ + } else { + h->maxsgentries = 31; /* default to traditional values */ + h->chainsize = 0; + } +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { int i, prod_index, err; @@ -3389,27 +3413,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) err = hpsa_find_cfgtables(h); if (err) goto err_out_free_res; - - h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); - h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements)); - - /* - * Limit in-command s/g elements to 32 save dma'able memory. - * Howvever spec says if 0, use 31 - */ - - h->max_cmd_sg_entries = 31; - if (h->maxsgentries > 512) { - h->max_cmd_sg_entries = 32; - h->chainsize = h->maxsgentries - h->max_cmd_sg_entries + 1; - h->maxsgentries--; /* save one for chain pointer */ - } else { - h->maxsgentries = 31; /* default to traditional values */ - h->chainsize = 0; - } - - /* Allow room for some ioctls */ - h->nr_cmds = h->max_commands - 4; + hpsa_find_board_params(h); if ((readb(&h->cfgtable->Signature[0]) != 'C') || (readb(&h->cfgtable->Signature[1]) != 'I') || -- cgit v1.2.3 From 76c46e4970f7ee6d8c54220a767e93d67b74cd33 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:32 -0500 Subject: [SCSI] hpsa: factor out hpsa-CISS-signature-present Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index dcbe54b1dfba..f2a9af64dfaa 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3372,6 +3372,18 @@ static void __devinit hpsa_find_board_params(struct ctlr_info *h) } } +static inline bool hpsa_CISS_signature_present(struct ctlr_info *h) +{ + if ((readb(&h->cfgtable->Signature[0]) != 'C') || + (readb(&h->cfgtable->Signature[1]) != 'I') || + (readb(&h->cfgtable->Signature[2]) != 'S') || + (readb(&h->cfgtable->Signature[3]) != 'S')) { + dev_warn(&h->pdev->dev, "not a valid CISS config table\n"); + return false; + } + return true; +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { int i, prod_index, err; @@ -3415,11 +3427,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) goto err_out_free_res; hpsa_find_board_params(h); - if ((readb(&h->cfgtable->Signature[0]) != 'C') || - (readb(&h->cfgtable->Signature[1]) != 'I') || - (readb(&h->cfgtable->Signature[2]) != 'S') || - (readb(&h->cfgtable->Signature[3]) != 'S')) { - dev_warn(&h->pdev->dev, "not a valid CISS config table\n"); + if (!hpsa_CISS_signature_present(h)) { err = -ENODEV; goto err_out_free_res; } -- cgit v1.2.3 From f7c391015ab64c835a9bb403626b38a51d6432cc Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:38 -0500 Subject: [SCSI] hpsa: factor out hpsa_enable_scsi_prefetch Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f2a9af64dfaa..62f9784ecf8f 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3384,6 +3384,18 @@ static inline bool hpsa_CISS_signature_present(struct ctlr_info *h) return true; } +/* Need to enable prefetch in the SCSI core for 6400 in x86 */ +static inline void hpsa_enable_scsi_prefetch(struct ctlr_info *h) +{ +#ifdef CONFIG_X86 + u32 prefetch; + + prefetch = readl(&(h->cfgtable->SCSI_Prefetch)); + prefetch |= 0x100; + writel(prefetch, &(h->cfgtable->SCSI_Prefetch)); +#endif +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { int i, prod_index, err; @@ -3431,15 +3443,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) err = -ENODEV; goto err_out_free_res; } -#ifdef CONFIG_X86 - { - /* Need to enable prefetch in the SCSI core for 6400 in x86 */ - u32 prefetch; - prefetch = readl(&(h->cfgtable->SCSI_Prefetch)); - prefetch |= 0x100; - writel(prefetch, &(h->cfgtable->SCSI_Prefetch)); - } -#endif + hpsa_enable_scsi_prefetch(h); /* Disabling DMA prefetch for the P600 * An ASIC bug may result in a prefetch beyond -- cgit v1.2.3 From 3d0eab67cf556db4430a42fbb45dc90ef690d30c Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:43 -0500 Subject: [SCSI] hpsa: factor out hpsa_p600_dma_prefetch_quirk Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 62f9784ecf8f..9e81e0bcf1e2 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3396,6 +3396,20 @@ static inline void hpsa_enable_scsi_prefetch(struct ctlr_info *h) #endif } +/* Disable DMA prefetch for the P600. Otherwise an ASIC bug may result + * in a prefetch beyond physical memory. + */ +static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h) +{ + u32 dma_prefetch; + + if (h->board_id != 0x3225103C) + return; + dma_prefetch = readl(h->vaddr + I2O_DMA1_CFG); + dma_prefetch |= 0x8000; + writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG); +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { int i, prod_index, err; @@ -3444,17 +3458,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) goto err_out_free_res; } hpsa_enable_scsi_prefetch(h); - - /* Disabling DMA prefetch for the P600 - * An ASIC bug may result in a prefetch beyond - * physical memory. - */ - if (h->board_id == 0x3225103C) { - u32 dma_prefetch; - dma_prefetch = readl(h->vaddr + I2O_DMA1_CFG); - dma_prefetch |= 0x8000; - writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG); - } + hpsa_p600_dma_prefetch_quirk(h); h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); /* Update the field, and then ring the doorbell */ -- cgit v1.2.3 From eb6b2ae9058accd183fe8b31f1985312bf333624 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:48 -0500 Subject: [SCSI] hpsa: factor out hpsa_enter_simple_mode Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 62 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9e81e0bcf1e2..4d4ecca399ae 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3410,9 +3410,41 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h) writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG); } +static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h) +{ + int i; + + h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); + /* Update the field, and then ring the doorbell */ + writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); + writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); + + /* under certain very rare conditions, this can take awhile. + * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right + * as we enter this code.) + */ + for (i = 0; i < MAX_CONFIG_WAIT; i++) { + if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) + break; + /* delay and try again */ + msleep(10); + } + +#ifdef HPSA_DEBUG + print_cfg_table(&h->pdev->dev, h->cfgtable); +#endif /* HPSA_DEBUG */ + + if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { + dev_warn(&h->pdev->dev, + "unable to get board into simple mode\n"); + return -ENODEV; + } + return 0; +} + static int __devinit hpsa_pci_init(struct ctlr_info *h) { - int i, prod_index, err; + int prod_index, err; prod_index = hpsa_lookup_board_id(h->pdev, &h->board_id); if (prod_index < 0) @@ -3459,33 +3491,9 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) } hpsa_enable_scsi_prefetch(h); hpsa_p600_dma_prefetch_quirk(h); - - h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); - /* Update the field, and then ring the doorbell */ - writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); - writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); - - /* under certain very rare conditions, this can take awhile. - * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right - * as we enter this code.) - */ - for (i = 0; i < MAX_CONFIG_WAIT; i++) { - if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) - break; - /* delay and try again */ - msleep(10); - } - -#ifdef HPSA_DEBUG - print_cfg_table(&h->pdev->dev, h->cfgtable); -#endif /* HPSA_DEBUG */ - - if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { - dev_warn(&h->pdev->dev, - "unable to get board into simple mode\n"); - err = -ENODEV; + err = hpsa_enter_simple_mode(h); + if (err) goto err_out_free_res; - } return 0; err_out_free_res: -- cgit v1.2.3 From cda7612d4b96d51324c6fc4d5e47d629da6cb500 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:53 -0500 Subject: [SCSI] hpsa: check that simple mode is supported before trying to enter simple mode transport method. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4d4ecca399ae..57d038045adc 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3413,6 +3413,11 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h) static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h) { int i; + u32 trans_support; + + trans_support = readl(&(h->cfgtable->TransportSupport)); + if (!(trans_support & SIMPLE_MODE)) + return -ENOTSUPP; h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); /* Update the field, and then ring the doorbell */ -- cgit v1.2.3 From 58f8665cc369b9633af072afb741b8f0a01622fa Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:13:58 -0500 Subject: [SCSI] hpsa: clean up debug ifdefs Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 57d038045adc..7e602d282d52 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3135,9 +3135,9 @@ static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev) * the io functions. * This is for debug only. */ -#ifdef HPSA_DEBUG static void print_cfg_table(struct device *dev, struct CfgTable *tb) { +#ifdef HPSA_DEBUG int i; char temp_name[17]; @@ -3167,8 +3167,8 @@ static void print_cfg_table(struct device *dev, struct CfgTable *tb) dev_info(dev, " Server Name = %s\n", temp_name); dev_info(dev, " Heartbeat Counter = 0x%x\n\n\n", readl(&(tb->HeartBeat))); -} #endif /* HPSA_DEBUG */ +} static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) { @@ -3434,11 +3434,7 @@ static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h) /* delay and try again */ msleep(10); } - -#ifdef HPSA_DEBUG print_cfg_table(&h->pdev->dev, h->cfgtable); -#endif /* HPSA_DEBUG */ - if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { dev_warn(&h->pdev->dev, "unable to get board into simple mode\n"); -- cgit v1.2.3 From 7136f9a78eece43226dee1a46ec6fc144f561239 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:14:03 -0500 Subject: [SCSI] hpsa: mark hpsa_mark_hpsa_put_ctlr_into_performant_mode as __devinit Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 7e602d282d52..d495d8b19c9c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -158,7 +158,7 @@ static void check_ioctl_unit_attention(struct ctlr_info *h, /* performant mode helper functions */ static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, int *bucket_map); -static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); +static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); static inline u32 next_command(struct ctlr_info *h); static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); @@ -3803,7 +3803,7 @@ static void calc_bucket_map(int bucket[], int num_buckets, } } -static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) +static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) { u32 trans_support; u64 trans_offset; -- cgit v1.2.3 From 3f4336f33314e7d3687ff46af1fcaa970e3f4e00 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:14:08 -0500 Subject: [SCSI] hpsa: factor out hpsa_wait_for_mode_change_ack Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index d495d8b19c9c..e89c40aa2b35 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3410,19 +3410,9 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h) writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG); } -static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h) +static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h) { int i; - u32 trans_support; - - trans_support = readl(&(h->cfgtable->TransportSupport)); - if (!(trans_support & SIMPLE_MODE)) - return -ENOTSUPP; - - h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); - /* Update the field, and then ring the doorbell */ - writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); - writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); /* under certain very rare conditions, this can take awhile. * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right @@ -3434,6 +3424,21 @@ static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h) /* delay and try again */ msleep(10); } +} + +static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h) +{ + u32 trans_support; + + trans_support = readl(&(h->cfgtable->TransportSupport)); + if (!(trans_support & SIMPLE_MODE)) + return -ENOTSUPP; + + h->max_commands = readl(&(h->cfgtable->CmdsOutMax)); + /* Update the field, and then ring the doorbell */ + writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); + writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); + hpsa_wait_for_mode_change_ack(h); print_cfg_table(&h->pdev->dev, h->cfgtable); if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { dev_warn(&h->pdev->dev, @@ -3814,7 +3819,6 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) */ int bft[8] = {5, 6, 8, 10, 12, 20, 28, 35}; /* for scatter/gathers */ int i = 0; - int l = 0; unsigned long register_value; trans_support = readl(&(h->cfgtable->TransportSupport)); @@ -3858,17 +3862,7 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) writel(CFGTBL_Trans_Performant, &(h->cfgtable->HostWrite.TransportRequest)); writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); - /* under certain very rare conditions, this can take awhile. - * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right - * as we enter this code.) */ - for (l = 0; l < MAX_CONFIG_WAIT; l++) { - register_value = readl(h->vaddr + SA5_DOORBELL); - if (!(register_value & CFGTBL_ChangeReq)) - break; - /* delay and try again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10); - } + hpsa_wait_for_mode_change_ack(h); register_value = readl(&(h->cfgtable->TransportActive)); if (!(register_value & CFGTBL_Trans_Performant)) { dev_warn(&h->pdev->dev, "unable to get board into" -- cgit v1.2.3 From ec18d2abad04091c5125b0a37ad80a00099d8ac0 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:14:13 -0500 Subject: [SCSI] hpsa: remove unused variable trans_offset Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index e89c40aa2b35..ad70f3e29c24 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3811,7 +3811,6 @@ static void calc_bucket_map(int bucket[], int num_buckets, static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) { u32 trans_support; - u64 trans_offset; /* 5 = 1 s/g entry or 4k * 6 = 2 s/g entry or 8k * 8 = 4 s/g entry or 16k @@ -3846,7 +3845,6 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) memset(h->reply_pool, 0, h->reply_pool_size); h->reply_pool_head = h->reply_pool; - trans_offset = readl(&(h->cfgtable->TransMethodOffset)); bft[7] = h->max_sg_entries + 4; calc_bucket_map(bft, ARRAY_SIZE(bft), 32, h->blockFetchTable); for (i = 0; i < 8; i++) -- cgit v1.2.3 From 6c311b5725b9500bdd0f527cd97496b11999fbbd Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:14:19 -0500 Subject: [SCSI] hpsa: factor out hpsa_enter_performant_mode Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 54 +++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ad70f3e29c24..3c51544db958 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3808,36 +3808,16 @@ static void calc_bucket_map(int bucket[], int num_buckets, } } -static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) +static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h) { - u32 trans_support; + int i; + unsigned long register_value; + int bft[8] = {5, 6, 8, 10, 12, 20, 28, 35}; /* for scatter/gathers */ /* 5 = 1 s/g entry or 4k * 6 = 2 s/g entry or 8k * 8 = 4 s/g entry or 16k * 10 = 6 s/g entry or 24k */ - int bft[8] = {5, 6, 8, 10, 12, 20, 28, 35}; /* for scatter/gathers */ - int i = 0; - unsigned long register_value; - - trans_support = readl(&(h->cfgtable->TransportSupport)); - if (!(trans_support & PERFORMANT_MODE)) - return; - - h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); - h->max_sg_entries = 32; - /* Performant mode ring buffer and supporting data structures */ - h->reply_pool_size = h->max_commands * sizeof(u64); - h->reply_pool = pci_alloc_consistent(h->pdev, h->reply_pool_size, - &(h->reply_pool_dhandle)); - - /* Need a block fetch table for performant mode */ - h->blockFetchTable = kmalloc(((h->max_sg_entries+1) * - sizeof(u32)), GFP_KERNEL); - - if ((h->reply_pool == NULL) - || (h->blockFetchTable == NULL)) - goto clean_up; h->reply_pool_wraparound = 1; /* spec: init to 1 */ @@ -3867,6 +3847,32 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) " performant mode\n"); return; } +} + +static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) +{ + u32 trans_support; + + trans_support = readl(&(h->cfgtable->TransportSupport)); + if (!(trans_support & PERFORMANT_MODE)) + return; + + h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); + h->max_sg_entries = 32; + /* Performant mode ring buffer and supporting data structures */ + h->reply_pool_size = h->max_commands * sizeof(u64); + h->reply_pool = pci_alloc_consistent(h->pdev, h->reply_pool_size, + &(h->reply_pool_dhandle)); + + /* Need a block fetch table for performant mode */ + h->blockFetchTable = kmalloc(((h->max_sg_entries+1) * + sizeof(u32)), GFP_KERNEL); + + if ((h->reply_pool == NULL) + || (h->blockFetchTable == NULL)) + goto clean_up; + + hpsa_enter_performant_mode(h); /* Change the access methods to the performant access methods */ h->access = SA5_performant_access; -- cgit v1.2.3 From 873f339fc53750c1e715f5e1d2dfdb9869b7ea3f Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:14:24 -0500 Subject: [SCSI] hpsa: remove unused firm_ver member of the per-hba structure Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 6 ------ drivers/scsi/hpsa.h | 1 - 2 files changed, 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3c51544db958..50fddf84e47f 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1440,12 +1440,6 @@ static int hpsa_update_device_info(struct ctlr_info *h, goto bail_out; } - /* As a side effect, record the firmware version number - * if we happen to be talking to the RAID controller. - */ - if (is_hba_lunid(scsi3addr)) - memcpy(h->firm_ver, &inq_buff[32], 4); - this_device->devtype = (inq_buff[0] & 0x1f); memcpy(this_device->scsi3addr, scsi3addr, 8); memcpy(this_device->vendor, &inq_buff[8], diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 1bb5233b09a0..a203ef65cb50 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -53,7 +53,6 @@ struct ctlr_info { int ctlr; char devname[8]; char *product_name; - char firm_ver[4]; /* Firmware version */ struct pci_dev *pdev; u32 board_id; void __iomem *vaddr; -- cgit v1.2.3 From d28ce020fb0ef9254fc9e0bd07f5898c69af9f7d Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:14:34 -0500 Subject: [SCSI] hpsa: expose controller firmware revision via /sys. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- Documentation/scsi/hpsa.txt | 7 +++++++ drivers/scsi/hpsa.c | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'drivers/scsi') diff --git a/Documentation/scsi/hpsa.txt b/Documentation/scsi/hpsa.txt index 4055657340a2..dca658362cbf 100644 --- a/Documentation/scsi/hpsa.txt +++ b/Documentation/scsi/hpsa.txt @@ -38,6 +38,7 @@ HPSA specific entries in /sys ------------------------------ /sys/class/scsi_host/host*/rescan + /sys/class/scsi_host/host*/firmware_revision the host "rescan" attribute is a write only attribute. Writing to this attribute will cause the driver to scan for new, changed, or removed devices @@ -48,6 +49,12 @@ HPSA specific entries in /sys normally have to use this. It may be useful when hot plugging devices like tape drives, or entire storage boxes containing pre-configured logical drives. + The "firmware_revision" attribute contains the firmware version of the Smart Array. + For example: + + root@host:/sys/class/scsi_host/host4# cat firmware_revision + 7.14 + HPSA specific disk attributes: ------------------------------ diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 50fddf84e47f..410910762fc5 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -148,6 +148,8 @@ static ssize_t lunid_show(struct device *dev, struct device_attribute *attr, char *buf); static ssize_t unique_id_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t host_show_firmware_revision(struct device *dev, + struct device_attribute *attr, char *buf); static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno); static ssize_t host_store_rescan(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); @@ -165,6 +167,8 @@ static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); +static DEVICE_ATTR(firmware_revision, S_IRUGO, + host_show_firmware_revision, NULL); static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_raid_level, @@ -175,6 +179,7 @@ static struct device_attribute *hpsa_sdev_attrs[] = { static struct device_attribute *hpsa_shost_attrs[] = { &dev_attr_rescan, + &dev_attr_firmware_revision, NULL, }; @@ -260,6 +265,21 @@ static ssize_t host_store_rescan(struct device *dev, return count; } +static ssize_t host_show_firmware_revision(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ctlr_info *h; + struct Scsi_Host *shost = class_to_shost(dev); + unsigned char *fwrev; + + h = shost_to_hba(shost); + if (!h->hba_inquiry_data) + return 0; + fwrev = &h->hba_inquiry_data[32]; + return snprintf(buf, 20, "%c%c%c%c\n", + fwrev[0], fwrev[1], fwrev[2], fwrev[3]); +} + /* Enqueuing and dequeuing functions for cmdlists. */ static inline void addQ(struct hlist_head *list, struct CommandList *c) { -- cgit v1.2.3 From def342bd745d88ed73541b9c07cefb13d8c576fd Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 27 May 2010 15:14:39 -0500 Subject: [SCSI] hpsa: fix block fetch table problem. We have 32 (MAXSGENTRIES) scatter gather elements embedded in the command. With all these, the total command size is about 576 bytes. However, the last entry in the block fetch table is 35. (the block fetch table contains the number of 16-byte chunks the firmware needs to fetch for a given number of scatter gather elements.) 35 * 16 = 560 bytes, which isn't enough. It needs to be 36. (36 * 16 == 576) or, MAXSGENTRIES + 4. (plus 4 because there's a bunch of stuff at the front of the command before the first scatter gather element that takes up 4 * 16 bytes.) Without this fix, the controller may have to perform two DMA operations to fetch the command since the first one may not get the whole thing. Signed-off-by: Don Brace Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 410910762fc5..1133b5fda0e7 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3826,7 +3826,26 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h) { int i; unsigned long register_value; - int bft[8] = {5, 6, 8, 10, 12, 20, 28, 35}; /* for scatter/gathers */ + + /* This is a bit complicated. There are 8 registers on + * the controller which we write to to tell it 8 different + * sizes of commands which there may be. It's a way of + * reducing the DMA done to fetch each command. Encoded into + * each command's tag are 3 bits which communicate to the controller + * which of the eight sizes that command fits within. The size of + * each command depends on how many scatter gather entries there are. + * Each SG entry requires 16 bytes. The eight registers are programmed + * with the number of 16-byte blocks a command of that size requires. + * The smallest command possible requires 5 such 16 byte blocks. + * the largest command possible requires MAXSGENTRIES + 4 16-byte + * blocks. Note, this only extends to the SG entries contained + * within the command block, and does not extend to chained blocks + * of SG elements. bft[] contains the eight values we write to + * the registers. They are not evenly distributed, but have more + * sizes for small commands, and fewer sizes for larger commands. + */ + int bft[8] = {5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4}; + BUILD_BUG_ON(28 > MAXSGENTRIES + 4); /* 5 = 1 s/g entry or 4k * 6 = 2 s/g entry or 8k * 8 = 4 s/g entry or 16k -- cgit v1.2.3 From b963752f47c54a29c11acee99e6c99b3c6bb35c5 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 28 May 2010 15:08:15 -0700 Subject: [SCSI] qla2xxx: Clear drive active CRB register when not in use. The CRB drive active register is cleared when driver is unloaded or when driver enters failed state. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 1 - drivers/scsi/qla2xxx/qla_init.c | 2 ++ drivers/scsi/qla2xxx/qla_iocb.c | 4 ++-- drivers/scsi/qla2xxx/qla_nx.c | 4 ++++ drivers/scsi/qla2xxx/qla_nx.h | 3 +-- drivers/scsi/qla2xxx/qla_os.c | 4 ++++ 6 files changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 8217c3bcbc2e..2247ef8702e4 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -513,7 +513,6 @@ extern int qla82xx_nvram_config(struct scsi_qla_host *); extern int qla82xx_pinit_from_rom(scsi_qla_host_t *); extern int qla82xx_load_firmware(scsi_qla_host_t *); extern int qla82xx_reset_hw(scsi_qla_host_t *); -extern int qla82xx_load_risc_blob(scsi_qla_host_t *, uint32_t *); extern void qla82xx_watchdog(scsi_qla_host_t *); /* Firmware and flash related functions */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ab2cc71994c2..f1db11a0d699 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1454,6 +1454,8 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) rval = ha->isp_ops->load_risc(vha, &srisc_address); if (rval == QLA_SUCCESS) goto enable_82xx_npiv; + else + goto failed; } if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) { diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 8ef945365412..5d0e99c2b522 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1683,7 +1683,7 @@ qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) struct srb_iocb *lio = ctx->u.iocb_cmd; uint16_t opts; - mbx->entry_type = MBX_IOCB_TYPE;; + mbx->entry_type = MBX_IOCB_TYPE; SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT); opts = lio->u.logio.flags & SRB_LOGIN_COND_PLOGI ? BIT_0 : 0; @@ -1718,7 +1718,7 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) { struct qla_hw_data *ha = sp->fcport->vha->hw; - mbx->entry_type = MBX_IOCB_TYPE;; + mbx->entry_type = MBX_IOCB_TYPE; SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); mbx->mb0 = cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); mbx->mb1 = HAS_EXTENDED_IDS(ha) ? diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index ff562de0e8e7..eb12bf260a17 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3279,6 +3279,10 @@ qla82xx_dev_failed_handler(scsi_qla_host_t *vha) /* Disable the board */ qla_printk(KERN_INFO, ha, "Disabling the board\n"); + qla82xx_idc_lock(ha); + qla82xx_clear_drv_active(ha); + qla82xx_idc_unlock(ha); + /* Set DEV_FAILED flag to disable timer */ vha->device_flags |= DFLG_DEV_FAILED; qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index f8f99a5ea532..aa95d3816d6c 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -538,11 +538,10 @@ /* Driver Coexistence Defines */ #define QLA82XX_CRB_DRV_ACTIVE (QLA82XX_CAM_RAM(0x138)) #define QLA82XX_CRB_DEV_STATE (QLA82XX_CAM_RAM(0x140)) -#define QLA82XX_CRB_DEV_PART_INFO (QLA82XX_CAM_RAM(0x14c)) -#define QLA82XX_CRB_DRV_IDC_VERSION (QLA82XX_CAM_RAM(0x174)) #define QLA82XX_CRB_DRV_STATE (QLA82XX_CAM_RAM(0x144)) #define QLA82XX_CRB_DRV_SCRATCH (QLA82XX_CAM_RAM(0x148)) #define QLA82XX_CRB_DEV_PART_INFO (QLA82XX_CAM_RAM(0x14c)) +#define QLA82XX_CRB_DRV_IDC_VERSION (QLA82XX_CAM_RAM(0x174)) /* Every driver should use these Device State */ #define QLA82XX_DEV_COLD 1 diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index be1a8fcbb1fb..c345ba716728 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2402,6 +2402,10 @@ qla2x00_remove_one(struct pci_dev *pdev) scsi_host_put(base_vha->host); if (IS_QLA82XX(ha)) { + qla82xx_idc_lock(ha); + qla82xx_clear_drv_active(ha); + qla82xx_idc_unlock(ha); + iounmap((device_reg_t __iomem *)ha->nx_pcibase); if (!ql2xdbwr) iounmap((device_reg_t __iomem *)ha->nxdb_wr_ptr); -- cgit v1.2.3 From d3fa9e7d270e3d9b3fda325cdcb2ea77a00ed876 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 28 May 2010 15:08:16 -0700 Subject: [SCSI] qla2xxx: Add portid to async-request messages. This helps to correlate submission/completion messages during triaging. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 6 ++++-- drivers/scsi/qla2xxx/qla_isr.c | 41 +++++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 16 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f1db11a0d699..4bf973483818 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -131,8 +131,10 @@ qla2x00_async_iocb_timeout(srb_t *sp) struct srb_ctx *ctx = sp->ctx; DEBUG2(printk(KERN_WARNING - "scsi(%ld:%x): Async-%s timeout.\n", - fcport->vha->host_no, sp->handle, ctx->name)); + "scsi(%ld:%x): Async-%s timeout - portid=%02x%02x%02x.\n", + fcport->vha->host_no, sp->handle, + ctx->name, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa)); fcport->flags &= ~FCF_ASYNC_SENT; if (ctx->type == SRB_LOGIN_CMD) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index be3d8bed2ecf..bc82ba99f251 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -918,12 +918,15 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, QLA_LOGIO_LOGIN_RETRIED : 0; if (mbx->entry_status) { DEBUG2(printk(KERN_WARNING - "scsi(%ld:%x): Async-%s error entry - entry-status=%x " - "status=%x state-flag=%x status-flags=%x.\n", + "scsi(%ld:%x): Async-%s error entry - portid=%02x%02x%02x " + "entry-status=%x status=%x state-flag=%x " + "status-flags=%x.\n", fcport->vha->host_no, sp->handle, type, - mbx->entry_status, le16_to_cpu(mbx->status), - le16_to_cpu(mbx->state_flags), + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa, mbx->entry_status, + le16_to_cpu(mbx->status), le16_to_cpu(mbx->state_flags), le16_to_cpu(mbx->status_flags))); + DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx))); goto logio_done; @@ -935,9 +938,11 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, status = 0; if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) { DEBUG2(printk(KERN_DEBUG - "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n", + "scsi(%ld:%x): Async-%s complete - portid=%02x%02x%02x " + "mbx1=%x.\n", fcport->vha->host_no, sp->handle, type, - le16_to_cpu(mbx->mb1))); + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa, le16_to_cpu(mbx->mb1))); data[0] = MBS_COMMAND_COMPLETE; if (ctx->type == SRB_LOGIN_CMD) { @@ -963,9 +968,10 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, } DEBUG2(printk(KERN_WARNING - "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x " - "mb6=%x mb7=%x.\n", - fcport->vha->host_no, sp->handle, type, status, + "scsi(%ld:%x): Async-%s failed - portid=%02x%02x%02x status=%x " + "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", + fcport->vha->host_no, sp->handle, type, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa, status, le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1), le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6), le16_to_cpu(mbx->mb7))); @@ -1096,9 +1102,11 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, QLA_LOGIO_LOGIN_RETRIED : 0; if (logio->entry_status) { DEBUG2(printk(KERN_WARNING - "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n", + "scsi(%ld:%x): Async-%s error entry - " + "portid=%02x%02x%02x entry-status=%x.\n", fcport->vha->host_no, sp->handle, type, - logio->entry_status)); + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa, logio->entry_status)); DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio))); goto logio_done; @@ -1106,8 +1114,11 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { DEBUG2(printk(KERN_DEBUG - "scsi(%ld:%x): Async-%s complete - iop0=%x.\n", + "scsi(%ld:%x): Async-%s complete - portid=%02x%02x%02x " + "iop0=%x.\n", fcport->vha->host_no, sp->handle, type, + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa, le32_to_cpu(logio->io_parameter[0]))); data[0] = MBS_COMMAND_COMPLETE; @@ -1152,8 +1163,10 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, } DEBUG2(printk(KERN_WARNING - "scsi(%ld:%x): Async-%s failed - comp=%x iop0=%x iop1=%x.\n", - fcport->vha->host_no, sp->handle, type, + "scsi(%ld:%x): Async-%s failed - portid=%02x%02x%02x comp=%x " + "iop0=%x iop1=%x.\n", + fcport->vha->host_no, sp->handle, type, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa, le16_to_cpu(logio->comp_status), le32_to_cpu(logio->io_parameter[0]), le32_to_cpu(logio->io_parameter[1]))); -- cgit v1.2.3 From 7e2b895b93db603ac3462175baa846ebf1be44da Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 28 May 2010 15:08:17 -0700 Subject: [SCSI] qla2xxx: Fix cpu-affinity usage for non-capable ISPs. The TMFs used for pre-24xx ISPs incorrectly assumed 'cpu' tag data could be valid. These chips have no multi-q/cpu-affinity support. This corrects an oops seen on ISP23xx parts. Signed-off-by: Andrew Vasquez Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index f3650d0434ca..043f808ba3f4 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -866,8 +866,8 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) l = l; vha = fcport->vha; - req = vha->hw->req_q_map[tag]; - rsp = vha->hw->rsp_q_map[tag]; + req = vha->hw->req_q_map[0]; + rsp = req->rsp; mcp->mb[0] = MBC_ABORT_TARGET; mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0; if (HAS_EXTENDED_IDS(vha->hw)) { @@ -915,8 +915,8 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no)); vha = fcport->vha; - req = vha->hw->req_q_map[tag]; - rsp = vha->hw->rsp_q_map[tag]; + req = vha->hw->req_q_map[0]; + rsp = req->rsp; mcp->mb[0] = MBC_LUN_RESET; mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; if (HAS_EXTENDED_IDS(vha->hw)) -- cgit v1.2.3 From 083a469db4ecf3b286a96b5b722c37fc1affe0be Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 28 May 2010 15:08:18 -0700 Subject: [SCSI] qla2xxx: Correct use-after-free oops seen during EH-abort. Hold a reference to the srb (sp) while aborting an I/O -- as the I/O can/will complete from within the interrupt-context. Signed-off-by: Andrew Vasquez Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_os.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 839610909018..f8239bff0924 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -202,6 +202,7 @@ struct sd_dif_tuple { * SCSI Request Block */ typedef struct srb { + atomic_t ref_count; struct fc_port *fcport; uint32_t handle; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c345ba716728..9e656296b757 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -517,6 +517,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport, if (!sp) return sp; + atomic_set(&sp->ref_count, 1); sp->fcport = fcport; sp->cmd = cmd; sp->flags = 0; @@ -797,6 +798,12 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha) return (return_status); } +static void +sp_get(struct srb *sp) +{ + atomic_inc(&sp->ref_count); +} + /************************************************************************** * qla2xxx_eh_abort * @@ -825,6 +832,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) struct qla_hw_data *ha = vha->hw; struct req_que *req = vha->req; srb_t *spt; + int got_ref = 0; fc_block_scsi_eh(cmd); @@ -856,6 +864,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) DEBUG2(printk("%s(%ld): aborting sp %p from RISC." " pid=%ld.\n", __func__, vha->host_no, sp, serial)); + /* Get a reference to the sp and drop the lock.*/ + sp_get(sp); + got_ref++; + spin_unlock_irqrestore(&ha->hardware_lock, flags); if (ha->isp_ops->abort_command(sp)) { DEBUG2(printk("%s(%ld): abort_command " @@ -881,6 +893,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } } + if (got_ref) + qla2x00_sp_compl(ha, sp); + qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n", vha->host_no, id, lun, wait, serial, ret); @@ -3468,7 +3483,7 @@ qla2x00_sp_free_dma(srb_t *sp) } void -qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp) +qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp) { struct scsi_cmnd *cmd = sp->cmd; @@ -3489,6 +3504,20 @@ qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp) cmd->scsi_done(cmd); } +void +qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp) +{ + if (atomic_read(&sp->ref_count) == 0) { + DEBUG2(qla_printk(KERN_WARNING, ha, + "SP reference-count to ZERO -- sp=%p\n", sp)); + DEBUG2(BUG()); + return; + } + if (!atomic_dec_and_test(&sp->ref_count)) + return; + qla2x00_sp_final_compl(ha, sp); +} + /************************************************************************** * qla2x00_timer * -- cgit v1.2.3 From 6ac5260850841eb4055811a68ff47d658ebe9a59 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 28 May 2010 15:08:19 -0700 Subject: [SCSI] qla2xxx: Correct async-srb issues. * hold the hardware_lock throughout the duration of ctx-sp timeout handling -- could result in use-after-free oops. * retry a timed-out login-request. * done() routines are called with the hardware-lock held, issue qla2x00_mark_device_lost() with proper 'defer' flag. * FCP2 capabilities are only relevant to target devices. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 20 ++++++++++++++------ drivers/scsi/qla2xxx/qla_isr.c | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 4bf973483818..cc7352545081 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -60,9 +60,8 @@ qla2x00_ctx_sp_timeout(unsigned long __data) ctx = sp->ctx; iocb = ctx->u.iocb_cmd; iocb->timeout(sp); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - iocb->free(sp); + spin_unlock_irqrestore(&ha->hardware_lock, flags); } void @@ -137,8 +136,16 @@ qla2x00_async_iocb_timeout(srb_t *sp) fcport->d_id.b.area, fcport->d_id.b.al_pa)); fcport->flags &= ~FCF_ASYNC_SENT; - if (ctx->type == SRB_LOGIN_CMD) + if (ctx->type == SRB_LOGIN_CMD) { + struct srb_iocb *lio = ctx->u.iocb_cmd; qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); + /* Retry as needed. */ + lio->u.logio.data[0] = MBS_COMMAND_ERROR; + lio->u.logio.data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ? + QLA_LOGIO_LOGIN_RETRIED : 0; + qla2x00_post_async_login_done_work(fcport->vha, fcport, + lio->u.logio.data); + } } static void @@ -420,10 +427,11 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, if (data[1] & QLA_LOGIO_LOGIN_RETRIED) set_bit(RELOGIN_NEEDED, &vha->dpc_flags); else - qla2x00_mark_device_lost(vha, fcport, 1, 0); + qla2x00_mark_device_lost(vha, fcport, 1, 1); break; case MBS_PORT_ID_USED: fcport->loop_id = data[1]; + qla2x00_post_async_logout_work(vha, fcport, NULL); qla2x00_post_async_login_work(vha, fcport, NULL); break; case MBS_LOOP_ID_USED: @@ -431,7 +439,7 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, rval = qla2x00_find_new_loop_id(vha, fcport); if (rval != QLA_SUCCESS) { fcport->flags &= ~FCF_ASYNC_SENT; - qla2x00_mark_device_lost(vha, fcport, 1, 0); + qla2x00_mark_device_lost(vha, fcport, 1, 1); break; } qla2x00_post_async_login_work(vha, fcport, NULL); @@ -463,7 +471,7 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport, if (data[1] & QLA_LOGIO_LOGIN_RETRIED) set_bit(RELOGIN_NEEDED, &vha->dpc_flags); else - qla2x00_mark_device_lost(vha, fcport, 1, 0); + qla2x00_mark_device_lost(vha, fcport, 1, 1); return; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index bc82ba99f251..912befdceb16 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -949,7 +949,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, fcport->port_type = FCT_TARGET; if (le16_to_cpu(mbx->mb1) & BIT_0) fcport->port_type = FCT_INITIATOR; - if (le16_to_cpu(mbx->mb1) & BIT_1) + else if (le16_to_cpu(mbx->mb1) & BIT_1) fcport->flags |= FCF_FCP2_DEVICE; } goto logio_done; -- cgit v1.2.3 From 3a6478df74c271cb3be5895b39fddf75e9cef89c Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 28 May 2010 15:08:20 -0700 Subject: [SCSI] qla2xxx: Limit rport-flaps during link-disruptions. Signed-off-by: Andrew Vasquez Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index cc7352545081..9d969b596b14 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2651,7 +2651,8 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); if (test_bit(RSCN_UPDATE, &save_flags)) { set_bit(RSCN_UPDATE, &vha->dpc_flags); - vha->flags.rscn_queue_overflow = 1; + if (!IS_ALOGIO_CAPABLE(ha)) + vha->flags.rscn_queue_overflow = 1; } } @@ -3209,8 +3210,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, if (qla2x00_is_reserved_id(vha, loop_id)) continue; - if (atomic_read(&vha->loop_down_timer) || - LOOP_TRANSITION(vha)) { + if (ha->current_topology == ISP_CFG_FL && + (atomic_read(&vha->loop_down_timer) || + LOOP_TRANSITION(vha))) { atomic_set(&vha->loop_down_timer, 0); set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); -- cgit v1.2.3 From 23f2ebd17a13835c5b34994d2c2e5faacc127947 Mon Sep 17 00:00:00 2001 From: Sarang Radke Date: Fri, 28 May 2010 15:08:21 -0700 Subject: [SCSI] qla2xxx: Add internal loopback support for ISP81xx. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 196 +++++++++++++++++++++++++++++++++++++---- drivers/scsi/qla2xxx/qla_bsg.h | 7 ++ drivers/scsi/qla2xxx/qla_def.h | 4 + drivers/scsi/qla2xxx/qla_gbl.h | 5 ++ drivers/scsi/qla2xxx/qla_isr.c | 7 +- drivers/scsi/qla2xxx/qla_mbx.c | 66 ++++++++++++++ drivers/scsi/qla2xxx/qla_os.c | 1 + 7 files changed, 269 insertions(+), 17 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index b905dfe5ea61..3a0248388505 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -483,6 +483,98 @@ done: return rval; } +/* Set the port configuration to enable the + * internal loopback on ISP81XX + */ +static inline int +qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config, + uint16_t *new_config) +{ + int ret = 0; + int rval = 0; + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA81XX(ha)) + goto done_set_internal; + + new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1); + memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ; + + ha->notify_dcbx_comp = 1; + ret = qla81xx_set_port_config(vha, new_config); + if (ret != QLA_SUCCESS) { + DEBUG2(printk(KERN_ERR + "%s(%lu): Set port config failed\n", + __func__, vha->host_no)); + ha->notify_dcbx_comp = 0; + rval = -EINVAL; + goto done_set_internal; + } + + /* Wait for DCBX complete event */ + if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) { + DEBUG2(qla_printk(KERN_WARNING, ha, + "State change notificaition not received.\n")); + } else + DEBUG2(qla_printk(KERN_INFO, ha, + "State change RECEIVED\n")); + + ha->notify_dcbx_comp = 0; + +done_set_internal: + return rval; +} + +/* Set the port configuration to disable the + * internal loopback on ISP81XX + */ +static inline int +qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config, + int wait) +{ + int ret = 0; + int rval = 0; + uint16_t new_config[4]; + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA81XX(ha)) + goto done_reset_internal; + + memset(new_config, 0 , sizeof(new_config)); + if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 == + ENABLE_INTERNAL_LOOPBACK) { + new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK; + memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ; + + ha->notify_dcbx_comp = wait; + ret = qla81xx_set_port_config(vha, new_config); + if (ret != QLA_SUCCESS) { + DEBUG2(printk(KERN_ERR + "%s(%lu): Set port config failed\n", + __func__, vha->host_no)); + ha->notify_dcbx_comp = 0; + rval = -EINVAL; + goto done_reset_internal; + } + + /* Wait for DCBX complete event */ + if (wait && !wait_for_completion_timeout(&ha->dcbx_comp, + (20 * HZ))) { + DEBUG2(qla_printk(KERN_WARNING, ha, + "State change notificaition not received.\n")); + ha->notify_dcbx_comp = 0; + rval = -EINVAL; + goto done_reset_internal; + } else + DEBUG2(qla_printk(KERN_INFO, ha, + "State change RECEIVED\n")); + + ha->notify_dcbx_comp = 0; + } +done_reset_internal: + return rval; +} + static int qla2x00_process_loopback(struct fc_bsg_job *bsg_job) { @@ -494,6 +586,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job) char *type; struct msg_echo_lb elreq; uint16_t response[MAILBOX_REGISTER_COUNT]; + uint16_t config[4], new_config[4]; uint8_t *fw_sts_ptr; uint8_t *req_data = NULL; dma_addr_t req_data_dma; @@ -568,29 +661,102 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job) elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; - if (ha->current_topology != ISP_CFG_F) { - type = "FC_BSG_HST_VENDOR_LOOPBACK"; + if ((ha->current_topology == ISP_CFG_F || + (IS_QLA81XX(ha) && + le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE + && req_data_len == MAX_ELS_FRAME_PAYLOAD)) && + elreq.options == EXTERNAL_LOOPBACK) { + type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; DEBUG2(qla_printk(KERN_INFO, ha, - "scsi(%ld) bsg rqst type: %s\n", - vha->host_no, type)); - - command_sent = INT_DEF_LB_LOOPBACK_CMD; - rval = qla2x00_loopback_test(vha, &elreq, response); + "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type)); + command_sent = INT_DEF_LB_ECHO_CMD; + rval = qla2x00_echo_test(vha, &elreq, response); + } else { if (IS_QLA81XX(ha)) { + memset(config, 0, sizeof(config)); + memset(new_config, 0, sizeof(new_config)); + if (qla81xx_get_port_config(vha, config)) { + DEBUG2(printk(KERN_ERR + "%s(%lu): Get port config failed\n", + __func__, vha->host_no)); + bsg_job->reply->reply_payload_rcv_len = 0; + bsg_job->reply->result = (DID_ERROR << 16); + rval = -EPERM; + goto done_free_dma_req; + } + + if (elreq.options != EXTERNAL_LOOPBACK) { + DEBUG2(qla_printk(KERN_INFO, ha, + "Internal: current port config = %x\n", + config[0])); + if (qla81xx_set_internal_loopback(vha, config, + new_config)) { + bsg_job->reply->reply_payload_rcv_len = + 0; + bsg_job->reply->result = + (DID_ERROR << 16); + rval = -EPERM; + goto done_free_dma_req; + } + } else { + /* For external loopback to work + * ensure internal loopback is disabled + */ + if (qla81xx_reset_internal_loopback(vha, + config, 1)) { + bsg_job->reply->reply_payload_rcv_len = + 0; + bsg_job->reply->result = + (DID_ERROR << 16); + rval = -EPERM; + goto done_free_dma_req; + } + } + + type = "FC_BSG_HST_VENDOR_LOOPBACK"; + DEBUG2(qla_printk(KERN_INFO, ha, + "scsi(%ld) bsg rqst type: %s\n", + vha->host_no, type)); + + command_sent = INT_DEF_LB_LOOPBACK_CMD; + rval = qla2x00_loopback_test(vha, &elreq, response); + + if (new_config[1]) { + /* Revert back to original port config + * Also clear internal loopback + */ + qla81xx_reset_internal_loopback(vha, + new_config, 0); + } + if (response[0] == MBS_COMMAND_ERROR && - response[1] == MBS_LB_RESET) { + response[1] == MBS_LB_RESET) { DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing " - "ISP\n", __func__, vha->host_no)); + "ISP\n", __func__, vha->host_no)); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + /* Also reset the MPI */ + if (qla81xx_restart_mpi_firmware(vha) != + QLA_SUCCESS) { + qla_printk(KERN_INFO, ha, + "MPI reset failed for host%ld.\n", + vha->host_no); + } + + bsg_job->reply->reply_payload_rcv_len = 0; + bsg_job->reply->result = (DID_ERROR << 16); + rval = -EIO; + goto done_free_dma_req; } + } else { + type = "FC_BSG_HST_VENDOR_LOOPBACK"; + DEBUG2(qla_printk(KERN_INFO, ha, + "scsi(%ld) bsg rqst type: %s\n", + vha->host_no, type)); + command_sent = INT_DEF_LB_LOOPBACK_CMD; + rval = qla2x00_loopback_test(vha, &elreq, response); } - } else { - type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; - DEBUG2(qla_printk(KERN_INFO, ha, - "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type)); - command_sent = INT_DEF_LB_ECHO_CMD; - rval = qla2x00_echo_test(vha, &elreq, response); } if (rval) { diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index 76ed92dd2ef2..1f096dabc015 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h @@ -19,6 +19,13 @@ #define INT_DEF_LB_LOOPBACK_CMD 0 #define INT_DEF_LB_ECHO_CMD 1 +/* Loopback related definations */ +#define EXTERNAL_LOOPBACK 0xF2 +#define ENABLE_INTERNAL_LOOPBACK 0x02 +#define INTERNAL_LOOPBACK_MASK 0x000E +#define MAX_ELS_FRAME_PAYLOAD 252 +#define ELS_OPCODE_BYTE 0x10 + /* BSG Vendor specific definations */ #define A84_ISSUE_WRITE_TYPE_CMD 0 #define A84_ISSUE_READ_TYPE_CMD 1 diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index f8239bff0924..2895855adc9a 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -714,6 +714,8 @@ typedef struct { #define MBC_SEND_RNFT_ELS 0x5e /* Send RNFT ELS request */ #define MBC_GET_LINK_PRIV_STATS 0x6d /* Get link & private data. */ #define MBC_SET_VENDOR_ID 0x76 /* Set Vendor ID. */ +#define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */ +#define MBC_GET_PORT_CONFIG 0x123 /* Get port configuration */ /* Firmware return data sizes */ #define FCAL_MAP_SIZE 128 @@ -2631,6 +2633,8 @@ struct qla_hw_data { struct mutex vport_lock; /* Virtual port synchronization */ struct completion mbx_cmd_comp; /* Serialize mbx access */ struct completion mbx_intr_comp; /* Used for completion notification */ + struct completion dcbx_comp; /* For set port config notification */ + int notify_dcbx_comp; /* Basic firmware related information. */ uint16_t fw_major_version; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 2247ef8702e4..7ae2ee42564e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -357,6 +357,11 @@ qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); extern int qla2x00_get_data_rate(scsi_qla_host_t *); extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *); +extern int +qla81xx_get_port_config(scsi_qla_host_t *, uint16_t *); + +extern int +qla81xx_set_port_config(scsi_qla_host_t *, uint16_t *); /* * Global Function Prototypes in qla_isr.c source file. diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 912befdceb16..e51fc5f9fcdb 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -545,10 +545,13 @@ skip_rio: if (IS_QLA2100(ha)) break; - if (IS_QLA8XXX_TYPE(ha)) + if (IS_QLA8XXX_TYPE(ha)) { DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x " "%04x\n", vha->host_no, mb[1], mb[2], mb[3])); - else + if (ha->notify_dcbx_comp) + complete(&ha->dcbx_comp); + + } else DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE " "received.\n", vha->host_no)); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 043f808ba3f4..10f4815aec77 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -3949,6 +3949,72 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) return rval; } +int +qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + struct qla_hw_data *ha = vha->hw; + + DEBUG11(printk(KERN_INFO + "%s(%ld): entered.\n", __func__, vha->host_no)); + + if (!IS_QLA81XX(ha)) + return QLA_FUNCTION_FAILED; + mcp->mb[0] = MBC_GET_PORT_CONFIG; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk(KERN_WARNING + "%s(%ld): failed=%x (%x).\n", __func__, + vha->host_no, rval, mcp->mb[0])); + } else { + /* Copy all bits to preserve original value */ + memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4); + + DEBUG11(printk(KERN_INFO + "%s(%ld): done.\n", __func__, vha->host_no)); + } + return rval; +} + +int +qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk(KERN_INFO + "%s(%ld): entered.\n", __func__, vha->host_no)); + + mcp->mb[0] = MBC_SET_PORT_CONFIG; + /* Copy all bits to preserve original setting */ + memcpy(&mcp->mb[1], mb, sizeof(uint16_t) * 4); + mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk(KERN_WARNING + "%s(%ld): failed=%x (%x).\n", __func__, + vha->host_no, rval, mcp->mb[0])); + } else + DEBUG11(printk(KERN_INFO + "%s(%ld): done.\n", __func__, vha->host_no)); + + return rval; +} + + int qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, uint16_t *mb) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 9e656296b757..fa59181bcb02 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2128,6 +2128,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) init_completion(&ha->mbx_cmd_comp); complete(&ha->mbx_cmd_comp); init_completion(&ha->mbx_intr_comp); + init_completion(&ha->dcbx_comp); set_bit(0, (unsigned long *) ha->vp_idx_map); -- cgit v1.2.3 From b0cd579cde8ee0c7ed52239531ba09bcbc5b54c2 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 28 May 2010 15:08:22 -0700 Subject: [SCSI] qla2xxx: Make the FC port capability mutual exclusive. In case of both target and initiator capabilities reported by fc port, the fc port port capability is made mutualy exclusive with priority given for target capabilities. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index e51fc5f9fcdb..8a608725eb76 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1133,9 +1133,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, fcport->port_type = FCT_TARGET; if (iop[0] & BIT_8) fcport->flags |= FCF_FCP2_DEVICE; - } - if (iop[0] & BIT_5) + } else if (iop[0] & BIT_5) fcport->port_type = FCT_INITIATOR; + if (logio->io_parameter[7] || logio->io_parameter[8]) fcport->supported_classes |= FC_COS_CLASS2; if (logio->io_parameter[9] || logio->io_parameter[10]) -- cgit v1.2.3 From 9c2b297572bf3cc36d26520cd8f7e7ef4cb857f8 Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Fri, 28 May 2010 15:08:23 -0700 Subject: [SCSI] qla2xxx: Support for loading Unified ROM Image (URI) format firmware file. Used bootloder address from FLT while loading FW from flash as well. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 3 + drivers/scsi/qla2xxx/qla_nx.c | 184 +++++++++++++++++++++++++++++++++++++++-- drivers/scsi/qla2xxx/qla_nx.h | 35 ++++++++ 3 files changed, 215 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 2895855adc9a..f0e792a82dde 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2788,6 +2788,9 @@ struct qla_hw_data { uint16_t gbl_dsd_avail; struct list_head gbl_dsd_list; #define NUM_DSD_CHAIN 4096 + + uint8_t fw_type; + __le32 file_prd_off; /* File firmware product offset */ }; /* diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index eb12bf260a17..1a9a7343dffa 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1407,7 +1407,8 @@ qla82xx_fw_load_from_flash(struct qla_hw_data *ha) { int i; long size = 0; - long flashaddr = BOOTLD_START, memaddr = BOOTLD_START; + long flashaddr = ha->flt_region_bootload << 2; + long memaddr = BOOTLD_START; u64 data; u32 high, low; size = (IMAGE_START - BOOTLD_START) / 8; @@ -1677,6 +1678,94 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, return ret; } +static struct qla82xx_uri_table_desc * +qla82xx_get_table_desc(const u8 *unirom, int section) +{ + uint32_t i; + struct qla82xx_uri_table_desc *directory = + (struct qla82xx_uri_table_desc *)&unirom[0]; + __le32 offset; + __le32 tab_type; + __le32 entries = cpu_to_le32(directory->num_entries); + + for (i = 0; i < entries; i++) { + offset = cpu_to_le32(directory->findex) + + (i * cpu_to_le32(directory->entry_size)); + tab_type = cpu_to_le32(*((u32 *)&unirom[offset] + 8)); + + if (tab_type == section) + return (struct qla82xx_uri_table_desc *)&unirom[offset]; + } + + return NULL; +} + +static struct qla82xx_uri_data_desc * +qla82xx_get_data_desc(struct qla_hw_data *ha, + u32 section, u32 idx_offset) +{ + const u8 *unirom = ha->hablob->fw->data; + int idx = cpu_to_le32(*((int *)&unirom[ha->file_prd_off] + idx_offset)); + struct qla82xx_uri_table_desc *tab_desc = NULL; + __le32 offset; + + tab_desc = qla82xx_get_table_desc(unirom, section); + if (!tab_desc) + return NULL; + + offset = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * idx); + + return (struct qla82xx_uri_data_desc *)&unirom[offset]; +} + +static u8 * +qla82xx_get_bootld_offset(struct qla_hw_data *ha) +{ + u32 offset = BOOTLD_START; + struct qla82xx_uri_data_desc *uri_desc = NULL; + + if (ha->fw_type == QLA82XX_UNIFIED_ROMIMAGE) { + uri_desc = qla82xx_get_data_desc(ha, + QLA82XX_URI_DIR_SECT_BOOTLD, QLA82XX_URI_BOOTLD_IDX_OFF); + if (uri_desc) + offset = cpu_to_le32(uri_desc->findex); + } + + return (u8 *)&ha->hablob->fw->data[offset]; +} + +static __le32 +qla82xx_get_fw_size(struct qla_hw_data *ha) +{ + struct qla82xx_uri_data_desc *uri_desc = NULL; + + if (ha->fw_type == QLA82XX_UNIFIED_ROMIMAGE) { + uri_desc = qla82xx_get_data_desc(ha, QLA82XX_URI_DIR_SECT_FW, + QLA82XX_URI_FIRMWARE_IDX_OFF); + if (uri_desc) + return cpu_to_le32(uri_desc->size); + } + + return cpu_to_le32(*(u32 *)&ha->hablob->fw->data[FW_SIZE_OFFSET]); +} + +static u8 * +qla82xx_get_fw_offs(struct qla_hw_data *ha) +{ + u32 offset = IMAGE_START; + struct qla82xx_uri_data_desc *uri_desc = NULL; + + if (ha->fw_type == QLA82XX_UNIFIED_ROMIMAGE) { + uri_desc = qla82xx_get_data_desc(ha, QLA82XX_URI_DIR_SECT_FW, + QLA82XX_URI_FIRMWARE_IDX_OFF); + if (uri_desc) + offset = cpu_to_le32(uri_desc->findex); + } + + return (u8 *)&ha->hablob->fw->data[offset]; +} + /* PCI related functions */ char * qla82xx_pci_info_str(struct scsi_qla_host *vha, char *str) @@ -1878,19 +1967,19 @@ int qla82xx_fw_load_from_blob(struct qla_hw_data *ha) size = (IMAGE_START - BOOTLD_START) / 8; - ptr64 = (u64 *)&ha->hablob->fw->data[BOOTLD_START]; + ptr64 = (u64 *)qla82xx_get_bootld_offset(ha); flashaddr = BOOTLD_START; for (i = 0; i < size; i++) { data = cpu_to_le64(ptr64[i]); - qla82xx_pci_mem_write_2M(ha, flashaddr, &data, 8); + if (qla82xx_pci_mem_write_2M(ha, flashaddr, &data, 8)) + return -EIO; flashaddr += 8; } - size = *(u32 *)&ha->hablob->fw->data[FW_SIZE_OFFSET]; - size = (__force u32)cpu_to_le32(size) / 8; - ptr64 = (u64 *)&ha->hablob->fw->data[IMAGE_START]; flashaddr = FLASH_ADDR_START; + size = (__force u32)qla82xx_get_fw_size(ha) / 8; + ptr64 = (u64 *)qla82xx_get_fw_offs(ha); for (i = 0; i < size; i++) { data = cpu_to_le64(ptr64[i]); @@ -1899,19 +1988,88 @@ int qla82xx_fw_load_from_blob(struct qla_hw_data *ha) return -EIO; flashaddr += 8; } + udelay(100); /* Write a magic value to CAMRAM register * at a specified offset to indicate * that all data is written and * ready for firmware to initialize. */ - qla82xx_wr_32(ha, QLA82XX_CAM_RAM(0x1fc), 0x12345678); + qla82xx_wr_32(ha, QLA82XX_CAM_RAM(0x1fc), QLA82XX_BDINFO_MAGIC); + read_lock(&ha->hw_lock); if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); } else qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001d); + read_unlock(&ha->hw_lock); + return 0; +} + +static int +qla82xx_set_product_offset(struct qla_hw_data *ha) +{ + struct qla82xx_uri_table_desc *ptab_desc = NULL; + const uint8_t *unirom = ha->hablob->fw->data; + uint32_t i; + __le32 entries; + __le32 flags, file_chiprev, offset; + uint8_t chiprev = ha->chip_revision; + /* Hardcoding mn_present flag for P3P */ + int mn_present = 0; + uint32_t flagbit; + + ptab_desc = qla82xx_get_table_desc(unirom, + QLA82XX_URI_DIR_SECT_PRODUCT_TBL); + if (!ptab_desc) + return -1; + + entries = cpu_to_le32(ptab_desc->num_entries); + + for (i = 0; i < entries; i++) { + offset = cpu_to_le32(ptab_desc->findex) + + (i * cpu_to_le32(ptab_desc->entry_size)); + flags = cpu_to_le32(*((int *)&unirom[offset] + + QLA82XX_URI_FLAGS_OFF)); + file_chiprev = cpu_to_le32(*((int *)&unirom[offset] + + QLA82XX_URI_CHIP_REV_OFF)); + + flagbit = mn_present ? 1 : 2; + + if ((chiprev == file_chiprev) && ((1ULL << flagbit) & flags)) { + ha->file_prd_off = offset; + return 0; + } + } + return -1; +} + +int +qla82xx_validate_firmware_blob(scsi_qla_host_t *vha, uint8_t fw_type) +{ + __le32 val; + uint32_t min_size; + struct qla_hw_data *ha = vha->hw; + const struct firmware *fw = ha->hablob->fw; + + ha->fw_type = fw_type; + + if (fw_type == QLA82XX_UNIFIED_ROMIMAGE) { + if (qla82xx_set_product_offset(ha)) + return -EINVAL; + + min_size = QLA82XX_URI_FW_MIN_SIZE; + } else { + val = cpu_to_le32(*(u32 *)&fw->data[QLA82XX_FW_MAGIC_OFFSET]); + if ((__force u32)val != QLA82XX_BDINFO_MAGIC) + return -EINVAL; + + min_size = QLA82XX_FW_MIN_SIZE; + } + + if (fw->size < min_size) + return -EINVAL; return 0; } @@ -2470,6 +2628,18 @@ try_blob_fw: goto fw_load_failed; } + /* Validating firmware blob */ + if (qla82xx_validate_firmware_blob(vha, + QLA82XX_FLASH_ROMIMAGE)) { + /* Fallback to URI format */ + if (qla82xx_validate_firmware_blob(vha, + QLA82XX_UNIFIED_ROMIMAGE)) { + qla_printk(KERN_ERR, ha, + "No valid firmware image found!!!"); + return QLA_FUNCTION_FAILED; + } + } + if (qla82xx_fw_load_from_blob(ha) == QLA_SUCCESS) { qla_printk(KERN_ERR, ha, "%s: Firmware loaded successfully " diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index aa95d3816d6c..9a9127efadaf 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -773,13 +773,48 @@ struct qla82xx_legacy_intr_set { .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \ } +#define BRDCFG_START 0x4000 #define BOOTLD_START 0x10000 #define IMAGE_START 0x100000 #define FLASH_ADDR_START 0x43000 /* Magic number to let user know flash is programmed */ #define QLA82XX_BDINFO_MAGIC 0x12345678 +#define QLA82XX_FW_MAGIC_OFFSET (BRDCFG_START + 0x128) #define FW_SIZE_OFFSET (0x3e840c) +#define QLA82XX_FW_MIN_SIZE 0x3fffff + +/* UNIFIED ROMIMAGE START */ +#define QLA82XX_URI_FW_MIN_SIZE 0xc8000 +#define QLA82XX_URI_DIR_SECT_PRODUCT_TBL 0x0 +#define QLA82XX_URI_DIR_SECT_BOOTLD 0x6 +#define QLA82XX_URI_DIR_SECT_FW 0x7 + +/* Offsets */ +#define QLA82XX_URI_CHIP_REV_OFF 10 +#define QLA82XX_URI_FLAGS_OFF 11 +#define QLA82XX_URI_BIOS_VERSION_OFF 12 +#define QLA82XX_URI_BOOTLD_IDX_OFF 27 +#define QLA82XX_URI_FIRMWARE_IDX_OFF 29 + +struct qla82xx_uri_table_desc{ + uint32_t findex; + uint32_t num_entries; + uint32_t entry_size; + uint32_t reserved[5]; +}; + +struct qla82xx_uri_data_desc{ + uint32_t findex; + uint32_t size; + uint32_t reserved[5]; +}; + +/* UNIFIED ROMIMAGE END */ + +#define QLA82XX_UNIFIED_ROMIMAGE 3 +#define QLA82XX_FLASH_ROMIMAGE 4 +#define QLA82XX_UNKNOWN_ROMIMAGE 0xff #define QLA82XX_IS_REVISION_P3PLUS(_rev_) ((_rev_) >= 0x50) #define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0) -- cgit v1.2.3 From 3f3b6f98cb33043cba04f45a2f2c43b8303c120c Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Fri, 28 May 2010 15:08:24 -0700 Subject: [SCSI] qla2xxx: Do not enable VP in non fabric topology. After topology change ISP is reset and VPs are re-enabled. If the topology is not fabric, VPs could falsely get enabled. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 8220e7b9799b..d1618b4a5e50 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -136,7 +136,8 @@ qla24xx_enable_vp(scsi_qla_host_t *vha) /* Check if physical ha port is Up */ if (atomic_read(&base_vha->loop_state) == LOOP_DOWN || - atomic_read(&base_vha->loop_state) == LOOP_DEAD) { + atomic_read(&base_vha->loop_state) == LOOP_DEAD || + !(ha->current_topology & ISP_CFG_F)) { vha->vp_err_state = VP_ERR_PORTDWN; fc_vport_set_state(vha->fc_vport, FC_VPORT_LINKDOWN); goto enable_failed; -- cgit v1.2.3 From cdbb0a4f31c486e4f6fb6e673a892f4f5205f91c Mon Sep 17 00:00:00 2001 From: Santosh Vernekar Date: Fri, 28 May 2010 15:08:25 -0700 Subject: [SCSI] qla2xxx: Handle outstanding mbx cmds on hung f/w scenarios. Outstanding mailbox commands, have no way to recover on f/w hung, and we timeout on waiting for mbx response. This in turn affects the recovery process as follows: - We might already be in dpc while waiting for mbx to complete, so recovery for that pci function will never get invoked. Reset Timeout (10 sec) is far less than mbx timeout (30 sec). - Other mbx cmds will get stuck due to serial mbx access. Solution is to identify fw-hung scenario and handle outstanding mbx commands to have an early-exit instead of waiting for response. Other mbx commands waiting for access will also do an early-exit if fw-hung is still applicable. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 3 +- drivers/scsi/qla2xxx/qla_mbx.c | 78 +++++++++++++++++++++++++++++------------ drivers/scsi/qla2xxx/qla_nx.c | 20 ++++++++++- 4 files changed, 78 insertions(+), 24 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index f0e792a82dde..2bb187e23db0 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2413,6 +2413,7 @@ struct qla_hw_data { uint32_t cpu_affinity_enabled :1; uint32_t disable_msix_handshake :1; uint32_t fcp_prio_enabled :1; + uint32_t fw_hung :1; } flags; /* This spinlock is used to protect "io transactions", you must diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 9d969b596b14..4c6caccc6ad5 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1972,7 +1972,8 @@ qla2x00_fw_ready(scsi_qla_host_t *vha) } } else { /* Mailbox cmd failed. Timeout on min_wait. */ - if (time_after_eq(jiffies, mtime)) + if (time_after_eq(jiffies, mtime) || + (IS_QLA82XX(ha) && ha->flags.fw_hung)) break; } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 10f4815aec77..2f39e3093939 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -37,7 +37,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) device_reg_t __iomem *reg; uint8_t abort_active; uint8_t io_lock_on; - uint16_t command; + uint16_t command = 0; uint16_t *iptr; uint16_t __iomem *optr; uint32_t cnt; @@ -83,6 +83,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) return QLA_FUNCTION_TIMEOUT; } + if (IS_QLA82XX(ha) && ha->flags.fw_hung) { + /* Setting Link-Down error */ + mcp->mb[0] = MBS_LINK_DOWN_ERROR; + rval = QLA_FUNCTION_FAILED; + goto premature_exit; + } + ha->flags.mbox_busy = 1; /* Save mailbox command for debug */ ha->mcp = mcp; @@ -151,7 +158,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) DEBUG2_3_11(printk(KERN_INFO "%s(%ld): Pending Mailbox timeout. " "Exiting.\n", __func__, base_vha->host_no)); - return QLA_FUNCTION_TIMEOUT; + rval = QLA_FUNCTION_TIMEOUT; + goto premature_exit; } WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING); } else if (IS_FWI2_CAPABLE(ha)) @@ -176,7 +184,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) DEBUG2_3_11(printk(KERN_INFO "%s(%ld): Pending Mailbox timeout. " "Exiting.\n", __func__, base_vha->host_no)); - return QLA_FUNCTION_TIMEOUT; + rval = QLA_FUNCTION_TIMEOUT; + goto premature_exit; } WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING); } else if (IS_FWI2_CAPABLE(ha)) @@ -214,6 +223,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) ha->flags.mbox_int = 0; clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + if (IS_QLA82XX(ha) && ha->flags.fw_hung) { + ha->flags.mbox_busy = 0; + /* Setting Link-Down error */ + mcp->mb[0] = MBS_LINK_DOWN_ERROR; + ha->mcp = NULL; + rval = QLA_FUNCTION_FAILED; + goto premature_exit; + } + if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) rval = QLA_FUNCTION_FAILED; @@ -279,35 +297,51 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) DEBUG2_3_11(printk("%s(%ld): timeout schedule " "isp_abort_needed.\n", __func__, base_vha->host_no)); - qla_printk(KERN_WARNING, ha, - "Mailbox command timeout occurred. Scheduling ISP " - "abort. eeh_busy: 0x%x\n", ha->flags.eeh_busy); - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); - qla2xxx_wake_dpc(vha); + + if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && + !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && + !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { + + qla_printk(KERN_WARNING, ha, + "Mailbox command timeout occured. " + "Scheduling ISP " "abort. eeh_busy: 0x%x\n", + ha->flags.eeh_busy); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + } } else if (!abort_active) { /* call abort directly since we are in the DPC thread */ DEBUG(printk("%s(%ld): timeout calling abort_isp\n", __func__, base_vha->host_no)); DEBUG2_3_11(printk("%s(%ld): timeout calling " "abort_isp\n", __func__, base_vha->host_no)); - qla_printk(KERN_WARNING, ha, - "Mailbox command timeout occurred. Issuing ISP " - "abort.\n"); - - set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); - clear_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); - if (ha->isp_ops->abort_isp(base_vha)) { - /* Failed. retry later. */ - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); + + if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && + !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && + !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { + + qla_printk(KERN_WARNING, ha, + "Mailbox command timeout occured. " + "Issuing ISP abort.\n"); + + set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); + clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + if (ha->isp_ops->abort_isp(vha)) { + /* Failed. retry later. */ + set_bit(ISP_ABORT_NEEDED, + &vha->dpc_flags); + } + clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); + DEBUG(printk("%s(%ld): finished abort_isp\n", + __func__, vha->host_no)); + DEBUG2_3_11(printk( + "%s(%ld): finished abort_isp\n", + __func__, vha->host_no)); } - clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); - DEBUG(printk("%s(%ld): finished abort_isp\n", __func__, - base_vha->host_no)); - DEBUG2_3_11(printk("%s(%ld): finished abort_isp\n", - __func__, base_vha->host_no)); } } +premature_exit: /* Allow next mbx cmd to come in. */ complete(&ha->mbx_cmd_comp); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 1a9a7343dffa..512ba8a4ac57 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3543,6 +3543,14 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha) set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } qla2xxx_wake_dpc(vha); + if (ha->flags.mbox_busy) { + ha->flags.fw_hung = 1; + ha->flags.mbox_int = 1; + DEBUG2(qla_printk(KERN_ERR, ha, + "Due to fw hung, doing premature " + "completion of mbx command\n")); + complete(&ha->mbx_intr_comp); + } } } vha->fw_heartbeat_counter = fw_heartbeat_counter; @@ -3646,6 +3654,14 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) "%s(): Adapter reset needed!\n", __func__); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); + if (ha->flags.mbox_busy) { + ha->flags.fw_hung = 1; + ha->flags.mbox_int = 1; + DEBUG2(qla_printk(KERN_ERR, ha, + "Need reset, doing premature " + "completion of mbx command\n")); + complete(&ha->mbx_intr_comp); + } } else { qla82xx_check_fw_alive(vha); } @@ -3701,8 +3717,10 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) qla82xx_clear_rst_ready(ha); qla82xx_idc_unlock(ha); - if (rval == QLA_SUCCESS) + if (rval == QLA_SUCCESS) { + ha->flags.fw_hung = 0; qla82xx_restart_isp(vha); + } if (rval) { vha->flags.online = 1; -- cgit v1.2.3 From 0547fb37ca1f8da18e65b7452f99e9784f026be2 Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Fri, 28 May 2010 15:08:26 -0700 Subject: [SCSI] qla2xxx: Fix flash write failure on ISP82xx. Driver was not unprotecting correctly, use correct bits to unprotect the flash on ISP 82xx. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 512ba8a4ac57..ee575b4efbee 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -19,6 +19,7 @@ #define QLA82XX_PCI_OCM0_2M (0xc0000) #define VALID_OCM_ADDR(addr) (((addr) & 0x3f800) != 0x3f800) #define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) +#define BLOCK_PROTECT_BITS 0x0F /* CRB window related */ #define CRB_BLK(off) ((off >> 20) & 0x3f) @@ -3147,10 +3148,10 @@ qla82xx_unprotect_flash(struct qla_hw_data *ha) if (ret < 0) goto done_unprotect; - val &= ~(0x7 << 2); + val &= ~(BLOCK_PROTECT_BITS << 2); ret = qla82xx_write_status_reg(ha, val); if (ret < 0) { - val |= (0x7 << 2); + val |= (BLOCK_PROTECT_BITS << 2); qla82xx_write_status_reg(ha, val); } @@ -3178,7 +3179,7 @@ qla82xx_protect_flash(struct qla_hw_data *ha) if (ret < 0) goto done_protect; - val |= (0x7 << 2); + val |= (BLOCK_PROTECT_BITS << 2); /* LOCK all sectors */ ret = qla82xx_write_status_reg(ha, val); if (ret < 0) -- cgit v1.2.3 From ba77ef53547883b6be06c0657d5dc1642ad43d0c Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Fri, 28 May 2010 15:08:27 -0700 Subject: [SCSI] qla2xxx: T10 DIF enablement for 81XX Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 1e4cafabba15..2b499c7601ec 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1732,7 +1732,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); } - if (IS_QLA25XX(ha) && ql2xenabledif) { + if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) { if (ha->fw_attributes & BIT_4) { vha->flags.difdix_supported = 1; DEBUG18(qla_printk(KERN_INFO, ha, diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index fa59181bcb02..bc35ecfbc28f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1677,7 +1677,7 @@ static struct isp_operations qla81xx_isp_ops = { .read_optrom = qla25xx_read_optrom_data, .write_optrom = qla24xx_write_optrom_data, .get_flash_version = qla24xx_get_flash_version, - .start_scsi = qla24xx_start_scsi, + .start_scsi = qla24xx_dif_start_scsi, .abort_isp = qla2x00_abort_isp, }; @@ -2274,7 +2274,7 @@ skip_dpc: DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", base_vha->host_no, ha)); - if (IS_QLA25XX(ha) && ql2xenabledif) { + if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) { if (ha->fw_attributes & BIT_4) { base_vha->flags.difdix_supported = 1; DEBUG18(qla_printk(KERN_INFO, ha, -- cgit v1.2.3 From 6907869d726c04362122afd92717f86915a69f96 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 28 May 2010 15:08:28 -0700 Subject: [SCSI] qla2xxx: Enable CRB based doorbell posting for request queue as default for ISP 82xx. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 13 +++++++++---- drivers/scsi/qla2xxx/qla_os.c | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index ee575b4efbee..e3e3ebdfe5d9 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3372,11 +3372,16 @@ qla82xx_start_iocbs(srb_t *sp) dbval = 0x04 | (ha->portnum << 5); dbval = dbval | (req->id << 8) | (req->ring_index << 16); - WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval); - wmb(); - while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { - WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval); + if (ql2xdbwr) + qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); + else { + WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, dbval); wmb(); + while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { + WRT_REG_DWORD((unsigned long __iomem *)ha->nxdb_wr_ptr, + dbval); + wmb(); + } } } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index bc35ecfbc28f..5be8db748964 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -140,7 +140,7 @@ MODULE_PARM_DESC(ql2xetsenable, "Enables firmware ETS burst." "Default is 0 - skip ETS enablement."); -int ql2xdbwr; +int ql2xdbwr = 1; module_param(ql2xdbwr, int, S_IRUGO|S_IRUSR); MODULE_PARM_DESC(ql2xdbwr, "Option to specify scheme for request queue posting\n" -- cgit v1.2.3 From 6c7ccf7bb96a0ae16d2bcc6155e1d1fc3e728b39 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 28 May 2010 15:08:29 -0700 Subject: [SCSI] qla2xxx: Removed redundant check for ISP 84xx. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 2b499c7601ec..fd6f7b100547 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1208,7 +1208,7 @@ qla24xx_84xx_fw_version_show(struct device *dev, if (!IS_QLA84XX(ha)) return snprintf(buf, PAGE_SIZE, "\n"); - if (ha->cs84xx && ha->cs84xx->op_fw_version == 0) + if (ha->cs84xx->op_fw_version == 0) rval = qla84xx_verify_chip(vha, status); if ((rval == QLA_SUCCESS) && (status[0] == 0)) -- cgit v1.2.3 From 5b91490e457a88080b4dbc68f4bc2eadd65e30ea Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 28 May 2010 15:08:30 -0700 Subject: [SCSI] qla2xxx: For ISP 23xx, select user specified login timeout value if greater than minuimum value(4 secs). Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 4c6caccc6ad5..d0b993c8a189 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -121,7 +121,23 @@ done: /* Asynchronous Login/Logout Routines -------------------------------------- */ -#define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2) +static inline unsigned long +qla2x00_get_async_timeout(struct scsi_qla_host *vha) +{ + unsigned long tmo; + struct qla_hw_data *ha = vha->hw; + + /* Firmware should use switch negotiated r_a_tov for timeout. */ + tmo = ha->r_a_tov / 10 * 2; + if (!IS_FWI2_CAPABLE(ha)) { + /* + * Except for earlier ISPs where the timeout is seeded from the + * initialization control block. + */ + tmo = ha->login_timeout; + } + return tmo; +} static void qla2x00_async_iocb_timeout(srb_t *sp) @@ -163,7 +179,6 @@ int qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, uint16_t *data) { - struct qla_hw_data *ha = vha->hw; srb_t *sp; struct srb_ctx *ctx; struct srb_iocb *lio; @@ -171,7 +186,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, rval = QLA_FUNCTION_FAILED; sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), - ELS_TMO_2_RATOV(ha) + 2); + qla2x00_get_async_timeout(vha) + 2); if (!sp) goto done; @@ -215,7 +230,6 @@ qla2x00_async_logout_ctx_done(srb_t *sp) int qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) { - struct qla_hw_data *ha = vha->hw; srb_t *sp; struct srb_ctx *ctx; struct srb_iocb *lio; @@ -223,7 +237,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) rval = QLA_FUNCTION_FAILED; sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), - ELS_TMO_2_RATOV(ha) + 2); + qla2x00_get_async_timeout(vha) + 2); if (!sp) goto done; @@ -264,7 +278,6 @@ int qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport, uint16_t *data) { - struct qla_hw_data *ha = vha->hw; srb_t *sp; struct srb_ctx *ctx; struct srb_iocb *lio; @@ -272,7 +285,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport, rval = QLA_FUNCTION_FAILED; sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), - ELS_TMO_2_RATOV(ha) + 2); + qla2x00_get_async_timeout(vha) + 2); if (!sp) goto done; @@ -316,7 +329,6 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, uint32_t tag) { struct scsi_qla_host *vha = fcport->vha; - struct qla_hw_data *ha = vha->hw; srb_t *sp; struct srb_ctx *ctx; struct srb_iocb *tcf; @@ -324,7 +336,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, rval = QLA_FUNCTION_FAILED; sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), - ELS_TMO_2_RATOV(ha) + 2); + qla2x00_get_async_timeout(vha) + 2); if (!sp) goto done; @@ -2409,7 +2421,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) ha->retry_count = nv->retry_count; /* Set minimum login_timeout to 4 seconds. */ - if (nv->login_timeout < ql2xlogintimeout) + if (nv->login_timeout != ql2xlogintimeout) nv->login_timeout = ql2xlogintimeout; if (nv->login_timeout < 4) nv->login_timeout = 4; -- cgit v1.2.3 From c0ff2775a1dcbaf2cbe3fb571ae5ea11b63ea590 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 28 May 2010 15:08:31 -0700 Subject: [SCSI] qla2xxx: Updated version number to 8.03.03-k0. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 109068df933f..9b49b0862747 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,9 +7,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.02-k2" +#define QLA2XXX_VERSION "8.03.03-k0" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 -#define QLA_DRIVER_PATCH_VER 2 -#define QLA_DRIVER_BETA_VER 2 +#define QLA_DRIVER_PATCH_VER 3 +#define QLA_DRIVER_BETA_VER 0 -- cgit v1.2.3 From da2907ffd08a2d708c829ec171f05fe3ceab1315 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 30 May 2010 15:49:22 +0200 Subject: [SCSI] dpt_i2o: Use GFP_ATOMIC when a lock is held The function adpt_i2o_post_wait is called from several places, in some of which, such as adpt_abort, a lock may be held. The functions adpt_i2o_reparse_lct and adpt_i2o_lct_get are called from several places, including adpt_rescan where a lock may be held. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @gfp exists@ identifier fn; position p; @@ fn(...) { ... when != spin_unlock_irqrestore when any GFP_KERNEL@p ... when any } @locked@ identifier gfp.fn; @@ spin_lock_irqsave(...) ... when != spin_unlock_irqrestore fn(...) @depends on locked@ position gfp.p; @@ - GFP_KERNEL@p + GFP_ATOMIC // Signed-off-by: Julia Lawall Signed-off-by: James Bottomley --- drivers/scsi/dpt_i2o.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index b0c576f84b28..f2d4df14c311 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -1290,7 +1290,7 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout) ulong flags = 0; struct adpt_i2o_post_wait_data *p1, *p2; struct adpt_i2o_post_wait_data *wait_data = - kmalloc(sizeof(struct adpt_i2o_post_wait_data),GFP_KERNEL); + kmalloc(sizeof(struct adpt_i2o_post_wait_data), GFP_ATOMIC); DECLARE_WAITQUEUE(wait, current); if (!wait_data) @@ -2651,7 +2651,8 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) pDev = pDev->next_lun; } if(!pDev ) { // Something new add it - d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL); + d = kmalloc(sizeof(struct i2o_device), + GFP_ATOMIC); if(d==NULL) { printk(KERN_CRIT "Out of memory for I2O device data.\n"); @@ -2673,7 +2674,9 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) } pDev = pHba->channel[bus_no].device[scsi_id]; if( pDev == NULL){ - pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL); + pDev = + kzalloc(sizeof(struct adpt_device), + GFP_ATOMIC); if(pDev == NULL) { return -ENOMEM; } @@ -2682,7 +2685,9 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) while (pDev->next_lun) { pDev = pDev->next_lun; } - pDev = pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL); + pDev = pDev->next_lun = + kzalloc(sizeof(struct adpt_device), + GFP_ATOMIC); if(pDev == NULL) { return -ENOMEM; } @@ -3127,7 +3132,7 @@ static int adpt_i2o_lct_get(adpt_hba* pHba) if (pHba->lct == NULL) { pHba->lct = dma_alloc_coherent(&pHba->pDev->dev, pHba->lct_size, &pHba->lct_pa, - GFP_KERNEL); + GFP_ATOMIC); if(pHba->lct == NULL) { printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n", pHba->name); -- cgit v1.2.3 From 8701f18504751a5b89be3203e28c5ec04c147167 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Fri, 4 Jun 2010 10:26:50 -0700 Subject: [SCSI] ipr: add endian swap enablement for 64 bit adapters A change in the hardware design of the chip for the new adapters changes the default endianness of MMIO operations. This patch adds a register definition which when written to with a predefined value will change the endianness back to what the driver expects. This patch also fixes two problems found during testing. First, the first reserved field in the ipr_hostrcb64_fabirc_desc structure only reserved one byte. The correct amount to reserve is 2 bytes. Second, the reserved field of the ipr_hostrcb64_error structure only reserved 2 bytes. The correct amount to reserve is 16 bytes. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 19 +++++++++++++++++-- drivers/scsi/ipr.h | 9 +++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index f820cffb7f00..62bbe31dd47b 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -167,7 +167,8 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { .clr_uproc_interrupt_reg32 = 0x0002C, .init_feedback_reg = 0x0005C, .dump_addr_reg = 0x00064, - .dump_data_reg = 0x00068 + .dump_data_reg = 0x00068, + .endian_swap_reg = 0x00084 } }, }; @@ -7208,6 +7209,12 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) ipr_init_ioa_mem(ioa_cfg); ioa_cfg->allow_interrupts = 1; + if (ioa_cfg->sis64) { + /* Set the adapter to the correct endian mode. */ + writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg); + int_reg = readl(ioa_cfg->regs.endian_swap_reg); + } + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { @@ -7365,6 +7372,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + volatile u32 int_reg; int rc; ENTER; @@ -7383,6 +7391,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) ipr_fail_all_ops(ioa_cfg); + if (ioa_cfg->sis64) { + /* Set the adapter to the correct endian mode. */ + writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg); + int_reg = readl(ioa_cfg->regs.endian_swap_reg); + } + if (ioa_cfg->ioa_unit_checked) { ioa_cfg->ioa_unit_checked = 0; ipr_get_unit_check_buffer(ioa_cfg); @@ -7547,7 +7561,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd) } /** - * ipr_reset_alert_part2 - Alert the adapter of a pending reset + * ipr_reset_alert - Alert the adapter of a pending reset * @ipr_cmd: ipr command struct * * Description: This function alerts the adapter that it will be reset. @@ -8318,6 +8332,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, t->init_feedback_reg = base + p->init_feedback_reg; t->dump_addr_reg = base + p->dump_addr_reg; t->dump_data_reg = base + p->dump_data_reg; + t->endian_swap_reg = base + p->endian_swap_reg; } } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index b965f3587c9d..ea391ffc8711 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -996,7 +996,7 @@ struct ipr_hostrcb64_fabric_desc { __be16 length; u8 descriptor_id; - u8 reserved; + u8 reserved[2]; u8 path_state; u8 reserved2[2]; @@ -1054,7 +1054,7 @@ struct ipr_hostrcb64_error { __be64 fd_lun; u8 fd_res_path[8]; __be64 time_stamp; - u8 reserved[2]; + u8 reserved[16]; union { struct ipr_hostrcb_type_ff_error type_ff_error; struct ipr_hostrcb_type_12_error type_12_error; @@ -1254,6 +1254,9 @@ struct ipr_interrupt_offsets { unsigned long dump_addr_reg; unsigned long dump_data_reg; + +#define IPR_ENDIAN_SWAP_KEY 0x000C0C00 + unsigned long endian_swap_reg; }; struct ipr_interrupts { @@ -1279,6 +1282,8 @@ struct ipr_interrupts { void __iomem *dump_addr_reg; void __iomem *dump_data_reg; + + void __iomem *endian_swap_reg; }; struct ipr_chip_cfg_t { -- cgit v1.2.3 From ffc954936b134cc6d2eba1282cc71084929c3704 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 7 Jun 2010 15:23:17 -0400 Subject: [SCSI] lpfc 8.3.13: FC Discovery Fixes and enhancements. - Retry PLOGI up to 48 times when LS_RJT reason is "Unable to supply requested data." - When dev loss timeout occures do not change state if there is an outstanding REG_LOGIN. - Add logic to ignore REG_LOGIN completion if discovery is restarted while waiting for REG_LOGIN. - Only change state on REG_LOGIN completion if still in state waiting for REG_LOGIN completion. - Only send ADISCs to FCP-2 Targets (not Initiators). Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_disc.h | 2 ++ drivers/scsi/lpfc/lpfc_els.c | 9 +++++++++ drivers/scsi/lpfc/lpfc_hbadisc.c | 35 ++++++++++++++++++++++++++++++++--- drivers/scsi/lpfc/lpfc_nportdisc.c | 7 ++++++- 5 files changed, 50 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index fbc9baeb6048..6b404e510a3b 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -41,6 +41,7 @@ void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, LPFC_MBOXQ_t *, uint32_t); +void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 36257a685509..7cae69de36f7 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -114,6 +114,8 @@ struct lpfc_nodelist { }; /* Defines for nlp_flag (uint32) */ +#define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */ +#define NLP_REG_LOGIN_SEND 0x00000002 /* sent reglogin to adapter */ #define NLP_PLOGI_SND 0x00000020 /* sent PLOGI request for this entry */ #define NLP_PRLI_SND 0x00000040 /* sent PRLI request for this entry */ #define NLP_ADISC_SND 0x00000080 /* sent ADISC request for this entry */ diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index c4c7f0ad7468..6b1850c9fdff 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2740,6 +2740,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, retry = 1; break; } + if (stat.un.b.lsRjtRsnCodeExp == + LSEXP_CANT_GIVE_DATA) { + if (cmd == ELS_CMD_PLOGI) { + delay = 1000; + maxretry = 48; + } + retry = 1; + break; + } if (cmd == ELS_CMD_PLOGI) { delay = 1000; maxretry = lpfc_max_els_tries + 1; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 1f87b4fb8b50..8082d69ea730 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -275,7 +275,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) if (!(vport->load_flag & FC_UNLOADING) && !(ndlp->nlp_flag & NLP_DELAY_TMO) && !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && - (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) + (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE)) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); lpfc_unregister_unused_fcf(phba); @@ -2715,11 +2716,35 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) struct lpfc_vport *vport = pmb->vport; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; + struct Scsi_Host *shost = lpfc_shost_from_vport(vport); pmb->context1 = NULL; - /* Good status, call state machine */ - lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN); + if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; + + if (ndlp->nlp_flag & NLP_IGNR_REG_CMPL || + ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) { + /* We rcvd a rscn after issuing this + * mbox reg login, we may have cycled + * back through the state and be + * back at reg login state so this + * mbox needs to be ignored becase + * there is another reg login in + * proccess. + */ + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; + spin_unlock_irq(shost->host_lock); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_free_rpi(phba, + pmb->u.mb.un.varRegLogin.rpi); + + } else + /* Good status, call state machine */ + lpfc_disc_state_machine(vport, ndlp, pmb, + NLP_EVT_CMPL_REG_LOGIN); + lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); @@ -3842,6 +3867,9 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) kfree(mp); } list_del(&mb->list); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_free_rpi(phba, + mb->u.mb.un.varRegLogin.rpi); mempool_free(mb, phba->mbox_mem_pool); /* We shall not invoke the lpfc_nlp_put to decrement * the ndlp reference count as we are in the process @@ -3883,6 +3911,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_cancel_retry_delay_tmo(vport, ndlp); if ((ndlp->nlp_flag & NLP_DEFER_RM) && + !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) && !(ndlp->nlp_flag & NLP_RPI_VALID)) { /* For this case we need to cleanup the default rpi * allocated by the firmware. diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index b90820a699fd..9810b3d3cc53 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -626,7 +626,8 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (!(vport->fc_flag & FC_PT2PT)) { /* Check config parameter use-adisc or FCP-2 */ if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || - ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { + ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) && + (ndlp->nlp_type & NLP_FCP_TARGET))) { spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_NPR_ADISC; spin_unlock_irq(shost->host_lock); @@ -962,6 +963,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login; break; default: + ndlp->nlp_flag |= NLP_REG_LOGIN_SEND; mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; } mbox->context2 = lpfc_nlp_get(ndlp); @@ -972,6 +974,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, NLP_STE_REG_LOGIN_ISSUE); return ndlp->nlp_state; } + if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; /* decrement node reference count to the failed mbox * command */ @@ -1458,6 +1462,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); spin_lock_irq(shost->host_lock); + ndlp->nlp_flag |= NLP_IGNR_REG_CMPL; ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); spin_unlock_irq(shost->host_lock); lpfc_disc_set_adisc(vport, ndlp); -- cgit v1.2.3 From 6e7288d9a4b6691bf13fb07e3593d70d725d0737 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 7 Jun 2010 15:23:35 -0400 Subject: [SCSI] lpfc 8.3.13: Initialization code clean up and fixes. - Add poll or wait flag parameter to hba_init_link and hba_down_link. - (From Linux Community) Make return with ENXIO negative. - Remove unused INB code from driver. - Prevent block_magmt_io from returning until mailbox is inactive. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 8 ++------ drivers/scsi/lpfc/lpfc_attr.c | 4 ++-- drivers/scsi/lpfc/lpfc_hw.h | 8 -------- drivers/scsi/lpfc/lpfc_init.c | 40 +++++++++++++++++++++++++++++++++++----- drivers/scsi/lpfc/lpfc_mbox.c | 1 - drivers/scsi/lpfc/lpfc_sli.c | 22 ++++------------------ 6 files changed, 43 insertions(+), 40 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index e35a4c71eb9a..4cb78483bf79 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -510,9 +510,9 @@ struct lpfc_hba { void (*lpfc_stop_port) (struct lpfc_hba *); int (*lpfc_hba_init_link) - (struct lpfc_hba *); + (struct lpfc_hba *, uint32_t); int (*lpfc_hba_down_link) - (struct lpfc_hba *); + (struct lpfc_hba *, uint32_t); /* SLI4 specific HBA data structure */ struct lpfc_sli4_hba sli4_hba; @@ -525,7 +525,6 @@ struct lpfc_hba { #define LPFC_SLI3_NPIV_ENABLED 0x02 #define LPFC_SLI3_VPORT_TEARDOWN 0x04 #define LPFC_SLI3_CRP_ENABLED 0x08 -#define LPFC_SLI3_INB_ENABLED 0x10 #define LPFC_SLI3_BG_ENABLED 0x20 #define LPFC_SLI3_DSS_ENABLED 0x40 uint32_t iocb_cmd_size; @@ -557,9 +556,6 @@ struct lpfc_hba { MAILBOX_t *mbox; uint32_t *mbox_ext; - uint32_t *inb_ha_copy; - uint32_t *inb_counter; - uint32_t inb_last_counter; uint32_t ha_copy; struct _PCB *pcb; struct _IOCB *IOCBs; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index bf33b315f93e..b17fe5149e38 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -506,10 +506,10 @@ lpfc_link_state_store(struct device *dev, struct device_attribute *attr, if ((strncmp(buf, "up", sizeof("up") - 1) == 0) && (phba->link_state == LPFC_LINK_DOWN)) - status = phba->lpfc_hba_init_link(phba); + status = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); else if ((strncmp(buf, "down", sizeof("down") - 1) == 0) && (phba->link_state >= LPFC_LINK_UP)) - status = phba->lpfc_hba_down_link(phba); + status = phba->lpfc_hba_down_link(phba, MBX_NOWAIT); if (status == 0) return strlen(buf); diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index e654d01dad24..bc813fd99d5e 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -3014,18 +3014,10 @@ struct sli3_pgp { uint32_t hbq_get[16]; }; -struct sli3_inb_pgp { - uint32_t ha_copy; - uint32_t counter; - struct lpfc_pgp port[MAX_RINGS]; - uint32_t hbq_get[16]; -}; - union sli_var { struct sli2_desc s2; struct sli3_desc s3; struct sli3_pgp s3_pgp; - struct sli3_inb_pgp s3_inb_pgp; }; typedef struct { diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index cd9697edf860..8da8fc69227f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -621,6 +621,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) /** * lpfc_hba_init_link - Initialize the FC link * @phba: pointer to lpfc hba data structure. + * @flag: mailbox command issue mode - either MBX_POLL or MBX_NOWAIT * * This routine will issue the INIT_LINK mailbox command call. * It is available to other drivers through the lpfc_hba data @@ -632,7 +633,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) * Any other value - error **/ int -lpfc_hba_init_link(struct lpfc_hba *phba) +lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag) { struct lpfc_vport *vport = phba->pport; LPFC_MBOXQ_t *pmb; @@ -651,7 +652,7 @@ lpfc_hba_init_link(struct lpfc_hba *phba) phba->cfg_link_speed); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; lpfc_set_loopback_flag(phba); - rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); + rc = lpfc_sli_issue_mbox(phba, pmb, flag); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0498 Adapter failed to init, mbxCmd x%x " @@ -664,17 +665,21 @@ lpfc_hba_init_link(struct lpfc_hba *phba) writel(0xffffffff, phba->HAregaddr); readl(phba->HAregaddr); /* flush */ phba->link_state = LPFC_HBA_ERROR; - if (rc != MBX_BUSY) + if (rc != MBX_BUSY || flag == MBX_POLL) mempool_free(pmb, phba->mbox_mem_pool); return -EIO; } phba->cfg_suppress_link_up = LPFC_INITIALIZE_LINK; + if (flag == MBX_POLL) + mempool_free(pmb, phba->mbox_mem_pool); return 0; } /** * lpfc_hba_down_link - this routine downs the FC link + * @phba: pointer to lpfc hba data structure. + * @flag: mailbox command issue mode - either MBX_POLL or MBX_NOWAIT * * This routine will issue the DOWN_LINK mailbox command call. * It is available to other drivers through the lpfc_hba data @@ -685,7 +690,7 @@ lpfc_hba_init_link(struct lpfc_hba *phba) * Any other value - error **/ int -lpfc_hba_down_link(struct lpfc_hba *phba) +lpfc_hba_down_link(struct lpfc_hba *phba, uint32_t flag) { LPFC_MBOXQ_t *pmb; int rc; @@ -701,7 +706,7 @@ lpfc_hba_down_link(struct lpfc_hba *phba) "0491 Adapter Link is disabled.\n"); lpfc_down_link(phba, pmb); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); + rc = lpfc_sli_issue_mbox(phba, pmb, flag); if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -711,6 +716,9 @@ lpfc_hba_down_link(struct lpfc_hba *phba) mempool_free(pmb, phba->mbox_mem_pool); return -EIO; } + if (flag == MBX_POLL) + mempool_free(pmb, phba->mbox_mem_pool); + return 0; } @@ -2279,10 +2287,32 @@ static void lpfc_block_mgmt_io(struct lpfc_hba * phba) { unsigned long iflag; + uint8_t actcmd = MBX_HEARTBEAT; + unsigned long timeout; + spin_lock_irqsave(&phba->hbalock, iflag); phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO; + if (phba->sli.mbox_active) + actcmd = phba->sli.mbox_active->u.mb.mbxCommand; spin_unlock_irqrestore(&phba->hbalock, iflag); + /* Determine how long we might wait for the active mailbox + * command to be gracefully completed by firmware. + */ + timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) + + jiffies; + /* Wait for the outstnading mailbox command to complete */ + while (phba->sli.mbox_active) { + /* Check active mailbox complete status every 2ms */ + msleep(2); + if (time_after(jiffies, timeout)) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2813 Mgmt IO is Blocked %x " + "- mbox cmd %x still active\n", + phba->sli.sli_flag, actcmd); + break; + } + } } /** diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index e84dc33ca201..196371fae242 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1199,7 +1199,6 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mb->un.varCfgPort.cdss = 1; /* Configure Security */ mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */ - mb->un.varCfgPort.cinb = 1; /* Interrupt Notification Block */ mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); if (phba->max_vpi && phba->cfg_enable_npiv && phba->vpd.sli3Feat.cmv) { diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7a61455140b6..87ae175a0830 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -3794,7 +3794,7 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba) phba->link_state = LPFC_HBA_ERROR; mempool_free(pmb, phba->mbox_mem_pool); - return ENXIO; + return -ENXIO; } } phba->hbq_count = hbq_count; @@ -3885,7 +3885,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED | LPFC_SLI3_CRP_ENABLED | - LPFC_SLI3_INB_ENABLED | LPFC_SLI3_BG_ENABLED); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -3927,20 +3926,9 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED; if (pmb->u.mb.un.varCfgPort.gcrp) phba->sli3_options |= LPFC_SLI3_CRP_ENABLED; - if (pmb->u.mb.un.varCfgPort.ginb) { - phba->sli3_options |= LPFC_SLI3_INB_ENABLED; - phba->hbq_get = phba->mbox->us.s3_inb_pgp.hbq_get; - phba->port_gp = phba->mbox->us.s3_inb_pgp.port; - phba->inb_ha_copy = &phba->mbox->us.s3_inb_pgp.ha_copy; - phba->inb_counter = &phba->mbox->us.s3_inb_pgp.counter; - phba->inb_last_counter = - phba->mbox->us.s3_inb_pgp.counter; - } else { - phba->hbq_get = phba->mbox->us.s3_pgp.hbq_get; - phba->port_gp = phba->mbox->us.s3_pgp.port; - phba->inb_ha_copy = NULL; - phba->inb_counter = NULL; - } + + phba->hbq_get = phba->mbox->us.s3_pgp.hbq_get; + phba->port_gp = phba->mbox->us.s3_pgp.port; if (phba->cfg_enable_bg) { if (pmb->u.mb.un.varCfgPort.gbg) @@ -3953,8 +3941,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) } else { phba->hbq_get = NULL; phba->port_gp = phba->mbox->us.s2.port; - phba->inb_ha_copy = NULL; - phba->inb_counter = NULL; phba->max_vpi = 0; } do_prep_failed: -- cgit v1.2.3 From b92938b41ee84b83347b62baa6daa0d06a742e94 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 7 Jun 2010 15:24:12 -0400 Subject: [SCSI] lpfc 8.3.13: SCSI specific changes - Fix hba_queue_depth to reflect actual available XRIs - Add support for new SLER specific firmware status codes. - Free SCSI buffer when iotag allocation fails. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hw.h | 8 ++++++++ drivers/scsi/lpfc/lpfc_init.c | 7 +++++-- drivers/scsi/lpfc/lpfc_scsi.c | 5 ++++- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index bc813fd99d5e..8887fd831a2c 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -3124,6 +3124,14 @@ typedef struct { #define IOERR_BUFFER_SHORTAGE 0x28 #define IOERR_DEFAULT 0x29 #define IOERR_CNT 0x2A +#define IOERR_SLER_FAILURE 0x46 +#define IOERR_SLER_CMD_RCV_FAILURE 0x47 +#define IOERR_SLER_REC_RJT_ERR 0x48 +#define IOERR_SLER_REC_SRR_RETRY_ERR 0x49 +#define IOERR_SLER_SRR_RJT_ERR 0x4A +#define IOERR_SLER_RRQ_RJT_ERR 0x4C +#define IOERR_SLER_RRQ_RETRY_ERR 0x4D +#define IOERR_SLER_ABTS_ERR 0x4E #define IOERR_DRVR_MASK 0x100 #define IOERR_SLI_DOWN 0x101 /* ulpStatus - Driver defined */ diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 8da8fc69227f..62585870f083 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5563,9 +5563,12 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) mempool_free(pmb, phba->mbox_mem_pool); /* Reset the DFT_HBA_Q_DEPTH to the max xri */ - if (phba->cfg_hba_queue_depth > (phba->sli4_hba.max_cfg_param.max_xri)) + if (phba->cfg_hba_queue_depth > + (phba->sli4_hba.max_cfg_param.max_xri - + lpfc_sli4_get_els_iocb_cnt(phba))) phba->cfg_hba_queue_depth = - phba->sli4_hba.max_cfg_param.max_xri; + phba->sli4_hba.max_cfg_param.max_xri - + lpfc_sli4_get_els_iocb_cnt(phba); return rc; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f4a3b2e79eea..f7a92653467a 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -774,6 +774,8 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) /* Allocate iotag for psb->cur_iocbq. */ iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq); if (iotag == 0) { + pci_pool_free(phba->lpfc_scsi_dma_buf_pool, + psb->data, psb->dma_handle); kfree(psb); break; } @@ -2363,7 +2365,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, case IOSTAT_LOCAL_REJECT: if (lpfc_cmd->result == IOERR_INVALID_RPI || lpfc_cmd->result == IOERR_NO_RESOURCES || - lpfc_cmd->result == IOERR_ABORT_REQUESTED) { + lpfc_cmd->result == IOERR_ABORT_REQUESTED || + lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) { cmd->result = ScsiResult(DID_REQUEUE, 0); break; } -- cgit v1.2.3 From 98fc5dd952ecfd3abff7c06e7a55a5eab4dd95b7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 7 Jun 2010 15:24:29 -0400 Subject: [SCSI] lpfc 8.3.13: Misc fixes - Change the Max receive size on CIN FCFs to 0x800 - (From linux community) Check boundary before checking for NULL. - Update last completion time for completed I/O to prevent heartbeat. - Add Balius PCI Device IDs Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hw.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 6 ++++++ drivers/scsi/lpfc/lpfc_sli.c | 4 ++++ drivers/scsi/lpfc/lpfc_sli4.h | 2 +- drivers/scsi/lpfc/lpfc_vport.c | 2 +- 5 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 8887fd831a2c..f5dbf2be3eab 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1170,6 +1170,7 @@ typedef struct { #define PCI_DEVICE_ID_TIGERSHARK 0x0704 #define PCI_DEVICE_ID_TOMCAT 0x0714 #define PCI_DEVICE_ID_FALCON 0xf180 +#define PCI_DEVICE_ID_BALIUS 0xe131 #define JEDEC_ID_ADDRESS 0x0080001c #define FIREFLY_JEDEC_ID 0x1ACC diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 62585870f083..7dc55989b8ff 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1826,6 +1826,10 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) m = (typeof(m)){"LPSe12002-ML1-E", "PCIe", "EmulexSecure Fibre"}; break; + case PCI_DEVICE_ID_BALIUS: + m = (typeof(m)){"LPVe12002", "PCIe Shared I/O", + "Fibre Channel Adapter"}; + break; default: m = (typeof(m)){"Unknown", "", ""}; break; @@ -8835,6 +8839,8 @@ static struct pci_device_id lpfc_id_table[] = { PCI_ANY_ID, PCI_ANY_ID, }, {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FALCON, PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BALIUS, + PCI_ANY_ID, PCI_ANY_ID, }, { 0 } }; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 87ae175a0830..103a5aa4ae81 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -9194,6 +9194,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, { struct lpfc_wcqe_release wcqe; bool workposted = false; + unsigned long iflag; /* Copy the work queue CQE and convert endian order if needed */ lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe)); @@ -9202,6 +9203,9 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, switch (bf_get(lpfc_wcqe_c_code, &wcqe)) { case CQE_CODE_COMPL_WQE: /* Process the WQ complete event */ + spin_lock_irqsave(&phba->hbalock, iflag); + phba->last_completion_time = jiffies; + spin_unlock_irqrestore(&phba->hbalock, iflag); lpfc_sli4_fp_handle_fcp_wcqe(phba, (struct lpfc_wcqe_complete *)&wcqe); break; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 58bb4c81b54e..1f8ec72c5dcb 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -58,7 +58,7 @@ #define LPFC_FCOE_FCF_MAP0 0x0E #define LPFC_FCOE_FCF_MAP1 0xFC #define LPFC_FCOE_FCF_MAP2 0x00 -#define LPFC_FCOE_MAX_RCV_SIZE 0x5AC +#define LPFC_FCOE_MAX_RCV_SIZE 0x800 #define LPFC_FCOE_FKA_ADV_PER 0 #define LPFC_FCOE_FIP_PRIORITY 0x80 diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index ab91359bde20..1655507a682c 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -782,7 +782,7 @@ lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports) int i; if (vports == NULL) return; - for (i = 0; vports[i] != NULL && i <= phba->max_vports; i++) + for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) scsi_host_put(lpfc_shost_from_vport(vports[i])); kfree(vports); } -- cgit v1.2.3 From 2a9bf3d011303d8da64cd5e0e7fdd95f0c143984 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 7 Jun 2010 15:24:45 -0400 Subject: [SCSI] lpfc 8.3.13: Add TX Queue Support for SLI4 ELS commands. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 5 +- drivers/scsi/lpfc/lpfc_attr.c | 58 +++++++++++ drivers/scsi/lpfc/lpfc_bsg.c | 9 ++ drivers/scsi/lpfc/lpfc_crtn.h | 9 ++ drivers/scsi/lpfc/lpfc_els.c | 36 +++++-- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 + drivers/scsi/lpfc/lpfc_init.c | 8 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 24 ++++- drivers/scsi/lpfc/lpfc_scsi.c | 4 +- drivers/scsi/lpfc/lpfc_sli.c | 194 ++++++++++++++++++++++++++++++++----- drivers/scsi/lpfc/lpfc_sli.h | 2 + 11 files changed, 310 insertions(+), 41 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 4cb78483bf79..fcfc495d1e0d 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -20,7 +20,6 @@ *******************************************************************/ #include - struct lpfc_sli2_slim; #define LPFC_PCI_DEV_LP 0x1 @@ -376,6 +375,7 @@ struct lpfc_vport { #define WORKER_FABRIC_BLOCK_TMO 0x400 /* hba: fabric block timeout */ #define WORKER_RAMP_DOWN_QUEUE 0x800 /* hba: Decrease Q depth */ #define WORKER_RAMP_UP_QUEUE 0x1000 /* hba: Increase Q depth */ +#define WORKER_SERVICE_TXQ 0x2000 /* hba: IOCBs on the txq */ struct timer_list fc_fdmitmo; struct timer_list els_tmofunc; @@ -624,6 +624,7 @@ struct lpfc_hba { uint32_t cfg_hostmem_hgp; uint32_t cfg_log_verbose; uint32_t cfg_aer_support; + uint32_t cfg_iocb_cnt; uint32_t cfg_suppress_link_up; #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ @@ -812,6 +813,8 @@ struct lpfc_hba { uint8_t menlo_flag; /* menlo generic flags */ #define HBA_MENLO_SUPPORT 0x1 /* HBA supports menlo commands */ + uint32_t iocb_cnt; + uint32_t iocb_max; }; static inline struct Scsi_Host * diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index b17fe5149e38..39b0760c438d 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1949,6 +1949,59 @@ static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL); LPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK, LPFC_DELAY_INIT_LINK_INDEFINITELY, "Suppress Link Up at initialization"); +/* +# lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS +# 1 - (1024) +# 2 - (2048) +# 3 - (3072) +# 4 - (4096) +# 5 - (5120) +*/ +static ssize_t +lpfc_iocb_hw_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + + return snprintf(buf, PAGE_SIZE, "%d\n", phba->iocb_max); +} + +static DEVICE_ATTR(iocb_hw, S_IRUGO, + lpfc_iocb_hw_show, NULL); +static ssize_t +lpfc_txq_hw_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + + return snprintf(buf, PAGE_SIZE, "%d\n", + phba->sli.ring[LPFC_ELS_RING].txq_max); +} + +static DEVICE_ATTR(txq_hw, S_IRUGO, + lpfc_txq_hw_show, NULL); +static ssize_t +lpfc_txcmplq_hw_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_hba *phba = ((struct lpfc_vport *) shost->hostdata)->phba; + + return snprintf(buf, PAGE_SIZE, "%d\n", + phba->sli.ring[LPFC_ELS_RING].txcmplq_max); +} + +static DEVICE_ATTR(txcmplq_hw, S_IRUGO, + lpfc_txcmplq_hw_show, NULL); + +int lpfc_iocb_cnt = 2; +module_param(lpfc_iocb_cnt, int, 1); +MODULE_PARM_DESC(lpfc_iocb_cnt, + "Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs"); +lpfc_param_show(iocb_cnt); +lpfc_param_init(iocb_cnt, 2, 1, 5); +static DEVICE_ATTR(lpfc_iocb_cnt, S_IRUGO, + lpfc_iocb_cnt_show, NULL); /* # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear @@ -3334,6 +3387,10 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_aer_support, &dev_attr_lpfc_aer_state_cleanup, &dev_attr_lpfc_suppress_link_up, + &dev_attr_lpfc_iocb_cnt, + &dev_attr_iocb_hw, + &dev_attr_txq_hw, + &dev_attr_txcmplq_hw, NULL, }; @@ -4521,6 +4578,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); lpfc_aer_support_init(phba, lpfc_aer_support); lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); + lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); return; } diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index dcf088262b20..55f984166dbc 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -377,6 +377,11 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) if (rc == IOCB_SUCCESS) return 0; /* done for now */ + else if (rc == IOCB_BUSY) + rc = EAGAIN; + else + rc = EIO; + /* iocb failed so cleanup */ pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, @@ -625,6 +630,10 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job) lpfc_nlp_put(ndlp); if (rc == IOCB_SUCCESS) return 0; /* done for now */ + else if (rc == IOCB_BUSY) + rc = EAGAIN; + else + rc = EIO; pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, job->request_payload.sg_cnt, DMA_TO_DEVICE); diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 6b404e510a3b..361f4e7e23e4 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -403,3 +403,12 @@ int lpfc_bsg_request(struct fc_bsg_job *); int lpfc_bsg_timeout(struct fc_bsg_job *); int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *); +void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *, + struct lpfc_iocbq *); +struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *, + struct lpfc_sli_ring *); +int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, + struct lpfc_iocbq *, uint32_t); +uint32_t lpfc_drain_txq(struct lpfc_hba *); + + diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6b1850c9fdff..f936f8c7efe1 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1472,8 +1472,12 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } goto out; } - /* PLOGI failed */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + /* PLOGI failed Don't print the vport to vport rjts */ + if (irsp->ulpStatus != IOSTAT_LS_RJT || + (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && + ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || + (phba)->pport->cfg_log_verbose & LOG_ELS) + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, "2753 PLOGI failure DID:%06X Status:x%x/x%x\n", ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4]); @@ -5144,6 +5148,7 @@ lpfc_els_timeout(unsigned long ptr) return; } + /** * lpfc_els_timeout_handler - Process an els timeout event * @vport: pointer to a virtual N_Port data structure. @@ -5164,13 +5169,19 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) uint32_t els_command = 0; uint32_t timeout; uint32_t remote_ID = 0xffffffff; + LIST_HEAD(txcmplq_completions); + LIST_HEAD(abort_list); + - spin_lock_irq(&phba->hbalock); timeout = (uint32_t)(phba->fc_ratov << 1); pring = &phba->sli.ring[LPFC_ELS_RING]; - list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { + spin_lock_irq(&phba->hbalock); + list_splice_init(&pring->txcmplq, &txcmplq_completions); + spin_unlock_irq(&phba->hbalock); + + list_for_each_entry_safe(piocb, tmp_iocb, &txcmplq_completions, list) { cmd = &piocb->iocb; if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || @@ -5207,13 +5218,22 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) if (ndlp && NLP_CHK_NODE_ACT(ndlp)) remote_ID = ndlp->nlp_DID; } + list_add_tail(&piocb->dlist, &abort_list); + } + spin_lock_irq(&phba->hbalock); + list_splice(&txcmplq_completions, &pring->txcmplq); + spin_unlock_irq(&phba->hbalock); + + list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "0127 ELS timeout Data: x%x x%x x%x " - "x%x\n", els_command, - remote_ID, cmd->ulpCommand, cmd->ulpIoTag); + "0127 ELS timeout Data: x%x x%x x%x " + "x%x\n", els_command, + remote_ID, cmd->ulpCommand, cmd->ulpIoTag); + spin_lock_irq(&phba->hbalock); + list_del_init(&piocb->dlist); lpfc_sli_issue_abort_iotag(phba, pring, piocb); + spin_unlock_irq(&phba->hbalock); } - spin_unlock_irq(&phba->hbalock); if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 8082d69ea730..d1c5c52b1c25 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -587,6 +587,8 @@ lpfc_work_done(struct lpfc_hba *phba) (status & HA_RXMASK)); } + if (phba->pport->work_port_events & WORKER_SERVICE_TXQ) + lpfc_drain_txq(phba); /* * Turn on Ring interrupts */ diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7dc55989b8ff..184e45f286d2 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8147,8 +8147,12 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) } /* Initialize and populate the iocb list per host */ - error = lpfc_init_iocb_list(phba, - phba->sli4_hba.max_cfg_param.max_xri); + + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "2821 initialize iocb list %d.\n", + phba->cfg_iocb_cnt*1024); + error = lpfc_init_iocb_list(phba, phba->cfg_iocb_cnt*1024); + if (error) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "1413 Failed to initialize iocb list.\n"); diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 9810b3d3cc53..bccc9c66fa37 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -190,6 +190,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } + /* * Free resources / clean up outstanding I/Os * associated with a LPFC_NODELIST entry. This @@ -199,13 +200,15 @@ int lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { LIST_HEAD(completions); + LIST_HEAD(txcmplq_completions); + LIST_HEAD(abort_list); struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; struct lpfc_iocbq *iocb, *next_iocb; /* Abort outstanding I/O on NPort */ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY, - "0205 Abort outstanding I/O on NPort x%x " + "2819 Abort outstanding I/O on NPort x%x " "Data: x%x x%x x%x\n", ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); @@ -224,14 +227,25 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) } /* Next check the txcmplq */ - list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { + list_splice_init(&pring->txcmplq, &txcmplq_completions); + spin_unlock_irq(&phba->hbalock); + + list_for_each_entry_safe(iocb, next_iocb, &txcmplq_completions, list) { /* Check to see if iocb matches the nport we are looking for */ - if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { - lpfc_sli_issue_abort_iotag(phba, pring, iocb); - } + if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) + list_add_tail(&iocb->dlist, &abort_list); } + spin_lock_irq(&phba->hbalock); + list_splice(&txcmplq_completions, &pring->txcmplq); spin_unlock_irq(&phba->hbalock); + list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) { + spin_lock_irq(&phba->hbalock); + list_del_init(&iocb->dlist); + lpfc_sli_issue_abort_iotag(phba, pring, iocb); + spin_unlock_irq(&phba->hbalock); + } + /* Cancel all the IOCBs from the completions list */ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f7a92653467a..c6bdf63925d9 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -3228,7 +3228,9 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, iocbqrsp->iocb.un.ulpWord[4]); - } else + } else if (status == IOCB_BUSY) + ret = FAILED; + else ret = SUCCESS; lpfc_sli_release_iocbq(phba, iocbqrsp); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 103a5aa4ae81..ae3cb0ab0ae4 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -455,6 +455,11 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba) struct lpfc_iocbq * iocbq = NULL; list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list); + + if (iocbq) + phba->iocb_cnt++; + if (phba->iocb_cnt > phba->iocb_max) + phba->iocb_max = phba->iocb_cnt; return iocbq; } @@ -575,7 +580,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { struct lpfc_sglq *sglq; size_t start_clean = offsetof(struct lpfc_iocbq, iocb); - unsigned long iflag; + unsigned long iflag = 0; + struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; if (iocbq->sli4_xritag == NO_XRI) sglq = NULL; @@ -593,6 +599,17 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) } else { sglq->state = SGL_FREED; list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); + + /* Check if TXQ queue needs to be serviced */ + if (pring->txq_cnt) { + spin_lock_irqsave( + &phba->pport->work_port_lock, iflag); + phba->pport->work_port_events |= + WORKER_SERVICE_TXQ; + lpfc_worker_wake_up(phba); + spin_unlock_irqrestore( + &phba->pport->work_port_lock, iflag); + } } } @@ -605,6 +622,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); } + /** * __lpfc_sli_release_iocbq_s3 - Release iocb to the iocb pool * @phba: Pointer to HBA context object. @@ -642,6 +660,7 @@ static void __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { phba->__lpfc_sli_release_iocbq(phba, iocbq); + phba->iocb_cnt--; } /** @@ -872,7 +891,11 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *piocb) { list_add_tail(&piocb->list, &pring->txcmplq); + piocb->iocb_flag |= LPFC_IO_ON_Q; pring->txcmplq_cnt++; + if (pring->txcmplq_cnt > pring->txcmplq_max) + pring->txcmplq_max = pring->txcmplq_cnt; + if ((unlikely(pring->ringno == LPFC_ELS_RING)) && (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { @@ -897,7 +920,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, * the txq, the function returns first iocb in the list after * removing the iocb from the list, else it returns NULL. **/ -static struct lpfc_iocbq * +struct lpfc_iocbq * lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { struct lpfc_iocbq *cmd_iocb; @@ -2150,7 +2173,10 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; list_del_init(&cmd_iocb->list); - pring->txcmplq_cnt--; + if (cmd_iocb->iocb_flag & LPFC_IO_ON_Q) { + pring->txcmplq_cnt--; + cmd_iocb->iocb_flag &= ~LPFC_IO_ON_Q; + } return cmd_iocb; } @@ -2183,7 +2209,10 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba, if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; list_del_init(&cmd_iocb->list); - pring->txcmplq_cnt--; + if (cmd_iocb->iocb_flag & LPFC_IO_ON_Q) { + cmd_iocb->iocb_flag &= ~LPFC_IO_ON_Q; + pring->txcmplq_cnt--; + } return cmd_iocb; } @@ -5578,7 +5607,7 @@ lpfc_mbox_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) * iocb to the txq when SLI layer cannot submit the command iocb * to the ring. **/ -static void +void __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *piocb) { @@ -6195,7 +6224,6 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { struct lpfc_sglq *sglq; - uint16_t xritag; union lpfc_wqe wqe; struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number]; @@ -6204,10 +6232,26 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) sglq = NULL; else { + if (pring->txq_cnt) { + if (!(flag & SLI_IOCB_RET_IOCB)) { + __lpfc_sli_ringtx_put(phba, + pring, piocb); + return IOCB_SUCCESS; + } else { + return IOCB_BUSY; + } + } else { sglq = __lpfc_sli_get_sglq(phba); - if (!sglq) - return IOCB_ERROR; - piocb->sli4_xritag = sglq->sli4_xritag; + if (!sglq) { + if (!(flag & SLI_IOCB_RET_IOCB)) { + __lpfc_sli_ringtx_put(phba, + pring, + piocb); + return IOCB_SUCCESS; + } else + return IOCB_BUSY; + } + } } } else if (piocb->iocb_flag & LPFC_IO_FCP) { sglq = NULL; /* These IO's already have an XRI and @@ -6223,8 +6267,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, } if (sglq) { - xritag = lpfc_sli4_bpl2sgl(phba, piocb, sglq); - if (xritag != sglq->sli4_xritag) + piocb->sli4_xritag = sglq->sli4_xritag; + + if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) return IOCB_ERROR; } @@ -6264,7 +6309,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, * IOCB_SUCCESS - Success * IOCB_BUSY - Busy **/ -static inline int +int __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { @@ -7081,13 +7126,6 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ abort_iocb = phba->sli.iocbq_lookup[abort_context]; - lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI, - "0327 Cannot abort els iocb %p " - "with tag %x context %x, abort status %x, " - "abort code %x\n", - abort_iocb, abort_iotag, abort_context, - irsp->ulpStatus, irsp->un.ulpWord[4]); - /* * If the iocb is not found in Firmware queue the iocb * might have completed already. Do not free it again. @@ -7106,6 +7144,13 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (abort_iocb && phba->sli_rev == LPFC_SLI_REV4) abort_context = abort_iocb->iocb.ulpContext; } + + lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_SLI, + "0327 Cannot abort els iocb %p " + "with tag %x context %x, abort status %x, " + "abort code %x\n", + abort_iocb, abort_iotag, abort_context, + irsp->ulpStatus, irsp->un.ulpWord[4]); /* * make sure we have the right iocbq before taking it * off the txcmplq and try to call completion routine. @@ -7123,7 +7168,10 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * following abort XRI from the HBA. */ list_del_init(&abort_iocb->list); - pring->txcmplq_cnt--; + if (abort_iocb->iocb_flag & LPFC_IO_ON_Q) { + abort_iocb->iocb_flag &= ~LPFC_IO_ON_Q; + pring->txcmplq_cnt--; + } /* Firmware could still be in progress of DMAing * payload, so don't free data buffer till after @@ -7255,8 +7303,9 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, "0339 Abort xri x%x, original iotag x%x, " "abort cmd iotag x%x\n", + iabt->un.acxri.abortIoTag, iabt->un.acxri.abortContextTag, - iabt->un.acxri.abortIoTag, abtsiocbp->iotag); + abtsiocbp->iotag); retval = __lpfc_sli_issue_iocb(phba, pring->ringno, abtsiocbp, 0); if (retval) @@ -7586,7 +7635,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, long timeleft, timeout_req = 0; int retval = IOCB_SUCCESS; uint32_t creg_val; - + struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; /* * If the caller has provided a response iocbq buffer, then context2 * is NULL or its an error. @@ -7608,7 +7657,8 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, readl(phba->HCregaddr); /* flush */ } - retval = lpfc_sli_issue_iocb(phba, ring_number, piocb, 0); + retval = lpfc_sli_issue_iocb(phba, ring_number, piocb, + SLI_IOCB_RET_IOCB); if (retval == IOCB_SUCCESS) { timeout_req = timeout * HZ; timeleft = wait_event_timeout(done_q, @@ -7630,6 +7680,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, timeout, (timeleft / jiffies)); retval = IOCB_TIMEDOUT; } + } else if (retval == IOCB_BUSY) { + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "2818 Max IOCBs %d txq cnt %d txcmplq cnt %d\n", + phba->iocb_cnt, pring->txq_cnt, pring->txcmplq_cnt); + return retval; } else { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "0332 IOCB wait issue failed, Data x%x\n", @@ -8775,12 +8830,17 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, { struct lpfc_iocbq *irspiocbq; unsigned long iflags; + struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_FCP_RING]; /* Get an irspiocbq for later ELS response processing use */ irspiocbq = lpfc_sli_get_iocbq(phba); if (!irspiocbq) { lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0387 Failed to allocate an iocbq\n"); + "0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d " + "fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n", + pring->txq_cnt, phba->iocb_cnt, + phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt, + phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt); return false; } @@ -12695,3 +12755,89 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) spin_unlock_irq(&phba->hbalock); } +/** + * lpfc_drain_txq - Drain the txq + * @phba: Pointer to HBA context object. + * + * This function attempt to submit IOCBs on the txq + * to the adapter. For SLI4 adapters, the txq contains + * ELS IOCBs that have been deferred because the there + * are no SGLs. This congestion can occur with large + * vport counts during node discovery. + **/ + +uint32_t +lpfc_drain_txq(struct lpfc_hba *phba) +{ + LIST_HEAD(completions); + struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; + struct lpfc_iocbq *piocbq = 0; + unsigned long iflags = 0; + char *fail_msg = NULL; + struct lpfc_sglq *sglq; + union lpfc_wqe wqe; + + spin_lock_irqsave(&phba->hbalock, iflags); + if (pring->txq_cnt > pring->txq_max) + pring->txq_max = pring->txq_cnt; + + spin_unlock_irqrestore(&phba->hbalock, iflags); + + while (pring->txq_cnt) { + spin_lock_irqsave(&phba->hbalock, iflags); + + sglq = __lpfc_sli_get_sglq(phba); + if (!sglq) { + spin_unlock_irqrestore(&phba->hbalock, iflags); + break; + } else { + piocbq = lpfc_sli_ringtx_get(phba, pring); + if (!piocbq) { + /* The txq_cnt out of sync. This should + * never happen + */ + sglq = __lpfc_clear_active_sglq(phba, + sglq->sli4_xritag); + spin_unlock_irqrestore(&phba->hbalock, iflags); + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2823 txq empty and txq_cnt is %d\n ", + pring->txq_cnt); + break; + } + } + + /* The xri and iocb resources secured, + * attempt to issue request + */ + piocbq->sli4_xritag = sglq->sli4_xritag; + if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) + fail_msg = "to convert bpl to sgl"; + else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe)) + fail_msg = "to convert iocb to wqe"; + else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) + fail_msg = " - Wq is full"; + else + lpfc_sli_ringtxcmpl_put(phba, pring, piocbq); + + if (fail_msg) { + /* Failed means we can't issue and need to cancel */ + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2822 IOCB failed %s iotag 0x%x " + "xri 0x%x\n", + fail_msg, + piocbq->iotag, piocbq->sli4_xritag); + list_add_tail(&piocbq->list, &completions); + } + spin_unlock_irqrestore(&phba->hbalock, iflags); + } + + spin_lock_irqsave(&phba->pport->work_port_lock, iflags); + phba->pport->work_port_events &= ~WORKER_SERVICE_TXQ; + spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags); + + /* Cancel all the IOCBs that cannot be issued */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); + + return pring->txq_cnt; +} diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index e3792151ca06..cd56d6cce6c3 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -48,6 +48,7 @@ struct lpfc_iocbq { /* lpfc_iocbqs are used in double linked lists */ struct list_head list; struct list_head clist; + struct list_head dlist; uint16_t iotag; /* pre-assigned IO tag */ uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ struct lpfc_cq_event cq_event; @@ -64,6 +65,7 @@ struct lpfc_iocbq { #define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */ #define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */ #define DSS_SECURITY_OP 0x100 /* security IO */ +#define LPFC_IO_ON_Q 0x200 /* The IO is still on the TXCMPLQ */ #define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */ #define LPFC_FIP_ELS_ID_SHIFT 14 -- cgit v1.2.3 From 18cacc34887df274feb3f1ff420d7592e4ea246f Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 7 Jun 2010 15:24:54 -0400 Subject: [SCSI] lpfc 8.3.13: Update Driver Version to 8.3.13 Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 5294c3a515a1..e79090df228a 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.12" +#define LPFC_DRIVER_VERSION "8.3.13" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" -- cgit v1.2.3 From c20c426732a5a5d21e99b36286f79c2024115341 Mon Sep 17 00:00:00 2001 From: Anil Ravindranath Date: Tue, 8 Jun 2010 10:56:34 -0700 Subject: [SCSI] pmcraid: MSI-X support and other changes 1. MSI-X interrupt support 2. Driver changes to support new maxRAID controller FW version. The changes are mainly done to handle async notification changes done in newer controller FW version. 3. Added state change notifications to notify applications of controller states. Signed-off-by: Anil Ravindranath Signed-off-by: James Bottomley --- drivers/scsi/pmcraid.c | 886 ++++++++++++++++++++++++++++++++++++------------- drivers/scsi/pmcraid.h | 305 ++++++++++------- 2 files changed, 843 insertions(+), 348 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index c44e4ab4e938..9ebcea3643b2 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -113,6 +113,7 @@ static struct pmcraid_chip_details pmcraid_chip_cfg[] = { .global_intr_mask = 0x00034, .ioa_host_intr = 0x0009C, .ioa_host_intr_clr = 0x000A0, + .ioa_host_msix_intr = 0x7FC40, .ioa_host_mask = 0x7FC28, .ioa_host_mask_clr = 0x7FC28, .host_ioa_intr = 0x00020, @@ -154,8 +155,12 @@ static int pmcraid_slave_alloc(struct scsi_device *scsi_dev) u8 target, bus, lun; unsigned long lock_flags; int rc = -ENXIO; + u16 fw_version; + pinstance = shost_priv(scsi_dev->host); + fw_version = be16_to_cpu(pinstance->inq_data->fw_version); + /* Driver exposes VSET and GSCSI resources only; all other device types * are not exposed. Resource list is synchronized using resource lock * so any traversal or modifications to the list should be done inside @@ -166,7 +171,11 @@ static int pmcraid_slave_alloc(struct scsi_device *scsi_dev) /* do not expose VSETs with order-ids > MAX_VSET_TARGETS */ if (RES_IS_VSET(temp->cfg_entry)) { - target = temp->cfg_entry.unique_flags1; + if (fw_version <= PMCRAID_FW_VERSION_1) + target = temp->cfg_entry.unique_flags1; + else + target = temp->cfg_entry.array_id & 0xFF; + if (target > PMCRAID_MAX_VSET_TARGETS) continue; bus = PMCRAID_VSET_BUS_ID; @@ -283,7 +292,7 @@ static void pmcraid_slave_destroy(struct scsi_device *scsi_dev) * @reason: calling context * * Return value - * actual depth set + * actual depth set */ static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth, int reason) @@ -305,7 +314,7 @@ static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth, * @tag: type of tags to use * * Return value: - * actual queue type set + * actual queue type set */ static int pmcraid_change_queue_type(struct scsi_device *scsi_dev, int tag) { @@ -357,6 +366,7 @@ void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index) * processed by IOA */ memset(&cmd->ioa_cb->ioarcb.cdb, 0, PMCRAID_MAX_CDB_LEN); + ioarcb->hrrq_id = 0; ioarcb->request_flags0 = 0; ioarcb->request_flags1 = 0; ioarcb->cmd_timeout = 0; @@ -368,13 +378,15 @@ void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index) ioarcb->add_cmd_param_offset = 0; cmd->ioa_cb->ioasa.ioasc = 0; cmd->ioa_cb->ioasa.residual_data_length = 0; - cmd->u.time_left = 0; + cmd->time_left = 0; } cmd->cmd_done = NULL; cmd->scsi_cmd = NULL; cmd->release = 0; cmd->completion_req = 0; + cmd->sense_buffer = 0; + cmd->sense_buffer_dma = 0; cmd->dma_handle = 0; init_timer(&cmd->timer); } @@ -449,7 +461,9 @@ void pmcraid_return_cmd(struct pmcraid_cmd *cmd) */ static u32 pmcraid_read_interrupts(struct pmcraid_instance *pinstance) { - return ioread32(pinstance->int_regs.ioa_host_interrupt_reg); + return (pinstance->interrupt_mode) ? + ioread32(pinstance->int_regs.ioa_host_msix_interrupt_reg) : + ioread32(pinstance->int_regs.ioa_host_interrupt_reg); } /** @@ -469,10 +483,15 @@ static void pmcraid_disable_interrupts( u32 gmask = ioread32(pinstance->int_regs.global_interrupt_mask_reg); u32 nmask = gmask | GLOBAL_INTERRUPT_MASK; - iowrite32(nmask, pinstance->int_regs.global_interrupt_mask_reg); iowrite32(intrs, pinstance->int_regs.ioa_host_interrupt_clr_reg); - iowrite32(intrs, pinstance->int_regs.ioa_host_interrupt_mask_reg); - ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); + iowrite32(nmask, pinstance->int_regs.global_interrupt_mask_reg); + ioread32(pinstance->int_regs.global_interrupt_mask_reg); + + if (!pinstance->interrupt_mode) { + iowrite32(intrs, + pinstance->int_regs.ioa_host_interrupt_mask_reg); + ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); + } } /** @@ -493,14 +512,51 @@ static void pmcraid_enable_interrupts( u32 nmask = gmask & (~GLOBAL_INTERRUPT_MASK); iowrite32(nmask, pinstance->int_regs.global_interrupt_mask_reg); - iowrite32(~intrs, pinstance->int_regs.ioa_host_interrupt_mask_reg); - ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); + + if (!pinstance->interrupt_mode) { + iowrite32(~intrs, + pinstance->int_regs.ioa_host_interrupt_mask_reg); + ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); + } pmcraid_info("enabled interrupts global mask = %x intr_mask = %x\n", ioread32(pinstance->int_regs.global_interrupt_mask_reg), ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg)); } +/** + * pmcraid_clr_trans_op - clear trans to op interrupt + * + * @pinstance: pointer to per adapter instance structure + * + * Return Value + * None + */ +static void pmcraid_clr_trans_op( + struct pmcraid_instance *pinstance +) +{ + unsigned long lock_flags; + + if (!pinstance->interrupt_mode) { + iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, + pinstance->int_regs.ioa_host_interrupt_mask_reg); + ioread32(pinstance->int_regs.ioa_host_interrupt_mask_reg); + iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, + pinstance->int_regs.ioa_host_interrupt_clr_reg); + ioread32(pinstance->int_regs.ioa_host_interrupt_clr_reg); + } + + if (pinstance->reset_cmd != NULL) { + del_timer(&pinstance->reset_cmd->timer); + spin_lock_irqsave( + pinstance->host->host_lock, lock_flags); + pinstance->reset_cmd->cmd_done(pinstance->reset_cmd); + spin_unlock_irqrestore( + pinstance->host->host_lock, lock_flags); + } +} + /** * pmcraid_reset_type - Determine the required reset type * @pinstance: pointer to adapter instance structure @@ -536,7 +592,7 @@ static void pmcraid_reset_type(struct pmcraid_instance *pinstance) * pmcraid_bist_done - completion function for PCI BIST * @cmd: pointer to reset command * Return Value - * none + * none */ static void pmcraid_ioa_reset(struct pmcraid_cmd *); @@ -552,16 +608,16 @@ static void pmcraid_bist_done(struct pmcraid_cmd *cmd) /* If PCI config space can't be accessed wait for another two secs */ if ((rc != PCIBIOS_SUCCESSFUL || (!(pci_reg & PCI_COMMAND_MEMORY))) && - cmd->u.time_left > 0) { + cmd->time_left > 0) { pmcraid_info("BIST not complete, waiting another 2 secs\n"); - cmd->timer.expires = jiffies + cmd->u.time_left; - cmd->u.time_left = 0; + cmd->timer.expires = jiffies + cmd->time_left; + cmd->time_left = 0; cmd->timer.data = (unsigned long)cmd; cmd->timer.function = (void (*)(unsigned long))pmcraid_bist_done; add_timer(&cmd->timer); } else { - cmd->u.time_left = 0; + cmd->time_left = 0; pmcraid_info("BIST is complete, proceeding with reset\n"); spin_lock_irqsave(pinstance->host->host_lock, lock_flags); pmcraid_ioa_reset(cmd); @@ -585,10 +641,10 @@ static void pmcraid_start_bist(struct pmcraid_cmd *cmd) pinstance->int_regs.host_ioa_interrupt_reg); doorbells = ioread32(pinstance->int_regs.host_ioa_interrupt_reg); intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); - pmcraid_info("doorbells after start bist: %x intrs: %x \n", + pmcraid_info("doorbells after start bist: %x intrs: %x\n", doorbells, intrs); - cmd->u.time_left = msecs_to_jiffies(PMCRAID_BIST_TIMEOUT); + cmd->time_left = msecs_to_jiffies(PMCRAID_BIST_TIMEOUT); cmd->timer.data = (unsigned long)cmd; cmd->timer.expires = jiffies + msecs_to_jiffies(PMCRAID_BIST_TIMEOUT); cmd->timer.function = (void (*)(unsigned long))pmcraid_bist_done; @@ -612,7 +668,7 @@ static void pmcraid_reset_alert_done(struct pmcraid_cmd *cmd) * some more time to wait, restart the timer */ if (((status & INTRS_CRITICAL_OP_IN_PROGRESS) == 0) || - cmd->u.time_left <= 0) { + cmd->time_left <= 0) { pmcraid_info("critical op is reset proceeding with reset\n"); spin_lock_irqsave(pinstance->host->host_lock, lock_flags); pmcraid_ioa_reset(cmd); @@ -620,7 +676,7 @@ static void pmcraid_reset_alert_done(struct pmcraid_cmd *cmd) } else { pmcraid_info("critical op is not yet reset waiting again\n"); /* restart timer if some more time is available to wait */ - cmd->u.time_left -= PMCRAID_CHECK_FOR_RESET_TIMEOUT; + cmd->time_left -= PMCRAID_CHECK_FOR_RESET_TIMEOUT; cmd->timer.data = (unsigned long)cmd; cmd->timer.expires = jiffies + PMCRAID_CHECK_FOR_RESET_TIMEOUT; cmd->timer.function = @@ -638,6 +694,7 @@ static void pmcraid_reset_alert_done(struct pmcraid_cmd *cmd) * successfully written to IOA. Returns non-zero in case pci_config_space * is not accessible */ +static void pmcraid_notify_ioastate(struct pmcraid_instance *, u32); static void pmcraid_reset_alert(struct pmcraid_cmd *cmd) { struct pmcraid_instance *pinstance = cmd->drv_inst; @@ -658,7 +715,7 @@ static void pmcraid_reset_alert(struct pmcraid_cmd *cmd) * OPERATION bit is reset. A timer is started to wait for this * bit to be reset. */ - cmd->u.time_left = PMCRAID_RESET_TIMEOUT; + cmd->time_left = PMCRAID_RESET_TIMEOUT; cmd->timer.data = (unsigned long)cmd; cmd->timer.expires = jiffies + PMCRAID_CHECK_FOR_RESET_TIMEOUT; cmd->timer.function = @@ -693,7 +750,8 @@ static void pmcraid_timeout_handler(struct pmcraid_cmd *cmd) unsigned long lock_flags; dev_info(&pinstance->pdev->dev, - "Adapter being reset due to command timeout.\n"); + "Adapter being reset due to cmd(CDB[0] = %x) timeout\n", + cmd->ioa_cb->ioarcb.cdb[0]); /* Command timeouts result in hard reset sequence. The command that got * timed out may be the one used as part of reset sequence. In this @@ -736,9 +794,14 @@ static void pmcraid_timeout_handler(struct pmcraid_cmd *cmd) */ if (cmd == pinstance->reset_cmd) cmd->cmd_done = pmcraid_ioa_reset; - } + /* Notify apps of important IOA bringup/bringdown sequences */ + if (pinstance->scn.ioa_state != PMC_DEVICE_EVENT_RESET_START && + pinstance->scn.ioa_state != PMC_DEVICE_EVENT_SHUTDOWN_START) + pmcraid_notify_ioastate(pinstance, + PMC_DEVICE_EVENT_RESET_START); + pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; scsi_block_requests(pinstance->host); pmcraid_reset_alert(cmd); @@ -866,7 +929,7 @@ static void _pmcraid_fire_command(struct pmcraid_cmd *cmd) /* Add this command block to pending cmd pool. We do this prior to * writting IOARCB to ioarrin because IOA might complete the command * by the time we are about to add it to the list. Response handler - * (isr/tasklet) looks for cmb block in the pending pending list. + * (isr/tasklet) looks for cmd block in the pending pending list. */ spin_lock_irqsave(&pinstance->pending_pool_lock, lock_flags); list_add_tail(&cmd->free_list, &pinstance->pending_cmd_pool); @@ -915,6 +978,23 @@ static void pmcraid_send_cmd( _pmcraid_fire_command(cmd); } +/** + * pmcraid_ioa_shutdown_done - completion function for IOA shutdown command + * @cmd: pointer to the command block used for sending IOA shutdown command + * + * Return value + * None + */ +static void pmcraid_ioa_shutdown_done(struct pmcraid_cmd *cmd) +{ + struct pmcraid_instance *pinstance = cmd->drv_inst; + unsigned long lock_flags; + + spin_lock_irqsave(pinstance->host->host_lock, lock_flags); + pmcraid_ioa_reset(cmd); + spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); +} + /** * pmcraid_ioa_shutdown - sends SHUTDOWN command to ioa * @@ -943,30 +1023,112 @@ static void pmcraid_ioa_shutdown(struct pmcraid_cmd *cmd) pmcraid_info("firing normal shutdown command (%d) to IOA\n", le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle)); - pmcraid_send_cmd(cmd, pmcraid_ioa_reset, + pmcraid_notify_ioastate(cmd->drv_inst, PMC_DEVICE_EVENT_SHUTDOWN_START); + + pmcraid_send_cmd(cmd, pmcraid_ioa_shutdown_done, PMCRAID_SHUTDOWN_TIMEOUT, pmcraid_timeout_handler); } /** - * pmcraid_identify_hrrq - registers host rrq buffers with IOA - * @cmd: pointer to command block to be used for identify hrrq + * pmcraid_get_fwversion_done - completion function for get_fwversion + * + * @cmd: pointer to command block used to send INQUIRY command * * Return Value - * 0 in case of success, otherwise non-zero failure code + * none */ - static void pmcraid_querycfg(struct pmcraid_cmd *); +static void pmcraid_get_fwversion_done(struct pmcraid_cmd *cmd) +{ + struct pmcraid_instance *pinstance = cmd->drv_inst; + u32 ioasc = le32_to_cpu(cmd->ioa_cb->ioasa.ioasc); + unsigned long lock_flags; + + /* configuration table entry size depends on firmware version. If fw + * version is not known, it is not possible to interpret IOA config + * table + */ + if (ioasc) { + pmcraid_err("IOA Inquiry failed with %x\n", ioasc); + spin_lock_irqsave(pinstance->host->host_lock, lock_flags); + pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; + pmcraid_reset_alert(cmd); + spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); + } else { + pmcraid_querycfg(cmd); + } +} + +/** + * pmcraid_get_fwversion - reads firmware version information + * + * @cmd: pointer to command block used to send INQUIRY command + * + * Return Value + * none + */ +static void pmcraid_get_fwversion(struct pmcraid_cmd *cmd) +{ + struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; + struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl; + struct pmcraid_instance *pinstance = cmd->drv_inst; + u16 data_size = sizeof(struct pmcraid_inquiry_data); + + pmcraid_reinit_cmdblk(cmd); + ioarcb->request_type = REQ_TYPE_SCSI; + ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); + ioarcb->cdb[0] = INQUIRY; + ioarcb->cdb[1] = 1; + ioarcb->cdb[2] = 0xD0; + ioarcb->cdb[3] = (data_size >> 8) & 0xFF; + ioarcb->cdb[4] = data_size & 0xFF; + + /* Since entire inquiry data it can be part of IOARCB itself + */ + ioarcb->ioadl_bus_addr = cpu_to_le64((cmd->ioa_cb_bus_addr) + + offsetof(struct pmcraid_ioarcb, + add_data.u.ioadl[0])); + ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc)); + ioarcb->ioarcb_bus_addr &= ~(0x1FULL); + + ioarcb->request_flags0 |= NO_LINK_DESCS; + ioarcb->data_transfer_length = cpu_to_le32(data_size); + ioadl = &(ioarcb->add_data.u.ioadl[0]); + ioadl->flags = IOADL_FLAGS_LAST_DESC; + ioadl->address = cpu_to_le64(pinstance->inq_data_baddr); + ioadl->data_len = cpu_to_le32(data_size); + + pmcraid_send_cmd(cmd, pmcraid_get_fwversion_done, + PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); +} + +/** + * pmcraid_identify_hrrq - registers host rrq buffers with IOA + * @cmd: pointer to command block to be used for identify hrrq + * + * Return Value + * none + */ static void pmcraid_identify_hrrq(struct pmcraid_cmd *cmd) { struct pmcraid_instance *pinstance = cmd->drv_inst; struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb; - int index = 0; + int index = cmd->hrrq_index; __be64 hrrq_addr = cpu_to_be64(pinstance->hrrq_start_bus_addr[index]); u32 hrrq_size = cpu_to_be32(sizeof(u32) * PMCRAID_MAX_CMD); + void (*done_function)(struct pmcraid_cmd *); pmcraid_reinit_cmdblk(cmd); + cmd->hrrq_index = index + 1; + + if (cmd->hrrq_index < pinstance->num_hrrq) { + done_function = pmcraid_identify_hrrq; + } else { + cmd->hrrq_index = 0; + done_function = pmcraid_get_fwversion; + } /* Initialize ioarcb */ ioarcb->request_type = REQ_TYPE_IOACMD; @@ -980,8 +1142,8 @@ static void pmcraid_identify_hrrq(struct pmcraid_cmd *cmd) /* IOA expects 64-bit pci address to be written in B.E format * (i.e cdb[2]=MSByte..cdb[9]=LSB. */ - pmcraid_info("HRRQ_IDENTIFY with hrrq:ioarcb => %llx:%llx\n", - hrrq_addr, ioarcb->ioarcb_bus_addr); + pmcraid_info("HRRQ_IDENTIFY with hrrq:ioarcb:index => %llx:%llx:%x\n", + hrrq_addr, ioarcb->ioarcb_bus_addr, index); memcpy(&(ioarcb->cdb[2]), &hrrq_addr, sizeof(hrrq_addr)); memcpy(&(ioarcb->cdb[10]), &hrrq_size, sizeof(hrrq_size)); @@ -990,7 +1152,7 @@ static void pmcraid_identify_hrrq(struct pmcraid_cmd *cmd) * Note that this gets called even during reset from SCSI mid-layer * or tasklet */ - pmcraid_send_cmd(cmd, pmcraid_querycfg, + pmcraid_send_cmd(cmd, done_function, PMCRAID_INTERNAL_TIMEOUT, pmcraid_timeout_handler); } @@ -1047,7 +1209,7 @@ static struct pmcraid_cmd *pmcraid_init_hcam } if (type == PMCRAID_HCAM_CODE_CONFIG_CHANGE) { - rcb_size = sizeof(struct pmcraid_hcam_ccn); + rcb_size = sizeof(struct pmcraid_hcam_ccn_ext); cmd_done = pmcraid_process_ccn; dma = pinstance->ccn.baddr + PMCRAID_AEN_HDR_SIZE; hcam = &pinstance->ccn; @@ -1094,7 +1256,7 @@ static struct pmcraid_cmd *pmcraid_init_hcam * This function will send a Host Controlled Async command to IOA. * * Return value: - * none + * none */ static void pmcraid_send_hcam(struct pmcraid_instance *pinstance, u8 type) { @@ -1202,18 +1364,25 @@ static void pmcraid_cancel_ldn(struct pmcraid_cmd *cmd) /** * pmcraid_expose_resource - check if the resource can be exposed to OS * + * @fw_version: firmware version code * @cfgte: pointer to configuration table entry of the resource * * Return value: - * true if resource can be added to midlayer, false(0) otherwise + * true if resource can be added to midlayer, false(0) otherwise */ -static int pmcraid_expose_resource(struct pmcraid_config_table_entry *cfgte) +static int pmcraid_expose_resource(u16 fw_version, + struct pmcraid_config_table_entry *cfgte) { int retval = 0; - if (cfgte->resource_type == RES_TYPE_VSET) - retval = ((cfgte->unique_flags1 & 0x80) == 0); - else if (cfgte->resource_type == RES_TYPE_GSCSI) + if (cfgte->resource_type == RES_TYPE_VSET) { + if (fw_version <= PMCRAID_FW_VERSION_1) + retval = ((cfgte->unique_flags1 & 0x80) == 0); + else + retval = ((cfgte->unique_flags0 & 0x80) == 0 && + (cfgte->unique_flags1 & 0x80) == 0); + + } else if (cfgte->resource_type == RES_TYPE_GSCSI) retval = (RES_BUS(cfgte->resource_address) != PMCRAID_VIRTUAL_ENCL_BUS_ID); return retval; @@ -1246,8 +1415,8 @@ static struct genl_family pmcraid_event_family = { * pmcraid_netlink_init - registers pmcraid_event_family * * Return value: - * 0 if the pmcraid_event_family is successfully registered - * with netlink generic, non-zero otherwise + * 0 if the pmcraid_event_family is successfully registered + * with netlink generic, non-zero otherwise */ static int pmcraid_netlink_init(void) { @@ -1268,7 +1437,7 @@ static int pmcraid_netlink_init(void) * pmcraid_netlink_release - unregisters pmcraid_event_family * * Return value: - * none + * none */ static void pmcraid_netlink_release(void) { @@ -1283,31 +1452,30 @@ static void pmcraid_netlink_release(void) * Return value: * 0 if success, error value in case of any failure. */ -static int pmcraid_notify_aen(struct pmcraid_instance *pinstance, u8 type) +static int pmcraid_notify_aen( + struct pmcraid_instance *pinstance, + struct pmcraid_aen_msg *aen_msg, + u32 data_size +) { struct sk_buff *skb; - struct pmcraid_aen_msg *aen_msg; void *msg_header; - int data_size, total_size; + u32 total_size, nla_genl_hdr_total_size; int result; - - if (type == PMCRAID_HCAM_CODE_LOG_DATA) { - aen_msg = pinstance->ldn.msg; - data_size = pinstance->ldn.hcam->data_len; - } else { - aen_msg = pinstance->ccn.msg; - data_size = pinstance->ccn.hcam->data_len; - } - - data_size += sizeof(struct pmcraid_hcam_hdr); aen_msg->hostno = (pinstance->host->unique_id << 16 | MINOR(pinstance->cdev.dev)); aen_msg->length = data_size; + data_size += sizeof(*aen_msg); total_size = nla_total_size(data_size); - skb = genlmsg_new(total_size, GFP_ATOMIC); + /* Add GENL_HDR to total_size */ + nla_genl_hdr_total_size = + (total_size + (GENL_HDRLEN + + ((struct genl_family *)&pmcraid_event_family)->hdrsize) + + NLMSG_HDRLEN); + skb = genlmsg_new(nla_genl_hdr_total_size, GFP_ATOMIC); if (!skb) { @@ -1329,7 +1497,7 @@ static int pmcraid_notify_aen(struct pmcraid_instance *pinstance, u8 type) result = nla_put(skb, PMCRAID_AEN_ATTR_EVENT, data_size, aen_msg); if (result) { - pmcraid_err("failed to copy AEN attribute data \n"); + pmcraid_err("failed to copy AEN attribute data\n"); nlmsg_free(skb); return -EINVAL; } @@ -1350,12 +1518,56 @@ static int pmcraid_notify_aen(struct pmcraid_instance *pinstance, u8 type) * value. */ if (result) - pmcraid_info("failed to send %s event message %x!\n", - type == PMCRAID_HCAM_CODE_LOG_DATA ? "LDN" : "CCN", - result); + pmcraid_info("error (%x) sending aen event message\n", result); return result; } +/** + * pmcraid_notify_ccn - notifies about CCN event msg to user space + * @pinstance: pointer adapter instance structure + * + * Return value: + * 0 if success, error value in case of any failure + */ +static int pmcraid_notify_ccn(struct pmcraid_instance *pinstance) +{ + return pmcraid_notify_aen(pinstance, + pinstance->ccn.msg, + pinstance->ccn.hcam->data_len + + sizeof(struct pmcraid_hcam_hdr)); +} + +/** + * pmcraid_notify_ldn - notifies about CCN event msg to user space + * @pinstance: pointer adapter instance structure + * + * Return value: + * 0 if success, error value in case of any failure + */ +static int pmcraid_notify_ldn(struct pmcraid_instance *pinstance) +{ + return pmcraid_notify_aen(pinstance, + pinstance->ldn.msg, + pinstance->ldn.hcam->data_len + + sizeof(struct pmcraid_hcam_hdr)); +} + +/** + * pmcraid_notify_ioastate - sends IOA state event msg to user space + * @pinstance: pointer adapter instance structure + * @evt: controller state event to be sent + * + * Return value: + * 0 if success, error value in case of any failure + */ +static void pmcraid_notify_ioastate(struct pmcraid_instance *pinstance, u32 evt) +{ + pinstance->scn.ioa_state = evt; + pmcraid_notify_aen(pinstance, + &pinstance->scn.msg, + sizeof(u32)); +} + /** * pmcraid_handle_config_change - Handle a config change from the adapter * @pinstance: pointer to per adapter instance structure @@ -1375,10 +1587,12 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) unsigned long host_lock_flags; u32 new_entry = 1; u32 hidden_entry = 0; + u16 fw_version; int rc; ccn_hcam = (struct pmcraid_hcam_ccn *)pinstance->ccn.hcam; cfg_entry = &ccn_hcam->cfg_entry; + fw_version = be16_to_cpu(pinstance->inq_data->fw_version); pmcraid_info ("CCN(%x): %x type: %x lost: %x flags: %x res: %x:%x:%x:%x\n", @@ -1391,7 +1605,10 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) RES_IS_VSET(*cfg_entry) ? PMCRAID_VSET_BUS_ID : (RES_IS_GSCSI(*cfg_entry) ? PMCRAID_PHYS_BUS_ID : RES_BUS(cfg_entry->resource_address)), - RES_IS_VSET(*cfg_entry) ? cfg_entry->unique_flags1 : + RES_IS_VSET(*cfg_entry) ? + (fw_version <= PMCRAID_FW_VERSION_1 ? + cfg_entry->unique_flags1 : + cfg_entry->array_id & 0xFF) : RES_TARGET(cfg_entry->resource_address), RES_LUN(cfg_entry->resource_address)); @@ -1415,11 +1632,16 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) */ if (pinstance->ccn.hcam->notification_type == NOTIFICATION_TYPE_ENTRY_CHANGED && - cfg_entry->resource_type == RES_TYPE_VSET && - cfg_entry->unique_flags1 & 0x80) { - hidden_entry = 1; - } else if (!pmcraid_expose_resource(cfg_entry)) + cfg_entry->resource_type == RES_TYPE_VSET) { + + if (fw_version <= PMCRAID_FW_VERSION_1) + hidden_entry = (cfg_entry->unique_flags1 & 0x80) != 0; + else + hidden_entry = (cfg_entry->unique_flags1 & 0x80) != 0; + + } else if (!pmcraid_expose_resource(fw_version, cfg_entry)) { goto out_notify_apps; + } spin_lock_irqsave(&pinstance->resource_lock, lock_flags); list_for_each_entry(res, &pinstance->used_res_q, queue) { @@ -1466,13 +1688,15 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance) list_add_tail(&res->queue, &pinstance->used_res_q); } - memcpy(&res->cfg_entry, cfg_entry, - sizeof(struct pmcraid_config_table_entry)); + memcpy(&res->cfg_entry, cfg_entry, pinstance->config_table_entry_size); if (pinstance->ccn.hcam->notification_type == NOTIFICATION_TYPE_ENTRY_DELETED || hidden_entry) { if (res->scsi_dev) { - res->cfg_entry.unique_flags1 &= 0x7F; + if (fw_version <= PMCRAID_FW_VERSION_1) + res->cfg_entry.unique_flags1 &= 0x7F; + else + res->cfg_entry.array_id &= 0xFF; res->change_detected = RES_CHANGE_DEL; res->cfg_entry.resource_handle = PMCRAID_INVALID_RES_HANDLE; @@ -1491,7 +1715,7 @@ out_notify_apps: /* Notify configuration changes to registered applications.*/ if (!pmcraid_disable_aen) - pmcraid_notify_aen(pinstance, PMCRAID_HCAM_CODE_CONFIG_CHANGE); + pmcraid_notify_ccn(pinstance); cmd = pmcraid_init_hcam(pinstance, PMCRAID_HCAM_CODE_CONFIG_CHANGE); if (cmd) @@ -1528,7 +1752,7 @@ void pmcraid_ioasc_logger(u32 ioasc, struct pmcraid_cmd *cmd) return; /* log the error string */ - pmcraid_err("cmd [%d] for resource %x failed with %x(%s)\n", + pmcraid_err("cmd [%x] for resource %x failed with %x(%s)\n", cmd->ioa_cb->ioarcb.cdb[0], cmd->ioa_cb->ioarcb.resource_handle, le32_to_cpu(ioasc), error_info->error_string); @@ -1663,7 +1887,7 @@ static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) } /* send netlink message for HCAM notification if enabled */ if (!pmcraid_disable_aen) - pmcraid_notify_aen(pinstance, PMCRAID_HCAM_CODE_LOG_DATA); + pmcraid_notify_ldn(pinstance); cmd = pmcraid_init_hcam(pinstance, PMCRAID_HCAM_CODE_LOG_DATA); if (cmd) @@ -1701,10 +1925,13 @@ static void pmcraid_unregister_hcams(struct pmcraid_cmd *cmd) atomic_set(&pinstance->ldn.ignore, 1); /* If adapter reset was forced as part of runtime reset sequence, - * start the reset sequence. + * start the reset sequence. Reset will be triggered even in case + * IOA unit_check. */ - if (pinstance->force_ioa_reset && !pinstance->ioa_bringdown) { + if ((pinstance->force_ioa_reset && !pinstance->ioa_bringdown) || + pinstance->ioa_unit_check) { pinstance->force_ioa_reset = 0; + pinstance->ioa_unit_check = 0; pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; pmcraid_reset_alert(cmd); return; @@ -1735,10 +1962,13 @@ static int pmcraid_reset_enable_ioa(struct pmcraid_instance *pinstance) pmcraid_enable_interrupts(pinstance, PMCRAID_PCI_INTERRUPTS); if (intrs & INTRS_TRANSITION_TO_OPERATIONAL) { - iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, - pinstance->int_regs.ioa_host_interrupt_mask_reg); - iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, - pinstance->int_regs.ioa_host_interrupt_clr_reg); + if (!pinstance->interrupt_mode) { + iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, + pinstance->int_regs. + ioa_host_interrupt_mask_reg); + iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, + pinstance->int_regs.ioa_host_interrupt_clr_reg); + } return 1; } else { return 0; @@ -1777,8 +2007,19 @@ static void pmcraid_soft_reset(struct pmcraid_cmd *cmd) doorbell = DOORBELL_RUNTIME_RESET | DOORBELL_ENABLE_DESTRUCTIVE_DIAGS; + /* Since we do RESET_ALERT and Start BIST we have to again write + * MSIX Doorbell to indicate the interrupt mode + */ + if (pinstance->interrupt_mode) { + iowrite32(DOORBELL_INTR_MODE_MSIX, + pinstance->int_regs.host_ioa_interrupt_reg); + ioread32(pinstance->int_regs.host_ioa_interrupt_reg); + } + iowrite32(doorbell, pinstance->int_regs.host_ioa_interrupt_reg); + ioread32(pinstance->int_regs.host_ioa_interrupt_reg), int_reg = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); + pmcraid_info("Waiting for IOA to become operational %x:%x\n", ioread32(pinstance->int_regs.host_ioa_interrupt_reg), int_reg); @@ -1854,7 +2095,8 @@ static void pmcraid_fail_outstanding_cmds(struct pmcraid_instance *pinstance) } else if (cmd->cmd_done == pmcraid_internal_done || cmd->cmd_done == pmcraid_erp_done) { cmd->cmd_done(cmd); - } else if (cmd->cmd_done != pmcraid_ioa_reset) { + } else if (cmd->cmd_done != pmcraid_ioa_reset && + cmd->cmd_done != pmcraid_ioa_shutdown_done) { pmcraid_return_cmd(cmd); } @@ -1964,6 +2206,13 @@ static void pmcraid_ioa_reset(struct pmcraid_cmd *cmd) pinstance->ioa_reset_attempts = 0; pmcraid_err("IOA didn't respond marking it as dead\n"); pinstance->ioa_state = IOA_STATE_DEAD; + + if (pinstance->ioa_bringdown) + pmcraid_notify_ioastate(pinstance, + PMC_DEVICE_EVENT_SHUTDOWN_FAILED); + else + pmcraid_notify_ioastate(pinstance, + PMC_DEVICE_EVENT_RESET_FAILED); reset_complete = 1; break; } @@ -1971,7 +2220,6 @@ static void pmcraid_ioa_reset(struct pmcraid_cmd *cmd) /* Once either bist or pci reset is done, restore PCI config * space. If this fails, proceed with hard reset again */ - if (pci_restore_state(pinstance->pdev)) { pmcraid_info("config-space error resetting again\n"); pinstance->ioa_state = IOA_STATE_IN_RESET_ALERT; @@ -2002,6 +2250,8 @@ static void pmcraid_ioa_reset(struct pmcraid_cmd *cmd) pinstance->ioa_shutdown_type = SHUTDOWN_NONE; pinstance->ioa_bringdown = 0; pinstance->ioa_state = IOA_STATE_UNKNOWN; + pmcraid_notify_ioastate(pinstance, + PMC_DEVICE_EVENT_SHUTDOWN_SUCCESS); reset_complete = 1; } else { /* bring-up IOA, so proceed with soft reset @@ -2051,6 +2301,8 @@ static void pmcraid_ioa_reset(struct pmcraid_cmd *cmd) */ if (pinstance->ioa_shutdown_type == SHUTDOWN_NONE && pinstance->force_ioa_reset == 0) { + pmcraid_notify_ioastate(pinstance, + PMC_DEVICE_EVENT_RESET_SUCCESS); reset_complete = 1; } else { if (pinstance->ioa_shutdown_type != SHUTDOWN_NONE) @@ -2116,6 +2368,8 @@ static void pmcraid_initiate_reset(struct pmcraid_instance *pinstance) pinstance->ioa_shutdown_type = SHUTDOWN_NONE; pinstance->reset_cmd = cmd; pinstance->force_ioa_reset = 1; + pmcraid_notify_ioastate(pinstance, + PMC_DEVICE_EVENT_RESET_START); pmcraid_ioa_reset(cmd); } } @@ -2191,7 +2445,7 @@ static int pmcraid_reset_reload( wait_event(pinstance->reset_wait_q, !pinstance->ioa_reset_in_progress); - pmcraid_info("reset_reload: reset is complete !! \n"); + pmcraid_info("reset_reload: reset is complete !!\n"); scsi_unblock_requests(pinstance->host); if (pinstance->ioa_state == target_state) reset = 0; @@ -2225,6 +2479,8 @@ static int pmcraid_reset_bringdown(struct pmcraid_instance *pinstance) */ static int pmcraid_reset_bringup(struct pmcraid_instance *pinstance) { + pmcraid_notify_ioastate(pinstance, PMC_DEVICE_EVENT_RESET_START); + return pmcraid_reset_reload(pinstance, SHUTDOWN_NONE, IOA_STATE_OPERATIONAL); @@ -2704,7 +2960,7 @@ static struct pmcraid_cmd *pmcraid_abort_cmd(struct pmcraid_cmd *cmd) pmcraid_info("command (%d) CDB[0] = %x for %x\n", le32_to_cpu(cancel_cmd->ioa_cb->ioarcb.response_handle) >> 2, - cmd->ioa_cb->ioarcb.cdb[0], + cancel_cmd->ioa_cb->ioarcb.cdb[0], le32_to_cpu(cancel_cmd->ioa_cb->ioarcb.resource_handle)); pmcraid_send_cmd(cancel_cmd, @@ -2729,8 +2985,8 @@ static int pmcraid_abort_complete(struct pmcraid_cmd *cancel_cmd) u32 ioasc; wait_for_completion(&cancel_cmd->wait_for_completion); - res = cancel_cmd->u.res; - cancel_cmd->u.res = NULL; + res = cancel_cmd->res; + cancel_cmd->res = NULL; ioasc = le32_to_cpu(cancel_cmd->ioa_cb->ioasa.ioasc); /* If the abort task is not timed out we will get a Good completion @@ -2823,7 +3079,7 @@ static int pmcraid_eh_abort_handler(struct scsi_cmnd *scsi_cmd) host_lock_flags); if (cancel_cmd) { - cancel_cmd->u.res = cmd->scsi_cmd->device->hostdata; + cancel_cmd->res = cmd->scsi_cmd->device->hostdata; rc = pmcraid_abort_complete(cancel_cmd); } @@ -2842,7 +3098,7 @@ static int pmcraid_eh_abort_handler(struct scsi_cmnd *scsi_cmd) * takes care by locking/unlocking host_lock. * * Return value - * SUCCESS or FAILED + * SUCCESS or FAILED */ static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd) { @@ -2879,7 +3135,7 @@ static int pmcraid_eh_target_reset_handler(struct scsi_cmnd *scmd) * Initiates adapter reset to bring it up to operational state * * Return value - * SUCCESS or FAILED + * SUCCESS or FAILED */ static int pmcraid_eh_host_reset_handler(struct scsi_cmnd *scmd) { @@ -2991,7 +3247,7 @@ pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount) * to firmware. This builds ioadl descriptors and sets up ioarcb fields. * * Return value: - * 0 on success or -1 on failure + * 0 on success or -1 on failure */ static int pmcraid_build_ioadl( struct pmcraid_instance *pinstance, @@ -3049,7 +3305,7 @@ static int pmcraid_build_ioadl( * Free a DMA'able memory previously allocated with pmcraid_alloc_sglist * * Return value: - * none + * none */ static void pmcraid_free_sglist(struct pmcraid_sglist *sglist) { @@ -3070,7 +3326,7 @@ static void pmcraid_free_sglist(struct pmcraid_sglist *sglist) * list. * * Return value - * pointer to sglist / NULL on failure + * pointer to sglist / NULL on failure */ static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen) { @@ -3224,11 +3480,12 @@ static int pmcraid_queuecommand( struct pmcraid_resource_entry *res; struct pmcraid_ioarcb *ioarcb; struct pmcraid_cmd *cmd; + u32 fw_version; int rc = 0; pinstance = (struct pmcraid_instance *)scsi_cmd->device->host->hostdata; - + fw_version = be16_to_cpu(pinstance->inq_data->fw_version); scsi_cmd->scsi_done = done; res = scsi_cmd->device->hostdata; scsi_cmd->result = (DID_OK << 16); @@ -3247,6 +3504,15 @@ static int pmcraid_queuecommand( if (pinstance->ioa_reset_in_progress) return SCSI_MLQUEUE_HOST_BUSY; + /* Firmware doesn't support SYNCHRONIZE_CACHE command (0x35), complete + * the command here itself with success return + */ + if (scsi_cmd->cmnd[0] == SYNCHRONIZE_CACHE) { + pmcraid_info("SYNC_CACHE(0x35), completing in driver itself\n"); + scsi_cmd->scsi_done(scsi_cmd); + return 0; + } + /* initialize the command and IOARCB to be sent to IOA */ cmd = pmcraid_get_free_cmd(pinstance); @@ -3261,6 +3527,13 @@ static int pmcraid_queuecommand( ioarcb->resource_handle = res->cfg_entry.resource_handle; ioarcb->request_type = REQ_TYPE_SCSI; + /* set hrrq number where the IOA should respond to. Note that all cmds + * generated internally uses hrrq_id 0, exception to this is the cmd + * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses + * hrrq_id assigned here in queuecommand + */ + ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) % + pinstance->num_hrrq; cmd->cmd_done = pmcraid_io_done; if (RES_IS_GSCSI(res->cfg_entry) || RES_IS_VSET(res->cfg_entry)) { @@ -3287,7 +3560,9 @@ static int pmcraid_queuecommand( RES_IS_VSET(res->cfg_entry) ? PMCRAID_VSET_BUS_ID : PMCRAID_PHYS_BUS_ID, RES_IS_VSET(res->cfg_entry) ? - res->cfg_entry.unique_flags1 : + (fw_version <= PMCRAID_FW_VERSION_1 ? + res->cfg_entry.unique_flags1 : + res->cfg_entry.array_id & 0xFF) : RES_TARGET(res->cfg_entry.resource_address), RES_LUN(res->cfg_entry.resource_address)); @@ -3465,6 +3740,7 @@ static long pmcraid_ioctl_passthrough( unsigned long request_buffer; unsigned long request_offset; unsigned long lock_flags; + u32 ioasc; int request_size; int buffer_size; u8 access, direction; @@ -3566,6 +3842,14 @@ static long pmcraid_ioctl_passthrough( buffer->ioarcb.add_cmd_param_length); } + /* set hrrq number where the IOA should respond to. Note that all cmds + * generated internally uses hrrq_id 0, exception to this is the cmd + * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses + * hrrq_id assigned here in queuecommand + */ + ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) % + pinstance->num_hrrq; + if (request_size) { rc = pmcraid_build_passthrough_ioadls(cmd, request_size, @@ -3606,6 +3890,14 @@ static long pmcraid_ioctl_passthrough( _pmcraid_fire_command(cmd); spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); + /* NOTE ! Remove the below line once abort_task is implemented + * in firmware. This line disables ioctl command timeout handling logic + * similar to IO command timeout handling, making ioctl commands to wait + * until the command completion regardless of timeout value specified in + * ioarcb + */ + buffer->ioarcb.cmd_timeout = 0; + /* If command timeout is specified put caller to wait till that time, * otherwise it would be blocking wait. If command gets timed out, it * will be aborted. @@ -3620,25 +3912,47 @@ static long pmcraid_ioctl_passthrough( le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle >> 2), cmd->ioa_cb->ioarcb.cdb[0]); - rc = -ETIMEDOUT; spin_lock_irqsave(pinstance->host->host_lock, lock_flags); cancel_cmd = pmcraid_abort_cmd(cmd); spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); if (cancel_cmd) { wait_for_completion(&cancel_cmd->wait_for_completion); + ioasc = cancel_cmd->ioa_cb->ioasa.ioasc; pmcraid_return_cmd(cancel_cmd); + + /* if abort task couldn't find the command i.e it got + * completed prior to aborting, return good completion. + * if command got aborted succesfully or there was IOA + * reset due to abort task itself getting timedout then + * return -ETIMEDOUT + */ + if (ioasc == PMCRAID_IOASC_IOA_WAS_RESET || + PMCRAID_IOASC_SENSE_KEY(ioasc) == 0x00) { + if (ioasc != PMCRAID_IOASC_GC_IOARCB_NOTFOUND) + rc = -ETIMEDOUT; + goto out_handle_response; + } } - goto out_free_sglist; + /* no command block for abort task or abort task failed to abort + * the IOARCB, then wait for 150 more seconds and initiate reset + * sequence after timeout + */ + if (!wait_for_completion_timeout( + &cmd->wait_for_completion, + msecs_to_jiffies(150 * 1000))) { + pmcraid_reset_bringup(cmd->drv_inst); + rc = -ETIMEDOUT; + } } +out_handle_response: /* If the command failed for any reason, copy entire IOASA buffer and * return IOCTL success. If copying IOASA to user-buffer fails, return * EFAULT */ - if (le32_to_cpu(cmd->ioa_cb->ioasa.ioasc)) { - + if (PMCRAID_IOASC_SENSE_KEY(le32_to_cpu(cmd->ioa_cb->ioasa.ioasc))) { void *ioasa = (void *)(arg + offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa)); @@ -3651,6 +3965,7 @@ static long pmcraid_ioctl_passthrough( rc = -EFAULT; } } + /* If the data transfer was from device, copy the data onto user * buffers */ @@ -3699,7 +4014,7 @@ static long pmcraid_ioctl_driver( int rc = -ENOSYS; if (!access_ok(VERIFY_READ, user_buffer, _IOC_SIZE(cmd))) { - pmcraid_err("ioctl_driver: access fault in request buffer \n"); + pmcraid_err("ioctl_driver: access fault in request buffer\n"); return -EFAULT; } @@ -4011,36 +4326,77 @@ static struct scsi_host_template pmcraid_host_template = { .proc_name = PMCRAID_DRIVER_NAME }; -/** - * pmcraid_isr_common - Common interrupt handler routine - * - * @pinstance: pointer to adapter instance - * @intrs: active interrupts (contents of ioa_host_interrupt register) - * @hrrq_id: Host RRQ index +/* + * pmcraid_isr_msix - implements MSI-X interrupt handling routine + * @irq: interrupt vector number + * @dev_id: pointer hrrq_vector * * Return Value - * none + * IRQ_HANDLED if interrupt is handled or IRQ_NONE if ignored */ -static void pmcraid_isr_common( - struct pmcraid_instance *pinstance, - u32 intrs, - int hrrq_id -) + +static irqreturn_t pmcraid_isr_msix(int irq, void *dev_id) { - u32 intrs_clear = - (intrs & INTRS_CRITICAL_OP_IN_PROGRESS) ? intrs - : INTRS_HRRQ_VALID; - iowrite32(intrs_clear, - pinstance->int_regs.ioa_host_interrupt_clr_reg); - intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); + struct pmcraid_isr_param *hrrq_vector; + struct pmcraid_instance *pinstance; + unsigned long lock_flags; + u32 intrs_val; + int hrrq_id; + + hrrq_vector = (struct pmcraid_isr_param *)dev_id; + hrrq_id = hrrq_vector->hrrq_id; + pinstance = hrrq_vector->drv_inst; + + if (!hrrq_id) { + /* Read the interrupt */ + intrs_val = pmcraid_read_interrupts(pinstance); + if (intrs_val && + ((ioread32(pinstance->int_regs.host_ioa_interrupt_reg) + & DOORBELL_INTR_MSIX_CLR) == 0)) { + /* Any error interrupts including unit_check, + * initiate IOA reset.In case of unit check indicate + * to reset_sequence that IOA unit checked and prepare + * for a dump during reset sequence + */ + if (intrs_val & PMCRAID_ERROR_INTERRUPTS) { + if (intrs_val & INTRS_IOA_UNIT_CHECK) + pinstance->ioa_unit_check = 1; + + pmcraid_err("ISR: error interrupts: %x \ + initiating reset\n", intrs_val); + spin_lock_irqsave(pinstance->host->host_lock, + lock_flags); + pmcraid_initiate_reset(pinstance); + spin_unlock_irqrestore( + pinstance->host->host_lock, + lock_flags); + } + /* If interrupt was as part of the ioa initialization, + * clear it. Delete the timer and wakeup the + * reset engine to proceed with reset sequence + */ + if (intrs_val & INTRS_TRANSITION_TO_OPERATIONAL) + pmcraid_clr_trans_op(pinstance); + + /* Clear the interrupt register by writing + * to host to ioa doorbell. Once done + * FW will clear the interrupt. + */ + iowrite32(DOORBELL_INTR_MSIX_CLR, + pinstance->int_regs.host_ioa_interrupt_reg); + ioread32(pinstance->int_regs.host_ioa_interrupt_reg); + - /* hrrq valid bit was set, schedule tasklet to handle the response */ - if (intrs_clear == INTRS_HRRQ_VALID) - tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id])); + } + } + + tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id])); + + return IRQ_HANDLED; } /** - * pmcraid_isr - implements interrupt handling routine + * pmcraid_isr - implements legacy interrupt handling routine * * @irq: interrupt vector number * @dev_id: pointer hrrq_vector @@ -4052,8 +4408,9 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) { struct pmcraid_isr_param *hrrq_vector; struct pmcraid_instance *pinstance; - unsigned long lock_flags; u32 intrs; + unsigned long lock_flags; + int hrrq_id = 0; /* In case of legacy interrupt mode where interrupts are shared across * isrs, it may be possible that the current interrupt is not from IOA @@ -4062,21 +4419,13 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) printk(KERN_INFO "%s(): NULL host pointer\n", __func__); return IRQ_NONE; } - hrrq_vector = (struct pmcraid_isr_param *)dev_id; pinstance = hrrq_vector->drv_inst; - /* Acquire the lock (currently host_lock) while processing interrupts. - * This interval is small as most of the response processing is done by - * tasklet without the lock. - */ - spin_lock_irqsave(pinstance->host->host_lock, lock_flags); intrs = pmcraid_read_interrupts(pinstance); - if (unlikely((intrs & PMCRAID_PCI_INTERRUPTS) == 0)) { - spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); + if (unlikely((intrs & PMCRAID_PCI_INTERRUPTS) == 0)) return IRQ_NONE; - } /* Any error interrupts including unit_check, initiate IOA reset. * In case of unit check indicate to reset_sequence that IOA unit @@ -4091,13 +4440,28 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id) pinstance->int_regs.ioa_host_interrupt_clr_reg); pmcraid_err("ISR: error interrupts: %x initiating reset\n", intrs); - intrs = ioread32(pinstance->int_regs.ioa_host_interrupt_reg); + intrs = ioread32( + pinstance->int_regs.ioa_host_interrupt_clr_reg); + spin_lock_irqsave(pinstance->host->host_lock, lock_flags); pmcraid_initiate_reset(pinstance); + spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); } else { - pmcraid_isr_common(pinstance, intrs, hrrq_vector->hrrq_id); - } + /* If interrupt was as part of the ioa initialization, + * clear. Delete the timer and wakeup the + * reset engine to proceed with reset sequence + */ + if (intrs & INTRS_TRANSITION_TO_OPERATIONAL) { + pmcraid_clr_trans_op(pinstance); + } else { + iowrite32(intrs, + pinstance->int_regs.ioa_host_interrupt_clr_reg); + ioread32( + pinstance->int_regs.ioa_host_interrupt_clr_reg); - spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags); + tasklet_schedule( + &(pinstance->isr_tasklet[hrrq_id])); + } + } return IRQ_HANDLED; } @@ -4120,6 +4484,7 @@ static void pmcraid_worker_function(struct work_struct *workp) struct scsi_device *sdev; unsigned long lock_flags; unsigned long host_lock_flags; + u16 fw_version; u8 bus, target, lun; pinstance = container_of(workp, struct pmcraid_instance, worker_q); @@ -4127,6 +4492,8 @@ static void pmcraid_worker_function(struct work_struct *workp) if (!atomic_read(&pinstance->expose_resources)) return; + fw_version = be16_to_cpu(pinstance->inq_data->fw_version); + spin_lock_irqsave(&pinstance->resource_lock, lock_flags); list_for_each_entry_safe(res, temp, &pinstance->used_res_q, queue) { @@ -4166,12 +4533,16 @@ static void pmcraid_worker_function(struct work_struct *workp) if (res->change_detected == RES_CHANGE_ADD) { - if (!pmcraid_expose_resource(&res->cfg_entry)) + if (!pmcraid_expose_resource(fw_version, + &res->cfg_entry)) continue; if (RES_IS_VSET(res->cfg_entry)) { bus = PMCRAID_VSET_BUS_ID; - target = res->cfg_entry.unique_flags1; + if (fw_version <= PMCRAID_FW_VERSION_1) + target = res->cfg_entry.unique_flags1; + else + target = res->cfg_entry.array_id & 0xFF; lun = PMCRAID_VSET_LUN_ID; } else { bus = PMCRAID_PHYS_BUS_ID; @@ -4201,7 +4572,7 @@ static void pmcraid_worker_function(struct work_struct *workp) * Return Value * None */ -void pmcraid_tasklet_function(unsigned long instance) +static void pmcraid_tasklet_function(unsigned long instance) { struct pmcraid_isr_param *hrrq_vector; struct pmcraid_instance *pinstance; @@ -4210,35 +4581,12 @@ void pmcraid_tasklet_function(unsigned long instance) unsigned long host_lock_flags; spinlock_t *lockp; /* hrrq buffer lock */ int id; - u32 intrs; __le32 resp; hrrq_vector = (struct pmcraid_isr_param *)instance; pinstance = hrrq_vector->drv_inst; id = hrrq_vector->hrrq_id; lockp = &(pinstance->hrrq_lock[id]); - intrs = pmcraid_read_interrupts(pinstance); - - /* If interrupts was as part of the ioa initialization, clear and mask - * it. Delete the timer and wakeup the reset engine to proceed with - * reset sequence - */ - if (intrs & INTRS_TRANSITION_TO_OPERATIONAL) { - iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, - pinstance->int_regs.ioa_host_interrupt_mask_reg); - iowrite32(INTRS_TRANSITION_TO_OPERATIONAL, - pinstance->int_regs.ioa_host_interrupt_clr_reg); - - if (pinstance->reset_cmd != NULL) { - del_timer(&pinstance->reset_cmd->timer); - spin_lock_irqsave(pinstance->host->host_lock, - host_lock_flags); - pinstance->reset_cmd->cmd_done(pinstance->reset_cmd); - spin_unlock_irqrestore(pinstance->host->host_lock, - host_lock_flags); - } - return; - } /* loop through each of the commands responded by IOA. Each HRRQ buf is * protected by its own lock. Traversals must be done within this lock @@ -4256,27 +4604,6 @@ void pmcraid_tasklet_function(unsigned long instance) int cmd_index = resp >> 2; struct pmcraid_cmd *cmd = NULL; - if (cmd_index < PMCRAID_MAX_CMD) { - cmd = pinstance->cmd_list[cmd_index]; - } else { - /* In case of invalid response handle, initiate IOA - * reset sequence. - */ - spin_unlock_irqrestore(lockp, hrrq_lock_flags); - - pmcraid_err("Invalid response %d initiating reset\n", - cmd_index); - - spin_lock_irqsave(pinstance->host->host_lock, - host_lock_flags); - pmcraid_initiate_reset(pinstance); - spin_unlock_irqrestore(pinstance->host->host_lock, - host_lock_flags); - - spin_lock_irqsave(lockp, hrrq_lock_flags); - break; - } - if (pinstance->hrrq_curr[id] < pinstance->hrrq_end[id]) { pinstance->hrrq_curr[id]++; } else { @@ -4284,6 +4611,14 @@ void pmcraid_tasklet_function(unsigned long instance) pinstance->host_toggle_bit[id] ^= 1u; } + if (cmd_index >= PMCRAID_MAX_CMD) { + /* In case of invalid response handle, log message */ + pmcraid_err("Invalid response handle %d\n", cmd_index); + resp = le32_to_cpu(*(pinstance->hrrq_curr[id])); + continue; + } + + cmd = pinstance->cmd_list[cmd_index]; spin_unlock_irqrestore(lockp, hrrq_lock_flags); spin_lock_irqsave(&pinstance->pending_pool_lock, @@ -4324,7 +4659,16 @@ void pmcraid_tasklet_function(unsigned long instance) static void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) { - free_irq(pinstance->pdev->irq, &(pinstance->hrrq_vector[0])); + int i; + + for (i = 0; i < pinstance->num_hrrq; i++) + free_irq(pinstance->hrrq_vector[i].vector, + &(pinstance->hrrq_vector[i])); + + if (pinstance->interrupt_mode) { + pci_disable_msix(pinstance->pdev); + pinstance->interrupt_mode = 0; + } } /** @@ -4337,14 +4681,70 @@ void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) static int pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance) { + int rc; struct pci_dev *pdev = pinstance->pdev; + if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { + int num_hrrq = PMCRAID_NUM_MSIX_VECTORS; + struct msix_entry entries[PMCRAID_NUM_MSIX_VECTORS]; + int i; + for (i = 0; i < PMCRAID_NUM_MSIX_VECTORS; i++) + entries[i].entry = i; + + rc = pci_enable_msix(pdev, entries, num_hrrq); + if (rc < 0) + goto pmcraid_isr_legacy; + + /* Check how many MSIX vectors are allocated and register + * msi-x handlers for each of them giving appropriate buffer + */ + if (rc > 0) { + num_hrrq = rc; + if (pci_enable_msix(pdev, entries, num_hrrq)) + goto pmcraid_isr_legacy; + } + + for (i = 0; i < num_hrrq; i++) { + pinstance->hrrq_vector[i].hrrq_id = i; + pinstance->hrrq_vector[i].drv_inst = pinstance; + pinstance->hrrq_vector[i].vector = entries[i].vector; + rc = request_irq(pinstance->hrrq_vector[i].vector, + pmcraid_isr_msix, 0, + PMCRAID_DRIVER_NAME, + &(pinstance->hrrq_vector[i])); + + if (rc) { + int j; + for (j = 0; j < i; j++) + free_irq(entries[j].vector, + &(pinstance->hrrq_vector[j])); + pci_disable_msix(pdev); + goto pmcraid_isr_legacy; + } + } + + pinstance->num_hrrq = num_hrrq; + pinstance->interrupt_mode = 1; + iowrite32(DOORBELL_INTR_MODE_MSIX, + pinstance->int_regs.host_ioa_interrupt_reg); + ioread32(pinstance->int_regs.host_ioa_interrupt_reg); + goto pmcraid_isr_out; + } + +pmcraid_isr_legacy: + /* If MSI-X registration failed fallback to legacy mode, where + * only one hrrq entry will be used + */ pinstance->hrrq_vector[0].hrrq_id = 0; pinstance->hrrq_vector[0].drv_inst = pinstance; - pinstance->hrrq_vector[0].vector = 0; + pinstance->hrrq_vector[0].vector = pdev->irq; pinstance->num_hrrq = 1; - return request_irq(pdev->irq, pmcraid_isr, IRQF_SHARED, - PMCRAID_DRIVER_NAME, &pinstance->hrrq_vector[0]); + rc = 0; + + rc = request_irq(pdev->irq, pmcraid_isr, IRQF_SHARED, + PMCRAID_DRIVER_NAME, &pinstance->hrrq_vector[0]); +pmcraid_isr_out: + return rc; } /** @@ -4516,12 +4916,11 @@ pmcraid_release_host_rrqs(struct pmcraid_instance *pinstance, int maxindex) static int __devinit pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) { - int i; - int buf_count = PMCRAID_MAX_CMD / pinstance->num_hrrq; + int i, buffer_size; - for (i = 0; i < pinstance->num_hrrq; i++) { - int buffer_size = HRRQ_ENTRY_SIZE * buf_count; + buffer_size = HRRQ_ENTRY_SIZE * PMCRAID_MAX_CMD; + for (i = 0; i < pinstance->num_hrrq; i++) { pinstance->hrrq_start[i] = pci_alloc_consistent( pinstance->pdev, @@ -4529,7 +4928,8 @@ pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) &(pinstance->hrrq_start_bus_addr[i])); if (pinstance->hrrq_start[i] == 0) { - pmcraid_err("could not allocate host rrq: %d\n", i); + pmcraid_err("pci_alloc failed for hrrq vector : %d\n", + i); pmcraid_release_host_rrqs(pinstance, i); return -ENOMEM; } @@ -4537,7 +4937,7 @@ pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance) memset(pinstance->hrrq_start[i], 0, buffer_size); pinstance->hrrq_curr[i] = pinstance->hrrq_start[i]; pinstance->hrrq_end[i] = - pinstance->hrrq_start[i] + buf_count - 1; + pinstance->hrrq_start[i] + PMCRAID_MAX_CMD - 1; pinstance->host_toggle_bit[i] = 1; spin_lock_init(&pinstance->hrrq_lock[i]); } @@ -4557,7 +4957,7 @@ static void pmcraid_release_hcams(struct pmcraid_instance *pinstance) if (pinstance->ccn.msg != NULL) { pci_free_consistent(pinstance->pdev, PMCRAID_AEN_HDR_SIZE + - sizeof(struct pmcraid_hcam_ccn), + sizeof(struct pmcraid_hcam_ccn_ext), pinstance->ccn.msg, pinstance->ccn.baddr); @@ -4591,7 +4991,7 @@ static int pmcraid_allocate_hcams(struct pmcraid_instance *pinstance) pinstance->ccn.msg = pci_alloc_consistent( pinstance->pdev, PMCRAID_AEN_HDR_SIZE + - sizeof(struct pmcraid_hcam_ccn), + sizeof(struct pmcraid_hcam_ccn_ext), &(pinstance->ccn.baddr)); pinstance->ldn.msg = pci_alloc_consistent( @@ -4723,6 +5123,32 @@ static void pmcraid_kill_tasklets(struct pmcraid_instance *pinstance) tasklet_kill(&pinstance->isr_tasklet[i]); } +/** + * pmcraid_release_buffers - release per-adapter buffers allocated + * + * @pinstance: pointer to adapter soft state + * + * Return Value + * none + */ +static void pmcraid_release_buffers(struct pmcraid_instance *pinstance) +{ + pmcraid_release_config_buffers(pinstance); + pmcraid_release_control_blocks(pinstance, PMCRAID_MAX_CMD); + pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); + pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); + + if (pinstance->inq_data != NULL) { + pci_free_consistent(pinstance->pdev, + sizeof(struct pmcraid_inquiry_data), + pinstance->inq_data, + pinstance->inq_data_baddr); + + pinstance->inq_data = NULL; + pinstance->inq_data_baddr = 0; + } +} + /** * pmcraid_init_buffers - allocates memory and initializes various structures * @pinstance: pointer to per adapter instance structure @@ -4753,20 +5179,32 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) } if (pmcraid_allocate_cmd_blocks(pinstance)) { - pmcraid_err("couldn't allocate memory for cmd blocks \n"); + pmcraid_err("couldn't allocate memory for cmd blocks\n"); pmcraid_release_config_buffers(pinstance); pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); return -ENOMEM; } if (pmcraid_allocate_control_blocks(pinstance)) { - pmcraid_err("couldn't allocate memory control blocks \n"); + pmcraid_err("couldn't allocate memory control blocks\n"); pmcraid_release_config_buffers(pinstance); pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); return -ENOMEM; } + /* allocate DMAable memory for page D0 INQUIRY buffer */ + pinstance->inq_data = pci_alloc_consistent( + pinstance->pdev, + sizeof(struct pmcraid_inquiry_data), + &pinstance->inq_data_baddr); + + if (pinstance->inq_data == NULL) { + pmcraid_err("couldn't allocate DMA memory for INQUIRY\n"); + pmcraid_release_buffers(pinstance); + return -ENOMEM; + } + /* Initialize all the command blocks and add them to free pool. No * need to lock (free_pool_lock) as this is done in initialization * itself @@ -4785,7 +5223,7 @@ static int __devinit pmcraid_init_buffers(struct pmcraid_instance *pinstance) * pmcraid_reinit_buffers - resets various buffer pointers * @pinstance: pointer to adapter instance * Return value - * none + * none */ static void pmcraid_reinit_buffers(struct pmcraid_instance *pinstance) { @@ -4836,6 +5274,8 @@ static int __devinit pmcraid_init_instance( mapped_pci_addr + chip_cfg->ioa_host_intr; pint_regs->ioa_host_interrupt_clr_reg = mapped_pci_addr + chip_cfg->ioa_host_intr_clr; + pint_regs->ioa_host_msix_interrupt_reg = + mapped_pci_addr + chip_cfg->ioa_host_msix_intr; pint_regs->host_ioa_interrupt_reg = mapped_pci_addr + chip_cfg->host_ioa_intr; pint_regs->host_ioa_interrupt_clr_reg = @@ -4858,6 +5298,7 @@ static int __devinit pmcraid_init_instance( init_waitqueue_head(&pinstance->reset_wait_q); atomic_set(&pinstance->outstanding_cmds, 0); + atomic_set(&pinstance->last_message_id, 0); atomic_set(&pinstance->expose_resources, 0); INIT_LIST_HEAD(&pinstance->free_res_q); @@ -4882,23 +5323,6 @@ static int __devinit pmcraid_init_instance( return 0; } -/** - * pmcraid_release_buffers - release per-adapter buffers allocated - * - * @pinstance: pointer to adapter soft state - * - * Return Value - * none - */ -static void pmcraid_release_buffers(struct pmcraid_instance *pinstance) -{ - pmcraid_release_config_buffers(pinstance); - pmcraid_release_control_blocks(pinstance, PMCRAID_MAX_CMD); - pmcraid_release_cmd_blocks(pinstance, PMCRAID_MAX_CMD); - pmcraid_release_host_rrqs(pinstance, pinstance->num_hrrq); - -} - /** * pmcraid_shutdown - shutdown adapter controller. * @pdev: pci device struct @@ -4958,7 +5382,7 @@ static int pmcraid_setup_chrdev(struct pmcraid_instance *pinstance) pmcraid_release_minor(minor); else device_create(pmcraid_class, NULL, MKDEV(pmcraid_major, minor), - NULL, "pmcsas%u", minor); + NULL, "%s%u", PMCRAID_DEVFILE, minor); return error; } @@ -5050,7 +5474,6 @@ static int pmcraid_resume(struct pci_dev *pdev) struct pmcraid_instance *pinstance = pci_get_drvdata(pdev); struct Scsi_Host *host = pinstance->host; int rc; - int hrrqs; pci_set_power_state(pdev, PCI_D0); pci_enable_wake(pdev, PCI_D0, 0); @@ -5077,8 +5500,8 @@ static int pmcraid_resume(struct pci_dev *pdev) goto disable_device; } + pmcraid_disable_interrupts(pinstance, ~0); atomic_set(&pinstance->outstanding_cmds, 0); - hrrqs = pinstance->num_hrrq; rc = pmcraid_register_interrupt_handler(pinstance); if (rc) { @@ -5100,7 +5523,7 @@ static int pmcraid_resume(struct pci_dev *pdev) * state. */ if (pmcraid_reset_bringup(pinstance)) { - dev_err(&pdev->dev, "couldn't initialize IOA \n"); + dev_err(&pdev->dev, "couldn't initialize IOA\n"); rc = -ENODEV; goto release_tasklets; } @@ -5108,6 +5531,7 @@ static int pmcraid_resume(struct pci_dev *pdev) return 0; release_tasklets: + pmcraid_disable_interrupts(pinstance, ~0); pmcraid_kill_tasklets(pinstance); pmcraid_unregister_interrupt_handler(pinstance); @@ -5129,7 +5553,7 @@ disable_device: /** * pmcraid_complete_ioa_reset - Called by either timer or tasklet during - * completion of the ioa reset + * completion of the ioa reset * @cmd: pointer to reset command block */ static void pmcraid_complete_ioa_reset(struct pmcraid_cmd *cmd) @@ -5204,11 +5628,14 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) struct pmcraid_config_table_entry *cfgte; unsigned long lock_flags; int found, rc, i; + u16 fw_version; LIST_HEAD(old_res); if (pinstance->cfg_table->flags & MICROCODE_UPDATE_REQUIRED) pmcraid_err("IOA requires microcode download\n"); + fw_version = be16_to_cpu(pinstance->inq_data->fw_version); + /* resource list is protected by pinstance->resource_lock. * init_res_table can be called from probe (user-thread) or runtime * reset (timer/tasklet) @@ -5219,9 +5646,14 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) list_move_tail(&res->queue, &old_res); for (i = 0; i < pinstance->cfg_table->num_entries; i++) { - cfgte = &pinstance->cfg_table->entries[i]; + if (be16_to_cpu(pinstance->inq_data->fw_version) <= + PMCRAID_FW_VERSION_1) + cfgte = &pinstance->cfg_table->entries[i]; + else + cfgte = (struct pmcraid_config_table_entry *) + &pinstance->cfg_table->entries_ext[i]; - if (!pmcraid_expose_resource(cfgte)) + if (!pmcraid_expose_resource(fw_version, cfgte)) continue; found = 0; @@ -5263,10 +5695,12 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) */ if (found) { memcpy(&res->cfg_entry, cfgte, - sizeof(struct pmcraid_config_table_entry)); + pinstance->config_table_entry_size); pmcraid_info("New res type:%x, vset:%x, addr:%x:\n", res->cfg_entry.resource_type, - res->cfg_entry.unique_flags1, + (fw_version <= PMCRAID_FW_VERSION_1 ? + res->cfg_entry.unique_flags1 : + res->cfg_entry.array_id & 0xFF), le32_to_cpu(res->cfg_entry.resource_address)); } } @@ -5306,6 +5740,14 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd) struct pmcraid_instance *pinstance = cmd->drv_inst; int cfg_table_size = cpu_to_be32(sizeof(struct pmcraid_config_table)); + if (be16_to_cpu(pinstance->inq_data->fw_version) <= + PMCRAID_FW_VERSION_1) + pinstance->config_table_entry_size = + sizeof(struct pmcraid_config_table_entry); + else + pinstance->config_table_entry_size = + sizeof(struct pmcraid_config_table_entry_ext); + ioarcb->request_type = REQ_TYPE_IOACMD; ioarcb->resource_handle = cpu_to_le32(PMCRAID_IOA_RES_HANDLE); @@ -5338,7 +5780,7 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd) /** - * pmcraid_probe - PCI probe entry pointer for PMC MaxRaid controller driver + * pmcraid_probe - PCI probe entry pointer for PMC MaxRAID controller driver * @pdev: pointer to pci device structure * @dev_id: pointer to device ids structure * @@ -5485,7 +5927,7 @@ static int __devinit pmcraid_probe( */ pmcraid_info("starting IOA initialization sequence\n"); if (pmcraid_reset_bringup(pinstance)) { - dev_err(&pdev->dev, "couldn't initialize IOA \n"); + dev_err(&pdev->dev, "couldn't initialize IOA\n"); rc = 1; goto out_release_bufs; } diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index b8ad07c3449e..6cfa0145a1d7 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -40,10 +40,12 @@ * Driver version: version string in major_version.minor_version.patch format * Driver date : date information in "Mon dd yyyy" format */ -#define PMCRAID_DRIVER_NAME "PMC MaxRAID" +#define PMCRAID_DRIVER_NAME "PMC MaxRAID" #define PMCRAID_DEVFILE "pmcsas" -#define PMCRAID_DRIVER_VERSION "1.0.2" -#define PMCRAID_DRIVER_DATE __DATE__ +#define PMCRAID_DRIVER_VERSION "2.0.2" +#define PMCRAID_DRIVER_DATE __DATE__ + +#define PMCRAID_FW_VERSION_1 0x002 /* Maximum number of adapters supported by current version of the driver */ #define PMCRAID_MAX_ADAPTERS 1024 @@ -85,17 +87,17 @@ #define PMCRAID_IOARCB_ALIGNMENT 32 #define PMCRAID_IOADL_ALIGNMENT 16 #define PMCRAID_IOASA_ALIGNMENT 4 -#define PMCRAID_NUM_MSIX_VECTORS 1 +#define PMCRAID_NUM_MSIX_VECTORS 16 /* various other limits */ -#define PMCRAID_VENDOR_ID_LEN 8 -#define PMCRAID_PRODUCT_ID_LEN 16 -#define PMCRAID_SERIAL_NUM_LEN 8 -#define PMCRAID_LUN_LEN 8 -#define PMCRAID_MAX_CDB_LEN 16 -#define PMCRAID_DEVICE_ID_LEN 8 -#define PMCRAID_SENSE_DATA_LEN 256 -#define PMCRAID_ADD_CMD_PARAM_LEN 48 +#define PMCRAID_VENDOR_ID_LEN 8 +#define PMCRAID_PRODUCT_ID_LEN 16 +#define PMCRAID_SERIAL_NUM_LEN 8 +#define PMCRAID_LUN_LEN 8 +#define PMCRAID_MAX_CDB_LEN 16 +#define PMCRAID_DEVICE_ID_LEN 8 +#define PMCRAID_SENSE_DATA_LEN 256 +#define PMCRAID_ADD_CMD_PARAM_LEN 48 #define PMCRAID_MAX_BUS_TO_SCAN 1 #define PMCRAID_MAX_NUM_TARGETS_PER_BUS 256 @@ -116,17 +118,10 @@ #define PMCRAID_VSET_MAX_SECTORS 512 #define PMCRAID_MAX_CMD_PER_LUN 254 -/* Number of configuration table entries (resources) */ -#define PMCRAID_MAX_NUM_OF_VSETS 240 - -/* Todo : Check max limit for Phase 1 */ -#define PMCRAID_MAX_NUM_OF_PHY_DEVS 256 - -/* MAX_NUM_OF_DEVS includes 1 FP, 1 Dummy Enclosure device */ -#define PMCRAID_MAX_NUM_OF_DEVS \ - (PMCRAID_MAX_NUM_OF_VSETS + PMCRAID_MAX_NUM_OF_PHY_DEVS + 2) - -#define PMCRAID_MAX_RESOURCES PMCRAID_MAX_NUM_OF_DEVS +/* Number of configuration table entries (resources), includes 1 FP, + * 1 Enclosure device + */ +#define PMCRAID_MAX_RESOURCES 256 /* Adapter Commands used by driver */ #define PMCRAID_QUERY_RESOURCE_STATE 0xC2 @@ -177,6 +172,7 @@ #define PMCRAID_IOASC_SENSE_STATUS(ioasc) ((ioasc) & 0x000000ff) #define PMCRAID_IOASC_GOOD_COMPLETION 0x00000000 +#define PMCRAID_IOASC_GC_IOARCB_NOTFOUND 0x005A0000 #define PMCRAID_IOASC_NR_INIT_CMD_REQUIRED 0x02040200 #define PMCRAID_IOASC_NR_IOA_RESET_REQUIRED 0x02048000 #define PMCRAID_IOASC_NR_SYNC_REQUIRED 0x023F0000 @@ -187,12 +183,12 @@ #define PMCRAID_IOASC_HW_IOA_RESET_REQUIRED 0x04448600 #define PMCRAID_IOASC_IR_INVALID_RESOURCE_HANDLE 0x05250000 #define PMCRAID_IOASC_AC_TERMINATED_BY_HOST 0x0B5A0000 -#define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000 -#define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000 +#define PMCRAID_IOASC_UA_BUS_WAS_RESET 0x06290000 +#define PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER 0x06298000 /* Driver defined IOASCs */ -#define PMCRAID_IOASC_IOA_WAS_RESET 0x10000001 -#define PMCRAID_IOASC_PCI_ACCESS_ERROR 0x10000002 +#define PMCRAID_IOASC_IOA_WAS_RESET 0x10000001 +#define PMCRAID_IOASC_PCI_ACCESS_ERROR 0x10000002 /* Various timeout values (in milliseconds) used. If any of these are chip * specific, move them to pmcraid_chip_details structure. @@ -336,6 +332,13 @@ struct pmcraid_config_table_entry { __u8 lun[PMCRAID_LUN_LEN]; } __attribute__((packed, aligned(4))); +/* extended configuration table sizes are of 64 bytes in size */ +#define PMCRAID_CFGTE_EXT_SIZE 32 +struct pmcraid_config_table_entry_ext { + struct pmcraid_config_table_entry cfgte; + __u8 cfgte_ext[PMCRAID_CFGTE_EXT_SIZE]; +}; + /* resource types (config_table_entry.resource_type values) */ #define RES_TYPE_AF_DASD 0x00 #define RES_TYPE_GSCSI 0x01 @@ -376,7 +379,12 @@ struct pmcraid_config_table { __u8 reserved1; __u8 flags; __u8 reserved2[11]; - struct pmcraid_config_table_entry entries[PMCRAID_MAX_RESOURCES]; + union { + struct pmcraid_config_table_entry + entries[PMCRAID_MAX_RESOURCES]; + struct pmcraid_config_table_entry_ext + entries_ext[PMCRAID_MAX_RESOURCES]; + }; } __attribute__((packed, aligned(4))); /* config_table.flags value */ @@ -385,7 +393,7 @@ struct pmcraid_config_table { /* * HCAM format */ -#define PMCRAID_HOSTRCB_LDNSIZE 4056 +#define PMCRAID_HOSTRCB_LDNSIZE 4056 /* Error log notification format */ struct pmcraid_hostrcb_error { @@ -416,6 +424,15 @@ struct pmcraid_hcam_hdr { struct pmcraid_hcam_ccn { struct pmcraid_hcam_hdr header; struct pmcraid_config_table_entry cfg_entry; + struct pmcraid_config_table_entry cfg_entry_old; +} __attribute__((packed, aligned(4))); + +#define PMCRAID_CCN_EXT_SIZE 3944 +struct pmcraid_hcam_ccn_ext { + struct pmcraid_hcam_hdr header; + struct pmcraid_config_table_entry_ext cfg_entry; + struct pmcraid_config_table_entry_ext cfg_entry_old; + __u8 reserved[PMCRAID_CCN_EXT_SIZE]; } __attribute__((packed, aligned(4))); struct pmcraid_hcam_ldn { @@ -431,6 +448,8 @@ struct pmcraid_hcam_ldn { #define NOTIFICATION_TYPE_ENTRY_CHANGED 0x0 #define NOTIFICATION_TYPE_ENTRY_NEW 0x1 #define NOTIFICATION_TYPE_ENTRY_DELETED 0x2 +#define NOTIFICATION_TYPE_STATE_CHANGE 0x3 +#define NOTIFICATION_TYPE_ENTRY_STATECHANGED 0x4 #define NOTIFICATION_TYPE_ERROR_LOG 0x10 #define NOTIFICATION_TYPE_INFORMATION_LOG 0x11 @@ -460,6 +479,7 @@ struct pmcraid_chip_details { unsigned long mailbox; unsigned long global_intr_mask; unsigned long ioa_host_intr; + unsigned long ioa_host_msix_intr; unsigned long ioa_host_intr_clr; unsigned long ioa_host_mask; unsigned long ioa_host_mask_clr; @@ -482,6 +502,7 @@ struct pmcraid_chip_details { #define INTRS_IOA_PROCESSOR_ERROR PMC_BIT32(29) #define INTRS_HRRQ_VALID PMC_BIT32(30) #define INTRS_OPERATIONAL_STATUS PMC_BIT32(0) +#define INTRS_ALLOW_MSIX_VECTOR0 PMC_BIT32(31) /* Host to IOA Doorbells */ #define DOORBELL_RUNTIME_RESET PMC_BIT32(1) @@ -489,10 +510,12 @@ struct pmcraid_chip_details { #define DOORBELL_IOA_DEBUG_ALERT PMC_BIT32(9) #define DOORBELL_ENABLE_DESTRUCTIVE_DIAGS PMC_BIT32(8) #define DOORBELL_IOA_START_BIST PMC_BIT32(23) +#define DOORBELL_INTR_MODE_MSIX PMC_BIT32(25) +#define DOORBELL_INTR_MSIX_CLR PMC_BIT32(26) #define DOORBELL_RESET_IOA PMC_BIT32(31) /* Global interrupt mask register value */ -#define GLOBAL_INTERRUPT_MASK 0x4ULL +#define GLOBAL_INTERRUPT_MASK 0x5ULL #define PMCRAID_ERROR_INTERRUPTS (INTRS_IOARCB_TRANSFER_FAILED | \ INTRS_IOA_UNIT_CHECK | \ @@ -503,8 +526,8 @@ struct pmcraid_chip_details { #define PMCRAID_PCI_INTERRUPTS (PMCRAID_ERROR_INTERRUPTS | \ INTRS_HRRQ_VALID | \ - INTRS_CRITICAL_OP_IN_PROGRESS |\ - INTRS_TRANSITION_TO_OPERATIONAL) + INTRS_TRANSITION_TO_OPERATIONAL |\ + INTRS_ALLOW_MSIX_VECTOR0) /* control_block, associated with each of the commands contains IOARCB, IOADLs * memory for IOASA. Additional 3 * 16 bytes are allocated in order to support @@ -526,17 +549,24 @@ struct pmcraid_sglist { struct scatterlist scatterlist[1]; }; +/* page D0 inquiry data of focal point resource */ +struct pmcraid_inquiry_data { + __u8 ph_dev_type; + __u8 page_code; + __u8 reserved1; + __u8 add_page_len; + __u8 length; + __u8 reserved2; + __le16 fw_version; + __u8 reserved3[16]; +}; + /* pmcraid_cmd - LLD representation of SCSI command */ struct pmcraid_cmd { /* Ptr and bus address of DMA.able control block for this command */ struct pmcraid_control_block *ioa_cb; dma_addr_t ioa_cb_bus_addr; - - /* sense buffer for REQUEST SENSE command if firmware is not sending - * auto sense data - */ - dma_addr_t sense_buffer_dma; dma_addr_t dma_handle; u8 *sense_buffer; @@ -556,11 +586,22 @@ struct pmcraid_cmd { struct pmcraid_sglist *sglist; /* used for passthrough IOCTLs */ - /* scratch used during reset sequence */ + /* scratch used */ union { + /* during reset sequence */ unsigned long time_left; struct pmcraid_resource_entry *res; - } u; + int hrrq_index; + + /* used during IO command error handling. Sense buffer + * for REQUEST SENSE command if firmware is not sending + * auto sense data + */ + struct { + u8 *sense_buffer; + dma_addr_t sense_buffer_dma; + }; + }; }; /* @@ -568,6 +609,7 @@ struct pmcraid_cmd { */ struct pmcraid_interrupts { void __iomem *ioa_host_interrupt_reg; + void __iomem *ioa_host_msix_interrupt_reg; void __iomem *ioa_host_interrupt_clr_reg; void __iomem *ioa_host_interrupt_mask_reg; void __iomem *ioa_host_interrupt_mask_clr_reg; @@ -578,11 +620,12 @@ struct pmcraid_interrupts { /* ISR parameters LLD allocates (one for each MSI-X if enabled) vectors */ struct pmcraid_isr_param { - u8 hrrq_id; /* hrrq entry index */ - u16 vector; /* allocated msi-x vector */ struct pmcraid_instance *drv_inst; + u16 vector; /* allocated msi-x vector */ + u8 hrrq_id; /* hrrq entry index */ }; + /* AEN message header sent as part of event data to applications */ struct pmcraid_aen_msg { u32 hostno; @@ -591,6 +634,19 @@ struct pmcraid_aen_msg { u8 data[0]; }; +/* Controller state event message type */ +struct pmcraid_state_msg { + struct pmcraid_aen_msg msg; + u32 ioa_state; +}; + +#define PMC_DEVICE_EVENT_RESET_START 0x11000000 +#define PMC_DEVICE_EVENT_RESET_SUCCESS 0x11000001 +#define PMC_DEVICE_EVENT_RESET_FAILED 0x11000002 +#define PMC_DEVICE_EVENT_SHUTDOWN_START 0x11000003 +#define PMC_DEVICE_EVENT_SHUTDOWN_SUCCESS 0x11000004 +#define PMC_DEVICE_EVENT_SHUTDOWN_FAILED 0x11000005 + struct pmcraid_hostrcb { struct pmcraid_instance *drv_inst; struct pmcraid_aen_msg *msg; @@ -628,6 +684,7 @@ struct pmcraid_instance { /* HostRCBs needed for HCAM */ struct pmcraid_hostrcb ldn; struct pmcraid_hostrcb ccn; + struct pmcraid_state_msg scn; /* controller state change msg */ /* Bus address of start of HRRQ */ @@ -645,12 +702,15 @@ struct pmcraid_instance { /* Lock for HRRQ access */ spinlock_t hrrq_lock[PMCRAID_NUM_MSIX_VECTORS]; + struct pmcraid_inquiry_data *inq_data; + dma_addr_t inq_data_baddr; + + /* size of configuration table entry, varies based on the firmware */ + u32 config_table_entry_size; + /* Expected toggle bit at host */ u8 host_toggle_bit[PMCRAID_NUM_MSIX_VECTORS]; - /* No of Reset IOA retries . IOA marked dead if threshold exceeds */ - u8 ioa_reset_attempts; -#define PMCRAID_RESET_ATTEMPTS 3 /* Wait Q for threads to wait for Reset IOA completion */ wait_queue_head_t reset_wait_q; @@ -664,14 +724,22 @@ struct pmcraid_instance { struct Scsi_Host *host; /* mid layer interface structure handle */ struct pci_dev *pdev; /* PCI device structure handle */ + /* No of Reset IOA retries . IOA marked dead if threshold exceeds */ + u8 ioa_reset_attempts; +#define PMCRAID_RESET_ATTEMPTS 3 + u8 current_log_level; /* default level for logging IOASC errors */ u8 num_hrrq; /* Number of interrupt vectors allocated */ + u8 interrupt_mode; /* current interrupt mode legacy or msix */ dev_t dev; /* Major-Minor numbers for Char device */ /* Used as ISR handler argument */ struct pmcraid_isr_param hrrq_vector[PMCRAID_NUM_MSIX_VECTORS]; + /* Message id as filled in last fired IOARCB, used to identify HRRQ */ + atomic_t last_message_id; + /* configuration table */ struct pmcraid_config_table *cfg_table; dma_addr_t cfg_table_bus_addr; @@ -686,8 +754,14 @@ struct pmcraid_instance { struct list_head free_cmd_pool; struct list_head pending_cmd_pool; - spinlock_t free_pool_lock; /* free pool lock */ - spinlock_t pending_pool_lock; /* pending pool lock */ + spinlock_t free_pool_lock; /* free pool lock */ + spinlock_t pending_pool_lock; /* pending pool lock */ + + /* Tasklet to handle deferred processing */ + struct tasklet_struct isr_tasklet[PMCRAID_NUM_MSIX_VECTORS]; + + /* Work-queue (Shared) for deferred reset processing */ + struct work_struct worker_q; /* No of IO commands pending with FW */ atomic_t outstanding_cmds; @@ -695,11 +769,6 @@ struct pmcraid_instance { /* should add/delete resources to mid-layer now ?*/ atomic_t expose_resources; - /* Tasklet to handle deferred processing */ - struct tasklet_struct isr_tasklet[PMCRAID_NUM_MSIX_VECTORS]; - - /* Work-queue (Shared) for deferred reset processing */ - struct work_struct worker_q; u32 ioa_state:4; /* For IOA Reset sequence FSM */ @@ -728,7 +797,10 @@ struct pmcraid_instance { /* LLD maintained resource entry structure */ struct pmcraid_resource_entry { struct list_head queue; /* link to "to be exposed" resources */ - struct pmcraid_config_table_entry cfg_entry; + union { + struct pmcraid_config_table_entry cfg_entry; + struct pmcraid_config_table_entry_ext cfg_entry_ext; + }; struct scsi_device *scsi_dev; /* Link scsi_device structure */ atomic_t read_failures; /* count of failed READ commands */ atomic_t write_failures; /* count of failed WRITE commands */ @@ -771,73 +843,75 @@ struct pmcraid_ioasc_error { * statically. */ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { - {0x01180600, IOASC_LOG_LEVEL_MUST, + {0x01180600, IOASC_LOG_LEVEL_HARD, "Recovered Error, soft media error, sector reassignment suggested"}, - {0x015D0000, IOASC_LOG_LEVEL_MUST, - "Recovered Error, failure prediction threshold exceeded"}, - {0x015D9200, IOASC_LOG_LEVEL_MUST, - "Recovered Error, soft Cache Card Battery error threshold"}, - {0x015D9200, IOASC_LOG_LEVEL_MUST, - "Recovered Error, soft Cache Card Battery error threshold"}, - {0x02048000, IOASC_LOG_LEVEL_MUST, + {0x015D0000, IOASC_LOG_LEVEL_HARD, + "Recovered Error, failure prediction thresold exceeded"}, + {0x015D9200, IOASC_LOG_LEVEL_HARD, + "Recovered Error, soft Cache Card Battery error thresold"}, + {0x015D9200, IOASC_LOG_LEVEL_HARD, + "Recovered Error, soft Cache Card Battery error thresold"}, + {0x02048000, IOASC_LOG_LEVEL_HARD, "Not Ready, IOA Reset Required"}, - {0x02408500, IOASC_LOG_LEVEL_MUST, + {0x02408500, IOASC_LOG_LEVEL_HARD, "Not Ready, IOA microcode download required"}, - {0x03110B00, IOASC_LOG_LEVEL_MUST, + {0x03110B00, IOASC_LOG_LEVEL_HARD, "Medium Error, data unreadable, reassignment suggested"}, {0x03110C00, IOASC_LOG_LEVEL_MUST, "Medium Error, data unreadable do not reassign"}, - {0x03310000, IOASC_LOG_LEVEL_MUST, + {0x03310000, IOASC_LOG_LEVEL_HARD, "Medium Error, media corrupted"}, - {0x04050000, IOASC_LOG_LEVEL_MUST, + {0x04050000, IOASC_LOG_LEVEL_HARD, "Hardware Error, IOA can't communicate with device"}, {0x04080000, IOASC_LOG_LEVEL_MUST, "Hardware Error, device bus error"}, - {0x04080000, IOASC_LOG_LEVEL_MUST, + {0x04088000, IOASC_LOG_LEVEL_MUST, "Hardware Error, device bus is not functioning"}, - {0x04118000, IOASC_LOG_LEVEL_MUST, + {0x04118000, IOASC_LOG_LEVEL_HARD, "Hardware Error, IOA reserved area data check"}, - {0x04118100, IOASC_LOG_LEVEL_MUST, + {0x04118100, IOASC_LOG_LEVEL_HARD, "Hardware Error, IOA reserved area invalid data pattern"}, - {0x04118200, IOASC_LOG_LEVEL_MUST, + {0x04118200, IOASC_LOG_LEVEL_HARD, "Hardware Error, IOA reserved area LRC error"}, - {0x04320000, IOASC_LOG_LEVEL_MUST, + {0x04320000, IOASC_LOG_LEVEL_HARD, "Hardware Error, reassignment space exhausted"}, - {0x04330000, IOASC_LOG_LEVEL_MUST, + {0x04330000, IOASC_LOG_LEVEL_HARD, "Hardware Error, data transfer underlength error"}, - {0x04330000, IOASC_LOG_LEVEL_MUST, + {0x04330000, IOASC_LOG_LEVEL_HARD, "Hardware Error, data transfer overlength error"}, {0x04418000, IOASC_LOG_LEVEL_MUST, "Hardware Error, PCI bus error"}, - {0x04440000, IOASC_LOG_LEVEL_MUST, + {0x04440000, IOASC_LOG_LEVEL_HARD, "Hardware Error, device error"}, - {0x04448300, IOASC_LOG_LEVEL_MUST, + {0x04448200, IOASC_LOG_LEVEL_MUST, + "Hardware Error, IOA error"}, + {0x04448300, IOASC_LOG_LEVEL_HARD, "Hardware Error, undefined device response"}, - {0x04448400, IOASC_LOG_LEVEL_MUST, + {0x04448400, IOASC_LOG_LEVEL_HARD, "Hardware Error, IOA microcode error"}, - {0x04448600, IOASC_LOG_LEVEL_MUST, + {0x04448600, IOASC_LOG_LEVEL_HARD, "Hardware Error, IOA reset required"}, - {0x04449200, IOASC_LOG_LEVEL_MUST, + {0x04449200, IOASC_LOG_LEVEL_HARD, "Hardware Error, hard Cache Fearuee Card Battery error"}, - {0x0444A000, IOASC_LOG_LEVEL_MUST, + {0x0444A000, IOASC_LOG_LEVEL_HARD, "Hardware Error, failed device altered"}, - {0x0444A200, IOASC_LOG_LEVEL_MUST, + {0x0444A200, IOASC_LOG_LEVEL_HARD, "Hardware Error, data check after reassignment"}, - {0x0444A300, IOASC_LOG_LEVEL_MUST, + {0x0444A300, IOASC_LOG_LEVEL_HARD, "Hardware Error, LRC error after reassignment"}, - {0x044A0000, IOASC_LOG_LEVEL_MUST, + {0x044A0000, IOASC_LOG_LEVEL_HARD, "Hardware Error, device bus error (msg/cmd phase)"}, - {0x04670400, IOASC_LOG_LEVEL_MUST, + {0x04670400, IOASC_LOG_LEVEL_HARD, "Hardware Error, new device can't be used"}, - {0x04678000, IOASC_LOG_LEVEL_MUST, + {0x04678000, IOASC_LOG_LEVEL_HARD, "Hardware Error, invalid multiadapter configuration"}, - {0x04678100, IOASC_LOG_LEVEL_MUST, + {0x04678100, IOASC_LOG_LEVEL_HARD, "Hardware Error, incorrect connection between enclosures"}, - {0x04678200, IOASC_LOG_LEVEL_MUST, + {0x04678200, IOASC_LOG_LEVEL_HARD, "Hardware Error, connections exceed IOA design limits"}, - {0x04678300, IOASC_LOG_LEVEL_MUST, + {0x04678300, IOASC_LOG_LEVEL_HARD, "Hardware Error, incorrect multipath connection"}, - {0x04679000, IOASC_LOG_LEVEL_MUST, + {0x04679000, IOASC_LOG_LEVEL_HARD, "Hardware Error, command to LUN failed"}, {0x064C8000, IOASC_LOG_LEVEL_HARD, "Unit Attention, cache exists for missing/failed device"}, @@ -845,15 +919,15 @@ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { "Unit Attention, incompatible exposed mode device"}, {0x06670600, IOASC_LOG_LEVEL_HARD, "Unit Attention, attachment of logical unit failed"}, - {0x06678000, IOASC_LOG_LEVEL_MUST, + {0x06678000, IOASC_LOG_LEVEL_HARD, "Unit Attention, cables exceed connective design limit"}, - {0x06678300, IOASC_LOG_LEVEL_MUST, + {0x06678300, IOASC_LOG_LEVEL_HARD, "Unit Attention, incomplete multipath connection between" \ "IOA and enclosure"}, - {0x06678400, IOASC_LOG_LEVEL_MUST, + {0x06678400, IOASC_LOG_LEVEL_HARD, "Unit Attention, incomplete multipath connection between" \ "device and enclosure"}, - {0x06678500, IOASC_LOG_LEVEL_MUST, + {0x06678500, IOASC_LOG_LEVEL_HARD, "Unit Attention, incomplete multipath connection between" \ "IOA and remote IOA"}, {0x06678600, IOASC_LOG_LEVEL_HARD, @@ -863,11 +937,11 @@ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { "function"}, {0x06698200, IOASC_LOG_LEVEL_HARD, "Unit Attention, corrupt array parity detected on device"}, - {0x066B0200, IOASC_LOG_LEVEL_MUST, + {0x066B0200, IOASC_LOG_LEVEL_HARD, "Unit Attention, array exposed"}, {0x066B8200, IOASC_LOG_LEVEL_HARD, "Unit Attention, exposed array is still protected"}, - {0x066B9200, IOASC_LOG_LEVEL_MUST, + {0x066B9200, IOASC_LOG_LEVEL_HARD, "Unit Attention, Multipath redundancy level got worse"}, {0x07270000, IOASC_LOG_LEVEL_HARD, "Data Protect, device is read/write protected by IOA"}, @@ -875,37 +949,37 @@ static struct pmcraid_ioasc_error pmcraid_ioasc_error_table[] = { "Data Protect, IOA doesn't support device attribute"}, {0x07278100, IOASC_LOG_LEVEL_HARD, "Data Protect, NVRAM mirroring prohibited"}, - {0x07278400, IOASC_LOG_LEVEL_MUST, + {0x07278400, IOASC_LOG_LEVEL_HARD, "Data Protect, array is short 2 or more devices"}, - {0x07278600, IOASC_LOG_LEVEL_MUST, + {0x07278600, IOASC_LOG_LEVEL_HARD, "Data Protect, exposed array is short a required device"}, - {0x07278700, IOASC_LOG_LEVEL_MUST, + {0x07278700, IOASC_LOG_LEVEL_HARD, "Data Protect, array members not at required addresses"}, - {0x07278800, IOASC_LOG_LEVEL_MUST, + {0x07278800, IOASC_LOG_LEVEL_HARD, "Data Protect, exposed mode device resource address conflict"}, - {0x07278900, IOASC_LOG_LEVEL_MUST, + {0x07278900, IOASC_LOG_LEVEL_HARD, "Data Protect, incorrect resource address of exposed mode device"}, - {0x07278A00, IOASC_LOG_LEVEL_MUST, + {0x07278A00, IOASC_LOG_LEVEL_HARD, "Data Protect, Array is missing a device and parity is out of sync"}, - {0x07278B00, IOASC_LOG_LEVEL_MUST, + {0x07278B00, IOASC_LOG_LEVEL_HARD, "Data Protect, maximum number of arrays already exist"}, {0x07278C00, IOASC_LOG_LEVEL_HARD, "Data Protect, cannot locate cache data for device"}, {0x07278D00, IOASC_LOG_LEVEL_HARD, "Data Protect, cache data exits for a changed device"}, - {0x07279100, IOASC_LOG_LEVEL_MUST, + {0x07279100, IOASC_LOG_LEVEL_HARD, "Data Protect, detection of a device requiring format"}, - {0x07279200, IOASC_LOG_LEVEL_MUST, + {0x07279200, IOASC_LOG_LEVEL_HARD, "Data Protect, IOA exceeds maximum number of devices"}, - {0x07279600, IOASC_LOG_LEVEL_MUST, + {0x07279600, IOASC_LOG_LEVEL_HARD, "Data Protect, missing array, volume set is not functional"}, - {0x07279700, IOASC_LOG_LEVEL_MUST, + {0x07279700, IOASC_LOG_LEVEL_HARD, "Data Protect, single device for a volume set"}, - {0x07279800, IOASC_LOG_LEVEL_MUST, + {0x07279800, IOASC_LOG_LEVEL_HARD, "Data Protect, missing multiple devices for a volume set"}, {0x07279900, IOASC_LOG_LEVEL_HARD, "Data Protect, maximum number of volument sets already exists"}, - {0x07279A00, IOASC_LOG_LEVEL_MUST, + {0x07279A00, IOASC_LOG_LEVEL_HARD, "Data Protect, other volume set problem"}, }; @@ -952,27 +1026,6 @@ struct pmcraid_ioctl_header { #define PMCRAID_IOCTL_SIGNATURE "PMCRAID" - -/* - * pmcraid_event_details - defines AEN details that apps can retrieve from LLD - * - * .rcb_ccn - complete RCB of CCN - * .rcb_ldn - complete RCB of CCN - */ -struct pmcraid_event_details { - struct pmcraid_hcam_ccn rcb_ccn; - struct pmcraid_hcam_ldn rcb_ldn; -}; - -/* - * pmcraid_driver_ioctl_buffer - structure passed as argument to most of the - * PMC driver handled ioctls. - */ -struct pmcraid_driver_ioctl_buffer { - struct pmcraid_ioctl_header ioctl_header; - struct pmcraid_event_details event_details; -}; - /* * pmcraid_passthrough_ioctl_buffer - structure given as argument to * passthrough(or firmware handled) IOCTL commands. Note that ioarcb requires -- cgit v1.2.3 From 75baf69657ea2107f2c202cd29dada206ae4b7c4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 8 Jun 2010 18:31:21 -0400 Subject: [SCSI] lpfc 8.3.14: PCI fixes and enhancements - Allow enabling MSI-X intterupts with fewer vectors than requested by looking at the return value from pci_enable_msix. - Implemented driver PCI AER error handling routines for supporting AER error recovering on SLI4 devices. - Remove redundant SLI_ACTIVE checks Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 22 +---- drivers/scsi/lpfc/lpfc_init.c | 195 +++++++++++++++++++++++++++++++++++++++--- drivers/scsi/lpfc/lpfc_scsi.c | 10 ++- drivers/scsi/lpfc/lpfc_sli.c | 41 +++++++-- drivers/scsi/lpfc/lpfc_sli4.h | 1 + 5 files changed, 228 insertions(+), 41 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 39b0760c438d..a7c6b7390554 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -864,7 +864,6 @@ lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mrpi, uint32_t *arpi, uint32_t *mvpi, uint32_t *avpi) { - struct lpfc_sli *psli = &phba->sli; struct lpfc_mbx_read_config *rd_config; LPFC_MBOXQ_t *pmboxq; MAILBOX_t *pmb; @@ -893,8 +892,7 @@ lpfc_get_hba_info(struct lpfc_hba *phba, pmb->mbxOwner = OWN_HOST; pmboxq->context1 = NULL; - if ((phba->pport->fc_flag & FC_OFFLINE_MODE) || - (!(psli->sli_flag & LPFC_SLI_ACTIVE))) + if (phba->pport->fc_flag & FC_OFFLINE_MODE) rc = MBX_NOT_FINISHED; else rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); @@ -2943,9 +2941,6 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, struct lpfc_hba *phba = vport->phba; int val = 0, rc = -EINVAL; - /* AER not supported on OC devices yet */ - if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) - return -EPERM; if (!isdigit(buf[0])) return -EINVAL; if (sscanf(buf, "%i", &val) != 1) @@ -3018,12 +3013,6 @@ lpfc_param_show(aer_support) static int lpfc_aer_support_init(struct lpfc_hba *phba, int val) { - /* AER not supported on OC devices yet */ - if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { - phba->cfg_aer_support = 0; - return -EPERM; - } - if (val == 0 || val == 1) { phba->cfg_aer_support = val; return 0; @@ -3068,9 +3057,6 @@ lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr, struct lpfc_hba *phba = vport->phba; int val, rc = -1; - /* AER not supported on OC devices yet */ - if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) - return -EPERM; if (!isdigit(buf[0])) return -EINVAL; if (sscanf(buf, "%i", &val) != 1) @@ -4099,8 +4085,7 @@ lpfc_get_stats(struct Scsi_Host *shost) pmboxq->context1 = NULL; pmboxq->vport = vport; - if ((vport->fc_flag & FC_OFFLINE_MODE) || - (!(psli->sli_flag & LPFC_SLI_ACTIVE))) + if (vport->fc_flag & FC_OFFLINE_MODE) rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); else rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); @@ -4124,8 +4109,7 @@ lpfc_get_stats(struct Scsi_Host *shost) pmboxq->context1 = NULL; pmboxq->vport = vport; - if ((vport->fc_flag & FC_OFFLINE_MODE) || - (!(psli->sli_flag & LPFC_SLI_ACTIVE))) + if (vport->fc_flag & FC_OFFLINE_MODE) rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); else rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 184e45f286d2..08db674ec580 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7030,22 +7030,28 @@ lpfc_sli_disable_intr(struct lpfc_hba *phba) static int lpfc_sli4_enable_msix(struct lpfc_hba *phba) { - int rc, index; + int vectors, rc, index; /* Set up MSI-X multi-message vectors */ for (index = 0; index < phba->sli4_hba.cfg_eqn; index++) phba->sli4_hba.msix_entries[index].entry = index; /* Configure MSI-X capability structure */ + vectors = phba->sli4_hba.cfg_eqn; +enable_msix_vectors: rc = pci_enable_msix(phba->pcidev, phba->sli4_hba.msix_entries, - phba->sli4_hba.cfg_eqn); - if (rc) { + vectors); + if (rc > 1) { + vectors = rc; + goto enable_msix_vectors; + } else if (rc) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0484 PCI enable MSI-X failed (%d)\n", rc); goto msi_fail_out; } + /* Log MSI-X vector assignment */ - for (index = 0; index < phba->sli4_hba.cfg_eqn; index++) + for (index = 0; index < vectors; index++) lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0489 MSI-X entry[%d]: vector=x%x " "message=%d\n", index, @@ -7067,7 +7073,7 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) } /* The rest of the vector(s) are associated to fast-path handler(s) */ - for (index = 1; index < phba->sli4_hba.cfg_eqn; index++) { + for (index = 1; index < vectors; index++) { phba->sli4_hba.fcp_eq_hdl[index - 1].idx = index - 1; phba->sli4_hba.fcp_eq_hdl[index - 1].phba = phba; rc = request_irq(phba->sli4_hba.msix_entries[index].vector, @@ -7081,6 +7087,7 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) goto cfg_fail_out; } } + phba->sli4_hba.msix_vec_nr = vectors; return rc; @@ -7114,9 +7121,10 @@ lpfc_sli4_disable_msix(struct lpfc_hba *phba) /* Free up MSI-X multi-message vectors */ free_irq(phba->sli4_hba.msix_entries[0].vector, phba); - for (index = 1; index < phba->sli4_hba.cfg_eqn; index++) + for (index = 1; index < phba->sli4_hba.msix_vec_nr; index++) free_irq(phba->sli4_hba.msix_entries[index].vector, &phba->sli4_hba.fcp_eq_hdl[index - 1]); + /* Disable MSI-X */ pci_disable_msix(phba->pcidev); @@ -7158,6 +7166,7 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba) pci_disable_msi(phba->pcidev); lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "0490 MSI request_irq failed (%d)\n", rc); + return rc; } for (index = 0; index < phba->cfg_fcp_eq_count; index++) { @@ -7165,7 +7174,7 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba) phba->sli4_hba.fcp_eq_hdl[index].phba = phba; } - return rc; + return 0; } /** @@ -7876,6 +7885,9 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "2710 PCI channel disable preparing for reset\n"); + /* Block any management I/Os to the device */ + lpfc_block_mgmt_io(phba); + /* Block all SCSI devices' I/Os on the host */ lpfc_scsi_dev_block(phba); @@ -7885,6 +7897,7 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) /* Disable interrupt and pci device */ lpfc_sli_disable_intr(phba); pci_disable_device(phba->pcidev); + /* Flush all driver's outstanding SCSI I/Os as we are to reset */ lpfc_sli_flush_fcp_rings(phba); } @@ -7898,7 +7911,7 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) * pending I/Os. **/ static void -lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba) +lpfc_sli_prep_dev_for_perm_failure(struct lpfc_hba *phba) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "2711 PCI channel permanent disable for failure\n"); @@ -7947,7 +7960,7 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state) return PCI_ERS_RESULT_NEED_RESET; case pci_channel_io_perm_failure: /* Permanent failure, prepare for device down */ - lpfc_prep_dev_for_perm_failure(phba); + lpfc_sli_prep_dev_for_perm_failure(phba); return PCI_ERS_RESULT_DISCONNECT; default: /* Unknown state, prepare and request slot reset */ @@ -8016,7 +8029,8 @@ lpfc_io_slot_reset_s3(struct pci_dev *pdev) } else phba->intr_mode = intr_mode; - /* Take device offline; this will perform cleanup */ + /* Take device offline, it will perform cleanup */ + lpfc_offline_prep(phba); lpfc_offline(phba); lpfc_sli_brdrestart(phba); @@ -8201,6 +8215,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) /* Default to single FCP EQ for non-MSI-X */ if (phba->intr_type != MSIX) phba->cfg_fcp_eq_count = 1; + else if (phba->sli4_hba.msix_vec_nr < phba->cfg_fcp_eq_count) + phba->cfg_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1; /* Set up SLI-4 HBA */ if (lpfc_sli4_hba_setup(phba)) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -8362,7 +8378,7 @@ lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg) struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "0298 PCI device Power Management suspend.\n"); + "2843 PCI device Power Management suspend.\n"); /* Bring down the device */ lpfc_offline_prep(phba); @@ -8452,6 +8468,84 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev) return 0; } +/** + * lpfc_sli4_prep_dev_for_recover - Prepare SLI4 device for pci slot recover + * @phba: pointer to lpfc hba data structure. + * + * This routine is called to prepare the SLI4 device for PCI slot recover. It + * aborts all the outstanding SCSI I/Os to the pci device. + **/ +static void +lpfc_sli4_prep_dev_for_recover(struct lpfc_hba *phba) +{ + struct lpfc_sli *psli = &phba->sli; + struct lpfc_sli_ring *pring; + + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2828 PCI channel I/O abort preparing for recovery\n"); + /* + * There may be errored I/Os through HBA, abort all I/Os on txcmplq + * and let the SCSI mid-layer to retry them to recover. + */ + pring = &psli->ring[psli->fcp_ring]; + lpfc_sli_abort_iocb_ring(phba, pring); +} + +/** + * lpfc_sli4_prep_dev_for_reset - Prepare SLI4 device for pci slot reset + * @phba: pointer to lpfc hba data structure. + * + * This routine is called to prepare the SLI4 device for PCI slot reset. It + * disables the device interrupt and pci device, and aborts the internal FCP + * pending I/Os. + **/ +static void +lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba) +{ + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2826 PCI channel disable preparing for reset\n"); + + /* Block any management I/Os to the device */ + lpfc_block_mgmt_io(phba); + + /* Block all SCSI devices' I/Os on the host */ + lpfc_scsi_dev_block(phba); + + /* stop all timers */ + lpfc_stop_hba_timers(phba); + + /* Disable interrupt and pci device */ + lpfc_sli4_disable_intr(phba); + pci_disable_device(phba->pcidev); + + /* Flush all driver's outstanding SCSI I/Os as we are to reset */ + lpfc_sli_flush_fcp_rings(phba); +} + +/** + * lpfc_sli4_prep_dev_for_perm_failure - Prepare SLI4 dev for pci slot disable + * @phba: pointer to lpfc hba data structure. + * + * This routine is called to prepare the SLI4 device for PCI slot permanently + * disabling. It blocks the SCSI transport layer traffic and flushes the FCP + * pending I/Os. + **/ +static void +lpfc_sli4_prep_dev_for_perm_failure(struct lpfc_hba *phba) +{ + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2827 PCI channel permanent disable for failure\n"); + + /* Block all SCSI devices' I/Os on the host */ + lpfc_scsi_dev_block(phba); + + /* stop all timers */ + lpfc_stop_hba_timers(phba); + + /* Clean up all driver's outstanding SCSI I/Os */ + lpfc_sli_flush_fcp_rings(phba); +} + /** * lpfc_io_error_detected_s4 - Method for handling PCI I/O error to SLI-4 device * @pdev: pointer to PCI device. @@ -8471,7 +8565,29 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev) static pci_ers_result_t lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state) { - return PCI_ERS_RESULT_NEED_RESET; + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + + switch (state) { + case pci_channel_io_normal: + /* Non-fatal error, prepare for recovery */ + lpfc_sli4_prep_dev_for_recover(phba); + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: + /* Fatal error, prepare for slot reset */ + lpfc_sli4_prep_dev_for_reset(phba); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + /* Permanent failure, prepare for device down */ + lpfc_sli4_prep_dev_for_perm_failure(phba); + return PCI_ERS_RESULT_DISCONNECT; + default: + /* Unknown state, prepare and request slot reset */ + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2825 Unknown PCI error state: x%x\n", state); + lpfc_sli4_prep_dev_for_reset(phba); + return PCI_ERS_RESULT_NEED_RESET; + } } /** @@ -8495,6 +8611,39 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state) static pci_ers_result_t lpfc_io_slot_reset_s4(struct pci_dev *pdev) { + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + struct lpfc_sli *psli = &phba->sli; + uint32_t intr_mode; + + dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); + if (pci_enable_device_mem(pdev)) { + printk(KERN_ERR "lpfc: Cannot re-enable " + "PCI device after reset.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_restore_state(pdev); + if (pdev->is_busmaster) + pci_set_master(pdev); + + spin_lock_irq(&phba->hbalock); + psli->sli_flag &= ~LPFC_SLI_ACTIVE; + spin_unlock_irq(&phba->hbalock); + + /* Configure and enable interrupt */ + intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode); + if (intr_mode == LPFC_INTR_ERROR) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2824 Cannot re-enable interrupt after " + "slot reset.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } else + phba->intr_mode = intr_mode; + + /* Log the current active interrupt mode */ + lpfc_log_intr_mode(phba, phba->intr_mode); + return PCI_ERS_RESULT_RECOVERED; } @@ -8511,7 +8660,27 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev) static void lpfc_io_resume_s4(struct pci_dev *pdev) { - return; + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + + /* + * In case of slot reset, as function reset is performed through + * mailbox command which needs DMA to be enabled, this operation + * has to be moved to the io resume phase. Taking device offline + * will perform the necessary cleanup. + */ + if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE)) { + /* Perform device reset */ + lpfc_offline_prep(phba); + lpfc_offline(phba); + lpfc_sli_brdrestart(phba); + /* Bring the device back online */ + lpfc_online(phba); + } + + /* Clean up Advanced Error Reporting (AER) if needed */ + if (phba->hba_flag & HBA_AER_ENABLED) + pci_cleanup_aer_uncorrect_error_status(pdev); } /** diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c6bdf63925d9..f68753ea941f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -2295,15 +2295,21 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, struct lpfc_vport *vport = pIocbIn->vport; struct lpfc_rport_data *rdata = lpfc_cmd->rdata; struct lpfc_nodelist *pnode = rdata->pnode; - struct scsi_cmnd *cmd = lpfc_cmd->pCmd; + struct scsi_cmnd *cmd; int result; struct scsi_device *tmp_sdev; int depth; unsigned long flags; struct lpfc_fast_path_event *fast_path_evt; - struct Scsi_Host *shost = cmd->device->host; + struct Scsi_Host *shost; uint32_t queue_depth, scsi_id; + /* Sanity check on return of outstanding command */ + if (!(lpfc_cmd->pCmd)) + return; + cmd = lpfc_cmd->pCmd; + shost = cmd->device->host; + lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; lpfc_cmd->status = pIocbOut->iocb.ulpStatus; /* pick up SLI4 exhange busy status from HBA */ diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index ae3cb0ab0ae4..9c609546b4ef 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -3593,13 +3593,16 @@ static int lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) { struct lpfc_sli *psli = &phba->sli; - + uint32_t hba_aer_enabled; /* Restart HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "0296 Restart HBA Data: x%x x%x\n", phba->pport->port_state, psli->sli_flag); + /* Take PCIe device Advanced Error Reporting (AER) state */ + hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED; + lpfc_sli4_brdreset(phba); spin_lock_irq(&phba->hbalock); @@ -3611,6 +3614,10 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets)); psli->stats_start = get_seconds(); + /* Reset HBA AER if it was enabled, note hba_flag was reset above */ + if (hba_aer_enabled) + pci_disable_pcie_error_reporting(phba->pcidev); + lpfc_hba_down_post(phba); return 0; @@ -4554,6 +4561,24 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* Start error attention (ERATT) polling timer */ mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL); + /* Enable PCIe device Advanced Error Reporting (AER) if configured */ + if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) { + rc = pci_enable_pcie_error_reporting(phba->pcidev); + if (!rc) { + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "2829 This device supports " + "Advanced Error Reporting (AER)\n"); + spin_lock_irq(&phba->hbalock); + phba->hba_flag |= HBA_AER_ENABLED; + spin_unlock_irq(&phba->hbalock); + } else { + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "2830 This device does not support " + "Advanced Error Reporting (AER)\n"); + phba->cfg_aer_support = 0; + } + } + /* * The port is ready, set the host's link state to LINK_DOWN * in preparation for link interrupts. @@ -9089,9 +9114,10 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe) } } if (unlikely(!cq)) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0365 Slow-path CQ identifier (%d) does " - "not exist\n", cqid); + if (phba->sli.sli_flag & LPFC_SLI_ACTIVE) + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "0365 Slow-path CQ identifier " + "(%d) does not exist\n", cqid); return; } @@ -9321,9 +9347,10 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, cq = phba->sli4_hba.fcp_cq[fcp_cqidx]; if (unlikely(!cq)) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "0367 Fast-path completion queue does not " - "exist\n"); + if (phba->sli.sli_flag & LPFC_SLI_ACTIVE) + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "0367 Fast-path completion queue " + "does not exist\n"); return; } diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 1f8ec72c5dcb..ccdb95774e84 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -382,6 +382,7 @@ struct lpfc_sli4_hba { struct lpfc_pc_sli4_params pc_sli4_params; struct msix_entry *msix_entries; uint32_t cfg_eqn; + uint32_t msix_vec_nr; struct lpfc_fcp_eq_hdl *fcp_eq_hdl; /* FCP per-WQ handle */ /* Pointers to the constructed SLI4 queues */ struct lpfc_queue **fp_eq; /* Fast-path event queue */ -- cgit v1.2.3 From dbb6b3ab10464aa11df74c0d0a14e869a8c6fd1b Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 8 Jun 2010 18:31:37 -0400 Subject: [SCSI] lpfc 8.3.14: FCoE Discovery Fixes - Prevent unregistring of unused FCF when FLOGI is pending. - Prevent point to point discovery on a FCoE HBA. - Fixed FCF discovery failure after swapping FCoE port by switching over to fast failover method when no FCF matches in-use FCF. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 38 +++++++++- drivers/scsi/lpfc/lpfc_hbadisc.c | 151 ++++++++++++++++++++++++++++++++++----- drivers/scsi/lpfc/lpfc_sli.c | 3 +- drivers/scsi/lpfc/lpfc_sli4.h | 3 + 4 files changed, 175 insertions(+), 20 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index f936f8c7efe1..017c933d60ab 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -796,7 +796,9 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * due to new FCF discovery */ if ((phba->hba_flag & HBA_FIP_SUPPORT) && - (phba->fcf.fcf_flag & FCF_DISCOVERY)) { + (phba->fcf.fcf_flag & FCF_DISCOVERY) && + (irsp->ulpStatus != IOSTAT_LOCAL_REJECT) && + (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, "2611 FLOGI failed on registered " "FCF record fcf_index:%d, trying " @@ -890,9 +892,39 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ if (sp->cmn.fPort) rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp); - else + else if (!(phba->hba_flag & HBA_FCOE_SUPPORT)) rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp); - + else { + lpfc_printf_vlog(vport, KERN_ERR, + LOG_FIP | LOG_ELS, + "2831 FLOGI response with cleared Fabric " + "bit fcf_index 0x%x " + "Switch Name %02x%02x%02x%02x%02x%02x%02x%02x " + "Fabric Name " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + phba->fcf.current_rec.fcf_indx, + phba->fcf.current_rec.switch_name[0], + phba->fcf.current_rec.switch_name[1], + phba->fcf.current_rec.switch_name[2], + phba->fcf.current_rec.switch_name[3], + phba->fcf.current_rec.switch_name[4], + phba->fcf.current_rec.switch_name[5], + phba->fcf.current_rec.switch_name[6], + phba->fcf.current_rec.switch_name[7], + phba->fcf.current_rec.fabric_name[0], + phba->fcf.current_rec.fabric_name[1], + phba->fcf.current_rec.fabric_name[2], + phba->fcf.current_rec.fabric_name[3], + phba->fcf.current_rec.fabric_name[4], + phba->fcf.current_rec.fabric_name[5], + phba->fcf.current_rec.fabric_name[6], + phba->fcf.current_rec.fabric_name[7]); + lpfc_nlp_put(ndlp); + spin_lock_irq(&phba->hbalock); + phba->fcf.fcf_flag &= ~FCF_DISCOVERY; + spin_unlock_irq(&phba->hbalock); + goto out; + } if (!rc) { /* Mark the FCF discovery process done */ if (phba->hba_flag & HBA_FIP_SUPPORT) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index d1c5c52b1c25..7cd5c47a66ea 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1300,7 +1300,7 @@ lpfc_register_fcf(struct lpfc_hba *phba) * used for this FCF when the function returns. * If the FCF record need to be used with a particular vlan id, the vlan is * set in the vlan_id on return of the function. If not VLAN tagging need to - * be used with the FCF vlan_id will be set to 0xFFFF; + * be used with the FCF vlan_id will be set to LPFC_FCOE_NULL_VID; **/ static int lpfc_match_fcf_conn_list(struct lpfc_hba *phba, @@ -1336,7 +1336,7 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, if (phba->valid_vlan) *vlan_id = phba->vlan_id; else - *vlan_id = 0xFFFF; + *vlan_id = LPFC_FCOE_NULL_VID; return 1; } @@ -1360,7 +1360,7 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, if (fcf_vlan_id) *vlan_id = fcf_vlan_id; else - *vlan_id = 0xFFFF; + *vlan_id = LPFC_FCOE_NULL_VID; return 1; } @@ -1469,7 +1469,7 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, else if (fcf_vlan_id) *vlan_id = fcf_vlan_id; else - *vlan_id = 0xFFFF; + *vlan_id = LPFC_FCOE_NULL_VID; return 1; } @@ -1521,6 +1521,9 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf) * Do not continue FCF discovery and clear FCF_DISC_INPROGRESS * flag */ + lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, + "2833 Stop FCF discovery process due to link " + "state change (x%x)\n", phba->link_state); spin_lock_irq(&phba->hbalock); phba->hba_flag &= ~FCF_DISC_INPROGRESS; phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | FCF_DISCOVERY); @@ -1695,6 +1698,37 @@ lpfc_sli4_log_fcf_record_info(struct lpfc_hba *phba, next_fcf_index); } +/** + lpfc_sli4_fcf_record_match - testing new FCF record for matching existing FCF + * @phba: pointer to lpfc hba data structure. + * @fcf_rec: pointer to an existing FCF record. + * @new_fcf_record: pointer to a new FCF record. + * @new_vlan_id: vlan id from the new FCF record. + * + * This function performs matching test of a new FCF record against an existing + * FCF record. If the new_vlan_id passed in is LPFC_FCOE_IGNORE_VID, vlan id + * will not be used as part of the FCF record matching criteria. + * + * Returns true if all the fields matching, otherwise returns false. + */ +static bool +lpfc_sli4_fcf_record_match(struct lpfc_hba *phba, + struct lpfc_fcf_rec *fcf_rec, + struct fcf_record *new_fcf_record, + uint16_t new_vlan_id) +{ + if (new_vlan_id != LPFC_FCOE_IGNORE_VID) + if (!lpfc_vlan_id_match(fcf_rec->vlan_id, new_vlan_id)) + return false; + if (!lpfc_mac_addr_match(fcf_rec->mac_addr, new_fcf_record)) + return false; + if (!lpfc_sw_name_match(fcf_rec->switch_name, new_fcf_record)) + return false; + if (!lpfc_fab_name_match(fcf_rec->fabric_name, new_fcf_record)) + return false; + return true; +} + /** * lpfc_mbx_cmpl_fcf_scan_read_fcf_rec - fcf scan read_fcf mbox cmpl handler. * @phba: pointer to lpfc hba data structure. @@ -1758,7 +1792,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) */ if (!rc) { lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, - "2781 FCF record fcf_index:x%x failed FCF " + "2781 FCF record (x%x) failed FCF " "connection list check, fcf_avail:x%x, " "fcf_valid:x%x\n", bf_get(lpfc_fcf_record_fcf_index, @@ -1767,6 +1801,32 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) new_fcf_record), bf_get(lpfc_fcf_record_fcf_valid, new_fcf_record)); + if ((phba->fcf.fcf_flag & FCF_IN_USE) && + lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec, + new_fcf_record, LPFC_FCOE_IGNORE_VID)) { + /* + * In case the current in-use FCF record becomes + * invalid/unavailable during FCF discovery that + * was not triggered by fast FCF failover process, + * treat it as fast FCF failover. + */ + if (!(phba->fcf.fcf_flag & FCF_REDISC_PEND) && + !(phba->fcf.fcf_flag & FCF_REDISC_FOV)) { + lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, + "2835 Invalid in-use FCF " + "record (x%x) reported, " + "entering fast FCF failover " + "mode scanning.\n", + phba->fcf.current_rec.fcf_indx); + spin_lock_irq(&phba->hbalock); + phba->fcf.fcf_flag |= FCF_REDISC_FOV; + spin_unlock_irq(&phba->hbalock); + lpfc_sli4_mbox_cmd_free(phba, mboxq); + lpfc_sli4_fcf_scan_read_fcf_rec(phba, + LPFC_FCOE_FCF_GET_FIRST); + return; + } + } goto read_next_fcf; } else { fcf_index = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record); @@ -1783,14 +1843,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) */ spin_lock_irq(&phba->hbalock); if (phba->fcf.fcf_flag & FCF_IN_USE) { - if (lpfc_fab_name_match(phba->fcf.current_rec.fabric_name, - new_fcf_record) && - lpfc_sw_name_match(phba->fcf.current_rec.switch_name, - new_fcf_record) && - lpfc_mac_addr_match(phba->fcf.current_rec.mac_addr, - new_fcf_record) && - lpfc_vlan_id_match(phba->fcf.current_rec.vlan_id, - vlan_id)) { + if (lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec, + new_fcf_record, vlan_id)) { phba->fcf.fcf_flag |= FCF_AVAILABLE; if (phba->fcf.fcf_flag & FCF_REDISC_PEND) /* Stop FCF redisc wait timer if pending */ @@ -1800,6 +1854,13 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | FCF_DISCOVERY); spin_unlock_irq(&phba->hbalock); + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2836 The new FCF record (x%x) " + "matches the in-use FCF record " + "(x%x)\n", + phba->fcf.current_rec.fcf_indx, + bf_get(lpfc_fcf_record_fcf_index, + new_fcf_record)); goto out; } /* @@ -1831,6 +1892,12 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) */ if (boot_flag && !(fcf_rec->flag & BOOT_ENABLE)) { /* Choose this FCF record */ + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2837 Update current FCF record " + "(x%x) with new FCF record (x%x)\n", + fcf_rec->fcf_indx, + bf_get(lpfc_fcf_record_fcf_index, + new_fcf_record)); __lpfc_update_fcf_record(phba, fcf_rec, new_fcf_record, addr_mode, vlan_id, BOOT_ENABLE); spin_unlock_irq(&phba->hbalock); @@ -1851,6 +1918,12 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) */ if (new_fcf_record->fip_priority < fcf_rec->priority) { /* Choose the new FCF record with lower priority */ + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2838 Update current FCF record " + "(x%x) with new FCF record (x%x)\n", + fcf_rec->fcf_indx, + bf_get(lpfc_fcf_record_fcf_index, + new_fcf_record)); __lpfc_update_fcf_record(phba, fcf_rec, new_fcf_record, addr_mode, vlan_id, 0); /* Reset running random FCF selection count */ @@ -1860,11 +1933,18 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->fcf.eligible_fcf_cnt++; select_new_fcf = lpfc_sli4_new_fcf_random_select(phba, phba->fcf.eligible_fcf_cnt); - if (select_new_fcf) + if (select_new_fcf) { + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2839 Update current FCF record " + "(x%x) with new FCF record (x%x)\n", + fcf_rec->fcf_indx, + bf_get(lpfc_fcf_record_fcf_index, + new_fcf_record)); /* Choose the new FCF by random selection */ __lpfc_update_fcf_record(phba, fcf_rec, new_fcf_record, addr_mode, vlan_id, 0); + } } spin_unlock_irq(&phba->hbalock); goto read_next_fcf; @@ -1874,6 +1954,11 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) * initial best-fit FCF. */ if (fcf_rec) { + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2840 Update current FCF record " + "with initial FCF record (x%x)\n", + bf_get(lpfc_fcf_record_fcf_index, + new_fcf_record)); __lpfc_update_fcf_record(phba, fcf_rec, new_fcf_record, addr_mode, vlan_id, (boot_flag ? BOOT_ENABLE : 0)); @@ -1931,6 +2016,12 @@ read_next_fcf: lpfc_unregister_fcf(phba); /* Replace in-use record with the new record */ + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2842 Replace the current in-use " + "FCF record (x%x) with failover FCF " + "record (x%x)\n", + phba->fcf.current_rec.fcf_indx, + phba->fcf.failover_rec.fcf_indx); memcpy(&phba->fcf.current_rec, &phba->fcf.failover_rec, sizeof(struct lpfc_fcf_rec)); @@ -1954,6 +2045,28 @@ read_next_fcf: if ((phba->fcf.fcf_flag & FCF_REDISC_EVT) || (phba->fcf.fcf_flag & FCF_REDISC_PEND)) return; + + if (phba->fcf.fcf_flag & FCF_IN_USE) { + /* + * In case the current in-use FCF record no + * longer existed during FCF discovery that + * was not triggered by fast FCF failover + * process, treat it as fast FCF failover. + */ + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2841 In-use FCF record (x%x) " + "not reported, entering fast " + "FCF failover mode scanning.\n", + phba->fcf.current_rec.fcf_indx); + spin_lock_irq(&phba->hbalock); + phba->fcf.fcf_flag |= FCF_REDISC_FOV; + spin_unlock_irq(&phba->hbalock); + lpfc_sli4_mbox_cmd_free(phba, mboxq); + lpfc_sli4_fcf_scan_read_fcf_rec(phba, + LPFC_FCOE_FCF_GET_FIRST); + return; + } + /* * Otherwise, initial scan or post linkdown rescan, * register with the best FCF record found so far @@ -2036,6 +2149,11 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) next_fcf_index); /* Upload new FCF record to the failover FCF record */ + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2834 Update the current FCF record (x%x) " + "with the next FCF record (x%x)\n", + phba->fcf.failover_rec.fcf_indx, + bf_get(lpfc_fcf_record_fcf_index, new_fcf_record)); spin_lock_irq(&phba->hbalock); __lpfc_update_fcf_record(phba, &phba->fcf.failover_rec, new_fcf_record, addr_mode, vlan_id, @@ -2053,7 +2171,7 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) lpfc_printf_log(phba, KERN_INFO, LOG_FIP, "2783 FLOGI round robin FCF failover from FCF " - "(index:x%x) to FCF (index:x%x).\n", + "(x%x) to FCF (x%x).\n", current_fcf_index, bf_get(lpfc_fcf_record_fcf_index, new_fcf_record)); @@ -5217,7 +5335,8 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); if (!(phba->hba_flag & HBA_FCOE_SUPPORT) || !(phba->fcf.fcf_flag & FCF_REGISTERED) || - !(phba->hba_flag & HBA_FIP_SUPPORT)) { + !(phba->hba_flag & HBA_FIP_SUPPORT) || + (phba->pport->port_state == LPFC_FLOGI)) { spin_unlock_irq(&phba->hbalock); return; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 9c609546b4ef..f38c05dc5635 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -12404,7 +12404,8 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba) next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask, LPFC_SLI4_FCF_TBL_INDX_MAX, 0); /* Round robin failover stop condition */ - if (next_fcf_index == phba->fcf.fcf_rr_init_indx) + if ((next_fcf_index == phba->fcf.fcf_rr_init_indx) || + (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)) return LPFC_FCOE_FCF_NEXT_NONE; return next_fcf_index; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index ccdb95774e84..7686c1a9a634 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -51,6 +51,9 @@ #define LPFC_FCOE_FCF_GET_FIRST 0xFFFF #define LPFC_FCOE_FCF_NEXT_NONE 0xFFFF +#define LPFC_FCOE_NULL_VID 0xFFF +#define LPFC_FCOE_IGNORE_VID 0xFFFF + /* First 3 bytes of default FCF MAC is specified by FC_MAP */ #define LPFC_FCOE_FCF_MAC3 0xFF #define LPFC_FCOE_FCF_MAC4 0xFF -- cgit v1.2.3 From d7c479929b6804f4e9d5fb5f721aba31622f3d97 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 8 Jun 2010 18:31:54 -0400 Subject: [SCSI] lpfc 8.3.14: SCSI and SLI API fixes - Fixed accounting of allocated SCSI buffers when post sgl fails. - Restrict scsi buffer allocation based on LUN count (sdev_cnt). - Create __lpfc_sli_free_rpi that doesn't take out the hbalock. - Modify lpfc_sli_free_rpi to call __lpfc_sli_free_rpi. - Call __lpfc_sli_free_rpi in lpfc_cleanup_pending_mbox. - Do not swap the strings returned in mailbox commands and do not swap byte aligned data in VPD. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 1 + drivers/scsi/lpfc/lpfc_init.c | 1 + drivers/scsi/lpfc/lpfc_mbox.c | 20 ++++++++++++++++++++ drivers/scsi/lpfc/lpfc_scsi.c | 14 ++++++++++---- drivers/scsi/lpfc/lpfc_sli.c | 34 +++++++++++++++++++++++++++------- drivers/scsi/lpfc/lpfc_sli4.h | 1 + 8 files changed, 62 insertions(+), 11 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index fcfc495d1e0d..bb40fcbe17c5 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -815,6 +815,7 @@ struct lpfc_hba { #define HBA_MENLO_SUPPORT 0x1 /* HBA supports menlo commands */ uint32_t iocb_cnt; uint32_t iocb_max; + atomic_t sdev_cnt; }; static inline struct Scsi_Host * diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 361f4e7e23e4..03f4ddc18572 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -191,6 +191,7 @@ irqreturn_t lpfc_sli4_sp_intr_handler(int, void *); irqreturn_t lpfc_sli4_fp_intr_handler(int, void *); void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *); +void lpfc_sli4_swap_str(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *); void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7cd5c47a66ea..9fcad20491ef 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -3845,6 +3845,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) mempool_free(mbox, phba->mbox_mem_pool); } lpfc_no_rpi(phba, ndlp); + ndlp->nlp_rpi = 0; ndlp->nlp_flag &= ~NLP_RPI_VALID; ndlp->nlp_flag &= ~NLP_NPR_ADISC; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 08db674ec580..fb06933f8e6c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -4919,6 +4919,7 @@ lpfc_create_shost(struct lpfc_hba *phba) phba->fc_altov = FF_DEF_ALTOV; phba->fc_arbtov = FF_DEF_ARBTOV; + atomic_set(&phba->sdev_cnt, 0); vport = lpfc_create_port(phba, phba->brd_no, &phba->pcidev->dev); if (!vport) return -ENODEV; diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 196371fae242..cb5d93b41b50 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -955,6 +955,26 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) return; } +void +lpfc_sli4_swap_str(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) +{ + MAILBOX_t *mb = &pmb->u.mb; + struct lpfc_mqe *mqe; + + switch (mb->mbxCommand) { + case MBX_READ_REV: + mqe = &pmb->u.mqe; + lpfc_sli_pcimem_bcopy(mqe->un.read_rev.fw_name, + mqe->un.read_rev.fw_name, 16); + lpfc_sli_pcimem_bcopy(mqe->un.read_rev.ulp_fw_name, + mqe->un.read_rev.ulp_fw_name, 16); + break; + default: + break; + } + return; +} + /** * lpfc_build_hbq_profile2 - Set up the HBQ Selection Profile 2 * @hbqmb: pointer to the HBQ configuration data structure in mailbox command. diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f68753ea941f..7b66b71a14fe 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -747,7 +747,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) int status = 0, index; int bcnt; int non_sequential_xri = 0; - int rc = 0; LIST_HEAD(sblist); for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { @@ -860,7 +859,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) if (status) { /* Put this back on the abort scsi list */ psb->exch_busy = 1; - rc++; } else { psb->exch_busy = 0; psb->status = IOSTAT_SUCCESS; @@ -879,7 +877,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) if (status) { /* Put this back on the abort scsi list */ psb->exch_busy = 1; - rc++; } else { psb->exch_busy = 0; psb->status = IOSTAT_SUCCESS; @@ -889,7 +886,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) } } - return bcnt + non_sequential_xri - rc; + return bcnt + non_sequential_xri; } /** @@ -3572,11 +3569,13 @@ lpfc_slave_alloc(struct scsi_device *sdev) uint32_t total = 0; uint32_t num_to_alloc = 0; int num_allocated = 0; + uint32_t sdev_cnt; if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; sdev->hostdata = rport->dd_data; + sdev_cnt = atomic_inc_return(&phba->sdev_cnt); /* * Populate the cmds_per_lun count scsi_bufs into this host's globally @@ -3588,6 +3587,10 @@ lpfc_slave_alloc(struct scsi_device *sdev) total = phba->total_scsi_bufs; num_to_alloc = vport->cfg_lun_queue_depth + 2; + /* If allocated buffers are enough do nothing */ + if ((sdev_cnt * (vport->cfg_lun_queue_depth + 2)) < total) + return 0; + /* Allow some exchanges to be available always to complete discovery */ if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, @@ -3669,6 +3672,9 @@ lpfc_slave_configure(struct scsi_device *sdev) static void lpfc_slave_destroy(struct scsi_device *sdev) { + struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata; + struct lpfc_hba *phba = vport->phba; + atomic_dec(&phba->sdev_cnt); sdev->hostdata = NULL; return; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f38c05dc5635..7ddf52682271 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4236,7 +4236,8 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, if (mqe->un.read_rev.avail_vpd_len < *vpd_size) *vpd_size = mqe->un.read_rev.avail_vpd_len; - lpfc_sli_pcimem_bcopy(dmabuf->virt, vpd, *vpd_size); + memcpy(vpd, dmabuf->virt, *vpd_size); + dma_free_coherent(&phba->pcidev->dev, dma_size, dmabuf->virt, dmabuf->phys); kfree(dmabuf); @@ -5305,7 +5306,8 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if (mcqe_status != MB_CQE_STATUS_SUCCESS) { bf_set(lpfc_mqe_status, mb, LPFC_MBX_ERROR_RANGE | mcqe_status); rc = MBXERR_ERROR; - } + } else + lpfc_sli4_swap_str(phba, mboxq); lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, "(%d):0356 Mailbox cmd x%x (x%x) Status x%x " @@ -7790,9 +7792,10 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, * if LPFC_MBX_WAKE flag is set the mailbox is completed * else do not free the resources. */ - if (pmboxq->mbox_flag & LPFC_MBX_WAKE) + if (pmboxq->mbox_flag & LPFC_MBX_WAKE) { retval = MBX_SUCCESS; - else { + lpfc_sli4_swap_str(phba, pmboxq); + } else { retval = MBX_TIMEOUT; pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; } @@ -11967,6 +11970,22 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) return rpi; } +/** + * lpfc_sli4_free_rpi - Release an rpi for reuse. + * @phba: pointer to lpfc hba data structure. + * + * This routine is invoked to release an rpi to the pool of + * available rpis maintained by the driver. + **/ +void +__lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) +{ + if (test_and_clear_bit(rpi, phba->sli4_hba.rpi_bmask)) { + phba->sli4_hba.rpi_count--; + phba->sli4_hba.max_cfg_param.rpi_used--; + } +} + /** * lpfc_sli4_free_rpi - Release an rpi for reuse. * @phba: pointer to lpfc hba data structure. @@ -11978,9 +11997,7 @@ void lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) { spin_lock_irq(&phba->hbalock); - clear_bit(rpi, phba->sli4_hba.rpi_bmask); - phba->sli4_hba.rpi_count--; - phba->sli4_hba.max_cfg_param.rpi_used--; + __lpfc_sli4_free_rpi(phba, rpi); spin_unlock_irq(&phba->hbalock); } @@ -12751,6 +12768,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) continue; if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) { + if (phba->sli_rev == LPFC_SLI_REV4) + __lpfc_sli4_free_rpi(phba, + mb->u.mb.un.varRegLogin.rpi); mp = (struct lpfc_dmabuf *) (mb->context1); if (mp) { __lpfc_mbuf_free(phba, mp->virt, mp->phys); diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 7686c1a9a634..c916079fbb35 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -528,6 +528,7 @@ int lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *); struct lpfc_rpi_hdr *lpfc_sli4_create_rpi_hdr(struct lpfc_hba *); void lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *); int lpfc_sli4_alloc_rpi(struct lpfc_hba *); +void __lpfc_sli4_free_rpi(struct lpfc_hba *, int); void lpfc_sli4_free_rpi(struct lpfc_hba *, int); void lpfc_sli4_remove_rpis(struct lpfc_hba *); void lpfc_sli4_async_event_proc(struct lpfc_hba *); -- cgit v1.2.3 From 2cae179486a356aca2a2617f0399f04c66598d8b Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 8 Jun 2010 18:32:13 -0400 Subject: [SCSI] lpfc 8.3.14: Update Driver version to 8.3.14 Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index e79090df228a..33d9d8db4d35 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.13" +#define LPFC_DRIVER_VERSION "8.3.14" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" -- cgit v1.2.3 From fa95d206e4a4fb549bdb9fe71091417f4912178f Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 9 Jun 2010 03:30:08 -0500 Subject: [SCSI] be2iscsi: fix disconnection cleanup This patch fixes 4 bugs in the connection connect/disconnect cleanup path. 1. If beiscsi_open_conn fails beiscsi_free_ep was always being called, and if beiscsi_open_conn failed because beiscsi_get_cid failed then we would free an unallocated cid. 2. If beiscsi_ep_connect failed due to a beiscsi_open_conn failure it was leaking iscsi_endpoints. 3. beiscsi_ep_disconnect was leaking iscsi_endpoints. beiscsi_ep_disconnect should free the iscsi_endpoint. We cannot do it in beiscsi_conn_stop because that is only called for iscsi connection cleanup. If beiscsi_ep_connect returns success, but then the poll function fails or the connect times out then beiscsi_ep_disconnect will be called to clean up the ep. The conn_stop callout will not be called in that path. 4. beiscsi_conn_stop was freeing the iscsi_endpoint then accessing it a couple lines later. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_iscsi.c | 123 +++++++++++++++++---------------------- drivers/scsi/be2iscsi/be_iscsi.h | 2 - drivers/scsi/be2iscsi/be_main.c | 2 +- 3 files changed, 56 insertions(+), 71 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index c3928cb8b042..454027ccbf16 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -441,6 +441,31 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba) return cid; } +/** + * beiscsi_put_cid - Free the cid + * @phba: The phba for which the cid is being freed + * @cid: The cid to free + */ +static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) +{ + phba->avlbl_cids++; + phba->cid_array[phba->cid_free++] = cid; + if (phba->cid_free == phba->params.cxns_per_ctrl) + phba->cid_free = 0; +} + +/** + * beiscsi_free_ep - free endpoint + * @ep: pointer to iscsi endpoint structure + */ +static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) +{ + struct beiscsi_hba *phba = beiscsi_ep->phba; + + beiscsi_put_cid(phba, beiscsi_ep->ep_cid); + beiscsi_ep->phba = NULL; +} + /** * beiscsi_open_conn - Ask FW to open a TCP connection * @ep: endpoint to be used @@ -475,7 +500,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl * 2)) { SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); - return ret; + goto free_ep; } beiscsi_ep->cid_vld = 0; @@ -493,10 +518,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; if (status || extd_status) { SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed" - " status = %d extd_status = %d \n", + " status = %d extd_status = %d\n", status, extd_status); free_mcc_tag(&phba->ctrl, tag); - return -1; + goto free_ep; } else { wrb = queue_get_wrb(mccq, wrb_num); free_mcc_tag(&phba->ctrl, tag); @@ -508,31 +533,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); } return 0; -} - -/** - * beiscsi_put_cid - Free the cid - * @phba: The phba for which the cid is being freed - * @cid: The cid to free - */ -static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) -{ - phba->avlbl_cids++; - phba->cid_array[phba->cid_free++] = cid; - if (phba->cid_free == phba->params.cxns_per_ctrl) - phba->cid_free = 0; -} - -/** - * beiscsi_free_ep - free endpoint - * @ep: pointer to iscsi endpoint structure - */ -static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) -{ - struct beiscsi_hba *phba = beiscsi_ep->phba; - beiscsi_put_cid(phba, beiscsi_ep->ep_cid); - beiscsi_ep->phba = NULL; +free_ep: + beiscsi_free_ep(beiscsi_ep); + return -1; } /** @@ -585,7 +589,7 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, return ep; free_ep: - beiscsi_free_ep(beiscsi_ep); + iscsi_destroy_endpoint(ep); return ERR_PTR(ret); } @@ -631,30 +635,6 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) return ret; } -/** - * beiscsi_ep_disconnect - Tears down the TCP connection - * @ep: endpoint to be used - * - * Tears down the TCP connection - */ -void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) -{ - struct beiscsi_conn *beiscsi_conn; - struct beiscsi_endpoint *beiscsi_ep; - struct beiscsi_hba *phba; - - beiscsi_ep = ep->dd_data; - phba = beiscsi_ep->phba; - SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n", - beiscsi_ep->ep_cid); - - if (beiscsi_ep->conn) { - beiscsi_conn = beiscsi_ep->conn; - iscsi_suspend_queue(beiscsi_conn->conn); - } - -} - /** * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table * @phba: The phba instance @@ -673,28 +653,35 @@ static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba, } /** - * beiscsi_conn_stop - Invalidate and stop the connection - * @cls_conn: pointer to get iscsi_conn - * @flag: The type of connection closure + * beiscsi_ep_disconnect - Tears down the TCP connection + * @ep: endpoint to be used + * + * Tears down the TCP connection */ -void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) +void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) { - struct iscsi_conn *conn = cls_conn->dd_data; - struct beiscsi_conn *beiscsi_conn = conn->dd_data; + struct beiscsi_conn *beiscsi_conn; struct beiscsi_endpoint *beiscsi_ep; - struct iscsi_session *session = conn->session; - struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); - struct beiscsi_hba *phba = iscsi_host_priv(shost); + struct beiscsi_hba *phba; unsigned int tag; unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; - beiscsi_ep = beiscsi_conn->ep; - if (!beiscsi_ep) { - SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n"); + beiscsi_ep = ep->dd_data; + phba = beiscsi_ep->phba; + SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n", + beiscsi_ep->ep_cid); + + if (!beiscsi_ep->conn) { + SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect, no " + "beiscsi_ep\n"); return; } - SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop ep_cid = %d\n", - beiscsi_ep->ep_cid); + beiscsi_conn = beiscsi_ep->conn; + iscsi_suspend_queue(beiscsi_conn->conn); + + SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect ep_cid = %d\n", + beiscsi_ep->ep_cid); + tag = mgmt_invalidate_connection(phba, beiscsi_ep, beiscsi_ep->ep_cid, 1, savecfg_flag); @@ -707,9 +694,9 @@ void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) phba->ctrl.mcc_numtag[tag]); free_mcc_tag(&phba->ctrl, tag); } + beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL); beiscsi_free_ep(beiscsi_ep); - iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); - iscsi_conn_stop(cls_conn, flag); + iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); } diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index 1f512c28cbf9..870cdb2a73e4 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h @@ -59,8 +59,6 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn); -void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag); - struct iscsi_endpoint *beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, int non_blocking); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index dd5b105f8f47..854414551bb0 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3955,7 +3955,7 @@ struct iscsi_transport beiscsi_iscsi_transport = { .get_session_param = iscsi_session_get_param, .get_host_param = beiscsi_get_host_param, .start_conn = beiscsi_conn_start, - .stop_conn = beiscsi_conn_stop, + .stop_conn = iscsi_conn_stop, .send_pdu = iscsi_conn_send_pdu, .xmit_task = beiscsi_task_xmit, .cleanup_task = beiscsi_cleanup_task, -- cgit v1.2.3 From c5f10187965f93ef7ef67da9c7c449b13b6dee1b Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Wed, 9 Jun 2010 08:24:55 -0700 Subject: [SCSI] ipr: add writeq definition if needed Compiling the driver will fail on 32 bit powerpc and other architectures where writeq is not defined. This patch adds a definition for writeq. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index ea391ffc8711..0ef9a67112a8 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1860,4 +1860,12 @@ static inline int ipr_sdt_is_fmt2(u32 sdt_word) return 0; } +#ifndef writeq +static inline void writeq(u64 val, void __iomem *addr) +{ + writel(((u32) (val >> 32)), addr); + writel(((u32) (val)), (addr + 4)); +} #endif + +#endif /* _IPR_H */ -- cgit v1.2.3 From 1462b8ffd9a9e4798d4e0f9eaadbd1ac0373a11b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 10 Jun 2010 09:52:21 +0200 Subject: [SCSI] be2iscsi: fix memory leak on error path I added a kfree(pwrb_arr) in front of the return. Signed-off-by: Dan Carpenter Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 854414551bb0..353a90b3574d 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -2750,6 +2750,7 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, if (status != 0) { shost_printk(KERN_ERR, phba->shost, "wrbq create failed."); + kfree(pwrb_arr); return status; } phwi_ctrlr->wrb_context[i * 2].cid = phwi_context->be_wrbq[i]. -- cgit v1.2.3 From 82284c09c5dc5c5a5046f3c852f2683dab60109c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 10 Jun 2010 09:53:05 +0200 Subject: [SCSI] be2iscsi: fix null dereference on error path "phba" is always null here so we can't dereference it. Signed-off-by: Dan Carpenter Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 353a90b3574d..0d35bf6c6acc 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3774,8 +3774,8 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, ret = beiscsi_enable_pci(pcidev); if (ret < 0) { - shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" - "Failed to enable pci device \n"); + dev_err(&pcidev->dev, "beiscsi_dev_probe-" + " Failed to enable pci device\n"); return ret; } -- cgit v1.2.3 From 56115598c571cadd4b465836e1423a452a908c89 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Thu, 10 Jun 2010 14:46:34 -0700 Subject: [SCSI] ipr: move setting of the allow_restart flag for vsets and disks A problem was found where the call to scsi_add_device() fails intermittently for an adapter. This is caused when __scsi_add_device() returns -ENODEV as a result of not calling scsi_probe_and_add_lun() since the call to scsi_host_scan_allowed() fails. scsi_host_scan_allowed() fails because the adapter state is set to SHOST_RECOVERY instead of SHOST_RUNNING. The state of the adapter is being set to SHOST_RECOVERY by scsi_eh_scmd_add() during error handling. This problem is avoided by moving the setting of the allow_restart flag to later in the device initialization sequence. This prevents further error handling if we get a NOT_READY response from a TUR command by causing scsi_check_sense() to return SUCCESS. Therefore, scsi_eh_scmd_add() will not run and the adapter state will remain as SHOST_RUNNING. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 62bbe31dd47b..37158eab3c89 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4353,8 +4353,6 @@ static int ipr_slave_configure(struct scsi_device *sdev) IPR_VSET_RW_TIMEOUT); blk_queue_max_hw_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS); } - if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res)) - sdev->allow_restart = 1; if (ipr_is_gata(res) && res->sata_port) ap = res->sata_port->ap; spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); @@ -6771,7 +6769,8 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd) list_move_tail(&res->queue, &ioa_cfg->used_res_q); ipr_init_res_entry(res, &cfgtew); res->add_to_ml = 1; - } + } else if (res->sdev && (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))) + res->sdev->allow_restart = 1; if (found) ipr_update_res_entry(res, &cfgtew); -- cgit v1.2.3 From 281ae642a6475ede25ff86ec124214e346c25e22 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 11 Jun 2010 16:43:33 -0700 Subject: [SCSI] libfcoe: FIP link keep-alive should continue while logged off A check in fcoe_ctlr_send_keep_alive() returns if there's no port_id for the local port. This could miss a keep alive if we just did a host reset and have logged off and will log back in. Return only if we are doing the port keep alive, in which case we need to be logged in. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 50aaa4bcfc50..cc5e8864b805 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -343,7 +343,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, fcf = fip->sel_fcf; lp = fip->lp; - if (!fcf || !lp->port_id) + if (!fcf || (ports && !lp->port_id)) return; len = sizeof(*kal) + ports * sizeof(*vn); -- cgit v1.2.3 From 1508f3ecd991ecbf272e08f5ee70d2618f49159e Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 11 Jun 2010 16:43:38 -0700 Subject: [SCSI] libfcoe: Avoid hang when receiving non-critical descriptors Avoid infinite loop while processing FIP ELS or discovery advertisement with non-critical descriptors. Signed-off-by: Bhanu Prakash Gollapudi Acked-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index cc5e8864b805..66120f135d99 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -703,7 +703,7 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, /* standard says ignore unknown descriptors >= 128 */ if (desc->fip_dtype < FIP_DT_VENDOR_BASE) return -EINVAL; - continue; + break; } desc = (struct fip_desc *)((char *)desc + dlen); rlen -= dlen; @@ -885,7 +885,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) /* standard says ignore unknown descriptors >= 128 */ if (desc->fip_dtype < FIP_DT_VENDOR_BASE) goto drop; - continue; + break; } desc = (struct fip_desc *)((char *)desc + dlen); rlen -= dlen; -- cgit v1.2.3 From 516a648631c912e84e0035590f98eef1d716f4ea Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 11 Jun 2010 16:43:44 -0700 Subject: [SCSI] libfcoe: No solicitation if adv is dropped Host does not send discovery solicitation messages if Disc. Adv from FCF are dropped. It restarts sending solicitation only after receiving a Discovery Adv. from FCF. Fix is to restart solicitation immediately after CVL processing. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 66120f135d99..1d5b949d4fd0 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -1232,8 +1232,11 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) fip->reset_req = 0; spin_unlock_bh(&fip->lock); - if (reset) + if (reset) { fc_lport_reset(fip->lp); + /* restart things with a solicitation */ + fcoe_ctlr_solicit(fip, NULL); + } if (fip->send_ctlr_ka) { fip->send_ctlr_ka = 0; -- cgit v1.2.3 From 292e40b956982601dfc61fe8f0470eb18a616d7e Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 11 Jun 2010 16:43:49 -0700 Subject: [SCSI] libfc: Retry a rejected PRLI request Retry upto max_rport_retry_count when a target responds with LS_RJT for a PRLI request. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 39e440f0f54a..3ee497a05168 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -739,7 +739,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, } else { FC_RPORT_DBG(rdata, "Bad ELS response for PRLI command\n"); - fc_rport_enter_delete(rdata, RPORT_EV_FAILED); + fc_rport_error_retry(rdata, fp); } out: -- cgit v1.2.3 From 618461c02b00a658ec8aa07d409cd496a7e254e2 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 11 Jun 2010 16:43:54 -0700 Subject: [SCSI] libfc: Honor LS_ACC response codes for PRLI As per FC-LS Rev 1.62 table 46, response codes are handled as follows: 1. If the Req executed is true, PRLI is accepted. 2. If Req executed is not set, if resp code is 5, PRLI is not retried and port is logged out. 3. If resp code is anything apart from 1 or 5, PRLI is retired upto max retry count. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 3ee497a05168..e33c5c7961a2 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -698,6 +698,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, u32 roles = FC_RPORT_ROLE_UNKNOWN; u32 fcp_parm = 0; u8 op; + u8 resp_code = 0; mutex_lock(&rdata->rp_mutex); @@ -722,11 +723,25 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { pp = fc_frame_payload_get(fp, sizeof(*pp)); - if (pp && pp->prli.prli_spp_len >= sizeof(pp->spp)) { - fcp_parm = ntohl(pp->spp.spp_params); - if (fcp_parm & FCP_SPPF_RETRY) - rdata->flags |= FC_RP_FLAGS_RETRY; + if (!pp) + goto out; + + resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK); + FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n", + pp->spp.spp_flags); + if (resp_code != FC_SPP_RESP_ACK) { + if (resp_code == FC_SPP_RESP_CONF) + fc_rport_error(rdata, fp); + else + fc_rport_error_retry(rdata, fp); + goto out; } + if (pp->prli.prli_spp_len < sizeof(pp->spp)) + goto out; + + fcp_parm = ntohl(pp->spp.spp_params); + if (fcp_parm & FCP_SPPF_RETRY) + rdata->flags |= FC_RP_FLAGS_RETRY; rdata->supported_classes = FC_COS_CLASS3; if (fcp_parm & FCP_SPPF_INIT_FCN) -- cgit v1.2.3 From f8fc6c2c99b8085368119d6cf39b997255052826 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 11 Jun 2010 16:44:04 -0700 Subject: [SCSI] libfc: Handle unsolicited PRLO request Resubmitting after incorporating Joe's review comment. Unsolicited PRLO request is now handled by sending LS_ACC, and then relogin to the remote port if an N-port login session exists for that remote port. Note that this patch should be applied on top of Joe Eykholt's "Fix remote port restart problem" patch. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 71 ++++++++++++++++++++++++++++++++++++++----- include/scsi/fc/fc_els.h | 9 ++++++ 2 files changed, 72 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index e33c5c7961a2..df85e19079fb 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1573,30 +1573,85 @@ drop: * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests * @rdata: The remote port that sent the PRLO request * @sp: The sequence that the PRLO was on - * @fp: The PRLO request frame + * @rx_fp: The PRLO request frame * * Locking Note: The rport lock is exected to be held before calling * this function. */ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, struct fc_seq *sp, - struct fc_frame *fp) + struct fc_frame *rx_fp) { struct fc_lport *lport = rdata->local_port; - struct fc_frame_header *fh; + struct fc_exch *ep; + struct fc_frame *fp; + struct { + struct fc_els_prlo prlo; + struct fc_els_spp spp; + } *pp; + struct fc_els_spp *rspp; /* request service param page */ + struct fc_els_spp *spp; /* response spp */ + unsigned int len; + unsigned int plen; + u32 f_ctl; struct fc_seq_els_data rjt_data; - fh = fc_frame_header_get(fp); + rjt_data.fp = NULL; + fh = fc_frame_header_get(rx_fp); FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n", fc_rport_state(rdata)); - rjt_data.fp = NULL; - rjt_data.reason = ELS_RJT_UNAB; - rjt_data.explan = ELS_EXPL_NONE; + len = fr_len(rx_fp) - sizeof(*fh); + pp = fc_frame_payload_get(rx_fp, sizeof(*pp)); + if (!pp) + goto reject_len; + plen = ntohs(pp->prlo.prlo_len); + if (plen != 20) + goto reject_len; + if (plen < len) + len = plen; + + rspp = &pp->spp; + + fp = fc_frame_alloc(lport, len); + if (!fp) { + rjt_data.reason = ELS_RJT_UNAB; + rjt_data.explan = ELS_EXPL_INSUF_RES; + goto reject; + } + + sp = lport->tt.seq_start_next(sp); + WARN_ON(!sp); + pp = fc_frame_payload_get(fp, len); + WARN_ON(!pp); + memset(pp, 0, len); + pp->prlo.prlo_cmd = ELS_LS_ACC; + pp->prlo.prlo_obs = 0x10; + pp->prlo.prlo_len = htons(len); + spp = &pp->spp; + spp->spp_type = rspp->spp_type; + spp->spp_type_ext = rspp->spp_type_ext; + spp->spp_flags = FC_SPP_RESP_ACK; + + fc_rport_enter_delete(rdata, RPORT_EV_LOGO); + + f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; + f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; + ep = fc_seq_exch(sp); + fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, + FC_TYPE_ELS, f_ctl, 0); + lport->tt.seq_send(lport, sp, fp); + goto drop; + +reject_len: + rjt_data.reason = ELS_RJT_PROT; + rjt_data.explan = ELS_EXPL_INV_LEN; +reject: lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); - fc_frame_free(fp); +drop: + fc_frame_free(rx_fp); } /** diff --git a/include/scsi/fc/fc_els.h b/include/scsi/fc/fc_els.h index f94328132a26..70a7e92a7664 100644 --- a/include/scsi/fc/fc_els.h +++ b/include/scsi/fc/fc_els.h @@ -404,6 +404,15 @@ struct fc_els_prli { /* service parameter pages follow */ }; +/* + * ELS_PRLO - Process logout request and response. + */ +struct fc_els_prlo { + __u8 prlo_cmd; /* command */ + __u8 prlo_obs; /* obsolete, but shall be set to 10h */ + __be16 prlo_len; /* payload length */ +}; + /* * ELS_ADISC payload */ -- cgit v1.2.3 From 8690cb8359d8e9f8d7ca12791ef7ea32b709df8b Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 11 Jun 2010 16:44:10 -0700 Subject: [SCSI] libfcoe: fix lenient aging of FCF advertisements [This patch has several improvements to the code in the fip timers. It hasn't been tested yet. I'm sending it out for review. Vasu, perhaps you can merge this with your patch and test it together.] The current code allows an advertisement to be used even if it has been 3 times the FCF keep-alive advertisement period (FKA) since one was received from that FCF. The spec. calls for 2.5 times FKA. Fix this and make sure we detect missed keep-alives promptly. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 76 +++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 34 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 1d5b949d4fd0..3ab3db39fc52 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -557,38 +557,44 @@ EXPORT_SYMBOL(fcoe_ctlr_els_send); * * Called with lock held and preemption disabled. * - * An FCF is considered old if we have missed three advertisements. - * That is, there have been no valid advertisement from it for three - * times its keep-alive period including fuzz. + * An FCF is considered old if we have missed two advertisements. + * That is, there have been no valid advertisement from it for 2.5 + * times its keep-alive period. * * In addition, determine the time when an FCF selection can occur. * * Also, increment the MissDiscAdvCount when no advertisement is received * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB). + * + * Returns the time in jiffies for the next call. */ -static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) +static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) { struct fcoe_fcf *fcf; struct fcoe_fcf *next; + unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); + unsigned long deadline; unsigned long sel_time = 0; - unsigned long mda_time = 0; struct fcoe_dev_stats *stats; list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { - mda_time = fcf->fka_period + (fcf->fka_period >> 1); - if ((fip->sel_fcf == fcf) && - (time_after(jiffies, fcf->time + mda_time))) { - mod_timer(&fip->timer, jiffies + mda_time); - stats = per_cpu_ptr(fip->lp->dev_stats, - smp_processor_id()); - stats->MissDiscAdvCount++; - printk(KERN_INFO "libfcoe: host%d: Missing Discovery " - "Advertisement for fab %16.16llx count %lld\n", - fip->lp->host->host_no, fcf->fabric_name, - stats->MissDiscAdvCount); + deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2; + if (fip->sel_fcf == fcf) { + if (time_after(jiffies, deadline)) { + stats = per_cpu_ptr(fip->lp->dev_stats, + smp_processor_id()); + stats->MissDiscAdvCount++; + printk(KERN_INFO "libfcoe: host%d: " + "Missing Discovery Advertisement " + "for fab %16.16llx count %lld\n", + fip->lp->host->host_no, fcf->fabric_name, + stats->MissDiscAdvCount); + } else if (time_after(next_timer, deadline)) + next_timer = deadline; } - if (time_after(jiffies, fcf->time + fcf->fka_period * 3 + - msecs_to_jiffies(FIP_FCF_FUZZ * 3))) { + + deadline += fcf->fka_period; + if (time_after(jiffies, deadline)) { if (fip->sel_fcf == fcf) fip->sel_fcf = NULL; list_del(&fcf->list); @@ -598,19 +604,21 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) stats = per_cpu_ptr(fip->lp->dev_stats, smp_processor_id()); stats->VLinkFailureCount++; - } else if (fcoe_ctlr_mtu_valid(fcf) && - (!sel_time || time_before(sel_time, fcf->time))) { - sel_time = fcf->time; + } else { + if (time_after(next_timer, deadline)) + next_timer = deadline; + if (fcoe_ctlr_mtu_valid(fcf) && + (!sel_time || time_before(sel_time, fcf->time))) + sel_time = fcf->time; } } if (sel_time) { sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); fip->sel_time = sel_time; - if (time_before(sel_time, fip->timer.expires)) - mod_timer(&fip->timer, sel_time); } else { fip->sel_time = 0; } + return next_timer; } /** @@ -1148,7 +1156,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg; struct fcoe_fcf *sel; struct fcoe_fcf *fcf; - unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); + unsigned long next_timer; spin_lock_bh(&fip->lock); if (fip->state == FIP_ST_DISABLED) { @@ -1157,13 +1165,16 @@ static void fcoe_ctlr_timeout(unsigned long arg) } fcf = fip->sel_fcf; - fcoe_ctlr_age_fcfs(fip); + next_timer = fcoe_ctlr_age_fcfs(fip); sel = fip->sel_fcf; - if (!sel && fip->sel_time && time_after_eq(jiffies, fip->sel_time)) { - fcoe_ctlr_select(fip); - sel = fip->sel_fcf; - fip->sel_time = 0; + if (!sel && fip->sel_time) { + if (time_after_eq(jiffies, fip->sel_time)) { + fcoe_ctlr_select(fip); + sel = fip->sel_fcf; + fip->sel_time = 0; + } else if (time_after(next_timer, fip->sel_time)) + next_timer = fip->sel_time; } if (sel != fcf) { @@ -1201,12 +1212,9 @@ static void fcoe_ctlr_timeout(unsigned long arg) } if (time_after(next_timer, fip->port_ka_time)) next_timer = fip->port_ka_time; - mod_timer(&fip->timer, next_timer); - } else if (fip->sel_time) { - next_timer = fip->sel_time + - msecs_to_jiffies(FCOE_CTLR_START_DELAY); - mod_timer(&fip->timer, next_timer); } + if (!list_empty(&fip->fcfs)) + mod_timer(&fip->timer, next_timer); if (fip->send_ctlr_ka || fip->send_port_ka) schedule_work(&fip->timer_work); spin_unlock_bh(&fip->lock); -- cgit v1.2.3 From d99ee45b7cb89803b79745dc3014ba64bfd02b7d Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 11 Jun 2010 16:44:15 -0700 Subject: [SCSI] libfcoe: Use fka_period as periodic timeouts to age out fcf if keep alives are disabled due to fd_flags set and also stop updating keep alive values in that case. Update select fcf time only if fcf is not already selected or select time is not already determined from parse adv, and then have select time cleared only once after fcf is selected. Changed deadline check to time_after_eq() from time_after() since now next timeout will be on exact 2.5 times FKA followed by first advertisement. Signed-off-by: Vasu Dev Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 3ab3db39fc52..4893098b3d3f 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -594,7 +594,7 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) } deadline += fcf->fka_period; - if (time_after(jiffies, deadline)) { + if (time_after_eq(jiffies, deadline)) { if (fip->sel_fcf == fcf) fip->sel_fcf = NULL; list_del(&fcf->list); @@ -612,12 +612,11 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) sel_time = fcf->time; } } - if (sel_time) { + if (sel_time && !fip->sel_fcf && !fip->sel_time) { sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); fip->sel_time = sel_time; - } else { - fip->sel_time = 0; } + return next_timer; } @@ -775,7 +774,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) * ignored after a usable solicited advertisement * has been received. */ - if (fcf == fip->sel_fcf) { + if (fcf == fip->sel_fcf && !fcf->fd_flags) { fip->ctlr_ka_time -= fcf->fka_period; fip->ctlr_ka_time += new.fka_period; if (time_before(fip->ctlr_ka_time, fip->timer.expires)) @@ -813,7 +812,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) * If this is the first validated FCF, note the time and * set a timer to trigger selection. */ - if (mtu_valid && !fip->sel_time && fcoe_ctlr_fcf_usable(fcf)) { + if (mtu_valid && !fip->sel_fcf && fcoe_ctlr_fcf_usable(fcf)) { fip->sel_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY); if (!timer_pending(&fip->timer) || @@ -1187,6 +1186,8 @@ static void fcoe_ctlr_timeout(unsigned long arg) fip->port_ka_time = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); fip->ctlr_ka_time = jiffies + sel->fka_period; + if (time_after(next_timer, fip->ctlr_ka_time)) + next_timer = fip->ctlr_ka_time; } else { printk(KERN_NOTICE "libfcoe: host%d: " "FIP Fibre-Channel Forwarder timed out. " -- cgit v1.2.3 From c600fea2d813e8734748202970722c3b6a76b9a1 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 11 Jun 2010 16:44:20 -0700 Subject: [SCSI] libfcoe: update FIP FCF D flag from advertisments Allow the D flag (indicating that keep-alives are not needed) to be updated dynamically from received FIP advertisements. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 4893098b3d3f..27c21ca802b2 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -769,18 +769,21 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) list_add(&fcf->list, &fip->fcfs); } else { /* - * Flags in advertisements are ignored once the FCF is - * selected. Flags in unsolicited advertisements are - * ignored after a usable solicited advertisement - * has been received. + * Update the FCF's keep-alive descriptor flags. + * Other flag changes from new advertisements are + * ignored after a solicited advertisement is + * received and the FCF is selectable (usable). */ + fcf->fd_flags = new.fd_flags; + if (!fcoe_ctlr_fcf_usable(fcf)) + fcf->flags = new.flags; + if (fcf == fip->sel_fcf && !fcf->fd_flags) { fip->ctlr_ka_time -= fcf->fka_period; fip->ctlr_ka_time += new.fka_period; if (time_before(fip->ctlr_ka_time, fip->timer.expires)) mod_timer(&fip->timer, fip->ctlr_ka_time); - } else if (!fcoe_ctlr_fcf_usable(fcf)) - fcf->flags = new.flags; + } fcf->fka_period = new.fka_period; memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN); } -- cgit v1.2.3 From 0a9c5d344dbd983af59865f9880621e5cbbda899 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 11 Jun 2010 16:44:25 -0700 Subject: [SCSI] libfcoe: Handle duplicate critical descriptors As per FC-BB-5 rev 2, section 7.8.6.2, malformed FIP frame shall be discarded. Drop discovery adv, ELS and CLV's with duplicate critical descriptors. [Resending after incorporating Joe's review comments] Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 27c21ca802b2..db7185c0b964 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -640,6 +640,7 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, unsigned long t; size_t rlen; size_t dlen; + u32 desc_mask; memset(fcf, 0, sizeof(*fcf)); fcf->fka_period = msecs_to_jiffies(FCOE_CTLR_DEF_FKA); @@ -647,6 +648,12 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, fiph = (struct fip_header *)skb->data; fcf->flags = ntohs(fiph->fip_flags); + /* + * mask of required descriptors. validating each one clears its bit. + */ + desc_mask = BIT(FIP_DT_PRI) | BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | + BIT(FIP_DT_FAB) | BIT(FIP_DT_FKA); + rlen = ntohs(fiph->fip_dl_len) * 4; if (rlen + sizeof(*fiph) > skb->len) return -EINVAL; @@ -656,11 +663,19 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, dlen = desc->fip_dlen * FIP_BPW; if (dlen < sizeof(*desc) || dlen > rlen) return -EINVAL; + /* Drop Adv if there are duplicate critical descriptors */ + if ((desc->fip_dtype < 32) && + !(desc_mask & 1U << desc->fip_dtype)) { + LIBFCOE_FIP_DBG(fip, "Duplicate Critical " + "Descriptors in FIP adv\n"); + return -EINVAL; + } switch (desc->fip_dtype) { case FIP_DT_PRI: if (dlen != sizeof(struct fip_pri_desc)) goto len_err; fcf->pri = ((struct fip_pri_desc *)desc)->fd_pri; + desc_mask &= ~BIT(FIP_DT_PRI); break; case FIP_DT_MAC: if (dlen != sizeof(struct fip_mac_desc)) @@ -673,12 +688,14 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, "in FIP adv\n"); return -EINVAL; } + desc_mask &= ~BIT(FIP_DT_MAC); break; case FIP_DT_NAME: if (dlen != sizeof(struct fip_wwn_desc)) goto len_err; wwn = (struct fip_wwn_desc *)desc; fcf->switch_name = get_unaligned_be64(&wwn->fd_wwn); + desc_mask &= ~BIT(FIP_DT_NAME); break; case FIP_DT_FAB: if (dlen != sizeof(struct fip_fab_desc)) @@ -687,6 +704,7 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, fcf->fabric_name = get_unaligned_be64(&fab->fd_wwn); fcf->vfid = ntohs(fab->fd_vfid); fcf->fc_map = ntoh24(fab->fd_map); + desc_mask &= ~BIT(FIP_DT_FAB); break; case FIP_DT_FKA: if (dlen != sizeof(struct fip_fka_desc)) @@ -697,6 +715,7 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, t = ntohl(fka->fd_fka_period); if (t >= FCOE_CTLR_MIN_FKA) fcf->fka_period = msecs_to_jiffies(t); + desc_mask &= ~BIT(FIP_DT_FKA); break; case FIP_DT_MAP_OUI: case FIP_DT_FCOE_SIZE: @@ -719,6 +738,11 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, return -EINVAL; if (!fcf->switch_name || !fcf->fabric_name) return -EINVAL; + if (desc_mask) { + LIBFCOE_FIP_DBG(fip, "adv missing descriptors mask %x\n", + desc_mask); + return -EINVAL; + } return 0; len_err: @@ -847,6 +871,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) size_t els_len = 0; size_t rlen; size_t dlen; + u32 dupl_desc = 0; fiph = (struct fip_header *)skb->data; sub = fiph->fip_subcode; @@ -862,6 +887,15 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) dlen = desc->fip_dlen * FIP_BPW; if (dlen < sizeof(*desc) || dlen > rlen) goto drop; + /* Drop ELS if there are duplicate critical descriptors */ + if (desc->fip_dtype < 32) { + if (dupl_desc & 1U << desc->fip_dtype) { + LIBFCOE_FIP_DBG(fip, "Duplicate Critical " + "Descriptors in FIP ELS\n"); + goto drop; + } + dupl_desc |= (1 << desc->fip_dtype); + } switch (desc->fip_dtype) { case FIP_DT_MAC: if (dlen != sizeof(struct fip_mac_desc)) @@ -973,6 +1007,13 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, dlen = desc->fip_dlen * FIP_BPW; if (dlen > rlen) return; + /* Drop CVL if there are duplicate critical descriptors */ + if ((desc->fip_dtype < 32) && + !(desc_mask & 1U << desc->fip_dtype)) { + LIBFCOE_FIP_DBG(fip, "Duplicate Critical " + "Descriptors in FIP CVL\n"); + return; + } switch (desc->fip_dtype) { case FIP_DT_MAC: mp = (struct fip_mac_desc *)desc; -- cgit v1.2.3 From 5550fda73d8bd3bed454e28c46f5a4e5288769bb Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 11 Jun 2010 16:44:31 -0700 Subject: [SCSI] libfcoe: Host doesnt handle CVL to NPIV ports Clear virtual link for NPIV ports is now handled by resetting the matching vnport. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index db7185c0b964..ce651ca2a4bc 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -989,7 +989,9 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, size_t dlen; struct fcoe_fcf *fcf = fip->sel_fcf; struct fc_lport *lport = fip->lp; - u32 desc_mask; + struct fc_lport *vn_port = NULL; + u32 desc_mask; + int is_vn_port = 0; LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); @@ -1038,8 +1040,26 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, if (compare_ether_addr(vp->fd_mac, fip->get_src_addr(lport)) == 0 && get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn && - ntoh24(vp->fd_fc_id) == lport->port_id) + ntoh24(vp->fd_fc_id) == lport->port_id) { desc_mask &= ~BIT(FIP_DT_VN_ID); + break; + } + /* check if clr_vlink is for NPIV port */ + mutex_lock(&lport->lp_mutex); + list_for_each_entry(vn_port, &lport->vports, list) { + if (compare_ether_addr(vp->fd_mac, + fip->get_src_addr(vn_port)) == 0 && + (get_unaligned_be64(&vp->fd_wwpn) + == vn_port->wwpn) && + (ntoh24(vp->fd_fc_id) == + fc_host_port_id(vn_port->host))) { + desc_mask &= ~BIT(FIP_DT_VN_ID); + is_vn_port = 1; + break; + } + } + mutex_unlock(&lport->lp_mutex); + break; default: /* standard says ignore unknown descriptors >= 128 */ @@ -1060,14 +1080,18 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, } else { LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); - spin_lock_bh(&fip->lock); - per_cpu_ptr(lport->dev_stats, - smp_processor_id())->VLinkFailureCount++; - fcoe_ctlr_reset(fip); - spin_unlock_bh(&fip->lock); + if (is_vn_port) + fc_lport_reset(vn_port); + else { + spin_lock_bh(&fip->lock); + per_cpu_ptr(lport->dev_stats, + smp_processor_id())->VLinkFailureCount++; + fcoe_ctlr_reset(fip); + spin_unlock_bh(&fip->lock); - fc_lport_reset(fip->lp); - fcoe_ctlr_solicit(fip, NULL); + fc_lport_reset(fip->lp); + fcoe_ctlr_solicit(fip, NULL); + } } } -- cgit v1.2.3 From be61331d902e63011138723da3f737d34506f797 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 11 Jun 2010 16:44:36 -0700 Subject: [SCSI] libfcoe: Check for order and missing critical descriptors for FIP ELS requests As per FC-BB-5 rev.2, section 7.8.7.1, strict ordering of FIP descriptors is required for ELS requests. Also, look for missing and duplicate critical descriptors. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index ce651ca2a4bc..f009191063f1 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -871,7 +871,8 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) size_t els_len = 0; size_t rlen; size_t dlen; - u32 dupl_desc = 0; + u32 desc_mask = 0; + u32 desc_cnt = 0; fiph = (struct fip_header *)skb->data; sub = fiph->fip_subcode; @@ -884,20 +885,27 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) desc = (struct fip_desc *)(fiph + 1); while (rlen > 0) { + desc_cnt++; dlen = desc->fip_dlen * FIP_BPW; if (dlen < sizeof(*desc) || dlen > rlen) goto drop; /* Drop ELS if there are duplicate critical descriptors */ if (desc->fip_dtype < 32) { - if (dupl_desc & 1U << desc->fip_dtype) { + if (desc_mask & 1U << desc->fip_dtype) { LIBFCOE_FIP_DBG(fip, "Duplicate Critical " "Descriptors in FIP ELS\n"); goto drop; } - dupl_desc |= (1 << desc->fip_dtype); + desc_mask |= (1 << desc->fip_dtype); } switch (desc->fip_dtype) { case FIP_DT_MAC: + if (desc_cnt == 1) { + LIBFCOE_FIP_DBG(fip, "FIP descriptors " + "received out of order\n"); + goto drop; + } + if (dlen != sizeof(struct fip_mac_desc)) goto len_err; memcpy(granted_mac, @@ -914,6 +922,11 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) case FIP_DT_FDISC: case FIP_DT_LOGO: case FIP_DT_ELP: + if (desc_cnt != 1) { + LIBFCOE_FIP_DBG(fip, "FIP descriptors " + "received out of order\n"); + goto drop; + } if (fh) goto drop; if (dlen < sizeof(*els) + sizeof(*fh) + 1) @@ -929,6 +942,11 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) /* standard says ignore unknown descriptors >= 128 */ if (desc->fip_dtype < FIP_DT_VENDOR_BASE) goto drop; + if (desc_cnt <= 2) { + LIBFCOE_FIP_DBG(fip, "FIP descriptors " + "received out of order\n"); + goto drop; + } break; } desc = (struct fip_desc *)((char *)desc + dlen); @@ -944,6 +962,13 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) fip->flogi_oxid = FC_XID_UNKNOWN; + if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) && + (!(1U << FIP_DT_MAC & desc_mask)))) { + LIBFCOE_FIP_DBG(fip, "Missing critical descriptors " + "in FIP ELS\n"); + goto drop; + } + /* * Convert skb into an fc_frame containing only the ELS. */ -- cgit v1.2.3 From 1c4bfe6305215f09f3e80a14a824e4ae45b2c7ed Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 11 Jun 2010 16:44:41 -0700 Subject: [SCSI] libfc: lport state is enum not bit mask lport state is enum not bit mask. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index ec1f66c4a9d4..8914f1e95b72 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -745,7 +745,7 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) fh = fc_frame_header_get(fp); r_ctl = fh->fh_r_ctl; - if (!(lport->state & LPORT_ST_READY)) + if (lport->state != LPORT_ST_READY) goto out; if (fc_fcp_lock_pkt(fsp)) goto out; -- cgit v1.2.3 From 0db6f4353d68c0108b5fe0bad8259de0197589c6 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 11 Jun 2010 16:44:46 -0700 Subject: [SCSI] fnic: fnic_scsi.c: clean up In fnic_abort_cmd() and fnic_device_reset() assign `rport' earlier to make FNIC_SCSI_DBG() calls cleaner. In fnic_clean_pending_aborts() `rport' is not used. Signed-off-by: Roel Kluin Acked-by: Abhijeet Joglekar Signed-off-by: Andrew Morton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fnic/fnic_scsi.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 3cc47c6e1ada..198cbab3e894 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -1246,11 +1246,10 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) lp = shost_priv(sc->device->host); fnic = lport_priv(lp); - FNIC_SCSI_DBG(KERN_DEBUG, - fnic->lport->host, - "Abort Cmd called FCID 0x%x, LUN 0x%x TAG %d\n", - (starget_to_rport(scsi_target(sc->device)))->port_id, - sc->device->lun, sc->request->tag); + rport = starget_to_rport(scsi_target(sc->device)); + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, + "Abort Cmd called FCID 0x%x, LUN 0x%x TAG %d\n", + rport->port_id, sc->device->lun, sc->request->tag); if (lp->state != LPORT_ST_READY || !(lp->link_up)) { ret = FAILED; @@ -1299,7 +1298,6 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) * port is up, then send abts to the remote port to terminate * the IO. Else, just locally terminate the IO in the firmware */ - rport = starget_to_rport(scsi_target(sc->device)); if (fc_remote_port_chkready(rport) == 0) task_req = FCPIO_ITMF_ABT_TASK; else @@ -1418,7 +1416,6 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, unsigned long flags; int ret = 0; struct scsi_cmnd *sc; - struct fc_rport *rport; struct scsi_lun fc_lun; struct scsi_device *lun_dev = lr_sc->device; DECLARE_COMPLETION_ONSTACK(tm_done); @@ -1458,7 +1455,6 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, /* Now queue the abort command to firmware */ int_to_scsilun(sc->device->lun, &fc_lun); - rport = starget_to_rport(scsi_target(sc->device)); if (fnic_queue_abort_io_req(fnic, tag, FCPIO_ITMF_ABT_TASK_TERM, @@ -1528,18 +1524,16 @@ int fnic_device_reset(struct scsi_cmnd *sc) lp = shost_priv(sc->device->host); fnic = lport_priv(lp); - FNIC_SCSI_DBG(KERN_DEBUG, - fnic->lport->host, - "Device reset called FCID 0x%x, LUN 0x%x\n", - (starget_to_rport(scsi_target(sc->device)))->port_id, - sc->device->lun); + rport = starget_to_rport(scsi_target(sc->device)); + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, + "Device reset called FCID 0x%x, LUN 0x%x\n", + rport->port_id, sc->device->lun); if (lp->state != LPORT_ST_READY || !(lp->link_up)) goto fnic_device_reset_end; /* Check if remote port up */ - rport = starget_to_rport(scsi_target(sc->device)); if (fc_remote_port_chkready(rport)) goto fnic_device_reset_end; -- cgit v1.2.3 From 4b2164d4d212e437c9f080023a67f8f9356d2c4c Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 11 Jun 2010 16:44:51 -0700 Subject: [SCSI] libfc: Fix remote port restart problem This patch somewhat combines two fixes to remote port handing in libfc. The first problem was that rport work could be queued on a deleted and freed rport. This is handled by not resetting rdata->event ton NONE if the rdata is about to be deleted. However, that fix led to the second problem, described by Bhanu Gollapudi, as follows: > Here is the sequence of events. T1 is first LOGO receive thread, T2 is > fc_rport_work() scheduled by T1 and T3 is second LOGO receive thread and > T4 is fc_rport_work scheduled by T3. > > 1. (T1)Received 1st LOGO in state Ready > 2. (T1)Delete port & enter to RESTART state. > 3. (T1)schdule event_work, since event is RPORT_EV_NONE. > 4. (T1)set event = RPORT_EV_LOGO > 5. (T1)Enter RESTART state as disc_id is set. > 6. (T2)remember to PLOGI, and set event = RPORT_EV_NONE > 6. (T3)Received 2nd LOGO > 7. (T3)Delete Port & enter to RESTART state. > 8. (T3)schedule event_work, since event is RPORT_EV_NONE. > 9. (T3)Enter RESTART state as disc_id is set. > 9. (T3)set event = RPORT_EV_LOGO > 10.(T2)work restart, enter PLOGI state and issues PLOGI > 11.(T4)Since state is not RESTART anymore, restart is not set, and the > event is not reset to RPORT_EV_NONE. (current event is RPORT_EV_LOGO). > 12. Now, PLOGI succeeds and fc_rport_enter_ready() will not schedule > event_work, and hence the rport will never be created, eventually losing > the target after dev_loss_tmo. So, the problem here is that we were tracking the desire for the rport be restarted by state RESTART, which was otherwise equivalent to DELETE. A contributing factor is that we dropped the lock between steps 6 and 10 in thread T2, which allows the state to change, and we didn't completely re-evaluate then. This is hopefully corrected by the following minor redesign: Simplify the rport restart logic by making the decision to restart after deleting the transport rport. That decision is based on a new STARTED flag that indicates fc_rport_login() has been called and fc_rport_logoff() has not been called since then. This replaces the need for the RESTART state. Only restart if the rdata is still in DELETED state and only if it still has the STARTED flag set. Also now, since we clear the event code much later in the work thread, allow for the possibility that the rport may have become READY again via incoming PLOGI, and if so, queue another event to handle that. In the problem scenario, the second LOGO received will cause the LOGO event to occur again. Reported-by: Bhanu Gollapudi Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 75 ++++++++++++++++++------------------------- include/scsi/libfc.h | 5 ++- 2 files changed, 33 insertions(+), 47 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index df85e19079fb..d385efc68c15 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -89,7 +89,6 @@ static const char *fc_rport_state_names[] = { [RPORT_ST_LOGO] = "LOGO", [RPORT_ST_ADISC] = "ADISC", [RPORT_ST_DELETE] = "Delete", - [RPORT_ST_RESTART] = "Restart", }; /** @@ -246,7 +245,6 @@ static void fc_rport_work(struct work_struct *work) struct fc_rport_operations *rport_ops; struct fc_rport_identifiers ids; struct fc_rport *rport; - int restart = 0; mutex_lock(&rdata->rp_mutex); event = rdata->event; @@ -298,24 +296,6 @@ static void fc_rport_work(struct work_struct *work) port_id = rdata->ids.port_id; mutex_unlock(&rdata->rp_mutex); - if (port_id != FC_FID_DIR_SERV) { - /* - * We must drop rp_mutex before taking disc_mutex. - * Re-evaluate state to allow for restart. - * A transition to RESTART state must only happen - * while disc_mutex is held and rdata is on the list. - */ - mutex_lock(&lport->disc.disc_mutex); - mutex_lock(&rdata->rp_mutex); - if (rdata->rp_state == RPORT_ST_RESTART) - restart = 1; - else - list_del(&rdata->peers); - rdata->event = RPORT_EV_NONE; - mutex_unlock(&rdata->rp_mutex); - mutex_unlock(&lport->disc.disc_mutex); - } - if (rport_ops && rport_ops->event_callback) { FC_RPORT_DBG(rdata, "callback ev %d\n", event); rport_ops->event_callback(lport, rdata, event); @@ -336,13 +316,34 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); fc_remote_port_delete(rport); } - if (restart) { - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "work restart\n"); - fc_rport_enter_plogi(rdata); + + mutex_lock(&lport->disc.disc_mutex); + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state == RPORT_ST_DELETE) { + if (port_id == FC_FID_DIR_SERV) { + rdata->event = RPORT_EV_NONE; + mutex_unlock(&rdata->rp_mutex); + } else if (rdata->flags & FC_RP_STARTED) { + rdata->event = RPORT_EV_NONE; + FC_RPORT_DBG(rdata, "work restart\n"); + fc_rport_enter_plogi(rdata); + mutex_unlock(&rdata->rp_mutex); + } else { + FC_RPORT_DBG(rdata, "work delete\n"); + list_del(&rdata->peers); + mutex_unlock(&rdata->rp_mutex); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } + } else { + /* + * Re-open for events. Reissue READY event if ready. + */ + rdata->event = RPORT_EV_NONE; + if (rdata->rp_state == RPORT_ST_READY) + fc_rport_enter_ready(rdata); mutex_unlock(&rdata->rp_mutex); - } else - kref_put(&rdata->kref, lport->tt.rport_destroy); + } + mutex_unlock(&lport->disc.disc_mutex); break; default: @@ -367,16 +368,14 @@ int fc_rport_login(struct fc_rport_priv *rdata) { mutex_lock(&rdata->rp_mutex); + rdata->flags |= FC_RP_STARTED; switch (rdata->rp_state) { case RPORT_ST_READY: FC_RPORT_DBG(rdata, "ADISC port\n"); fc_rport_enter_adisc(rdata); break; - case RPORT_ST_RESTART: - break; case RPORT_ST_DELETE: FC_RPORT_DBG(rdata, "Restart deleted port\n"); - fc_rport_state_enter(rdata, RPORT_ST_RESTART); break; default: FC_RPORT_DBG(rdata, "Login to port\n"); @@ -431,15 +430,12 @@ int fc_rport_logoff(struct fc_rport_priv *rdata) FC_RPORT_DBG(rdata, "Remove port\n"); + rdata->flags &= ~FC_RP_STARTED; if (rdata->rp_state == RPORT_ST_DELETE) { FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); goto out; } - - if (rdata->rp_state == RPORT_ST_RESTART) - FC_RPORT_DBG(rdata, "Port in Restart state, deleting\n"); - else - fc_rport_enter_logo(rdata); + fc_rport_enter_logo(rdata); /* * Change the state to Delete so that we discard @@ -503,7 +499,6 @@ static void fc_rport_timeout(struct work_struct *work) case RPORT_ST_READY: case RPORT_ST_INIT: case RPORT_ST_DELETE: - case RPORT_ST_RESTART: break; } @@ -527,6 +522,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) switch (rdata->rp_state) { case RPORT_ST_PLOGI: case RPORT_ST_LOGO: + rdata->flags &= ~FC_RP_STARTED; fc_rport_enter_delete(rdata, RPORT_EV_FAILED); break; case RPORT_ST_RTV: @@ -537,7 +533,6 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) fc_rport_enter_logo(rdata); break; case RPORT_ST_DELETE: - case RPORT_ST_RESTART: case RPORT_ST_READY: case RPORT_ST_INIT: break; @@ -1392,7 +1387,6 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, break; case RPORT_ST_DELETE: case RPORT_ST_LOGO: - case RPORT_ST_RESTART: FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", fc_rport_state(rdata)); mutex_unlock(&rdata->rp_mutex); @@ -1684,13 +1678,6 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, fc_rport_state(rdata)); fc_rport_enter_delete(rdata, RPORT_EV_LOGO); - - /* - * If the remote port was created due to discovery, set state - * to log back in. It may have seen a stale RSCN about us. - */ - if (rdata->disc_id) - fc_rport_state_enter(rdata, RPORT_ST_RESTART); mutex_unlock(&rdata->rp_mutex); } else FC_RPORT_ID_DBG(lport, sid, diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 7495c0ba67ee..db54c4a2d14b 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -104,7 +104,6 @@ enum fc_disc_event { * @RPORT_ST_LOGO: Remote port logout (LOGO) sent * @RPORT_ST_ADISC: Discover Address sent * @RPORT_ST_DELETE: Remote port being deleted - * @RPORT_ST_RESTART: Remote port being deleted and will restart */ enum fc_rport_state { RPORT_ST_INIT, @@ -115,7 +114,6 @@ enum fc_rport_state { RPORT_ST_LOGO, RPORT_ST_ADISC, RPORT_ST_DELETE, - RPORT_ST_RESTART, }; /** @@ -173,6 +171,7 @@ struct fc_rport_libfc_priv { u16 flags; #define FC_RP_FLAGS_REC_SUPPORTED (1 << 0) #define FC_RP_FLAGS_RETRY (1 << 1) + #define FC_RP_STARTED (1 << 2) unsigned int e_d_tov; unsigned int r_a_tov; }; @@ -185,7 +184,7 @@ struct fc_rport_libfc_priv { * @rp_state: Enumeration that tracks progress of PLOGI, PRLI, * and RTV exchanges * @ids: The remote port identifiers and roles - * @flags: REC and RETRY supported flags + * @flags: STARTED, REC and RETRY_SUPPORTED flags * @max_seq: Maximum number of concurrent sequences * @disc_id: The discovery identifier * @maxframe_size: The maximum frame size -- cgit v1.2.3 From f034260db330bb3ffc815fcb682b1c84aca09591 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 11 Jun 2010 16:44:57 -0700 Subject: [SCSI] libfc: fix indefinite rport restart Remote ports were restarting indefinitely after getting rejects in PRLI. Fix by adding a counter of restarts and limiting that with the port login retry limit as well. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 6 +++++- include/scsi/libfc.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index d385efc68c15..363cde30c940 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -257,6 +257,7 @@ static void fc_rport_work(struct work_struct *work) case RPORT_EV_READY: ids = rdata->ids; rdata->event = RPORT_EV_NONE; + rdata->major_retries = 0; kref_get(&rdata->kref); mutex_unlock(&rdata->rp_mutex); @@ -323,7 +324,10 @@ static void fc_rport_work(struct work_struct *work) if (port_id == FC_FID_DIR_SERV) { rdata->event = RPORT_EV_NONE; mutex_unlock(&rdata->rp_mutex); - } else if (rdata->flags & FC_RP_STARTED) { + } else if ((rdata->flags & FC_RP_STARTED) && + rdata->major_retries < + lport->max_rport_retry_count) { + rdata->major_retries++; rdata->event = RPORT_EV_NONE; FC_RPORT_DBG(rdata, "work restart\n"); fc_rport_enter_plogi(rdata); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index db54c4a2d14b..6d78df77dab6 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -189,6 +189,7 @@ struct fc_rport_libfc_priv { * @disc_id: The discovery identifier * @maxframe_size: The maximum frame size * @retries: The retry count for the current state + * @major_retries: The retry count for the entire PLOGI/PRLI state machine * @e_d_tov: Error detect timeout value (in msec) * @r_a_tov: Resource allocation timeout value (in msec) * @rp_mutex: The mutex that protects the remote port @@ -206,6 +207,7 @@ struct fc_rport_priv { u16 disc_id; u16 maxframe_size; unsigned int retries; + unsigned int major_retries; unsigned int e_d_tov; unsigned int r_a_tov; struct mutex rp_mutex; -- cgit v1.2.3 From ae52e7f09ff509df11cd408eabe90132b6be1231 Mon Sep 17 00:00:00 2001 From: Nick Cheng Date: Fri, 18 Jun 2010 15:39:12 +0800 Subject: [SCSI] arcmsr: Support 1024 scatter-gather list entries and improve AP while FW trapped and behaviors of EHs 1. To support 4M/1024 scatter-gather list entry, reorganize struct ARCMSR_CDB and struct CommandControlBlock 2. To modify arcmsr_probe 3. In order to help fix F/W issue, add the driver mode for type B card 4. To improve AP's behavior while F/W resets 5. To unify struct MessageUnit_B's members' naming in all OS drivers' 6. To improve error handlers, arcmsr_bus_reset(), arcmsr_abort() 7. To fix the arcmsr_queue_command() in bus reset stage, just let the commands pass down to FW, don't block Signed-off-by: Nick Cheng Signed-off-by: James Bottomley --- drivers/scsi/arcmsr/arcmsr.h | 135 ++--- drivers/scsi/arcmsr/arcmsr_hba.c | 1225 +++++++++++++++++++------------------- 2 files changed, 677 insertions(+), 683 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index ce5371b3cdd5..c0861c05cd49 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -48,16 +48,22 @@ struct device_attribute; /*The limit of outstanding scsi command that firmware can handle*/ #define ARCMSR_MAX_OUTSTANDING_CMD 256 #define ARCMSR_MAX_FREECCB_NUM 320 -#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2008/11/03" +#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2009/12/09" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 +#define ARCMSR_MAX_XFER_SECTORS_C 304 #define ARCMSR_MAX_TARGETID 17 #define ARCMSR_MAX_TARGETLUN 8 #define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD #define ARCMSR_MAX_QBUFFER 4096 -#define ARCMSR_MAX_SG_ENTRIES 38 +#define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 +#define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#ifndef PCI_DEVICE_ID_ARECA_1880 +#define PCI_DEVICE_ID_ARECA_1880 0x1880 + #endif /* ********************************************************************************** ** @@ -141,26 +147,19 @@ struct CMD_MESSAGE_FIELD ** structure for holding DMA address data ************************************************************* */ +#define IS_DMA64 (sizeof(dma_addr_t) == 8) #define IS_SG64_ADDR 0x01000000 /* bit24 */ struct SG32ENTRY { __le32 length; __le32 address; -}; +} __attribute__ ((packed)); struct SG64ENTRY { __le32 length; __le32 address; __le32 addresshigh; -}; -struct SGENTRY_UNION -{ - union - { - struct SG32ENTRY sg32entry; - struct SG64ENTRY sg64entry; - }u; -}; +} __attribute__ ((packed)); /* ******************************************************************** ** Q Buffer of IOP Message Transfer @@ -187,6 +186,9 @@ struct FIRMWARE_INFO char model[8]; /*15, 60-67*/ char firmware_ver[16]; /*17, 68-83*/ char device_map[16]; /*21, 84-99*/ + uint32_t cfgVersion; /*25,100-103 Added for checking of new firmware capability*/ + uint8_t cfgSerial[16]; /*26,104-119*/ + uint32_t cfgPicStatus; /*30,120-123*/ }; /* signature of set and get firmware config */ #define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 @@ -213,6 +215,8 @@ struct FIRMWARE_INFO #define ARCMSR_CCBREPLY_FLAG_ERROR 0x10000000 /* outbound firmware ok */ #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 +/* ARC-1680 Bus Reset*/ +#define ARCMSR_ARC1680_BUS_RESET 0x00000003 /* ************************************************************************ @@ -264,11 +268,11 @@ struct FIRMWARE_INFO /* data tunnel buffer between user space program and its firmware */ /* user space data to iop 128bytes */ -#define ARCMSR_IOCTL_WBUFFER 0x0000fe00 +#define ARCMSR_MESSAGE_WBUFFER 0x0000fe00 /* iop data to user space 128bytes */ -#define ARCMSR_IOCTL_RBUFFER 0x0000ff00 +#define ARCMSR_MESSAGE_RBUFFER 0x0000ff00 /* iop message_rwbuffer for message command */ -#define ARCMSR_MSGCODE_RWBUFFER 0x0000fa00 +#define ARCMSR_MESSAGE_RWBUFFER 0x0000fa00 /* ******************************************************************************* ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) @@ -290,7 +294,7 @@ struct ARCMSR_CDB #define ARCMSR_CDB_FLAG_HEADQ 0x08 #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 - uint8_t Reserved1; + uint8_t msgPages; uint32_t Context; uint32_t DataLength; uint8_t Cdb[16]; @@ -303,10 +307,10 @@ struct ARCMSR_CDB uint8_t SenseData[15]; union { - struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; - struct SG64ENTRY sg64entry[ARCMSR_MAX_SG_ENTRIES]; + struct SG32ENTRY sg32entry[1]; + struct SG64ENTRY sg64entry[1]; } u; -}; +} __attribute__ ((packed)); /* ******************************************************************************* ** Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor @@ -344,13 +348,13 @@ struct MessageUnit_B uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; uint32_t postq_index; uint32_t doneq_index; - uint32_t __iomem *drv2iop_doorbell_reg; - uint32_t __iomem *drv2iop_doorbell_mask_reg; - uint32_t __iomem *iop2drv_doorbell_reg; - uint32_t __iomem *iop2drv_doorbell_mask_reg; - uint32_t __iomem *msgcode_rwbuffer_reg; - uint32_t __iomem *ioctl_wbuffer_reg; - uint32_t __iomem *ioctl_rbuffer_reg; + uint32_t __iomem *drv2iop_doorbell; + uint32_t __iomem *drv2iop_doorbell_mask; + uint32_t __iomem *iop2drv_doorbell; + uint32_t __iomem *iop2drv_doorbell_mask; + uint32_t __iomem *message_rwbuffer; + uint32_t __iomem *message_wbuffer; + uint32_t __iomem *message_rbuffer; }; /* @@ -370,14 +374,17 @@ struct AdapterControlBlock unsigned long vir2phy_offset; /* Offset is used in making arc cdb physical to virtual calculations */ uint32_t outbound_int_enable; - + spinlock_t eh_lock; + spinlock_t ccblist_lock; union { struct MessageUnit_A __iomem * pmuA; struct MessageUnit_B * pmuB; }; /* message unit ATU inbound base address0 */ - + void __iomem *mem_base0; + void __iomem *mem_base1; uint32_t acb_flags; + u16 dev_id; uint8_t adapter_index; #define ACB_F_SCSISTOPADAPTER 0x0001 #define ACB_F_MSG_STOP_BGRB 0x0002 @@ -394,6 +401,7 @@ struct AdapterControlBlock #define ACB_F_BUS_RESET 0x0080 #define ACB_F_IOP_INITED 0x0100 /* iop init */ + #define ACB_F_ABORT 0x0200 #define ACB_F_FIRMWARE_TRAP 0x0400 struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; /* used for memory free */ @@ -408,7 +416,8 @@ struct AdapterControlBlock /* dma_coherent used for memory free */ dma_addr_t dma_coherent_handle; /* dma_coherent_handle used for memory free */ - + dma_addr_t dma_coherent_handle_hbb_mu; + unsigned int uncache_size; uint8_t rqbuffer[ARCMSR_MAX_QBUFFER]; /* data collection buffer for read from 80331 */ int32_t rqbuf_firstindex; @@ -432,14 +441,18 @@ struct AdapterControlBlock uint32_t firm_numbers_queue; uint32_t firm_sdram_size; uint32_t firm_hd_channels; + uint32_t firm_cfg_version; char firm_model[12]; char firm_version[20]; char device_map[20]; /*21,84-99*/ struct work_struct arcmsr_do_message_isr_bh; struct timer_list eternal_timer; - unsigned short fw_state; + unsigned short fw_flag; + #define FW_NORMAL 0x0000 + #define FW_BOG 0x0001 + #define FW_DEADLOCK 0x0010 atomic_t rq_map_token; - int ante_token_value; + atomic_t ante_token_value; };/* HW_DEVICE_EXTENSION */ /* ******************************************************************************* @@ -449,65 +462,31 @@ struct AdapterControlBlock */ struct CommandControlBlock { - struct ARCMSR_CDB arcmsr_cdb; - /* - ** 0-503 (size of CDB = 504): - ** arcmsr messenger scsi command descriptor size 504 bytes - */ - uint32_t cdb_shifted_phyaddr; - /* 504-507 */ - uint32_t reserved1; - /* 508-511 */ -#if BITS_PER_LONG == 64 - /* ======================512+64 bytes======================== */ - struct list_head list; - /* 512-527 16 bytes next/prev ptrs for ccb lists */ - struct scsi_cmnd * pcmd; - /* 528-535 8 bytes pointer of linux scsi command */ - struct AdapterControlBlock * acb; - /* 536-543 8 bytes pointer of acb */ - - uint16_t ccb_flags; - /* 544-545 */ + /*x32:sizeof struct_CCB=(32+60)byte, x64:sizeof struct_CCB=(64+60)byte*/ + struct list_head list; /*x32: 8byte, x64: 16byte*/ + struct scsi_cmnd *pcmd; /*8 bytes pointer of linux scsi command */ + struct AdapterControlBlock *acb; /*x32: 4byte, x64: 8byte*/ + uint32_t shifted_cdb_phyaddr; /*x32: 4byte, x64: 4byte*/ + uint16_t ccb_flags; /*x32: 2byte, x64: 2byte*/ #define CCB_FLAG_READ 0x0000 #define CCB_FLAG_WRITE 0x0001 #define CCB_FLAG_ERROR 0x0002 #define CCB_FLAG_FLUSHCACHE 0x0004 #define CCB_FLAG_MASTER_ABORTED 0x0008 - uint16_t startdone; - /* 546-547 */ + uint16_t startdone; /*x32:2byte,x32:2byte*/ #define ARCMSR_CCB_DONE 0x0000 #define ARCMSR_CCB_START 0x55AA #define ARCMSR_CCB_ABORTED 0xAA55 #define ARCMSR_CCB_ILLEGAL 0xFFFF - uint32_t reserved2[7]; - /* 548-551 552-555 556-559 560-563 564-567 568-571 572-575 */ + #if BITS_PER_LONG == 64 + /* ======================512+64 bytes======================== */ + uint32_t reserved[6]; /*24 byte*/ #else /* ======================512+32 bytes======================== */ - struct list_head list; - /* 512-519 8 bytes next/prev ptrs for ccb lists */ - struct scsi_cmnd * pcmd; - /* 520-523 4 bytes pointer of linux scsi command */ - struct AdapterControlBlock * acb; - /* 524-527 4 bytes pointer of acb */ - - uint16_t ccb_flags; - /* 528-529 */ - #define CCB_FLAG_READ 0x0000 - #define CCB_FLAG_WRITE 0x0001 - #define CCB_FLAG_ERROR 0x0002 - #define CCB_FLAG_FLUSHCACHE 0x0004 - #define CCB_FLAG_MASTER_ABORTED 0x0008 - uint16_t startdone; - /* 530-531 */ - #define ARCMSR_CCB_DONE 0x0000 - #define ARCMSR_CCB_START 0x55AA - #define ARCMSR_CCB_ABORTED 0xAA55 - #define ARCMSR_CCB_ILLEGAL 0xFFFF - uint32_t reserved2[3]; - /* 532-535 536-539 540-543 */ + uint32_t reserved[2]; /*8 byte*/ #endif - /* ========================================================== */ + /* ======================================================= */ + struct ARCMSR_CDB arcmsr_cdb; }; /* ******************************************************************************* diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index ffa54792bb33..ba33473b27a1 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -58,7 +58,6 @@ #include #include #include -#include #include #include #include @@ -71,20 +70,13 @@ #include #include #include "arcmsr.h" - -#ifdef CONFIG_SCSI_ARCMSR_RESET - static int sleeptime = 20; - static int retrycount = 12; - module_param(sleeptime, int, S_IRUGO|S_IWUSR); - MODULE_PARM_DESC(sleeptime, "The waiting period for FW ready while bus reset"); - module_param(retrycount, int, S_IRUGO|S_IWUSR); - MODULE_PARM_DESC(retrycount, "The retry count for FW ready while bus reset"); -#endif -MODULE_AUTHOR("Erich Chen "); -MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Bus Adapter"); +MODULE_AUTHOR("Nick Cheng "); +MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx) SATA/SAS RAID Host Bus Adapter"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(ARCMSR_DRIVER_VERSION); - +static int sleeptime = 20; +static int retrycount = 12; +wait_queue_head_t wait_q; static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd); static int arcmsr_iop_confirm(struct AdapterControlBlock *acb); @@ -108,7 +100,7 @@ static void arcmsr_request_device_map(unsigned long pacb); static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb); static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb); static void arcmsr_message_isr_bh_fn(struct work_struct *work); -static void *arcmsr_get_firmware_spec(struct AdapterControlBlock *acb, int mode); +static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb); static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); static const char *arcmsr_info(struct Scsi_Host *); @@ -135,10 +127,10 @@ static struct scsi_host_template arcmsr_scsi_host_template = { .eh_bus_reset_handler = arcmsr_bus_reset, .bios_param = arcmsr_bios_param, .change_queue_depth = arcmsr_adjust_disk_queue_depth, - .can_queue = ARCMSR_MAX_OUTSTANDING_CMD, + .can_queue = ARCMSR_MAX_FREECCB_NUM, .this_id = ARCMSR_SCSI_INITIATOR_ID, - .sg_tablesize = ARCMSR_MAX_SG_ENTRIES, - .max_sectors = ARCMSR_MAX_XFER_SECTORS, + .sg_tablesize = ARCMSR_DEFAULT_SG_ENTRIES, + .max_sectors = ARCMSR_MAX_XFER_SECTORS_C, .cmd_per_lun = ARCMSR_MAX_CMD_PERLUN, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = arcmsr_host_attrs, @@ -162,6 +154,7 @@ static struct pci_device_id arcmsr_device_id_table[] = { {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1381)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1680)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1681)}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1880)}, {0, 0}, /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, arcmsr_device_id_table); @@ -173,15 +166,72 @@ static struct pci_driver arcmsr_pci_driver = { .shutdown = arcmsr_shutdown, }; +static void arcmsr_free_mu(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: + break; + case ACB_ADAPTER_TYPE_B:{ + struct MessageUnit_B *reg = acb->pmuB; + dma_free_coherent(&acb->pdev->dev, + sizeof(struct MessageUnit_B), + reg, acb->dma_coherent_handle_hbb_mu); + } + } +} + +static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb) +{ + struct pci_dev *pdev = acb->pdev; + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A:{ + acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!acb->pmuA) { + printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); + return false; + } + break; + } + case ACB_ADAPTER_TYPE_B:{ + void __iomem *mem_base0, *mem_base1; + mem_base0 = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!mem_base0) { + printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); + return false; + } + mem_base1 = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); + if (!mem_base1) { + iounmap(mem_base0); + printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); + return false; + } + acb->mem_base0 = mem_base0; + acb->mem_base1 = mem_base1; + } + } + return true; +} + +static void arcmsr_unmap_pciregion(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A:{ + iounmap(acb->pmuA); + } + case ACB_ADAPTER_TYPE_B:{ + iounmap(acb->mem_base0); + iounmap(acb->mem_base1); + } + } +} + static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) { irqreturn_t handle_state; struct AdapterControlBlock *acb = dev_id; - spin_lock(acb->host->host_lock); handle_state = arcmsr_interrupt(acb); - spin_unlock(acb->host->host_lock); - return handle_state; } @@ -218,6 +268,7 @@ static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb) struct pci_dev *pdev = acb->pdev; u16 dev_id; pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id); + acb->dev_id = dev_id; switch (dev_id) { case 0x1201 : { acb->adapter_type = ACB_ADAPTER_TYPE_B; @@ -228,141 +279,210 @@ static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb) } } -static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) +static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = acb->pmuA; + uint32_t Index; + uint8_t Retries = 0x00; + + do { + for (Index = 0; Index < 100; Index++) { + if (readl(®->outbound_intstatus) & + ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { + writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, + ®->outbound_intstatus); + return 0x00; + } + msleep(10); + } /*max 1 seconds*/ + + } while (Retries++ < 20);/*max 20 sec*/ + return 0xff; +} + +static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) { + struct MessageUnit_B *reg = acb->pmuB; + uint32_t Index; + uint8_t Retries = 0x00; + do { + for (Index = 0; Index < 100; Index++) { + if (readl(reg->iop2drv_doorbell) + & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { + writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN + , reg->iop2drv_doorbell); + writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); + return 0x00; + } + msleep(10); + } /*max 1 seconds*/ + + } while (Retries++ < 20);/*max 20 sec*/ + return 0xff; +} + +static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = acb->pmuA; + int retry_count = 30; + + writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); + do { + if (!arcmsr_hba_wait_msgint_ready(acb)) + break; + else { + retry_count--; + printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ + timeout, retry count down = %d \n", acb->host->host_no, retry_count); + } + } while (retry_count != 0); +} + +static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = acb->pmuB; + int retry_count = 30; + + writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell); + do { + if (!arcmsr_hbb_wait_msgint_ready(acb)) + break; + else { + retry_count--; + printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ + timeout,retry count down = %d \n", acb->host->host_no, retry_count); + } + } while (retry_count != 0); +} + +static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) +{ switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - struct pci_dev *pdev = acb->pdev; - void *dma_coherent; - dma_addr_t dma_coherent_handle, dma_addr; - struct CommandControlBlock *ccb_tmp; - int i, j; + arcmsr_flush_hba_cache(acb); + } + break; - acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - if (!acb->pmuA) { - printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", - acb->host->host_no); - return -ENOMEM; + case ACB_ADAPTER_TYPE_B: { + arcmsr_flush_hbb_cache(acb); } + } +} - dma_coherent = dma_alloc_coherent(&pdev->dev, - ARCMSR_MAX_FREECCB_NUM * - sizeof (struct CommandControlBlock) + 0x20, - &dma_coherent_handle, GFP_KERNEL); +static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) +{ + struct pci_dev *pdev = acb->pdev; + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + void *dma_coherent; + dma_addr_t dma_coherent_handle; + struct CommandControlBlock *ccb_tmp; + int i = 0, j = 0; + dma_addr_t cdb_phyaddr; + unsigned long roundup_ccbsize = 0; + unsigned long max_xfer_len; + unsigned long max_sg_entrys; + uint32_t firm_config_version; + + for (i = 0; i < ARCMSR_MAX_TARGETID; i++) + for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) + acb->devstate[i][j] = ARECA_RAID_GONE; + + max_xfer_len = ARCMSR_MAX_XFER_LEN; + max_sg_entrys = ARCMSR_DEFAULT_SG_ENTRIES; + firm_config_version = acb->firm_cfg_version; + if ((firm_config_version & 0xFF) >= 3) { + max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH << ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 16M byte */ + max_sg_entrys = (max_xfer_len/4096); + } + acb->host->max_sectors = max_xfer_len/512; + acb->host->sg_tablesize = max_sg_entrys; + roundup_ccbsize = roundup(sizeof(struct CommandControlBlock) + max_sg_entrys * sizeof(struct SG64ENTRY), 32); + acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM; + dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size, &dma_coherent_handle, GFP_KERNEL); if (!dma_coherent) { - iounmap(acb->pmuA); + printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error \n", acb->host->host_no); return -ENOMEM; } - + memset(dma_coherent, 0, acb->uncache_size); acb->dma_coherent = dma_coherent; acb->dma_coherent_handle = dma_coherent_handle; - - if (((unsigned long)dma_coherent & 0x1F)) { - dma_coherent = dma_coherent + - (0x20 - ((unsigned long)dma_coherent & 0x1F)); - dma_coherent_handle = dma_coherent_handle + - (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); - } - - dma_addr = dma_coherent_handle; ccb_tmp = (struct CommandControlBlock *)dma_coherent; + acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle; for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; - ccb_tmp->acb = acb; + cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb); + ccb_tmp->shifted_cdb_phyaddr = cdb_phyaddr >> 5; acb->pccb_pool[i] = ccb_tmp; + ccb_tmp->acb = acb; + INIT_LIST_HEAD(&ccb_tmp->list); list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); - dma_addr = dma_addr + sizeof(struct CommandControlBlock); - ccb_tmp++; - } - - acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; - for (i = 0; i < ARCMSR_MAX_TARGETID; i++) - for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) - acb->devstate[i][j] = ARECA_RAID_GONE; + ccb_tmp = (struct CommandControlBlock *)((unsigned long)ccb_tmp + roundup_ccbsize); + dma_coherent_handle = dma_coherent_handle + roundup_ccbsize; } break; - + } case ACB_ADAPTER_TYPE_B: { - struct pci_dev *pdev = acb->pdev; - struct MessageUnit_B *reg; - void __iomem *mem_base0, *mem_base1; void *dma_coherent; - dma_addr_t dma_coherent_handle, dma_addr; + dma_addr_t dma_coherent_handle; struct CommandControlBlock *ccb_tmp; - int i, j; - - dma_coherent = dma_alloc_coherent(&pdev->dev, - ((ARCMSR_MAX_FREECCB_NUM * - sizeof(struct CommandControlBlock) + 0x20) + - sizeof(struct MessageUnit_B)), + uint32_t cdb_phyaddr; + unsigned int roundup_ccbsize = 0; + unsigned long max_xfer_len; + unsigned long max_sg_entrys; + unsigned long firm_config_version; + unsigned long max_freeccb_num = 0; + int i = 0, j = 0; + + max_freeccb_num = ARCMSR_MAX_FREECCB_NUM; + max_xfer_len = ARCMSR_MAX_XFER_LEN; + max_sg_entrys = ARCMSR_DEFAULT_SG_ENTRIES; + firm_config_version = acb->firm_cfg_version; + if ((firm_config_version & 0xFF) >= 3) { + max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH << + ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 16M byte */ + max_sg_entrys = (max_xfer_len/4096);/* max 4097 sg entry*/ + } + acb->host->max_sectors = max_xfer_len / 512; + acb->host->sg_tablesize = max_sg_entrys; + roundup_ccbsize = roundup(sizeof(struct CommandControlBlock)+ + (max_sg_entrys - 1) * sizeof(struct SG64ENTRY), 32); + acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM; + dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size, &dma_coherent_handle, GFP_KERNEL); - if (!dma_coherent) - return -ENOMEM; + if (!dma_coherent) { + printk(KERN_NOTICE "DMA allocation failed...........................\n"); + return -ENOMEM; + } + memset(dma_coherent, 0, acb->uncache_size); acb->dma_coherent = dma_coherent; acb->dma_coherent_handle = dma_coherent_handle; - - if (((unsigned long)dma_coherent & 0x1F)) { - dma_coherent = dma_coherent + - (0x20 - ((unsigned long)dma_coherent & 0x1F)); - dma_coherent_handle = dma_coherent_handle + - (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); - } - - dma_addr = dma_coherent_handle; ccb_tmp = (struct CommandControlBlock *)dma_coherent; + acb->vir2phy_offset = (unsigned long)dma_coherent - + (unsigned long)dma_coherent_handle; for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; - ccb_tmp->acb = acb; + cdb_phyaddr = dma_coherent_handle + + offsetof(struct CommandControlBlock, arcmsr_cdb); + ccb_tmp->shifted_cdb_phyaddr = cdb_phyaddr >> 5; acb->pccb_pool[i] = ccb_tmp; + ccb_tmp->acb = acb; + INIT_LIST_HEAD(&ccb_tmp->list); list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); - dma_addr = dma_addr + sizeof(struct CommandControlBlock); - ccb_tmp++; - } - - reg = (struct MessageUnit_B *)(dma_coherent + - ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); - acb->pmuB = reg; - mem_base0 = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - if (!mem_base0) - goto out; - - mem_base1 = ioremap(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); - if (!mem_base1) { - iounmap(mem_base0); - goto out; + ccb_tmp = (struct CommandControlBlock *)((unsigned long)ccb_tmp + + roundup_ccbsize); + dma_coherent_handle = dma_coherent_handle + roundup_ccbsize; } - - reg->drv2iop_doorbell_reg = mem_base0 + ARCMSR_DRV2IOP_DOORBELL; - reg->drv2iop_doorbell_mask_reg = mem_base0 + - ARCMSR_DRV2IOP_DOORBELL_MASK; - reg->iop2drv_doorbell_reg = mem_base0 + ARCMSR_IOP2DRV_DOORBELL; - reg->iop2drv_doorbell_mask_reg = mem_base0 + - ARCMSR_IOP2DRV_DOORBELL_MASK; - reg->ioctl_wbuffer_reg = mem_base1 + ARCMSR_IOCTL_WBUFFER; - reg->ioctl_rbuffer_reg = mem_base1 + ARCMSR_IOCTL_RBUFFER; - reg->msgcode_rwbuffer_reg = mem_base1 + ARCMSR_MSGCODE_RWBUFFER; - - acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; for (i = 0; i < ARCMSR_MAX_TARGETID; i++) for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) - acb->devstate[i][j] = ARECA_RAID_GOOD; + acb->devstate[i][j] = ARECA_RAID_GONE; } break; } return 0; - -out: - dma_free_coherent(&acb->pdev->dev, - (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + - sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); - return -ENOMEM; } static void arcmsr_message_isr_bh_fn(struct work_struct *work) { @@ -411,8 +531,8 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; char *acb_dev_map = (char *)acb->device_map; - uint32_t __iomem *signature = (uint32_t __iomem *)(®->msgcode_rwbuffer_reg[0]); - char __iomem *devicemap = (char __iomem *)(®->msgcode_rwbuffer_reg[21]); + uint32_t __iomem *signature = (uint32_t __iomem *)(®->message_rwbuffer[0]); + char __iomem *devicemap = (char __iomem *)(®->message_rwbuffer[21]); int target, lun; struct scsi_device *psdev; char diff; @@ -447,8 +567,7 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work) } } -static int arcmsr_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct Scsi_Host *host; struct AdapterControlBlock *acb; @@ -456,19 +575,13 @@ static int arcmsr_probe(struct pci_dev *pdev, int error; error = pci_enable_device(pdev); - if (error) - goto out; - pci_set_master(pdev); - - host = scsi_host_alloc(&arcmsr_scsi_host_template, - sizeof(struct AdapterControlBlock)); + if (error) { + return -ENODEV; + } + host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof(struct AdapterControlBlock)); if (!host) { - error = -ENOMEM; - goto out_disable_device; + goto pci_disable_dev; } - acb = (struct AdapterControlBlock *)host->hostdata; - memset(acb, 0, sizeof (struct AdapterControlBlock)); - error = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (error) { error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); @@ -476,126 +589,90 @@ static int arcmsr_probe(struct pci_dev *pdev, printk(KERN_WARNING "scsi%d: No suitable DMA mask available\n", host->host_no); - goto out_host_put; + goto scsi_host_release; } } + init_waitqueue_head(&wait_q); bus = pdev->bus->number; dev_fun = pdev->devfn; - acb->host = host; + acb = (struct AdapterControlBlock *) host->hostdata; + memset(acb, 0, sizeof(struct AdapterControlBlock)); acb->pdev = pdev; - host->max_sectors = ARCMSR_MAX_XFER_SECTORS; + acb->host = host; host->max_lun = ARCMSR_MAX_TARGETLUN; host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/ host->max_cmd_len = 16; /*this is issue of 64bit LBA, over 2T byte*/ - host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES; host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; host->this_id = ARCMSR_SCSI_INITIATOR_ID; host->unique_id = (bus << 8) | dev_fun; - host->irq = pdev->irq; + pci_set_drvdata(pdev, host); + pci_set_master(pdev); error = pci_request_regions(pdev, "arcmsr"); if (error) { - goto out_host_put; + goto scsi_host_release; } - arcmsr_define_adapter_type(acb); - + spin_lock_init(&acb->eh_lock); + spin_lock_init(&acb->ccblist_lock); acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; INIT_LIST_HEAD(&acb->ccb_free_list); - INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn); + arcmsr_define_adapter_type(acb); + error = arcmsr_remap_pciregion(acb); + if (!error) { + goto pci_release_regs; + } + error = arcmsr_get_firmware_spec(acb); + if (!error) { + goto unmap_pci_region; + } error = arcmsr_alloc_ccb_pool(acb); - if (error) - goto out_release_regions; - + if (error) { + goto free_hbb_mu; + } arcmsr_iop_init(acb); - error = request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_SHARED, "arcmsr", acb); - if (error) - goto out_free_ccb_pool; - - pci_set_drvdata(pdev, host); - if (strncmp(acb->firm_version, "V1.42", 5) >= 0) - host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B; - error = scsi_add_host(host, &pdev->dev); - if (error) - goto out_free_irq; - - error = arcmsr_alloc_sysfs_attr(acb); - if (error) - goto out_free_sysfs; - + if (error) { + goto RAID_controller_stop; + } + error = request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb); + if (error) { + goto scsi_host_remove; + } + host->irq = pdev->irq; scsi_scan_host(host); - #ifdef CONFIG_SCSI_ARCMSR_AER - pci_enable_pcie_error_reporting(pdev); - #endif + INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn); atomic_set(&acb->rq_map_token, 16); - acb->fw_state = true; + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; init_timer(&acb->eternal_timer); - acb->eternal_timer.expires = jiffies + msecs_to_jiffies(10*HZ); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ); acb->eternal_timer.data = (unsigned long) acb; acb->eternal_timer.function = &arcmsr_request_device_map; add_timer(&acb->eternal_timer); - + if (arcmsr_alloc_sysfs_attr(acb)) + goto out_free_sysfs; return 0; out_free_sysfs: - out_free_irq: - free_irq(pdev->irq, acb); - out_free_ccb_pool: +scsi_host_remove: + scsi_remove_host(host); +RAID_controller_stop: + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); arcmsr_free_ccb_pool(acb); - out_release_regions: +free_hbb_mu: + arcmsr_free_mu(acb); +unmap_pci_region: + arcmsr_unmap_pciregion(acb); +pci_release_regs: pci_release_regions(pdev); - out_host_put: +scsi_host_release: scsi_host_put(host); - out_disable_device: +pci_disable_dev: pci_disable_device(pdev); - out: - return error; -} - -static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) -{ - struct MessageUnit_A __iomem *reg = acb->pmuA; - uint32_t Index; - uint8_t Retries = 0x00; - - do { - for (Index = 0; Index < 100; Index++) { - if (readl(®->outbound_intstatus) & - ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { - writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, - ®->outbound_intstatus); - return 0x00; - } - msleep(10); - }/*max 1 seconds*/ - - } while (Retries++ < 20);/*max 20 sec*/ - return 0xff; -} - -static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) -{ - struct MessageUnit_B *reg = acb->pmuB; - uint32_t Index; - uint8_t Retries = 0x00; - - do { - for (Index = 0; Index < 100; Index++) { - if (readl(reg->iop2drv_doorbell_reg) - & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { - writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN - , reg->iop2drv_doorbell_reg); - writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); - return 0x00; - } - msleep(10); - }/*max 1 seconds*/ - - } while (Retries++ < 20);/*max 20 sec*/ - return 0xff; + return -ENODEV; } static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) @@ -616,7 +693,7 @@ static uint8_t arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) { struct MessageUnit_B *reg = acb->pmuB; - writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); + writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell); if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'abort all outstanding command' timeout \n" @@ -642,76 +719,41 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) return rtnval; } +static bool arcmsr_hbb_enable_driver_mode(struct AdapterControlBlock *pacb) +{ + struct MessageUnit_B *reg = pacb->pmuB; + + writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell); + if (arcmsr_hbb_wait_msgint_ready(pacb)) { + printk(KERN_ERR "arcmsr%d: can't set driver mode. \n", pacb->host->host_no); + return false; +} + return true; +} + static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) { struct scsi_cmnd *pcmd = ccb->pcmd; scsi_dma_unmap(pcmd); -} + } -static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) +static void arcmsr_ccb_complete(struct CommandControlBlock *ccb) { struct AdapterControlBlock *acb = ccb->acb; struct scsi_cmnd *pcmd = ccb->pcmd; + unsigned long flags; + atomic_dec(&acb->ccboutstandingcount); arcmsr_pci_unmap_dma(ccb); - if (stand_flag == 1) - atomic_dec(&acb->ccboutstandingcount); ccb->startdone = ARCMSR_CCB_DONE; ccb->ccb_flags = 0; + spin_lock_irqsave(&acb->ccblist_lock, flags); list_add_tail(&ccb->list, &acb->ccb_free_list); + spin_unlock_irqrestore(&acb->ccblist_lock, flags); pcmd->scsi_done(pcmd); } -static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) -{ - struct MessageUnit_A __iomem *reg = acb->pmuA; - int retry_count = 30; - - writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); - do { - if (!arcmsr_hba_wait_msgint_ready(acb)) - break; - else { - retry_count--; - printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ - timeout, retry count down = %d \n", acb->host->host_no, retry_count); - } - } while (retry_count != 0); -} - -static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) -{ - struct MessageUnit_B *reg = acb->pmuB; - int retry_count = 30; - - writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg); - do { - if (!arcmsr_hbb_wait_msgint_ready(acb)) - break; - else { - retry_count--; - printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ - timeout,retry count down = %d \n", acb->host->host_no, retry_count); - } - } while (retry_count != 0); -} - -static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) -{ - switch (acb->adapter_type) { - - case ACB_ADAPTER_TYPE_A: { - arcmsr_flush_hba_cache(acb); - } - break; - - case ACB_ADAPTER_TYPE_B: { - arcmsr_flush_hbb_cache(acb); - } - } -} - static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) { @@ -745,15 +787,15 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B : { struct MessageUnit_B *reg = acb->pmuB; - orig_mask = readl(reg->iop2drv_doorbell_mask_reg); - writel(0, reg->iop2drv_doorbell_mask_reg); + orig_mask = readl(reg->iop2drv_doorbell_mask); + writel(0, reg->iop2drv_doorbell_mask); } break; } return orig_mask; } -static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, \ +static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb, uint32_t flag_ccb) { @@ -764,13 +806,13 @@ static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, \ if (acb->devstate[id][lun] == ARECA_RAID_GONE) acb->devstate[id][lun] = ARECA_RAID_GOOD; ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); } else { switch (ccb->arcmsr_cdb.DeviceStatus) { case ARCMSR_DEV_SELECT_TIMEOUT: { acb->devstate[id][lun] = ARECA_RAID_GONE; ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); } break; @@ -779,14 +821,14 @@ static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, \ case ARCMSR_DEV_INIT_FAIL: { acb->devstate[id][lun] = ARECA_RAID_GONE; ccb->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); } break; case ARCMSR_DEV_CHECK_CONDITION: { acb->devstate[id][lun] = ARECA_RAID_GOOD; arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); } break; @@ -801,7 +843,7 @@ static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, \ , ccb->arcmsr_cdb.DeviceStatus); acb->devstate[id][lun] = ARECA_RAID_GONE; ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); break; } } @@ -811,14 +853,19 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t fla { struct CommandControlBlock *ccb; + struct ARCMSR_CDB *arcmsr_cdb; + int id, lun; - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5)); + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5)); + ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { if (ccb->startdone == ARCMSR_CCB_ABORTED) { struct scsi_cmnd *abortcmd = ccb->pcmd; if (abortcmd) { + id = abortcmd->device->id; + lun = abortcmd->device->lun; abortcmd->result |= DID_ABORT << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); printk(KERN_NOTICE "arcmsr%d: ccb ='0x%p' \ isr got aborted command \n", acb->host->host_no, ccb); } @@ -883,6 +930,7 @@ static void arcmsr_remove(struct pci_dev *pdev) int poll_count = 0; arcmsr_free_sysfs_attr(acb); scsi_remove_host(host); + scsi_host_put(host); flush_scheduled_work(); del_timer_sync(&acb->eternal_timer); arcmsr_disable_outbound_ints(acb); @@ -908,17 +956,14 @@ static void arcmsr_remove(struct pci_dev *pdev) if (ccb->startdone == ARCMSR_CCB_START) { ccb->startdone = ARCMSR_CCB_ABORTED; ccb->pcmd->result = DID_ABORT << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); } } } - free_irq(pdev->irq, acb); arcmsr_free_ccb_pool(acb); + arcmsr_free_mu(acb); pci_release_regions(pdev); - - scsi_host_put(host); - pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } @@ -973,7 +1018,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE | ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); - writel(mask, reg->iop2drv_doorbell_mask_reg); + writel(mask, reg->iop2drv_doorbell_mask); acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; } } @@ -986,6 +1031,9 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb, int8_t *psge = (int8_t *)&arcmsr_cdb->u; __le32 address_lo, address_hi; int arccdbsize = 0x30; + __le32 length = 0; + int i, cdb_sgcount = 0; + struct scatterlist *sg; int nseg; ccb->pcmd = pcmd; @@ -995,19 +1043,12 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb, arcmsr_cdb->LUN = pcmd->device->lun; arcmsr_cdb->Function = 1; arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len; - arcmsr_cdb->Context = (unsigned long)arcmsr_cdb; + arcmsr_cdb->Context = 0; memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); nseg = scsi_dma_map(pcmd); - if (nseg > ARCMSR_MAX_SG_ENTRIES) + if (nseg > acb->host->sg_tablesize || nseg < 0) return FAILED; - BUG_ON(nseg < 0); - - if (nseg) { - __le32 length; - int i, cdb_sgcount = 0; - struct scatterlist *sg; - /* map stor port SG list to our iop SG List. */ scsi_for_each_sg(pcmd, sg, nseg, i) { /* Get the physical address of the current data pointer */ @@ -1034,10 +1075,10 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb, } arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount; arcmsr_cdb->DataLength = scsi_bufflen(pcmd); + arcmsr_cdb->msgPages = arccdbsize/0x100 + (arccdbsize % 0x100 ? 1 : 0); if ( arccdbsize > 256) arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; - } - if (pcmd->sc_data_direction == DMA_TO_DEVICE ) { + if (pcmd->cmnd[0]|WRITE_6 || pcmd->cmnd[0] | WRITE_10 || pcmd->cmnd[0]|WRITE_12) { arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; ccb->ccb_flags |= CCB_FLAG_WRITE; } @@ -1046,7 +1087,7 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb, static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) { - uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr; + uint32_t shifted_cdb_phyaddr = ccb->shifted_cdb_phyaddr; struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; atomic_inc(&acb->ccboutstandingcount); ccb->startdone = ARCMSR_CCB_START; @@ -1056,10 +1097,10 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr struct MessageUnit_A __iomem *reg = acb->pmuA; if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) - writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, + writel(shifted_cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, ®->inbound_queueport); else { - writel(cdb_shifted_phyaddr, ®->inbound_queueport); + writel(shifted_cdb_phyaddr, ®->inbound_queueport); } } break; @@ -1071,16 +1112,16 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); writel(0, ®->post_qbuffer[ending_index]); if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { - writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\ + writel(shifted_cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\ ®->post_qbuffer[index]); } else { - writel(cdb_shifted_phyaddr, ®->post_qbuffer[index]); + writel(shifted_cdb_phyaddr, ®->post_qbuffer[index]); } index++; index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */ reg->postq_index = index; - writel(ARCMSR_DRV2IOP_CDB_POSTED, reg->drv2iop_doorbell_reg); + writel(ARCMSR_DRV2IOP_CDB_POSTED, reg->drv2iop_doorbell); } break; } @@ -1103,7 +1144,7 @@ static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) { struct MessageUnit_B *reg = acb->pmuB; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; - writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg); + writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell); if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE @@ -1131,23 +1172,14 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { + dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle); iounmap(acb->pmuA); - dma_free_coherent(&acb->pdev->dev, - ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, - acb->dma_coherent, - acb->dma_coherent_handle); - break; } + break; case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = acb->pmuB; - iounmap((u8 *)reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); - iounmap((u8 *)reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); - dma_free_coherent(&acb->pdev->dev, - (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + - sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); + dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle); } } - } void arcmsr_iop_message_read(struct AdapterControlBlock *acb) @@ -1161,7 +1193,7 @@ void arcmsr_iop_message_read(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; - writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); + writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell); } break; } @@ -1186,7 +1218,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) ** push inbound doorbell tell iop, driver data write ok ** and wait reply on next hwinterrupt for next Qbuffer post */ - writel(ARCMSR_DRV2IOP_DATA_WRITE_OK, reg->drv2iop_doorbell_reg); + writel(ARCMSR_DRV2IOP_DATA_WRITE_OK, reg->drv2iop_doorbell); } break; } @@ -1206,7 +1238,7 @@ struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; - qbuffer = (struct QBUFFER __iomem *)reg->ioctl_rbuffer_reg; + qbuffer = (struct QBUFFER __iomem *)reg->message_rbuffer; } break; } @@ -1227,7 +1259,7 @@ static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBloc case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; - pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg; + pqbuffer = (struct QBUFFER __iomem *)reg->message_wbuffer; } break; } @@ -1362,7 +1394,7 @@ static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) struct MessageUnit_B *reg = acb->pmuB; /*clear interrupt and message state*/ - writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); + writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); schedule_work(&acb->arcmsr_do_message_isr_bh); } static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) @@ -1394,16 +1426,16 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) uint32_t outbound_doorbell; struct MessageUnit_B *reg = acb->pmuB; - outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & + outbound_doorbell = readl(reg->iop2drv_doorbell) & acb->outbound_int_enable; if (!outbound_doorbell) return 1; - writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); + writel(~outbound_doorbell, reg->iop2drv_doorbell); /*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/ - readl(reg->iop2drv_doorbell_reg); - writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); + readl(reg->iop2drv_doorbell); + writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } @@ -1523,12 +1555,6 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, goto message_out; } - if (!acb->fw_state) { - pcmdmessagefld->cmdmessage.ReturnCode = - ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; - } - ptmpQbuffer = ver_addr; while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) && (allxfer_len < 1031)) { @@ -1560,7 +1586,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, } memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len); pcmdmessagefld->cmdmessage.Length = allxfer_len; + if (acb->fw_flag == FW_DEADLOCK) { + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + } else { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + } kfree(ver_addr); } break; @@ -1575,12 +1605,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, retvalue = ARCMSR_MESSAGE_FAIL; goto message_out; } - if (!acb->fw_state) { + if (acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; + } else { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; } - ptmpuserbuffer = ver_addr; user_len = pcmdmessagefld->cmdmessage.Length; memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); @@ -1633,12 +1664,6 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { uint8_t *pQbuffer = acb->rqbuffer; - if (!acb->fw_state) { - pcmdmessagefld->cmdmessage.ReturnCode = - ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; - } - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; arcmsr_iop_message_read(acb); @@ -1647,16 +1672,24 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, acb->rqbuf_firstindex = 0; acb->rqbuf_lastindex = 0; memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + if (acb->fw_flag == FW_DEADLOCK) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + } else { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; + } } break; case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { uint8_t *pQbuffer = acb->wqbuffer; - if (!acb->fw_state) { + if (acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; + } else { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { @@ -1669,18 +1702,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, acb->wqbuf_firstindex = 0; acb->wqbuf_lastindex = 0; memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - pcmdmessagefld->cmdmessage.ReturnCode = - ARCMSR_MESSAGE_RETURNCODE_OK; } break; case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { uint8_t *pQbuffer; - if (!acb->fw_state) { - pcmdmessagefld->cmdmessage.ReturnCode = - ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; - } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; @@ -1698,47 +1724,52 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, memset(pQbuffer, 0, sizeof(struct QBUFFER)); pQbuffer = acb->wqbuffer; memset(pQbuffer, 0, sizeof(struct QBUFFER)); - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + if (acb->fw_flag == FW_DEADLOCK) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + } else { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; + } } break; case ARCMSR_MESSAGE_RETURN_CODE_3F: { - if (!acb->fw_state) { + if (acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; - } - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; + } else { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_3F; } break; - + } case ARCMSR_MESSAGE_SAY_HELLO: { int8_t *hello_string = "Hello! I am ARCMSR"; - if (!acb->fw_state) { + if (acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; + } else { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; } memcpy(pcmdmessagefld->messagedatabuffer, hello_string , (int16_t)strlen(hello_string)); - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } break; case ARCMSR_MESSAGE_SAY_GOODBYE: - if (!acb->fw_state) { + if (acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; } arcmsr_iop_parking(acb); break; case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: - if (!acb->fw_state) { + if (acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - goto message_out; } arcmsr_flush_adapter_cache(acb); break; @@ -1756,11 +1787,16 @@ static struct CommandControlBlock *arcmsr_get_freeccb(struct AdapterControlBlock { struct list_head *head = &acb->ccb_free_list; struct CommandControlBlock *ccb = NULL; - + unsigned long flags; + spin_lock_irqsave(&acb->ccblist_lock, flags); if (!list_empty(head)) { ccb = list_entry(head->next, struct CommandControlBlock, list); - list_del(head->next); + list_del_init(&ccb->list); + } else { + spin_unlock_irqrestore(&acb->ccblist_lock, flags); + return 0; } + spin_unlock_irqrestore(&acb->ccblist_lock, flags); return ccb; } @@ -1835,66 +1871,12 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, return 0; } - if (acb->acb_flags & ACB_F_BUS_RESET) { - switch (acb->adapter_type) { - case ACB_ADAPTER_TYPE_A: { - struct MessageUnit_A __iomem *reg = acb->pmuA; - uint32_t intmask_org, outbound_doorbell; - - if ((readl(®->outbound_msgaddr1) & - ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { - printk(KERN_NOTICE "arcmsr%d: bus reset and return busy\n", - acb->host->host_no); - return SCSI_MLQUEUE_HOST_BUSY; - } - - acb->acb_flags &= ~ACB_F_FIRMWARE_TRAP; - printk(KERN_NOTICE "arcmsr%d: hardware bus reset and reset ok\n", - acb->host->host_no); - /* disable all outbound interrupt */ - intmask_org = arcmsr_disable_outbound_ints(acb); - arcmsr_get_firmware_spec(acb, 1); - /*start background rebuild*/ - arcmsr_start_adapter_bgrb(acb); - /* clear Qbuffer if door bell ringed */ - outbound_doorbell = readl(®->outbound_doorbell); - /*clear interrupt */ - writel(outbound_doorbell, ®->outbound_doorbell); - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); - /* enable outbound Post Queue,outbound doorbell Interrupt */ - arcmsr_enable_outbound_ints(acb, intmask_org); - acb->acb_flags |= ACB_F_IOP_INITED; - acb->acb_flags &= ~ACB_F_BUS_RESET; - } - break; - case ACB_ADAPTER_TYPE_B: { - } - } - } - if (target == 16) { /* virtual device for iop message transfer */ arcmsr_handle_virtual_command(acb, cmd); return 0; } - if (acb->devstate[target][lun] == ARECA_RAID_GONE) { - uint8_t block_cmd; - block_cmd = cmd->cmnd[0] & 0x0f; - if (block_cmd == 0x08 || block_cmd == 0x0a) { - printk(KERN_NOTICE - "arcmsr%d: block 'read/write'" - "command with gone raid volume" - " Cmd = %2x, TargetId = %d, Lun = %d \n" - , acb->host->host_no - , cmd->cmnd[0] - , target, lun); - cmd->result = (DID_NO_CONNECT << 16); - cmd->scsi_done(cmd); - return 0; - } - } if (atomic_read(&acb->ccboutstandingcount) >= ARCMSR_MAX_OUTSTANDING_CMD) return SCSI_MLQUEUE_HOST_BUSY; @@ -1911,7 +1893,7 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, return 0; } -static void *arcmsr_get_hba_config(struct AdapterControlBlock *acb, int mode) +static bool arcmsr_get_hba_config(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; char *acb_firm_model = acb->firm_model; @@ -1926,10 +1908,8 @@ static void *arcmsr_get_hba_config(struct AdapterControlBlock *acb, int mode) if (arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ miscellaneous data' timeout \n", acb->host->host_no); - return NULL; + return false; } - - if (mode == 1) { count = 8; while (count) { *acb_firm_model = readb(iop_firm_model); @@ -1953,53 +1933,68 @@ static void *arcmsr_get_hba_config(struct AdapterControlBlock *acb, int mode) iop_device_map++; count--; } - - printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" - , acb->host->host_no - , acb->firm_version); + printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", + acb->host->host_no, + acb->firm_version, + acb->firm_model); acb->signature = readl(®->message_rwbuffer[0]); acb->firm_request_len = readl(®->message_rwbuffer[1]); acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); acb->firm_sdram_size = readl(®->message_rwbuffer[3]); acb->firm_hd_channels = readl(®->message_rwbuffer[4]); + acb->firm_cfg_version = readl(®->message_rwbuffer[25]); /*firm_cfg_version,25,100-103*/ + return true; } - return reg->message_rwbuffer; -} -static void __iomem *arcmsr_get_hbb_config(struct AdapterControlBlock *acb, int mode) +static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) { struct MessageUnit_B *reg = acb->pmuB; - uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg; + struct pci_dev *pdev = acb->pdev; + void *dma_coherent; + dma_addr_t dma_coherent_handle; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; char *acb_device_map = acb->device_map; - char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]); + char __iomem *iop_firm_model; /*firm_model,15,60-67*/ - char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]); + char __iomem *iop_firm_version; /*firm_version,17,68-83*/ - char __iomem *iop_device_map = (char __iomem *) (&lrwbuffer[21]); + char __iomem *iop_device_map; /*firm_version,21,84-99*/ int count; - - writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); + dma_coherent = dma_alloc_coherent(&pdev->dev, sizeof(struct MessageUnit_B), &dma_coherent_handle, GFP_KERNEL); + if (!dma_coherent) { + printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error for hbb mu\n", acb->host->host_no); + return false; + } + acb->dma_coherent_handle_hbb_mu = dma_coherent_handle; + reg = (struct MessageUnit_B *)dma_coherent; + acb->pmuB = reg; + reg->drv2iop_doorbell = (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_DRV2IOP_DOORBELL); + reg->drv2iop_doorbell_mask = (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_DRV2IOP_DOORBELL_MASK); + reg->iop2drv_doorbell = (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_IOP2DRV_DOORBELL); + reg->iop2drv_doorbell_mask = (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_IOP2DRV_DOORBELL_MASK); + reg->message_wbuffer = (uint32_t __iomem *)((unsigned long)acb->mem_base1 + ARCMSR_MESSAGE_WBUFFER); + reg->message_rbuffer = (uint32_t __iomem *)((unsigned long)acb->mem_base1 + ARCMSR_MESSAGE_RBUFFER); + reg->message_rwbuffer = (uint32_t __iomem *)((unsigned long)acb->mem_base1 + ARCMSR_MESSAGE_RWBUFFER); + iop_firm_model = (char __iomem *)(®->message_rwbuffer[15]); /*firm_model,15,60-67*/ + iop_firm_version = (char __iomem *)(®->message_rwbuffer[17]); /*firm_version,17,68-83*/ + iop_device_map = (char __iomem *)(®->message_rwbuffer[21]); /*firm_version,21,84-99*/ + + writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell); if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ miscellaneous data' timeout \n", acb->host->host_no); - return NULL; + return false; } - - if (mode == 1) { count = 8; - while (count) - { + while (count) { *acb_firm_model = readb(iop_firm_model); acb_firm_model++; iop_firm_model++; count--; } - count = 16; - while (count) - { + while (count) { *acb_firm_version = readb(iop_firm_version); acb_firm_version++; iop_firm_version++; @@ -2014,46 +2009,41 @@ static void __iomem *arcmsr_get_hbb_config(struct AdapterControlBlock *acb, int count--; } - printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", + printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", acb->host->host_no, - acb->firm_version); + acb->firm_version, + acb->firm_model); - acb->signature = readl(lrwbuffer++); + acb->signature = readl(®->message_rwbuffer[1]); /*firm_signature,1,00-03*/ - acb->firm_request_len = readl(lrwbuffer++); + acb->firm_request_len = readl(®->message_rwbuffer[2]); /*firm_request_len,1,04-07*/ - acb->firm_numbers_queue = readl(lrwbuffer++); + acb->firm_numbers_queue = readl(®->message_rwbuffer[3]); /*firm_numbers_queue,2,08-11*/ - acb->firm_sdram_size = readl(lrwbuffer++); + acb->firm_sdram_size = readl(®->message_rwbuffer[4]); /*firm_sdram_size,3,12-15*/ - acb->firm_hd_channels = readl(lrwbuffer); + acb->firm_hd_channels = readl(®->message_rwbuffer[5]); /*firm_ide_channels,4,16-19*/ + acb->firm_cfg_version = readl(®->message_rwbuffer[25]); /*firm_cfg_version,25,100-103*/ + /*firm_ide_channels,4,16-19*/ + return true; } - return reg->msgcode_rwbuffer_reg; -} -static void *arcmsr_get_firmware_spec(struct AdapterControlBlock *acb, int mode) +static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) { - void *rtnval = 0; - switch (acb->adapter_type) { - case ACB_ADAPTER_TYPE_A: { - rtnval = arcmsr_get_hba_config(acb, mode); - } - break; - - case ACB_ADAPTER_TYPE_B: { - rtnval = arcmsr_get_hbb_config(acb, mode); - } - break; - } - return rtnval; + if (acb->adapter_type == ACB_ADAPTER_TYPE_A) + return arcmsr_get_hba_config(acb); + else + return arcmsr_get_hbb_config(acb); } -static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, +static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { struct MessageUnit_A __iomem *reg = acb->pmuA; struct CommandControlBlock *ccb; + struct ARCMSR_CDB *arcmsr_cdb; uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; + int rtn; polling_hba_ccb_retry: poll_count++; @@ -2061,16 +2051,19 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ while (1) { if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) { - if (poll_ccb_done) + if (poll_ccb_done) { + rtn = SUCCESS; break; - else { - msleep(25); - if (poll_count > 100) + } else { + if (poll_count > 100) { + rtn = FAILED; break; + } goto polling_hba_ccb_retry; } } - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5)); + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5)); + ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); poll_ccb_done = (ccb == poll_ccb) ? 1:0; if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { @@ -2081,8 +2074,7 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, , ccb->pcmd->device->lun , ccb); ccb->pcmd->result = DID_ABORT << 16; - arcmsr_ccb_complete(ccb, 1); - poll_ccb_done = 1; + arcmsr_ccb_complete(ccb); continue; } printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" @@ -2092,32 +2084,38 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, , ccb , atomic_read(&acb->ccboutstandingcount)); continue; - } + } else { arcmsr_report_ccb_state(acb, ccb, flag_ccb); } } + return rtn; +} -static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, +static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { struct MessageUnit_B *reg = acb->pmuB; + struct ARCMSR_CDB *arcmsr_cdb; struct CommandControlBlock *ccb; uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0; - int index; + int index, rtn; polling_hbb_ccb_retry: poll_count++; /* clear doorbell interrupt */ - writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); + writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); while (1) { index = reg->doneq_index; if ((flag_ccb = readl(®->done_qbuffer[index])) == 0) { - if (poll_ccb_done) + if (poll_ccb_done) { + rtn = SUCCESS; break; - else { + } else { msleep(25); - if (poll_count > 100) + if (poll_count > 100) { + rtn = FAILED; break; + } goto polling_hbb_ccb_retry; } } @@ -2127,19 +2125,19 @@ static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, index %= ARCMSR_MAX_HBB_POSTQUEUE; reg->doneq_index = index; /* check ifcommand done with no error*/ - ccb = (struct CommandControlBlock *)\ - (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5)); + ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); poll_ccb_done = (ccb == poll_ccb) ? 1:0; if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { - printk(KERN_NOTICE "arcmsr%d: \ - scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n" + printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" + " poll command abort successfully \n" ,acb->host->host_no ,ccb->pcmd->device->id ,ccb->pcmd->device->lun ,ccb); ccb->pcmd->result = DID_ABORT << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); continue; } printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" @@ -2149,30 +2147,34 @@ static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, , ccb , atomic_read(&acb->ccboutstandingcount)); continue; - } + } else { arcmsr_report_ccb_state(acb, ccb, flag_ccb); + } } /*drain reply FIFO*/ + return rtn; } -static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, +static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { + int rtn = 0; switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - arcmsr_polling_hba_ccbdone(acb,poll_ccb); + rtn = arcmsr_polling_hba_ccbdone(acb, poll_ccb); } break; case ACB_ADAPTER_TYPE_B: { - arcmsr_polling_hbb_ccbdone(acb,poll_ccb); + rtn = arcmsr_polling_hbb_ccbdone(acb, poll_ccb); } } + return rtn; } static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) { - uint32_t cdb_phyaddr, ccb_phyaddr_hi32; + uint32_t cdb_phyaddr, cdb_phyaddr_hi32; dma_addr_t dma_coherent_handle; /* ******************************************************************** @@ -2182,7 +2184,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) */ dma_coherent_handle = acb->dma_coherent_handle; cdb_phyaddr = (uint32_t)(dma_coherent_handle); - ccb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16); + cdb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16); /* *********************************************************************** ** if adapter type B, set window of "post command Q" @@ -2191,13 +2193,13 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - if (ccb_phyaddr_hi32 != 0) { + if (cdb_phyaddr_hi32 != 0) { struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t intmask_org; intmask_org = arcmsr_disable_outbound_ints(acb); writel(ARCMSR_SIGNATURE_SET_CONFIG, \ ®->message_rwbuffer[0]); - writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]); + writel(cdb_phyaddr_hi32, ®->message_rwbuffer[1]); writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, \ ®->inbound_msgaddr0); if (arcmsr_hba_wait_msgint_ready(acb)) { @@ -2220,19 +2222,18 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) intmask_org = arcmsr_disable_outbound_ints(acb); reg->postq_index = 0; reg->doneq_index = 0; - writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell_reg); + writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell); if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d:can not set diver mode\n", \ acb->host->host_no); return 1; } - post_queue_phyaddr = cdb_phyaddr + ARCMSR_MAX_FREECCB_NUM * \ - sizeof(struct CommandControlBlock) + offsetof(struct MessageUnit_B, post_qbuffer) ; - rwbuffer = reg->msgcode_rwbuffer_reg; + post_queue_phyaddr = acb->dma_coherent_handle_hbb_mu; + rwbuffer = reg->message_rwbuffer; /* driver "set config" signature */ writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++); /* normal should be zero */ - writel(ccb_phyaddr_hi32, rwbuffer++); + writel(cdb_phyaddr_hi32, rwbuffer++); /* postQ size (256 + 8)*4 */ writel(post_queue_phyaddr, rwbuffer++); /* doneQ size (256 + 8)*4 */ @@ -2240,19 +2241,13 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) /* ccb maxQ size must be --> [(256 + 8)*4]*/ writel(1056, rwbuffer); - writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell_reg); + writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell); if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \ timeout \n",acb->host->host_no); return 1; } - - writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell_reg); - if (arcmsr_hbb_wait_msgint_ready(acb)) { - printk(KERN_NOTICE "arcmsr%d: 'can not set diver mode \n"\ - ,acb->host->host_no); - return 1; - } + arcmsr_hbb_enable_driver_mode(acb); arcmsr_enable_outbound_ints(acb, intmask_org); } break; @@ -2277,9 +2272,9 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; do { - firmware_state = readl(reg->iop2drv_doorbell_reg); + firmware_state = readl(reg->iop2drv_doorbell); } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); - writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); + writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); } break; } @@ -2288,22 +2283,19 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; - - if (unlikely(atomic_read(&acb->rq_map_token) == 0)) { - acb->fw_state = false; + if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ((acb->acb_flags & ACB_F_ABORT) != 0)) { + return; } else { - /*to prevent rq_map_token from changing by other interrupt, then - avoid the dead-lock*/ - acb->fw_state = true; - atomic_dec(&acb->rq_map_token); - if (!(acb->fw_state) || - (acb->ante_token_value == atomic_read(&acb->rq_map_token))) { + acb->fw_flag = FW_NORMAL; + if (atomic_read(&acb->ante_token_value) == atomic_read(&acb->rq_map_token)) { atomic_set(&acb->rq_map_token, 16); } - acb->ante_token_value = atomic_read(&acb->rq_map_token); + atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token)); + if (atomic_dec_and_test(&acb->rq_map_token)) + return; writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); } - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6000)); return; } @@ -2311,21 +2303,19 @@ static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) { struct MessageUnit_B __iomem *reg = acb->pmuB; - if (unlikely(atomic_read(&acb->rq_map_token) == 0)) { - acb->fw_state = false; + if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ((acb->acb_flags & ACB_F_ABORT) != 0)) { + return; } else { - /*to prevent rq_map_token from changing by other interrupt, then - avoid the dead-lock*/ - acb->fw_state = true; - atomic_dec(&acb->rq_map_token); - if (!(acb->fw_state) || - (acb->ante_token_value == atomic_read(&acb->rq_map_token))) { + acb->fw_flag = FW_NORMAL; + if (atomic_read(&acb->ante_token_value) == atomic_read(&acb->rq_map_token)) { atomic_set(&acb->rq_map_token, 16); } - acb->ante_token_value = atomic_read(&acb->rq_map_token); - writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); + atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token)); + if (atomic_dec_and_test(&acb->rq_map_token)) + return; + writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell); + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); } - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6000)); return; } @@ -2360,7 +2350,7 @@ static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) { struct MessageUnit_B *reg = acb->pmuB; acb->acb_flags |= ACB_F_MSG_START_BGRB; - writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg); + writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell); if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ rebulid' timeout \n",acb->host->host_no); @@ -2396,8 +2386,8 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; /*clear interrupt and message state*/ - writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); - writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); + writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); + writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell); /* let IOP know data has been read */ } break; @@ -2412,7 +2402,7 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; - writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell_reg); + writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell); if(arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT"); return; @@ -2427,13 +2417,19 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) { uint8_t value[64]; int i; + struct MessageUnit_A __iomem *reg = acb->pmuA; /* backup pci config data */ + printk(KERN_ERR "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no); for (i = 0; i < 64; i++) { pci_read_config_byte(acb->pdev, i, &value[i]); } /* hardware reset signal */ + if ((acb->dev_id == 0x1680)) { + writel(ARCMSR_ARC1680_BUS_RESET, ®->reserved1[0]); + } else { pci_write_config_byte(acb->pdev, 0x84, 0x20); + } msleep(1000); /* write back pci config data */ for (i = 0; i < 64; i++) { @@ -2446,37 +2442,25 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) **************************************************************************** **************************************************************************** */ -#ifdef CONFIG_SCSI_ARCMSR_RESET int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd) { struct Scsi_Host *shost = NULL; - spinlock_t *host_lock = NULL; int i, isleep; shost = cmd->device->host; - host_lock = shost->host_lock; - - printk(KERN_NOTICE "Host %d bus reset over, sleep %d seconds (busy %d, can queue %d) ...........\n", - shost->host_no, sleeptime, shost->host_busy, shost->can_queue); isleep = sleeptime / 10; - spin_unlock_irq(host_lock); if (isleep > 0) { for (i = 0; i < isleep; i++) { msleep(10000); - printk(KERN_NOTICE "^%d^\n", i); } } isleep = sleeptime % 10; if (isleep > 0) { msleep(isleep * 1000); - printk(KERN_NOTICE "^v^\n"); } - spin_lock_irq(host_lock); - printk(KERN_NOTICE "***** wake up *****\n"); return 0; } -#endif static void arcmsr_iop_init(struct AdapterControlBlock *acb) { uint32_t intmask_org; @@ -2485,7 +2469,6 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb) intmask_org = arcmsr_disable_outbound_ints(acb); arcmsr_wait_firmware_ready(acb); arcmsr_iop_confirm(acb); - arcmsr_get_firmware_spec(acb, 1); /*start background rebuild*/ arcmsr_start_adapter_bgrb(acb); /* empty doorbell Qbuffer if door bell ringed */ @@ -2508,14 +2491,12 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb) intmask_org = arcmsr_disable_outbound_ints(acb); /* talk to iop 331 outstanding command aborted */ rtnval = arcmsr_abort_allcmd(acb); - /* wait for 3 sec for all command aborted*/ - ssleep(3); /* clear all outbound posted Q */ arcmsr_done4abort_postqueue(acb); for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { - arcmsr_ccb_complete(ccb, 1); + arcmsr_ccb_complete(ccb); } } atomic_set(&acb->ccboutstandingcount, 0); @@ -2530,54 +2511,49 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) { struct AdapterControlBlock *acb = (struct AdapterControlBlock *)cmd->device->host->hostdata; - int retry = 0; - - if (acb->acb_flags & ACB_F_BUS_RESET) - return SUCCESS; + uint32_t intmask_org, outbound_doorbell; + int retry_count = 0; + int rtn = FAILED; - printk(KERN_NOTICE "arcmsr%d: bus reset ..... \n", acb->adapter_index); - acb->acb_flags |= ACB_F_BUS_RESET; + acb = (struct AdapterControlBlock *) cmd->device->host->hostdata; + printk(KERN_ERR "arcmsr: executing eh bus reset .....num_resets = %d, \ + num_aborts = %d \n", acb->num_resets, acb->num_aborts); acb->num_resets++; - while (atomic_read(&acb->ccboutstandingcount) != 0 && retry < 4) { - arcmsr_interrupt(acb); - retry++; - } - if (arcmsr_iop_reset(acb)) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - printk(KERN_NOTICE "arcmsr%d: do hardware bus reset, num_resets = %d num_aborts = %d \n", - acb->adapter_index, acb->num_resets, acb->num_aborts); + if (acb->acb_flags & ACB_F_BUS_RESET) { + long timeout; + timeout = wait_event_timeout(wait_q, + (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ); + if (timeout) { + return SUCCESS; + } + } + acb->acb_flags |= ACB_F_BUS_RESET; + if (arcmsr_iop_reset(acb)) { + struct MessageUnit_A __iomem *reg; + reg = acb->pmuA; arcmsr_hardware_reset(acb); - acb->acb_flags |= ACB_F_FIRMWARE_TRAP; acb->acb_flags &= ~ACB_F_IOP_INITED; - #ifdef CONFIG_SCSI_ARCMSR_RESET - struct MessageUnit_A __iomem *reg = acb->pmuA; - uint32_t intmask_org, outbound_doorbell; - int retry_count = 0; sleep_again: arcmsr_sleep_for_bus_reset(cmd); - if ((readl(®->outbound_msgaddr1) & - ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { - printk(KERN_NOTICE "arcmsr%d: hardware bus reset and return busy, retry=%d \n", - acb->host->host_no, retry_count); + if ((readl(®->outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { + printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, \ + retry=%d \n", acb->host->host_no, retry_count); if (retry_count > retrycount) { - printk(KERN_NOTICE "arcmsr%d: hardware bus reset and return busy, retry aborted \n", - acb->host->host_no); - return SUCCESS; + acb->fw_flag = FW_DEADLOCK; + printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, \ + RETRY TERMINATED!! \n", acb->host->host_no); + return FAILED; } retry_count++; goto sleep_again; } - acb->acb_flags &= ~ACB_F_FIRMWARE_TRAP; acb->acb_flags |= ACB_F_IOP_INITED; - acb->acb_flags &= ~ACB_F_BUS_RESET; - printk(KERN_NOTICE "arcmsr%d: hardware bus reset and reset ok \n", - acb->host->host_no); /* disable all outbound interrupt */ intmask_org = arcmsr_disable_outbound_ints(acb); - arcmsr_get_firmware_spec(acb, 1); - /*start background rebuild*/ + arcmsr_get_firmware_spec(acb); arcmsr_start_adapter_bgrb(acb); /* clear Qbuffer if door bell ringed */ outbound_doorbell = readl(®->outbound_doorbell); @@ -2586,38 +2562,74 @@ sleep_again: /* enable outbound Post Queue,outbound doorbell Interrupt */ arcmsr_enable_outbound_ints(acb, intmask_org); atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + acb->acb_flags &= ~ACB_F_BUS_RESET; + rtn = SUCCESS; + printk(KERN_ERR "arcmsr: scsi eh bus reset succeeds\n"); + } else { + acb->acb_flags &= ~ACB_F_BUS_RESET; + if (atomic_read(&acb->rq_map_token) == 0) { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; init_timer(&acb->eternal_timer); - acb->eternal_timer.expires = jiffies + msecs_to_jiffies(20*HZ); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); acb->eternal_timer.data = (unsigned long) acb; acb->eternal_timer.function = &arcmsr_request_device_map; add_timer(&acb->eternal_timer); - #endif + } else { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); } - break; - case ACB_ADAPTER_TYPE_B: { + rtn = SUCCESS; } + break; } + case ACB_ADAPTER_TYPE_B:{ + acb->acb_flags |= ACB_F_BUS_RESET; + if (arcmsr_iop_reset(acb)) { + acb->acb_flags &= ~ACB_F_BUS_RESET; + rtn = FAILED; } else { acb->acb_flags &= ~ACB_F_BUS_RESET; + if (atomic_read(&acb->rq_map_token) == 0) { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + } else { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + } + rtn = SUCCESS; } - return SUCCESS; + } + } + return rtn; } -static void arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, +static int arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) { - u32 intmask; - - ccb->startdone = ARCMSR_CCB_ABORTED; - - /* - ** Wait for 3 sec for all command done. - */ - ssleep(3); - - intmask = arcmsr_disable_outbound_ints(acb); - arcmsr_polling_ccbdone(acb, ccb); - arcmsr_enable_outbound_ints(acb, intmask); + int rtn; + spin_lock_irq(&acb->eh_lock); + rtn = arcmsr_polling_ccbdone(acb, ccb); + spin_unlock_irq(&acb->eh_lock); + return rtn; } static int arcmsr_abort(struct scsi_cmnd *cmd) @@ -2625,10 +2637,12 @@ static int arcmsr_abort(struct scsi_cmnd *cmd) struct AdapterControlBlock *acb = (struct AdapterControlBlock *)cmd->device->host->hostdata; int i = 0; + int rtn = FAILED; printk(KERN_NOTICE "arcmsr%d: abort device command of scsi id = %d lun = %d \n", acb->host->host_no, cmd->device->id, cmd->device->lun); + acb->acb_flags |= ACB_F_ABORT; acb->num_aborts++; /* ************************************************ @@ -2637,17 +2651,18 @@ static int arcmsr_abort(struct scsi_cmnd *cmd) ************************************************ */ if (!atomic_read(&acb->ccboutstandingcount)) - return SUCCESS; + return rtn; for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { struct CommandControlBlock *ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START && ccb->pcmd == cmd) { - arcmsr_abort_one_cmd(acb, ccb); + ccb->startdone = ARCMSR_CCB_ABORTED; + rtn = arcmsr_abort_one_cmd(acb, ccb); break; } } - - return SUCCESS; + acb->acb_flags &= ~ACB_F_ABORT; + return rtn; } static const char *arcmsr_info(struct Scsi_Host *host) -- cgit v1.2.3 From 2e931f3176d61c693ace27498fdb823ef605e619 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:15 -0500 Subject: [SCSI] hpsa: add new controllers Add 5 CCISSE smart array controllers Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 1133b5fda0e7..ec9b3a279f58 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -86,6 +86,11 @@ static const struct pci_device_id hpsa_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324a}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324b}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3233}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3250}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3251}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3252}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3253}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3254}, #define PCI_DEVICE_ID_HP_CISSF 0x333f {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x333F}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -109,6 +114,11 @@ static struct board_type products[] = { {0x324b103C, "Smart Array P711m", &SA5_access}, {0x3233103C, "StorageWorks P1210m", &SA5_access}, {0x333F103C, "StorageWorks P1210m", &SA5_access}, + {0x3250103C, "Smart Array", &SA5_access}, + {0x3250113C, "Smart Array", &SA5_access}, + {0x3250123C, "Smart Array", &SA5_access}, + {0x3250133C, "Smart Array", &SA5_access}, + {0x3250143C, "Smart Array", &SA5_access}, {0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; -- cgit v1.2.3 From 6798cc0a4964ceabc27de762c41929f8a875e3fd Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:20 -0500 Subject: [SCSI] hpsa: Make "hpsa_allow_any=1" boot param enable Compaq Smart Arrays. We were previously only accepting HP boards. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ec9b3a279f58..25faaae324a3 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -95,6 +95,8 @@ static const struct pci_device_id hpsa_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x333F}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, + {PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} }; @@ -3293,7 +3295,9 @@ static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id) if (*board_id == products[i].board_id) return i; - if (subsystem_vendor_id != PCI_VENDOR_ID_HP || !hpsa_allow_any) { + if ((subsystem_vendor_id != PCI_VENDOR_ID_HP && + subsystem_vendor_id != PCI_VENDOR_ID_COMPAQ) || + !hpsa_allow_any) { dev_warn(&pdev->dev, "unrecognized board ID: " "0x%08x, ignoring.\n", *board_id); return -ENODEV; -- cgit v1.2.3 From 12d2cd4711b9e3ddcf911281ec4fe511b5cfff63 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:25 -0500 Subject: [SCSI] hpsa: make hpsa_find_memory_BAR not require the per HBA structure. Rationale for this is that in order to fix the hard reset code used by kdump, we need to use this function before we even have the per HBA structure. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 25faaae324a3..f5305a4b8b32 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3313,20 +3313,20 @@ static inline bool hpsa_board_disabled(struct pci_dev *pdev) return ((command & PCI_COMMAND_MEMORY) == 0); } -static int __devinit hpsa_pci_find_memory_BAR(struct ctlr_info *h, +static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev, unsigned long *memory_bar) { int i; for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) - if (pci_resource_flags(h->pdev, i) & IORESOURCE_MEM) { + if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { /* addressing mode bits already removed */ - *memory_bar = pci_resource_start(h->pdev, i); - dev_dbg(&h->pdev->dev, "memory BAR = %lx\n", + *memory_bar = pci_resource_start(pdev, i); + dev_dbg(&pdev->dev, "memory BAR = %lx\n", *memory_bar); return 0; } - dev_warn(&h->pdev->dev, "no memory BAR found\n"); + dev_warn(&pdev->dev, "no memory BAR found\n"); return -ENODEV; } @@ -3503,7 +3503,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h) return err; } hpsa_interrupt_mode(h); - err = hpsa_pci_find_memory_BAR(h, &h->paddr); + err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr); if (err) goto err_out_free_res; h->vaddr = remap_pci_mem(h->paddr, 0x250); -- cgit v1.2.3 From a51fd47f1b8f2b9937011c433269d2ec182b9879 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:30 -0500 Subject: [SCSI] hpsa: factor out hpsa_find_cfg_addrs. Rationale for this is that I will also need to use this code in fixing kdump host reset code prior to having the hba structure. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f5305a4b8b32..44f81a0ae531 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3345,29 +3345,39 @@ static int __devinit hpsa_wait_for_board_ready(struct ctlr_info *h) return -ENODEV; } +static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev, + void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index, + u64 *cfg_offset) +{ + *cfg_base_addr = readl(vaddr + SA5_CTCFG_OFFSET); + *cfg_offset = readl(vaddr + SA5_CTMEM_OFFSET); + *cfg_base_addr &= (u32) 0x0000ffff; + *cfg_base_addr_index = find_PCI_BAR_index(pdev, *cfg_base_addr); + if (*cfg_base_addr_index == -1) { + dev_warn(&pdev->dev, "cannot find cfg_base_addr_index\n"); + return -ENODEV; + } + return 0; +} + static int __devinit hpsa_find_cfgtables(struct ctlr_info *h) { u64 cfg_offset; u32 cfg_base_addr; u64 cfg_base_addr_index; u32 trans_offset; + int rc; - /* get the address index number */ - cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET); - cfg_base_addr &= (u32) 0x0000ffff; - cfg_base_addr_index = find_PCI_BAR_index(h->pdev, cfg_base_addr); - if (cfg_base_addr_index == -1) { - dev_warn(&h->pdev->dev, "cannot find cfg_base_addr_index\n"); - return -ENODEV; - } - cfg_offset = readl(h->vaddr + SA5_CTMEM_OFFSET); + rc = hpsa_find_cfg_addrs(h->pdev, h->vaddr, &cfg_base_addr, + &cfg_base_addr_index, &cfg_offset); + if (rc) + return rc; h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev, - cfg_base_addr_index) + cfg_offset, - sizeof(h->cfgtable)); + cfg_base_addr_index) + cfg_offset, sizeof(*h->cfgtable)); if (!h->cfgtable) return -ENOMEM; /* Find performant mode table. */ - trans_offset = readl(&(h->cfgtable->TransMethodOffset)); + trans_offset = readl(&h->cfgtable->TransMethodOffset); h->transtable = remap_pci_mem(pci_resource_start(h->pdev, cfg_base_addr_index)+cfg_offset+trans_offset, sizeof(*h->transtable)); -- cgit v1.2.3 From 4c2a8c40d877effc25774f00406a4a7df1967102 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:35 -0500 Subject: [SCSI] hpsa: factor out the code to reset controllers on driver load for kdump support Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 44f81a0ae531..b2f478596dfb 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3571,33 +3571,44 @@ static void __devinit hpsa_hba_inquiry(struct ctlr_info *h) } } +static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev) +{ + int i; + + if (!reset_devices) + return 0; + + /* Reset the controller with a PCI power-cycle */ + if (hpsa_hard_reset_controller(pdev) || hpsa_reset_msi(pdev)) + return -ENODEV; + + /* Some devices (notably the HP Smart Array 5i Controller) + need a little pause here */ + msleep(HPSA_POST_RESET_PAUSE_MSECS); + + /* Now try to get the controller to respond to a no-op */ + for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) { + if (hpsa_noop(pdev) == 0) + break; + else + dev_warn(&pdev->dev, "no-op failed%s\n", + (i < 11 ? "; re-trying" : "")); + } + return 0; +} + static int __devinit hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int i, rc; - int dac; + int dac, rc; struct ctlr_info *h; if (number_of_controllers == 0) printk(KERN_INFO DRIVER_NAME "\n"); - if (reset_devices) { - /* Reset the controller with a PCI power-cycle */ - if (hpsa_hard_reset_controller(pdev) || hpsa_reset_msi(pdev)) - return -ENODEV; - - /* Some devices (notably the HP Smart Array 5i Controller) - need a little pause here */ - msleep(HPSA_POST_RESET_PAUSE_MSECS); - /* Now try to get the controller to respond to a no-op */ - for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) { - if (hpsa_noop(pdev) == 0) - break; - else - dev_warn(&pdev->dev, "no-op failed%s\n", - (i < 11 ? "; re-trying" : "")); - } - } + rc = hpsa_init_reset_devices(pdev); + if (rc) + return rc; /* Command structures must be aligned on a 32-byte boundary because * the 5 lower bits of the address are used by the hardware. and by -- cgit v1.2.3 From 1df8552abf36519ca8b9e2a8d1e204bac2076d51 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:40 -0500 Subject: [SCSI] hpsa: Fix hard reset code. Smart Array controllers newer than the P600 do not honor the PCI power state method of resetting the controllers. Instead, in these cases we can get them to reset via the "doorbell" register. This escaped notice until we began using "performant" mode because the fact that the controllers did not reset did not normally impede subsequent operation, and so things generally appeared to "work". Once the performant mode code was added, if the controller does not reset, it remains in performant mode. The code immediately after the reset presumes the controller is in "simple" mode (which previously, it had remained in simple mode the whole time). If the controller remains in performant mode any code which presumes it is in simple mode will not work. So the reset needs to be fixed. Unfortunately there are some controllers which cannot be reset by either method. (eg. p800). We detect these cases by noticing that the controller seems to remain in performant mode even after a reset has been attempted. In those case, we proceed anyway, as if the reset has happened (and skip the step of waiting for the controller to become ready -- which is expecting it to be in "simple" mode.) To sum up, we try to do a better job of resetting the controller if "reset_devices" is set, and if it doesn't work, we print a message and try to continue anyway. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 174 ++++++++++++++++++++++++++++++++++++------------ drivers/scsi/hpsa_cmd.h | 4 ++ 2 files changed, 137 insertions(+), 41 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b2f478596dfb..f57d533f7475 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -174,6 +174,11 @@ static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, int *bucket_map); static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); static inline u32 next_command(struct ctlr_info *h); +static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev, + void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index, + u64 *cfg_offset); +static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev, + unsigned long *memory_bar); static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); @@ -3078,17 +3083,75 @@ static __devinit int hpsa_reset_msi(struct pci_dev *pdev) return 0; } +static int hpsa_controller_hard_reset(struct pci_dev *pdev, + void * __iomem vaddr, bool use_doorbell) +{ + u16 pmcsr; + int pos; + + if (use_doorbell) { + /* For everything after the P600, the PCI power state method + * of resetting the controller doesn't work, so we have this + * other way using the doorbell register. + */ + dev_info(&pdev->dev, "using doorbell to reset controller\n"); + writel(DOORBELL_CTLR_RESET, vaddr + SA5_DOORBELL); + msleep(1000); + } else { /* Try to do it the PCI power state way */ + + /* Quoting from the Open CISS Specification: "The Power + * Management Control/Status Register (CSR) controls the power + * state of the device. The normal operating state is D0, + * CSR=00h. The software off state is D3, CSR=03h. To reset + * the controller, place the interface device in D3 then to D0, + * this causes a secondary PCI reset which will reset the + * controller." */ + + pos = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (pos == 0) { + dev_err(&pdev->dev, + "hpsa_reset_controller: " + "PCI PM not supported\n"); + return -ENODEV; + } + dev_info(&pdev->dev, "using PCI PM to reset controller\n"); + /* enter the D3hot power management state */ + pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr); + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + pmcsr |= PCI_D3hot; + pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); + + msleep(500); + + /* enter the D0 power management state */ + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + pmcsr |= PCI_D0; + pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); + + msleep(500); + } + return 0; +} + /* This does a hard reset of the controller using PCI power management - * states. + * states or the using the doorbell register. */ -static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev) +static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) { - u16 pmcsr, saved_config_space[32]; - int i, pos; + u16 saved_config_space[32]; + u64 cfg_offset; + u32 cfg_base_addr; + u64 cfg_base_addr_index; + void __iomem *vaddr; + unsigned long paddr; + u32 misc_fw_support, active_transport; + int rc, i; + struct CfgTable __iomem *cfgtable; + bool use_doorbell; - dev_info(&pdev->dev, "using PCI PM to reset controller\n"); - /* This is very nearly the same thing as + /* For controllers as old as the P600, this is very nearly + * the same thing as * * pci_save_state(pci_dev); * pci_set_power_state(pci_dev, PCI_D3hot); @@ -3102,41 +3165,42 @@ static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev) * violate the ordering requirements for restoring the * configuration space from the CCISS document (see the * comment below). So we roll our own .... + * + * For controllers newer than the P600, the pci power state + * method of resetting doesn't work so we have another way + * using the doorbell register. */ - for (i = 0; i < 32; i++) pci_read_config_word(pdev, 2*i, &saved_config_space[i]); - pos = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pos == 0) { - dev_err(&pdev->dev, - "hpsa_reset_controller: PCI PM not supported\n"); - return -ENODEV; - } - - /* Quoting from the Open CISS Specification: "The Power - * Management Control/Status Register (CSR) controls the power - * state of the device. The normal operating state is D0, - * CSR=00h. The software off state is D3, CSR=03h. To reset - * the controller, place the interface device in D3 then to - * D0, this causes a secondary PCI reset which will reset the - * controller." - */ - /* enter the D3hot power management state */ - pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr); - pmcsr &= ~PCI_PM_CTRL_STATE_MASK; - pmcsr |= PCI_D3hot; - pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); + /* find the first memory BAR, so we can find the cfg table */ + rc = hpsa_pci_find_memory_BAR(pdev, &paddr); + if (rc) + return rc; + vaddr = remap_pci_mem(paddr, 0x250); + if (!vaddr) + return -ENOMEM; - msleep(500); + /* find cfgtable in order to check if reset via doorbell is supported */ + rc = hpsa_find_cfg_addrs(pdev, vaddr, &cfg_base_addr, + &cfg_base_addr_index, &cfg_offset); + if (rc) + goto unmap_vaddr; + cfgtable = remap_pci_mem(pci_resource_start(pdev, + cfg_base_addr_index) + cfg_offset, sizeof(*cfgtable)); + if (!cfgtable) { + rc = -ENOMEM; + goto unmap_vaddr; + } - /* enter the D0 power management state */ - pmcsr &= ~PCI_PM_CTRL_STATE_MASK; - pmcsr |= PCI_D0; - pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); + /* If reset via doorbell register is supported, use that. */ + misc_fw_support = readl(&cfgtable->misc_fw_support); + use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; - msleep(500); + rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell); + if (rc) + goto unmap_cfgtable; /* Restore the PCI configuration space. The Open CISS * Specification says, "Restore the PCI Configuration @@ -3153,7 +3217,29 @@ static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev) wmb(); pci_write_config_word(pdev, 4, saved_config_space[2]); - return 0; + /* Some devices (notably the HP Smart Array 5i Controller) + need a little pause here */ + msleep(HPSA_POST_RESET_PAUSE_MSECS); + + /* Controller should be in simple mode at this point. If it's not, + * It means we're on one of those controllers which doesn't support + * the doorbell reset method and on which the PCI power management reset + * method doesn't work (P800, for example.) + * In those cases, pretend the reset worked and hope for the best. + */ + active_transport = readl(&cfgtable->TransportActive); + if (active_transport & PERFORMANT_MODE) { + dev_warn(&pdev->dev, "Unable to successfully reset controller," + " proceeding anyway.\n"); + rc = -ENOTSUPP; + } + +unmap_cfgtable: + iounmap(cfgtable); + +unmap_vaddr: + iounmap(vaddr); + return rc; } /* @@ -3573,18 +3659,24 @@ static void __devinit hpsa_hba_inquiry(struct ctlr_info *h) static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev) { - int i; + int rc, i; if (!reset_devices) return 0; - /* Reset the controller with a PCI power-cycle */ - if (hpsa_hard_reset_controller(pdev) || hpsa_reset_msi(pdev)) - return -ENODEV; + /* Reset the controller with a PCI power-cycle or via doorbell */ + rc = hpsa_kdump_hard_reset_controller(pdev); - /* Some devices (notably the HP Smart Array 5i Controller) - need a little pause here */ - msleep(HPSA_POST_RESET_PAUSE_MSECS); + /* -ENOTSUPP here means we cannot reset the controller + * but it's already (and still) up and running in + * "performant mode". + */ + if (rc == -ENOTSUPP) + return 0; /* just try to do the kdump anyhow. */ + if (rc) + return -ENODEV; + if (hpsa_reset_msi(pdev)) + return -ENODEV; /* Now try to get the controller to respond to a no-op */ for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) { diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 78de9b6d1e0b..f5c4c3cc0530 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -100,6 +100,7 @@ /* Configuration Table */ #define CFGTBL_ChangeReq 0x00000001l #define CFGTBL_AccCmds 0x00000001l +#define DOORBELL_CTLR_RESET 0x00000004l #define CFGTBL_Trans_Simple 0x00000002l #define CFGTBL_Trans_Performant 0x00000004l @@ -339,6 +340,9 @@ struct CfgTable { u32 MaxPhysicalDevices; u32 MaxPhysicalDrivesPerLogicalUnit; u32 MaxPerformantModeCommands; + u8 reserved[0x78 - 0x58]; + u32 misc_fw_support; /* offset 0x78 */ +#define MISC_FW_DOORBELL_RESET (0x02) }; #define NUM_BLOCKFETCH_ENTRIES 8 -- cgit v1.2.3 From 1886765906686cdb08c35afae20e4ad8f82367f5 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:45 -0500 Subject: [SCSI] hpsa: forbid hard reset of 640x boards The 6402/6404 are two PCI devices -- two Smart Array controllers -- that fit into one slot. It is possible to reset them independently, however, they share a battery backed cache module. One of the pair controls the cache and the 2nd one access the cache through the first one. If you reset the one controlling the cache, the other one will not be a happy camper. So we just forbid resetting this conjoined mess. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f57d533f7475..d903cc690eb9 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -179,6 +179,7 @@ static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev, u64 *cfg_offset); static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev, unsigned long *memory_bar); +static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id); static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); @@ -3148,7 +3149,7 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) int rc, i; struct CfgTable __iomem *cfgtable; bool use_doorbell; - + u32 board_id; /* For controllers as old as the P600, this is very nearly * the same thing as @@ -3170,6 +3171,18 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) * method of resetting doesn't work so we have another way * using the doorbell register. */ + + /* Exclude 640x boards. These are two pci devices in one slot + * which share a battery backed cache module. One controls the + * cache, the other accesses the cache through the one that controls + * it. If we reset the one controlling the cache, the other will + * likely not be happy. Just forbid resetting this conjoined mess. + * The 640x isn't really supported by hpsa anyway. + */ + hpsa_lookup_board_id(pdev, &board_id); + if (board_id == 0x409C0E11 || board_id == 0x409D0E11) + return -ENOTSUPP; + for (i = 0; i < 32; i++) pci_read_config_word(pdev, 2*i, &saved_config_space[i]); @@ -3669,7 +3682,8 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev) /* -ENOTSUPP here means we cannot reset the controller * but it's already (and still) up and running in - * "performant mode". + * "performant mode". Or, it might be 640x, which can't reset + * due to concerns about shared bbwc between 6402/6404 pair. */ if (rc == -ENOTSUPP) return 0; /* just try to do the kdump anyhow. */ -- cgit v1.2.3 From 10f66018088fd0c9fe81b1e328e3264c7b10caa5 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:50 -0500 Subject: [SCSI] hpsa: separate intx and msi/msix interrupt handlers There are things which need to be done in the intx interrupt handler which do not need to be done in the msi/msix interrupt handler, like checking that the interrupt is actually for us, and checking that the interrupt pending bit on the hardware is set (which we weren't previously doing at all, which means old controllers wouldn't work), so it makes sense to separate these into two functions. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index d903cc690eb9..f8b614b591e4 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -126,7 +126,8 @@ static struct board_type products[] = { static int number_of_controllers; -static irqreturn_t do_hpsa_intr(int irq, void *dev_id); +static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id); +static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id); static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg); static void start_io(struct ctlr_info *h); @@ -2858,9 +2859,8 @@ static inline bool interrupt_pending(struct ctlr_info *h) static inline long interrupt_not_for_us(struct ctlr_info *h) { - return !(h->msi_vector || h->msix_vector) && - ((h->access.intr_pending(h) == 0) || - (h->interrupts_enabled == 0)); + return (h->access.intr_pending(h) == 0) || + (h->interrupts_enabled == 0); } static inline int bad_tag(struct ctlr_info *h, u32 tag_index, @@ -2934,7 +2934,7 @@ static inline u32 process_nonindexed_cmd(struct ctlr_info *h, return next_command(h); } -static irqreturn_t do_hpsa_intr(int irq, void *dev_id) +static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id) { struct ctlr_info *h = dev_id; unsigned long flags; @@ -2942,6 +2942,26 @@ static irqreturn_t do_hpsa_intr(int irq, void *dev_id) if (interrupt_not_for_us(h)) return IRQ_NONE; + spin_lock_irqsave(&h->lock, flags); + while (interrupt_pending(h)) { + raw_tag = get_next_completion(h); + while (raw_tag != FIFO_EMPTY) { + if (hpsa_tag_contains_index(raw_tag)) + raw_tag = process_indexed_cmd(h, raw_tag); + else + raw_tag = process_nonindexed_cmd(h, raw_tag); + } + } + spin_unlock_irqrestore(&h->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id) +{ + struct ctlr_info *h = dev_id; + unsigned long flags; + u32 raw_tag; + spin_lock_irqsave(&h->lock, flags); raw_tag = get_next_completion(h); while (raw_tag != FIFO_EMPTY) { @@ -3754,8 +3774,13 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, /* make sure the board interrupts are off */ h->access.set_intr_mask(h, HPSA_INTR_OFF); - rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr, - IRQF_DISABLED, h->devname, h); + + if (h->msix_vector || h->msi_vector) + rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_msi, + IRQF_DISABLED, h->devname, h); + else + rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_intx, + IRQF_DISABLED, h->devname, h); if (rc) { dev_err(&pdev->dev, "unable to get irq %d for %s\n", h->intr[PERF_MODE_INT], h->devname); -- cgit v1.2.3 From cba3d38b6cf85bd91b7c6f65f43863d1fd19259c Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Jun 2010 13:51:56 -0500 Subject: [SCSI] hpsa: sanitize max commands Some controllers might try to tell us they support 0 commands in performant mode. This is a lie told by buggy firmware. We have to be wary of this lest we try to allocate a negative number of command blocks, which will be treated as unsigned, and get an out of memory condition. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f8b614b591e4..4f5551b5fe53 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3505,13 +3505,25 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h) return 0; } +static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h) +{ + h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); + if (h->max_commands < 16) { + dev_warn(&h->pdev->dev, "Controller reports " + "max supported commands of %d, an obvious lie. " + "Using 16. Ensure that firmware is up to date.\n", + h->max_commands); + h->max_commands = 16; + } +} + /* Interrogate the hardware for some limits: * max commands, max SG elements without chaining, and with chaining, * SG chain block size, etc. */ static void __devinit hpsa_find_board_params(struct ctlr_info *h) { - h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); + hpsa_get_max_perf_mode_cmds(h); h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */ h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements)); /* @@ -4056,7 +4068,7 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) if (!(trans_support & PERFORMANT_MODE)) return; - h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); + hpsa_get_max_perf_mode_cmds(h); h->max_sg_entries = 32; /* Performant mode ring buffer and supporting data structures */ h->reply_pool_size = h->max_commands * sizeof(u64); -- cgit v1.2.3 From 593d5720745658a4a973952fb74f6d863c531e97 Mon Sep 17 00:00:00 2001 From: Karen Xie Date: Wed, 16 Jun 2010 17:10:37 -0700 Subject: [SCSI] cxgb3i: zero out reserved or un-used fields. Zero out the reserved or un-used CPL message fields to prevent any garbage value. Signed-off-by: Karen Xie Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/cxgb3i/cxgb3i_ddp.c | 2 ++ drivers/scsi/cxgb3i/cxgb3i_offload.c | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index b58d9134ac1b..be0e23042c76 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c @@ -499,6 +499,7 @@ static int setup_conn_pgidx(struct t3cdev *tdev, unsigned int tid, int pg_idx, /* set up ulp submode and page size */ req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); + req->wr.wr_lo = 0; OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); req->reply = V_NO_REPLY(reply ? 0 : 1); req->cpu_idx = 0; @@ -564,6 +565,7 @@ int cxgb3i_setup_conn_digest(struct t3cdev *tdev, unsigned int tid, /* set up ulp submode and page size */ req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); + req->wr.wr_lo = 0; OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); req->reply = V_NO_REPLY(reply ? 0 : 1); req->cpu_idx = 0; diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index a175be9c496f..246a6c246ed9 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c @@ -264,6 +264,7 @@ static void make_act_open_req(struct s3_conn *c3cn, struct sk_buff *skb, skb->priority = CPL_PRIORITY_SETUP; req = (struct cpl_act_open_req *)__skb_put(skb, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); + req->wr.wr_lo = 0; OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, atid)); req->local_port = c3cn->saddr.sin_port; req->peer_port = c3cn->daddr.sin_port; @@ -273,6 +274,7 @@ static void make_act_open_req(struct s3_conn *c3cn, struct sk_buff *skb, V_TX_CHANNEL(e->smt_idx)); req->opt0l = htonl(calc_opt0l(c3cn)); req->params = 0; + req->opt2 = 0; } static void fail_act_open(struct s3_conn *c3cn, int errno) @@ -379,6 +381,7 @@ static void send_abort_req(struct s3_conn *c3cn) c3cn->cpl_abort_req = NULL; req = (struct cpl_abort_req *)skb->head; + memset(req, 0, sizeof(*req)); skb->priority = CPL_PRIORITY_DATA; set_arp_failure_handler(skb, abort_arp_failure); @@ -406,6 +409,7 @@ static void send_abort_rpl(struct s3_conn *c3cn, int rst_status) c3cn->cpl_abort_rpl = NULL; skb->priority = CPL_PRIORITY_DATA; + memset(rpl, 0, sizeof(*rpl)); rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL)); rpl->wr.wr_lo = htonl(V_WR_TID(c3cn->tid)); OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, c3cn->tid)); @@ -430,6 +434,7 @@ static u32 send_rx_credits(struct s3_conn *c3cn, u32 credits, u32 dack) req = (struct cpl_rx_data_ack *)__skb_put(skb, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); + req->wr.wr_lo = 0; OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, c3cn->tid)); req->credit_dack = htonl(dack | V_RX_CREDITS(credits)); skb->priority = CPL_PRIORITY_ACK; -- cgit v1.2.3 From ab6ce92541ea24c6a92be8498d7d1b26c14ec62d Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:25:13 +0530 Subject: [SCSI] mpt2sas: Fix to use sas device list instead of enclosure list for _transpor_get_enclosure_identifier. Enclosure_identifier not being returned by mpt2sas The driver exports callback function to the sas transport layer for obtaining the enclosure logical id. This function is called _transport_get_enclosure_identifier. The driver was searching the wrong list for the enclosure_identifier. The driver should be searching the sas device list instead of enclosure list. The sas address that is passed to the driver is for the end device, not enclosure. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_transport.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 2727c3b65104..778e149f9637 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -1007,18 +1007,18 @@ static int _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) { struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy); - struct _sas_node *sas_expander; + struct _sas_device *sas_device; unsigned long flags; - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, rphy->identify.sas_address); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (!sas_expander) + if (!sas_device) return -ENXIO; - *identifier = sas_expander->enclosure_logical_id; + *identifier = sas_device->enclosure_logical_id; return 0; } -- cgit v1.2.3 From d274213a1ae59e8abde8d43e1e3a478fe9f28794 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:28:55 +0530 Subject: [SCSI] mpt2sas: Hold Controller reset when another reset is in progress Driver should not allow multiple host reset when already host reset is in progress. It is possible that host reset was sent by scsi mid layer while there was already an host reset active, either issued via IOCTL interface or internaly, like a config page timeout. Since there was a host reset active, the driver would return a FAILED response to the scsi mid layer. The solution is make sure pending host resets will wait for the active host reset to complete before returning control back up the call stack. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 29 ++++++++++++++++++++++------- drivers/scsi/mpt2sas/mpt2sas_base.h | 4 ++++ drivers/scsi/mpt2sas/mpt2sas_scsih.c | 1 + 3 files changed, 27 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 0ec1ed389c20..f0c0df4278d7 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3804,7 +3804,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) return; /* wait for pending commands to complete */ - wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 3 * HZ); + wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ); } /** @@ -3828,13 +3828,24 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, if (mpt2sas_fwfault_debug) mpt2sas_halt_firmware(ioc); - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - if (ioc->shost_recovery) { - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - printk(MPT2SAS_ERR_FMT "%s: busy\n", - ioc->name, __func__); - return -EBUSY; + /* TODO - What we really should be doing is pulling + * out all the code associated with NO_SLEEP; its never used. + * That is legacy code from mpt fusion driver, ported over. + * I will leave this BUG_ON here for now till its been resolved. + */ + BUG_ON(sleep_flag == NO_SLEEP); + + /* wait for an active reset in progress to complete */ + if (!mutex_trylock(&ioc->reset_in_progress_mutex)) { + do { + ssleep(1); + } while (ioc->shost_recovery == 1); + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: exit\n", ioc->name, + __func__)); + return ioc->ioc_reset_in_progress_status; } + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); ioc->shost_recovery = 1; spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); @@ -3853,9 +3864,13 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + ioc->ioc_reset_in_progress_status = r; ioc->shost_recovery = 0; complete(&ioc->shost_recovery_done); spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + mutex_unlock(&ioc->reset_in_progress_mutex); + dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: exit\n", ioc->name, + __func__)); return r; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 0f41fcd4e52b..6032cbf31c7e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -600,9 +600,13 @@ struct MPT2SAS_ADAPTER { int aen_event_read_flag; u8 broadcast_aen_busy; u8 shost_recovery; + + struct mutex reset_in_progress_mutex; struct completion shost_recovery_done; spinlock_t ioc_reset_in_progress_lock; u8 ioc_link_reset_in_progress; + int ioc_reset_in_progress_status; + u8 ignore_loginfos; u8 remove_host; u8 wait_for_port_enable_to_complete; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 456ea7c3b099..9ce225303938 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -6557,6 +6557,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; ioc->logging_level = logging_level; /* misc semaphores and spin locks */ + mutex_init(&ioc->reset_in_progress_mutex); spin_lock_init(&ioc->ioc_reset_in_progress_lock); spin_lock_init(&ioc->scsi_lookup_lock); spin_lock_init(&ioc->sas_device_lock); -- cgit v1.2.3 From dd5fd3323abcb799d4d81f3c4b3e2a5fcbfce7bf Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:31:17 +0530 Subject: [SCSI] mpt2sas: staged device discovery. disable_discovery module parameter is added. Added command line option called disable_discovery. When enabled on the command line, the driver will not send a port_enable when loaded for the first time. If port_enable is not called, then there is no discovery of devices, as well as the sas topology. Then later if one desires to invoke discovery, then they will need to issue a diagnostic reset. A diagnostic reset can be issued various ways. One of the way is throught sysfs. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index f0c0df4278d7..68cb000bf486 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -95,6 +95,10 @@ int mpt2sas_fwfault_debug; MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault " "and halt firmware - (default=0)"); +static int disable_discovery = -1; +module_param(disable_discovery, int, 0); +MODULE_PARM_DESC(disable_discovery, " disable discovery "); + /** * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. * @@ -3520,6 +3524,9 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) if (sleep_flag == CAN_SLEEP) _base_static_config_pages(ioc); + if (ioc->wait_for_port_enable_to_complete && disable_discovery > 0) + return r; + r = _base_send_port_enable(ioc, sleep_flag); if (r) return r; -- cgit v1.2.3 From d5f491e65851627358b2c1a4e322681b17539550 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:32:54 +0530 Subject: [SCSI] mpt2sas: Added expander phy counter support Added support to retrieve the invalid_dword_count, running_disparity_error_count, loss_of_dword_sync_count, and phy_reset_problem_count for expanders. This will be exported to attributes within the sas transport layer. A new wrapper function was added for sending SMP passthru to retrieve the expander phy error log. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_transport.c | 242 +++++++++++++++++++++++++++++-- 1 file changed, 233 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 778e149f9637..a96501fdba0c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -951,11 +951,229 @@ _transport_find_local_phy(struct MPT2SAS_ADAPTER *ioc, struct sas_phy *phy) return NULL; } +/* report phy error log structure */ +struct phy_error_log_request{ + u8 smp_frame_type; /* 0x40 */ + u8 function; /* 0x11 */ + u8 allocated_response_length; + u8 request_length; /* 02 */ + u8 reserved_1[5]; + u8 phy_identifier; + u8 reserved_2[2]; +}; + +/* report phy error log reply structure */ +struct phy_error_log_reply{ + u8 smp_frame_type; /* 0x41 */ + u8 function; /* 0x11 */ + u8 function_result; + u8 response_length; + u16 expander_change_count; + u8 reserved_1[3]; + u8 phy_identifier; + u8 reserved_2[2]; + u32 invalid_dword; + u32 running_disparity_error; + u32 loss_of_dword_sync; + u32 phy_reset_problem; +}; + /** - * _transport_get_linkerrors - + * _transport_get_expander_phy_error_log - return expander counters + * @ioc: per adapter object + * @phy: The sas phy object + * + * Returns 0 for success, non-zero for failure. + * + */ +static int +_transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc, + struct sas_phy *phy) +{ + Mpi2SmpPassthroughRequest_t *mpi_request; + Mpi2SmpPassthroughReply_t *mpi_reply; + struct phy_error_log_request *phy_error_log_request; + struct phy_error_log_reply *phy_error_log_reply; + int rc; + u16 smid; + u32 ioc_state; + unsigned long timeleft; + void *psge; + u32 sgl_flags; + u8 issue_reset = 0; + void *data_out = NULL; + dma_addr_t data_out_dma; + u32 sz; + u64 *sas_address_le; + u16 wait_state_count; + + if (ioc->shost_recovery) { + printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", + __func__, ioc->name); + return -EFAULT; + } + + mutex_lock(&ioc->transport_cmds.mutex); + + if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + ioc->transport_cmds.status = MPT2_CMD_PENDING; + + wait_state_count = 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + if (wait_state_count++ == 10) { + printk(MPT2SAS_ERR_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + ssleep(1); + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + printk(MPT2SAS_INFO_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + if (wait_state_count) + printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", + ioc->name, __func__); + + smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->transport_cmds.smid = smid; + + sz = sizeof(struct phy_error_log_request) + + sizeof(struct phy_error_log_reply); + data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); + if (!data_out) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + rc = -ENOMEM; + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + + rc = -EINVAL; + memset(data_out, 0, sz); + phy_error_log_request = data_out; + phy_error_log_request->smp_frame_type = 0x40; + phy_error_log_request->function = 0x11; + phy_error_log_request->request_length = 2; + phy_error_log_request->allocated_response_length = 0; + phy_error_log_request->phy_identifier = phy->number; + + memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); + mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; + mpi_request->PhysicalPort = 0xFF; + mpi_request->VF_ID = 0; /* TODO */ + mpi_request->VP_ID = 0; + sas_address_le = (u64 *)&mpi_request->SASAddress; + *sas_address_le = cpu_to_le64(phy->identify.sas_address); + mpi_request->RequestDataLength = + cpu_to_le16(sizeof(struct phy_error_log_request)); + psge = &mpi_request->SGL; + + /* WRITE sgel first */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + sizeof(struct phy_error_log_request), data_out_dma); + + /* incr sgel */ + psge += ioc->sge_size; + + /* READ sgel last */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | + MPI2_SGE_FLAGS_END_OF_LIST); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + sizeof(struct phy_error_log_reply), data_out_dma + + sizeof(struct phy_error_log_request)); + + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - " + "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name, + (unsigned long long)phy->identify.sas_address, phy->number)); + mpt2sas_base_put_smid_default(ioc, smid); + init_completion(&ioc->transport_cmds.done); + timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, + 10*HZ); + + if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2SmpPassthroughRequest_t)/4); + if (!(ioc->transport_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - " + "complete\n", ioc->name)); + + if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { + + mpi_reply = ioc->transport_cmds.reply; + + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT + "phy_error_log - reply data transfer size(%d)\n", + ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); + + if (le16_to_cpu(mpi_reply->ResponseDataLength) != + sizeof(struct phy_error_log_reply)) + goto out; + + phy_error_log_reply = data_out + + sizeof(struct phy_error_log_request); + + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT + "phy_error_log - function_result(%d)\n", + ioc->name, phy_error_log_reply->function_result)); + + phy->invalid_dword_count = + be32_to_cpu(phy_error_log_reply->invalid_dword); + phy->running_disparity_error_count = + be32_to_cpu(phy_error_log_reply->running_disparity_error); + phy->loss_of_dword_sync_count = + be32_to_cpu(phy_error_log_reply->loss_of_dword_sync); + phy->phy_reset_problem_count = + be32_to_cpu(phy_error_log_reply->phy_reset_problem); + rc = 0; + } else + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT + "phy_error_log - no reply\n", ioc->name)); + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + out: + ioc->transport_cmds.status = MPT2_CMD_NOT_USED; + if (data_out) + pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); + + mutex_unlock(&ioc->transport_cmds.mutex); + return rc; +} + +/** + * _transport_get_linkerrors - return phy counters for both hba and expanders * @phy: The sas phy object * - * Only support sas_host direct attached phys. * Returns 0 for success, non-zero for failure. * */ @@ -963,17 +1181,24 @@ static int _transport_get_linkerrors(struct sas_phy *phy) { struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); - struct _sas_phy *mpt2sas_phy; + unsigned long flags; Mpi2ConfigReply_t mpi_reply; Mpi2SasPhyPage1_t phy_pg1; - mpt2sas_phy = _transport_find_local_phy(ioc, phy); - - if (!mpt2sas_phy) /* this phy not on sas_host */ + spin_lock_irqsave(&ioc->sas_node_lock, flags); + if (_transport_sas_node_find_by_sas_address(ioc, + phy->identify.sas_address) == NULL) { + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; + } + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + + if (phy->identify.sas_address != ioc->sas_hba.sas_address) + return _transport_get_expander_phy_error_log(ioc, phy); + /* get hba phy error logs */ if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1, - mpt2sas_phy->phy_id))) { + phy->number))) { printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); return -ENXIO; @@ -982,8 +1207,7 @@ _transport_get_linkerrors(struct sas_phy *phy) if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status" "(0x%04x), loginfo(0x%08x)\n", ioc->name, - mpt2sas_phy->phy_id, - le16_to_cpu(mpi_reply.IOCStatus), + phy->number, le16_to_cpu(mpi_reply.IOCStatus), le32_to_cpu(mpi_reply.IOCLogInfo)); phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount); -- cgit v1.2.3 From b8d7d7bb37b5e25ea740369eb12de5279fe6ab30 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:34:31 +0530 Subject: [SCSI] mpt2sas: Added expander phy control support Added support to send link resets, hard resets, enable/disable phys, and changing link rates for for expanders. This will be exported to attributes within the sas transport layer. A new wrapper function was added for sending SMP passthru to expanders for phy control. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_transport.c | 305 ++++++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 30 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index a96501fdba0c..6c94deeb7be7 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -940,16 +940,6 @@ rphy_to_ioc(struct sas_rphy *rphy) return shost_priv(shost); } -static struct _sas_phy * -_transport_find_local_phy(struct MPT2SAS_ADAPTER *ioc, struct sas_phy *phy) -{ - int i; - - for (i = 0; i < ioc->sas_hba.num_phys; i++) - if (ioc->sas_hba.phy[i].phy == phy) - return(&ioc->sas_hba.phy[i]); - return NULL; -} /* report phy error log structure */ struct phy_error_log_request{ @@ -1270,32 +1260,260 @@ _transport_get_bay_identifier(struct sas_rphy *rphy) return sas_device->slot; } +/* phy control request structure */ +struct phy_control_request{ + u8 smp_frame_type; /* 0x40 */ + u8 function; /* 0x91 */ + u8 allocated_response_length; + u8 request_length; /* 0x09 */ + u16 expander_change_count; + u8 reserved_1[3]; + u8 phy_identifier; + u8 phy_operation; + u8 reserved_2[13]; + u64 attached_device_name; + u8 programmed_min_physical_link_rate; + u8 programmed_max_physical_link_rate; + u8 reserved_3[6]; +}; + +/* phy control reply structure */ +struct phy_control_reply{ + u8 smp_frame_type; /* 0x41 */ + u8 function; /* 0x11 */ + u8 function_result; + u8 response_length; +}; + +#define SMP_PHY_CONTROL_LINK_RESET (0x01) +#define SMP_PHY_CONTROL_HARD_RESET (0x02) +#define SMP_PHY_CONTROL_DISABLE (0x03) + +/** + * _transport_expander_phy_control - expander phy control + * @ioc: per adapter object + * @phy: The sas phy object + * + * Returns 0 for success, non-zero for failure. + * + */ +static int +_transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc, + struct sas_phy *phy, u8 phy_operation) +{ + Mpi2SmpPassthroughRequest_t *mpi_request; + Mpi2SmpPassthroughReply_t *mpi_reply; + struct phy_control_request *phy_control_request; + struct phy_control_reply *phy_control_reply; + int rc; + u16 smid; + u32 ioc_state; + unsigned long timeleft; + void *psge; + u32 sgl_flags; + u8 issue_reset = 0; + void *data_out = NULL; + dma_addr_t data_out_dma; + u32 sz; + u64 *sas_address_le; + u16 wait_state_count; + + if (ioc->shost_recovery) { + printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", + __func__, ioc->name); + return -EFAULT; + } + + mutex_lock(&ioc->transport_cmds.mutex); + + if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) { + printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + ioc->transport_cmds.status = MPT2_CMD_PENDING; + + wait_state_count = 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + if (wait_state_count++ == 10) { + printk(MPT2SAS_ERR_FMT + "%s: failed due to ioc not operational\n", + ioc->name, __func__); + rc = -EFAULT; + goto out; + } + ssleep(1); + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + printk(MPT2SAS_INFO_FMT "%s: waiting for " + "operational state(count=%d)\n", ioc->name, + __func__, wait_state_count); + } + if (wait_state_count) + printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", + ioc->name, __func__); + + smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + rc = -EAGAIN; + goto out; + } + + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + ioc->transport_cmds.smid = smid; + + sz = sizeof(struct phy_control_request) + + sizeof(struct phy_control_reply); + data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); + if (!data_out) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, + __LINE__, __func__); + rc = -ENOMEM; + mpt2sas_base_free_smid(ioc, smid); + goto out; + } + + rc = -EINVAL; + memset(data_out, 0, sz); + phy_control_request = data_out; + phy_control_request->smp_frame_type = 0x40; + phy_control_request->function = 0x91; + phy_control_request->request_length = 9; + phy_control_request->allocated_response_length = 0; + phy_control_request->phy_identifier = phy->number; + phy_control_request->phy_operation = phy_operation; + phy_control_request->programmed_min_physical_link_rate = + phy->minimum_linkrate << 4; + phy_control_request->programmed_max_physical_link_rate = + phy->maximum_linkrate << 4; + + memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); + mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; + mpi_request->PhysicalPort = 0xFF; + mpi_request->VF_ID = 0; /* TODO */ + mpi_request->VP_ID = 0; + sas_address_le = (u64 *)&mpi_request->SASAddress; + *sas_address_le = cpu_to_le64(phy->identify.sas_address); + mpi_request->RequestDataLength = + cpu_to_le16(sizeof(struct phy_error_log_request)); + psge = &mpi_request->SGL; + + /* WRITE sgel first */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + sizeof(struct phy_control_request), data_out_dma); + + /* incr sgel */ + psge += ioc->sge_size; + + /* READ sgel last */ + sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | + MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | + MPI2_SGE_FLAGS_END_OF_LIST); + sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; + ioc->base_add_sg_single(psge, sgl_flags | + sizeof(struct phy_control_reply), data_out_dma + + sizeof(struct phy_control_request)); + + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - " + "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name, + (unsigned long long)phy->identify.sas_address, phy->number, + phy_operation)); + mpt2sas_base_put_smid_default(ioc, smid); + init_completion(&ioc->transport_cmds.done); + timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, + 10*HZ); + + if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) { + printk(MPT2SAS_ERR_FMT "%s: timeout\n", + ioc->name, __func__); + _debug_dump_mf(mpi_request, + sizeof(Mpi2SmpPassthroughRequest_t)/4); + if (!(ioc->transport_cmds.status & MPT2_CMD_RESET)) + issue_reset = 1; + goto issue_host_reset; + } + + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - " + "complete\n", ioc->name)); + + if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { + + mpi_reply = ioc->transport_cmds.reply; + + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT + "phy_control - reply data transfer size(%d)\n", + ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); + + if (le16_to_cpu(mpi_reply->ResponseDataLength) != + sizeof(struct phy_control_reply)) + goto out; + + phy_control_reply = data_out + + sizeof(struct phy_control_request); + + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT + "phy_control - function_result(%d)\n", + ioc->name, phy_control_reply->function_result)); + + rc = 0; + } else + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT + "phy_control - no reply\n", ioc->name)); + + issue_host_reset: + if (issue_reset) + mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, + FORCE_BIG_HAMMER); + out: + ioc->transport_cmds.status = MPT2_CMD_NOT_USED; + if (data_out) + pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); + + mutex_unlock(&ioc->transport_cmds.mutex); + return rc; +} + /** * _transport_phy_reset - * @phy: The sas phy object * @hard_reset: * - * Only support sas_host direct attached phys. * Returns 0 for success, non-zero for failure. */ static int _transport_phy_reset(struct sas_phy *phy, int hard_reset) { struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); - struct _sas_phy *mpt2sas_phy; Mpi2SasIoUnitControlReply_t mpi_reply; Mpi2SasIoUnitControlRequest_t mpi_request; + unsigned long flags; - mpt2sas_phy = _transport_find_local_phy(ioc, phy); - - if (!mpt2sas_phy) /* this phy not on sas_host */ + spin_lock_irqsave(&ioc->sas_node_lock, flags); + if (_transport_sas_node_find_by_sas_address(ioc, + phy->identify.sas_address) == NULL) { + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; + } + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + /* handle expander phys */ + if (phy->identify.sas_address != ioc->sas_hba.sas_address) + return _transport_expander_phy_control(ioc, phy, + (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET : + SMP_PHY_CONTROL_LINK_RESET); + + /* handle hba phys */ memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t)); mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; mpi_request.Operation = hard_reset ? MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET; - mpi_request.PhyNum = mpt2sas_phy->phy_id; + mpi_request.PhyNum = phy->number; if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) { printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", @@ -1306,8 +1524,7 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset) if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status" "(0x%04x), loginfo(0x%08x)\n", ioc->name, - mpt2sas_phy->phy_id, - le16_to_cpu(mpi_reply.IOCStatus), + phy->number, le16_to_cpu(mpi_reply.IOCStatus), le32_to_cpu(mpi_reply.IOCLogInfo)); return 0; @@ -1325,17 +1542,28 @@ static int _transport_phy_enable(struct sas_phy *phy, int enable) { struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); - struct _sas_phy *mpt2sas_phy; Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; Mpi2ConfigReply_t mpi_reply; u16 ioc_status; u16 sz; int rc = 0; + unsigned long flags; - mpt2sas_phy = _transport_find_local_phy(ioc, phy); - - if (!mpt2sas_phy) /* this phy not on sas_host */ + spin_lock_irqsave(&ioc->sas_node_lock, flags); + if (_transport_sas_node_find_by_sas_address(ioc, + phy->identify.sas_address) == NULL) { + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; + } + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + + /* handle expander phys */ + if (phy->identify.sas_address != ioc->sas_hba.sas_address) + return _transport_expander_phy_control(ioc, phy, + (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET : + SMP_PHY_CONTROL_DISABLE); + + /* handle hba phys */ /* sas_iounit page 1 */ sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * @@ -1364,14 +1592,18 @@ _transport_phy_enable(struct sas_phy *phy, int enable) } if (enable) - sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags + sas_iounit_pg1->PhyData[phy->number].PhyFlags &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; else - sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags + sas_iounit_pg1->PhyData[phy->number].PhyFlags |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz); + /* link reset */ + if (enable) + _transport_phy_reset(phy, 0); + out: kfree(sas_iounit_pg1); return rc; @@ -1389,7 +1621,6 @@ static int _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) { struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); - struct _sas_phy *mpt2sas_phy; Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; Mpi2SasPhyPage0_t phy_pg0; Mpi2ConfigReply_t mpi_reply; @@ -1397,11 +1628,15 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) u16 sz; int i; int rc = 0; + unsigned long flags; - mpt2sas_phy = _transport_find_local_phy(ioc, phy); - - if (!mpt2sas_phy) /* this phy not on sas_host */ + spin_lock_irqsave(&ioc->sas_node_lock, flags); + if (_transport_sas_node_find_by_sas_address(ioc, + phy->identify.sas_address) == NULL) { + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; + } + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (!rates->minimum_linkrate) rates->minimum_linkrate = phy->minimum_linkrate; @@ -1413,6 +1648,16 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) else if (rates->maximum_linkrate > phy->maximum_linkrate_hw) rates->maximum_linkrate = phy->maximum_linkrate_hw; + /* handle expander phys */ + if (phy->identify.sas_address != ioc->sas_hba.sas_address) { + phy->minimum_linkrate = rates->minimum_linkrate; + phy->maximum_linkrate = rates->maximum_linkrate; + return _transport_expander_phy_control(ioc, phy, + SMP_PHY_CONTROL_LINK_RESET); + } + + /* handle hba phys */ + /* sas_iounit page 1 */ sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * sizeof(Mpi2SasIOUnit1PhyData_t)); @@ -1440,7 +1685,7 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) } for (i = 0; i < ioc->sas_hba.num_phys; i++) { - if (mpt2sas_phy->phy_id != i) { + if (phy->number != i) { sas_iounit_pg1->PhyData[i].MaxMinLinkRate = (ioc->sas_hba.phy[i].phy->minimum_linkrate + (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4)); @@ -1464,7 +1709,7 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) /* read phy page 0, then update the rates in the sas transport phy */ if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, - mpt2sas_phy->phy_id)) { + phy->number)) { phy->minimum_linkrate = _transport_convert_phy_link_rate( phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); phy->maximum_linkrate = _transport_convert_phy_link_rate( -- cgit v1.2.3 From d32a8c15e1116e87f0105356eca1afb99842ab49 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:36:53 +0530 Subject: [SCSI] mpt2sas: Added sysfs counter for ioc reset Added a new sysfs shost attribute called ioc_reset_count. This will keep count of host resets (both diagnostic and message unit). Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 9 +++++++-- drivers/scsi/mpt2sas/mpt2sas_base.h | 1 + drivers/scsi/mpt2sas/mpt2sas_ctl.c | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 68cb000bf486..88befc798469 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3402,6 +3402,7 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, enum reset_type type) { u32 ioc_state; + int rc; dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, __func__)); @@ -3430,11 +3431,15 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) if (!(_base_send_ioc_reset(ioc, - MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) + MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) { + ioc->ioc_reset_count++; return 0; + } issue_diag_reset: - return _base_diag_reset(ioc, CAN_SLEEP); + rc = _base_diag_reset(ioc, CAN_SLEEP); + ioc->ioc_reset_count++; + return rc; } /** diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 6032cbf31c7e..a4a731529226 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -615,6 +615,7 @@ struct MPT2SAS_ADAPTER { u16 msix_vector_count; u32 *msix_table; u32 *msix_table_backup; + u32 ioc_reset_count; /* internal commands, callback index */ u8 scsi_io_cb_idx; diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index d88e9756d8f5..25c866e3e900 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -2581,6 +2581,29 @@ _ctl_fwfault_debug_store(struct device *cdev, static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR, _ctl_fwfault_debug_show, _ctl_fwfault_debug_store); + +/** + * _ctl_ioc_reset_count_show - ioc reset count + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * This is firmware queue depth limit + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%08d\n", ioc->ioc_reset_count); +} +static DEVICE_ATTR(ioc_reset_count, S_IRUGO, + _ctl_ioc_reset_count_show, NULL); + + struct device_attribute *mpt2sas_host_attrs[] = { &dev_attr_version_fw, &dev_attr_version_bios, @@ -2597,6 +2620,7 @@ struct device_attribute *mpt2sas_host_attrs[] = { &dev_attr_fwfault_debug, &dev_attr_fw_queue_depth, &dev_attr_host_sas_address, + &dev_attr_ioc_reset_count, NULL, }; -- cgit v1.2.3 From 203d65b16cfef448dbfb79f66b672be4511fc6a9 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:37:59 +0530 Subject: [SCSI] mpt2sas: MPI header version N is updated. Updating MPI header version N. Removed mpi_history.txt. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpi/mpi2.h | 17 ++- drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h | 193 +++++++++++++++++++++++++++++++---- drivers/scsi/mpt2sas/mpi/mpi2_init.h | 17 +-- drivers/scsi/mpt2sas/mpi/mpi2_ioc.h | 119 ++++++++++++++++++++- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 7 +- 5 files changed, 308 insertions(+), 45 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h index dada0a13223f..4b1c2f0350f9 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2.h @@ -8,7 +8,7 @@ * scatter/gather formats. * Creation Date: June 21, 2006 * - * mpi2.h Version: 02.00.14 + * mpi2.h Version: 02.00.15 * * Version History * --------------- @@ -57,6 +57,10 @@ * Added MSI-x index mask and shift for Reply Post Host * Index register. * Added function code for Host Based Discovery Action. + * 02-10-10 02.00.15 Bumped MPI2_HEADER_VERSION_UNIT. + * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL. + * Added defines for product-specific range of message + * function codes, 0xF0 to 0xFF. * -------------------------------------------------------------------------- */ @@ -82,7 +86,7 @@ #define MPI2_VERSION_02_00 (0x0200) /* versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x0E) +#define MPI2_HEADER_VERSION_UNIT (0x0F) #define MPI2_HEADER_VERSION_DEV (0x00) #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) @@ -473,8 +477,6 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION /***************************************************************************** * * Message Functions -* 0x80 -> 0x8F reserved for private message use per product -* * *****************************************************************************/ @@ -506,6 +508,13 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION #define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C) /* RAID Accelerator*/ /* Host Based Discovery Action */ #define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F) +/* Power Management Control */ +#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30) +/* beginning of product-specific range */ +#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) +/* end of product-specific range */ +#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) + diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h index d4e9d6f8452e..e3728d736d85 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h @@ -6,7 +6,7 @@ * Title: MPI Configuration messages and pages * Creation Date: November 10, 2006 * - * mpi2_cnfg.h Version: 02.00.13 + * mpi2_cnfg.h Version: 02.00.14 * * Version History * --------------- @@ -109,6 +109,18 @@ * Added Ethernet configuration pages. * 10-28-09 02.00.13 Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY. * Added SAS PHY Page 4 structure and defines. + * 02-10-10 02.00.14 Modified the comments for the configuration page + * structures that contain an array of data. The host + * should use the "count" field in the page data (e.g. the + * NumPhys field) to determine the number of valid elements + * in the array. + * Added/modified some MPI2_MFGPAGE_DEVID_SAS defines. + * Added PowerManagementCapabilities to IO Unit Page 7. + * Added PortWidthModGroup field to + * MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines. + * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines. * -------------------------------------------------------------------------- */ @@ -373,8 +385,9 @@ typedef struct _MPI2_CONFIG_REPLY #define MPI2_MFGPAGE_DEVID_SAS2208_4 (0x0083) #define MPI2_MFGPAGE_DEVID_SAS2208_5 (0x0084) #define MPI2_MFGPAGE_DEVID_SAS2208_6 (0x0085) -#define MPI2_MFGPAGE_DEVID_SAS2208_7 (0x0086) -#define MPI2_MFGPAGE_DEVID_SAS2208_8 (0x0087) +#define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086) +#define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087) +#define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E) /* Manufacturing Page 0 */ @@ -540,7 +553,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_4 /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength or NumPhys at runtime. + * one and check the value returned for NumPhys at runtime. */ #ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES #define MPI2_MAN_PAGE_5_PHY_ENTRIES (1) @@ -618,7 +631,7 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check NumPhys at runtime. + * one and check the value returned for NumPhys at runtime. */ #ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX #define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1) @@ -731,7 +744,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. + * one and check the value returned for GPIOCount at runtime. */ #ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX #define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1) @@ -760,7 +773,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 /* * Upper layer code (drivers, utilities, etc.) should leave this define set to - * one and check Header.PageLength or NumDmaEngines at runtime. + * one and check the value returned for NumDmaEngines at runtime. */ #ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES #define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1) @@ -823,7 +836,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { U8 PCIeWidth; /* 0x06 */ U8 PCIeSpeed; /* 0x07 */ U32 ProcessorState; /* 0x08 */ - U32 Reserved2; /* 0x0C */ + U32 PowerManagementCapabilities; /* 0x0C */ U16 IOCTemperature; /* 0x10 */ U8 IOCTemperatureUnits; /* 0x12 */ U8 IOCSpeed; /* 0x13 */ @@ -831,7 +844,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { } MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7, Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t; -#define MPI2_IOUNITPAGE7_PAGEVERSION (0x00) +#define MPI2_IOUNITPAGE7_PAGEVERSION (0x01) /* defines for IO Unit Page 7 PCIeWidth field */ #define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01) @@ -852,6 +865,14 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { #define MPI2_IOUNITPAGE7_PSTATE_DISABLED (0x01) #define MPI2_IOUNITPAGE7_PSTATE_ENABLED (0x02) +/* defines for IO Unit Page 7 PowerManagementCapabilities field */ +#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED (0x00000400) +#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED (0x00000200) +#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED (0x00000100) +#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) +#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) + + /* defines for IO Unit Page 7 IOCTemperatureUnits field */ #define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00) #define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01) @@ -1195,7 +1216,7 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_3 /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength or NumPhys at runtime. + * one and check the value returned for NumPhys at runtime. */ #ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES #define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1) @@ -1269,7 +1290,7 @@ typedef struct _MPI2_RAIDVOL0_SETTINGS /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength at runtime. + * one and check the value returned for NumPhysDisks at runtime. */ #ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX #define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) @@ -1471,7 +1492,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.PageLength or NumPhysDiskPaths at runtime. + * one and check the value returned for NumPhysDiskPaths at runtime. */ #ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX #define MPI2_RAID_PHYS_DISK1_PATH_MAX (1) @@ -1633,7 +1654,7 @@ typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.ExtPageLength or NumPhys at runtime. + * one and check the value returned for NumPhys at runtime. */ #ifndef MPI2_SAS_IOUNIT0_PHY_MAX #define MPI2_SAS_IOUNIT0_PHY_MAX (1) @@ -1704,7 +1725,7 @@ typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.ExtPageLength or NumPhys at runtime. + * one and check the value returned for NumPhys at runtime. */ #ifndef MPI2_SAS_IOUNIT1_PHY_MAX #define MPI2_SAS_IOUNIT1_PHY_MAX (1) @@ -1795,7 +1816,7 @@ typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * four and check Header.ExtPageLength or NumPhys at runtime. + * one and check the value returned for NumPhys at runtime. */ #ifndef MPI2_SAS_IOUNIT4_PHY_MAX #define MPI2_SAS_IOUNIT4_PHY_MAX (4) @@ -1833,7 +1854,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS { U8 ControlFlags; /* 0x00 */ - U8 Reserved1; /* 0x01 */ + U8 PortWidthModGroup; /* 0x01 */ U16 InactivityTimerExponent; /* 0x02 */ U8 SATAPartialTimeout; /* 0x04 */ U8 Reserved2; /* 0x05 */ @@ -1853,6 +1874,9 @@ typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS { #define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE (0x02) #define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE (0x01) +/* defines for PortWidthModeGroup field */ +#define MPI2_SASIOUNIT5_PWMG_DISABLE (0xFF) + /* defines for InactivityTimerExponent field */ #define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER (0x7000) #define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER (12) @@ -1874,7 +1898,7 @@ typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS { /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.ExtPageLength or NumPhys at runtime. + * one and check the value returned for NumPhys at runtime. */ #ifndef MPI2_SAS_IOUNIT5_PHY_MAX #define MPI2_SAS_IOUNIT5_PHY_MAX (1) @@ -1892,7 +1916,132 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 { MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5, Mpi2SasIOUnitPage5_t, MPI2_POINTER pMpi2SasIOUnitPage5_t; -#define MPI2_SASIOUNITPAGE5_PAGEVERSION (0x00) +#define MPI2_SASIOUNITPAGE5_PAGEVERSION (0x01) + + +/* SAS IO Unit Page 6 */ + +typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS { + U8 CurrentStatus; /* 0x00 */ + U8 CurrentModulation; /* 0x01 */ + U8 CurrentUtilization; /* 0x02 */ + U8 Reserved1; /* 0x03 */ + U32 Reserved2; /* 0x04 */ +} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, + MPI2_POINTER PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, + Mpi2SasIOUnit6PortWidthModGroupStatus_t, + MPI2_POINTER pMpi2SasIOUnit6PortWidthModGroupStatus_t; + +/* defines for CurrentStatus field */ +#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE (0x00) +#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED (0x01) +#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG (0x02) +#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN (0x03) +#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY (0x04) +#define MPI2_SASIOUNIT6_STATUS_INACTIVE (0x05) +#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT (0x06) +#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST (0x07) + +/* defines for CurrentModulation field */ +#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT (0x00) +#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT (0x01) +#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT (0x02) +#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03) + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumGroups at runtime. + */ +#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX +#define MPI2_SAS_IOUNIT6_GROUP_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 { + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 Reserved2; /* 0x0C */ + U8 NumGroups; /* 0x10 */ + U8 Reserved3; /* 0x11 */ + U16 Reserved4; /* 0x12 */ + MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS + PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /* 0x14 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_6, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6, + Mpi2SasIOUnitPage6_t, MPI2_POINTER pMpi2SasIOUnitPage6_t; + +#define MPI2_SASIOUNITPAGE6_PAGEVERSION (0x00) + + +/* SAS IO Unit Page 7 */ + +typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS { + U8 Flags; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U8 Threshold75Pct; /* 0x04 */ + U8 Threshold50Pct; /* 0x05 */ + U8 Threshold25Pct; /* 0x06 */ + U8 Reserved3; /* 0x07 */ +} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, + MPI2_POINTER PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, + Mpi2SasIOUnit7PortWidthModGroupSettings_t, + MPI2_POINTER pMpi2SasIOUnit7PortWidthModGroupSettings_t; + +/* defines for Flags field */ +#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION (0x01) + + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * one and check the value returned for NumGroups at runtime. + */ +#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX +#define MPI2_SAS_IOUNIT7_GROUP_MAX (1) +#endif + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 { + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U8 SamplingInterval; /* 0x08 */ + U8 WindowLength; /* 0x09 */ + U16 Reserved1; /* 0x0A */ + U32 Reserved2; /* 0x0C */ + U32 Reserved3; /* 0x10 */ + U8 NumGroups; /* 0x14 */ + U8 Reserved4; /* 0x15 */ + U16 Reserved5; /* 0x16 */ + MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS + PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX]; /* 0x18 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_7, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7, + Mpi2SasIOUnitPage7_t, MPI2_POINTER pMpi2SasIOUnitPage7_t; + +#define MPI2_SASIOUNITPAGE7_PAGEVERSION (0x00) + + +/* SAS IO Unit Page 8 */ + +typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 { + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 PowerManagementCapabilities;/* 0x0C */ + U32 Reserved2; /* 0x10 */ +} MPI2_CONFIG_PAGE_SASIOUNIT_8, + MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8, + Mpi2SasIOUnitPage8_t, MPI2_POINTER pMpi2SasIOUnitPage8_t; + +#define MPI2_SASIOUNITPAGE8_PAGEVERSION (0x00) + +/* defines for PowerManagementCapabilities field */ +#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x000001000) +#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x000000800) +#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x000000400) +#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x000000200) +#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x000000100) +#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x000000010) +#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x000000008) +#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x000000004) +#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x000000002) +#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x000000001) @@ -2182,7 +2331,7 @@ typedef struct _MPI2_SASPHY2_PHY_EVENT { /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.ExtPageLength or NumPhyEvents at runtime. + * one and check the value returned for NumPhyEvents at runtime. */ #ifndef MPI2_SASPHY2_PHY_EVENT_MAX #define MPI2_SASPHY2_PHY_EVENT_MAX (1) @@ -2274,7 +2423,7 @@ typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG { /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.ExtPageLength or NumPhyEvents at runtime. + * one and check the value returned for NumPhyEvents at runtime. */ #ifndef MPI2_SASPHY3_PHY_EVENT_MAX #define MPI2_SASPHY3_PHY_EVENT_MAX (1) @@ -2385,7 +2534,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.ExtPageLength or NumPhys at runtime. + * one and check the value returned for NumLogEntries at runtime. */ #ifndef MPI2_LOG_0_NUM_LOG_ENTRIES #define MPI2_LOG_0_NUM_LOG_ENTRIES (1) @@ -2435,7 +2584,7 @@ typedef struct _MPI2_CONFIG_PAGE_LOG_0 /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to - * one and check Header.ExtPageLength or NumPhys at runtime. + * one and check the value returned for NumElements at runtime. */ #ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS #define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1) diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h index 220bf65a9216..c4c99dfcb820 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h @@ -6,7 +6,7 @@ * Title: MPI SCSI initiator mode messages and structures * Creation Date: June 23, 2006 * - * mpi2_init.h Version: 02.00.08 + * mpi2_init.h Version: 02.00.09 * * Version History * --------------- @@ -31,6 +31,7 @@ * both SCSI IO Error Reply and SCSI Task Management Reply. * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY. * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define. + * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it. * -------------------------------------------------------------------------- */ @@ -57,20 +58,6 @@ typedef struct } MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32, Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t; -/* TBD: I don't think this is needed for MPI2/Gen2 */ -#if 0 -typedef struct -{ - U8 CDB[16]; /* 0x00 */ - U32 DataLength; /* 0x10 */ - U32 PrimaryReferenceTag; /* 0x14 */ - U16 PrimaryApplicationTag; /* 0x18 */ - U16 PrimaryApplicationTagMask; /* 0x1A */ - U32 TransferLength; /* 0x1C */ -} MPI2_SCSI_IO32_CDB_EEDP16, MPI2_POINTER PTR_MPI2_SCSI_IO32_CDB_EEDP16, - Mpi2ScsiIo32CdbEedp16_t, MPI2_POINTER pMpi2ScsiIo32CdbEedp16_t; -#endif - typedef union { U8 CDB32[32]; diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h index f18f114922ba..495bedc4d1f7 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h @@ -6,7 +6,7 @@ * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: October 11, 2006 * - * mpi2_ioc.h Version: 02.00.13 + * mpi2_ioc.h Version: 02.00.14 * * Version History * --------------- @@ -98,6 +98,9 @@ * (MPI2_FW_HEADER_PID_). * Modified values for SAS ProductID Family * (MPI2_FW_HEADER_PID_FAMILY_). + * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines. + * Added PowerManagementControl Request structures and + * defines. * -------------------------------------------------------------------------- */ @@ -469,6 +472,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY #define MPI2_EVENT_SAS_PHY_COUNTER (0x0022) #define MPI2_EVENT_GPIO_INTERRUPT (0x0023) #define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024) +#define MPI2_EVENT_SAS_QUIESCE (0x0025) /* Log Entry Added Event data */ @@ -895,6 +899,22 @@ typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER { * */ +/* SAS Quiesce Event data */ + +typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE { + U8 ReasonCode; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 Reserved3; /* 0x04 */ +} MPI2_EVENT_DATA_SAS_QUIESCE, + MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_QUIESCE, + Mpi2EventDataSasQuiesce_t, MPI2_POINTER pMpi2EventDataSasQuiesce_t; + +/* SAS Quiesce Event data ReasonCode values */ +#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED (0x01) +#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED (0x02) + + /* Host Based Discovery Phy Event data */ typedef struct _MPI2_EVENT_HBD_PHY_SAS { @@ -1006,6 +1026,7 @@ typedef struct _MPI2_FW_DOWNLOAD_REQUEST #define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) #define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) #define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) +#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A) #define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) /* FWDownload TransactionContext Element */ @@ -1183,7 +1204,6 @@ typedef struct _MPI2_FW_IMAGE_HEADER #define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00) #define MPI2_FW_HEADER_PID_PROD_A (0x0000) -#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00) #define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200) #define MPI2_FW_HEADER_PID_PROD_IR_SCSI (0x0700) @@ -1407,5 +1427,100 @@ typedef struct _MPI2_INIT_IMAGE_FOOTER #define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14) +/**************************************************************************** +* PowerManagementControl message +****************************************************************************/ + +/* PowerManagementControl Request message */ +typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST { + U8 Feature; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U8 Parameter1; /* 0x0C */ + U8 Parameter2; /* 0x0D */ + U8 Parameter3; /* 0x0E */ + U8 Parameter4; /* 0x0F */ + U32 Reserved5; /* 0x10 */ + U32 Reserved6; /* 0x14 */ +} MPI2_PWR_MGMT_CONTROL_REQUEST, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REQUEST, + Mpi2PwrMgmtControlRequest_t, MPI2_POINTER pMpi2PwrMgmtControlRequest_t; + +/* defines for the Feature field */ +#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01) +#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02) +#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) +#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04) +#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80) +#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF) + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */ +/* Parameter1 contains a PHY number */ +/* Parameter2 indicates power condition action using these defines */ +#define MPI2_PM_CONTROL_PARAM2_PARTIAL (0x01) +#define MPI2_PM_CONTROL_PARAM2_SLUMBER (0x02) +#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT (0x03) +/* Parameter3 and Parameter4 are reserved */ + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION + * Feature */ +/* Parameter1 contains SAS port width modulation group number */ +/* Parameter2 indicates IOC action using these defines */ +#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP (0x01) +#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION (0x02) +#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP (0x03) +/* Parameter3 indicates desired modulation level using these defines */ +#define MPI2_PM_CONTROL_PARAM3_25_PERCENT (0x00) +#define MPI2_PM_CONTROL_PARAM3_50_PERCENT (0x01) +#define MPI2_PM_CONTROL_PARAM3_75_PERCENT (0x02) +#define MPI2_PM_CONTROL_PARAM3_100_PERCENT (0x03) +/* Parameter4 is reserved */ + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */ +/* Parameter1 indicates desired PCIe link speed using these defines */ +#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) +#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) +#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) +/* Parameter2 indicates desired PCIe link width using these defines */ +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) +/* Parameter3 and Parameter4 are reserved */ + +/* parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */ +/* Parameter1 indicates desired IOC hardware clock speed using these defines */ +#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED (0x01) +#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED (0x02) +#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED (0x04) +#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED (0x08) +/* Parameter2, Parameter3, and Parameter4 are reserved */ + + +/* PowerManagementControl Reply message */ +typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY { + U8 Feature; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U16 Reserved5; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI2_PWR_MGMT_CONTROL_REPLY, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REPLY, + Mpi2PwrMgmtControlReply_t, MPI2_POINTER pMpi2PwrMgmtControlReply_t; + + #endif diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 9ce225303938..87c686525f07 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -223,9 +223,12 @@ static struct pci_device_id scsih_pci_table[] = { PCI_ANY_ID, PCI_ANY_ID }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6, PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_7, + /* Mustang ~ 2308 */ + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1, PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_8, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */ }; -- cgit v1.2.3 From 570c67ac443dab5c46e5744e950f0539724cb65d Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:43:17 +0530 Subject: [SCSI] mpt2sas: Added sysfs support for trace buffer Added support so the diag ring buffer can be pulled via sysfs Added three new shost attributes: host_trace_buffer, host_trace_buffer_enable, and host_trace_buffer_size. The host_trace_buffer_enable attribute is used to either post or release the trace buffers. The host_trace_buffer_size attribute contains the size of the trace buffer. The host_trace_buffer atttribute contains a maximum 4KB window of the buffer. In order to read the entire host buffer, you will need to write the offset to host_trace_buffer prior to reading it. release the host buffer, then write the entire host buffer contents to a file. In addition to this enhancement, we moved the automatic posting of host buffers at driver load time to be called prior to port_enable, instead of after. That way discovery is available in the host buffer. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 10 +- drivers/scsi/mpt2sas/mpt2sas_base.h | 2 + drivers/scsi/mpt2sas/mpt2sas_ctl.c | 192 ++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 88befc798469..93c06239d951 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3529,8 +3529,12 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) if (sleep_flag == CAN_SLEEP) _base_static_config_pages(ioc); - if (ioc->wait_for_port_enable_to_complete && disable_discovery > 0) - return r; + if (ioc->wait_for_port_enable_to_complete) { + if (diag_buffer_enable != 0) + mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable); + if (disable_discovery > 0) + return r; + } r = _base_send_port_enable(ioc, sleep_flag); if (r) @@ -3679,8 +3683,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) goto out_free_resources; mpt2sas_base_start_watchdog(ioc); - if (diag_buffer_enable != 0) - mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable); return 0; out_free_resources: diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index a4a731529226..ffe93984e56a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -750,6 +750,8 @@ struct MPT2SAS_ADAPTER { Mpi2ManufacturingPage10_t manu_pg10; u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23]; u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; + u32 ring_buffer_offset; + u32 ring_buffer_sz; }; typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 25c866e3e900..371f063a926c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -2603,6 +2603,195 @@ _ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr, static DEVICE_ATTR(ioc_reset_count, S_IRUGO, _ctl_ioc_reset_count_show, NULL); +struct DIAG_BUFFER_START { + u32 Size; + u32 DiagVersion; + u8 BufferType; + u8 Reserved[3]; + u32 Reserved1; + u32 Reserved2; + u32 Reserved3; +}; +/** + * _ctl_host_trace_buffer_size_show - host buffer size (trace only) + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read-only' shost attribute. + */ +static ssize_t +_ctl_host_trace_buffer_size_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + u32 size = 0; + struct DIAG_BUFFER_START *request_data; + + if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { + printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " + "registered\n", ioc->name, __func__); + return 0; + } + + if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & + MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { + printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " + "registered\n", ioc->name, __func__); + return 0; + } + + request_data = (struct DIAG_BUFFER_START *) + ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]; + if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 || + le32_to_cpu(request_data->DiagVersion) == 0x01000000) && + le32_to_cpu(request_data->Reserved3) == 0x4742444c) + size = le32_to_cpu(request_data->Size); + + ioc->ring_buffer_sz = size; + return snprintf(buf, PAGE_SIZE, "%d\n", size); +} +static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO, + _ctl_host_trace_buffer_size_show, NULL); + +/** + * _ctl_host_trace_buffer_show - firmware ring buffer (trace only) + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read/write' shost attribute. + * + * You will only be able to read 4k bytes of ring buffer at a time. + * In order to read beyond 4k bytes, you will have to write out the + * offset to the same attribute, it will move the pointer. + */ +static ssize_t +_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + void *request_data; + u32 size; + + if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { + printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " + "registered\n", ioc->name, __func__); + return 0; + } + + if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & + MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { + printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not " + "registered\n", ioc->name, __func__); + return 0; + } + + if (ioc->ring_buffer_offset > ioc->ring_buffer_sz) + return 0; + + size = ioc->ring_buffer_sz - ioc->ring_buffer_offset; + size = (size > PAGE_SIZE) ? PAGE_SIZE : size; + request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset; + memcpy(buf, request_data, size); + return size; +} + +static ssize_t +_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + int val = 0; + + if (sscanf(buf, "%d", &val) != 1) + return -EINVAL; + + ioc->ring_buffer_offset = val; + return strlen(buf); +} +static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR, + _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store); + +/*****************************************/ + +/** + * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only) + * @cdev - pointer to embedded class device + * @buf - the buffer returned + * + * A sysfs 'read/write' shost attribute. + * + * This is a mechnism to post/release host_trace_buffers + */ +static ssize_t +_ctl_host_trace_buffer_enable_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + + if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) || + ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & + MPT2_DIAG_BUFFER_IS_REGISTERED) == 0)) + return snprintf(buf, PAGE_SIZE, "off\n"); + else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & + MPT2_DIAG_BUFFER_IS_RELEASED)) + return snprintf(buf, PAGE_SIZE, "release\n"); + else + return snprintf(buf, PAGE_SIZE, "post\n"); +} + +static ssize_t +_ctl_host_trace_buffer_enable_store(struct device *cdev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + char str[10] = ""; + struct mpt2_diag_register diag_register; + u8 issue_reset = 0; + + if (sscanf(buf, "%s", str) != 1) + return -EINVAL; + + if (!strcmp(str, "post")) { + /* exit out if host buffers are already posted */ + if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) && + (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & + MPT2_DIAG_BUFFER_IS_REGISTERED) && + ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & + MPT2_DIAG_BUFFER_IS_RELEASED) == 0)) + goto out; + memset(&diag_register, 0, sizeof(struct mpt2_diag_register)); + printk(MPT2SAS_INFO_FMT "posting host trace buffers\n", + ioc->name); + diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; + diag_register.requested_buffer_size = (1024 * 1024); + diag_register.unique_id = 0x7075900; + ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0; + _ctl_diag_register_2(ioc, &diag_register); + } else if (!strcmp(str, "release")) { + /* exit out if host buffers are already released */ + if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) + goto out; + if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & + MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) + goto out; + if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & + MPT2_DIAG_BUFFER_IS_RELEASED)) + goto out; + printk(MPT2SAS_INFO_FMT "releasing host trace buffer\n", + ioc->name); + _ctl_send_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, &issue_reset); + } + + out: + return strlen(buf); +} +static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR, + _ctl_host_trace_buffer_enable_show, _ctl_host_trace_buffer_enable_store); struct device_attribute *mpt2sas_host_attrs[] = { &dev_attr_version_fw, @@ -2621,6 +2810,9 @@ struct device_attribute *mpt2sas_host_attrs[] = { &dev_attr_fw_queue_depth, &dev_attr_host_sas_address, &dev_attr_ioc_reset_count, + &dev_attr_host_trace_buffer_size, + &dev_attr_host_trace_buffer, + &dev_attr_host_trace_buffer_enable, NULL, }; -- cgit v1.2.3 From eabb08ad2d3b0257cd2c9aed4f106fb39d14604a Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:43:57 +0530 Subject: [SCSI] mpt2sas: print level KERN_DEBUG is replaced by KERN_INFO Converting print level from MPT2SAS_DEBUG_FMT to MPT2SAS_INFO_FMT. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 82 ++++++++++++++++---------------- drivers/scsi/mpt2sas/mpt2sas_base.h | 1 - drivers/scsi/mpt2sas/mpt2sas_config.c | 4 +- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 68 +++++++++++++------------- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 56 +++++++++++----------- drivers/scsi/mpt2sas/mpt2sas_transport.c | 16 +++---- 6 files changed, 113 insertions(+), 114 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 93c06239d951..3774b0742b2b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1242,7 +1242,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) u64 pio_chip = 0; u64 chip_phys = 0; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); @@ -1865,7 +1865,7 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc) static void _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) { - dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); if (ioc->request) { @@ -1951,7 +1951,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) u32 retry_sz; u16 max_request_credit; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); retry_sz = 0; @@ -2378,7 +2378,7 @@ _base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout, do { int_status = readl(&ioc->chip->HostInterruptStatus); if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { - dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "successfull count(%d), timeout(%d)\n", ioc->name, __func__, count, timeout)); return 0; @@ -2419,7 +2419,7 @@ _base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout, do { int_status = readl(&ioc->chip->HostInterruptStatus); if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { - dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "successfull count(%d), timeout(%d)\n", ioc->name, __func__, count, timeout)); return 0; @@ -2467,7 +2467,7 @@ _base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout, do { doorbell_reg = readl(&ioc->chip->Doorbell); if (!(doorbell_reg & MPI2_DOORBELL_USED)) { - dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "successfull count(%d), timeout(%d)\n", ioc->name, __func__, count, timeout)); return 0; @@ -2641,9 +2641,9 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes, if (ioc->logging_level & MPT_DEBUG_INIT) { mfp = (u32 *)reply; - printk(KERN_DEBUG "\toffset:data\n"); + printk(KERN_INFO "\toffset:data\n"); for (i = 0; i < reply_bytes/4; i++) - printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4, + printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4, le32_to_cpu(mfp[i])); } return 0; @@ -2676,7 +2676,7 @@ mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, void *request; u16 wait_state_count; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); mutex_lock(&ioc->base_cmds.mutex); @@ -2781,7 +2781,7 @@ mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, void *request; u16 wait_state_count; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); mutex_lock(&ioc->base_cmds.mutex); @@ -2869,7 +2869,7 @@ _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag) Mpi2PortFactsReply_t mpi_reply, *pfacts; int mpi_reply_sz, mpi_request_sz, r; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); mpi_reply_sz = sizeof(Mpi2PortFactsReply_t); @@ -2911,7 +2911,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) Mpi2IOCFactsReply_t mpi_reply, *facts; int mpi_reply_sz, mpi_request_sz, r; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t); @@ -2983,7 +2983,7 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) struct timeval current_time; u16 ioc_status; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); @@ -3044,9 +3044,9 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) int i; mfp = (u32 *)&mpi_request; - printk(KERN_DEBUG "\toffset:data\n"); + printk(KERN_INFO "\toffset:data\n"); for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++) - printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4, + printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4, le32_to_cpu(mfp[i])); } @@ -3125,7 +3125,7 @@ _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) r = -ETIME; goto out; } else - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n", + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n", ioc->name, __func__)); ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL, @@ -3185,7 +3185,7 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) int r = 0; int i; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); if (ioc->base_cmds.status & MPT2_CMD_PENDING) { @@ -3223,7 +3223,7 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) else r = -ETIME; } else - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n", + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n", ioc->name, __func__)); ioc->base_cmds.status = MPT2_CMD_NOT_USED; return r; @@ -3285,7 +3285,7 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) _base_save_msix_table(ioc); - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n", + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n", ioc->name)); count = 0; @@ -3293,7 +3293,7 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* Write magic sequence to WriteSequence register * Loop until in diagnostic mode */ - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "write magic " + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "write magic " "sequence\n", ioc->name)); writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence); @@ -3313,7 +3313,7 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) goto out; host_diagnostic = readl(&ioc->chip->HostDiagnostic); - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "wrote magic " + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "wrote magic " "sequence: count(%d), host_diagnostic(0x%08x)\n", ioc->name, count, host_diagnostic)); @@ -3321,7 +3321,7 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) hcb_size = readl(&ioc->chip->HCBSize); - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "diag reset: issued\n", + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "diag reset: issued\n", ioc->name)); writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER, &ioc->chip->HostDiagnostic); @@ -3348,29 +3348,29 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) if (host_diagnostic & MPI2_DIAG_HCB_MODE) { - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter " + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter " "assuming the HCB Address points to good F/W\n", ioc->name)); host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK; host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW; writel(host_diagnostic, &ioc->chip->HostDiagnostic); - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "re-enable the HCDW\n", ioc->name)); writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE, &ioc->chip->HCBSize); } - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter\n", + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter\n", ioc->name)); writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET, &ioc->chip->HostDiagnostic); - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "disable writes to the " + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "disable writes to the " "diagnostic register\n", ioc->name)); writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); - drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "Wait for FW to go to the " + drsprintk(ioc, printk(MPT2SAS_INFO_FMT "Wait for FW to go to the " "READY state\n", ioc->name)); ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20, sleep_flag); @@ -3404,18 +3404,18 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, u32 ioc_state; int rc; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); ioc_state = mpt2sas_base_get_iocstate(ioc, 0); - dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: ioc_state(0x%08x)\n", + dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n", ioc->name, __func__, ioc_state)); if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY) return 0; if (ioc_state & MPI2_DOORBELL_USED) { - dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell " + dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell " "active!\n", ioc->name)); goto issue_diag_reset; } @@ -3458,7 +3458,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) u16 smid; struct _tr_list *delayed_tr, *delayed_tr_next; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); /* clean the delayed target reset list */ @@ -3554,7 +3554,7 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) { struct pci_dev *pdev = ioc->pdev; - dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); _base_mask_interrupts(ioc); @@ -3587,7 +3587,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) { int r, i; - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); r = mpt2sas_base_map_resources(ioc); @@ -3719,7 +3719,7 @@ void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) { - dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); mpt2sas_base_stop_watchdog(ioc); @@ -3752,11 +3752,11 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) { switch (reset_phase) { case MPT2_IOC_PRE_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); break; case MPT2_IOC_AFTER_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); if (ioc->transport_cmds.status & MPT2_CMD_PENDING) { ioc->transport_cmds.status |= MPT2_CMD_RESET; @@ -3776,7 +3776,7 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) } break; case MPT2_IOC_DONE_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); break; } @@ -3836,7 +3836,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, int r; unsigned long flags; - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); if (mpt2sas_fwfault_debug) @@ -3854,7 +3854,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, do { ssleep(1); } while (ioc->shost_recovery == 1); - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: exit\n", ioc->name, + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name, __func__)); return ioc->ioc_reset_in_progress_status; } @@ -3874,7 +3874,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, if (!r) _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); out: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: %s\n", + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %s\n", ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); @@ -3884,7 +3884,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); mutex_unlock(&ioc->reset_in_progress_mutex); - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: exit\n", ioc->name, + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name, __func__)); return r; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index ffe93984e56a..08404b331f73 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -124,7 +124,6 @@ * logging format */ #define MPT2SAS_FMT "%s: " -#define MPT2SAS_DEBUG_FMT KERN_DEBUG MPT2SAS_FMT #define MPT2SAS_INFO_FMT KERN_INFO MPT2SAS_FMT #define MPT2SAS_NOTE_FMT KERN_NOTICE MPT2SAS_FMT #define MPT2SAS_WARN_FMT KERN_WARNING MPT2SAS_FMT diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c index c65442982d7b..e26f9206a521 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c @@ -159,7 +159,7 @@ _config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, if (!desc) return; - printk(MPT2SAS_DEBUG_FMT "%s: %s(%d), action(%d), form(0x%08x), " + printk(MPT2SAS_INFO_FMT "%s: %s(%d), action(%d), form(0x%08x), " "smid(%d)\n", ioc->name, calling_function_name, desc, mpi_request->Header.PageNumber, mpi_request->Action, le32_to_cpu(mpi_request->PageAddress), smid); @@ -168,7 +168,7 @@ _config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, return; if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) - printk(MPT2SAS_DEBUG_FMT + printk(MPT2SAS_INFO_FMT "\tiocstatus(0x%04x), loginfo(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->IOCStatus), le32_to_cpu(mpi_reply->IOCLogInfo)); diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 371f063a926c..55fbd5b69b83 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -188,14 +188,14 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, if (!desc) return; - printk(MPT2SAS_DEBUG_FMT "%s: %s, smid(%d)\n", + printk(MPT2SAS_INFO_FMT "%s: %s, smid(%d)\n", ioc->name, calling_function_name, desc, smid); if (!mpi_reply) return; if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) - printk(MPT2SAS_DEBUG_FMT + printk(MPT2SAS_INFO_FMT "\tiocstatus(0x%04x), loginfo(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->IOCStatus), le32_to_cpu(mpi_reply->IOCLogInfo)); @@ -206,7 +206,7 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, Mpi2SCSIIOReply_t *scsi_reply = (Mpi2SCSIIOReply_t *)mpi_reply; if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) - printk(MPT2SAS_DEBUG_FMT + printk(MPT2SAS_INFO_FMT "\tscsi_state(0x%02x), scsi_status" "(0x%02x)\n", ioc->name, scsi_reply->SCSIState, @@ -392,7 +392,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) switch (reset_phase) { case MPT2_IOC_PRE_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { if (!(ioc->diag_buffer_status[i] & @@ -405,7 +405,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) } break; case MPT2_IOC_AFTER_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) { ioc->ctl_cmds.status |= MPT2_CMD_RESET; @@ -414,7 +414,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) } break; case MPT2_IOC_DONE_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { @@ -531,7 +531,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); if (!found) { - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name, desc, le16_to_cpu(tm_request->DevHandle), lun)); tm_reply = ioc->ctl_cmds.reply; @@ -549,7 +549,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, return 1; } - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name, desc, le16_to_cpu(tm_request->DevHandle), lun, le16_to_cpu(tm_request->TaskMID))); @@ -756,7 +756,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, Mpi2SCSITaskManagementRequest_t *tm_request = (Mpi2SCSITaskManagementRequest_t *)mpi_request; - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "TASK_MGMT: " "handle(0x%04x), task_type(0x%02x)\n", ioc->name, le16_to_cpu(tm_request->DevHandle), tm_request->TaskType)); @@ -851,7 +851,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, Mpi2SCSITaskManagementReply_t *tm_reply = (Mpi2SCSITaskManagementReply_t *)mpi_reply; - printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: " + printk(MPT2SAS_INFO_FMT "TASK_MGMT: " "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " "TerminationCount(0x%08x)\n", ioc->name, le16_to_cpu(tm_reply->IOCStatus), @@ -950,7 +950,7 @@ _ctl_getiocinfo(void __user *arg) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); memset(&karg, 0 , sizeof(karg)); @@ -998,7 +998,7 @@ _ctl_eventquery(void __user *arg) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE; @@ -1031,7 +1031,7 @@ _ctl_eventenable(void __user *arg) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); if (ioc->event_log) @@ -1073,7 +1073,7 @@ _ctl_eventreport(void __user *arg) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); number_bytes = karg.hdr.max_data_size - @@ -1118,7 +1118,7 @@ _ctl_do_reset(void __user *arg) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, @@ -1219,7 +1219,7 @@ _ctl_btdh_mapping(void __user *arg) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); rc = _ctl_btdh_search_sas_device(ioc, &karg); @@ -1288,7 +1288,7 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, u16 ioc_status; u8 issue_reset = 0; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { @@ -1376,7 +1376,7 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), " + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(0x%p), " "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, (unsigned long long)request_data_dma, le32_to_cpu(mpi_request->BufferLength))); @@ -1414,10 +1414,10 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { ioc->diag_buffer_status[buffer_type] |= MPT2_DIAG_BUFFER_IS_REGISTERED; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", ioc->name, __func__)); } else { - printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " + printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " "log_info(0x%08x)\n", ioc->name, __func__, ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); rc = -EFAULT; @@ -1541,7 +1541,7 @@ _ctl_diag_unregister(void __user *arg) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); buffer_type = karg.unique_id & 0x000000ff; @@ -1611,7 +1611,7 @@ _ctl_diag_query(void __user *arg) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); karg.application_flags = 0; @@ -1689,7 +1689,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) int rc; unsigned long timeleft; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); rc = 0; @@ -1697,7 +1697,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) ioc_state = mpt2sas_base_get_iocstate(ioc, 1); if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "skipping due to FAULT state\n", ioc->name, __func__)); rc = -EAGAIN; @@ -1759,10 +1759,10 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { ioc->diag_buffer_status[buffer_type] |= MPT2_DIAG_BUFFER_IS_RELEASED; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", ioc->name, __func__)); } else { - printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " + printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " "log_info(0x%08x)\n", ioc->name, __func__, ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); rc = -EFAULT; @@ -1800,7 +1800,7 @@ _ctl_diag_release(void __user *arg, enum block_state state) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); buffer_type = karg.unique_id & 0x000000ff; @@ -1896,7 +1896,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); buffer_type = karg.unique_id & 0x000000ff; @@ -1927,7 +1927,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) } diag_data = (void *)(request_data + karg.starting_offset); - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(%p), " + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), " "offset(%d), sz(%d)\n", ioc->name, __func__, diag_data, karg.starting_offset, karg.bytes_to_read)); @@ -1942,11 +1942,11 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0) return 0; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: Reregister " + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: Reregister " "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type)); if ((ioc->diag_buffer_status[buffer_type] & MPT2_DIAG_BUFFER_IS_RELEASED) == 0) { - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "buffer_type(0x%02x) is still registered\n", ioc->name, __func__, buffer_type)); return 0; @@ -2020,10 +2020,10 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { ioc->diag_buffer_status[buffer_type] |= MPT2_DIAG_BUFFER_IS_REGISTERED; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n", + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n", ioc->name, __func__)); } else { - printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) " + printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) " "log_info(0x%08x)\n", ioc->name, __func__, ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); rc = -EFAULT; @@ -2140,7 +2140,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg) !ioc) return -ENODEV; - dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd)); break; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 87c686525f07..82c2d4c5ece6 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -435,7 +435,7 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, (ioc->bios_pg2.ReqBootDeviceForm & MPI2_BIOSPAGE2_FORM_MASK), &ioc->bios_pg2.RequestedBootDevice)) { - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: req_boot_device(0x%016llx)\n", ioc->name, __func__, (unsigned long long)sas_address)); @@ -450,7 +450,7 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, (ioc->bios_pg2.ReqAltBootDeviceForm & MPI2_BIOSPAGE2_FORM_MASK), &ioc->bios_pg2.RequestedAltBootDevice)) { - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: req_alt_boot_device(0x%016llx)\n", ioc->name, __func__, (unsigned long long)sas_address)); @@ -465,7 +465,7 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, (ioc->bios_pg2.CurrentBootDeviceForm & MPI2_BIOSPAGE2_FORM_MASK), &ioc->bios_pg2.CurrentBootDevice)) { - dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: current_boot_device(0x%016llx)\n", ioc->name, __func__, (unsigned long long)sas_address)); @@ -566,7 +566,7 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, { unsigned long flags; - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle" "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, sas_device->handle, (unsigned long long)sas_device->sas_address)); @@ -593,7 +593,7 @@ _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc, { unsigned long flags; - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle" "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, sas_device->handle, (unsigned long long)sas_device->sas_address)); @@ -695,7 +695,7 @@ _scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc, { unsigned long flags; - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle" "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__, raid_device->handle, (unsigned long long)raid_device->wwid)); @@ -2002,7 +2002,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel, ioc_state = mpt2sas_base_get_iocstate(ioc, 0); if (ioc_state & MPI2_DOORBELL_USED) { - dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell " + dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell " "active!\n", ioc->name)); mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER); @@ -2806,7 +2806,7 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, MPI2_EVENT_SAS_TOPO_ES_RESPONDING) { if (le16_to_cpu(local_event_data->ExpanderDevHandle) == expander_handle) { - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting ignoring flag\n", ioc->name)); fw_event->ignore = 1; } @@ -4347,9 +4347,9 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, status_str = "unknown status"; break; } - printk(MPT2SAS_DEBUG_FMT "sas topology change: (%s)\n", + printk(MPT2SAS_INFO_FMT "sas topology change: (%s)\n", ioc->name, status_str); - printk(KERN_DEBUG "\thandle(0x%04x), enclosure_handle(0x%04x) " + printk(KERN_INFO "\thandle(0x%04x), enclosure_handle(0x%04x) " "start_phy(%02d), count(%d)\n", le16_to_cpu(event_data->ExpanderDevHandle), le16_to_cpu(event_data->EnclosureHandle), @@ -4383,7 +4383,7 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, } link_rate = event_data->PHY[i].LinkRate >> 4; prev_link_rate = event_data->PHY[i].LinkRate & 0xF; - printk(KERN_DEBUG "\tphy(%02d), attached_handle(0x%04x): %s:" + printk(KERN_INFO "\tphy(%02d), attached_handle(0x%04x): %s:" " link rate: new(0x%02x), old(0x%02x)\n", phy_number, handle, status_str, link_rate, prev_link_rate); @@ -4427,7 +4427,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, _scsih_sas_host_refresh(ioc); if (fw_event->ignore) { - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander " + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring expander " "event\n", ioc->name)); return; } @@ -4453,7 +4453,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, /* handle siblings events */ for (i = 0; i < event_data->NumEntries; i++) { if (fw_event->ignore) { - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring " + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring " "expander event\n", ioc->name)); return; } @@ -4573,12 +4573,12 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, reason_str = "unknown reason"; break; } - printk(MPT2SAS_DEBUG_FMT "device status change: (%s)\n" + printk(MPT2SAS_INFO_FMT "device status change: (%s)\n" "\thandle(0x%04x), sas address(0x%016llx)", ioc->name, reason_str, le16_to_cpu(event_data->DevHandle), (unsigned long long)le64_to_cpu(event_data->SASAddress)); if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA) - printk(MPT2SAS_DEBUG_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name, + printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name, event_data->ASC, event_data->ASCQ); printk(KERN_INFO "\n"); } @@ -4662,7 +4662,7 @@ _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, break; } - printk(MPT2SAS_DEBUG_FMT "enclosure status change: (%s)\n" + printk(MPT2SAS_INFO_FMT "enclosure status change: (%s)\n" "\thandle(0x%04x), enclosure logical id(0x%016llx)" " number slots(%d)\n", ioc->name, reason_str, le16_to_cpu(event_data->EnclosureHandle), @@ -4713,10 +4713,10 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; #endif u16 ioc_status; - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: " + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primative: " "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, event_data->PortWidth)); - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); termination_count = 0; @@ -4760,7 +4760,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, } ioc->broadcast_aen_busy = 0; - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - exit, query_count = %d termination_count = %d\n", ioc->name, __func__, query_count, termination_count)); } @@ -4781,7 +4781,7 @@ _scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { - printk(MPT2SAS_DEBUG_FMT "discovery event: (%s)", ioc->name, + printk(MPT2SAS_INFO_FMT "discovery event: (%s)", ioc->name, (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? "start" : "stop"); if (event_data->DiscoveryStatus) @@ -5075,7 +5075,7 @@ _scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc, element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - printk(MPT2SAS_DEBUG_FMT "raid config change: (%s), elements(%d)\n", + printk(MPT2SAS_INFO_FMT "raid config change: (%s), elements(%d)\n", ioc->name, (le32_to_cpu(event_data->Flags) & MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? "foreign" : "native", event_data->NumElements); @@ -5128,7 +5128,7 @@ _scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc, element_str = "unknown element"; break; } - printk(KERN_DEBUG "\t(%s:%s), vol handle(0x%04x), " + printk(KERN_INFO "\t(%s:%s), vol handle(0x%04x), " "pd handle(0x%04x), pd num(0x%02x)\n", element_str, reason_str, le16_to_cpu(element->VolDevHandle), le16_to_cpu(element->PhysDiskDevHandle), @@ -5218,7 +5218,7 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, handle = le16_to_cpu(event_data->VolDevHandle); state = le32_to_cpu(event_data->NewValue); - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle(0x%04x), " + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), " "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, le32_to_cpu(event_data->PreviousValue), state)); @@ -5306,7 +5306,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, handle = le16_to_cpu(event_data->PhysDiskDevHandle); state = le32_to_cpu(event_data->NewValue); - dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle(0x%04x), " + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), " "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, le32_to_cpu(event_data->PreviousValue), state)); @@ -5494,7 +5494,7 @@ _scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work } if (ioc->logging_level & MPT_DEBUG_TASK_SET_FULL) - starget_printk(KERN_DEBUG, sas_device->starget, "task set " + starget_printk(KERN_INFO, sas_device->starget, "task set " "full: handle(0x%04x), sas_addr(0x%016llx), depth(%d)\n", handle, (unsigned long long)sas_address, current_depth); @@ -5885,11 +5885,11 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) { switch (reset_phase) { case MPT2_IOC_PRE_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); break; case MPT2_IOC_AFTER_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__)); if (ioc->scsih_cmds.status & MPT2_CMD_PENDING) { ioc->scsih_cmds.status |= MPT2_CMD_RESET; @@ -5906,7 +5906,7 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) _scsih_queue_rescan(ioc); break; case MPT2_IOC_DONE_RESET: - dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); _scsih_sas_host_refresh(ioc); _scsih_prep_device_scan(ioc); diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 6c94deeb7be7..f29ea5e78bb3 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -397,7 +397,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, sizeof(struct rep_manu_reply), data_out_dma + sizeof(struct rep_manu_request)); - dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - " + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - " "send to sas_addr(0x%016llx)\n", ioc->name, (unsigned long long)sas_address)); mpt2sas_base_put_smid_default(ioc, smid); @@ -415,7 +415,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, goto issue_host_reset; } - dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - " + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - " "complete\n", ioc->name)); if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { @@ -423,7 +423,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, mpi_reply = ioc->transport_cmds.reply; - dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - reply data transfer size(%d)\n", ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); @@ -449,7 +449,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, manufacture_reply->component_revision_id; } } else - dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - no reply\n", ioc->name)); issue_host_reset: @@ -1861,7 +1861,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4), dma_addr_in); - dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - " + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - " "sending smp request\n", ioc->name, __func__)); mpt2sas_base_put_smid_default(ioc, smid); @@ -1879,14 +1879,14 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, goto issue_host_reset; } - dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - " + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - " "complete\n", ioc->name, __func__)); if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) { mpi_reply = ioc->transport_cmds.reply; - dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - reply data transfer size(%d)\n", ioc->name, __func__, le16_to_cpu(mpi_reply->ResponseDataLength))); @@ -1897,7 +1897,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, rsp->resid_len -= le16_to_cpu(mpi_reply->ResponseDataLength); } else { - dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT + dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - no reply\n", ioc->name, __func__)); rc = -ENXIO; } -- cgit v1.2.3 From 7fbae67a3faa90abcbe949f1494769c84e51e189 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:45:17 +0530 Subject: [SCSI] mpt2sas: Tie a log info message to a specific PHY. Add support to display additional debug info for SCSI_IO and RAID_SCSI_IO_PASSTHROUGH sent from the normal entry queued entry point, as well as internal generated commands, and IOCTLS. The additional debug info included the phy number, as well as the sas address, enclosure logical id, and slot number. This debug info has to be enabled thru the logging_level command line option, by default this will not be displayed. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 2 ++ drivers/scsi/mpt2sas/mpt2sas_ctl.c | 42 ++++++++++++++++++++++++++++++++++++ drivers/scsi/mpt2sas/mpt2sas_scsih.c | 19 +++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 08404b331f73..e2c5cee6450e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -275,6 +275,7 @@ struct _internal_cmd { * @id: target id * @channel: target channel * @slot: number number + * @phy: phy identifier provided in sas device page 0 * @hidden_raid_component: set to 1 when this is a raid member * @responding: used in _scsih_sas_device_mark_responding */ @@ -293,6 +294,7 @@ struct _sas_device { int id; int channel; u16 slot; + u8 phy; u8 hidden_raid_component; u8 responding; }; diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 55fbd5b69b83..ce63a4a66706 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -80,6 +80,32 @@ enum block_state { BLOCKING, }; +/** + * _ctl_sas_device_find_by_handle - sas device search + * @ioc: per adapter object + * @handle: sas device handle (assigned by firmware) + * Context: Calling function should acquire ioc->sas_device_lock + * + * This searches for sas_device based on sas_address, then return sas_device + * object. + */ +static struct _sas_device * +_ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct _sas_device *sas_device, *r; + + r = NULL; + list_for_each_entry(sas_device, &ioc->sas_device_list, list) { + if (sas_device->handle != handle) + continue; + r = sas_device; + goto out; + } + + out: + return r; +} + #ifdef CONFIG_SCSI_MPT2SAS_LOGGING /** * _ctl_display_some_debug - debug routine @@ -205,6 +231,22 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { Mpi2SCSIIOReply_t *scsi_reply = (Mpi2SCSIIOReply_t *)mpi_reply; + struct _sas_device *sas_device = NULL; + unsigned long flags; + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _ctl_sas_device_find_by_handle(ioc, + le16_to_cpu(scsi_reply->DevHandle)); + if (sas_device) { + printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " + "phy(%d)\n", ioc->name, (unsigned long long) + sas_device->sas_address, sas_device->phy); + printk(MPT2SAS_WARN_FMT + "\tenclosure_logical_id(0x%016llx), slot(%d)\n", + ioc->name, sas_device->enclosure_logical_id, + sas_device->slot); + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) printk(MPT2SAS_INFO_FMT "\tscsi_state(0x%02x), scsi_status" diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 82c2d4c5ece6..db12e184d1d9 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -1749,9 +1749,10 @@ _scsih_slave_configure(struct scsi_device *sdev) } sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " - "sas_addr(0x%016llx), device_name(0x%016llx)\n", + "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n", ds, sas_device->handle, (unsigned long long)sas_device->sas_address, + sas_device->phy, (unsigned long long)sas_device->device_name); sdev_printk(KERN_INFO, sdev, "%s: " "enclosure_logical_id(0x%016llx), slot(%d)\n", ds, @@ -3128,6 +3129,8 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, char *desc_scsi_status = NULL; char *desc_scsi_state = ioc->tmp_string; u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); + struct _sas_device *sas_device = NULL; + unsigned long flags; if (log_info == 0x31170000) return; @@ -3243,6 +3246,19 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, strcat(desc_scsi_state, "autosense valid "); scsi_print_command(scmd); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, + le16_to_cpu(mpi_reply->DevHandle)); + if (sas_device) { + printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), phy(%d)\n", + ioc->name, sas_device->sas_address, sas_device->phy); + printk(MPT2SAS_WARN_FMT "\tenclosure_logical_id(0x%016llx), " + "slot(%d)\n", ioc->name, sas_device->enclosure_logical_id, + sas_device->slot); + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + printk(MPT2SAS_WARN_FMT "\tdev handle(0x%04x), " "ioc_status(%s)(0x%04x), smid(%d)\n", ioc->name, le16_to_cpu(mpi_reply->DevHandle), desc_ioc_state, @@ -4187,6 +4203,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) le16_to_cpu(sas_device_pg0.Slot); sas_device->device_info = device_info; sas_device->sas_address = sas_address; + sas_device->phy = sas_device_pg0.PhyNum; sas_device->hidden_raid_component = is_pd; /* get enclosure_logical_id */ -- cgit v1.2.3 From f3eedd698ebafd0fe8a292672604a2db61c2c00a Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:46:13 +0530 Subject: [SCSI] mpt2sas: Redesign Raid devices event handling using pd_handles per HBA Actual problem : Driver may receiving the top level expander removal event prior to all the individual PD removal events, hence the driver is breaking down all the PDs in advanced to the actaul PD UNHIDE event. Driver sends multiple Target Resets to the same volume handle for each individual PD removal. FIX DESCRIPTION: To fix this issue, the entire PD device handshake protocal has to be moved to interrupt context so the breakdown occurs immediately after the actual UNHIDE event arrives. The driver will only issue one Target Reset to the volume handle, occurring after the FAILED or MISSING volume status event arrives from interrupt context. For the PD UNHIDE event, the driver will issue target resets to the PD handles, followed by OP_REMOVE. The driver will set the "deteleted" flag during interrupt context. A "pd_handle" bitmask was introduced so the driver has a list of known pds during entire life of the PD; this replaces the "hidden_raid_component" flag handle in the sas_device object. Each bit in the bitmask represents a device handle. The bit in the bitmask would be toggled ON/OFF when the HIDE/UNHIDE events arrive; also this pd_handle bitmask would bould be refreshed across host resets. Here we kept older behavior of sending target reset to volume when there is a single drive pull, wait for the reply, then send target resets to the PDs. We kept this behavior so the driver will behave the same for older versions of firmware. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 17 ++ drivers/scsi/mpt2sas/mpt2sas_base.h | 14 +- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 463 +++++++++++++++++++++++++++-------- 3 files changed, 391 insertions(+), 103 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 3774b0742b2b..bb8acf781690 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3468,6 +3468,12 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) kfree(delayed_tr); } + list_for_each_entry_safe(delayed_tr, delayed_tr_next, + &ioc->delayed_tr_volume_list, list) { + list_del(&delayed_tr->list); + kfree(delayed_tr); + } + /* initialize the scsi lookup free list */ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); INIT_LIST_HEAD(&ioc->free_list); @@ -3622,6 +3628,15 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) init_waitqueue_head(&ioc->reset_wq); + /* allocate memory pd handle bitmask list */ + ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8); + if (ioc->facts.MaxDevHandle % 8) + ioc->pd_handles_sz++; + ioc->pd_handles = kzalloc(ioc->pd_handles_sz, + GFP_KERNEL); + if (!ioc->pd_handles) + goto out_free_resources; + ioc->fwfault_debug = mpt2sas_fwfault_debug; /* base internal command bits */ @@ -3691,6 +3706,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) mpt2sas_base_free_resources(ioc); _base_release_memory_pools(ioc); pci_set_drvdata(ioc->pdev, NULL); + kfree(ioc->pd_handles); kfree(ioc->tm_cmds.reply); kfree(ioc->transport_cmds.reply); kfree(ioc->scsih_cmds.reply); @@ -3726,6 +3742,7 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) mpt2sas_base_free_resources(ioc); _base_release_memory_pools(ioc); pci_set_drvdata(ioc->pdev, NULL); + kfree(ioc->pd_handles); kfree(ioc->pfacts); kfree(ioc->ctl_cmds.reply); kfree(ioc->base_cmds.reply); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index e2c5cee6450e..6fdee1680a6b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -276,7 +276,6 @@ struct _internal_cmd { * @channel: target channel * @slot: number number * @phy: phy identifier provided in sas device page 0 - * @hidden_raid_component: set to 1 when this is a raid member * @responding: used in _scsih_sas_device_mark_responding */ struct _sas_device { @@ -295,7 +294,6 @@ struct _sas_device { int channel; u16 slot; u8 phy; - u8 hidden_raid_component; u8 responding; }; @@ -489,6 +487,8 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); * @ctl_cb_idx: clt internal commands * @base_cb_idx: base internal commands * @config_cb_idx: base internal commands + * @tm_tr_cb_idx : device removal target reset handshake + * @tm_tr_volume_cb_idx : volume removal target reset * @base_cmds: * @transport_cmds: * @scsih_cmds: @@ -517,6 +517,9 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); * @sas_device_lock: * @io_missing_delay: time for IO completed by fw when PDR enabled * @device_missing_delay: time for device missing by fw when PDR enabled + * @sas_id : used for setting volume target IDs + * @pd_handles : bitmask for PD handles + * @pd_handles_sz : size of pd_handle bitmask * @config_page_sz: config page size * @config_page: reserve memory for config page payload * @config_page_dma: @@ -569,6 +572,8 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); * @reply_post_free_dma: * @reply_post_free_dma_pool: * @reply_post_host_index: head index in the pool where FW completes IO + * @delayed_tr_list: target reset link list + * @delayed_tr_volume_list: volume target reset link list */ struct MPT2SAS_ADAPTER { struct list_head list; @@ -627,6 +632,7 @@ struct MPT2SAS_ADAPTER { u8 base_cb_idx; u8 config_cb_idx; u8 tm_tr_cb_idx; + u8 tm_tr_volume_cb_idx; u8 tm_sas_control_cb_idx; struct _internal_cmd base_cmds; struct _internal_cmd transport_cmds; @@ -670,6 +676,9 @@ struct MPT2SAS_ADAPTER { u16 device_missing_delay; int sas_id; + void *pd_handles; + u16 pd_handles_sz; + /* config page */ u16 config_page_sz; void *config_page; @@ -741,6 +750,7 @@ struct MPT2SAS_ADAPTER { u32 reply_post_host_index; struct list_head delayed_tr_list; + struct list_head delayed_tr_volume_list; /* diag buffer support */ u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index db12e184d1d9..b327d60fad1b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -70,6 +70,8 @@ static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_expander); static void _firmware_event_work(struct work_struct *work); +static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid); + /* global parameters */ LIST_HEAD(mpt2sas_ioc_list); @@ -84,6 +86,7 @@ static u8 config_cb_idx = -1; static int mpt_ids; static u8 tm_tr_cb_idx = -1 ; +static u8 tm_tr_volume_cb_idx = -1 ; static u8 tm_sas_control_cb_idx = -1; /* command line options */ @@ -1226,7 +1229,7 @@ _scsih_target_alloc(struct scsi_target *starget) sas_device->starget = starget; sas_device->id = starget->id; sas_device->channel = starget->channel; - if (sas_device->hidden_raid_component) + if (test_bit(sas_device->handle, ioc->pd_handles)) sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT; } @@ -2583,6 +2586,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) Mpi2SCSITaskManagementRequest_t *mpi_request; u16 smid; struct _sas_device *sas_device; + struct MPT2SAS_TARGET *sas_target_priv_data; unsigned long flags; struct _tr_list *delayed_tr; @@ -2592,11 +2596,20 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) return; } + /* if PD, then return */ + if (test_bit(handle, ioc->pd_handles)) + return; + spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - if (sas_device && sas_device->hidden_raid_component) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; + if (sas_device && sas_device->starget && + sas_device->starget->hostdata) { + sas_target_priv_data = sas_device->starget->hostdata; + sas_target_priv_data->deleted = 1; + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT + "setting delete flag: handle(0x%04x), " + "sas_addr(0x%016llx)\n", ioc->name, handle, + (unsigned long long) sas_device->sas_address)); } spin_unlock_irqrestore(&ioc->sas_device_lock, flags); @@ -2658,6 +2671,99 @@ _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, return 1; } +/** + * _scsih_tm_tr_volume_send - send target reset request for volumes + * @ioc: per adapter object + * @handle: device handle + * Context: interrupt time. + * + * This is designed to send muliple task management request at the same + * time to the fifo. If the fifo is full, we will append the request, + * and process it in a future completion. + */ +static void +_scsih_tm_tr_volume_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + Mpi2SCSITaskManagementRequest_t *mpi_request; + u16 smid; + struct _tr_list *delayed_tr; + + if (ioc->shost_recovery || ioc->remove_host) { + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " + "progress!\n", __func__, ioc->name)); + return; + } + + smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx); + if (!smid) { + delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); + if (!delayed_tr) + return; + INIT_LIST_HEAD(&delayed_tr->list); + delayed_tr->handle = handle; + list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list); + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT + "DELAYED:tr:handle(0x%04x), (open)\n", + ioc->name, handle)); + return; + } + + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), " + "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid, + ioc->tm_tr_volume_cb_idx)); + mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); + memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); + mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; + mpi_request->DevHandle = cpu_to_le16(handle); + mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; + mpt2sas_base_put_smid_hi_priority(ioc, smid); +} + +/** + * _scsih_tm_volume_tr_complete - target reset completion + * @ioc: per adapter object + * @smid: system request message index + * @msix_index: MSIX table index supplied by the OS + * @reply: reply message frame(lower 32bit addr) + * Context: interrupt time. + * + * Return 1 meaning mf should be freed from _base_interrupt + * 0 means the mf is freed from this function. + */ +static u8 +_scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, + u8 msix_index, u32 reply) +{ + u16 handle; + Mpi2SCSITaskManagementRequest_t *mpi_request_tm; + Mpi2SCSITaskManagementReply_t *mpi_reply = + mpt2sas_base_get_reply_virt_addr(ioc, reply); + + if (ioc->shost_recovery || ioc->remove_host) { + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " + "progress!\n", __func__, ioc->name)); + return 1; + } + + mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid); + handle = le16_to_cpu(mpi_request_tm->DevHandle); + if (handle != le16_to_cpu(mpi_reply->DevHandle)) { + dewtprintk(ioc, printk("spurious interrupt: " + "handle(0x%04x:0x%04x), smid(%d)!!!\n", handle, + le16_to_cpu(mpi_reply->DevHandle), smid)); + return 0; + } + + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT + "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), " + "loginfo(0x%08x), completed(%d)\n", ioc->name, + handle, smid, le16_to_cpu(mpi_reply->IOCStatus), + le32_to_cpu(mpi_reply->IOCLogInfo), + le32_to_cpu(mpi_reply->TerminationCount))); + + return _scsih_check_for_pending_tm(ioc, smid); +} + /** * _scsih_tm_tr_complete - * @ioc: per adapter object @@ -2684,7 +2790,6 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, mpt2sas_base_get_reply_virt_addr(ioc, reply); Mpi2SasIoUnitControlRequest_t *mpi_request; u16 smid_sas_ctrl; - struct _tr_list *delayed_tr; if (ioc->shost_recovery || ioc->remove_host) { dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " @@ -2725,6 +2830,35 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, mpi_request->DevHandle = mpi_request_tm->DevHandle; mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); + return _scsih_check_for_pending_tm(ioc, smid); +} + +/** + * _scsih_check_for_pending_tm - check for pending task management + * @ioc: per adapter object + * @smid: system request message index + * + * This will check delayed target reset list, and feed the + * next reqeust. + * + * Return 1 meaning mf should be freed from _base_interrupt + * 0 means the mf is freed from this function. + */ +static u8 +_scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + struct _tr_list *delayed_tr; + + if (!list_empty(&ioc->delayed_tr_volume_list)) { + delayed_tr = list_entry(ioc->delayed_tr_volume_list.next, + struct _tr_list, list); + mpt2sas_base_free_smid(ioc, smid); + _scsih_tm_tr_volume_send(ioc, delayed_tr->handle); + list_del(&delayed_tr->list); + kfree(delayed_tr); + return 0; + } + if (!list_empty(&ioc->delayed_tr_list)) { delayed_tr = list_entry(ioc->delayed_tr_list.next, struct _tr_list, list); @@ -2732,8 +2866,9 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, _scsih_tm_tr_send(ioc, delayed_tr->handle); list_del(&delayed_tr->list); kfree(delayed_tr); - return 0; /* tells base_interrupt not to free mf */ + return 0; } + return 1; } @@ -2816,6 +2951,165 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } +/** + * _scsih_set_volume_delete_flag - setting volume delete flag + * @ioc: per adapter object + * @handle: device handle + * + * This + * Return nothing. + */ +static void +_scsih_set_volume_delete_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle) +{ + struct _raid_device *raid_device; + struct MPT2SAS_TARGET *sas_target_priv_data; + unsigned long flags; + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_handle(ioc, handle); + if (raid_device && raid_device->starget && + raid_device->starget->hostdata) { + sas_target_priv_data = + raid_device->starget->hostdata; + sas_target_priv_data->deleted = 1; + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT + "setting delete flag: handle(0x%04x), " + "wwid(0x%016llx)\n", ioc->name, handle, + (unsigned long long) raid_device->wwid)); + } + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); +} + +/** + * _scsih_set_volume_handle_for_tr - set handle for target reset to volume + * @handle: input handle + * @a: handle for volume a + * @b: handle for volume b + * + * IR firmware only supports two raid volumes. The purpose of this + * routine is to set the volume handle in either a or b. When the given + * input handle is non-zero, or when a and b have not been set before. + */ +static void +_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b) +{ + if (!handle || handle == *a || handle == *b) + return; + if (!*a) + *a = handle; + else if (!*b) + *b = handle; +} + +/** + * _scsih_check_ir_config_unhide_events - check for UNHIDE events + * @ioc: per adapter object + * @event_data: the event data payload + * Context: interrupt time. + * + * This routine will send target reset to volume, followed by target + * resets to the PDs. This is called when a PD has been removed, or + * volume has been deleted or removed. When the target reset is sent + * to volume, the PD target resets need to be queued to start upon + * completion of the volume target reset. + * + * Return nothing. + */ +static void +_scsih_check_ir_config_unhide_events(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataIrConfigChangeList_t *event_data) +{ + Mpi2EventIrConfigElement_t *element; + int i; + u16 handle, volume_handle, a, b; + struct _tr_list *delayed_tr; + + a = 0; + b = 0; + + /* Volume Resets for Deleted or Removed */ + element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; + for (i = 0; i < event_data->NumElements; i++, element++) { + if (element->ReasonCode == + MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED || + element->ReasonCode == + MPI2_EVENT_IR_CHANGE_RC_REMOVED) { + volume_handle = le16_to_cpu(element->VolDevHandle); + _scsih_set_volume_delete_flag(ioc, volume_handle); + _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); + } + } + + /* Volume Resets for UNHIDE events */ + element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; + for (i = 0; i < event_data->NumElements; i++, element++) { + if (le32_to_cpu(event_data->Flags) & + MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) + continue; + if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) { + volume_handle = le16_to_cpu(element->VolDevHandle); + _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); + } + } + + if (a) + _scsih_tm_tr_volume_send(ioc, a); + if (b) + _scsih_tm_tr_volume_send(ioc, b); + + /* PD target resets */ + element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; + for (i = 0; i < event_data->NumElements; i++, element++) { + if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) + continue; + handle = le16_to_cpu(element->PhysDiskDevHandle); + volume_handle = le16_to_cpu(element->VolDevHandle); + clear_bit(handle, ioc->pd_handles); + if (!volume_handle) + _scsih_tm_tr_send(ioc, handle); + else if (volume_handle == a || volume_handle == b) { + delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); + BUG_ON(!delayed_tr); + INIT_LIST_HEAD(&delayed_tr->list); + delayed_tr->handle = handle; + list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT + "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name, + handle)); + } else + _scsih_tm_tr_send(ioc, handle); + } +} + + +/** + * _scsih_check_volume_delete_events - set delete flag for volumes + * @ioc: per adapter object + * @event_data: the event data payload + * Context: interrupt time. + * + * This will handle the case when the cable connected to entire volume is + * pulled. We will take care of setting the deleted flag so normal IO will + * not be sent. + * + * Return nothing. + */ +static void +_scsih_check_volume_delete_events(struct MPT2SAS_ADAPTER *ioc, + Mpi2EventDataIrVolume_t *event_data) +{ + u32 state; + + if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) + return; + state = le32_to_cpu(event_data->NewValue); + if (state == MPI2_RAID_VOL_STATE_MISSING || state == + MPI2_RAID_VOL_STATE_FAILED) + _scsih_set_volume_delete_flag(ioc, + le16_to_cpu(event_data->VolDevHandle)); +} + /** * _scsih_flush_running_cmds - completing outstanding commands. * @ioc: per adapter object @@ -4204,7 +4498,6 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) sas_device->device_info = device_info; sas_device->sas_address = sas_address; sas_device->phy = sas_device_pg0.PhyNum; - sas_device->hidden_raid_component = is_pd; /* get enclosure_logical_id */ if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0( @@ -4224,62 +4517,6 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) return 0; } -/** - * _scsih_remove_pd_device - removing sas device pd object - * @ioc: per adapter object - * @sas_device_delete: the sas_device object - * - * For hidden raid components, we do driver-fw handshake from - * hotplug work threads. - * Return nothing. - */ -static void -_scsih_remove_pd_device(struct MPT2SAS_ADAPTER *ioc, struct _sas_device - sas_device) -{ - Mpi2SasIoUnitControlReply_t mpi_reply; - Mpi2SasIoUnitControlRequest_t mpi_request; - u16 vol_handle, handle; - - handle = sas_device.handle; - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle(0x%04x)," - " sas_addr(0x%016llx)\n", ioc->name, __func__, handle, - (unsigned long long) sas_device.sas_address)); - - vol_handle = sas_device.volume_handle; - if (!vol_handle) - return; - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset: " - "handle(0x%04x)\n", ioc->name, vol_handle)); - mpt2sas_scsih_issue_tm(ioc, vol_handle, 0, 0, 0, - MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30, NULL); - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset " - "done: handle(0x%04x)\n", ioc->name, vol_handle)); - if (ioc->shost_recovery) - return; - - /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle" - "(0x%04x)\n", ioc->name, handle)); - memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); - mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; - mpi_request.Operation = MPI2_SAS_OP_REMOVE_DEVICE; - mpi_request.DevHandle = cpu_to_le16(handle); - if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, - &mpi_request)) != 0) - printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: ioc_status" - "(0x%04x), loginfo(0x%08x)\n", ioc->name, - le16_to_cpu(mpi_reply.IOCStatus), - le32_to_cpu(mpi_reply.IOCLogInfo))); - - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: handle(0x%04x)," - " sas_addr(0x%016llx)\n", ioc->name, __func__, handle, - (unsigned long long) sas_device.sas_address)); -} - /** * _scsih_remove_device - removing sas device object * @ioc: per adapter object @@ -4310,9 +4547,6 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, sas_target_priv_data->deleted = 1; } - if (sas_device_backup.hidden_raid_component) - _scsih_remove_pd_device(ioc, sas_device_backup); - _scsih_ublock_io_device(ioc, sas_device_backup.handle); mpt2sas_transport_port_remove(ioc, sas_device_backup.sas_address, @@ -4909,17 +5143,15 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc, /** * _scsih_sas_volume_delete - delete volume * @ioc: per adapter object - * @element: IR config element data + * @handle: volume device handle * Context: user. * * Return nothing. */ static void -_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) +_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle) { struct _raid_device *raid_device; - u16 handle = le16_to_cpu(element->VolDevHandle); unsigned long flags; struct MPT2SAS_TARGET *sas_target_priv_data; @@ -4933,6 +5165,9 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, sas_target_priv_data->deleted = 1; scsi_remove_target(&raid_device->starget->dev); } + printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid" + "(0x%016llx)\n", ioc->name, raid_device->handle, + (unsigned long long) raid_device->wwid); _scsih_raid_device_remove(ioc, raid_device); } @@ -4961,7 +5196,7 @@ _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc, /* exposing raid component */ sas_device->volume_handle = 0; sas_device->volume_wwid = 0; - sas_device->hidden_raid_component = 0; + clear_bit(handle, ioc->pd_handles); _scsih_reprobe_target(sas_device->starget, 0); } @@ -4992,7 +5227,7 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, &sas_device->volume_handle); mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle, &sas_device->volume_wwid); - sas_device->hidden_raid_component = 1; + set_bit(handle, ioc->pd_handles); _scsih_reprobe_target(sas_device->starget, 1); } @@ -5041,13 +5276,13 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, u64 sas_address; u16 parent_handle; + set_bit(handle, ioc->pd_handles); + spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = _scsih_sas_device_find_by_handle(ioc, handle); spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) { - sas_device->hidden_raid_component = 1; + if (sas_device) return; - } if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { @@ -5191,7 +5426,8 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: case MPI2_EVENT_IR_CHANGE_RC_REMOVED: if (!foreign_config) - _scsih_sas_volume_delete(ioc, element); + _scsih_sas_volume_delete(ioc, + le16_to_cpu(element->VolDevHandle)); break; case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: _scsih_sas_pd_hide(ioc, element); @@ -5227,7 +5463,6 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u16 handle; u32 state; int rc; - struct MPT2SAS_TARGET *sas_target_priv_data; Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) @@ -5239,26 +5474,20 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, le32_to_cpu(event_data->PreviousValue), state)); - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - switch (state) { case MPI2_RAID_VOL_STATE_MISSING: case MPI2_RAID_VOL_STATE_FAILED: - if (!raid_device) - break; - if (raid_device->starget) { - sas_target_priv_data = raid_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - scsi_remove_target(&raid_device->starget->dev); - } - _scsih_raid_device_remove(ioc, raid_device); + _scsih_sas_volume_delete(ioc, handle); break; case MPI2_RAID_VOL_STATE_ONLINE: case MPI2_RAID_VOL_STATE_DEGRADED: case MPI2_RAID_VOL_STATE_OPTIMAL: + + spin_lock_irqsave(&ioc->raid_device_lock, flags); + raid_device = _scsih_raid_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); + if (raid_device) break; @@ -5327,19 +5556,21 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, le32_to_cpu(event_data->PreviousValue), state)); - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - switch (state) { case MPI2_RAID_PD_STATE_ONLINE: case MPI2_RAID_PD_STATE_DEGRADED: case MPI2_RAID_PD_STATE_REBUILDING: case MPI2_RAID_PD_STATE_OPTIMAL: - if (sas_device) { - sas_device->hidden_raid_component = 1; + case MPI2_RAID_PD_STATE_HOT_SPARE: + + set_bit(handle, ioc->pd_handles); + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = _scsih_sas_device_find_by_handle(ioc, handle); + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + + if (sas_device) return; - } if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, @@ -5369,7 +5600,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, case MPI2_RAID_PD_STATE_OFFLINE: case MPI2_RAID_PD_STATE_NOT_CONFIGURED: case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: - case MPI2_RAID_PD_STATE_HOT_SPARE: default: break; } @@ -5497,7 +5727,7 @@ _scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work sas_address = sas_device->sas_address; /* if hidden raid component, then change to volume characteristics */ - if (sas_device->hidden_raid_component && sas_device->volume_handle) { + if (test_bit(handle, ioc->pd_handles) && sas_device->volume_handle) { spin_lock_irqsave(&ioc->raid_device_lock, flags); raid_device = _scsih_raid_device_find_by_handle( ioc, sas_device->volume_handle); @@ -5722,9 +5952,11 @@ static void _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) { Mpi2RaidVolPage1_t volume_pg1; + Mpi2RaidPhysDiskPage0_t pd_pg0; Mpi2ConfigReply_t mpi_reply; u16 ioc_status; u16 handle; + u8 phys_disk_num; printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); @@ -5742,6 +5974,21 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) _scsih_mark_responding_raid_device(ioc, le64_to_cpu(volume_pg1.WWID), handle); } + + /* refresh the pd_handles */ + phys_disk_num = 0xFF; + memset(ioc->pd_handles, 0, ioc->pd_handles_sz); + while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, + &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, + phys_disk_num))) { + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + break; + phys_disk_num = pd_pg0.PhysDiskNum; + handle = le16_to_cpu(pd_pg0.DevHandle); + set_bit(handle, ioc->pd_handles); + } } /** @@ -6060,14 +6307,21 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, (Mpi2EventDataSasTopologyChangeList_t *) mpi_reply->EventData); break; - + case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: + _scsih_check_ir_config_unhide_events(ioc, + (Mpi2EventDataIrConfigChangeList_t *) + mpi_reply->EventData); + break; + case MPI2_EVENT_IR_VOLUME: + _scsih_check_volume_delete_events(ioc, + (Mpi2EventDataIrVolume_t *) + mpi_reply->EventData); + break; case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: case MPI2_EVENT_IR_OPERATION_STATUS: case MPI2_EVENT_SAS_DISCOVERY: case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: - case MPI2_EVENT_IR_VOLUME: case MPI2_EVENT_IR_PHYSICAL_DISK: - case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: case MPI2_EVENT_TASK_SET_FULL: break; @@ -6574,6 +6828,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->scsih_cb_idx = scsih_cb_idx; ioc->config_cb_idx = config_cb_idx; ioc->tm_tr_cb_idx = tm_tr_cb_idx; + ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx; ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; ioc->logging_level = logging_level; /* misc semaphores and spin locks */ @@ -6592,6 +6847,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ioc->raid_device_list); INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); INIT_LIST_HEAD(&ioc->delayed_tr_list); + INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); /* init shost parameters */ shost->max_cmd_len = 32; @@ -6894,6 +7150,10 @@ _scsih_init(void) tm_tr_cb_idx = mpt2sas_base_register_callback_handler( _scsih_tm_tr_complete); + + tm_tr_volume_cb_idx = mpt2sas_base_register_callback_handler( + _scsih_tm_volume_tr_complete); + tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler( _scsih_sas_control_complete); @@ -6933,6 +7193,7 @@ _scsih_exit(void) mpt2sas_base_release_callback_handler(ctl_cb_idx); mpt2sas_base_release_callback_handler(tm_tr_cb_idx); + mpt2sas_base_release_callback_handler(tm_tr_volume_cb_idx); mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); /* raid transport support */ -- cgit v1.2.3 From 3e2e833a547cbd0cb3fbe85a5f6ee71a93931fde Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:47:29 +0530 Subject: [SCSI] mpt2sas: Added -ENOMEM return type when allocation fails In the driver mpt2sas_base_attach subroutine, we need to add support to return the proper error code when there are memory allocation failures, e.g. returning -ENOMEM. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index bb8acf781690..d84874492cbf 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3634,8 +3634,10 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) ioc->pd_handles_sz++; ioc->pd_handles = kzalloc(ioc->pd_handles_sz, GFP_KERNEL); - if (!ioc->pd_handles) + if (!ioc->pd_handles) { + r = -ENOMEM; goto out_free_resources; + } ioc->fwfault_debug = mpt2sas_fwfault_debug; @@ -3676,6 +3678,13 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) goto out_free_resources; } + if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply || + !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply || + !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) { + r = -ENOMEM; + goto out_free_resources; + } + init_completion(&ioc->shost_recovery_done); for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) -- cgit v1.2.3 From d417d1c3a3c3b4d89a285f82a4e7710372e40a24 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:48:10 +0530 Subject: [SCSI] mpt2sas: Add additional check for responding volumes after Host Reset ISSUE DESCRIPTION: This test case involves creating two RAID1 volumes, then simultaneiously issue host reset and pull all the drives associated to the 1st raid volume. The observed behavour is the physical drives are removed, however the volume remains. The expected behavour is the volume as well as physical drives should be removed from OS. FIX: Add support in the post host reset device scan logic for raid volumes where the driver will have an additional check for responding raid volume where the status should be either online, optimal, or degraded. So for voluemes that have a status of missing or failed, the driver will mark them for deletion. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index b327d60fad1b..228961b94a68 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -5952,6 +5952,7 @@ static void _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) { Mpi2RaidVolPage1_t volume_pg1; + Mpi2RaidVolPage0_t volume_pg0; Mpi2RaidPhysDiskPage0_t pd_pg0; Mpi2ConfigReply_t mpi_reply; u16 ioc_status; @@ -5971,8 +5972,17 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) break; handle = le16_to_cpu(volume_pg1.DevHandle); - _scsih_mark_responding_raid_device(ioc, - le64_to_cpu(volume_pg1.WWID), handle); + + if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, + &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, + sizeof(Mpi2RaidVolPage0_t))) + continue; + + if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || + volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || + volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) + _scsih_mark_responding_raid_device(ioc, + le64_to_cpu(volume_pg1.WWID), handle); } /* refresh the pd_handles */ -- cgit v1.2.3 From 8e864a81e30ab996d3245ebd16a741b3614e6581 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:48:46 +0530 Subject: [SCSI] mpt2sas: Adding additional message to error escalation callback Adding additional messages to the error escallation callbacks which displays the wwid, sas address, handle, phy number, enclosure logical id, and slot. In the same eh callbacks, routines, the printks were converted to sdev_printks, which displays the bus target mapping. These additional modifications help better identify the device which is in recovery. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 143 +++++++++++++++++++++++++---------- 1 file changed, 104 insertions(+), 39 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 228961b94a68..854cc91e7aac 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2122,9 +2122,60 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel, return rc; } +/** + * _scsih_tm_display_info - displays info about the device + * @ioc: per adapter struct + * @scmd: pointer to scsi command object + * + * Called by task management callback handlers. + */ +static void +_scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) +{ + struct scsi_target *starget = scmd->device->sdev_target; + struct MPT2SAS_TARGET *priv_target = starget->hostdata; + struct _sas_device *sas_device = NULL; + unsigned long flags; + + if (!priv_target) + return; + + scsi_print_command(scmd); + if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { + starget_printk(KERN_INFO, starget, "volume handle(0x%04x), " + "volume wwid(0x%016llx)\n", + priv_target->handle, + (unsigned long long)priv_target->sas_address); + } else { + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + priv_target->sas_address); + if (sas_device) { + if (priv_target->flags & + MPT_TARGET_FLAGS_RAID_COMPONENT) { + starget_printk(KERN_INFO, starget, + "volume handle(0x%04x), " + "volume wwid(0x%016llx)\n", + sas_device->volume_handle, + (unsigned long long)sas_device->volume_wwid); + } + starget_printk(KERN_INFO, starget, + "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n", + sas_device->handle, + (unsigned long long)sas_device->sas_address, + sas_device->phy); + starget_printk(KERN_INFO, starget, + "enclosure_logical_id(0x%016llx), slot(%d)\n", + (unsigned long long)sas_device->enclosure_logical_id, + sas_device->slot); + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + } +} + /** * _scsih_abort - eh threads main abort routine - * @sdev: scsi device struct + * @scmd: pointer to scsi command object * * Returns SUCCESS if command aborted else FAILED */ @@ -2137,14 +2188,14 @@ _scsih_abort(struct scsi_cmnd *scmd) u16 handle; int r; - printk(MPT2SAS_INFO_FMT "attempting task abort! scmd(%p)\n", - ioc->name, scmd); - scsi_print_command(scmd); + sdev_printk(KERN_INFO, scmd->device, "attempting task abort! " + "scmd(%p)\n", scmd); + _scsih_tm_display_info(ioc, scmd); sas_device_priv_data = scmd->device->hostdata; if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - printk(MPT2SAS_INFO_FMT "device been deleted! scmd(%p)\n", - ioc->name, scmd); + sdev_printk(KERN_INFO, scmd->device, "device been deleted! " + "scmd(%p)\n", scmd); scmd->result = DID_NO_CONNECT << 16; scmd->scsi_done(scmd); r = SUCCESS; @@ -2176,14 +2227,14 @@ _scsih_abort(struct scsi_cmnd *scmd) MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, scmd); out: - printk(MPT2SAS_INFO_FMT "task abort: %s scmd(%p)\n", - ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); + sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n", + ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); return r; } /** * _scsih_dev_reset - eh threads main device reset routine - * @sdev: scsi device struct + * @scmd: pointer to scsi command object * * Returns SUCCESS if command aborted else FAILED */ @@ -2197,14 +2248,16 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) u16 handle; int r; - printk(MPT2SAS_INFO_FMT "attempting device reset! scmd(%p)\n", - ioc->name, scmd); - scsi_print_command(scmd); + struct scsi_target *starget = scmd->device->sdev_target; + + starget_printk(KERN_INFO, starget, "attempting target reset! " + "scmd(%p)\n", scmd); + _scsih_tm_display_info(ioc, scmd); sas_device_priv_data = scmd->device->hostdata; if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - printk(MPT2SAS_INFO_FMT "device been deleted! scmd(%p)\n", - ioc->name, scmd); + starget_printk(KERN_INFO, starget, "target been deleted! " + "scmd(%p)\n", scmd); scmd->result = DID_NO_CONNECT << 16; scmd->scsi_done(scmd); r = SUCCESS; @@ -2235,14 +2288,14 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, scmd); out: - printk(MPT2SAS_INFO_FMT "device reset: %s scmd(%p)\n", - ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); + sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", + ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); return r; } /** * _scsih_target_reset - eh threads main target reset routine - * @sdev: scsi device struct + * @scmd: pointer to scsi command object * * Returns SUCCESS if command aborted else FAILED */ @@ -2255,15 +2308,16 @@ _scsih_target_reset(struct scsi_cmnd *scmd) unsigned long flags; u16 handle; int r; + struct scsi_target *starget = scmd->device->sdev_target; - printk(MPT2SAS_INFO_FMT "attempting target reset! scmd(%p)\n", - ioc->name, scmd); - scsi_print_command(scmd); + starget_printk(KERN_INFO, starget, "attempting target reset! " + "scmd(%p)\n", scmd); + _scsih_tm_display_info(ioc, scmd); sas_device_priv_data = scmd->device->hostdata; if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - printk(MPT2SAS_INFO_FMT "target been deleted! scmd(%p)\n", - ioc->name, scmd); + starget_printk(KERN_INFO, starget, "target been deleted! " + "scmd(%p)\n", scmd); scmd->result = DID_NO_CONNECT << 16; scmd->scsi_done(scmd); r = SUCCESS; @@ -2294,14 +2348,14 @@ _scsih_target_reset(struct scsi_cmnd *scmd) 30, scmd); out: - printk(MPT2SAS_INFO_FMT "target reset: %s scmd(%p)\n", - ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); + starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", + ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); return r; } /** * _scsih_host_reset - eh threads main host reset routine - * @sdev: scsi device struct + * @scmd: pointer to scsi command object * * Returns SUCCESS if command aborted else FAILED */ @@ -3425,6 +3479,11 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); struct _sas_device *sas_device = NULL; unsigned long flags; + struct scsi_target *starget = scmd->device->sdev_target; + struct MPT2SAS_TARGET *priv_target = starget->hostdata; + + if (!priv_target) + return; if (log_info == 0x31170000) return; @@ -3541,22 +3600,28 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, scsi_print_command(scmd); - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, - le16_to_cpu(mpi_reply->DevHandle)); - if (sas_device) { - printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), phy(%d)\n", - ioc->name, sas_device->sas_address, sas_device->phy); - printk(MPT2SAS_WARN_FMT "\tenclosure_logical_id(0x%016llx), " - "slot(%d)\n", ioc->name, sas_device->enclosure_logical_id, - sas_device->slot); + if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { + printk(MPT2SAS_WARN_FMT "\tvolume wwid(0x%016llx)\n", ioc->name, + (unsigned long long)priv_target->sas_address); + } else { + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + priv_target->sas_address); + if (sas_device) { + printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " + "phy(%d)\n", ioc->name, sas_device->sas_address, + sas_device->phy); + printk(MPT2SAS_WARN_FMT + "\tenclosure_logical_id(0x%016llx), slot(%d)\n", + ioc->name, sas_device->enclosure_logical_id, + sas_device->slot); + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - printk(MPT2SAS_WARN_FMT "\tdev handle(0x%04x), " - "ioc_status(%s)(0x%04x), smid(%d)\n", ioc->name, - le16_to_cpu(mpi_reply->DevHandle), desc_ioc_state, - ioc_status, smid); + printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), " + "smid(%d)\n", ioc->name, le16_to_cpu(mpi_reply->DevHandle), + desc_ioc_state, ioc_status, smid); printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), " "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow, scsi_get_resid(scmd)); -- cgit v1.2.3 From 769578ff811e43ccddd96b15640fa7c9df65c374 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:49:28 +0530 Subject: [SCSI] mpt2sas: Copy sense buffer instead of working on direct memory location (1) driver was not setting the sense data size prior to sending SCSI_IO, resulting in the 0x31190000 loginfo (2) The driver needs to copy the sense data to local buffer prior to releasing the request message frame. If not, the sense buffer gets overwritten by the next SCSI_IO request. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 6 +++++- drivers/scsi/mpt2sas/mpt2sas_base.h | 2 ++ drivers/scsi/mpt2sas/mpt2sas_ctl.c | 25 +++++++++++++++++++++---- 3 files changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index d84874492cbf..1f22a764927a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3668,12 +3668,14 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) /* ctl module internal command bits */ ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); + ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; mutex_init(&ioc->ctl_cmds.mutex); if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply || !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply || - !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) { + !ioc->config_cmds.reply || !ioc->ctl_cmds.reply || + !ioc->ctl_cmds.sense) { r = -ENOMEM; goto out_free_resources; } @@ -3722,6 +3724,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) kfree(ioc->config_cmds.reply); kfree(ioc->base_cmds.reply); kfree(ioc->ctl_cmds.reply); + kfree(ioc->ctl_cmds.sense); kfree(ioc->pfacts); ioc->ctl_cmds.reply = NULL; ioc->base_cmds.reply = NULL; @@ -3754,6 +3757,7 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) kfree(ioc->pd_handles); kfree(ioc->pfacts); kfree(ioc->ctl_cmds.reply); + kfree(ioc->ctl_cmds.sense); kfree(ioc->base_cmds.reply); kfree(ioc->tm_cmds.reply); kfree(ioc->transport_cmds.reply); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 6fdee1680a6b..2bbb870a199a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -247,6 +247,7 @@ struct MPT2SAS_DEVICE { * @mutex: mutex * @done: completion * @reply: reply message pointer + * @sense: sense data * @status: MPT2_CMD_XXX status * @smid: system message id */ @@ -254,6 +255,7 @@ struct _internal_cmd { struct mutex mutex; struct completion done; void *reply; + void *sense; u16 status; u16 smid; }; diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index ce63a4a66706..c3f34a76913b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -275,6 +275,9 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { MPI2DefaultReply_t *mpi_reply; + Mpi2SCSIIOReply_t *scsiio_reply; + const void *sense_data; + u32 sz; if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) return 1; @@ -285,6 +288,20 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, if (mpi_reply) { memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID; + /* get sense data */ + if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || + mpi_reply->Function == + MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { + scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply; + if (scsiio_reply->SCSIState & + MPI2_SCSI_STATE_AUTOSENSE_VALID) { + sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, + le32_to_cpu(scsiio_reply->SenseCount)); + sense_data = mpt2sas_base_get_sense_buffer(ioc, + smid); + memcpy(ioc->ctl_cmds.sense, sense_data, sz); + } + } } #ifdef CONFIG_SCSI_MPT2SAS_LOGGING _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); @@ -618,7 +635,6 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, u8 issue_reset; u32 sz; void *psge; - void *priv_sense = NULL; void *data_out = NULL; dma_addr_t data_out_dma; size_t data_out_sz = 0; @@ -782,10 +798,10 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, { Mpi2SCSIIORequest_t *scsiio_request = (Mpi2SCSIIORequest_t *)mpi_request; + scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; scsiio_request->SenseBufferLowAddress = mpt2sas_base_get_sense_buffer_dma(ioc, smid); - priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); - memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); + memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE); if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) mpt2sas_base_put_smid_scsi_io(ioc, smid, le16_to_cpu(mpi_request->FunctionDependent1)); @@ -929,7 +945,8 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE); - if (copy_to_user(karg.sense_data_ptr, priv_sense, sz)) { + if (copy_to_user(karg.sense_data_ptr, + ioc->ctl_cmds.sense, sz)) { printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); ret = -ENODATA; -- cgit v1.2.3 From 1bbfa378afbf8a8bfa6f6523e4965398a578ad10 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:50:11 +0530 Subject: [SCSI] mpt2sas: Copy message frame before releasing to free pool to have a local reference. Current driver is not clearing the per device tm_busy flag following the Task Mangement request completion from the IOCTL path. When this flag is set, the IO queues are frozen. The reason the flag didn't get cleared is becuase the driver is referencing memory associated to the mpi request following the completion, when the memory had been reallocated for a new request. When the memory was reallocated, the driver didn't clear the flag becuase it was expecting a task managment reqeust, and the reallocated request was for SCSI_IO. To fix the problem the driver needs to have a cached backup copy of the original reqeust. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 56 ++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 18 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index c3f34a76913b..55ac1cb34778 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -626,7 +626,7 @@ static long _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command karg, void __user *mf, enum block_state state) { - MPI2RequestHeader_t *mpi_request; + MPI2RequestHeader_t *mpi_request = NULL, *request; MPI2DefaultReply_t *mpi_reply; u32 ioc_state; u16 ioc_status; @@ -679,31 +679,50 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", ioc->name, __func__); - smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); - if (!smid) { - printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ret = -EAGAIN; + mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL); + if (!mpi_request) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a memory for " + "mpi_request\n", ioc->name, __func__); + ret = -ENOMEM; goto out; } - ret = 0; - ioc->ctl_cmds.status = MPT2_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); - ioc->ctl_cmds.smid = smid; - data_out_sz = karg.data_out_size; - data_in_sz = karg.data_in_size; - /* copy in request message frame from user */ if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); ret = -EFAULT; - mpt2sas_base_free_smid(ioc, smid); goto out; } + if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { + smid = mpt2sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + ret = -EAGAIN; + goto out; + } + } else { + + smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); + if (!smid) { + printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", + ioc->name, __func__); + ret = -EAGAIN; + goto out; + } + } + + ret = 0; + ioc->ctl_cmds.status = MPT2_CMD_PENDING; + memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); + request = mpt2sas_base_get_msg_frame(ioc, smid); + memcpy(request, mpi_request, karg.data_sge_offset*4); + ioc->ctl_cmds.smid = smid; + data_out_sz = karg.data_out_size; + data_in_sz = karg.data_in_size; + if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { if (!le16_to_cpu(mpi_request->FunctionDependent1) || @@ -749,7 +768,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, } /* add scatter gather elements */ - psge = (void *)mpi_request + (karg.data_sge_offset*4); + psge = (void *)request + (karg.data_sge_offset*4); if (!data_out_sz && !data_in_sz) { mpt2sas_base_build_zero_len_sge(ioc, psge); @@ -797,7 +816,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: { Mpi2SCSIIORequest_t *scsiio_request = - (Mpi2SCSIIORequest_t *)mpi_request; + (Mpi2SCSIIORequest_t *)request; scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; scsiio_request->SenseBufferLowAddress = mpt2sas_base_get_sense_buffer_dma(ioc, smid); @@ -812,7 +831,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, case MPI2_FUNCTION_SCSI_TASK_MGMT: { Mpi2SCSITaskManagementRequest_t *tm_request = - (Mpi2SCSITaskManagementRequest_t *)mpi_request; + (Mpi2SCSITaskManagementRequest_t *)request; dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "TASK_MGMT: " "handle(0x%04x), task_type(0x%02x)\n", ioc->name, @@ -985,6 +1004,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, pci_free_consistent(ioc->pdev, data_out_sz, data_out, data_out_dma); + kfree(mpi_request); ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; mutex_unlock(&ioc->ctl_cmds.mutex); return ret; -- cgit v1.2.3 From d4572c3dbb00fa47b9e8cd496f12a8ec9e9b66c3 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Thu, 17 Jun 2010 13:50:57 +0530 Subject: [SCSI] mpt2sas: Bump version 06.100.00.00 Version upgrade patch Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 2bbb870a199a..0b0ef5e7899a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -69,11 +69,11 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation " #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "05.100.00.03" -#define MPT2SAS_MAJOR_VERSION 05 +#define MPT2SAS_DRIVER_VERSION "06.100.00.00" +#define MPT2SAS_MAJOR_VERSION 06 #define MPT2SAS_MINOR_VERSION 100 #define MPT2SAS_BUILD_VERSION 00 -#define MPT2SAS_RELEASE_VERSION 03 +#define MPT2SAS_RELEASE_VERSION 00 /* * Set MPT2SAS_SG_DEPTH value based on user input. -- cgit v1.2.3 From 73ee5d8672871bd69077ca71e7208a36bfa6343c Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 17 Jun 2010 13:55:13 -0500 Subject: [SCSI] ibmvfc: Fix soft lockup on resume This fixes a softlockup seen on resume. During resume, the CRQ must be reenabled. However, the H_ENABLE_CRQ hcall used to do this may return H_BUSY or H_LONG_BUSY. When this happens, the caller is expected to retry later. Normally the H_ENABLE_CRQ succeeds relatively soon. However, we have seen cases where this can take long enough to see softlockup warnings. This patch changes a simple loop, which was causing the softlockup, to a loop at task level which sleeps between retries rather than simply spinning. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 81 ++++++++++++++++++++++++++++-------------- drivers/scsi/ibmvscsi/ibmvfc.h | 2 ++ 2 files changed, 56 insertions(+), 27 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index fef49521cbc3..d6fcb3f43969 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -504,12 +504,23 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost, if (vhost->action == IBMVFC_HOST_ACTION_ALLOC_TGTS) vhost->action = action; break; - case IBMVFC_HOST_ACTION_LOGO: case IBMVFC_HOST_ACTION_INIT: case IBMVFC_HOST_ACTION_TGT_DEL: + switch (vhost->action) { + case IBMVFC_HOST_ACTION_RESET: + case IBMVFC_HOST_ACTION_REENABLE: + break; + default: + vhost->action = action; + break; + }; + break; + case IBMVFC_HOST_ACTION_LOGO: case IBMVFC_HOST_ACTION_QUERY_TGTS: case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: case IBMVFC_HOST_ACTION_NONE: + case IBMVFC_HOST_ACTION_RESET: + case IBMVFC_HOST_ACTION_REENABLE: default: vhost->action = action; break; @@ -641,7 +652,7 @@ static int ibmvfc_send_crq_init_complete(struct ibmvfc_host *vhost) **/ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost) { - long rc; + long rc = 0; struct vio_dev *vdev = to_vio_dev(vhost->dev); struct ibmvfc_crq_queue *crq = &vhost->crq; @@ -649,6 +660,8 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost) free_irq(vdev->irq, vhost); tasklet_kill(&vhost->tasklet); do { + if (rc) + msleep(100); rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); @@ -667,11 +680,13 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost) **/ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost) { - int rc; + int rc = 0; struct vio_dev *vdev = to_vio_dev(vhost->dev); /* Re-enable the CRQ */ do { + if (rc) + msleep(100); rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address); } while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc)); @@ -690,15 +705,19 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost) **/ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) { - int rc; + int rc = 0; + unsigned long flags; struct vio_dev *vdev = to_vio_dev(vhost->dev); struct ibmvfc_crq_queue *crq = &vhost->crq; /* Close the CRQ */ do { + if (rc) + msleep(100); rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); + spin_lock_irqsave(vhost->host->host_lock, flags); vhost->state = IBMVFC_NO_CRQ; vhost->logged_in = 0; ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); @@ -716,6 +735,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) dev_warn(vhost->dev, "Partner adapter not ready\n"); else if (rc != 0) dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc); + spin_unlock_irqrestore(vhost->host->host_lock, flags); return rc; } @@ -821,17 +841,9 @@ static void ibmvfc_purge_requests(struct ibmvfc_host *vhost, int error_code) **/ static void ibmvfc_hard_reset_host(struct ibmvfc_host *vhost) { - int rc; - - scsi_block_requests(vhost->host); ibmvfc_purge_requests(vhost, DID_ERROR); - if ((rc = ibmvfc_reset_crq(vhost)) || - (rc = ibmvfc_send_crq_init(vhost)) || - (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) { - dev_err(vhost->dev, "Error after reset rc=%d\n", rc); - ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); - } else - ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_RESET); } /** @@ -2606,22 +2618,13 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost) dev_info(vhost->dev, "Re-enabling adapter\n"); vhost->client_migrated = 1; ibmvfc_purge_requests(vhost, DID_REQUEUE); - if ((rc = ibmvfc_reenable_crq_queue(vhost)) || - (rc = ibmvfc_send_crq_init(vhost))) { - ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); - dev_err(vhost->dev, "Error after enable (rc=%ld)\n", rc); - } else - ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_REENABLE); } else { dev_err(vhost->dev, "Virtual adapter failed (rc=%d)\n", crq->format); - ibmvfc_purge_requests(vhost, DID_ERROR); - if ((rc = ibmvfc_reset_crq(vhost)) || - (rc = ibmvfc_send_crq_init(vhost))) { - ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); - dev_err(vhost->dev, "Error after reset (rc=%ld)\n", rc); - } else - ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_RESET); } return; case IBMVFC_CRQ_CMD_RSP: @@ -4123,6 +4126,8 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost) case IBMVFC_HOST_ACTION_TGT_DEL: case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: case IBMVFC_HOST_ACTION_QUERY: + case IBMVFC_HOST_ACTION_RESET: + case IBMVFC_HOST_ACTION_REENABLE: default: break; }; @@ -4220,6 +4225,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) struct ibmvfc_target *tgt; unsigned long flags; struct fc_rport *rport; + int rc; ibmvfc_log_ae(vhost, vhost->events_to_log); spin_lock_irqsave(vhost->host->host_lock, flags); @@ -4229,6 +4235,27 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) case IBMVFC_HOST_ACTION_LOGO_WAIT: case IBMVFC_HOST_ACTION_INIT_WAIT: break; + case IBMVFC_HOST_ACTION_RESET: + vhost->action = IBMVFC_HOST_ACTION_TGT_DEL; + spin_unlock_irqrestore(vhost->host->host_lock, flags); + rc = ibmvfc_reset_crq(vhost); + spin_lock_irqsave(vhost->host->host_lock, flags); + if (rc || (rc = ibmvfc_send_crq_init(vhost)) || + (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) { + ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); + dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc); + } + break; + case IBMVFC_HOST_ACTION_REENABLE: + vhost->action = IBMVFC_HOST_ACTION_TGT_DEL; + spin_unlock_irqrestore(vhost->host->host_lock, flags); + rc = ibmvfc_reenable_crq_queue(vhost); + spin_lock_irqsave(vhost->host->host_lock, flags); + if (rc || (rc = ibmvfc_send_crq_init(vhost))) { + ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); + dev_err(vhost->dev, "Error after enable (rc=%d)\n", rc); + } + break; case IBMVFC_HOST_ACTION_LOGO: vhost->job_step(vhost); break; diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 7e9742764e4b..2010d73aca81 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -649,6 +649,8 @@ struct ibmvfc_event_pool { enum ibmvfc_host_action { IBMVFC_HOST_ACTION_NONE = 0, + IBMVFC_HOST_ACTION_RESET, + IBMVFC_HOST_ACTION_REENABLE, IBMVFC_HOST_ACTION_LOGO, IBMVFC_HOST_ACTION_LOGO_WAIT, IBMVFC_HOST_ACTION_INIT, -- cgit v1.2.3 From 3f01424c8128af7a69c824176bff195be457d6ac Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 17 Jun 2010 13:55:15 -0500 Subject: [SCSI] ibmvfc: Add support for fc_block_scsi_eh Adds support for fc_block_scsi_eh to block the EH handlers if the target device is in the blocked state to ensure we don't take devices offline. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index d6fcb3f43969..bd96cecaa619 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2311,6 +2311,7 @@ static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) int rc = FAILED; ENTER; + fc_block_scsi_eh(cmd); ibmvfc_wait_while_resetting(vhost); cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); abort_rc = ibmvfc_abort_task_set(sdev); @@ -2337,6 +2338,7 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) int rc = FAILED; ENTER; + fc_block_scsi_eh(cmd); ibmvfc_wait_while_resetting(vhost); cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET); reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN"); @@ -2401,6 +2403,7 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) unsigned long cancel_rc = 0; ENTER; + fc_block_scsi_eh(cmd); ibmvfc_wait_while_resetting(vhost); starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset); reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); @@ -2422,6 +2425,7 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) int rc; struct ibmvfc_host *vhost = shost_priv(cmd->device->host); + fc_block_scsi_eh(cmd); dev_err(vhost->dev, "Resetting connection due to error recovery\n"); rc = ibmvfc_issue_fc_host_lip(vhost->host); return rc ? FAILED : SUCCESS; -- cgit v1.2.3 From 06395193b20124663b83b2894da827aec7e9d920 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 17 Jun 2010 13:55:16 -0500 Subject: [SCSI] ibmvfc: Driver version 1.0.8 Bump driver version. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 2010d73aca81..d7e8dcd90650 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -29,8 +29,8 @@ #include "viosrp.h" #define IBMVFC_NAME "ibmvfc" -#define IBMVFC_DRIVER_VERSION "1.0.7" -#define IBMVFC_DRIVER_DATE "(October 16, 2009)" +#define IBMVFC_DRIVER_VERSION "1.0.8" +#define IBMVFC_DRIVER_DATE "(June 17, 2010)" #define IBMVFC_DEFAULT_TIMEOUT 60 #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 -- cgit v1.2.3 From 0f33ece5bc3d5a9567b65cfbc736e8f206ecfc7b Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 17 Jun 2010 13:56:00 -0500 Subject: [SCSI] ibmvscsi: Fix softlockup on resume This fixes a softlockup seen on resume. During resume, the CRQ must be reenabled. However, the H_ENABLE_CRQ hcall used to do this may return H_BUSY or H_LONG_BUSY. When this happens, the caller is expected to retry later. This patch changes a simple loop, which was causing the softlockup, to a loop at task level which sleeps between retries rather than simply spinning. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 117 +++++++++++++++++++++++++++++--------- drivers/scsi/ibmvscsi/ibmvscsi.h | 4 ++ drivers/scsi/ibmvscsi/rpa_vscsi.c | 16 +++++- 3 files changed, 106 insertions(+), 31 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index aad35cc41e49..e50fad96329c 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -504,14 +505,8 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata) atomic_set(&hostdata->request_limit, 0); purge_requests(hostdata, DID_ERROR); - if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata)) || - (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0)) || - (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) { - atomic_set(&hostdata->request_limit, -1); - dev_err(hostdata->dev, "error after reset\n"); - } - - scsi_unblock_requests(hostdata->host); + hostdata->reset_crq = 1; + wake_up(&hostdata->work_wait_q); } /** @@ -1462,30 +1457,14 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, /* We need to re-setup the interpartition connection */ dev_info(hostdata->dev, "Re-enabling adapter!\n"); hostdata->client_migrated = 1; + hostdata->reenable_crq = 1; purge_requests(hostdata, DID_REQUEUE); - if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue, - hostdata)) || - (ibmvscsi_ops->send_crq(hostdata, - 0xC001000000000000LL, 0))) { - atomic_set(&hostdata->request_limit, - -1); - dev_err(hostdata->dev, "error after enable\n"); - } + wake_up(&hostdata->work_wait_q); } else { dev_err(hostdata->dev, "Virtual adapter failed rc %d!\n", crq->format); - - purge_requests(hostdata, DID_ERROR); - if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, - hostdata)) || - (ibmvscsi_ops->send_crq(hostdata, - 0xC001000000000000LL, 0))) { - atomic_set(&hostdata->request_limit, - -1); - dev_err(hostdata->dev, "error after reset\n"); - } + ibmvscsi_reset_host(hostdata); } - scsi_unblock_requests(hostdata->host); return; case 0x80: /* real payload */ break; @@ -1850,6 +1829,75 @@ static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev) return desired_io; } +static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata) +{ + int rc; + char *action = "reset"; + + if (hostdata->reset_crq) { + smp_rmb(); + hostdata->reset_crq = 0; + + rc = ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata); + if (!rc) + rc = ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0); + if (!rc) + rc = vio_enable_interrupts(to_vio_dev(hostdata->dev)); + } else if (hostdata->reenable_crq) { + smp_rmb(); + action = "enable"; + rc = ibmvscsi_ops->reenable_crq_queue(&hostdata->queue, hostdata); + hostdata->reenable_crq = 0; + if (!rc) + rc = ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0); + } else + return; + + if (rc) { + atomic_set(&hostdata->request_limit, -1); + dev_err(hostdata->dev, "error after %s\n", action); + } + + scsi_unblock_requests(hostdata->host); +} + +static int ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata) +{ + if (kthread_should_stop()) + return 1; + else if (hostdata->reset_crq) { + smp_rmb(); + return 1; + } else if (hostdata->reenable_crq) { + smp_rmb(); + return 1; + } + + return 0; +} + +static int ibmvscsi_work(void *data) +{ + struct ibmvscsi_host_data *hostdata = data; + int rc; + + set_user_nice(current, -20); + + while (1) { + rc = wait_event_interruptible(hostdata->work_wait_q, + ibmvscsi_work_to_do(hostdata)); + + BUG_ON(rc); + + if (kthread_should_stop()) + break; + + ibmvscsi_do_work(hostdata); + } + + return 0; +} + /** * Called by bus code for each adapter */ @@ -1875,6 +1923,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) hostdata = shost_priv(host); memset(hostdata, 0x00, sizeof(*hostdata)); INIT_LIST_HEAD(&hostdata->sent); + init_waitqueue_head(&hostdata->work_wait_q); hostdata->host = host; hostdata->dev = dev; atomic_set(&hostdata->request_limit, -1); @@ -1885,10 +1934,19 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) goto persist_bufs_failed; } + hostdata->work_thread = kthread_run(ibmvscsi_work, hostdata, "%s_%d", + "ibmvscsi", host->host_no); + + if (IS_ERR(hostdata->work_thread)) { + dev_err(&vdev->dev, "couldn't initialize kthread. rc=%ld\n", + PTR_ERR(hostdata->work_thread)); + goto init_crq_failed; + } + rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_events); if (rc != 0 && rc != H_RESOURCE) { dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc); - goto init_crq_failed; + goto kill_kthread; } if (initialize_event_pool(&hostdata->pool, max_events, hostdata) != 0) { dev_err(&vdev->dev, "couldn't initialize event pool\n"); @@ -1944,6 +2002,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) release_event_pool(&hostdata->pool, hostdata); init_pool_failed: ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_events); + kill_kthread: + kthread_stop(hostdata->work_thread); init_crq_failed: unmap_persist_bufs(hostdata); persist_bufs_failed: @@ -1960,6 +2020,7 @@ static int ibmvscsi_remove(struct vio_dev *vdev) ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_events); + kthread_stop(hostdata->work_thread); srp_remove_host(hostdata->host); scsi_remove_host(hostdata->host); scsi_host_put(hostdata->host); diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 9cb7c6a773e1..02197a2b22b9 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h @@ -91,12 +91,16 @@ struct event_pool { struct ibmvscsi_host_data { atomic_t request_limit; int client_migrated; + int reset_crq; + int reenable_crq; struct device *dev; struct event_pool pool; struct crq_queue queue; struct tasklet_struct srp_task; struct list_head sent; struct Scsi_Host *host; + struct task_struct *work_thread; + wait_queue_head_t work_wait_q; struct mad_adapter_info_data madapter_info; struct capabilities caps; dma_addr_t caps_addr; diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index 989b9a8ba72d..f48ae0190d95 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -71,11 +72,13 @@ static void rpavscsi_release_crq_queue(struct crq_queue *queue, struct ibmvscsi_host_data *hostdata, int max_requests) { - long rc; + long rc = 0; struct vio_dev *vdev = to_vio_dev(hostdata->dev); free_irq(vdev->irq, (void *)hostdata); tasklet_kill(&hostdata->srp_task); do { + if (rc) + msleep(100); rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); dma_unmap_single(hostdata->dev, @@ -200,11 +203,13 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata) static int rpavscsi_reset_crq_queue(struct crq_queue *queue, struct ibmvscsi_host_data *hostdata) { - int rc; + int rc = 0; struct vio_dev *vdev = to_vio_dev(hostdata->dev); /* Close the CRQ */ do { + if (rc) + msleep(100); rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); @@ -301,7 +306,10 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue, req_irq_failed: tasklet_kill(&hostdata->srp_task); + rc = 0; do { + if (rc) + msleep(100); rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); reg_crq_failed: @@ -323,11 +331,13 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue, static int rpavscsi_reenable_crq_queue(struct crq_queue *queue, struct ibmvscsi_host_data *hostdata) { - int rc; + int rc = 0; struct vio_dev *vdev = to_vio_dev(hostdata->dev); /* Re-enable the CRQ */ do { + if (rc) + msleep(100); rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address); } while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); -- cgit v1.2.3 From 1117ef8aed95521f46dae3052c7120baae48c2bb Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 17 Jun 2010 13:56:02 -0500 Subject: [SCSI] ibmvscsi: Fix error path deadlock Fixes a deadlock that can occur if we hit a command timeout during the virtual adapter initialization. The event done functions are written with the assumption that no locks are held, however, when purging requests this is not true. Fix up the purge function to drop the lock so that the done function is not called with the lock held, which can cause a deadlock. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index e50fad96329c..83b5a174164c 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -474,23 +474,26 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, */ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) { - struct srp_event_struct *tmp_evt, *pos; + struct srp_event_struct *evt; unsigned long flags; spin_lock_irqsave(hostdata->host->host_lock, flags); - list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { - list_del(&tmp_evt->list); - del_timer(&tmp_evt->timer); - if (tmp_evt->cmnd) { - tmp_evt->cmnd->result = (error_code << 16); - unmap_cmd_data(&tmp_evt->iu.srp.cmd, - tmp_evt, - tmp_evt->hostdata->dev); - if (tmp_evt->cmnd_done) - tmp_evt->cmnd_done(tmp_evt->cmnd); - } else if (tmp_evt->done) - tmp_evt->done(tmp_evt); - free_event_struct(&tmp_evt->hostdata->pool, tmp_evt); + while (!list_empty(&hostdata->sent)) { + evt = list_first_entry(&hostdata->sent, struct srp_event_struct, list); + list_del(&evt->list); + del_timer(&evt->timer); + + spin_unlock_irqrestore(hostdata->host->host_lock, flags); + if (evt->cmnd) { + evt->cmnd->result = (error_code << 16); + unmap_cmd_data(&evt->iu.srp.cmd, evt, + evt->hostdata->dev); + if (evt->cmnd_done) + evt->cmnd_done(evt->cmnd); + } else if (evt->done) + evt->done(evt); + free_event_struct(&evt->hostdata->pool, evt); + spin_lock_irqsave(hostdata->host->host_lock, flags); } spin_unlock_irqrestore(hostdata->host->host_lock, flags); } -- cgit v1.2.3 From f3a9c4d76a955e331e88992cd3b1e1498c231d52 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 17 Jun 2010 13:56:03 -0500 Subject: [SCSI] ibmvscsi: Fix possible request_limit issue If we encounter an error when sending a management datagram (i.e. non SCSI command, such as virtual adapter initialization command), we end up incrementing the request_limit, even though we don't decrement it for these commands. Fix this up by doing this increment in the error path for SRP commands only. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 83b5a174164c..4f906efb1519 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -548,6 +548,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, u64 *crq_as_u64 = (u64 *) &evt_struct->crq; int request_status = 0; int rc; + int srp_req = 0; /* If we have exhausted our request limit, just fail this request, * unless it is for a reset or abort. @@ -556,6 +557,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, * can handle more requests (can_queue) when we actually can't */ if (evt_struct->crq.format == VIOSRP_SRP_FORMAT) { + srp_req = 1; request_status = atomic_dec_if_positive(&hostdata->request_limit); /* If request limit was -1 when we started, it is now even @@ -630,7 +632,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, goto send_busy; } dev_err(hostdata->dev, "send error %d\n", rc); - atomic_inc(&hostdata->request_limit); + if (srp_req) + atomic_inc(&hostdata->request_limit); goto send_error; } @@ -640,7 +643,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); free_event_struct(&hostdata->pool, evt_struct); - if (request_status != -1) + if (srp_req && request_status != -1) atomic_inc(&hostdata->request_limit); return SCSI_MLQUEUE_HOST_BUSY; -- cgit v1.2.3 From aac3118d33e275a7b1134cb19227c982f4d43877 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 17 Jun 2010 13:56:04 -0500 Subject: [SCSI] ibmvscsi: Driver version 1.5.9 Bump driver version Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 4f906efb1519..67f78a470f5f 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -102,7 +102,7 @@ static int client_reserve = 1; static struct scsi_transport_template *ibmvscsi_transport_template; -#define IBMVSCSI_VERSION "1.5.8" +#define IBMVSCSI_VERSION "1.5.9" static struct ibmvscsi_ops *ibmvscsi_ops; -- cgit v1.2.3 From cdd3cb156f190edb37d7066ddbf879354da2b634 Mon Sep 17 00:00:00 2001 From: Nick Cheng Date: Tue, 13 Jul 2010 20:03:04 +0800 Subject: [SCSI] SCSI: Support Type C RAID controller 1. To support Type C RAID controller, ACB_ADAPTER_TYPE_C, i.e. PCI device ID: 0x1880. Signed-off-by: Nick Cheng< nick.cheng@areca.com.tw > Signed-off-by: James Bottomley --- drivers/scsi/arcmsr/arcmsr.h | 208 ++++- drivers/scsi/arcmsr/arcmsr_attr.c | 9 +- drivers/scsi/arcmsr/arcmsr_hba.c | 1538 ++++++++++++++++++++++++------------- 3 files changed, 1182 insertions(+), 573 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index c0861c05cd49..475c31ae985c 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -43,12 +43,11 @@ ******************************************************************************* */ #include - struct device_attribute; /*The limit of outstanding scsi command that firmware can handle*/ #define ARCMSR_MAX_OUTSTANDING_CMD 256 #define ARCMSR_MAX_FREECCB_NUM 320 -#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2009/12/09" +#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2010/02/02" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 @@ -60,7 +59,8 @@ struct device_attribute; #define ARCMSR_DEFAULT_SG_ENTRIES 38 #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ -#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define SCSI_CMD_ARECA_SPECIFIC 0xE1 #ifndef PCI_DEVICE_ID_ARECA_1880 #define PCI_DEVICE_ID_ARECA_1880 0x1880 #endif @@ -138,9 +138,9 @@ struct CMD_MESSAGE_FIELD #define ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE \ ARECA_SATA_RAID | FUNCTION_FLUSH_ADAPTER_CACHE /* ARECA IOCTL ReturnCode */ -#define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 -#define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 -#define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F +#define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 +#define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 +#define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F #define ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON 0x00000088 /* ************************************************************* @@ -153,13 +153,13 @@ struct SG32ENTRY { __le32 length; __le32 address; -} __attribute__ ((packed)); +}__attribute__ ((packed)); struct SG64ENTRY { __le32 length; __le32 address; __le32 addresshigh; -} __attribute__ ((packed)); +}__attribute__ ((packed)); /* ******************************************************************** ** Q Buffer of IOP Message Transfer @@ -186,9 +186,9 @@ struct FIRMWARE_INFO char model[8]; /*15, 60-67*/ char firmware_ver[16]; /*17, 68-83*/ char device_map[16]; /*21, 84-99*/ - uint32_t cfgVersion; /*25,100-103 Added for checking of new firmware capability*/ - uint8_t cfgSerial[16]; /*26,104-119*/ - uint32_t cfgPicStatus; /*30,120-123*/ + uint32_t cfgVersion; /*25,100-103 Added for checking of new firmware capability*/ + uint8_t cfgSerial[16]; /*26,104-119*/ + uint32_t cfgPicStatus; /*30,120-123*/ }; /* signature of set and get firmware config */ #define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 @@ -212,11 +212,15 @@ struct FIRMWARE_INFO #define ARCMSR_CCBPOST_FLAG_SGL_BSIZE 0x80000000 #define ARCMSR_CCBPOST_FLAG_IAM_BIOS 0x40000000 #define ARCMSR_CCBREPLY_FLAG_IAM_BIOS 0x40000000 -#define ARCMSR_CCBREPLY_FLAG_ERROR 0x10000000 +#define ARCMSR_CCBREPLY_FLAG_ERROR_MODE0 0x10000000 +#define ARCMSR_CCBREPLY_FLAG_ERROR_MODE1 0x00000001 /* outbound firmware ok */ #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 /* ARC-1680 Bus Reset*/ #define ARCMSR_ARC1680_BUS_RESET 0x00000003 +/* ARC-1880 Bus Reset*/ +#define ARCMSR_ARC1880_RESET_ADAPTER 0x00000024 +#define ARCMSR_ARC1880_DiagWrite_ENABLE 0x00000080 /* ************************************************************************ @@ -273,6 +277,61 @@ struct FIRMWARE_INFO #define ARCMSR_MESSAGE_RBUFFER 0x0000ff00 /* iop message_rwbuffer for message command */ #define ARCMSR_MESSAGE_RWBUFFER 0x0000fa00 +/* +************************************************************************ +** SPEC. for Areca HBC adapter +************************************************************************ +*/ +#define ARCMSR_HBC_ISR_THROTTLING_LEVEL 12 +#define ARCMSR_HBC_ISR_MAX_DONE_QUEUE 20 +/* Host Interrupt Mask */ +#define ARCMSR_HBCMU_UTILITY_A_ISR_MASK 0x00000001 /* When clear, the Utility_A interrupt routes to the host.*/ +#define ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK 0x00000004 /* When clear, the General Outbound Doorbell interrupt routes to the host.*/ +#define ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK 0x00000008 /* When clear, the Outbound Post List FIFO Not Empty interrupt routes to the host.*/ +#define ARCMSR_HBCMU_ALL_INTMASKENABLE 0x0000000D /* disable all ISR */ +/* Host Interrupt Status */ +#define ARCMSR_HBCMU_UTILITY_A_ISR 0x00000001 + /* + ** Set when the Utility_A Interrupt bit is set in the Outbound Doorbell Register. + ** It clears by writing a 1 to the Utility_A bit in the Outbound Doorbell Clear Register or through automatic clearing (if enabled). + */ +#define ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR 0x00000004 + /* + ** Set if Outbound Doorbell register bits 30:1 have a non-zero + ** value. This bit clears only when Outbound Doorbell bits + ** 30:1 are ALL clear. Only a write to the Outbound Doorbell + ** Clear register clears bits in the Outbound Doorbell register. + */ +#define ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR 0x00000008 + /* + ** Set whenever the Outbound Post List Producer/Consumer + ** Register (FIFO) is not empty. It clears when the Outbound + ** Post List FIFO is empty. + */ +#define ARCMSR_HBCMU_SAS_ALL_INT 0x00000010 + /* + ** This bit indicates a SAS interrupt from a source external to + ** the PCIe core. This bit is not maskable. + */ + /* DoorBell*/ +#define ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK 0x00000002 +#define ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK 0x00000004 + /*inbound message 0 ready*/ +#define ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE 0x00000008 + /*more than 12 request completed in a time*/ +#define ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING 0x00000010 +#define ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK 0x00000002 + /*outbound DATA WRITE isr door bell clear*/ +#define ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_DOORBELL_CLEAR 0x00000002 +#define ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK 0x00000004 + /*outbound DATA READ isr door bell clear*/ +#define ARCMSR_HBCMU_IOP2DRV_DATA_READ_DOORBELL_CLEAR 0x00000004 + /*outbound message 0 ready*/ +#define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE 0x00000008 + /*outbound message cmd isr door bell clear*/ +#define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR 0x00000008 + /*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/ +#define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK 0x80000000 /* ******************************************************************************* ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) @@ -310,7 +369,7 @@ struct ARCMSR_CDB struct SG32ENTRY sg32entry[1]; struct SG64ENTRY sg64entry[1]; } u; -} __attribute__ ((packed)); +}; /* ******************************************************************************* ** Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor @@ -356,7 +415,81 @@ struct MessageUnit_B uint32_t __iomem *message_wbuffer; uint32_t __iomem *message_rbuffer; }; - +/* +********************************************************************* +** LSI +********************************************************************* +*/ +struct MessageUnit_C{ + uint32_t message_unit_status; /*0000 0003*/ + uint32_t slave_error_attribute; /*0004 0007*/ + uint32_t slave_error_address; /*0008 000B*/ + uint32_t posted_outbound_doorbell; /*000C 000F*/ + uint32_t master_error_attribute; /*0010 0013*/ + uint32_t master_error_address_low; /*0014 0017*/ + uint32_t master_error_address_high; /*0018 001B*/ + uint32_t hcb_size; /*001C 001F*/ + uint32_t inbound_doorbell; /*0020 0023*/ + uint32_t diagnostic_rw_data; /*0024 0027*/ + uint32_t diagnostic_rw_address_low; /*0028 002B*/ + uint32_t diagnostic_rw_address_high; /*002C 002F*/ + uint32_t host_int_status; /*0030 0033*/ + uint32_t host_int_mask; /*0034 0037*/ + uint32_t dcr_data; /*0038 003B*/ + uint32_t dcr_address; /*003C 003F*/ + uint32_t inbound_queueport; /*0040 0043*/ + uint32_t outbound_queueport; /*0044 0047*/ + uint32_t hcb_pci_address_low; /*0048 004B*/ + uint32_t hcb_pci_address_high; /*004C 004F*/ + uint32_t iop_int_status; /*0050 0053*/ + uint32_t iop_int_mask; /*0054 0057*/ + uint32_t iop_inbound_queue_port; /*0058 005B*/ + uint32_t iop_outbound_queue_port; /*005C 005F*/ + uint32_t inbound_free_list_index; /*0060 0063*/ + uint32_t inbound_post_list_index; /*0064 0067*/ + uint32_t outbound_free_list_index; /*0068 006B*/ + uint32_t outbound_post_list_index; /*006C 006F*/ + uint32_t inbound_doorbell_clear; /*0070 0073*/ + uint32_t i2o_message_unit_control; /*0074 0077*/ + uint32_t last_used_message_source_address_low; /*0078 007B*/ + uint32_t last_used_message_source_address_high; /*007C 007F*/ + uint32_t pull_mode_data_byte_count[4]; /*0080 008F*/ + uint32_t message_dest_address_index; /*0090 0093*/ + uint32_t done_queue_not_empty_int_counter_timer; /*0094 0097*/ + uint32_t utility_A_int_counter_timer; /*0098 009B*/ + uint32_t outbound_doorbell; /*009C 009F*/ + uint32_t outbound_doorbell_clear; /*00A0 00A3*/ + uint32_t message_source_address_index; /*00A4 00A7*/ + uint32_t message_done_queue_index; /*00A8 00AB*/ + uint32_t reserved0; /*00AC 00AF*/ + uint32_t inbound_msgaddr0; /*00B0 00B3*/ + uint32_t inbound_msgaddr1; /*00B4 00B7*/ + uint32_t outbound_msgaddr0; /*00B8 00BB*/ + uint32_t outbound_msgaddr1; /*00BC 00BF*/ + uint32_t inbound_queueport_low; /*00C0 00C3*/ + uint32_t inbound_queueport_high; /*00C4 00C7*/ + uint32_t outbound_queueport_low; /*00C8 00CB*/ + uint32_t outbound_queueport_high; /*00CC 00CF*/ + uint32_t iop_inbound_queue_port_low; /*00D0 00D3*/ + uint32_t iop_inbound_queue_port_high; /*00D4 00D7*/ + uint32_t iop_outbound_queue_port_low; /*00D8 00DB*/ + uint32_t iop_outbound_queue_port_high; /*00DC 00DF*/ + uint32_t message_dest_queue_port_low; /*00E0 00E3*/ + uint32_t message_dest_queue_port_high; /*00E4 00E7*/ + uint32_t last_used_message_dest_address_low; /*00E8 00EB*/ + uint32_t last_used_message_dest_address_high; /*00EC 00EF*/ + uint32_t message_done_queue_base_address_low; /*00F0 00F3*/ + uint32_t message_done_queue_base_address_high; /*00F4 00F7*/ + uint32_t host_diagnostic; /*00F8 00FB*/ + uint32_t write_sequence; /*00FC 00FF*/ + uint32_t reserved1[34]; /*0100 0187*/ + uint32_t reserved2[1950]; /*0188 1FFF*/ + uint32_t message_wbuffer[32]; /*2000 207F*/ + uint32_t reserved3[32]; /*2080 20FF*/ + uint32_t message_rbuffer[32]; /*2100 217F*/ + uint32_t reserved4[32]; /*2180 21FF*/ + uint32_t msgcode_rwbuffer[256]; /*2200 23FF*/ +}; /* ******************************************************************************* ** Adapter Control Block @@ -374,11 +507,14 @@ struct AdapterControlBlock unsigned long vir2phy_offset; /* Offset is used in making arc cdb physical to virtual calculations */ uint32_t outbound_int_enable; + uint32_t cdb_phyaddr_hi32; + uint32_t reg_mu_acc_handle0; spinlock_t eh_lock; spinlock_t ccblist_lock; union { - struct MessageUnit_A __iomem * pmuA; - struct MessageUnit_B * pmuB; + struct MessageUnit_A __iomem *pmuA; + struct MessageUnit_B *pmuB; + struct MessageUnit_C __iomem *pmuC; }; /* message unit ATU inbound base address0 */ void __iomem *mem_base0; @@ -399,6 +535,8 @@ struct AdapterControlBlock /* message clear rqbuffer */ #define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 #define ACB_F_BUS_RESET 0x0080 + #define ACB_F_BUS_HANG_ON 0x0800/* need hardware reset bus */ + #define ACB_F_IOP_INITED 0x0100 /* iop init */ #define ACB_F_ABORT 0x0200 @@ -441,9 +579,9 @@ struct AdapterControlBlock uint32_t firm_numbers_queue; uint32_t firm_sdram_size; uint32_t firm_hd_channels; - uint32_t firm_cfg_version; - char firm_model[12]; - char firm_version[20]; + uint32_t firm_cfg_version; + char firm_model[12]; + char firm_version[20]; char device_map[20]; /*21,84-99*/ struct work_struct arcmsr_do_message_isr_bh; struct timer_list eternal_timer; @@ -460,31 +598,31 @@ struct AdapterControlBlock ** this CCB length must be 32 bytes boundary ******************************************************************************* */ -struct CommandControlBlock -{ +struct CommandControlBlock{ /*x32:sizeof struct_CCB=(32+60)byte, x64:sizeof struct_CCB=(64+60)byte*/ struct list_head list; /*x32: 8byte, x64: 16byte*/ struct scsi_cmnd *pcmd; /*8 bytes pointer of linux scsi command */ struct AdapterControlBlock *acb; /*x32: 4byte, x64: 8byte*/ - uint32_t shifted_cdb_phyaddr; /*x32: 4byte, x64: 4byte*/ + uint32_t cdb_phyaddr_pattern; /*x32: 4byte, x64: 4byte*/ + uint32_t arc_cdb_size; /*x32:4byte,x64:4byte*/ uint16_t ccb_flags; /*x32: 2byte, x64: 2byte*/ - #define CCB_FLAG_READ 0x0000 - #define CCB_FLAG_WRITE 0x0001 - #define CCB_FLAG_ERROR 0x0002 - #define CCB_FLAG_FLUSHCACHE 0x0004 - #define CCB_FLAG_MASTER_ABORTED 0x0008 + #define CCB_FLAG_READ 0x0000 + #define CCB_FLAG_WRITE 0x0001 + #define CCB_FLAG_ERROR 0x0002 + #define CCB_FLAG_FLUSHCACHE 0x0004 + #define CCB_FLAG_MASTER_ABORTED 0x0008 uint16_t startdone; /*x32:2byte,x32:2byte*/ - #define ARCMSR_CCB_DONE 0x0000 - #define ARCMSR_CCB_START 0x55AA - #define ARCMSR_CCB_ABORTED 0xAA55 - #define ARCMSR_CCB_ILLEGAL 0xFFFF + #define ARCMSR_CCB_DONE 0x0000 + #define ARCMSR_CCB_START 0x55AA + #define ARCMSR_CCB_ABORTED 0xAA55 + #define ARCMSR_CCB_ILLEGAL 0xFFFF #if BITS_PER_LONG == 64 /* ======================512+64 bytes======================== */ - uint32_t reserved[6]; /*24 byte*/ -#else + uint32_t reserved[5]; /*24 byte*/ + #else /* ======================512+32 bytes======================== */ - uint32_t reserved[2]; /*8 byte*/ -#endif + uint32_t reserved; /*8 byte*/ + #endif /* ======================================================= */ struct ARCMSR_CDB arcmsr_cdb; }; diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 07fdfe57e38e..69f8346aa288 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -59,8 +59,7 @@ struct device_attribute *arcmsr_host_attrs[]; -static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, - struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) @@ -106,8 +105,7 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, return (allxfer_len); } -static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, - struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) @@ -155,8 +153,7 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, } } -static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp, - struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index ba33473b27a1..95a895dd4f13 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -71,11 +71,11 @@ #include #include "arcmsr.h" MODULE_AUTHOR("Nick Cheng "); -MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx) SATA/SAS RAID Host Bus Adapter"); +MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx/1880) SATA/SAS RAID Host Bus Adapter"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(ARCMSR_DRIVER_VERSION); -static int sleeptime = 20; -static int retrycount = 12; +static int sleeptime = 10; +static int retrycount = 30; wait_queue_head_t wait_q; static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd); @@ -99,10 +99,12 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); static void arcmsr_request_device_map(unsigned long pacb); static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb); static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb); +static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb); static void arcmsr_message_isr_bh_fn(struct work_struct *work); static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb); static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); - +static void arcmsr_hbc_message_isr(struct AdapterControlBlock *pACB); +static void arcmsr_hardware_reset(struct AdapterControlBlock *acb); static const char *arcmsr_info(struct Scsi_Host *); static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, @@ -119,18 +121,18 @@ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, static struct scsi_host_template arcmsr_scsi_host_template = { .module = THIS_MODULE, - .name = "ARCMSR ARECA SATA/SAS RAID Host Bus Adapter" - ARCMSR_DRIVER_VERSION, + .name = "ARCMSR ARECA SATA/SAS RAID Controller" + ARCMSR_DRIVER_VERSION, .info = arcmsr_info, .queuecommand = arcmsr_queue_command, - .eh_abort_handler = arcmsr_abort, + .eh_abort_handler = arcmsr_abort, .eh_bus_reset_handler = arcmsr_bus_reset, .bios_param = arcmsr_bios_param, .change_queue_depth = arcmsr_adjust_disk_queue_depth, .can_queue = ARCMSR_MAX_FREECCB_NUM, - .this_id = ARCMSR_SCSI_INITIATOR_ID, - .sg_tablesize = ARCMSR_DEFAULT_SG_ENTRIES, - .max_sectors = ARCMSR_MAX_XFER_SECTORS_C, + .this_id = ARCMSR_SCSI_INITIATOR_ID, + .sg_tablesize = ARCMSR_DEFAULT_SG_ENTRIES, + .max_sectors = ARCMSR_MAX_XFER_SECTORS_C, .cmd_per_lun = ARCMSR_MAX_CMD_PERLUN, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = arcmsr_host_attrs, @@ -160,22 +162,45 @@ static struct pci_device_id arcmsr_device_id_table[] = { MODULE_DEVICE_TABLE(pci, arcmsr_device_id_table); static struct pci_driver arcmsr_pci_driver = { .name = "arcmsr", - .id_table = arcmsr_device_id_table, + .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, .shutdown = arcmsr_shutdown, }; +/* +**************************************************************************** +**************************************************************************** +*/ +int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *shost = NULL; + int i, isleep; + shost = cmd->device->host; + isleep = sleeptime / 10; + if (isleep > 0) { + for (i = 0; i < isleep; i++) { + msleep(10000); + } + } + + isleep = sleeptime % 10; + if (isleep > 0) { + msleep(isleep*1000); + } + printk(KERN_NOTICE "wake-up\n"); + return 0; +} -static void arcmsr_free_mu(struct AdapterControlBlock *acb) +static void arcmsr_free_hbb_mu(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: + case ACB_ADAPTER_TYPE_C: break; case ACB_ADAPTER_TYPE_B:{ - struct MessageUnit_B *reg = acb->pmuB; - dma_free_coherent(&acb->pdev->dev, - sizeof(struct MessageUnit_B), - reg, acb->dma_coherent_handle_hbb_mu); + dma_free_coherent(&acb->pdev->dev, + sizeof(struct MessageUnit_B), + acb->pmuB, acb->dma_coherent_handle_hbb_mu); } } } @@ -183,10 +208,9 @@ static void arcmsr_free_mu(struct AdapterControlBlock *acb) static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb) { struct pci_dev *pdev = acb->pdev; - - switch (acb->adapter_type) { + switch (acb->adapter_type){ case ACB_ADAPTER_TYPE_A:{ - acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + acb->pmuA = ioremap(pci_resource_start(pdev,0), pci_resource_len(pdev,0)); if (!acb->pmuA) { printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); return false; @@ -208,6 +232,19 @@ static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb) } acb->mem_base0 = mem_base0; acb->mem_base1 = mem_base1; + break; + } + case ACB_ADAPTER_TYPE_C:{ + acb->pmuC = ioremap_nocache(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); + if (!acb->pmuC) { + printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); + return false; + } + if (readl(&acb->pmuC->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, &acb->pmuC->outbound_doorbell_clear);/*clear interrupt*/ + return true; + } + break; } } return true; @@ -216,13 +253,19 @@ static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb) static void arcmsr_unmap_pciregion(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { - case ACB_ADAPTER_TYPE_A:{ - iounmap(acb->pmuA); - } - case ACB_ADAPTER_TYPE_B:{ - iounmap(acb->mem_base0); - iounmap(acb->mem_base1); - } + case ACB_ADAPTER_TYPE_A:{ + iounmap(acb->pmuA); + } + break; + case ACB_ADAPTER_TYPE_B:{ + iounmap(acb->mem_base0); + iounmap(acb->mem_base1); + } + + break; + case ACB_ADAPTER_TYPE_C:{ + iounmap(acb->pmuC); + } } } @@ -270,34 +313,37 @@ static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb) pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id); acb->dev_id = dev_id; switch (dev_id) { - case 0x1201 : { + case 0x1880: { + acb->adapter_type = ACB_ADAPTER_TYPE_C; + } + break; + case 0x1201: { acb->adapter_type = ACB_ADAPTER_TYPE_B; } break; - default : acb->adapter_type = ACB_ADAPTER_TYPE_A; + default: acb->adapter_type = ACB_ADAPTER_TYPE_A; } -} +} static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; uint32_t Index; uint8_t Retries = 0x00; - do { for (Index = 0; Index < 100; Index++) { if (readl(®->outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, ®->outbound_intstatus); - return 0x00; + return true; } msleep(10); - } /*max 1 seconds*/ + }/*max 1 seconds*/ } while (Retries++ < 20);/*max 20 sec*/ - return 0xff; + return false; } static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) @@ -305,7 +351,6 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) struct MessageUnit_B *reg = acb->pmuB; uint32_t Index; uint8_t Retries = 0x00; - do { for (Index = 0; Index < 100; Index++) { if (readl(reg->iop2drv_doorbell) @@ -313,23 +358,39 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN , reg->iop2drv_doorbell); writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); - return 0x00; + return true; } msleep(10); - } /*max 1 seconds*/ + }/*max 1 seconds*/ } while (Retries++ < 20);/*max 20 sec*/ - return 0xff; + return false; } +static uint8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *pACB) +{ + struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; + unsigned char Retries = 0x00; + uint32_t Index; + do { + for (Index = 0; Index < 100; Index++) { + if (readl(&phbcmu->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, &phbcmu->outbound_doorbell_clear);/*clear interrupt*/ + return true; + } + /* one us delay */ + msleep(10); + } /*max 1 seconds*/ + } while (Retries++ < 20); /*max 20 sec*/ + return false; +} static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; int retry_count = 30; - writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); do { - if (!arcmsr_hba_wait_msgint_ready(acb)) + if (arcmsr_hba_wait_msgint_ready(acb)) break; else { retry_count--; @@ -343,10 +404,9 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) { struct MessageUnit_B *reg = acb->pmuB; int retry_count = 30; - writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell); do { - if (!arcmsr_hbb_wait_msgint_ready(acb)) + if (arcmsr_hbb_wait_msgint_ready(acb)) break; else { retry_count--; @@ -356,6 +416,23 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) } while (retry_count != 0); } +static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *pACB) +{ + struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; + int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ + writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); + do { + if (arcmsr_hbc_wait_msgint_ready(pACB)) { + break; + } else { + retry_count--; + printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ + timeout,retry count down = %d \n", pACB->host->host_no, retry_count); + } + } while (retry_count != 0); + return; +} static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { @@ -368,151 +445,94 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { arcmsr_flush_hbb_cache(acb); } + break; + case ACB_ADAPTER_TYPE_C: { + arcmsr_flush_hbc_cache(acb); + } } } static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) { - struct pci_dev *pdev = acb->pdev; - switch (acb->adapter_type) { - case ACB_ADAPTER_TYPE_A: { - - void *dma_coherent; - dma_addr_t dma_coherent_handle; - struct CommandControlBlock *ccb_tmp; - int i = 0, j = 0; - dma_addr_t cdb_phyaddr; - unsigned long roundup_ccbsize = 0; - unsigned long max_xfer_len; - unsigned long max_sg_entrys; - uint32_t firm_config_version; - - for (i = 0; i < ARCMSR_MAX_TARGETID; i++) - for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) - acb->devstate[i][j] = ARECA_RAID_GONE; - - max_xfer_len = ARCMSR_MAX_XFER_LEN; - max_sg_entrys = ARCMSR_DEFAULT_SG_ENTRIES; - firm_config_version = acb->firm_cfg_version; - if ((firm_config_version & 0xFF) >= 3) { - max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH << ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 16M byte */ - max_sg_entrys = (max_xfer_len/4096); - } - acb->host->max_sectors = max_xfer_len/512; - acb->host->sg_tablesize = max_sg_entrys; - roundup_ccbsize = roundup(sizeof(struct CommandControlBlock) + max_sg_entrys * sizeof(struct SG64ENTRY), 32); - acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM; - dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size, &dma_coherent_handle, GFP_KERNEL); - if (!dma_coherent) { - printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error \n", acb->host->host_no); - return -ENOMEM; - } - memset(dma_coherent, 0, acb->uncache_size); - acb->dma_coherent = dma_coherent; - acb->dma_coherent_handle = dma_coherent_handle; - ccb_tmp = (struct CommandControlBlock *)dma_coherent; - acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle; - for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb); - ccb_tmp->shifted_cdb_phyaddr = cdb_phyaddr >> 5; - acb->pccb_pool[i] = ccb_tmp; - ccb_tmp->acb = acb; - INIT_LIST_HEAD(&ccb_tmp->list); - list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); - ccb_tmp = (struct CommandControlBlock *)((unsigned long)ccb_tmp + roundup_ccbsize); - dma_coherent_handle = dma_coherent_handle + roundup_ccbsize; - } - break; - } - case ACB_ADAPTER_TYPE_B: { - - void *dma_coherent; - dma_addr_t dma_coherent_handle; - struct CommandControlBlock *ccb_tmp; - uint32_t cdb_phyaddr; - unsigned int roundup_ccbsize = 0; - unsigned long max_xfer_len; - unsigned long max_sg_entrys; - unsigned long firm_config_version; - unsigned long max_freeccb_num = 0; - int i = 0, j = 0; - - max_freeccb_num = ARCMSR_MAX_FREECCB_NUM; - max_xfer_len = ARCMSR_MAX_XFER_LEN; - max_sg_entrys = ARCMSR_DEFAULT_SG_ENTRIES; - firm_config_version = acb->firm_cfg_version; - if ((firm_config_version & 0xFF) >= 3) { - max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH << - ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 16M byte */ - max_sg_entrys = (max_xfer_len/4096);/* max 4097 sg entry*/ - } - acb->host->max_sectors = max_xfer_len / 512; - acb->host->sg_tablesize = max_sg_entrys; - roundup_ccbsize = roundup(sizeof(struct CommandControlBlock)+ - (max_sg_entrys - 1) * sizeof(struct SG64ENTRY), 32); - acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM; - dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size, - &dma_coherent_handle, GFP_KERNEL); - - if (!dma_coherent) { - printk(KERN_NOTICE "DMA allocation failed...........................\n"); - return -ENOMEM; - } - memset(dma_coherent, 0, acb->uncache_size); - acb->dma_coherent = dma_coherent; - acb->dma_coherent_handle = dma_coherent_handle; - ccb_tmp = (struct CommandControlBlock *)dma_coherent; - acb->vir2phy_offset = (unsigned long)dma_coherent - - (unsigned long)dma_coherent_handle; - for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - cdb_phyaddr = dma_coherent_handle + - offsetof(struct CommandControlBlock, arcmsr_cdb); - ccb_tmp->shifted_cdb_phyaddr = cdb_phyaddr >> 5; - acb->pccb_pool[i] = ccb_tmp; - ccb_tmp->acb = acb; - INIT_LIST_HEAD(&ccb_tmp->list); - list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); - ccb_tmp = (struct CommandControlBlock *)((unsigned long)ccb_tmp + - roundup_ccbsize); - dma_coherent_handle = dma_coherent_handle + roundup_ccbsize; - } - for (i = 0; i < ARCMSR_MAX_TARGETID; i++) - for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) - acb->devstate[i][j] = ARECA_RAID_GONE; - } - break; + struct pci_dev *pdev = acb->pdev; + void *dma_coherent; + dma_addr_t dma_coherent_handle; + struct CommandControlBlock *ccb_tmp; + int i = 0, j = 0; + dma_addr_t cdb_phyaddr; + unsigned long roundup_ccbsize = 0, offset; + unsigned long max_xfer_len; + unsigned long max_sg_entrys; + uint32_t firm_config_version; + for (i = 0; i < ARCMSR_MAX_TARGETID; i++) + for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) + acb->devstate[i][j] = ARECA_RAID_GONE; + + max_xfer_len = ARCMSR_MAX_XFER_LEN; + max_sg_entrys = ARCMSR_DEFAULT_SG_ENTRIES; + firm_config_version = acb->firm_cfg_version; + if((firm_config_version & 0xFF) >= 3){ + max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH << ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 4M byte */ + max_sg_entrys = (max_xfer_len/4096); + } + acb->host->max_sectors = max_xfer_len/512; + acb->host->sg_tablesize = max_sg_entrys; + roundup_ccbsize = roundup(sizeof(struct CommandControlBlock) + (max_sg_entrys - 1) * sizeof(struct SG64ENTRY), 32); + acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM + 32; + dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size, &dma_coherent_handle, GFP_KERNEL); + if(!dma_coherent){ + printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error \n", acb->host->host_no); + return -ENOMEM; + } + acb->dma_coherent = dma_coherent; + acb->dma_coherent_handle = dma_coherent_handle; + memset(dma_coherent, 0, acb->uncache_size); + offset = roundup((unsigned long)dma_coherent, 32) - (unsigned long)dma_coherent; + dma_coherent_handle = dma_coherent_handle + offset; + dma_coherent = (struct CommandControlBlock *)dma_coherent + offset; + ccb_tmp = dma_coherent; + acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle; + for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){ + cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb); + ccb_tmp->cdb_phyaddr_pattern = ((acb->adapter_type == ACB_ADAPTER_TYPE_C) ? cdb_phyaddr : (cdb_phyaddr >> 5)); + acb->pccb_pool[i] = ccb_tmp; + ccb_tmp->acb = acb; + INIT_LIST_HEAD(&ccb_tmp->list); + list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); + ccb_tmp = (struct CommandControlBlock *)((unsigned long)ccb_tmp + roundup_ccbsize); + dma_coherent_handle = dma_coherent_handle + roundup_ccbsize; } return 0; } -static void arcmsr_message_isr_bh_fn(struct work_struct *work) -{ - struct AdapterControlBlock *acb = container_of(work, struct AdapterControlBlock, arcmsr_do_message_isr_bh); +static void arcmsr_message_isr_bh_fn(struct work_struct *work) +{ + struct AdapterControlBlock *acb = container_of(work,struct AdapterControlBlock, arcmsr_do_message_isr_bh); switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { struct MessageUnit_A __iomem *reg = acb->pmuA; char *acb_dev_map = (char *)acb->device_map; - uint32_t __iomem *signature = (uint32_t __iomem *) (®->message_rwbuffer[0]); - char __iomem *devicemap = (char __iomem *) (®->message_rwbuffer[21]); + uint32_t __iomem *signature = (uint32_t __iomem*) (®->message_rwbuffer[0]); + char __iomem *devicemap = (char __iomem*) (®->message_rwbuffer[21]); int target, lun; struct scsi_device *psdev; char diff; atomic_inc(&acb->rq_map_token); if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { - for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) { + for(target = 0; target < ARCMSR_MAX_TARGETID -1; target++) { diff = (*acb_dev_map)^readb(devicemap); if (diff != 0) { char temp; *acb_dev_map = readb(devicemap); - temp = *acb_dev_map; - for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { - if ((temp & 0x01) == 1 && (diff & 0x01) == 1) { + temp =*acb_dev_map; + for(lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { + if((temp & 0x01)==1 && (diff & 0x01) == 1) { scsi_add_device(acb->host, 0, target, lun); - } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) { + }else if((temp & 0x01) == 0 && (diff & 0x01) == 1) { psdev = scsi_device_lookup(acb->host, 0, target, lun); - if (psdev != NULL) { + if (psdev != NULL ) { scsi_remove_device(psdev); scsi_device_put(psdev); } @@ -531,8 +551,45 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; char *acb_dev_map = (char *)acb->device_map; - uint32_t __iomem *signature = (uint32_t __iomem *)(®->message_rwbuffer[0]); - char __iomem *devicemap = (char __iomem *)(®->message_rwbuffer[21]); + uint32_t __iomem *signature = (uint32_t __iomem*)(®->message_rwbuffer[0]); + char __iomem *devicemap = (char __iomem*)(®->message_rwbuffer[21]); + int target, lun; + struct scsi_device *psdev; + char diff; + + atomic_inc(&acb->rq_map_token); + if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { + for(target = 0; target < ARCMSR_MAX_TARGETID -1; target++) { + diff = (*acb_dev_map)^readb(devicemap); + if (diff != 0) { + char temp; + *acb_dev_map = readb(devicemap); + temp =*acb_dev_map; + for(lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { + if((temp & 0x01)==1 && (diff & 0x01) == 1) { + scsi_add_device(acb->host, 0, target, lun); + }else if((temp & 0x01) == 0 && (diff & 0x01) == 1) { + psdev = scsi_device_lookup(acb->host, 0, target, lun); + if (psdev != NULL ) { + scsi_remove_device(psdev); + scsi_device_put(psdev); + } + } + temp >>= 1; + diff >>= 1; + } + } + devicemap++; + acb_dev_map++; + } + } + } + break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *reg = acb->pmuC; + char *acb_dev_map = (char *)acb->device_map; + uint32_t __iomem *signature = (uint32_t __iomem *)(®->msgcode_rwbuffer[0]); + char __iomem *devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]); int target, lun; struct scsi_device *psdev; char diff; @@ -571,21 +628,20 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct Scsi_Host *host; struct AdapterControlBlock *acb; - uint8_t bus, dev_fun; + uint8_t bus,dev_fun; int error; - error = pci_enable_device(pdev); - if (error) { + if(error){ return -ENODEV; } host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof(struct AdapterControlBlock)); - if (!host) { - goto pci_disable_dev; + if(!host){ + goto pci_disable_dev; } error = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); - if (error) { + if(error){ error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (error) { + if(error){ printk(KERN_WARNING "scsi%d: No suitable DMA mask available\n", host->host_no); @@ -596,53 +652,53 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) bus = pdev->bus->number; dev_fun = pdev->devfn; acb = (struct AdapterControlBlock *) host->hostdata; - memset(acb, 0, sizeof(struct AdapterControlBlock)); + memset(acb,0,sizeof(struct AdapterControlBlock)); acb->pdev = pdev; acb->host = host; host->max_lun = ARCMSR_MAX_TARGETLUN; - host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/ - host->max_cmd_len = 16; /*this is issue of 64bit LBA, over 2T byte*/ - host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ - host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; + host->max_id = ARCMSR_MAX_TARGETID; /*16:8*/ + host->max_cmd_len = 16; /*this is issue of 64bit LBA ,over 2T byte*/ + host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ + host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; host->this_id = ARCMSR_SCSI_INITIATOR_ID; host->unique_id = (bus << 8) | dev_fun; pci_set_drvdata(pdev, host); pci_set_master(pdev); error = pci_request_regions(pdev, "arcmsr"); - if (error) { + if(error){ goto scsi_host_release; } spin_lock_init(&acb->eh_lock); spin_lock_init(&acb->ccblist_lock); acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | - ACB_F_MESSAGE_RQBUFFER_CLEARED | - ACB_F_MESSAGE_WQBUFFER_READED); + ACB_F_MESSAGE_RQBUFFER_CLEARED | + ACB_F_MESSAGE_WQBUFFER_READED); acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; INIT_LIST_HEAD(&acb->ccb_free_list); arcmsr_define_adapter_type(acb); error = arcmsr_remap_pciregion(acb); - if (!error) { + if(!error){ goto pci_release_regs; } error = arcmsr_get_firmware_spec(acb); - if (!error) { + if(!error){ goto unmap_pci_region; } error = arcmsr_alloc_ccb_pool(acb); - if (error) { + if(error){ goto free_hbb_mu; } arcmsr_iop_init(acb); error = scsi_add_host(host, &pdev->dev); - if (error) { + if(error){ goto RAID_controller_stop; } error = request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb); - if (error) { + if(error){ goto scsi_host_remove; } host->irq = pdev->irq; - scsi_scan_host(host); + scsi_scan_host(host); INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn); atomic_set(&acb->rq_map_token, 16); atomic_set(&acb->ante_token_value, 16); @@ -652,10 +708,10 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) acb->eternal_timer.data = (unsigned long) acb; acb->eternal_timer.function = &arcmsr_request_device_map; add_timer(&acb->eternal_timer); - if (arcmsr_alloc_sysfs_attr(acb)) + if(arcmsr_alloc_sysfs_attr(acb)) goto out_free_sysfs; return 0; - out_free_sysfs: +out_free_sysfs: scsi_host_remove: scsi_remove_host(host); RAID_controller_stop: @@ -663,7 +719,7 @@ RAID_controller_stop: arcmsr_flush_adapter_cache(acb); arcmsr_free_ccb_pool(acb); free_hbb_mu: - arcmsr_free_mu(acb); + arcmsr_free_hbb_mu(acb); unmap_pci_region: arcmsr_unmap_pciregion(acb); pci_release_regs: @@ -678,15 +734,14 @@ pci_disable_dev: static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; - writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); - if (arcmsr_hba_wait_msgint_ready(acb)) { + if (!arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'abort all outstanding command' timeout \n" , acb->host->host_no); - return 0xff; + return false; } - return 0x00; + return true; } static uint8_t arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) @@ -694,15 +749,27 @@ static uint8_t arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) struct MessageUnit_B *reg = acb->pmuB; writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell); - if (arcmsr_hbb_wait_msgint_ready(acb)) { + if (!arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'abort all outstanding command' timeout \n" , acb->host->host_no); - return 0xff; + return false; } - return 0x00; + return true; +} +static uint8_t arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *pACB) +{ + struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; + writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); + if (!arcmsr_hbc_wait_msgint_ready(pACB)) { + printk(KERN_NOTICE + "arcmsr%d: wait 'abort all outstanding command' timeout \n" + , pACB->host->host_no); + return false; + } + return true; } - static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) { uint8_t rtnval = 0; @@ -715,6 +782,11 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { rtnval = arcmsr_abort_hbb_allcmd(acb); } + break; + + case ACB_ADAPTER_TYPE_C: { + rtnval = arcmsr_abort_hbc_allcmd(acb); + } } return rtnval; } @@ -722,13 +794,12 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) static bool arcmsr_hbb_enable_driver_mode(struct AdapterControlBlock *pacb) { struct MessageUnit_B *reg = pacb->pmuB; - writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell); - if (arcmsr_hbb_wait_msgint_ready(pacb)) { + if (!arcmsr_hbb_wait_msgint_ready(pacb)) { printk(KERN_ERR "arcmsr%d: can't set driver mode. \n", pacb->host->host_no); return false; -} - return true; + } + return true; } static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) @@ -736,18 +807,16 @@ static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) struct scsi_cmnd *pcmd = ccb->pcmd; scsi_dma_unmap(pcmd); - } +} static void arcmsr_ccb_complete(struct CommandControlBlock *ccb) { struct AdapterControlBlock *acb = ccb->acb; struct scsi_cmnd *pcmd = ccb->pcmd; unsigned long flags; - atomic_dec(&acb->ccboutstandingcount); arcmsr_pci_unmap_dma(ccb); ccb->startdone = ARCMSR_CCB_DONE; - ccb->ccb_flags = 0; spin_lock_irqsave(&acb->ccblist_lock, flags); list_add_tail(&ccb->list, &acb->ccb_free_list); spin_unlock_irqrestore(&acb->ccblist_lock, flags); @@ -759,7 +828,6 @@ static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) struct scsi_cmnd *pcmd = ccb->pcmd; struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer; - pcmd->result = DID_OK << 16; if (sensebuffer) { int sense_data_length = @@ -775,8 +843,7 @@ static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) { u32 orig_mask = 0; - switch (acb->adapter_type) { - + switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A : { struct MessageUnit_A __iomem *reg = acb->pmuA; orig_mask = readl(®->outbound_intmask); @@ -784,30 +851,35 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) ®->outbound_intmask); } break; - case ACB_ADAPTER_TYPE_B : { struct MessageUnit_B *reg = acb->pmuB; orig_mask = readl(reg->iop2drv_doorbell_mask); writel(0, reg->iop2drv_doorbell_mask); } break; + case ACB_ADAPTER_TYPE_C:{ + struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; + /* disable all outbound interrupt */ + orig_mask = readl(®->host_int_mask); /* disable outbound message0 int */ + writel(orig_mask|ARCMSR_HBCMU_ALL_INTMASKENABLE, ®->host_int_mask); + } + break; } return orig_mask; } -static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, - struct CommandControlBlock *ccb, uint32_t flag_ccb) +static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, + struct CommandControlBlock *ccb, bool error) { - uint8_t id, lun; id = ccb->pcmd->device->id; lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { + if (!error) { if (acb->devstate[id][lun] == ARECA_RAID_GONE) acb->devstate[id][lun] = ARECA_RAID_GOOD; ccb->pcmd->result = DID_OK << 16; arcmsr_ccb_complete(ccb); - } else { + }else{ switch (ccb->arcmsr_cdb.DeviceStatus) { case ARCMSR_DEV_SELECT_TIMEOUT: { acb->devstate[id][lun] = ARECA_RAID_GONE; @@ -833,42 +905,37 @@ static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, break; default: - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d lun = %d" - " isr get command error done, " - "but got unknown DeviceStatus = 0x%x \n" - , acb->host->host_no - , id - , lun - , ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb); + printk(KERN_NOTICE + "arcmsr%d: scsi id = %d lun = %d isr get command error done, \ + but got unknown DeviceStatus = 0x%x \n" + , acb->host->host_no + , id + , lun + , ccb->arcmsr_cdb.DeviceStatus); + acb->devstate[id][lun] = ARECA_RAID_GONE; + ccb->pcmd->result = DID_NO_CONNECT << 16; + arcmsr_ccb_complete(ccb); break; } } } -static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t flag_ccb) +static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct CommandControlBlock *pCCB, bool error) { - struct CommandControlBlock *ccb; - struct ARCMSR_CDB *arcmsr_cdb; int id, lun; - - arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5)); - ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); - if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { - if (ccb->startdone == ARCMSR_CCB_ABORTED) { - struct scsi_cmnd *abortcmd = ccb->pcmd; + if ((pCCB->acb != acb) || (pCCB->startdone != ARCMSR_CCB_START)) { + if (pCCB->startdone == ARCMSR_CCB_ABORTED) { + struct scsi_cmnd *abortcmd = pCCB->pcmd; if (abortcmd) { id = abortcmd->device->id; - lun = abortcmd->device->lun; + lun = abortcmd->device->lun; abortcmd->result |= DID_ABORT << 16; - arcmsr_ccb_complete(ccb); - printk(KERN_NOTICE "arcmsr%d: ccb ='0x%p' \ - isr got aborted command \n", acb->host->host_no, ccb); + arcmsr_ccb_complete(pCCB); + printk(KERN_NOTICE "arcmsr%d: pCCB ='0x%p' isr got aborted command \n", + acb->host->host_no, pCCB); } + return; } printk(KERN_NOTICE "arcmsr%d: isr get an illegal ccb command \ done acb = '0x%p'" @@ -876,20 +943,22 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t fla " ccboutstandingcount = %d \n" , acb->host->host_no , acb - , ccb - , ccb->acb - , ccb->startdone + , pCCB + , pCCB->acb + , pCCB->startdone , atomic_read(&acb->ccboutstandingcount)); + return; } - else - arcmsr_report_ccb_state(acb, ccb, flag_ccb); + arcmsr_report_ccb_state(acb, pCCB, error); } static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) { int i = 0; uint32_t flag_ccb; - + struct ARCMSR_CDB *pARCMSR_CDB; + bool error; + struct CommandControlBlock *pCCB; switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { @@ -899,9 +968,12 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) acb->outbound_int_enable; /*clear and abort all outbound posted Q*/ writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) + while(((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { - arcmsr_drain_donequeue(acb, flag_ccb); + pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ + pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb); + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? true : false; + arcmsr_drain_donequeue(acb, pCCB, error); } } break; @@ -909,17 +981,37 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; /*clear all outbound posted Q*/ + writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, ®->iop2drv_doorbell); /* clear doorbell interrupt */ for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) { writel(0, ®->done_qbuffer[i]); - arcmsr_drain_donequeue(acb, flag_ccb); + pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset+(flag_ccb << 5));/*frame must be 32 bytes aligned*/ + pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb); + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? true : false; + arcmsr_drain_donequeue(acb, pCCB, error); } - writel(0, ®->post_qbuffer[i]); + reg->post_qbuffer[i] = 0; } reg->doneq_index = 0; reg->postq_index = 0; } break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *reg = acb->pmuC; + struct ARCMSR_CDB *pARCMSR_CDB; + uint32_t flag_ccb, ccb_cdb_phy; + bool error; + struct CommandControlBlock *pCCB; + while ((readl(®->host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { + /*need to do*/ + flag_ccb = readl(®->outbound_queueport_low); + ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); + pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset+ccb_cdb_phy);/*frame must be 32 bytes aligned*/ + pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb); + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false; + arcmsr_drain_donequeue(acb, pCCB, error); + } + } } } static void arcmsr_remove(struct pci_dev *pdev) @@ -930,16 +1022,15 @@ static void arcmsr_remove(struct pci_dev *pdev) int poll_count = 0; arcmsr_free_sysfs_attr(acb); scsi_remove_host(host); - scsi_host_put(host); flush_scheduled_work(); del_timer_sync(&acb->eternal_timer); arcmsr_disable_outbound_ints(acb); arcmsr_stop_adapter_bgrb(acb); - arcmsr_flush_adapter_cache(acb); + arcmsr_flush_adapter_cache(acb); acb->acb_flags |= ACB_F_SCSISTOPADAPTER; acb->acb_flags &= ~ACB_F_IOP_INITED; - for (poll_count = 0; poll_count < ARCMSR_MAX_OUTSTANDING_CMD; poll_count++) { + for (poll_count = 0; poll_count < ARCMSR_MAX_OUTSTANDING_CMD; poll_count++){ if (!atomic_read(&acb->ccboutstandingcount)) break; arcmsr_interrupt(acb);/* FIXME: need spinlock */ @@ -962,8 +1053,10 @@ static void arcmsr_remove(struct pci_dev *pdev) } free_irq(pdev->irq, acb); arcmsr_free_ccb_pool(acb); - arcmsr_free_mu(acb); + arcmsr_free_hbb_mu(acb); + arcmsr_unmap_pciregion(acb); pci_release_regions(pdev); + scsi_host_put(host); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } @@ -983,7 +1076,6 @@ static void arcmsr_shutdown(struct pci_dev *pdev) static int arcmsr_module_init(void) { int error = 0; - error = pci_register_driver(&arcmsr_pci_driver); return error; } @@ -999,10 +1091,9 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, u32 intmask_org) { u32 mask; - switch (acb->adapter_type) { - case ACB_ADAPTER_TYPE_A : { + case ACB_ADAPTER_TYPE_A: { struct MessageUnit_A __iomem *reg = acb->pmuA; mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE| @@ -1012,7 +1103,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, } break; - case ACB_ADAPTER_TYPE_B : { + case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | ARCMSR_IOP2DRV_DATA_READ_OK | @@ -1021,6 +1112,13 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, writel(mask, reg->iop2drv_doorbell_mask); acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; } + break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *reg = acb->pmuC; + mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK|ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); + writel(intmask_org & mask, ®->host_int_mask); + acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; + } } } @@ -1032,75 +1130,69 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb, __le32 address_lo, address_hi; int arccdbsize = 0x30; __le32 length = 0; - int i, cdb_sgcount = 0; + int i; struct scatterlist *sg; int nseg; - ccb->pcmd = pcmd; memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); - arcmsr_cdb->Bus = 0; arcmsr_cdb->TargetID = pcmd->device->id; arcmsr_cdb->LUN = pcmd->device->lun; arcmsr_cdb->Function = 1; - arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len; arcmsr_cdb->Context = 0; memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); nseg = scsi_dma_map(pcmd); - if (nseg > acb->host->sg_tablesize || nseg < 0) + if (unlikely(nseg > acb->host->sg_tablesize || nseg < 0)) return FAILED; - /* map stor port SG list to our iop SG List. */ - scsi_for_each_sg(pcmd, sg, nseg, i) { - /* Get the physical address of the current data pointer */ - length = cpu_to_le32(sg_dma_len(sg)); - address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sg))); - address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sg))); - if (address_hi == 0) { - struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; - - pdma_sg->address = address_lo; - pdma_sg->length = length; - psge += sizeof (struct SG32ENTRY); - arccdbsize += sizeof (struct SG32ENTRY); - } else { - struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; + scsi_for_each_sg(pcmd, sg, nseg, i) { + /* Get the physical address of the current data pointer */ + length = cpu_to_le32(sg_dma_len(sg)); + address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sg))); + address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sg))); + if (address_hi == 0) { + struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; + + pdma_sg->address = address_lo; + pdma_sg->length = length; + psge += sizeof (struct SG32ENTRY); + arccdbsize += sizeof (struct SG32ENTRY); + } else { + struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; - pdma_sg->addresshigh = address_hi; - pdma_sg->address = address_lo; - pdma_sg->length = length|cpu_to_le32(IS_SG64_ADDR); - psge += sizeof (struct SG64ENTRY); - arccdbsize += sizeof (struct SG64ENTRY); - } - cdb_sgcount++; + pdma_sg->addresshigh = address_hi; + pdma_sg->address = address_lo; + pdma_sg->length = length|cpu_to_le32(IS_SG64_ADDR); + psge += sizeof (struct SG64ENTRY); + arccdbsize += sizeof (struct SG64ENTRY); } - arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount; - arcmsr_cdb->DataLength = scsi_bufflen(pcmd); + } + arcmsr_cdb->sgcount = (uint8_t)nseg; + arcmsr_cdb->DataLength = scsi_bufflen(pcmd); arcmsr_cdb->msgPages = arccdbsize/0x100 + (arccdbsize % 0x100 ? 1 : 0); - if ( arccdbsize > 256) - arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; - if (pcmd->cmnd[0]|WRITE_6 || pcmd->cmnd[0] | WRITE_10 || pcmd->cmnd[0]|WRITE_12) { + if ( arccdbsize > 256) + arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; + if (pcmd->cmnd[0]|WRITE_6 || pcmd->cmnd[0]|WRITE_10 || pcmd->cmnd[0]|WRITE_12 ){ arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; - ccb->ccb_flags |= CCB_FLAG_WRITE; } + ccb->arc_cdb_size = arccdbsize; return SUCCESS; } static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) { - uint32_t shifted_cdb_phyaddr = ccb->shifted_cdb_phyaddr; + uint32_t cdb_phyaddr_pattern = ccb->cdb_phyaddr_pattern; struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; atomic_inc(&acb->ccboutstandingcount); ccb->startdone = ARCMSR_CCB_START; - switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { struct MessageUnit_A __iomem *reg = acb->pmuA; if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) - writel(shifted_cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, + writel(cdb_phyaddr_pattern | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, ®->inbound_queueport); else { - writel(shifted_cdb_phyaddr, ®->inbound_queueport); + writel(cdb_phyaddr_pattern, ®->inbound_queueport); } } break; @@ -1112,11 +1204,10 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); writel(0, ®->post_qbuffer[ending_index]); if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { - writel(shifted_cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\ + writel(cdb_phyaddr_pattern | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\ ®->post_qbuffer[index]); - } - else { - writel(shifted_cdb_phyaddr, ®->post_qbuffer[index]); + } else { + writel(cdb_phyaddr_pattern, ®->post_qbuffer[index]); } index++; index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */ @@ -1124,6 +1215,19 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr writel(ARCMSR_DRV2IOP_CDB_POSTED, reg->drv2iop_doorbell); } break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)acb->pmuC; + uint32_t ccb_post_stamp, arc_cdb_size; + + arc_cdb_size = (ccb->arc_cdb_size > 0x300) ? 0x300 : ccb->arc_cdb_size; + ccb_post_stamp = (cdb_phyaddr_pattern | ((arc_cdb_size - 1) >> 6) | 1); + if (acb->cdb_phyaddr_hi32) { + writel(acb->cdb_phyaddr_hi32, &phbcmu->inbound_queueport_high); + writel(ccb_post_stamp, &phbcmu->inbound_queueport_low); + } else { + writel(ccb_post_stamp, &phbcmu->inbound_queueport_low); + } + } } } @@ -1132,8 +1236,7 @@ static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) struct MessageUnit_A __iomem *reg = acb->pmuA; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); - - if (arcmsr_hba_wait_msgint_ready(acb)) { + if (!arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" , acb->host->host_no); @@ -1146,13 +1249,26 @@ static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) acb->acb_flags &= ~ACB_F_MSG_START_BGRB; writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell); - if (arcmsr_hbb_wait_msgint_ready(acb)) { + if (!arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" , acb->host->host_no); } } +static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *pACB) +{ + struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; + pACB->acb_flags &= ~ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); + if (!arcmsr_hbc_wait_msgint_ready(pACB)) { + printk(KERN_NOTICE + "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" + , pACB->host->host_no); + } + return; +} static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { @@ -1165,21 +1281,15 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) arcmsr_stop_hbb_bgrb(acb); } break; + case ACB_ADAPTER_TYPE_C: { + arcmsr_stop_hbc_bgrb(acb); + } } } static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) { - switch (acb->adapter_type) { - case ACB_ADAPTER_TYPE_A: { - dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle); - iounmap(acb->pmuA); - } - break; - case ACB_ADAPTER_TYPE_B: { - dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle); - } - } + dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle); } void arcmsr_iop_message_read(struct AdapterControlBlock *acb) @@ -1196,6 +1306,10 @@ void arcmsr_iop_message_read(struct AdapterControlBlock *acb) writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell); } break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C __iomem *reg = acb->pmuC; + writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell); + } } } @@ -1221,13 +1335,21 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) writel(ARCMSR_DRV2IOP_DATA_WRITE_OK, reg->drv2iop_doorbell); } break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C __iomem *reg = acb->pmuC; + /* + ** push inbound doorbell tell iop, driver data write ok + ** and wait reply on next hwinterrupt for next Qbuffer post + */ + writel(ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK, ®->inbound_doorbell); + } + break; } } struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) { struct QBUFFER __iomem *qbuffer = NULL; - switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { @@ -1241,6 +1363,10 @@ struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) qbuffer = (struct QBUFFER __iomem *)reg->message_rbuffer; } break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)acb->pmuC; + qbuffer = (struct QBUFFER __iomem *)&phbcmu->message_rbuffer; + } } return qbuffer; } @@ -1248,7 +1374,6 @@ struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) { struct QBUFFER __iomem *pqbuffer = NULL; - switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { @@ -1262,6 +1387,11 @@ static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBloc pqbuffer = (struct QBUFFER __iomem *)reg->message_wbuffer; } break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; + pqbuffer = (struct QBUFFER __iomem *)®->message_wbuffer; + } + } return pqbuffer; } @@ -1272,19 +1402,18 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) struct QBUFFER *pQbuffer; uint8_t __iomem *iop_data; int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; - rqbuf_lastindex = acb->rqbuf_lastindex; rqbuf_firstindex = acb->rqbuf_firstindex; prbuffer = arcmsr_get_iop_rqbuffer(acb); iop_data = (uint8_t __iomem *)prbuffer->data; iop_len = prbuffer->data_len; - my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1); + my_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1) & (ARCMSR_MAX_QBUFFER - 1); if (my_empty_len >= iop_len) { while (iop_len > 0) { pQbuffer = (struct QBUFFER *)&acb->rqbuffer[rqbuf_lastindex]; - memcpy(pQbuffer, iop_data,1); + memcpy(pQbuffer, iop_data, 1); rqbuf_lastindex++; rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; iop_data++; @@ -1335,25 +1464,52 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) { uint32_t outbound_doorbell; struct MessageUnit_A __iomem *reg = acb->pmuA; - outbound_doorbell = readl(®->outbound_doorbell); writel(outbound_doorbell, ®->outbound_doorbell); if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } - if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { + if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { arcmsr_iop2drv_data_read_handle(acb); } } - +static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *pACB) +{ + uint32_t outbound_doorbell; + struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC; + /* + ******************************************************************* + ** Maybe here we need to check wrqbuffer_lock is lock or not + ** DOORBELL: din! don! + ** check if there are any mail need to pack from firmware + ******************************************************************* + */ + outbound_doorbell = readl(®->outbound_doorbell); + writel(outbound_doorbell, ®->outbound_doorbell_clear);/*clear interrupt*/ + if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { + arcmsr_iop2drv_data_wrote_handle(pACB); + } + if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { + arcmsr_iop2drv_data_read_handle(pACB); + } + if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + arcmsr_hbc_message_isr(pACB); /* messenger of "driver to iop commands" */ + } + return; +} static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) { uint32_t flag_ccb; struct MessageUnit_A __iomem *reg = acb->pmuA; - + struct ARCMSR_CDB *pARCMSR_CDB; + struct CommandControlBlock *pCCB; + bool error; while ((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) { - arcmsr_drain_donequeue(acb, flag_ccb); + pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ + pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb); + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? true : false; + arcmsr_drain_donequeue(acb, pCCB, error); } } @@ -1362,29 +1518,62 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) uint32_t index; uint32_t flag_ccb; struct MessageUnit_B *reg = acb->pmuB; - + struct ARCMSR_CDB *pARCMSR_CDB; + struct CommandControlBlock *pCCB; + bool error; index = reg->doneq_index; - while ((flag_ccb = readl(®->done_qbuffer[index])) != 0) { writel(0, ®->done_qbuffer[index]); - arcmsr_drain_donequeue(acb, flag_ccb); + pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset+(flag_ccb << 5));/*frame must be 32 bytes aligned*/ + pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb); + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? true : false; + arcmsr_drain_donequeue(acb, pCCB, error); index++; index %= ARCMSR_MAX_HBB_POSTQUEUE; reg->doneq_index = index; } } + +static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) +{ + struct MessageUnit_C *phbcmu; + struct ARCMSR_CDB *arcmsr_cdb; + struct CommandControlBlock *ccb; + uint32_t flag_ccb, ccb_cdb_phy, throttling = 0; + int error; + + phbcmu = (struct MessageUnit_C *)acb->pmuC; + /* areca cdb command done */ + /* Use correct offset and size for syncing */ + + while (readl(&phbcmu->host_int_status) & + ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR){ + /* check if command done with no error*/ + flag_ccb = readl(&phbcmu->outbound_queueport_low); + ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);/*frame must be 32 bytes aligned*/ + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ccb_cdb_phy); + ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false; + /* check if command done with no error */ + arcmsr_drain_donequeue(acb, ccb, error); + if (throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { + writel(ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING, &phbcmu->inbound_doorbell); + break; + } + throttling++; + } +} /* ********************************************************************************** ** Handle a message interrupt ** -** The only message interrupt we expect is in response to a query for the current adapter config. +** The only message interrupt we expect is in response to a query for the current adapter config. ** We want this in order to compare the drivemap so that we can detect newly-attached drives. ********************************************************************************** */ static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { struct MessageUnit_A *reg = acb->pmuA; - /*clear interrupt and message state*/ writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, ®->outbound_intstatus); schedule_work(&acb->arcmsr_do_message_isr_bh); @@ -1397,13 +1586,29 @@ static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); schedule_work(&acb->arcmsr_do_message_isr_bh); } +/* +********************************************************************************** +** Handle a message interrupt +** +** The only message interrupt we expect is in response to a query for the +** current adapter config. +** We want this in order to compare the drivemap so that we can detect newly-attached drives. +********************************************************************************** +*/ +static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) +{ + struct MessageUnit_C *reg = acb->pmuC; + /*clear interrupt and message state*/ + writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, ®->outbound_doorbell_clear); + schedule_work(&acb->arcmsr_do_message_isr_bh); +} + static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) { uint32_t outbound_intstatus; struct MessageUnit_A __iomem *reg = acb->pmuA; - outbound_intstatus = readl(®->outbound_intstatus) & - acb->outbound_int_enable; + acb->outbound_int_enable; if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { return 1; } @@ -1414,7 +1619,7 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { arcmsr_hba_postqueue_isr(acb); } - if (outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { + if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { /* messenger of "driver to iop commands" */ arcmsr_hba_message_isr(acb); } @@ -1425,9 +1630,8 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) { uint32_t outbound_doorbell; struct MessageUnit_B *reg = acb->pmuB; - outbound_doorbell = readl(reg->iop2drv_doorbell) & - acb->outbound_int_enable; + acb->outbound_int_enable; if (!outbound_doorbell) return 1; @@ -1436,7 +1640,7 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) this action can push HW to write down the clear bit*/ readl(reg->iop2drv_doorbell); writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); - if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { + if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { @@ -1445,14 +1649,37 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { arcmsr_hbb_postqueue_isr(acb); } - if (outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { + if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { /* messenger of "driver to iop commands" */ arcmsr_hbb_message_isr(acb); } - return 0; } +static int arcmsr_handle_hbc_isr(struct AdapterControlBlock *pACB) +{ + uint32_t host_interrupt_status; + struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; + /* + ********************************************* + ** check outbound intstatus + ********************************************* + */ + host_interrupt_status = readl(&phbcmu->host_int_status); + if (!host_interrupt_status) { + /*it must be share irq*/ + return 1; + } + /* MU ioctl transfer doorbell interrupts*/ + if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { + arcmsr_hbc_doorbell_isr(pACB); /* messenger of "ioctl message read write" */ + } + /* MU post queue interrupts*/ + if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { + arcmsr_hbc_postqueue_isr(pACB); /* messenger of "scsi commands" */ + } + return 0; +} static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { @@ -1469,6 +1696,11 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) } } break; + case ACB_ADAPTER_TYPE_C: { + if (arcmsr_handle_hbc_isr(acb)) { + return IRQ_NONE; + } + } } return IRQ_HANDLED; } @@ -1495,7 +1727,6 @@ void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) struct QBUFFER __iomem *pwbuffer; uint8_t __iomem *iop_data; int32_t allxfer_len = 0; - pwbuffer = arcmsr_get_iop_wqbuffer(acb); iop_data = (uint8_t __iomem *)pwbuffer->data; if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { @@ -1528,7 +1759,6 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, (uint32_t ) cmd->cmnd[7] << 8 | (uint32_t ) cmd->cmnd[8]; /* 4 bytes: Areca io control code */ - sg = scsi_sglist(cmd); buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; if (scsi_sg_count(cmd) > 1) { @@ -1554,7 +1784,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, retvalue = ARCMSR_MESSAGE_FAIL; goto message_out; } - + ptmpQbuffer = ver_addr; while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) && (allxfer_len < 1031)) { @@ -1586,10 +1816,10 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, } memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len); pcmdmessagefld->cmdmessage.Length = allxfer_len; - if (acb->fw_flag == FW_DEADLOCK) { + if(acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - } else { - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + }else{ + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } kfree(ver_addr); } @@ -1605,11 +1835,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, retvalue = ARCMSR_MESSAGE_FAIL; goto message_out; } - if (acb->fw_flag == FW_DEADLOCK) { - pcmdmessagefld->cmdmessage.ReturnCode = + if(acb->fw_flag == FW_DEADLOCK) { + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - } else { - pcmdmessagefld->cmdmessage.ReturnCode = + }else{ + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } ptmpuserbuffer = ver_addr; @@ -1672,10 +1902,10 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, acb->rqbuf_firstindex = 0; acb->rqbuf_lastindex = 0; memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - if (acb->fw_flag == FW_DEADLOCK) { + if(acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - } else { + }else{ pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } @@ -1684,10 +1914,10 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { uint8_t *pQbuffer = acb->wqbuffer; - if (acb->fw_flag == FW_DEADLOCK) { + if(acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - } else { + }else{ pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } @@ -1724,10 +1954,10 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, memset(pQbuffer, 0, sizeof(struct QBUFFER)); pQbuffer = acb->wqbuffer; memset(pQbuffer, 0, sizeof(struct QBUFFER)); - if (acb->fw_flag == FW_DEADLOCK) { + if(acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - } else { + }else{ pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } @@ -1735,10 +1965,10 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, break; case ARCMSR_MESSAGE_RETURN_CODE_3F: { - if (acb->fw_flag == FW_DEADLOCK) { + if(acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - } else { + }else{ pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; } @@ -1746,10 +1976,10 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, } case ARCMSR_MESSAGE_SAY_HELLO: { int8_t *hello_string = "Hello! I am ARCMSR"; - if (acb->fw_flag == FW_DEADLOCK) { + if(acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; - } else { + }else{ pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } @@ -1759,7 +1989,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, break; case ARCMSR_MESSAGE_SAY_GOODBYE: - if (acb->fw_flag == FW_DEADLOCK) { + if(acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; } @@ -1767,7 +1997,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, break; case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: - if (acb->fw_flag == FW_DEADLOCK) { + if(acb->fw_flag == FW_DEADLOCK) { pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; } @@ -1792,7 +2022,7 @@ static struct CommandControlBlock *arcmsr_get_freeccb(struct AdapterControlBlock if (!list_empty(head)) { ccb = list_entry(head->next, struct CommandControlBlock, list); list_del_init(&ccb->list); - } else { + }else{ spin_unlock_irqrestore(&acb->ccblist_lock, flags); return 0; } @@ -1862,29 +2092,29 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, cmd->scsi_done = done; cmd->host_scribble = NULL; cmd->result = 0; - - if ((scsicmd == SYNCHRONIZE_CACHE) || (scsicmd == SEND_DIAGNOSTIC)) { - if (acb->devstate[target][lun] == ARECA_RAID_GONE) { - cmd->result = (DID_NO_CONNECT << 16); + if ((scsicmd == SYNCHRONIZE_CACHE) ||(scsicmd == SEND_DIAGNOSTIC)){ + if(acb->devstate[target][lun] == ARECA_RAID_GONE) { + cmd->result = (DID_NO_CONNECT << 16); } cmd->scsi_done(cmd); return 0; } - if (target == 16) { /* virtual device for iop message transfer */ arcmsr_handle_virtual_command(acb, cmd); return 0; } - if (atomic_read(&acb->ccboutstandingcount) >= ARCMSR_MAX_OUTSTANDING_CMD) return SCSI_MLQUEUE_HOST_BUSY; - + if ((scsicmd == SCSI_CMD_ARECA_SPECIFIC)) { + printk(KERN_NOTICE "Receiveing SCSI_CMD_ARECA_SPECIFIC command..\n"); + return 0; + } ccb = arcmsr_get_freeccb(acb); if (!ccb) return SCSI_MLQUEUE_HOST_BUSY; - if ( arcmsr_build_ccb( acb, ccb, cmd ) == FAILED ) { + if (arcmsr_build_ccb( acb, ccb, cmd ) == FAILED) { cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1); cmd->scsi_done(cmd); return 0; @@ -1901,17 +2131,16 @@ static bool arcmsr_get_hba_config(struct AdapterControlBlock *acb) char *acb_device_map = acb->device_map; char __iomem *iop_firm_model = (char __iomem *)(®->message_rwbuffer[15]); char __iomem *iop_firm_version = (char __iomem *)(®->message_rwbuffer[17]); - char __iomem *iop_device_map = (char __iomem *) (®->message_rwbuffer[21]); + char __iomem *iop_device_map = (char __iomem *)(®->message_rwbuffer[21]); int count; - writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); - if (arcmsr_hba_wait_msgint_ready(acb)) { + if (!arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ miscellaneous data' timeout \n", acb->host->host_no); return false; } count = 8; - while (count) { + while (count){ *acb_firm_model = readb(iop_firm_model); acb_firm_model++; iop_firm_model++; @@ -1919,25 +2148,25 @@ static bool arcmsr_get_hba_config(struct AdapterControlBlock *acb) } count = 16; - while (count) { + while (count){ *acb_firm_version = readb(iop_firm_version); acb_firm_version++; iop_firm_version++; count--; } - count = 16; - while (count) { - *acb_device_map = readb(iop_device_map); - acb_device_map++; - iop_device_map++; - count--; - } - printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", + count=16; + while(count){ + *acb_device_map = readb(iop_device_map); + acb_device_map++; + iop_device_map++; + count--; + } + printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", acb->host->host_no, acb->firm_version, acb->firm_model); - acb->signature = readl(®->message_rwbuffer[0]); + acb->signature = readl(®->message_rwbuffer[0]); acb->firm_request_len = readl(®->message_rwbuffer[1]); acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); acb->firm_sdram_size = readl(®->message_rwbuffer[3]); @@ -1962,14 +2191,14 @@ static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) /*firm_version,21,84-99*/ int count; dma_coherent = dma_alloc_coherent(&pdev->dev, sizeof(struct MessageUnit_B), &dma_coherent_handle, GFP_KERNEL); - if (!dma_coherent) { + if (!dma_coherent){ printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error for hbb mu\n", acb->host->host_no); return false; } acb->dma_coherent_handle_hbb_mu = dma_coherent_handle; reg = (struct MessageUnit_B *)dma_coherent; acb->pmuB = reg; - reg->drv2iop_doorbell = (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_DRV2IOP_DOORBELL); + reg->drv2iop_doorbell= (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_DRV2IOP_DOORBELL); reg->drv2iop_doorbell_mask = (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_DRV2IOP_DOORBELL_MASK); reg->iop2drv_doorbell = (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_IOP2DRV_DOORBELL); reg->iop2drv_doorbell_mask = (uint32_t __iomem *)((unsigned long)acb->mem_base0 + ARCMSR_IOP2DRV_DOORBELL_MASK); @@ -1981,41 +2210,41 @@ static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) iop_device_map = (char __iomem *)(®->message_rwbuffer[21]); /*firm_version,21,84-99*/ writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell); - if (arcmsr_hbb_wait_msgint_ready(acb)) { + if (!arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ miscellaneous data' timeout \n", acb->host->host_no); return false; } count = 8; - while (count) { + while (count){ *acb_firm_model = readb(iop_firm_model); acb_firm_model++; iop_firm_model++; count--; } count = 16; - while (count) { + while (count){ *acb_firm_version = readb(iop_firm_version); acb_firm_version++; iop_firm_version++; count--; } - count = 16; - while (count) { - *acb_device_map = readb(iop_device_map); - acb_device_map++; - iop_device_map++; - count--; - } - + count = 16; + while(count){ + *acb_device_map = readb(iop_device_map); + acb_device_map++; + iop_device_map++; + count--; + } + printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", - acb->host->host_no, + acb->host->host_no, acb->firm_version, acb->firm_model); acb->signature = readl(®->message_rwbuffer[1]); - /*firm_signature,1,00-03*/ + /*firm_signature,1,00-03*/ acb->firm_request_len = readl(®->message_rwbuffer[2]); /*firm_request_len,1,04-07*/ acb->firm_numbers_queue = readl(®->message_rwbuffer[3]); @@ -2028,12 +2257,73 @@ static bool arcmsr_get_hbb_config(struct AdapterControlBlock *acb) /*firm_ide_channels,4,16-19*/ return true; } + +static bool arcmsr_get_hbc_config(struct AdapterControlBlock *pACB) +{ + uint32_t intmask_org, Index, firmware_state = 0; + struct MessageUnit_C *reg = pACB->pmuC; + char *acb_firm_model = pACB->firm_model; + char *acb_firm_version = pACB->firm_version; + char *iop_firm_model = (char *)(®->msgcode_rwbuffer[15]); /*firm_model,15,60-67*/ + char *iop_firm_version = (char *)(®->msgcode_rwbuffer[17]); /*firm_version,17,68-83*/ + int count; + /* disable all outbound interrupt */ + intmask_org = readl(®->host_int_mask); /* disable outbound message0 int */ + writel(intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE, ®->host_int_mask); + /* wait firmware ready */ + do { + firmware_state = readl(®->outbound_msgaddr1); + } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0); + /* post "get config" instruction */ + writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); + /* wait message ready */ + for (Index = 0; Index < 2000; Index++) { + if (readl(®->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, ®->outbound_doorbell_clear);/*clear interrupt*/ + break; + } + udelay(10); + } /*max 1 seconds*/ + if (Index >= 2000) { + printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ + miscellaneous data' timeout \n", pACB->host->host_no); + return false; + } + count = 8; + while (count) { + *acb_firm_model = readb(iop_firm_model); + acb_firm_model++; + iop_firm_model++; + count--; + } + count = 16; + while (count) { + *acb_firm_version = readb(iop_firm_version); + acb_firm_version++; + iop_firm_version++; + count--; + } + printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n", + pACB->host->host_no, + pACB->firm_version, + pACB->firm_model); + pACB->firm_request_len = readl(®->msgcode_rwbuffer[1]); /*firm_request_len,1,04-07*/ + pACB->firm_numbers_queue = readl(®->msgcode_rwbuffer[2]); /*firm_numbers_queue,2,08-11*/ + pACB->firm_sdram_size = readl(®->msgcode_rwbuffer[3]); /*firm_sdram_size,3,12-15*/ + pACB->firm_hd_channels = readl(®->msgcode_rwbuffer[4]); /*firm_ide_channels,4,16-19*/ + pACB->firm_cfg_version = readl(®->msgcode_rwbuffer[25]); /*firm_cfg_version,25,100-103*/ + /*all interrupt service will be enable at arcmsr_iop_init*/ + return true; +} static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) { if (acb->adapter_type == ACB_ADAPTER_TYPE_A) return arcmsr_get_hba_config(acb); - else + else if (acb->adapter_type == ACB_ADAPTER_TYPE_B) return arcmsr_get_hbb_config(acb); + else + return arcmsr_get_hbc_config(acb); } static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, @@ -2044,18 +2334,19 @@ static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, struct ARCMSR_CDB *arcmsr_cdb; uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; int rtn; - + bool error; polling_hba_ccb_retry: poll_count++; outbound_intstatus = readl(®->outbound_intstatus) & acb->outbound_int_enable; writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ while (1) { if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) { - if (poll_ccb_done) { + if (poll_ccb_done){ rtn = SUCCESS; break; - } else { - if (poll_count > 100) { + }else { + msleep(25); + if (poll_count > 100){ rtn = FAILED; break; } @@ -2084,76 +2375,132 @@ static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, , ccb , atomic_read(&acb->ccboutstandingcount)); continue; - } else { - arcmsr_report_ccb_state(acb, ccb, flag_ccb); + } + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? true : false; + arcmsr_report_ccb_state(acb, ccb, error); } -} return rtn; } static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { - struct MessageUnit_B *reg = acb->pmuB; + struct MessageUnit_B *reg = acb->pmuB; struct ARCMSR_CDB *arcmsr_cdb; - struct CommandControlBlock *ccb; - uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0; + struct CommandControlBlock *ccb; + uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0; int index, rtn; - + bool error; polling_hbb_ccb_retry: - poll_count++; - /* clear doorbell interrupt */ + poll_count++; + /* clear doorbell interrupt */ writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); - while (1) { - index = reg->doneq_index; - if ((flag_ccb = readl(®->done_qbuffer[index])) == 0) { - if (poll_ccb_done) { + while(1){ + index = reg->doneq_index; + if ((flag_ccb = readl(®->done_qbuffer[index])) == 0) { + if (poll_ccb_done){ rtn = SUCCESS; - break; - } else { - msleep(25); - if (poll_count > 100) { + break; + }else { + msleep(25); + if (poll_count > 100){ rtn = FAILED; - break; - } - goto polling_hbb_ccb_retry; + break; } + goto polling_hbb_ccb_retry; } - writel(0, ®->done_qbuffer[index]); - index++; - /*if last index number set it to 0 */ - index %= ARCMSR_MAX_HBB_POSTQUEUE; - reg->doneq_index = index; - /* check ifcommand done with no error*/ + } + writel(0, ®->done_qbuffer[index]); + index++; + /*if last index number set it to 0 */ + index %= ARCMSR_MAX_HBB_POSTQUEUE; + reg->doneq_index = index; + /* check if command done with no error*/ arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5)); ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); - poll_ccb_done = (ccb == poll_ccb) ? 1:0; - if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { - if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { + poll_ccb_done = (ccb == poll_ccb) ? 1:0; + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" " poll command abort successfully \n" - ,acb->host->host_no - ,ccb->pcmd->device->id - ,ccb->pcmd->device->lun - ,ccb); - ccb->pcmd->result = DID_ABORT << 16; + ,acb->host->host_no + ,ccb->pcmd->device->id + ,ccb->pcmd->device->lun + ,ccb); + ccb->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(ccb); - continue; + continue; + } + printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" + " command done ccb = '0x%p'" + "ccboutstandingcount = %d \n" + , acb->host->host_no + , ccb + , atomic_read(&acb->ccboutstandingcount)); + continue; + } + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? true : false; + arcmsr_report_ccb_state(acb, ccb, error); + } + return rtn; +} + +static int arcmsr_polling_hbc_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) +{ + struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; + uint32_t flag_ccb, ccb_cdb_phy; + struct ARCMSR_CDB *arcmsr_cdb; + bool error; + struct CommandControlBlock *pCCB; + uint32_t poll_ccb_done = 0, poll_count = 0; + int rtn; +polling_hbc_ccb_retry: + poll_count++; + while (1) { + if ((readl(®->host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) == 0) { + if (poll_ccb_done) { + rtn = SUCCESS; + break; + } else { + msleep(25); + if (poll_count > 100) { + rtn = FAILED; + break; } - printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" - " command done ccb = '0x%p'" - "ccboutstandingcount = %d \n" + goto polling_hbc_ccb_retry; + } + } + flag_ccb = readl(®->outbound_queueport_low); + ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); + arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ccb_cdb_phy);/*frame must be 32 bytes aligned*/ + pCCB = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb); + poll_ccb_done = (pCCB == poll_ccb) ? 1 : 0; + /* check ifcommand done with no error*/ + if ((pCCB->acb != acb) || (pCCB->startdone != ARCMSR_CCB_START)) { + if (pCCB->startdone == ARCMSR_CCB_ABORTED) { + printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" + " poll command abort successfully \n" , acb->host->host_no - , ccb - , atomic_read(&acb->ccboutstandingcount)); + , pCCB->pcmd->device->id + , pCCB->pcmd->device->lun + , pCCB); + pCCB->pcmd->result = DID_ABORT << 16; + arcmsr_ccb_complete(pCCB); continue; - } else { - arcmsr_report_ccb_state(acb, ccb, flag_ccb); + } + printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" + " command done ccb = '0x%p'" + "ccboutstandingcount = %d \n" + , acb->host->host_no + , pCCB + , atomic_read(&acb->ccboutstandingcount)); + continue; } - } /*drain reply FIFO*/ + error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false; + arcmsr_report_ccb_state(acb, pCCB, error); + } return rtn; } - static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { @@ -2168,6 +2515,10 @@ static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, case ACB_ADAPTER_TYPE_B: { rtn = arcmsr_polling_hbb_ccbdone(acb, poll_ccb); } + break; + case ACB_ADAPTER_TYPE_C: { + rtn = arcmsr_polling_hbc_ccbdone(acb, poll_ccb); + } } return rtn; } @@ -2185,6 +2536,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) dma_coherent_handle = acb->dma_coherent_handle; cdb_phyaddr = (uint32_t)(dma_coherent_handle); cdb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16); + acb->cdb_phyaddr_hi32 = cdb_phyaddr_hi32; /* *********************************************************************** ** if adapter type B, set window of "post command Q" @@ -2202,7 +2554,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) writel(cdb_phyaddr_hi32, ®->message_rwbuffer[1]); writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, \ ®->inbound_msgaddr0); - if (arcmsr_hba_wait_msgint_ready(acb)) { + if (!arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: ""set ccb high \ part physical address timeout\n", acb->host->host_no); @@ -2223,7 +2575,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) reg->postq_index = 0; reg->doneq_index = 0; writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell); - if (arcmsr_hbb_wait_msgint_ready(acb)) { + if (!arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d:can not set diver mode\n", \ acb->host->host_no); return 1; @@ -2242,7 +2594,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) writel(1056, rwbuffer); writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell); - if (arcmsr_hbb_wait_msgint_ready(acb)) { + if (!arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \ timeout \n",acb->host->host_no); return 1; @@ -2251,6 +2603,27 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) arcmsr_enable_outbound_ints(acb, intmask_org); } break; + case ACB_ADAPTER_TYPE_C: { + if (cdb_phyaddr_hi32 != 0) { + struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; + + if (cdb_phyaddr_hi32 != 0) { + unsigned char Retries = 0x00; + do { + printk(KERN_NOTICE "arcmsr%d: cdb_phyaddr_hi32=0x%x \n", acb->adapter_index, cdb_phyaddr_hi32); + } while (Retries++ < 100); + } + writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->msgcode_rwbuffer[0]); + writel(cdb_phyaddr_hi32, ®->msgcode_rwbuffer[1]); + writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); + if (!arcmsr_hbc_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \ + timeout \n", acb->host->host_no); + return 1; + } + } + } } return 0; } @@ -2258,7 +2631,6 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) { uint32_t firmware_state = 0; - switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { @@ -2277,24 +2649,30 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell); } break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; + do { + firmware_state = readl(®->outbound_msgaddr1); + } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0); + } } } static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; - if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ((acb->acb_flags & ACB_F_ABORT) != 0)) { + if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){ return; } else { acb->fw_flag = FW_NORMAL; - if (atomic_read(&acb->ante_token_value) == atomic_read(&acb->rq_map_token)) { + if (atomic_read(&acb->ante_token_value) == atomic_read(&acb->rq_map_token)){ atomic_set(&acb->rq_map_token, 16); } atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token)); if (atomic_dec_and_test(&acb->rq_map_token)) return; writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); } return; } @@ -2302,7 +2680,25 @@ static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) { struct MessageUnit_B __iomem *reg = acb->pmuB; + if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){ + return; + } else { + acb->fw_flag = FW_NORMAL; + if (atomic_read(&acb->ante_token_value) == atomic_read(&acb->rq_map_token)) { + atomic_set(&acb->rq_map_token,16); + } + atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token)); + if(atomic_dec_and_test(&acb->rq_map_token)) + return; + writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell); + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); + } + return; +} +static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb) +{ + struct MessageUnit_C __iomem *reg = acb->pmuC; if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ((acb->acb_flags & ACB_F_ABORT) != 0)) { return; } else { @@ -2313,8 +2709,9 @@ static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token)); if (atomic_dec_and_test(&acb->rq_map_token)) return; - writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell); - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); } return; } @@ -2322,7 +2719,6 @@ static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) static void arcmsr_request_device_map(unsigned long pacb) { struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb; - switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { arcmsr_request_hba_device_map(acb); @@ -2332,6 +2728,9 @@ static void arcmsr_request_device_map(unsigned long pacb) arcmsr_request_hbb_device_map(acb); } break; + case ACB_ADAPTER_TYPE_C: { + arcmsr_request_hbc_device_map(acb); + } } } @@ -2340,7 +2739,7 @@ static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) struct MessageUnit_A __iomem *reg = acb->pmuA; acb->acb_flags |= ACB_F_MSG_START_BGRB; writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); - if (arcmsr_hba_wait_msgint_ready(acb)) { + if (!arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ rebulid' timeout \n", acb->host->host_no); } @@ -2351,12 +2750,24 @@ static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) struct MessageUnit_B *reg = acb->pmuB; acb->acb_flags |= ACB_F_MSG_START_BGRB; writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell); - if (arcmsr_hbb_wait_msgint_ready(acb)) { + if (!arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ rebulid' timeout \n",acb->host->host_no); } } +static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *pACB) +{ + struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC; + pACB->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_START_BGRB, &phbcmu->inbound_msgaddr0); + writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, &phbcmu->inbound_doorbell); + if (!arcmsr_hbc_wait_msgint_ready(pACB)) { + printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ + rebulid' timeout \n", pACB->host->host_no); + } + return; +} static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) { switch (acb->adapter_type) { @@ -2366,6 +2777,8 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: arcmsr_start_hbb_bgrb(acb); break; + case ACB_ADAPTER_TYPE_C: + arcmsr_start_hbc_bgrb(acb); } } @@ -2391,6 +2804,14 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) /* let IOP know data has been read */ } break; + case ACB_ADAPTER_TYPE_C: { + struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; + uint32_t outbound_doorbell; + /* empty doorbell Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); + writel(outbound_doorbell, ®->outbound_doorbell_clear); + writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell); + } } } @@ -2403,12 +2824,14 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) { struct MessageUnit_B *reg = acb->pmuB; writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell); - if(arcmsr_hbb_wait_msgint_ready(acb)) { + if (!arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT"); return; } } break; + case ACB_ADAPTER_TYPE_C: + return; } return; } @@ -2416,21 +2839,33 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) { uint8_t value[64]; - int i; - struct MessageUnit_A __iomem *reg = acb->pmuA; - + int i, count = 0; + struct MessageUnit_A __iomem *pmuA = acb->pmuA; + struct MessageUnit_C __iomem *pmuC = acb->pmuC; + u32 temp = 0; /* backup pci config data */ - printk(KERN_ERR "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no); + printk(KERN_NOTICE "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no); for (i = 0; i < 64; i++) { pci_read_config_byte(acb->pdev, i, &value[i]); } /* hardware reset signal */ if ((acb->dev_id == 0x1680)) { - writel(ARCMSR_ARC1680_BUS_RESET, ®->reserved1[0]); + writel(ARCMSR_ARC1680_BUS_RESET, &pmuA->reserved1[0]); + } else if ((acb->dev_id == 0x1880)) { + do { + count++; + writel(0xF, &pmuC->write_sequence); + writel(0x4, &pmuC->write_sequence); + writel(0xB, &pmuC->write_sequence); + writel(0x2, &pmuC->write_sequence); + writel(0x7, &pmuC->write_sequence); + writel(0xD, &pmuC->write_sequence); + } while ((((temp = readl(&pmuC->host_diagnostic)) | ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5)); + writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic); } else { - pci_write_config_byte(acb->pdev, 0x84, 0x20); + pci_write_config_byte(acb->pdev, 0x84, 0x20); } - msleep(1000); + msleep(2000); /* write back pci config data */ for (i = 0; i < 64; i++) { pci_write_config_byte(acb->pdev, i, value[i]); @@ -2438,35 +2873,11 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) msleep(1000); return; } -/* -**************************************************************************** -**************************************************************************** -*/ - int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd) - { - struct Scsi_Host *shost = NULL; - int i, isleep; - - shost = cmd->device->host; - isleep = sleeptime / 10; - if (isleep > 0) { - for (i = 0; i < isleep; i++) { - msleep(10000); - } - } - - isleep = sleeptime % 10; - if (isleep > 0) { - msleep(isleep * 1000); - } - return 0; - } static void arcmsr_iop_init(struct AdapterControlBlock *acb) { uint32_t intmask_org; - - /* disable all outbound interrupt */ - intmask_org = arcmsr_disable_outbound_ints(acb); + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); arcmsr_wait_firmware_ready(acb); arcmsr_iop_confirm(acb); /*start background rebuild*/ @@ -2485,7 +2896,6 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb) uint32_t intmask_org; uint8_t rtnval = 0x00; int i = 0; - if (atomic_read(&acb->ccboutstandingcount) != 0) { /* disable all outbound interrupt */ intmask_org = arcmsr_disable_outbound_ints(acb); @@ -2514,54 +2924,50 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) uint32_t intmask_org, outbound_doorbell; int retry_count = 0; int rtn = FAILED; - acb = (struct AdapterControlBlock *) cmd->device->host->hostdata; - printk(KERN_ERR "arcmsr: executing eh bus reset .....num_resets = %d, \ - num_aborts = %d \n", acb->num_resets, acb->num_aborts); + printk(KERN_ERR "arcmsr: executing bus reset eh.....num_resets = %d, num_aborts = %d \n", acb->num_resets, acb->num_aborts); acb->num_resets++; - switch (acb->adapter_type) { - case ACB_ADAPTER_TYPE_A: { - if (acb->acb_flags & ACB_F_BUS_RESET) { + switch(acb->adapter_type){ + case ACB_ADAPTER_TYPE_A:{ + if (acb->acb_flags & ACB_F_BUS_RESET){ long timeout; - timeout = wait_event_timeout(wait_q, - (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ); + printk(KERN_ERR "arcmsr: there is an bus reset eh proceeding.......\n"); + timeout = wait_event_timeout(wait_q, (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ); if (timeout) { return SUCCESS; } } acb->acb_flags |= ACB_F_BUS_RESET; - if (arcmsr_iop_reset(acb)) { + if (!arcmsr_iop_reset(acb)) { struct MessageUnit_A __iomem *reg; reg = acb->pmuA; - arcmsr_hardware_reset(acb); - acb->acb_flags &= ~ACB_F_IOP_INITED; + arcmsr_hardware_reset(acb); + acb->acb_flags &= ~ACB_F_IOP_INITED; sleep_again: - arcmsr_sleep_for_bus_reset(cmd); + arcmsr_sleep_for_bus_reset(cmd); if ((readl(®->outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { - printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, \ - retry=%d \n", acb->host->host_no, retry_count); - if (retry_count > retrycount) { + printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d \n", acb->host->host_no, retry_count); + if (retry_count > retrycount) { acb->fw_flag = FW_DEADLOCK; - printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, \ - RETRY TERMINATED!! \n", acb->host->host_no); + printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!! \n", acb->host->host_no); return FAILED; - } - retry_count++; - goto sleep_again; - } - acb->acb_flags |= ACB_F_IOP_INITED; - /* disable all outbound interrupt */ - intmask_org = arcmsr_disable_outbound_ints(acb); + } + retry_count++; + goto sleep_again; + } + acb->acb_flags |= ACB_F_IOP_INITED; + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); arcmsr_get_firmware_spec(acb); - arcmsr_start_adapter_bgrb(acb); - /* clear Qbuffer if door bell ringed */ - outbound_doorbell = readl(®->outbound_doorbell); - writel(outbound_doorbell, ®->outbound_doorbell); /*clear interrupt */ - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); - /* enable outbound Post Queue,outbound doorbell Interrupt */ - arcmsr_enable_outbound_ints(acb, intmask_org); - atomic_set(&acb->rq_map_token, 16); + arcmsr_start_adapter_bgrb(acb); + /* clear Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); + writel(outbound_doorbell, ®->outbound_doorbell); /*clear interrupt */ + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + atomic_set(&acb->rq_map_token, 16); atomic_set(&acb->ante_token_value, 16); acb->fw_flag = FW_NORMAL; init_timer(&acb->eternal_timer); @@ -2571,35 +2977,35 @@ sleep_again: add_timer(&acb->eternal_timer); acb->acb_flags &= ~ACB_F_BUS_RESET; rtn = SUCCESS; - printk(KERN_ERR "arcmsr: scsi eh bus reset succeeds\n"); + printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n"); } else { acb->acb_flags &= ~ACB_F_BUS_RESET; if (atomic_read(&acb->rq_map_token) == 0) { atomic_set(&acb->rq_map_token, 16); atomic_set(&acb->ante_token_value, 16); acb->fw_flag = FW_NORMAL; - init_timer(&acb->eternal_timer); + init_timer(&acb->eternal_timer); acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); - acb->eternal_timer.data = (unsigned long) acb; - acb->eternal_timer.function = &arcmsr_request_device_map; - add_timer(&acb->eternal_timer); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); } else { atomic_set(&acb->rq_map_token, 16); atomic_set(&acb->ante_token_value, 16); acb->fw_flag = FW_NORMAL; mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); - } + } rtn = SUCCESS; - } + } break; } case ACB_ADAPTER_TYPE_B:{ acb->acb_flags |= ACB_F_BUS_RESET; - if (arcmsr_iop_reset(acb)) { + if (!arcmsr_iop_reset(acb)) { acb->acb_flags &= ~ACB_F_BUS_RESET; rtn = FAILED; - } else { - acb->acb_flags &= ~ACB_F_BUS_RESET; + } else { + acb->acb_flags &= ~ACB_F_BUS_RESET; if (atomic_read(&acb->rq_map_token) == 0) { atomic_set(&acb->rq_map_token, 16); atomic_set(&acb->ante_token_value, 16); @@ -2616,7 +3022,78 @@ sleep_again: mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); } rtn = SUCCESS; - } + } + break; + } + case ACB_ADAPTER_TYPE_C:{ + if (acb->acb_flags & ACB_F_BUS_RESET) { + long timeout; + printk(KERN_ERR "arcmsr: there is an bus reset eh proceeding.......\n"); + timeout = wait_event_timeout(wait_q, (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ); + if (timeout) { + return SUCCESS; + } + } + acb->acb_flags |= ACB_F_BUS_RESET; + if (!arcmsr_iop_reset(acb)) { + struct MessageUnit_C __iomem *reg; + reg = acb->pmuC; + arcmsr_hardware_reset(acb); + acb->acb_flags &= ~ACB_F_IOP_INITED; +sleep: + arcmsr_sleep_for_bus_reset(cmd); + if ((readl(®->host_diagnostic) & 0x04) != 0) { + printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d \n", acb->host->host_no, retry_count); + if (retry_count > retrycount) { + acb->fw_flag = FW_DEADLOCK; + printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!! \n", acb->host->host_no); + return FAILED; + } + retry_count++; + goto sleep; + } + acb->acb_flags |= ACB_F_IOP_INITED; + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); + arcmsr_get_firmware_spec(acb); + arcmsr_start_adapter_bgrb(acb); + /* clear Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); + writel(outbound_doorbell, ®->outbound_doorbell_clear); /*clear interrupt */ + writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + acb->acb_flags &= ~ACB_F_BUS_RESET; + rtn = SUCCESS; + printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n"); + } else { + acb->acb_flags &= ~ACB_F_BUS_RESET; + if (atomic_read(&acb->rq_map_token) == 0) { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + } else { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + } + rtn = SUCCESS; + } + break; } } return rtn; @@ -2626,9 +3103,7 @@ static int arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) { int rtn; - spin_lock_irq(&acb->eh_lock); rtn = arcmsr_polling_ccbdone(acb, ccb); - spin_unlock_irq(&acb->eh_lock); return rtn; } @@ -2638,7 +3113,6 @@ static int arcmsr_abort(struct scsi_cmnd *cmd) (struct AdapterControlBlock *)cmd->device->host->hostdata; int i = 0; int rtn = FAILED; - printk(KERN_NOTICE "arcmsr%d: abort device command of scsi id = %d lun = %d \n", acb->host->host_no, cmd->device->id, cmd->device->lun); @@ -2672,7 +3146,6 @@ static const char *arcmsr_info(struct Scsi_Host *host) static char buf[256]; char *type; int raid6 = 1; - switch (acb->pdev->device) { case PCI_DEVICE_ID_ARECA_1110: case PCI_DEVICE_ID_ARECA_1200: @@ -2696,6 +3169,7 @@ static const char *arcmsr_info(struct Scsi_Host *host) case PCI_DEVICE_ID_ARECA_1381: case PCI_DEVICE_ID_ARECA_1680: case PCI_DEVICE_ID_ARECA_1681: + case PCI_DEVICE_ID_ARECA_1880: type = "SAS"; break; default: -- cgit v1.2.3 From cb237ef7a45f22373575b2d2ad2d06f7d38d6bce Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Thu, 17 Jun 2010 11:51:40 -0700 Subject: [SCSI] ipr: add MMIO write to perform BIST for 64 bit adapters The 64 bit chip used in new adapters does not properly support the BIST register in PCI config space. This patch implements an alternative MMIO write reset method. Signed-off-by: Wayne Boyer Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 37 +++++++++++++++++++++---------------- drivers/scsi/ipr.h | 4 ++++ 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 37158eab3c89..db205c9d42d1 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -174,15 +174,15 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { }; static const struct ipr_chip_t ipr_chip[] = { - { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[1] }, - { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[1] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, IPR_USE_MSI, IPR_SIS64, &ipr_chip_cfg[2] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2, IPR_USE_MSI, IPR_SIS64, &ipr_chip_cfg[2] } + { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] } }; static int ipr_max_bus_speeds [] = { @@ -7451,20 +7451,25 @@ static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd) static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - int rc; + int rc = PCIBIOS_SUCCESSFUL; ENTER; pci_block_user_cfg_access(ioa_cfg->pdev); - rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START); - if (rc != PCIBIOS_SUCCESSFUL) { - pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); - ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); - rc = IPR_RC_JOB_CONTINUE; - } else { + if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO) + writel(IPR_UPROCI_SIS64_START_BIST, + ioa_cfg->regs.set_uproc_interrupt_reg32); + else + rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START); + + if (rc == PCIBIOS_SUCCESSFUL) { ipr_cmd->job_step = ipr_reset_bist_done; ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); rc = IPR_RC_JOB_RETURN; + } else { + pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); + ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); + rc = IPR_RC_JOB_CONTINUE; } LEAVE; diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 0ef9a67112a8..ba63826dd905 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -272,6 +272,7 @@ IPR_PCII_NO_HOST_RRQ | IPR_PCII_IOARRIN_LOST | IPR_PCII_MMIO_ERROR) #define IPR_UPROCI_RESET_ALERT (0x80000000 >> 7) #define IPR_UPROCI_IO_DEBUG_ALERT (0x80000000 >> 9) +#define IPR_UPROCI_SIS64_START_BIST (0x80000000 >> 23) #define IPR_LDUMP_MAX_LONG_ACK_DELAY_IN_USEC 200000 /* 200 ms */ #define IPR_LDUMP_MAX_SHORT_ACK_DELAY_IN_USEC 200000 /* 200 ms */ @@ -1301,6 +1302,9 @@ struct ipr_chip_t { u16 sis_type; #define IPR_SIS32 0x00 #define IPR_SIS64 0x01 + u16 bist_method; +#define IPR_PCI_CFG 0x00 +#define IPR_MMIO 0x01 const struct ipr_chip_cfg_t *cfg; }; -- cgit v1.2.3 From 6e49949c5e9e04d64e16df3723dd3f5bd25a29e2 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 25 Apr 2010 07:03:57 -0500 Subject: [SCSI] Log msg when getting Unit Attention If the user accidentally changes LUN mappings or it occurs due to a bug, then it can cause data corruption that can take months and months to track down. This patch adds a log message when getting REPORT_LUNS_DATA_CHANGED and it adds a generic message for other Unit Attentions with asc == 0x3f. We are working on adding support for handling of these errors, but I think until then we should at least log a message so tracking down problems as a result of one of these changes is a little easier. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a5d630f5f519..c60cffbefa3c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -307,6 +307,19 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) (sshdr.asc == 0x04) && (sshdr.ascq == 0x02)) return FAILED; + if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) + scmd_printk(KERN_WARNING, scmd, + "Warning! Received an indication that the " + "LUN assignments on this target have " + "changed. The Linux SCSI layer does not " + "automatically remap LUN assignments.\n"); + else if (sshdr.asc == 0x3f) + scmd_printk(KERN_WARNING, scmd, + "Warning! Received an indication that the " + "operating parameters on this target have " + "changed. The Linux SCSI layer does not " + "automatically adjust these parameters.\n"); + if (blk_barrier_rq(scmd->request)) /* * barrier requests should always retry on UA -- cgit v1.2.3 From e4bf25fbcc64a87d7dc1d3318ca56c28382757e2 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Fri, 18 Jun 2010 13:16:07 -0700 Subject: [SCSI] scsi:hosts.c Fix warning: variable 'rval' set but not used The below patch fixes a warning message generated by gcc 4.6.0 CC drivers/scsi/hosts.o drivers/scsi/hosts.c: In function 'scsi_host_alloc': drivers/scsi/hosts.c:328:6: warning: variable 'rval' set but not used Fix this by removing the rval but placing a printk warning where it would have been set. Signed-off-by: Justin P. Mattock Signed-off-by: James Bottomley --- drivers/scsi/hosts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 6660fa92ffa1..a2b1414da288 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -325,7 +325,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) { struct Scsi_Host *shost; gfp_t gfp_mask = GFP_KERNEL; - int rval; if (sht->unchecked_isa_dma && privsize) gfp_mask |= __GFP_DMA; @@ -420,7 +419,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->ehandler = kthread_run(scsi_error_handler, shost, "scsi_eh_%d", shost->host_no); if (IS_ERR(shost->ehandler)) { - rval = PTR_ERR(shost->ehandler); + printk(KERN_WARNING "scsi%d: error handler thread failed to spawn, error = %ld\n", + shost->host_no, PTR_ERR(shost->ehandler)); goto fail_kfree; } -- cgit v1.2.3 From 24ae163ed33d2b8a70d2f0b1947b401d0a8e8719 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 22 Jun 2010 13:42:02 +0200 Subject: [SCSI] mvsas: fix potential NULL dereference Stanse found that in mvs_abort_task, mvi_dev is dereferenced earlier than tested for being NULL. Move the assignment below the test. Signed-off-by: Jiri Slaby Signed-off-by: James Bottomley --- drivers/scsi/mvsas/mv_sas.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index f5e321791903..cab924239862 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1640,7 +1640,7 @@ int mvs_abort_task(struct sas_task *task) struct mvs_tmf_task tmf_task; struct domain_device *dev = task->dev; struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; - struct mvs_info *mvi = mvi_dev->mvi_info; + struct mvs_info *mvi; int rc = TMF_RESP_FUNC_FAILED; unsigned long flags; u32 tag; @@ -1650,6 +1650,8 @@ int mvs_abort_task(struct sas_task *task) rc = TMF_RESP_FUNC_FAILED; } + mvi = mvi_dev->mvi_info; + spin_lock_irqsave(&task->task_state_lock, flags); if (task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); -- cgit v1.2.3 From b0f56d3d6becfb338a41615d6ce43d41547502c3 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Thu, 24 Jun 2010 13:34:14 -0700 Subject: [SCSI] ipr: add support for new Obsidian-E embedded adapter This patch allows the driver to recognize a new Obsidian-E based adapter that uses a new subsystem ID. This patch also fixes a few tab/space problems. Signed-off-by: Wayne Boyer Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 2 ++ drivers/scsi/ipr.h | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index db205c9d42d1..ce839c8eeea3 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -8891,6 +8891,8 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { IPR_USE_LONG_TRANSOP_TIMEOUT }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57CC, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, IPR_USE_LONG_TRANSOP_TIMEOUT | IPR_USE_PCI_WARM_RESET }, diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index ba63826dd905..d2ee20dcd888 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -62,12 +62,12 @@ #define IPR_SUBS_DEV_ID_2780 0x0264 #define IPR_SUBS_DEV_ID_5702 0x0266 #define IPR_SUBS_DEV_ID_5703 0x0278 -#define IPR_SUBS_DEV_ID_572E 0x028D -#define IPR_SUBS_DEV_ID_573E 0x02D3 -#define IPR_SUBS_DEV_ID_573D 0x02D4 +#define IPR_SUBS_DEV_ID_572E 0x028D +#define IPR_SUBS_DEV_ID_573E 0x02D3 +#define IPR_SUBS_DEV_ID_573D 0x02D4 #define IPR_SUBS_DEV_ID_571A 0x02C0 #define IPR_SUBS_DEV_ID_571B 0x02BE -#define IPR_SUBS_DEV_ID_571E 0x02BF +#define IPR_SUBS_DEV_ID_571E 0x02BF #define IPR_SUBS_DEV_ID_571F 0x02D5 #define IPR_SUBS_DEV_ID_572A 0x02C1 #define IPR_SUBS_DEV_ID_572B 0x02C2 @@ -82,6 +82,7 @@ #define IPR_SUBS_DEV_ID_57B4 0x033B #define IPR_SUBS_DEV_ID_57B2 0x035F #define IPR_SUBS_DEV_ID_57C6 0x0357 +#define IPR_SUBS_DEV_ID_57CC 0x035C #define IPR_SUBS_DEV_ID_57B5 0x033C #define IPR_SUBS_DEV_ID_57CE 0x035E -- cgit v1.2.3 From 4289a08680d646dcc18e291cb437a292738e504f Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Thu, 24 Jun 2010 17:00:59 -0700 Subject: [SCSI] ipr: change endian swap key to match hardware spec change The value used to change the endian representation on the new adapters has changed. This patch updates that value. Signed-off-by: Wayne Boyer Signed-off-by: James Bottomley --- drivers/scsi/ipr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index d2ee20dcd888..4d31625ab9cf 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1257,7 +1257,7 @@ struct ipr_interrupt_offsets { unsigned long dump_addr_reg; unsigned long dump_data_reg; -#define IPR_ENDIAN_SWAP_KEY 0x000C0C00 +#define IPR_ENDIAN_SWAP_KEY 0x00080800 unsigned long endian_swap_reg; }; -- cgit v1.2.3 From 9ab98f57b3e1d73cd0720d29c21b687ba609cde9 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 28 Jun 2010 01:04:45 +0900 Subject: [SCSI] scsi_debug: fix map_region and unmap_region oops map_region and unmap_region could access to invalid memory area since they don't check the size boundary. Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 136329b4027b..b02bdc6c2cd1 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1991,7 +1991,8 @@ static void map_region(sector_t lba, unsigned int len) block = lba + alignment; rem = do_div(block, granularity); - set_bit(block, map_storep); + if (block < map_size) + set_bit(block, map_storep); lba += granularity - rem; } @@ -2011,7 +2012,8 @@ static void unmap_region(sector_t lba, unsigned int len) block = lba + alignment; rem = do_div(block, granularity); - if (rem == 0 && lba + granularity <= end) + if (rem == 0 && lba + granularity <= end && + block < map_size) clear_bit(block, map_storep); lba += granularity - rem; -- cgit v1.2.3 From 6447f286326690a936c35f9f913499307f869934 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Thu, 1 Jul 2010 15:34:50 -0700 Subject: [SCSI] bnx2i: Separated the hardware's cleanup procedure from ep_disconnect This patch introduces a new bnx2i_hw_ep_disconnect routine which contains all chip related disconnect and clean up procedure of iSCSI offload connections. This separation is intended as a preparation for the subsequent bnx2i_stop patch. Signed-off-by: Eddie Wai Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Reviewed-by: Mike Christie Acked-by: Anil Veerabhadrappa Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 119 +++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 43 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index fa68ab34b998..6edfde5f2e09 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1866,54 +1866,35 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep) } -/** - * bnx2i_ep_disconnect - executes TCP connection teardown process - * @ep: TCP connection (endpoint) handle +/* + * bnx2i_hw_ep_disconnect - executes TCP connection teardown process in the hw + * @ep: TCP connection (bnx2i endpoint) handle * * executes TCP connection teardown process */ -static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) +int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) { - struct bnx2i_endpoint *bnx2i_ep; - struct bnx2i_conn *bnx2i_conn = NULL; - struct iscsi_session *session = NULL; - struct iscsi_conn *conn; + struct bnx2i_hba *hba = bnx2i_ep->hba; struct cnic_dev *cnic; - struct bnx2i_hba *hba; + struct iscsi_session *session = NULL; + struct iscsi_conn *conn = NULL; + int ret = 0; - bnx2i_ep = ep->dd_data; + if (!hba) + return 0; - /* driver should not attempt connection cleanup until TCP_CONNECT - * completes either successfully or fails. Timeout is 9-secs, so - * wait for it to complete - */ - while ((bnx2i_ep->state == EP_STATE_CONNECT_START) && - !time_after(jiffies, bnx2i_ep->timestamp + (12 * HZ))) - msleep(250); + cnic = hba->cnic; + if (!cnic) + return 0; + + if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) + goto destroy_conn; if (bnx2i_ep->conn) { - bnx2i_conn = bnx2i_ep->conn; - conn = bnx2i_conn->cls_conn->dd_data; + conn = bnx2i_ep->conn->cls_conn->dd_data; session = conn->session; - - iscsi_suspend_queue(conn); } - hba = bnx2i_ep->hba; - if (bnx2i_ep->state == EP_STATE_IDLE) - goto return_bnx2i_ep; - cnic = hba->cnic; - - mutex_lock(&hba->net_dev_lock); - - if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) - goto free_resc; - if (bnx2i_ep->hba_age != hba->age) - goto free_resc; - - if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) - goto destory_conn; - bnx2i_ep->state = EP_STATE_DISCONN_START; init_timer(&bnx2i_ep->ofld_timer); @@ -1924,6 +1905,7 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { int close = 0; + int close_ret = 0; if (session) { spin_lock_bh(&session->lock); @@ -1932,11 +1914,13 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) spin_unlock_bh(&session->lock); } if (close) - cnic->cm_close(bnx2i_ep->cm_sk); + close_ret = cnic->cm_close(bnx2i_ep->cm_sk); else - cnic->cm_abort(bnx2i_ep->cm_sk); + close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); + if (close_ret) + bnx2i_ep->state = EP_STATE_DISCONN_COMPL; } else - goto free_resc; + goto out; /* wait for option-2 conn teardown */ wait_event_interruptible(bnx2i_ep->ofld_wait, @@ -1946,20 +1930,69 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) flush_signals(current); del_timer_sync(&bnx2i_ep->ofld_timer); -destory_conn: - if (bnx2i_tear_down_conn(hba, bnx2i_ep)) { +destroy_conn: + if (bnx2i_tear_down_conn(hba, bnx2i_ep)) + ret = -EINVAL; +out: + bnx2i_ep->state = EP_STATE_IDLE; + return ret; +} + + +/** + * bnx2i_ep_disconnect - executes TCP connection teardown process + * @ep: TCP connection (iscsi endpoint) handle + * + * executes TCP connection teardown process + */ +static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) +{ + struct bnx2i_endpoint *bnx2i_ep; + struct bnx2i_conn *bnx2i_conn = NULL; + struct iscsi_conn *conn = NULL; + struct bnx2i_hba *hba; + + bnx2i_ep = ep->dd_data; + + /* driver should not attempt connection cleanup until TCP_CONNECT + * completes either successfully or fails. Timeout is 9-secs, so + * wait for it to complete + */ + while ((bnx2i_ep->state == EP_STATE_CONNECT_START) && + !time_after(jiffies, bnx2i_ep->timestamp + (12 * HZ))) + msleep(250); + + if (bnx2i_ep->conn) { + bnx2i_conn = bnx2i_ep->conn; + conn = bnx2i_conn->cls_conn->dd_data; + iscsi_suspend_queue(conn); + } + hba = bnx2i_ep->hba; + + mutex_lock(&hba->net_dev_lock); + + if (bnx2i_ep->state == EP_STATE_IDLE) + goto return_bnx2i_ep; + + if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) + goto free_resc; + + if (bnx2i_ep->hba_age != hba->age) + goto free_resc; + + /* Do all chip cleanup here */ + if (bnx2i_hw_ep_disconnect(bnx2i_ep)) { mutex_unlock(&hba->net_dev_lock); return; } free_resc: - mutex_unlock(&hba->net_dev_lock); bnx2i_free_qp_resc(hba, bnx2i_ep); return_bnx2i_ep: if (bnx2i_conn) bnx2i_conn->ep = NULL; bnx2i_free_ep(ep); - + mutex_unlock(&hba->net_dev_lock); if (!hba->ofld_conns_active) bnx2i_unreg_dev_all(); -- cgit v1.2.3 From 46012e8b8de325472790d154f4cfb1cf2d4fc49a Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Thu, 1 Jul 2010 15:34:51 -0700 Subject: [SCSI] bnx2i: Created an active linklist which holds bnx2i endpoints This introduces a new active linklist which would link up all active bnx2i_endpoints. This will be used by subsequent patches that follows. Signed-off-by: Eddie Wai Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Acked-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i.h | 4 ++++ drivers/scsi/bnx2i/bnx2i_iscsi.c | 46 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index 6b624e767d3b..c17c3a3d52b8 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -299,6 +299,7 @@ struct iscsi_cid_queue { * @cid_que: iscsi cid queue * @ep_rdwr_lock: read / write lock to synchronize various ep lists * @ep_ofld_list: connection list for pending offload completion + * @ep_active_list: connection list for active offload endpoints * @ep_destroy_list: connection list for pending offload completion * @mp_bd_tbl: BD table to be used with middle path requests * @mp_bd_dma: DMA address of 'mp_bd_tbl' memory buffer @@ -369,6 +370,7 @@ struct bnx2i_hba { rwlock_t ep_rdwr_lock; struct list_head ep_ofld_list; + struct list_head ep_active_list; struct list_head ep_destroy_list; /* @@ -645,6 +647,7 @@ enum { * @link: list head to link elements * @hba: adapter to which this connection belongs * @conn: iscsi connection this EP is linked to + * @cls_ep: associated iSCSI endpoint pointer * @sess: iscsi session this EP is linked to * @cm_sk: cnic sock struct * @hba_age: age to detect if 'iscsid' issues ep_disconnect() @@ -664,6 +667,7 @@ struct bnx2i_endpoint { struct list_head link; struct bnx2i_hba *hba; struct bnx2i_conn *conn; + struct iscsi_endpoint *cls_ep; struct cnic_sock *cm_sk; u32 hba_age; u32 state; diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 6edfde5f2e09..fb5fe88de90f 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -386,6 +386,7 @@ static struct iscsi_endpoint *bnx2i_alloc_ep(struct bnx2i_hba *hba) } bnx2i_ep = ep->dd_data; + bnx2i_ep->cls_ep = ep; INIT_LIST_HEAD(&bnx2i_ep->link); bnx2i_ep->state = EP_STATE_IDLE; bnx2i_ep->ep_iscsi_cid = (u16) -1; @@ -678,7 +679,6 @@ bnx2i_find_ep_in_ofld_list(struct bnx2i_hba *hba, u32 iscsi_cid) return ep; } - /** * bnx2i_find_ep_in_destroy_list - find iscsi_cid in destroy list * @hba: pointer to adapter instance @@ -708,6 +708,39 @@ bnx2i_find_ep_in_destroy_list(struct bnx2i_hba *hba, u32 iscsi_cid) return ep; } + +/** + * bnx2i_ep_active_list_add - add an entry to ep active list + * @hba: pointer to adapter instance + * @ep: pointer to endpoint (transport indentifier) structure + * + * current active conn queue manager + */ +static void bnx2i_ep_active_list_add(struct bnx2i_hba *hba, + struct bnx2i_endpoint *ep) +{ + write_lock_bh(&hba->ep_rdwr_lock); + list_add_tail(&ep->link, &hba->ep_active_list); + write_unlock_bh(&hba->ep_rdwr_lock); +} + + +/** + * bnx2i_ep_active_list_del - deletes an entry to ep active list + * @hba: pointer to adapter instance + * @ep: pointer to endpoint (transport indentifier) structure + * + * current active conn queue manager + */ +static void bnx2i_ep_active_list_del(struct bnx2i_hba *hba, + struct bnx2i_endpoint *ep) +{ + write_lock_bh(&hba->ep_rdwr_lock); + list_del_init(&ep->link); + write_unlock_bh(&hba->ep_rdwr_lock); +} + + /** * bnx2i_setup_host_queue_size - assigns shost->can_queue param * @hba: pointer to adapter instance @@ -784,6 +817,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) goto mp_bdt_mem_err; INIT_LIST_HEAD(&hba->ep_ofld_list); + INIT_LIST_HEAD(&hba->ep_active_list); INIT_LIST_HEAD(&hba->ep_destroy_list); rwlock_init(&hba->ep_rdwr_lock); @@ -857,6 +891,7 @@ void bnx2i_free_hba(struct bnx2i_hba *hba) iscsi_host_remove(shost); INIT_LIST_HEAD(&hba->ep_ofld_list); + INIT_LIST_HEAD(&hba->ep_active_list); INIT_LIST_HEAD(&hba->ep_destroy_list); pci_dev_put(hba->pcidev); @@ -1754,15 +1789,19 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, goto conn_failed; } else rc = cnic->cm_connect(bnx2i_ep->cm_sk, &saddr); - if (rc) goto release_ep; + bnx2i_ep_active_list_add(hba, bnx2i_ep); + if (bnx2i_map_ep_dbell_regs(bnx2i_ep)) - goto release_ep; + goto del_active_ep; + mutex_unlock(&hba->net_dev_lock); return ep; +del_active_ep: + bnx2i_ep_active_list_del(hba, bnx2i_ep); release_ep: if (bnx2i_tear_down_conn(hba, bnx2i_ep)) { mutex_unlock(&hba->net_dev_lock); @@ -1931,6 +1970,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) del_timer_sync(&bnx2i_ep->ofld_timer); destroy_conn: + bnx2i_ep_active_list_del(hba, bnx2i_ep); if (bnx2i_tear_down_conn(hba, bnx2i_ep)) ret = -EINVAL; out: -- cgit v1.2.3 From 55e15c975cbf9ef8b765eba9ebadc96f2a2e5752 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Thu, 1 Jul 2010 15:34:52 -0700 Subject: [SCSI] bnx2i: Optimized the bnx2i_stop connection clean up procedure For cases where the iSCSI disconnection procedure times out due to the iSCSI daemon being slow or unresponsive, the bnx2i_stop routine will now perform hardware cleanup via bnx2i_hw_ep_disconnect on all active endpoints so that subsequent operations will perform properly. Also moved the mutex locks inside ep_connect and ep_disconnect so that proper exclusivity can resolve simultaneous calls to the ep_disconnect routine. v2: Removed the unnecessary read lock in the bnx2i_stop Signed-off-by: Eddie Wai Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Acked-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i.h | 4 ++++ drivers/scsi/bnx2i/bnx2i_init.c | 33 ++++++++++++++++++++++++++++++--- drivers/scsi/bnx2i/bnx2i_iscsi.c | 12 ++++++------ 3 files changed, 40 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index c17c3a3d52b8..fed1a686da67 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -295,6 +295,7 @@ struct iscsi_cid_queue { * @max_cqes: CQ size * @num_ccell: number of command cells per connection * @ofld_conns_active: active connection list + * @eh_wait: wait queue for the endpoint to shutdown * @max_active_conns: max offload connections supported by this device * @cid_que: iscsi cid queue * @ep_rdwr_lock: read / write lock to synchronize various ep lists @@ -306,6 +307,7 @@ struct iscsi_cid_queue { * @dummy_buffer: Dummy buffer to be used with zero length scsicmd reqs * @dummy_buf_dma: DMA address of 'dummy_buffer' memory buffer * @lock: lock to synchonize access to hba structure + * @hba_shutdown_tmo: Timeout value to shutdown each connection * @pci_did: PCI device ID * @pci_vid: PCI vendor ID * @pci_sdid: PCI subsystem device ID @@ -770,6 +772,8 @@ extern struct bnx2i_endpoint *bnx2i_find_ep_in_destroy_list( extern int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep); extern void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action); +extern int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep); + /* Debug related function prototypes */ extern void bnx2i_print_pend_cmd_queue(struct bnx2i_conn *conn); extern void bnx2i_print_active_cmd_queue(struct bnx2i_conn *conn); diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index af6a00a600fb..f0f8361af4e9 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -176,6 +176,9 @@ void bnx2i_start(void *handle) void bnx2i_stop(void *handle) { struct bnx2i_hba *hba = handle; + struct list_head *pos, *tmp; + struct bnx2i_endpoint *bnx2i_ep; + int conns_active; /* check if cleanup happened in GOING_DOWN context */ if (!test_and_clear_bit(ADAPTER_STATE_GOING_DOWN, @@ -187,9 +190,33 @@ void bnx2i_stop(void *handle) * control returns to network driver. So it is required to cleanup and * release all connection resources before returning from this routine. */ - wait_event_interruptible_timeout(hba->eh_wait, - (hba->ofld_conns_active == 0), - hba->hba_shutdown_tmo); + while (hba->ofld_conns_active) { + conns_active = hba->ofld_conns_active; + wait_event_interruptible_timeout(hba->eh_wait, + (hba->ofld_conns_active != conns_active), + hba->hba_shutdown_tmo); + if (hba->ofld_conns_active == conns_active) + break; + } + if (hba->ofld_conns_active) { + /* Stage to force the disconnection + * This is the case where the daemon is either slow or + * not present + */ + printk(KERN_ALERT "bnx2i: Wait timeout, force all eps " + "to disconnect (%d)\n", hba->ofld_conns_active); + mutex_lock(&hba->net_dev_lock); + list_for_each_safe(pos, tmp, &hba->ep_active_list) { + bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link); + /* Clean up the chip only */ + bnx2i_hw_ep_disconnect(bnx2i_ep); + } + mutex_unlock(&hba->net_dev_lock); + if (hba->ofld_conns_active) + printk(KERN_ERR "bnx2i: EP disconnect timeout (%d)!\n", + hba->ofld_conns_active); + } + /* This flag should be cleared last so that ep_disconnect() gracefully * cleans up connection context */ diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index fb5fe88de90f..1600e7cae191 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -708,7 +708,6 @@ bnx2i_find_ep_in_destroy_list(struct bnx2i_hba *hba, u32 iscsi_cid) return ep; } - /** * bnx2i_ep_active_list_add - add an entry to ep active list * @hba: pointer to adapter instance @@ -856,9 +855,9 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) mutex_init(&hba->net_dev_lock); init_waitqueue_head(&hba->eh_wait); if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) - hba->hba_shutdown_tmo = 240 * HZ; + hba->hba_shutdown_tmo = 20 * HZ; else /* 5706/5708/5709 */ - hba->hba_shutdown_tmo = 30 * HZ; + hba->hba_shutdown_tmo = 20 * HZ; if (iscsi_host_add(shost, &hba->pcidev->dev)) goto free_dump_mem; @@ -1700,10 +1699,11 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) { rc = -EINVAL; - goto check_busy; + goto nohba; } cnic = hba->cnic; + mutex_lock(&hba->net_dev_lock); ep = bnx2i_alloc_ep(hba); if (!ep) { rc = -ENOMEM; @@ -1711,7 +1711,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, } bnx2i_ep = ep->dd_data; - mutex_lock(&hba->net_dev_lock); if (bnx2i_adapter_ready(hba)) { rc = -EPERM; goto net_if_down; @@ -1813,8 +1812,9 @@ iscsi_cid_err: bnx2i_free_qp_resc(hba, bnx2i_ep); qp_resc_err: bnx2i_free_ep(ep); - mutex_unlock(&hba->net_dev_lock); check_busy: + mutex_unlock(&hba->net_dev_lock); +nohba: bnx2i_unreg_dev_all(); return ERR_PTR(rc); } -- cgit v1.2.3 From e37d2c4791480e27c2e2e4a556e4d2ba1d353ff8 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Thu, 1 Jul 2010 15:34:53 -0700 Subject: [SCSI] bnx2i: Fine tuned conn destroy and context destroy timeout values Added variables to separate the fine tuned timeout values for connection destroy and context destroy for both 1g and 10g devices. v2: Extended the 5771X disconnect timeout from 10s to 20s as the firmware has a retransmission timeout of 16s. This fixes one of the iscsi_endpoint leak issues when the target is slow or non-responsive to our TCP FIN. Signed-off-by: Eddie Wai Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Acked-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i.h | 4 ++++ drivers/scsi/bnx2i/bnx2i_iscsi.c | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index fed1a686da67..69febb6f958b 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -308,6 +308,8 @@ struct iscsi_cid_queue { * @dummy_buf_dma: DMA address of 'dummy_buffer' memory buffer * @lock: lock to synchonize access to hba structure * @hba_shutdown_tmo: Timeout value to shutdown each connection + * @conn_teardown_tmo: Timeout value to tear down each connection + * @conn_ctx_destroy_tmo: Timeout value to destroy context of each connection * @pci_did: PCI device ID * @pci_vid: PCI vendor ID * @pci_sdid: PCI subsystem device ID @@ -387,6 +389,8 @@ struct bnx2i_hba { struct mutex net_dev_lock;/* sync net device access */ int hba_shutdown_tmo; + int conn_teardown_tmo; + int conn_ctx_destroy_tmo; /* * PCI related info. */ diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 1600e7cae191..f6eebb39fe54 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -854,10 +854,15 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) spin_lock_init(&hba->lock); mutex_init(&hba->net_dev_lock); init_waitqueue_head(&hba->eh_wait); - if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) + if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) { hba->hba_shutdown_tmo = 20 * HZ; - else /* 5706/5708/5709 */ + hba->conn_teardown_tmo = 20 * HZ; + hba->conn_ctx_destroy_tmo = 6 * HZ; + } else { /* 5706/5708/5709 */ hba->hba_shutdown_tmo = 20 * HZ; + hba->conn_teardown_tmo = 10 * HZ; + hba->conn_ctx_destroy_tmo = 2 * HZ; + } if (iscsi_host_add(shost, &hba->pcidev->dev)) goto free_dump_mem; @@ -1633,7 +1638,7 @@ static int bnx2i_tear_down_conn(struct bnx2i_hba *hba, ep->state = EP_STATE_CLEANUP_START; init_timer(&ep->ofld_timer); - ep->ofld_timer.expires = 10*HZ + jiffies; + ep->ofld_timer.expires = hba->conn_ctx_destroy_tmo + jiffies; ep->ofld_timer.function = bnx2i_ep_ofld_timer; ep->ofld_timer.data = (unsigned long) ep; add_timer(&ep->ofld_timer); @@ -1937,7 +1942,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) bnx2i_ep->state = EP_STATE_DISCONN_START; init_timer(&bnx2i_ep->ofld_timer); - bnx2i_ep->ofld_timer.expires = 10*HZ + jiffies; + bnx2i_ep->ofld_timer.expires = hba->conn_teardown_tmo + jiffies; bnx2i_ep->ofld_timer.function = bnx2i_ep_ofld_timer; bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep; add_timer(&bnx2i_ep->ofld_timer); -- cgit v1.2.3 From 2eefb20dbf3032da1ad111c1ce178f899bc4859a Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Thu, 1 Jul 2010 15:34:54 -0700 Subject: [SCSI] bnx2i: Fixed the TCP graceful termination initiation In compliance to RFC793, a TCP graceful termination will be used instead of an abortive termination for the case where the remote has initiated the close of the connection. Additionally, a TCP abortive termination will be used to close the connection when a logout response is not received in time after a logout request has been initiated. Signed-off-by: Eddie Wai Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Acked-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i.h | 2 ++ drivers/scsi/bnx2i/bnx2i_hwi.c | 4 +++ drivers/scsi/bnx2i/bnx2i_iscsi.c | 53 ++++++++++++++++++++++++++-------------- 3 files changed, 40 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index 69febb6f958b..00c033511cbf 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -639,6 +639,8 @@ enum { EP_STATE_CLEANUP_CMPL = 0x800, EP_STATE_TCP_FIN_RCVD = 0x1000, EP_STATE_TCP_RST_RCVD = 0x2000, + EP_STATE_LOGOUT_SENT = 0x4000, + EP_STATE_LOGOUT_RESP_RCVD = 0x8000, EP_STATE_PG_OFLD_FAILED = 0x1000000, EP_STATE_ULP_UPDATE_FAILED = 0x2000000, EP_STATE_CLEANUP_FAILED = 0x4000000, diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 3a66ca24c7bd..d23fc256d585 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -562,6 +562,8 @@ int bnx2i_send_iscsi_logout(struct bnx2i_conn *bnx2i_conn, logout_wqe->num_bds = 1; logout_wqe->cq_index = 0; /* CQ# used for completion, 5771x only */ + bnx2i_conn->ep->state = EP_STATE_LOGOUT_SENT; + bnx2i_ring_dbell_update_sq_params(bnx2i_conn, 1); return 0; } @@ -1482,6 +1484,8 @@ static int bnx2i_process_logout_resp(struct iscsi_session *session, resp_hdr->t2retain = cpu_to_be32(logout->time_to_retain); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr, NULL, 0); + + bnx2i_conn->ep->state = EP_STATE_LOGOUT_RESP_RCVD; done: spin_unlock(&session->lock); return 0; diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index f6eebb39fe54..c66c5a45aa27 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1890,6 +1890,8 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep) case EP_STATE_ULP_UPDATE_START: case EP_STATE_ULP_UPDATE_COMPL: case EP_STATE_TCP_FIN_RCVD: + case EP_STATE_LOGOUT_SENT: + case EP_STATE_LOGOUT_RESP_RCVD: case EP_STATE_ULP_UPDATE_FAILED: ret = 1; break; @@ -1923,6 +1925,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) struct iscsi_session *session = NULL; struct iscsi_conn *conn = NULL; int ret = 0; + int close = 0; + int close_ret = 0; if (!hba) return 0; @@ -1939,33 +1943,44 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) session = conn->session; } - bnx2i_ep->state = EP_STATE_DISCONN_START; - init_timer(&bnx2i_ep->ofld_timer); bnx2i_ep->ofld_timer.expires = hba->conn_teardown_tmo + jiffies; bnx2i_ep->ofld_timer.function = bnx2i_ep_ofld_timer; bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep; add_timer(&bnx2i_ep->ofld_timer); - if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { - int close = 0; - int close_ret = 0; - - if (session) { - spin_lock_bh(&session->lock); - if (session->state == ISCSI_STATE_LOGGING_OUT) - close = 1; - spin_unlock_bh(&session->lock); - } - if (close) - close_ret = cnic->cm_close(bnx2i_ep->cm_sk); - else - close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); - if (close_ret) - bnx2i_ep->state = EP_STATE_DISCONN_COMPL; - } else + if (!test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) goto out; + if (session) { + spin_lock_bh(&session->lock); + if (bnx2i_ep->state != EP_STATE_TCP_FIN_RCVD) { + if (session->state == ISCSI_STATE_LOGGING_OUT) { + if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) { + /* Logout sent, but no resp */ + printk(KERN_ALERT "bnx2i - WARNING " + "logout response was not " + "received!\n"); + } else if (bnx2i_ep->state == + EP_STATE_LOGOUT_RESP_RCVD) + close = 1; + } + } else + close = 1; + + spin_unlock_bh(&session->lock); + } + + bnx2i_ep->state = EP_STATE_DISCONN_START; + + if (close) + close_ret = cnic->cm_close(bnx2i_ep->cm_sk); + else + close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); + + if (close_ret) + bnx2i_ep->state = EP_STATE_DISCONN_COMPL; + /* wait for option-2 conn teardown */ wait_event_interruptible(bnx2i_ep->ofld_wait, bnx2i_ep->state != EP_STATE_DISCONN_START); -- cgit v1.2.3 From 625986c22e5c122b3e2f4e985680393453d8c5ce Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 1 Jul 2010 15:34:55 -0700 Subject: [SCSI] bnx2i: Added host param ISCSI_HOST_PARAM_IPADDRESS This sysfs attribute is proven to be useful during pivot_root. Signed-off-by: Michael Chan Signed-off-by: Eddie Wai Reviewed-by: Benjamin Li Acked-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index c66c5a45aa27..a46ccc380ab1 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1500,6 +1500,26 @@ static int bnx2i_host_get_param(struct Scsi_Host *shost, case ISCSI_HOST_PARAM_NETDEV_NAME: len = sprintf(buf, "%s\n", hba->netdev->name); break; + case ISCSI_HOST_PARAM_IPADDRESS: { + struct list_head *active_list = &hba->ep_active_list; + + read_lock_bh(&hba->ep_rdwr_lock); + if (!list_empty(&hba->ep_active_list)) { + struct bnx2i_endpoint *bnx2i_ep; + struct cnic_sock *csk; + + bnx2i_ep = list_first_entry(active_list, + struct bnx2i_endpoint, + link); + csk = bnx2i_ep->cm_sk; + if (test_bit(SK_F_IPV6, &csk->flags)) + len = sprintf(buf, "%pI6\n", csk->src_ip); + else + len = sprintf(buf, "%pI4\n", csk->src_ip); + } + read_unlock_bh(&hba->ep_rdwr_lock); + break; + } default: return iscsi_host_get_param(shost, param, buf); } @@ -2131,7 +2151,8 @@ struct iscsi_transport bnx2i_iscsi_transport = { ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO | ISCSI_PING_TMO | ISCSI_RECV_TMO | ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME, - .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_NETDEV_NAME, + .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | + ISCSI_HOST_NETDEV_NAME, .create_session = bnx2i_session_create, .destroy_session = bnx2i_session_destroy, .create_conn = bnx2i_conn_create, -- cgit v1.2.3 From a2f1d139df42df6f3a2641591dea9e068b68f68c Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Thu, 1 Jul 2010 15:34:56 -0700 Subject: [SCSI] bnx2i: Updated version from 2.1.1 to 2.1.2 Signed-off-by: Eddie Wai Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index f0f8361af4e9..a796f565f383 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -17,8 +17,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); static u32 adapter_count; #define DRV_MODULE_NAME "bnx2i" -#define DRV_MODULE_VERSION "2.1.1" -#define DRV_MODULE_RELDATE "Mar 24, 2010" +#define DRV_MODULE_VERSION "2.1.2" +#define DRV_MODULE_RELDATE "Jun 28, 2010" static char version[] __devinitdata = "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ -- cgit v1.2.3 From 3cb5469a2ab4b87a7c63dd218fdc1625bc73eccc Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Thu, 8 Jul 2010 14:44:34 -0600 Subject: [SCSI] mpt2sas: driver fails to recover from injected PCIe bus errors fixes surrounding PCIe enhanced error handling: (1) We need to reject all request generated internaly inside the driver as well as request arriving from the scsi mid layer when PCIe EEH is active. The fix is to add a per adapter flag called pci_error_recovery which is checked thru out the driver when request are generated. (2) We don't need to call the pci_driver->remove directly from the PCIe callbacks becuase its already called from the PCIe EEH code. In its place we are shutting down the watchdog timer, and flushing back all pending IO. (3) We need to save and restore the pci state across PCIe EEH handling. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 13 +++++++++ drivers/scsi/mpt2sas/mpt2sas_base.h | 2 ++ drivers/scsi/mpt2sas/mpt2sas_config.c | 2 +- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 4 +-- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 47 ++++++++++++++++++++++++-------- drivers/scsi/mpt2sas/mpt2sas_transport.c | 8 +++--- 6 files changed, 57 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 1f22a764927a..57bcd5c9dcff 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1311,6 +1311,9 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n", ioc->name, (unsigned long long)pio_chip, pio_sz); + /* Save PCI configuration state for recovery from PCI AER/EEH errors */ + pci_save_state(pdev); + return 0; out_fail: @@ -3407,6 +3410,9 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); + if (ioc->pci_error_recovery) + return 0; + ioc_state = mpt2sas_base_get_iocstate(ioc, 0); dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n", ioc->name, __func__, ioc_state)); @@ -3869,6 +3875,13 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); + if (ioc->pci_error_recovery) { + printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n", + ioc->name, __func__); + r = 0; + goto out; + } + if (mpt2sas_fwfault_debug) mpt2sas_halt_firmware(ioc); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 0b0ef5e7899a..0ebef0c0d949 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -477,6 +477,7 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); * @ioc_link_reset_in_progress: phy/hard reset in progress * @ignore_loginfos: ignore loginfos during task managment * @remove_host: flag for when driver unloads, to avoid sending dev resets + * @pci_error_recovery: flag to prevent ioc access until slot reset completes * @wait_for_port_enable_to_complete: * @msix_enable: flag indicating msix is enabled * @msix_vector_count: number msix vectors @@ -617,6 +618,7 @@ struct MPT2SAS_ADAPTER { u8 ignore_loginfos; u8 remove_host; + u8 pci_error_recovery; u8 wait_for_port_enable_to_complete; u8 msix_enable; diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c index e26f9206a521..6afd67b324fe 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c @@ -401,7 +401,7 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t if (ioc->config_cmds.smid == smid) mpt2sas_base_free_smid(ioc, smid); if ((ioc->shost_recovery) || (ioc->config_cmds.status & - MPT2_CMD_RESET)) + MPT2_CMD_RESET) || ioc->pci_error_recovery) goto retry_config; issue_host_reset = 1; r = -EFAULT; diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 55ac1cb34778..b774973f0765 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -2156,7 +2156,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg) !ioc) return -ENODEV; - if (ioc->shost_recovery) + if (ioc->shost_recovery || ioc->pci_error_recovery) return -EAGAIN; if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) { @@ -2275,7 +2275,7 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg) if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc) return -ENODEV; - if (ioc->shost_recovery) + if (ioc->shost_recovery || ioc->pci_error_recovery) return -EAGAIN; memset(&karg, 0, sizeof(struct mpt2_ioctl_command)); diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 854cc91e7aac..6273abd0535e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -1997,7 +1997,8 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel, goto err_out; } - if (ioc->shost_recovery || ioc->remove_host) { + if (ioc->shost_recovery || ioc->remove_host || + ioc->pci_error_recovery) { printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", __func__, ioc->name); rc = FAILED; @@ -2644,7 +2645,8 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) unsigned long flags; struct _tr_list *delayed_tr; - if (ioc->shost_recovery || ioc->remove_host) { + if (ioc->shost_recovery || ioc->remove_host || + ioc->pci_error_recovery) { dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " "progress!\n", __func__, ioc->name)); return; @@ -2742,7 +2744,8 @@ _scsih_tm_tr_volume_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) u16 smid; struct _tr_list *delayed_tr; - if (ioc->shost_recovery || ioc->remove_host) { + if (ioc->shost_recovery || ioc->remove_host || + ioc->pci_error_recovery) { dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " "progress!\n", __func__, ioc->name)); return; @@ -2793,7 +2796,8 @@ _scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, Mpi2SCSITaskManagementReply_t *mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); - if (ioc->shost_recovery || ioc->remove_host) { + if (ioc->shost_recovery || ioc->remove_host || + ioc->pci_error_recovery) { dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " "progress!\n", __func__, ioc->name)); return 1; @@ -2845,7 +2849,8 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, Mpi2SasIoUnitControlRequest_t *mpi_request; u16 smid_sas_ctrl; - if (ioc->shost_recovery || ioc->remove_host) { + if (ioc->shost_recovery || ioc->remove_host || + ioc->pci_error_recovery) { dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " "progress!\n", __func__, ioc->name)); return 1; @@ -3187,7 +3192,10 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc) count++; mpt2sas_base_free_smid(ioc, smid); scsi_dma_unmap(scmd); - scmd->result = DID_RESET << 16; + if (ioc->pci_error_recovery) + scmd->result = DID_NO_CONNECT << 16; + else + scmd->result = DID_RESET << 16; scmd->scsi_done(scmd); } dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n", @@ -3324,6 +3332,12 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) return 0; } + if (ioc->pci_error_recovery) { + scmd->result = DID_NO_CONNECT << 16; + scmd->scsi_done(scmd); + return 0; + } + sas_target_priv_data = sas_device_priv_data->sas_target; /* invalid device handle */ if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) { @@ -4156,7 +4170,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) if (!handle) return -1; - if (ioc->shost_recovery) + if (ioc->shost_recovery || ioc->pci_error_recovery) return -1; if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, @@ -4734,7 +4748,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, _scsih_sas_topology_change_event_debug(ioc, event_data); #endif - if (ioc->shost_recovery || ioc->remove_host) + if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery) return; if (!ioc->sas_hba.num_phys) @@ -4773,7 +4787,8 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, "expander event\n", ioc->name)); return; } - if (ioc->shost_recovery || ioc->remove_host) + if (ioc->shost_recovery || ioc->remove_host || + ioc->pci_error_recovery) return; phy_number = event_data->StartPhyNum + i; reason_code = event_data->PHY[i].PhyStatus & @@ -6273,7 +6288,8 @@ _firmware_event_work(struct work_struct *work) struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; /* the queue is being flushed so ignore this event */ - if (ioc->remove_host || fw_event->cancel_pending_work) { + if (ioc->remove_host || fw_event->cancel_pending_work || + ioc->pci_error_recovery) { _scsih_fw_event_free(ioc, fw_event); return; } @@ -6355,7 +6371,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u16 sz; /* events turned off due to host reset or driver unloading */ - if (ioc->remove_host) + if (ioc->remove_host || ioc->pci_error_recovery) return 1; mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); @@ -7058,12 +7074,17 @@ _scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) case pci_channel_io_normal: return PCI_ERS_RESULT_CAN_RECOVER; case pci_channel_io_frozen: + /* Fatal error, prepare for slot reset */ + ioc->pci_error_recovery = 1; scsi_block_requests(ioc->shost); mpt2sas_base_stop_watchdog(ioc); mpt2sas_base_free_resources(ioc); return PCI_ERS_RESULT_NEED_RESET; case pci_channel_io_perm_failure: - _scsih_remove(pdev); + /* Permanent error, prepare for device removal */ + ioc->pci_error_recovery = 1; + mpt2sas_base_stop_watchdog(ioc); + _scsih_flush_running_cmds(ioc); return PCI_ERS_RESULT_DISCONNECT; } return PCI_ERS_RESULT_NEED_RESET; @@ -7087,7 +7108,9 @@ _scsih_pci_slot_reset(struct pci_dev *pdev) printk(MPT2SAS_INFO_FMT "PCI error: slot reset callback!!\n", ioc->name); + ioc->pci_error_recovery = 0; ioc->pdev = pdev; + pci_restore_state(pdev); rc = mpt2sas_base_map_resources(ioc); if (rc) return PCI_ERS_RESULT_DISCONNECT; diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index f29ea5e78bb3..b55c6dc07470 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -140,7 +140,7 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle, u32 device_info; u32 ioc_status; - if (ioc->shost_recovery) { + if (ioc->shost_recovery || ioc->pci_error_recovery) { printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", __func__, ioc->name); return -EFAULT; @@ -302,7 +302,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, u64 *sas_address_le; u16 wait_state_count; - if (ioc->shost_recovery) { + if (ioc->shost_recovery || ioc->pci_error_recovery) { printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", __func__, ioc->name); return -EFAULT; @@ -894,7 +894,7 @@ mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node; struct _sas_phy *mpt2sas_phy; - if (ioc->shost_recovery) + if (ioc->shost_recovery || ioc->pci_error_recovery) return; spin_lock_irqsave(&ioc->sas_node_lock, flags); @@ -997,7 +997,7 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc, u64 *sas_address_le; u16 wait_state_count; - if (ioc->shost_recovery) { + if (ioc->shost_recovery || ioc->pci_error_recovery) { printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", __func__, ioc->name); return -EFAULT; -- cgit v1.2.3 From 293f82d59ed8b6d61d242e40ee7a6a146fae5eaa Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:45:20 -0700 Subject: [SCSI] bfa: enable new hardware This patch enables support of new mezzanine cards for HP and IBM blade server. - Add new pciids for HP and IBM mezzanine card. - Add a new firmware image for HP mezzanine card, which is running in FC only mode. Rename firmware image to reflect the difference. Change the firmware download code accordingly for the above changes. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_core.c | 1 + drivers/scsi/bfa/bfa_fwimg_priv.h | 25 ++++++--- drivers/scsi/bfa/bfa_ioc.c | 33 ++++++------ drivers/scsi/bfa/bfa_ioc.h | 7 +-- drivers/scsi/bfa/bfa_ioc_cb.c | 36 ++++--------- drivers/scsi/bfa/bfa_ioc_ct.c | 46 +++++++---------- drivers/scsi/bfa/bfa_iocfc.c | 6 +-- drivers/scsi/bfa/bfad.c | 8 +++ drivers/scsi/bfa/bfad_fwimg.c | 76 ++++++++++++++++++++-------- drivers/scsi/bfa/bfad_im_compat.h | 13 +++-- drivers/scsi/bfa/bfad_intr.c | 4 +- drivers/scsi/bfa/include/bfi/bfi_ioc.h | 1 + drivers/scsi/bfa/include/defs/bfa_defs_mfg.h | 3 ++ drivers/scsi/bfa/include/defs/bfa_defs_pci.h | 11 +++- 14 files changed, 155 insertions(+), 115 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 3a7b3f88932f..bef70924d5c8 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -333,6 +333,7 @@ bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids) {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G2P}, {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G1P}, {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT}, + {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT_FC}, }; *npciids = sizeof(__pciids) / sizeof(__pciids[0]); diff --git a/drivers/scsi/bfa/bfa_fwimg_priv.h b/drivers/scsi/bfa/bfa_fwimg_priv.h index 1ec1355924d9..d33e19e54395 100644 --- a/drivers/scsi/bfa/bfa_fwimg_priv.h +++ b/drivers/scsi/bfa/bfa_fwimg_priv.h @@ -21,11 +21,24 @@ #define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */ #define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32)) -extern u32 *bfi_image_ct_get_chunk(u32 off); -extern u32 bfi_image_ct_size; -extern u32 *bfi_image_cb_get_chunk(u32 off); -extern u32 bfi_image_cb_size; -extern u32 *bfi_image_cb; -extern u32 *bfi_image_ct; +/** + * BFI FW image type + */ +enum { + BFI_IMAGE_CB_FC, + BFI_IMAGE_CT_FC, + BFI_IMAGE_CT_CNA, + BFI_IMAGE_MAX, +}; + +extern u32 *bfi_image_get_chunk(int type, uint32_t off); +extern u32 bfi_image_get_size(int type); +extern u32 bfi_image_ct_fc_size; +extern u32 bfi_image_ct_cna_size; +extern u32 bfi_image_cb_fc_size; +extern u32 *bfi_image_ct_fc; +extern u32 *bfi_image_ct_cna; +extern u32 *bfi_image_cb_fc; + #endif /* __BFA_FWIMG_PRIV_H__ */ diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index e038bc9769f6..ef3b3fefbe74 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -59,14 +59,12 @@ BFA_TRC_FILE(CNA, IOC); ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc)) #define bfa_ioc_firmware_unlock(__ioc) \ ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc)) -#define bfa_ioc_fwimg_get_chunk(__ioc, __off) \ - ((__ioc)->ioc_hwif->ioc_fwimg_get_chunk(__ioc, __off)) -#define bfa_ioc_fwimg_get_size(__ioc) \ - ((__ioc)->ioc_hwif->ioc_fwimg_get_size(__ioc)) #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc)) #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) #define bfa_ioc_notify_hbfail(__ioc) \ ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc)) +#define bfa_ioc_is_optrom(__ioc) \ + (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ) bfa_boolean_t bfa_auto_recover = BFA_TRUE; @@ -879,8 +877,8 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) struct bfi_ioc_image_hdr_s *drv_fwhdr; int i; - drv_fwhdr = - (struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0); + drv_fwhdr = (struct bfi_ioc_image_hdr_s *) + bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) { if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) { @@ -907,12 +905,13 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc) /** * If bios/efi boot (flash based) -- return true */ - if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) + if (bfa_ioc_is_optrom(ioc)) return BFA_TRUE; bfa_ioc_fwver_get(ioc, &fwhdr); - drv_fwhdr = - (struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0); + drv_fwhdr = (struct bfi_ioc_image_hdr_s *) + bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); + if (fwhdr.signature != drv_fwhdr->signature) { bfa_trc(ioc, fwhdr.signature); @@ -1125,21 +1124,22 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, /** * Flash based firmware boot */ - bfa_trc(ioc, bfa_ioc_fwimg_get_size(ioc)); - if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) + bfa_trc(ioc, bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc))); + if (bfa_ioc_is_optrom(ioc)) boot_type = BFI_BOOT_TYPE_FLASH; - fwimg = bfa_ioc_fwimg_get_chunk(ioc, chunkno); + fwimg = bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno); + pgnum = bfa_ioc_smem_pgnum(ioc, loff); pgoff = bfa_ioc_smem_pgoff(ioc, loff); bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum); - for (i = 0; i < bfa_ioc_fwimg_get_size(ioc); i++) { + for (i = 0; i < bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) { if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) { chunkno = BFA_IOC_FLASH_CHUNK_NO(i); - fwimg = bfa_ioc_fwimg_get_chunk(ioc, + fwimg = bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), BFA_IOC_FLASH_CHUNK_ADDR(chunkno)); } @@ -1188,6 +1188,7 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc) struct bfi_ioc_attr_s *attr = ioc->attr; attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop); + attr->card_type = bfa_os_ntohl(attr->card_type); attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize); bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR); @@ -1416,7 +1417,7 @@ bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, { ioc->ioc_mc = mc; ioc->pcidev = *pcidev; - ioc->ctdev = (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT); + ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id); ioc->cna = ioc->ctdev && !ioc->fcmode; /** @@ -1916,7 +1917,7 @@ bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc) bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc) { - return ioc->fcmode || (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT); + return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id); } /** diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index d0804406ea1a..2fbb6b2efc7d 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -186,9 +186,6 @@ struct bfa_ioc_hwif_s { bfa_status_t (*ioc_pll_init) (struct bfa_ioc_s *ioc); bfa_boolean_t (*ioc_firmware_lock) (struct bfa_ioc_s *ioc); void (*ioc_firmware_unlock) (struct bfa_ioc_s *ioc); - u32 * (*ioc_fwimg_get_chunk) (struct bfa_ioc_s *ioc, - u32 off); - u32 (*ioc_fwimg_get_size) (struct bfa_ioc_s *ioc); void (*ioc_reg_init) (struct bfa_ioc_s *ioc); void (*ioc_map_port) (struct bfa_ioc_s *ioc); void (*ioc_isr_mode_set) (struct bfa_ioc_s *ioc, @@ -214,6 +211,10 @@ struct bfa_ioc_hwif_s { #define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++) #define BFA_IOC_FWIMG_MINSZ (16 * 1024) +#define BFA_IOC_FWIMG_TYPE(__ioc) \ + (((__ioc)->ctdev) ? \ + (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) : \ + BFI_IMAGE_CB_FC) #define BFA_IOC_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS) #define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS) diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index 3ce85319f739..324bdde7ea2e 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -33,26 +33,13 @@ BFA_TRC_FILE(CNA, IOC_CB); static bfa_status_t bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc); static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc); -static u32 *bfa_ioc_cb_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off); -static u32 bfa_ioc_cb_fwimg_get_size(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); static void bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); -struct bfa_ioc_hwif_s hwif_cb = { - bfa_ioc_cb_pll_init, - bfa_ioc_cb_firmware_lock, - bfa_ioc_cb_firmware_unlock, - bfa_ioc_cb_fwimg_get_chunk, - bfa_ioc_cb_fwimg_get_size, - bfa_ioc_cb_reg_init, - bfa_ioc_cb_map_port, - bfa_ioc_cb_isr_mode_set, - bfa_ioc_cb_notify_hbfail, - bfa_ioc_cb_ownership_reset, -}; +struct bfa_ioc_hwif_s hwif_cb; /** * Called from bfa_ioc_attach() to map asic specific calls. @@ -60,19 +47,16 @@ struct bfa_ioc_hwif_s hwif_cb = { void bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) { - ioc->ioc_hwif = &hwif_cb; -} - -static u32 * -bfa_ioc_cb_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off) -{ - return bfi_image_cb_get_chunk(off); -} + hwif_cb.ioc_pll_init = bfa_ioc_cb_pll_init; + hwif_cb.ioc_firmware_lock = bfa_ioc_cb_firmware_lock; + hwif_cb.ioc_firmware_unlock = bfa_ioc_cb_firmware_unlock; + hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init; + hwif_cb.ioc_map_port = bfa_ioc_cb_map_port; + hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; + hwif_cb.ioc_notify_hbfail = bfa_ioc_cb_notify_hbfail; + hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; -static u32 -bfa_ioc_cb_fwimg_get_size(struct bfa_ioc_s *ioc) -{ - return bfi_image_cb_size; + ioc->ioc_hwif = &hwif_cb; } /** diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 20b58ad5f95c..17bd1513b34e 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -33,27 +33,13 @@ BFA_TRC_FILE(CNA, IOC_CT); static bfa_status_t bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc); static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc); -static u32* bfa_ioc_ct_fwimg_get_chunk(struct bfa_ioc_s *ioc, - u32 off); -static u32 bfa_ioc_ct_fwimg_get_size(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); -struct bfa_ioc_hwif_s hwif_ct = { - bfa_ioc_ct_pll_init, - bfa_ioc_ct_firmware_lock, - bfa_ioc_ct_firmware_unlock, - bfa_ioc_ct_fwimg_get_chunk, - bfa_ioc_ct_fwimg_get_size, - bfa_ioc_ct_reg_init, - bfa_ioc_ct_map_port, - bfa_ioc_ct_isr_mode_set, - bfa_ioc_ct_notify_hbfail, - bfa_ioc_ct_ownership_reset, -}; +struct bfa_ioc_hwif_s hwif_ct; /** * Called from bfa_ioc_attach() to map asic specific calls. @@ -61,19 +47,16 @@ struct bfa_ioc_hwif_s hwif_ct = { void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) { - ioc->ioc_hwif = &hwif_ct; -} + hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; + hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock; + hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; + hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; + hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; + hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; + hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail; + hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; -static u32* -bfa_ioc_ct_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off) -{ - return bfi_image_ct_get_chunk(off); -} - -static u32 -bfa_ioc_ct_fwimg_get_size(struct bfa_ioc_s *ioc) -{ - return bfi_image_ct_size; + ioc->ioc_hwif = &hwif_ct; } /** @@ -95,7 +78,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) /** * If bios boot (flash based) -- do not increment usage count */ - if (bfa_ioc_ct_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) + if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ) return BFA_TRUE; bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); @@ -146,9 +129,14 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc) /** * Firmware lock is relevant only for CNA. + */ + if (!ioc->cna) + return; + + /** * If bios boot (flash based) -- do not decrement usage count */ - if (!ioc->cna || bfa_ioc_ct_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) + if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ) return; /** diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c index a76de2669bfc..273ecece79ad 100644 --- a/drivers/scsi/bfa/bfa_iocfc.c +++ b/drivers/scsi/bfa/bfa_iocfc.c @@ -170,7 +170,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, /** * Initialize chip specific handlers. */ - if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT) { + if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) { iocfc->hwif.hw_reginit = bfa_hwct_reginit; iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack; iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack; @@ -625,9 +625,9 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa->trcmod, bfa->aen, bfa->logm); /** - * Choose FC (ssid: 0x1C) v/s FCoE (ssid: 0x14) mode. + * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC. */ - if (0) + if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC) bfa_ioc_set_fcmode(&bfa->ioc); bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC); diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index d4fc4287ebd3..1b869add20b2 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -1172,6 +1172,14 @@ static struct pci_device_id bfad_id_table[] = { .class = (PCI_CLASS_SERIAL_FIBER << 8), .class_mask = ~0, }, + { + .vendor = BFA_PCI_VENDOR_ID_BROCADE, + .device = BFA_PCI_DEVICE_ID_CT_FC, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .class = (PCI_CLASS_SERIAL_FIBER << 8), + .class_mask = ~0, + }, {0, 0}, }; diff --git a/drivers/scsi/bfa/bfad_fwimg.c b/drivers/scsi/bfa/bfad_fwimg.c index 2ad65f275a92..1baca1a12085 100644 --- a/drivers/scsi/bfa/bfad_fwimg.c +++ b/drivers/scsi/bfa/bfad_fwimg.c @@ -33,16 +33,20 @@ #include #include -u32 bfi_image_ct_size; -u32 bfi_image_cb_size; -u32 *bfi_image_ct; -u32 *bfi_image_cb; +u32 bfi_image_ct_fc_size; +u32 bfi_image_ct_cna_size; +u32 bfi_image_cb_fc_size; +u32 *bfi_image_ct_fc; +u32 *bfi_image_ct_cna; +u32 *bfi_image_cb_fc; -#define BFAD_FW_FILE_CT "ctfw.bin" -#define BFAD_FW_FILE_CB "cbfw.bin" -MODULE_FIRMWARE(BFAD_FW_FILE_CT); -MODULE_FIRMWARE(BFAD_FW_FILE_CB); +#define BFAD_FW_FILE_CT_FC "ctfw_fc.bin" +#define BFAD_FW_FILE_CT_CNA "ctfw_cna.bin" +#define BFAD_FW_FILE_CB_FC "cbfw_fc.bin" +MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC); +MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA); +MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC); u32 * bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image, @@ -74,24 +78,54 @@ error: u32 * bfad_get_firmware_buf(struct pci_dev *pdev) { - if (pdev->device == BFA_PCI_DEVICE_ID_CT) { - if (bfi_image_ct_size == 0) - bfad_read_firmware(pdev, &bfi_image_ct, - &bfi_image_ct_size, BFAD_FW_FILE_CT); - return bfi_image_ct; + if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) { + if (bfi_image_ct_fc_size == 0) + bfad_read_firmware(pdev, &bfi_image_ct_fc, + &bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC); + return bfi_image_ct_fc; + } else if (pdev->device == BFA_PCI_DEVICE_ID_CT) { + if (bfi_image_ct_cna_size == 0) + bfad_read_firmware(pdev, &bfi_image_ct_cna, + &bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA); + return bfi_image_ct_cna; } else { - if (bfi_image_cb_size == 0) - bfad_read_firmware(pdev, &bfi_image_cb, - &bfi_image_cb_size, BFAD_FW_FILE_CB); - return bfi_image_cb; + if (bfi_image_cb_fc_size == 0) + bfad_read_firmware(pdev, &bfi_image_cb_fc, + &bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC); + return bfi_image_cb_fc; } } u32 * -bfi_image_ct_get_chunk(u32 off) -{ return (u32 *)(bfi_image_ct + off); } +bfi_image_ct_fc_get_chunk(u32 off) +{ return (u32 *)(bfi_image_ct_fc + off); } u32 * -bfi_image_cb_get_chunk(u32 off) -{ return (u32 *)(bfi_image_cb + off); } +bfi_image_ct_cna_get_chunk(u32 off) +{ return (u32 *)(bfi_image_ct_cna + off); } +u32 * +bfi_image_cb_fc_get_chunk(u32 off) +{ return (u32 *)(bfi_image_cb_fc + off); } + +uint32_t * +bfi_image_get_chunk(int type, uint32_t off) +{ + switch (type) { + case BFI_IMAGE_CT_FC: return bfi_image_ct_fc_get_chunk(off); break; + case BFI_IMAGE_CT_CNA: return bfi_image_ct_cna_get_chunk(off); break; + case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_get_chunk(off); break; + default: return 0; break; + } +} + +uint32_t +bfi_image_get_size(int type) +{ + switch (type) { + case BFI_IMAGE_CT_FC: return bfi_image_ct_fc_size; break; + case BFI_IMAGE_CT_CNA: return bfi_image_ct_cna_size; break; + case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_size; break; + default: return 0; break; + } +} diff --git a/drivers/scsi/bfa/bfad_im_compat.h b/drivers/scsi/bfa/bfad_im_compat.h index b36be15044a4..0a122abbbe89 100644 --- a/drivers/scsi/bfa/bfad_im_compat.h +++ b/drivers/scsi/bfa/bfad_im_compat.h @@ -18,9 +18,6 @@ #ifndef __BFAD_IM_COMPAT_H__ #define __BFAD_IM_COMPAT_H__ -extern u32 *bfi_image_buf; -extern u32 bfi_image_size; - extern struct device_attribute *bfad_im_host_attrs[]; extern struct device_attribute *bfad_im_vport_attrs[]; @@ -37,10 +34,12 @@ bfad_load_fwimg(struct pci_dev *pdev) static inline void bfad_free_fwimg(void) { - if (bfi_image_ct_size && bfi_image_ct) - vfree(bfi_image_ct); - if (bfi_image_cb_size && bfi_image_cb) - vfree(bfi_image_cb); + if (bfi_image_ct_fc_size && bfi_image_ct_fc) + vfree(bfi_image_ct_fc); + if (bfi_image_ct_cna_size && bfi_image_ct_cna) + vfree(bfi_image_ct_cna); + if (bfi_image_cb_fc_size && bfi_image_cb_fc) + vfree(bfi_image_cb_fc); } #endif diff --git a/drivers/scsi/bfa/bfad_intr.c b/drivers/scsi/bfa/bfad_intr.c index 2b7dbecbebca..fed27d163655 100644 --- a/drivers/scsi/bfa/bfad_intr.c +++ b/drivers/scsi/bfa/bfad_intr.c @@ -151,8 +151,8 @@ bfad_setup_intr(struct bfad_s *bfad) /* Set up the msix entry table */ bfad_init_msix_entry(bfad, msix_entries, mask, max_bit); - if ((pdev->device == BFA_PCI_DEVICE_ID_CT && !msix_disable_ct) || - (pdev->device != BFA_PCI_DEVICE_ID_CT && !msix_disable_cb)) { + if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) || + (!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) { error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec); if (error) { diff --git a/drivers/scsi/bfa/include/bfi/bfi_ioc.h b/drivers/scsi/bfa/include/bfi/bfi_ioc.h index a0158aac0024..03a9c9408ca5 100644 --- a/drivers/scsi/bfa/include/bfi/bfi_ioc.h +++ b/drivers/scsi/bfa/include/bfi/bfi_ioc.h @@ -63,6 +63,7 @@ struct bfi_ioc_attr_s { char fw_version[BFA_VERSION_LEN]; char optrom_version[BFA_VERSION_LEN]; struct bfa_mfg_vpd_s vpd; + uint32_t card_type; /* card type */ }; /** diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h index c5bd9c36ad4d..bfb50eb2124d 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h @@ -86,6 +86,9 @@ enum { BFA_MFG_TYPE_FC4P1 = 415, /* 4G 1port FC card */ BFA_MFG_TYPE_CNA10P2 = 1020, /* 10G 2port CNA card */ BFA_MFG_TYPE_CNA10P1 = 1010, /* 10G 1port CNA card */ + BFA_MFG_TYPE_JAYHAWK = 804, /* Jayhawk mezz card */ + BFA_MFG_TYPE_WANCHESE = 1007, /* Wanchese mezz card */ + BFA_MFG_TYPE_INVALID = 0, /* Invalid card type */ }; #pragma pack(1) diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h b/drivers/scsi/bfa/include/defs/bfa_defs_pci.h index c9b83321694b..ea7d89bbc0bb 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_pci.h @@ -26,8 +26,13 @@ enum { BFA_PCI_DEVICE_ID_FC_8G2P = 0x13, BFA_PCI_DEVICE_ID_FC_8G1P = 0x17, BFA_PCI_DEVICE_ID_CT = 0x14, + BFA_PCI_DEVICE_ID_CT_FC = 0x21, }; +#define bfa_asic_id_ct(devid) \ + ((devid) == BFA_PCI_DEVICE_ID_CT || \ + (devid) == BFA_PCI_DEVICE_ID_CT_FC) + /** * PCI sub-system device and vendor ID information */ @@ -35,7 +40,9 @@ enum { BFA_PCI_FCOE_SSDEVICE_ID = 0x14, }; -#define BFA_PCI_ACCESS_RANGES 1 /* Maximum number of device address ranges - * mapped through different BAR(s). */ +/** + * Maximum number of device address ranges mapped through different BAR(s) + */ +#define BFA_PCI_ACCESS_RANGES 1 #endif /* __BFA_DEFS_PCI_H__ */ -- cgit v1.2.3 From ed96932470e4ca3aab29518a748dc1162853b456 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:45:56 -0700 Subject: [SCSI] bfa: enable basic PBC support The patch includes the driver side changes to enable basic PBC (PreBoot Configuration) feature. - Data structure changes and new definitions for PBC. - APIs to access PBC info. - Remove unused code. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcpim.c | 5 -- drivers/scsi/bfa/bfa_fcport.c | 42 ++++++++-------- drivers/scsi/bfa/bfa_fcxp.c | 14 ++---- drivers/scsi/bfa/bfa_ioc.c | 41 ++++------------ drivers/scsi/bfa/bfa_ioc.h | 1 - drivers/scsi/bfa/bfa_iocfc.c | 27 ++++++----- drivers/scsi/bfa/bfa_iocfc.h | 5 +- drivers/scsi/bfa/bfa_lps.c | 6 --- drivers/scsi/bfa/bfa_port_priv.h | 4 +- drivers/scsi/bfa/bfa_priv.h | 3 -- drivers/scsi/bfa/bfa_rport.c | 5 -- drivers/scsi/bfa/bfa_sgpg.c | 5 -- drivers/scsi/bfa/bfa_uf.c | 5 -- drivers/scsi/bfa/include/bfi/bfi_iocfc.h | 2 + drivers/scsi/bfa/include/bfi/bfi_pbc.h | 62 ++++++++++++++++++++++++ drivers/scsi/bfa/include/defs/bfa_defs_adapter.h | 3 +- drivers/scsi/bfa/include/defs/bfa_defs_boot.h | 10 ++++ drivers/scsi/bfa/include/defs/bfa_defs_mfg.h | 38 +++++++-------- drivers/scsi/bfa/include/defs/bfa_defs_pport.h | 3 ++ 19 files changed, 154 insertions(+), 127 deletions(-) create mode 100644 drivers/scsi/bfa/include/bfi/bfi_pbc.h (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 790c945aeae6..12849e9071cd 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -79,11 +79,6 @@ bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa_ioim_attach(fcpim, meminfo); } -static void -bfa_fcpim_initdone(struct bfa_s *bfa) -{ -} - static void bfa_fcpim_detach(struct bfa_s *bfa) { diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index c589488db0c1..4961b8da9127 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -911,25 +911,6 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport); } -static void -bfa_fcport_initdone(struct bfa_s *bfa) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - - /** - * Initialize port attributes from IOC hardware data. - */ - bfa_fcport_set_wwns(fcport); - if (fcport->cfg.maxfrsize == 0) - fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc); - fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc); - fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc); - - bfa_assert(fcport->cfg.maxfrsize); - bfa_assert(fcport->cfg.rx_bbcredit); - bfa_assert(fcport->speed_sup); -} - static void bfa_fcport_detach(struct bfa_s *bfa) { @@ -1262,6 +1243,29 @@ bfa_fcport_send_stats_clear(void *cbarg) * bfa_pport_public */ +/** + * Called to initialize port attributes + */ +void +bfa_fcport_init(struct bfa_s *bfa) +{ + struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + + /** + * Initialize port attributes from IOC hardware data. + */ + bfa_fcport_set_wwns(fcport); + if (fcport->cfg.maxfrsize == 0) + fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc); + fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc); + fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc); + + bfa_assert(fcport->cfg.maxfrsize); + bfa_assert(fcport->cfg.rx_bbcredit); + bfa_assert(fcport->speed_sup); +} + + /** * Firmware message handler. */ diff --git a/drivers/scsi/bfa/bfa_fcxp.c b/drivers/scsi/bfa/bfa_fcxp.c index cf0ad6782686..8258f88bfee6 100644 --- a/drivers/scsi/bfa/bfa_fcxp.c +++ b/drivers/scsi/bfa/bfa_fcxp.c @@ -148,11 +148,6 @@ bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, claim_fcxps_mem(mod, meminfo); } -static void -bfa_fcxp_initdone(struct bfa_s *bfa) -{ -} - static void bfa_fcxp_detach(struct bfa_s *bfa) { @@ -225,7 +220,7 @@ bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg, bfa_status_t req_status, u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs) { - /**discarded fcxp completion */ + /* discarded fcxp completion */ } static void @@ -527,11 +522,8 @@ bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles, if (nreq_sgles > BFI_SGE_INLINE) { nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles); - if (bfa_sgpg_malloc - (bfa, &fcxp->req_sgpg_q, nreq_sgpg) + if (bfa_sgpg_malloc(bfa, &fcxp->req_sgpg_q, nreq_sgpg) != BFA_STATUS_OK) { - /* bfa_sgpg_wait(bfa, &fcxp->req_sgpg_wqe, - nreq_sgpg); */ /* * TODO */ @@ -685,7 +677,7 @@ bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport, fcxp->send_cbarg = cbarg; /** - * If no room in CPE queue, wait for + * If no room in CPE queue, wait for space in request queue */ send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP); if (!send_req) { diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index ef3b3fefbe74..268c071ce673 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -1608,6 +1608,13 @@ bfa_ioc_error_isr(struct bfa_ioc_s *ioc) bfa_fsm_send_event(ioc, IOC_E_HWERROR); } +void +bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc) +{ + ioc->fcmode = BFA_TRUE; + ioc->port_id = bfa_ioc_pcifn(ioc); +} + #ifndef BFA_BIOS_BUILD /** @@ -1697,6 +1704,9 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, /* For now, model descr uses same model string */ bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr); + ad_attr->card_type = ioc_attr->card_type; + ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type); + if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop)) ad_attr->prototype = 1; else @@ -1866,30 +1876,6 @@ bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc) return w.wwn; } -wwn_t -bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst) -{ - union { - wwn_t wwn; - u8 byte[sizeof(wwn_t)]; - } - w , w5; - - bfa_trc(ioc, inst); - - w.wwn = ioc->attr->mfg_wwn; - w5.byte[0] = 0x50 | w.byte[2] >> 4; - w5.byte[1] = w.byte[2] << 4 | w.byte[3] >> 4; - w5.byte[2] = w.byte[3] << 4 | w.byte[4] >> 4; - w5.byte[3] = w.byte[4] << 4 | w.byte[5] >> 4; - w5.byte[4] = w.byte[5] << 4 | w.byte[6] >> 4; - w5.byte[5] = w.byte[6] << 4 | w.byte[7] >> 4; - w5.byte[6] = w.byte[7] << 4 | (inst & 0x0f00) >> 8; - w5.byte[7] = (inst & 0xff); - - return w5.wwn; -} - u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc) { @@ -1907,13 +1893,6 @@ bfa_ioc_get_mac(struct bfa_ioc_s *ioc) return mac; } -void -bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc) -{ - ioc->fcmode = BFA_TRUE; - ioc->port_id = bfa_ioc_pcifn(ioc); -} - bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc) { diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 2fbb6b2efc7d..df15eccd760f 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -303,7 +303,6 @@ bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, */ wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc); wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc); -wwn_t bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst); mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc); u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc); diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c index 273ecece79ad..afa3da08b788 100644 --- a/drivers/scsi/bfa/bfa_iocfc.c +++ b/drivers/scsi/bfa/bfa_iocfc.c @@ -290,18 +290,6 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg, } } -/** - * BFA submodules initialization completion notification. - */ -static void -bfa_iocfc_initdone_submod(struct bfa_s *bfa) -{ - int i; - - for (i = 0; hal_mods[i]; i++) - hal_mods[i]->initdone(bfa); -} - /** * Start BFA submodules. */ @@ -394,6 +382,8 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa) /** * Configuration is complete - initialize/start submodules */ + bfa_fcport_init(bfa); + if (iocfc->action == BFA_IOCFC_ACT_INIT) bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa); else @@ -531,7 +521,6 @@ bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status) return; } - bfa_iocfc_initdone_submod(bfa); bfa_iocfc_send_cfg(bfa); } @@ -881,6 +870,18 @@ bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns) *wwns = cfgrsp->bootwwns.wwn; } +void +bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg) +{ + struct bfa_iocfc_s *iocfc = &bfa->iocfc; + struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; + + pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled; + pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns; + pbcfg->speed = cfgrsp->pbc_cfg.port_speed; + memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun)); +} + #endif diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h index fbb4bdc9d600..3ee9fe7a7967 100644 --- a/drivers/scsi/bfa/bfa_iocfc.h +++ b/drivers/scsi/bfa/bfa_iocfc.h @@ -116,7 +116,8 @@ struct bfa_iocfc_s { #define bfa_isr_mode_set(__bfa, __msix) \ ((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix)) #define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \ - (__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) + ((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, \ + __nvecs, __maxvec)) /* * FC specific IOC functions. @@ -166,6 +167,8 @@ void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len); void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi, bfa_boolean_t mincfg); void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns); +void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, + struct bfa_boot_pbc_s *pbcfg); #endif /* __BFA_IOCFC_H__ */ diff --git a/drivers/scsi/bfa/bfa_lps.c b/drivers/scsi/bfa/bfa_lps.c index ad06f6189092..acabb44f092f 100644 --- a/drivers/scsi/bfa/bfa_lps.c +++ b/drivers/scsi/bfa/bfa_lps.c @@ -41,7 +41,6 @@ static void bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev); -static void bfa_lps_initdone(struct bfa_s *bfa); static void bfa_lps_detach(struct bfa_s *bfa); static void bfa_lps_start(struct bfa_s *bfa); static void bfa_lps_stop(struct bfa_s *bfa); @@ -346,11 +345,6 @@ bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, } } -static void -bfa_lps_initdone(struct bfa_s *bfa) -{ -} - static void bfa_lps_detach(struct bfa_s *bfa) { diff --git a/drivers/scsi/bfa/bfa_port_priv.h b/drivers/scsi/bfa/bfa_port_priv.h index 40e256ec67ff..c52fe56df0bd 100644 --- a/drivers/scsi/bfa/bfa_port_priv.h +++ b/drivers/scsi/bfa/bfa_port_priv.h @@ -87,5 +87,7 @@ struct bfa_fcport_s { /* * public functions */ -void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); +void bfa_fcport_init(struct bfa_s *bfa); +void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); + #endif /* __BFA_PORT_PRIV_H__ */ diff --git a/drivers/scsi/bfa/bfa_priv.h b/drivers/scsi/bfa/bfa_priv.h index be80fc7e1b0e..bf4939b1676c 100644 --- a/drivers/scsi/bfa/bfa_priv.h +++ b/drivers/scsi/bfa/bfa_priv.h @@ -37,7 +37,6 @@ void *bfad, struct bfa_iocfc_cfg_s *cfg, \ struct bfa_meminfo_s *meminfo, \ struct bfa_pcidev_s *pcidev); \ - static void bfa_ ## __mod ## _initdone(struct bfa_s *bfa); \ static void bfa_ ## __mod ## _detach(struct bfa_s *bfa); \ static void bfa_ ## __mod ## _start(struct bfa_s *bfa); \ static void bfa_ ## __mod ## _stop(struct bfa_s *bfa); \ @@ -47,7 +46,6 @@ struct bfa_module_s hal_mod_ ## __mod = { \ bfa_ ## __mod ## _meminfo, \ bfa_ ## __mod ## _attach, \ - bfa_ ## __mod ## _initdone, \ bfa_ ## __mod ## _detach, \ bfa_ ## __mod ## _start, \ bfa_ ## __mod ## _stop, \ @@ -69,7 +67,6 @@ struct bfa_module_s { struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev); - void (*initdone) (struct bfa_s *bfa); void (*detach) (struct bfa_s *bfa); void (*start) (struct bfa_s *bfa); void (*stop) (struct bfa_s *bfa); diff --git a/drivers/scsi/bfa/bfa_rport.c b/drivers/scsi/bfa/bfa_rport.c index 7c509fa244e4..ccd0680f6f16 100644 --- a/drivers/scsi/bfa/bfa_rport.c +++ b/drivers/scsi/bfa/bfa_rport.c @@ -635,11 +635,6 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa_meminfo_kva(meminfo) = (u8 *) rp; } -static void -bfa_rport_initdone(struct bfa_s *bfa) -{ -} - static void bfa_rport_detach(struct bfa_s *bfa) { diff --git a/drivers/scsi/bfa/bfa_sgpg.c b/drivers/scsi/bfa/bfa_sgpg.c index 279d8f9b8907..ae452c42e40e 100644 --- a/drivers/scsi/bfa/bfa_sgpg.c +++ b/drivers/scsi/bfa/bfa_sgpg.c @@ -93,11 +93,6 @@ bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa; } -static void -bfa_sgpg_initdone(struct bfa_s *bfa) -{ -} - static void bfa_sgpg_detach(struct bfa_s *bfa) { diff --git a/drivers/scsi/bfa/bfa_uf.c b/drivers/scsi/bfa/bfa_uf.c index 4b3c2417d180..b2a37fc952de 100644 --- a/drivers/scsi/bfa/bfa_uf.c +++ b/drivers/scsi/bfa/bfa_uf.c @@ -169,11 +169,6 @@ bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, uf_mem_claim(ufm, meminfo); } -static void -bfa_uf_initdone(struct bfa_s *bfa) -{ -} - static void bfa_uf_detach(struct bfa_s *bfa) { diff --git a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h b/drivers/scsi/bfa/include/bfi/bfi_iocfc.h index c3760df72575..ccdfcc5d7e0b 100644 --- a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h +++ b/drivers/scsi/bfa/include/bfi/bfi_iocfc.h @@ -19,6 +19,7 @@ #define __BFI_IOCFC_H__ #include "bfi.h" +#include #include #include #include @@ -78,6 +79,7 @@ struct bfi_iocfc_cfgrsp_s { struct bfa_iocfc_fwcfg_s fwcfg; struct bfa_iocfc_intr_attr_s intr_attr; struct bfi_iocfc_bootwwns bootwwns; + struct bfi_pbc_s pbc_cfg; }; /** diff --git a/drivers/scsi/bfa/include/bfi/bfi_pbc.h b/drivers/scsi/bfa/include/bfi/bfi_pbc.h new file mode 100644 index 000000000000..88a4154c30c0 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_pbc.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + * + * Linux driver for Brocade Fibre Channel Host Bus Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef __BFI_PBC_H__ +#define __BFI_PBC_H__ + +#pragma pack(1) + +#define BFI_PBC_MAX_BLUNS 8 +#define BFI_PBC_MAX_VPORTS 16 + +#define BFI_PBC_PORT_DISABLED 2 +/** + * PBC boot lun configuration + */ +struct bfi_pbc_blun_s { + wwn_t tgt_pwwn; + lun_t tgt_lun; +}; + +/** + * PBC virtual port configuration + */ +struct bfi_pbc_vport_s { + wwn_t vp_pwwn; + wwn_t vp_nwwn; +}; + +/** + * BFI pre-boot configuration information + */ +struct bfi_pbc_s { + u8 port_enabled; + u8 boot_enabled; + u8 nbluns; + u8 nvports; + u8 port_speed; + u8 rsvd_a; + u16 hss; + wwn_t pbc_pwwn; + wwn_t pbc_nwwn; + struct bfi_pbc_blun_s blun[BFI_PBC_MAX_BLUNS]; + struct bfi_pbc_vport_s vport[BFI_PBC_MAX_VPORTS]; +}; + +#pragma pack() + +#endif /* __BFI_PBC_H__ */ diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h b/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h index 8c208fc8e329..aea0360d67d5 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h @@ -39,7 +39,7 @@ enum { struct bfa_adapter_attr_s { char manufacturer[BFA_ADAPTER_MFG_NAME_LEN]; char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; - u32 rsvd1; + u32 card_type; char model[BFA_ADAPTER_MODEL_NAME_LEN]; char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN]; wwn_t pwwn; @@ -60,6 +60,7 @@ struct bfa_adapter_attr_s { u8 pcie_lanes_orig; u8 pcie_lanes; u8 cna_capable; + u8 is_mezz; }; /** diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h b/drivers/scsi/bfa/include/defs/bfa_defs_boot.h index 6f4aa5283545..0fca10b6ad10 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_boot.h @@ -24,6 +24,8 @@ enum { BFA_BOOT_BOOTLUN_MAX = 4, /* maximum boot lun per IOC */ + BFA_PREBOOT_BOOTLUN_MAX = 8, /* maximum preboot lun per IOC */ + }; #define BOOT_CFG_REV1 1 @@ -67,5 +69,13 @@ struct bfa_boot_cfg_s { struct bfa_boot_bootlun_s blun_disc[BFA_BOOT_BOOTLUN_MAX]; }; +struct bfa_boot_pbc_s { + u8 enable; /* enable/disable SAN boot */ + u8 speed; /* boot speed settings */ + u8 topology; /* boot topology setting */ + u8 rsvd1; + u32 nbluns; /* number of boot luns */ + struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX]; +}; #endif /* __BFA_DEFS_BOOT_H__ */ diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h index bfb50eb2124d..d22fb7909643 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h @@ -44,26 +44,6 @@ */ #define BFA_MFG_CHKSUM_SIZE 16 -/** - * Manufacturing block encrypted version - */ -#define BFA_MFG_ENC_VER 2 - -/** - * Manufacturing block version 1 length - */ -#define BFA_MFG_VER1_LEN 128 - -/** - * Manufacturing block header length - */ -#define BFA_MFG_HDR_LEN 4 - -/** - * Checksum size - */ -#define BFA_MFG_CHKSUM_SIZE 16 - /** * Manufacturing block format */ @@ -98,6 +78,24 @@ enum { */ #define bfa_mfg_type2port_num(card_type) (((card_type) / 10) % 10) +/** + * Check if Mezz card + */ +#define bfa_mfg_is_mezz(type) (( \ + (type) == BFA_MFG_TYPE_JAYHAWK || \ + (type) == BFA_MFG_TYPE_WANCHESE)) + +/** + * Check if card type valid + */ +#define bfa_mfg_is_card_type_valid(type) (( \ + (type) == BFA_MFG_TYPE_FC8P2 || \ + (type) == BFA_MFG_TYPE_FC8P1 || \ + (type) == BFA_MFG_TYPE_FC4P2 || \ + (type) == BFA_MFG_TYPE_FC4P1 || \ + (type) == BFA_MFG_TYPE_CNA10P2 || \ + (type) == BFA_MFG_TYPE_CNA10P1 || \ + bfa_mfg_is_mezz(type))) /** * All numerical fields are in big-endian format. diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h index 26e5cc78095d..de6181cf9677 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h @@ -38,6 +38,7 @@ enum bfa_pport_states { BFA_PPORT_ST_IOCDOWN = 10, BFA_PPORT_ST_IOCDIS = 11, BFA_PPORT_ST_FWMISMATCH = 12, + BFA_PPORT_ST_PREBOOT_DISABLED = 13, BFA_PPORT_ST_MAX_STATE, }; @@ -203,6 +204,8 @@ struct bfa_pport_attr_s { */ wwn_t nwwn; /* node wwn */ wwn_t pwwn; /* port wwn */ + wwn_t factorynwwn; /* factory node wwn */ + wwn_t factorypwwn; /* factory port wwn */ enum fc_cos cos_supported; /* supported class of services */ u32 rsvd; struct fc_symname_s port_symname; /* port symbolic name */ -- cgit v1.2.3 From d9883548a0b0afec4786e6c5cd8d03d43a30b779 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:46:26 -0700 Subject: [SCSI] bfa: PBC vport create This patch enables creating PBC vport. During fcs init, fcs will read PBC vport using bfa iocfc API and invoke fcb callback to add the pbc vport entries into a list. The pbc vport list will be traversed in the subsequent pci probe process and vport will be created using fc transport provided vport create function. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcs.c | 10 +++- drivers/scsi/bfa/bfa_iocfc.c | 11 +++++ drivers/scsi/bfa/bfa_iocfc.h | 3 ++ drivers/scsi/bfa/bfad.c | 61 +++++++++++++++++++++++-- drivers/scsi/bfa/bfad_attr.c | 43 ++++++++++------- drivers/scsi/bfa/bfad_drv.h | 8 ++++ drivers/scsi/bfa/bfad_im.c | 1 + drivers/scsi/bfa/fabric.c | 2 +- drivers/scsi/bfa/fcs_vport.h | 1 + drivers/scsi/bfa/include/defs/bfa_defs_port.h | 12 ++--- drivers/scsi/bfa/include/defs/bfa_defs_status.h | 5 +- drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h | 3 +- drivers/scsi/bfa/include/fcs/bfa_fcs.h | 4 +- drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h | 4 ++ drivers/scsi/bfa/vport.c | 45 ++++++++++++++++++ 15 files changed, 179 insertions(+), 34 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index 3516172c597c..3ec2f49de61d 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -99,14 +99,22 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, void bfa_fcs_init(struct bfa_fcs_s *fcs) { - int i; + int i, npbc_vports; struct bfa_fcs_mod_s *mod; + struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS]; for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { mod = &fcs_modules[i]; if (mod->modinit) mod->modinit(fcs); } + /* Initialize pbc vports */ + if (!fcs->min_cfg) { + npbc_vports = + bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports); + for (i = 0; i < npbc_vports; i++) + bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]); + } } /** diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c index afa3da08b788..d3f1052744d3 100644 --- a/drivers/scsi/bfa/bfa_iocfc.c +++ b/drivers/scsi/bfa/bfa_iocfc.c @@ -882,6 +882,17 @@ bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg) memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun)); } +int +bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport) +{ + struct bfa_iocfc_s *iocfc = &bfa->iocfc; + struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; + + memcpy(pbc_vport, cfgrsp->pbc_cfg.vport, sizeof(cfgrsp->pbc_cfg.vport)); + return cfgrsp->pbc_cfg.nvports; +} + + #endif diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h index 3ee9fe7a7967..a08309fb981d 100644 --- a/drivers/scsi/bfa/bfa_iocfc.h +++ b/drivers/scsi/bfa/bfa_iocfc.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #define BFA_REQQ_NELEMS_MIN (4) @@ -169,6 +170,8 @@ void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi, void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns); void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg); +int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, + struct bfi_pbc_vport_s *pbc_vport); #endif /* __BFA_IOCFC_H__ */ diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 1b869add20b2..37f886d27922 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -322,7 +322,31 @@ ext: return rc; } +/** + * @brief + * FCS PBC VPORT Create + */ +void +bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport) +{ + + struct bfad_pcfg_s *pcfg; + + pcfg = kzalloc(sizeof(struct bfad_pcfg_s), GFP_ATOMIC); + if (!pcfg) { + bfa_trc(bfad, 0); + return; + } + pcfg->port_cfg.roles = BFA_PORT_ROLE_FCP_IM; + pcfg->port_cfg.pwwn = pbc_vport.vp_pwwn; + pcfg->port_cfg.nwwn = pbc_vport.vp_nwwn; + pcfg->port_cfg.preboot_vp = BFA_TRUE; + + list_add_tail(&pcfg->list_entry, &bfad->pbc_pcfg_list); + + return; +} void bfad_hal_mem_release(struct bfad_s *bfad) @@ -481,10 +505,10 @@ ext: */ bfa_status_t bfad_vport_create(struct bfad_s *bfad, u16 vf_id, - struct bfa_port_cfg_s *port_cfg, struct device *dev) + struct bfa_port_cfg_s *port_cfg, struct device *dev) { struct bfad_vport_s *vport; - int rc = BFA_STATUS_OK; + int rc = BFA_STATUS_OK; unsigned long flags; struct completion fcomp; @@ -496,8 +520,12 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id, vport->drv_port.bfad = bfad; spin_lock_irqsave(&bfad->bfad_lock, flags); - rc = bfa_fcs_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, vf_id, - port_cfg, vport); + if (port_cfg->preboot_vp == BFA_TRUE) + rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport, + &bfad->bfa_fcs, vf_id, port_cfg, vport); + else + rc = bfa_fcs_vport_create(&vport->fcs_vport, + &bfad->bfa_fcs, vf_id, port_cfg, vport); spin_unlock_irqrestore(&bfad->bfad_lock, flags); if (rc != BFA_STATUS_OK) @@ -884,6 +912,7 @@ bfa_status_t bfad_start_ops(struct bfad_s *bfad) { int retval; + struct bfad_pcfg_s *pcfg, *pcfg_new; /* PPORT FCS config */ bfad_fcs_port_cfg(bfad); @@ -901,6 +930,27 @@ bfad_start_ops(struct bfad_s *bfad) bfad_drv_start(bfad); + /* pbc vport creation */ + list_for_each_entry_safe(pcfg, pcfg_new, &bfad->pbc_pcfg_list, + list_entry) { + struct fc_vport_identifiers vid; + struct fc_vport *fc_vport; + + memset(&vid, 0, sizeof(vid)); + vid.roles = FC_PORT_ROLE_FCP_INITIATOR; + vid.vport_type = FC_PORTTYPE_NPIV; + vid.disable = false; + vid.node_name = wwn_to_u64((u8 *)&pcfg->port_cfg.nwwn); + vid.port_name = wwn_to_u64((u8 *)&pcfg->port_cfg.pwwn); + fc_vport = fc_vport_create(bfad->pport.im_port->shost, 0, &vid); + if (!fc_vport) + printk(KERN_WARNING "bfad%d: failed to create pbc vport" + " %llx\n", bfad->inst_no, vid.port_name); + list_del(&pcfg->list_entry); + kfree(pcfg); + + } + /* * If bfa_linkup_delay is set to -1 default; try to retrive the * value using the bfad_os_get_linkup_delay(); else use the @@ -928,7 +978,7 @@ out_cfg_pport_failure: } int -bfad_worker (void *ptr) +bfad_worker(void *ptr) { struct bfad_s *bfad; unsigned long flags; @@ -1031,6 +1081,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) bfad->ref_count = 0; bfad->pport.bfad = bfad; + INIT_LIST_HEAD(&bfad->pbc_pcfg_list); bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad, "%s", "bfad_worker"); diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index e477bfbfa7d8..871a30363560 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -373,47 +373,53 @@ bfad_im_vport_create(struct fc_vport *fc_vport, bool disable) (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; struct bfa_port_cfg_s port_cfg; + struct bfad_pcfg_s *pcfg; int status = 0, rc; unsigned long flags; memset(&port_cfg, 0, sizeof(port_cfg)); - - port_cfg.pwwn = wwn_to_u64((u8 *) &fc_vport->port_name); - port_cfg.nwwn = wwn_to_u64((u8 *) &fc_vport->node_name); - + u64_to_wwn(fc_vport->node_name, (u8 *)&port_cfg.nwwn); + u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn); if (strlen(vname) > 0) strcpy((char *)&port_cfg.sym_name, vname); - port_cfg.roles = BFA_PORT_ROLE_FCP_IM; - rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev); + spin_lock_irqsave(&bfad->bfad_lock, flags); + list_for_each_entry(pcfg, &bfad->pbc_pcfg_list, list_entry) { + if (port_cfg.pwwn == pcfg->port_cfg.pwwn) { + port_cfg.preboot_vp = pcfg->port_cfg.preboot_vp; + break; + } + } + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + + rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev); if (rc == BFA_STATUS_OK) { - struct bfad_vport_s *vport; + struct bfad_vport_s *vport; struct bfa_fcs_vport_s *fcs_vport; struct Scsi_Host *vshost; spin_lock_irqsave(&bfad->bfad_lock, flags); fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, port_cfg.pwwn); - if (fcs_vport == NULL) { - spin_unlock_irqrestore(&bfad->bfad_lock, flags); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + if (fcs_vport == NULL) return VPCERR_BAD_WWN; - } fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); if (disable) { + spin_lock_irqsave(&bfad->bfad_lock, flags); bfa_fcs_vport_stop(fcs_vport); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); } - spin_unlock_irqrestore(&bfad->bfad_lock, flags); vport = fcs_vport->vport_drv; vshost = vport->drv_port.im_port->shost; - fc_host_node_name(vshost) = wwn_to_u64((u8 *) &port_cfg.nwwn); - fc_host_port_name(vshost) = wwn_to_u64((u8 *) &port_cfg.pwwn); + fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn); + fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn); fc_vport->dd_data = vport; vport->drv_port.im_port->fc_vport = fc_vport; - } else if (rc == BFA_STATUS_INVALID_WWN) return VPCERR_BAD_WWN; else if (rc == BFA_STATUS_VPORT_EXISTS) @@ -422,7 +428,7 @@ bfad_im_vport_create(struct fc_vport *fc_vport, bool disable) return VPCERR_NO_FABRIC_SUPP; else if (rc == BFA_STATUS_VPORT_WWN_BP) return VPCERR_BAD_WWN; - else + else return FC_VPORT_FAILED; return status; @@ -449,7 +455,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport) port = im_port->port; vshost = vport->drv_port.im_port->shost; - pwwn = wwn_to_u64((u8 *) &fc_host_port_name(vshost)); + u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); spin_lock_irqsave(&bfad->bfad_lock, flags); fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); @@ -467,6 +473,9 @@ bfad_im_vport_delete(struct fc_vport *fc_vport) rc = bfa_fcs_vport_delete(&vport->fcs_vport); spin_unlock_irqrestore(&bfad->bfad_lock, flags); + if (rc == BFA_STATUS_PBC) + return -1; + wait_for_completion(vport->comp_del); free_scsi_host: @@ -490,7 +499,7 @@ bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable) vport = (struct bfad_vport_s *)fc_vport->dd_data; bfad = vport->drv_port.bfad; vshost = vport->drv_port.im_port->shost; - pwwn = wwn_to_u64((u8 *) &fc_vport->port_name); + u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); spin_lock_irqsave(&bfad->bfad_lock, flags); fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 6c920c1b53a4..2b58b29fe303 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -120,6 +120,8 @@ struct bfad_vport_s { struct bfad_port_s drv_port; struct bfa_fcs_vport_s fcs_vport; struct completion *comp_del; + struct list_head list_entry; + struct bfa_port_cfg_s port_cfg; }; /* @@ -195,6 +197,12 @@ struct bfad_s { bfa_boolean_t ipfc_enabled; union bfad_tmp_buf tmp_buf; struct fc_host_statistics link_stats; + struct list_head pbc_pcfg_list; +}; + +struct bfad_pcfg_s { + struct list_head list_entry; + struct bfa_port_cfg_s port_cfg; }; /* diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 5b7cf539e50b..0dff0d4b03c9 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -567,6 +567,7 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port, out_fc_rel: scsi_host_put(im_port->shost); + im_port->shost = NULL; out_free_idr: mutex_lock(&bfad_mutex); idr_remove(&bfad_im_port_index, im_port->idr_id); diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c index 8166e9745ec0..9315383fff8a 100644 --- a/drivers/scsi/bfa/fabric.c +++ b/drivers/scsi/bfa/fabric.c @@ -789,7 +789,7 @@ bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric) list_for_each_safe(qe, qen, &fabric->vport_q) { vport = (struct bfa_fcs_vport_s *)qe; - bfa_fcs_vport_delete(vport); + bfa_fcs_vport_fcs_delete(vport); } bfa_fcs_port_delete(&fabric->bport); diff --git a/drivers/scsi/bfa/fcs_vport.h b/drivers/scsi/bfa/fcs_vport.h index 13c32ebf946c..bb647a4a5dde 100644 --- a/drivers/scsi/bfa/fcs_vport.h +++ b/drivers/scsi/bfa/fcs_vport.h @@ -26,6 +26,7 @@ void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport); void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport); void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport); void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport); +void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport); #endif /* __FCS_VPORT_H__ */ diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_port.h b/drivers/scsi/bfa/include/defs/bfa_defs_port.h index 501bc9739d9d..752a81293d5a 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_port.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_port.h @@ -50,12 +50,12 @@ enum bfa_port_role { * FCS port configuration. */ struct bfa_port_cfg_s { - wwn_t pwwn; /* port wwn */ - wwn_t nwwn; /* node wwn */ - struct bfa_port_symname_s sym_name; /* vm port symbolic name */ - enum bfa_port_role roles; /* FCS port roles */ - u32 rsvd; - u8 tag[16]; /* opaque tag from application */ + wwn_t pwwn; /* port wwn */ + wwn_t nwwn; /* node wwn */ + struct bfa_port_symname_s sym_name; /* vm port symbolic name */ + bfa_boolean_t preboot_vp; /* vport created from PBC */ + enum bfa_port_role roles; /* FCS port roles */ + u8 tag[16]; /* opaque tag from application */ }; /** diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h index ec78b4cb121a..819db5abf461 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_status.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_status.h @@ -213,7 +213,8 @@ enum bfa_status { * loaded */ BFA_STATUS_CARD_TYPE_MISMATCH = 131, /* Card type mismatch */ BFA_STATUS_BAD_ASICBLK = 132, /* Bad ASIC block */ - BFA_STATUS_NO_DRIVER = 133, /* Brocade adapter/driver not installed or loaded */ + BFA_STATUS_NO_DRIVER = 133, /* Brocade adapter/driver not installed + * or loaded */ BFA_STATUS_INVALID_MAC = 134, /* Invalid mac address */ BFA_STATUS_IM_NO_VLAN = 135, /* No VLANs configured on the adapter */ BFA_STATUS_IM_ETH_LB_FAILED = 136, /* Ethernet loopback test failed */ @@ -249,6 +250,8 @@ enum bfa_status { BFA_STATUS_IM_TEAM_CFG_NOT_ALLOWED = 153, /* Given settings are not * allowed for the current * Teaming mode */ + BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot + * configuration */ BFA_STATUS_MAX_VAL /* Unknown error code */ }; #define bfa_status_t enum bfa_status diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h index a39f474c2fcf..cfd6ba7c47ec 100644 --- a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h +++ b/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h @@ -40,7 +40,8 @@ struct bfad_vport_s; * * @return None */ -void bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv); +void bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv); +void bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s); diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs.h b/drivers/scsi/bfa/include/fcs/bfa_fcs.h index f2fd35fdee28..54e5b81ab2a3 100644 --- a/drivers/scsi/bfa/include/fcs/bfa_fcs.h +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs.h @@ -61,8 +61,8 @@ struct bfa_fcs_s { /* * bfa fcs API functions */ -void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, - bfa_boolean_t min_cfg); +void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, + struct bfad_s *bfad, bfa_boolean_t min_cfg); void bfa_fcs_init(struct bfa_fcs_s *fcs); void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, struct bfa_fcs_driver_info_s *driver_info); diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h index cd33f2cd5c34..0af262430860 100644 --- a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h @@ -49,6 +49,10 @@ bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, u16 vf_id, struct bfa_port_cfg_s *port_cfg, struct bfad_vport_s *vport_drv); +bfa_status_t bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, + struct bfa_fcs_s *fcs, uint16_t vf_id, + struct bfa_port_cfg_s *port_cfg, + struct bfad_vport_s *vport_drv); bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport); bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport); bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport); diff --git a/drivers/scsi/bfa/vport.c b/drivers/scsi/bfa/vport.c index 27cd619a227a..f14e9f2d2c30 100644 --- a/drivers/scsi/bfa/vport.c +++ b/drivers/scsi/bfa/vport.c @@ -593,6 +593,15 @@ bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport) vport->vport_stats.fab_cleanup++; } +/** + * delete notification from fabric SM. To be invoked from within FCS. + */ +void +bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport) +{ + bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); +} + /** * Delete completion callback from associated lport */ @@ -646,6 +655,7 @@ bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, return BFA_STATUS_VPORT_MAX; vport->vport_drv = vport_drv; + vport_cfg->preboot_vp = BFA_FALSE; bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport); @@ -656,6 +666,36 @@ bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, return BFA_STATUS_OK; } +/** + * Use this function to instantiate a new FCS PBC vport object. This + * function will not trigger any HW initialization process (which will be + * done in vport_start() call) + * + * param[in] vport - pointer to bfa_fcs_vport_t. This space + * needs to be allocated by the driver. + * param[in] fcs - FCS instance + * param[in] vport_cfg - vport configuration + * param[in] vf_id - VF_ID if vport is created within a VF. + * FC_VF_ID_NULL to specify base fabric. + * param[in] vport_drv - Opaque handle back to the driver's vport + * structure + * + * retval BFA_STATUS_OK - on success. + * retval BFA_STATUS_FAILED - on failure. + */ +bfa_status_t +bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, + uint16_t vf_id, struct bfa_port_cfg_s *vport_cfg, + struct bfad_vport_s *vport_drv) +{ + bfa_status_t rc; + + rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv); + vport->lport.port_cfg.preboot_vp = BFA_TRUE; + + return rc; +} + /** * Use this function initialize the vport. * @@ -692,6 +732,8 @@ bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport) * Use this function to delete a vport object. Fabric object should * be stopped before this function call. * + * Donot invoke this from within FCS + * * param[in] vport - pointer to bfa_fcs_vport_t. * * return None @@ -699,6 +741,9 @@ bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport) bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport) { + if (vport->lport.port_cfg.preboot_vp) + return BFA_STATUS_PBC; + bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); return BFA_STATUS_OK; -- cgit v1.2.3 From 1769f990fc182695bc215ce4369688064addcd1e Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:47:08 -0700 Subject: [SCSI] bfa: vport state machine fix Vport state machine does not cleanup associated lport in some states: while waiting for fdisc response or fdisc failure state. The fixe is to cleanup lport on vport delete in all states. In fdisc state, discard fdisc response and delete lport and wait for lport deletecompletion. in error state, delete lport and wait for delete completion. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/vport.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/vport.c b/drivers/scsi/bfa/vport.c index f14e9f2d2c30..66f30a0d61e0 100644 --- a/drivers/scsi/bfa/vport.c +++ b/drivers/scsi/bfa/vport.c @@ -218,9 +218,9 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, switch (event) { case BFA_FCS_VPORT_SM_DELETE: - bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); + bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); bfa_lps_discard(vport->lps); - bfa_fcs_vport_do_logo(vport); + bfa_fcs_port_delete(&vport->lport); break; case BFA_FCS_VPORT_SM_OFFLINE: @@ -357,8 +357,9 @@ bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, switch (event) { case BFA_FCS_VPORT_SM_DELETE: - bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); - bfa_fcs_vport_free(vport); + bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); + bfa_fcs_port_delete(&vport->lport); + break; default: -- cgit v1.2.3 From 15b64a835def4c784c6e62ad762677f5cb56eba2 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:48:12 -0700 Subject: [SCSI] bfa: ioc attributes fix This patch fixes the APIs to obtain ioc attributes - fix API to obtain wwpn, wwnn, and mac. - add API to get mfg wwpn, wwnn, and mac. - fix API to obtain wwn of boot target. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcport.c | 3 ++ drivers/scsi/bfa/bfa_ioc.c | 58 +++++++++++++++++----------------- drivers/scsi/bfa/bfa_ioc.h | 3 ++ drivers/scsi/bfa/bfa_iocfc.c | 18 ++++++++--- drivers/scsi/bfa/bfa_iocfc.h | 2 +- drivers/scsi/bfa/bfad_im.c | 8 ++--- drivers/scsi/bfa/fabric.c | 16 ++++++++++ drivers/scsi/bfa/fcs_fabric.h | 2 ++ drivers/scsi/bfa/include/bfi/bfi_ioc.h | 19 +++++++---- drivers/scsi/bfa/ns.c | 4 +-- 10 files changed, 86 insertions(+), 47 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index 4961b8da9127..d28b721acaf8 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -1569,6 +1569,9 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr) attr->nwwn = fcport->nwwn; attr->pwwn = fcport->pwwn; + attr->factorypwwn = bfa_ioc_get_mfg_pwwn(&bfa->ioc); + attr->factorynwwn = bfa_ioc_get_mfg_nwwn(&bfa->ioc); + bfa_os_memcpy(&attr->pport_cfg, &fcport->cfg, sizeof(struct bfa_pport_cfg_s)); /* diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 268c071ce673..1600f747eb6c 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -1838,54 +1838,54 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr) } /** - * hal_wwn_public + * bfa_wwn_public */ wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc) { - union { - wwn_t wwn; - u8 byte[sizeof(wwn_t)]; - } - w; - - w.wwn = ioc->attr->mfg_wwn; - - if (bfa_ioc_portid(ioc) == 1) - w.byte[7]++; - - return w.wwn; + return ioc->attr->pwwn; } wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc) { - union { - wwn_t wwn; - u8 byte[sizeof(wwn_t)]; - } - w; - - w.wwn = ioc->attr->mfg_wwn; - - if (bfa_ioc_portid(ioc) == 1) - w.byte[7]++; - - w.byte[0] = 0x20; - - return w.wwn; + return ioc->attr->nwwn; } u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc) { - return ioc->attr->mfg_wwn; + return ioc->attr->mfg_pwwn; } mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc) { - mac_t mac; + /* + * Currently mfg mac is used as FCoE enode mac (not configured by PBC) + */ + if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE) + return bfa_ioc_get_mfg_mac(ioc); + else + return ioc->attr->mac; +} + +wwn_t +bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc) +{ + return ioc->attr->mfg_pwwn; +} + +wwn_t +bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc) +{ + return ioc->attr->mfg_nwwn; +} + +mac_t +bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc) +{ + mac_t mac; mac = ioc->attr->mfg_mac; mac.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc); diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index df15eccd760f..2425c00a72d3 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -304,6 +304,9 @@ bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc); wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc); mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc); +wwn_t bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc); +wwn_t bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc); +mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc); u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc); #endif /* __BFA_IOC_H__ */ diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c index d3f1052744d3..6f54bea356c6 100644 --- a/drivers/scsi/bfa/bfa_iocfc.c +++ b/drivers/scsi/bfa/bfa_iocfc.c @@ -861,13 +861,23 @@ bfa_iocfc_is_operational(struct bfa_s *bfa) * Return boot target port wwns -- read from boot information in flash. */ void -bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns) +bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns) { - struct bfa_iocfc_s *iocfc = &bfa->iocfc; - struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; + struct bfa_iocfc_s *iocfc = &bfa->iocfc; + struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; + int i; + + if (cfgrsp->pbc_cfg.boot_enabled && cfgrsp->pbc_cfg.nbluns) { + bfa_trc(bfa, cfgrsp->pbc_cfg.nbluns); + *nwwns = cfgrsp->pbc_cfg.nbluns; + for (i = 0; i < cfgrsp->pbc_cfg.nbluns; i++) + wwns[i] = cfgrsp->pbc_cfg.blun[i].tgt_pwwn; + + return; + } *nwwns = cfgrsp->bootwwns.nwwns; - *wwns = cfgrsp->bootwwns.wwn; + memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn)); } void diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h index a08309fb981d..2b281037fd79 100644 --- a/drivers/scsi/bfa/bfa_iocfc.h +++ b/drivers/scsi/bfa/bfa_iocfc.h @@ -167,7 +167,7 @@ void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len); void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi, bfa_boolean_t mincfg); -void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns); +void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns); void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg); int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 0dff0d4b03c9..943bc4b37284 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -1205,9 +1205,9 @@ int bfad_os_get_linkup_delay(struct bfad_s *bfad) { - u8 nwwns = 0; - wwn_t *wwns; - int ldelay; + u8 nwwns = 0; + wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX]; + int ldelay; /* * Querying for the boot target port wwns @@ -1216,7 +1216,7 @@ bfad_os_get_linkup_delay(struct bfad_s *bfad) * else => local boot machine set bfa_linkup_delay = 10 */ - bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, &wwns); + bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, wwns); if (nwwns > 0) { /* If boot over SAN; linkup_delay = 30sec */ diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c index 9315383fff8a..c646d6dd789b 100644 --- a/drivers/scsi/bfa/fabric.c +++ b/drivers/scsi/bfa/fabric.c @@ -1270,6 +1270,22 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, } +/** + * + * @param[in] fabric - fabric + * @param[in] node_symname - + * Caller allocated buffer to receive the symbolic name + * + * @return - none + */ +void +bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname) +{ + bfa_os_memcpy(node_symname, + fcs->fabric.bport.port_cfg.sym_name.symname, + BFA_SYMNAME_MAXLEN); +} + /** * Not used by FCS. */ diff --git a/drivers/scsi/bfa/fcs_fabric.h b/drivers/scsi/bfa/fcs_fabric.h index 244c3f00c50c..ed532db14e86 100644 --- a/drivers/scsi/bfa/fcs_fabric.h +++ b/drivers/scsi/bfa/fcs_fabric.h @@ -60,4 +60,6 @@ void bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, wwn_t fabric_name); +void bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname); + #endif /* __FCS_FABRIC_H__ */ diff --git a/drivers/scsi/bfa/include/bfi/bfi_ioc.h b/drivers/scsi/bfa/include/bfi/bfi_ioc.h index 03a9c9408ca5..7c5e6d5716df 100644 --- a/drivers/scsi/bfa/include/bfi/bfi_ioc.h +++ b/drivers/scsi/bfa/include/bfi/bfi_ioc.h @@ -48,9 +48,14 @@ struct bfi_ioc_getattr_req_s { }; struct bfi_ioc_attr_s { - wwn_t mfg_wwn; + wwn_t mfg_pwwn; /* Mfg port wwn */ + wwn_t mfg_nwwn; /* Mfg node wwn */ mac_t mfg_mac; - u16 rsvd_a; + u16 rsvd_a; + wwn_t pwwn; + wwn_t nwwn; + mac_t mac; /* PBC or Mfg mac */ + u16 rsvd_b; char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)]; u8 pcie_gen; u8 pcie_lanes_orig; @@ -58,12 +63,12 @@ struct bfi_ioc_attr_s { u8 rx_bbcredit; /* receive buffer credits */ u32 adapter_prop; /* adapter properties */ u16 maxfrsize; /* max receive frame size */ - char asic_rev; - u8 rsvd_b; - char fw_version[BFA_VERSION_LEN]; - char optrom_version[BFA_VERSION_LEN]; + char asic_rev; + u8 rsvd_c; + char fw_version[BFA_VERSION_LEN]; + char optrom_version[BFA_VERSION_LEN]; struct bfa_mfg_vpd_s vpd; - uint32_t card_type; /* card type */ + u32 card_type; /* card type */ }; /** diff --git a/drivers/scsi/bfa/ns.c b/drivers/scsi/bfa/ns.c index d20dd7e15742..2d6d2d6ff8dc 100644 --- a/drivers/scsi/bfa/ns.c +++ b/drivers/scsi/bfa/ns.c @@ -1228,10 +1228,10 @@ bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port) struct bfa_fcs_rport_s *rport; u8 nwwns; - wwn_t *wwns; + wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX]; int ii; - bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, &wwns); + bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns); for (ii = 0; ii < nwwns; ++ii) { rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]); -- cgit v1.2.3 From b85d045ee866011df535565bf12d684e8e5b7a9d Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:48:49 -0700 Subject: [SCSI] bfa: statistics and typo fix - Added time stamp for fcport stats reset - Added new fileds to the statistics data structures. - Typo removal and minor cleanup. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcpim_priv.h | 1 + drivers/scsi/bfa/bfa_fcport.c | 25 +++++++++++++++++++++-- drivers/scsi/bfa/bfa_port.c | 27 +++++++++++++++++++++++-- drivers/scsi/bfa/bfa_port_priv.h | 3 ++- drivers/scsi/bfa/bfad_drv.h | 13 ------------ drivers/scsi/bfa/fcpim.c | 1 + drivers/scsi/bfa/include/bfa.h | 2 ++ drivers/scsi/bfa/include/cna/port/bfa_port.h | 1 + drivers/scsi/bfa/include/defs/bfa_defs_auth.h | 6 +++--- drivers/scsi/bfa/include/defs/bfa_defs_fcport.h | 26 +++++++++--------------- drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h | 12 +++++++---- drivers/scsi/bfa/include/defs/bfa_defs_itnim.h | 10 +++++++++ drivers/scsi/bfa/include/defs/bfa_defs_port.h | 2 +- drivers/scsi/bfa/include/defs/bfa_defs_pport.h | 4 ++-- drivers/scsi/bfa/include/defs/bfa_defs_status.h | 24 ++++++++++++---------- drivers/scsi/bfa/ms.c | 3 +++ 16 files changed, 105 insertions(+), 55 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcpim_priv.h b/drivers/scsi/bfa/bfa_fcpim_priv.h index 5cf418460f75..3db39da72427 100644 --- a/drivers/scsi/bfa/bfa_fcpim_priv.h +++ b/drivers/scsi/bfa/bfa_fcpim_priv.h @@ -141,6 +141,7 @@ struct bfa_itnim_s { struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ struct bfa_fcpim_mod_s *fcpim; /* fcpim module */ struct bfa_itnim_hal_stats_s stats; + struct bfa_itnim_latency_s io_latency; }; #define bfa_itnim_is_online(_itnim) ((_itnim)->is_online) diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index d28b721acaf8..18d33072bec5 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -888,6 +888,7 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); struct bfa_pport_cfg_s *port_cfg = &fcport->cfg; struct bfa_fcport_ln_s *ln = &fcport->ln; + struct bfa_timeval_s tv; bfa_os_memset(fcport, 0, sizeof(struct bfa_fcport_s)); fcport->bfa = bfa; @@ -898,6 +899,12 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa_sm_set_state(fcport, bfa_fcport_sm_uninit); bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn); + /** + * initialize time stamp for stats reset + */ + bfa_os_gettimeofday(&tv); + fcport->stats_reset_time = tv.tv_sec; + /** * initialize and set default configuration */ @@ -1126,16 +1133,22 @@ __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete) if (complete) { if (fcport->stats_status == BFA_STATUS_OK) { + struct bfa_timeval_s tv; /* Swap FC QoS or FCoE stats */ - if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) + if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) { bfa_fcport_qos_stats_swap( &fcport->stats_ret->fcqos, &fcport->stats->fcqos); - else + } else { bfa_fcport_fcoe_stats_swap( &fcport->stats_ret->fcoe, &fcport->stats->fcoe); + + bfa_os_gettimeofday(&tv); + fcport->stats_ret->fcoe.secs_reset = + tv.tv_sec - fcport->stats_reset_time; + } } fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); } else { @@ -1191,6 +1204,14 @@ __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete) struct bfa_fcport_s *fcport = cbarg; if (complete) { + struct bfa_timeval_s tv; + + /** + * re-initialize time stamp for stats reset + */ + bfa_os_gettimeofday(&tv); + fcport->stats_reset_time = tv.tv_sec; + fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); } else { fcport->stats_busy = BFA_FALSE; diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index cab19028361a..6773e2282ddc 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -102,9 +102,14 @@ bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status) port->stats_busy = BFA_FALSE; if (status == BFA_STATUS_OK) { + struct bfa_timeval_s tv; + memcpy(port->stats, port->stats_dma.kva, sizeof(union bfa_pport_stats_u)); bfa_port_stats_swap(port, port->stats); + + bfa_os_gettimeofday(&tv); + port->stats->fc.secs_reset = tv.tv_sec - port->stats_reset_time; } if (port->stats_cbfn) { @@ -125,9 +130,17 @@ bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status) static void bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status) { + struct bfa_timeval_s tv; + port->stats_status = status; port->stats_busy = BFA_FALSE; + /** + * re-initialize time stamp for stats reset + */ + bfa_os_gettimeofday(&tv); + port->stats_reset_time = tv.tv_sec; + if (port->stats_cbfn) { port->stats_cbfn(port->stats_cbarg, status); port->stats_cbfn = NULL; @@ -428,6 +441,8 @@ void bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev, struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod) { + struct bfa_timeval_s tv; + bfa_assert(port); port->dev = dev; @@ -435,13 +450,21 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev, port->trcmod = trcmod; port->logmod = logmod; - port->stats_busy = port->endis_pending = BFA_FALSE; - port->stats_cbfn = port->endis_cbfn = NULL; + port->stats_busy = BFA_FALSE; + port->endis_pending = BFA_FALSE; + port->stats_cbfn = NULL; + port->endis_cbfn = NULL; bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port); bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port); bfa_ioc_hbfail_register(port->ioc, &port->hbfail); + /** + * initialize time stamp for stats reset + */ + bfa_os_gettimeofday(&tv); + port->stats_reset_time = tv.tv_sec; + bfa_trc(port, 0); } diff --git a/drivers/scsi/bfa/bfa_port_priv.h b/drivers/scsi/bfa/bfa_port_priv.h index c52fe56df0bd..c9ebe0426fa6 100644 --- a/drivers/scsi/bfa/bfa_port_priv.h +++ b/drivers/scsi/bfa/bfa_port_priv.h @@ -75,8 +75,9 @@ struct bfa_fcport_s { bfa_status_t stats_status; /* stats/statsclr status */ bfa_boolean_t stats_busy; /* outstanding stats/statsclr */ bfa_boolean_t stats_qfull; + u32 stats_reset_time; /* stats reset time stamp */ bfa_cb_pport_t stats_cbfn; /* driver callback function */ - void *stats_cbarg; /* *!< user callback arg */ + void *stats_cbarg; /* user callback arg */ bfa_boolean_t diag_busy; /* diag busy status */ bfa_boolean_t beacon; /* port beacon status */ bfa_boolean_t link_e2e_beacon; /* link beacon status */ diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 2b58b29fe303..8629f64a5287 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -141,18 +141,6 @@ struct bfad_cfg_param_s { u32 binding_method; }; -union bfad_tmp_buf { - /* From struct bfa_adapter_attr_s */ - char manufacturer[BFA_ADAPTER_MFG_NAME_LEN]; - char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; - char model[BFA_ADAPTER_MODEL_NAME_LEN]; - char fw_ver[BFA_VERSION_LEN]; - char optrom_ver[BFA_VERSION_LEN]; - - /* From struct bfa_ioc_pci_attr_s */ - u8 chip_rev[BFA_IOC_CHIP_REV_LEN]; /* chip revision */ -}; - /* * BFAD (PCI function) data structure */ @@ -195,7 +183,6 @@ struct bfad_s { struct bfa_plog_s plog_buf; int ref_count; bfa_boolean_t ipfc_enabled; - union bfad_tmp_buf tmp_buf; struct fc_host_statistics link_stats; struct list_head pbc_pcfg_list; }; diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/fcpim.c index 8ae4a2cfa85b..412018196bd2 100644 --- a/drivers/scsi/bfa/fcpim.c +++ b/drivers/scsi/bfa/fcpim.c @@ -738,6 +738,7 @@ bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn, attr->rec_support = itnim->rec_support; attr->conf_comp = itnim->conf_comp; attr->task_retry_id = itnim->task_retry_id; + bfa_os_memset(&attr->io_latency, 0, sizeof(struct bfa_itnim_latency_s)); return BFA_STATUS_OK; } diff --git a/drivers/scsi/bfa/include/bfa.h b/drivers/scsi/bfa/include/bfa.h index 1f5966cfbd16..9519a6d81045 100644 --- a/drivers/scsi/bfa/include/bfa.h +++ b/drivers/scsi/bfa/include/bfa.h @@ -126,6 +126,8 @@ struct bfa_sge_s { bfa_ioc_get_type(&(__bfa)->ioc) #define bfa_get_mac(__bfa) \ bfa_ioc_get_mac(&(__bfa)->ioc) +#define bfa_get_fw_clock_res(__bfa) \ + ((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res) /* * bfa API functions diff --git a/drivers/scsi/bfa/include/cna/port/bfa_port.h b/drivers/scsi/bfa/include/cna/port/bfa_port.h index 7cbf17d3141b..d7babaf97848 100644 --- a/drivers/scsi/bfa/include/cna/port/bfa_port.h +++ b/drivers/scsi/bfa/include/cna/port/bfa_port.h @@ -37,6 +37,7 @@ struct bfa_port_s { bfa_port_stats_cbfn_t stats_cbfn; void *stats_cbarg; bfa_status_t stats_status; + u32 stats_reset_time; union bfa_pport_stats_u *stats; struct bfa_dma_s stats_dma; bfa_boolean_t endis_pending; diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h b/drivers/scsi/bfa/include/defs/bfa_defs_auth.h index 45df32820911..f56ed871bb99 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_auth.h @@ -125,10 +125,10 @@ struct bfa_auth_attr_s { enum bfa_auth_status status; enum bfa_auth_algo algo; enum bfa_auth_group dh_grp; - u16 rjt_code; - u16 rjt_code_exp; + enum bfa_auth_rej_code rjt_code; + enum bfa_auth_rej_code_exp rjt_code_exp; u8 secret_set; - u8 resv[7]; + u8 resv[3]; }; #endif /* __BFA_DEFS_AUTH_H__ */ diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h index a07ef4a3cd78..af86a6396439 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h @@ -48,7 +48,7 @@ struct bfa_fcoe_stats_s { u64 disc_fcf_unavail; /* Discovery FCF not avail */ u64 linksvc_unsupp; /* FIP link service req unsupp. */ u64 linksvc_err; /* FIP link service req errors */ - u64 logo_req; /* FIP logo */ + u64 logo_req; /* FIP logos received */ u64 clrvlink_req; /* Clear virtual link requests */ u64 op_unsupp; /* FIP operation unsupp. */ u64 untagged; /* FIP untagged frames */ @@ -64,21 +64,15 @@ struct bfa_fcoe_stats_s { u64 txf_timeout; /* Tx timeouts */ u64 txf_parity_errors; /* Transmit parity err */ u64 txf_fid_parity_errors; /* Transmit FID parity err */ - u64 tx_pause; /* Tx pause frames */ - u64 tx_zero_pause; /* Tx zero pause frames */ - u64 tx_first_pause; /* Tx first pause frames */ - u64 rx_pause; /* Rx pause frames */ - u64 rx_zero_pause; /* Rx zero pause frames */ - u64 rx_first_pause; /* Rx first pause frames */ - u64 rxf_ucast_octets; /* Rx unicast octets */ - u64 rxf_ucast; /* Rx unicast frames */ - u64 rxf_ucast_vlan; /* Rx unicast vlan frames */ - u64 rxf_mcast_octets; /* Rx multicast octets */ - u64 rxf_mcast; /* Rx multicast frames */ - u64 rxf_mcast_vlan; /* Rx multicast vlan frames */ - u64 rxf_bcast_octets; /* Rx broadcast octests */ - u64 rxf_bcast; /* Rx broadcast frames */ - u64 rxf_bcast_vlan; /* Rx broadcast vlan frames */ + u64 rxf_ucast_octets; /* Rx FCoE unicast octets */ + u64 rxf_ucast; /* Rx FCoE unicast frames */ + u64 rxf_ucast_vlan; /* Rx FCoE unicast vlan frames */ + u64 rxf_mcast_octets; /* Rx FCoE multicast octets */ + u64 rxf_mcast; /* Rx FCoE multicast frames */ + u64 rxf_mcast_vlan; /* Rx FCoE multicast vlan frames */ + u64 rxf_bcast_octets; /* Rx FCoE broadcast octets */ + u64 rxf_bcast; /* Rx FCoE broadcast frames */ + u64 rxf_bcast_vlan; /* Rx FCoE broadcast vlan frames */ }; /** diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h index c290fb13d2d1..31e728a631ed 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h @@ -51,8 +51,10 @@ struct bfa_iocfc_fwcfg_s { u16 num_tsktm_reqs; /* TM task management requests*/ u16 num_fcxp_reqs; /* unassisted FC exchanges */ u16 num_uf_bufs; /* unsolicited recv buffers */ - u8 num_cqs; - u8 rsvd[5]; + u8 num_cqs; + u8 fw_tick_res; /*!< FW clock resolution in ms */ + u8 rsvd[4]; + }; struct bfa_iocfc_drvcfg_s { @@ -176,10 +178,10 @@ struct bfa_fw_port_fpg_stats_s { u32 nos_rx; u32 lip_rx; u32 arbf0_rx; + u32 arb_rx; u32 mrk_rx; u32 const_mrk_rx; u32 prim_unknown; - u32 rsvd; }; @@ -200,6 +202,8 @@ struct bfa_fw_port_lksm_stats_s { u32 lrr_tx; /* No. of times LRR tx started */ u32 ols_tx; /* No. of times OLS tx started */ u32 nos_tx; /* No. of times NOS tx started */ + u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */ + u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */ }; @@ -239,7 +243,7 @@ struct bfa_fw_fip_stats_s { u32 disc_fcf_unavail; /* Discovery FCF Not Avail. */ u32 linksvc_unsupp; /* Unsupported link service req */ u32 linksvc_err; /* Parse error in link service req */ - u32 logo_req; /* Number of FIP logos received */ + u32 logo_req; /* FIP logos received */ u32 clrvlink_req; /* Clear virtual link req */ u32 op_unsupp; /* Unsupported FIP operation */ u32 untagged; /* Untagged frames (ignored) */ diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h b/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h index 2ec769903d24..d77788b3999a 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h @@ -34,6 +34,15 @@ enum bfa_itnim_state { BFA_ITNIM_INITIATIOR = 7, /* initiator */ }; +struct bfa_itnim_latency_s { + u32 min; + u32 max; + u32 count; + u32 clock_res; + u32 avg; + u32 rsvd; +}; + struct bfa_itnim_hal_stats_s { u32 onlines; /* ITN nexus onlines (PRLI done) */ u32 offlines; /* ITN Nexus offlines */ @@ -91,6 +100,7 @@ struct bfa_itnim_attr_s { u8 task_retry_id; /* task retry ident support */ u8 rec_support; /* REC supported */ u8 conf_comp; /* confirmed completion supp */ + struct bfa_itnim_latency_s io_latency; /* IO latency */ }; /** diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_port.h b/drivers/scsi/bfa/include/defs/bfa_defs_port.h index 752a81293d5a..ebdf0d1731a4 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_port.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_port.h @@ -159,7 +159,7 @@ struct bfa_port_stats_s { u32 ms_plogi_rsp_err; u32 ms_plogi_acc_err; u32 ms_plogi_accepts; - u32 ms_rejects; /* NS command rejects */ + u32 ms_rejects; /* MS command rejects */ u32 ms_plogi_unknown_rsp; u32 ms_plogi_alloc_wait; diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h index de6181cf9677..2c2cec5ee278 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h @@ -246,7 +246,7 @@ struct bfa_pport_fc_stats_s { u64 secs_reset; /* Seconds since stats is reset */ u64 tx_frames; /* Tx frames */ u64 tx_words; /* Tx words */ - u64 tx_lip; /* TX LIP */ + u64 tx_lip; /* Tx LIP */ u64 tx_nos; /* Tx NOS */ u64 tx_ols; /* Tx OLS */ u64 tx_lr; /* Tx LR */ @@ -312,7 +312,7 @@ struct bfa_pport_eth_stats_s { u64 rx_zero_pause; /* Rx zero pause */ u64 tx_pause; /* Tx pause */ u64 tx_zero_pause; /* Tx zero pause */ - u64 rx_fcoe_pause; /* Rx fcoe pause */ + u64 rx_fcoe_pause; /* Rx FCoE pause */ u64 rx_fcoe_zero_pause; /* Rx FCoE zero pause */ u64 tx_fcoe_pause; /* Tx FCoE pause */ u64 tx_fcoe_zero_pause; /* Tx FCoE zero pause */ diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h index 819db5abf461..7cef900707c5 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_status.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_status.h @@ -84,8 +84,9 @@ enum bfa_status { BFA_STATUS_BADFRMHDR = 48, /* Bad frame header */ BFA_STATUS_BADFRMSZ = 49, /* Bad frame size check and replace * SFP/cable */ - BFA_STATUS_MISSINGFRM = 50, /* Missing frame check and replace - * SFP/cable */ + BFA_STATUS_MISSINGFRM = 50, /* Missing frame check and replace + * SFP/cable or for Mezz card check and + * replace pass through module */ BFA_STATUS_LINKTIMEOUT = 51, /* Link timeout check and replace * SFP/cable */ BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the @@ -173,7 +174,7 @@ enum bfa_status { BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */ BFA_STATUS_CEE_NOT_DN = 110, /* eth port is not at down state, please * bring down first */ - BFA_STATUS_10G_SPD = 111, /* Speed setting not valid for 10G HBA */ + BFA_STATUS_10G_SPD = 111, /* Speed setting not valid for 10G CNA */ BFA_STATUS_IM_INV_TEAM_NAME = 112, /* Invalid team name */ BFA_STATUS_IM_DUP_TEAM_NAME = 113, /* Given team name already * exists */ @@ -215,11 +216,11 @@ enum bfa_status { BFA_STATUS_BAD_ASICBLK = 132, /* Bad ASIC block */ BFA_STATUS_NO_DRIVER = 133, /* Brocade adapter/driver not installed * or loaded */ - BFA_STATUS_INVALID_MAC = 134, /* Invalid mac address */ + BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */ BFA_STATUS_IM_NO_VLAN = 135, /* No VLANs configured on the adapter */ BFA_STATUS_IM_ETH_LB_FAILED = 136, /* Ethernet loopback test failed */ - BFA_STATUS_IM_PVID_REMOVE = 137, /* Cannot remove port vlan (PVID) */ - BFA_STATUS_IM_PVID_EDIT = 138, /* Cannot edit port vlan (PVID) */ + BFA_STATUS_IM_PVID_REMOVE = 137, /* Cannot remove port VLAN (PVID) */ + BFA_STATUS_IM_PVID_EDIT = 138, /* Cannot edit port VLAN (PVID) */ BFA_STATUS_CNA_NO_BOOT = 139, /* Boot upload not allowed for CNA */ BFA_STATUS_IM_PVID_NON_ZERO = 140, /* Port VLAN ID (PVID) is Set to * Non-Zero Value */ @@ -233,14 +234,15 @@ enum bfa_status { BFA_STATUS_INSUFFICIENT_PERMS = 144, /* User doesn't have sufficient * permissions to execute the BCU * application */ - BFA_STATUS_IM_INV_VLAN_NAME = 145, /* Invalid/Reserved Vlan name + BFA_STATUS_IM_INV_VLAN_NAME = 145, /* Invalid/Reserved VLAN name * string. The name is not allowed - * for the normal Vlans */ + * for the normal VLAN */ BFA_STATUS_CMD_NOTSUPP_CNA = 146, /* Command not supported for CNA */ - BFA_STATUS_IM_PASSTHRU_EDIT = 147, /* Can not edit passthru vlan id */ - BFA_STATUS_IM_BIND_FAILED = 148, /*! < IM Driver bind operation + BFA_STATUS_IM_PASSTHRU_EDIT = 147, /* Can not edit passthrough VLAN + * id */ + BFA_STATUS_IM_BIND_FAILED = 148, /* IM Driver bind operation * failed */ - BFA_STATUS_IM_UNBIND_FAILED = 149, /* ! < IM Driver unbind operation + BFA_STATUS_IM_UNBIND_FAILED = 149, /* IM Driver unbind operation * failed */ BFA_STATUS_IM_PORT_IN_TEAM = 150, /* Port is already part of the * team */ diff --git a/drivers/scsi/bfa/ms.c b/drivers/scsi/bfa/ms.c index 5e8c8dee6c97..e776bcb49604 100644 --- a/drivers/scsi/bfa/ms.c +++ b/drivers/scsi/bfa/ms.c @@ -157,6 +157,7 @@ bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event) * Start timer for a delayed retry */ bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry); + ms->port->stats.ms_retries++; bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer, bfa_fcs_port_ms_timeout, ms, BFA_FCS_RETRY_TIMEOUT); @@ -279,6 +280,7 @@ bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event) */ if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry); + ms->port->stats.ms_retries++; bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer, bfa_fcs_port_ms_timeout, ms, BFA_FCS_RETRY_TIMEOUT); @@ -479,6 +481,7 @@ bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event) */ if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry); + ms->port->stats.ms_retries++; bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer, bfa_fcs_port_ms_timeout, ms, BFA_FCS_RETRY_TIMEOUT); -- cgit v1.2.3 From 4f1806bc3c409395de4dab5984f7a235dc4a0eda Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:50:15 -0700 Subject: [SCSI] bfa: use standards defined timeout for ELS/CT Use standards defined 2 * RA_TOV as a timeout for ELS Request retries. And standards defined 3 * RA_TOV as a timeout for FC-CT Request retries. Also, added a check to send RPSC2 to a Brocade Fabric only. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/fabric.c | 26 ++++++++++++++++++++++++++ drivers/scsi/bfa/fcpim.c | 2 +- drivers/scsi/bfa/fcs_fabric.h | 3 +++ drivers/scsi/bfa/fdmi.c | 6 +++--- drivers/scsi/bfa/include/protocol/fc.h | 1 + drivers/scsi/bfa/ms.c | 6 +++--- drivers/scsi/bfa/ns.c | 10 +++++----- drivers/scsi/bfa/rport.c | 8 ++++---- drivers/scsi/bfa/rport_ftrs.c | 13 +++++++++---- drivers/scsi/bfa/scn.c | 2 +- 10 files changed, 56 insertions(+), 21 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c index c646d6dd789b..ddd4ba9317e6 100644 --- a/drivers/scsi/bfa/fabric.c +++ b/drivers/scsi/bfa/fabric.c @@ -1027,6 +1027,32 @@ bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric) return fabric->num_vports; } +/* + * Get OUI of the attached switch. + * + * Note : Use of this function should be avoided as much as possible. + * This function should be used only if there is any requirement + * to check for FOS version below 6.3. + * To check if the attached fabric is a brocade fabric, use + * bfa_lps_is_brcd_fabric() which works for FOS versions 6.3 + * or above only. + */ + +u16 +bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric) +{ + wwn_t fab_nwwn; + u8 *tmp; + u16 oui; + + fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps); + + tmp = (uint8_t *)&fab_nwwn; + oui = (tmp[3] << 8) | tmp[4]; + + return oui; +} + /** * Unsolicited frame receive handling. */ diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/fcpim.c index 412018196bd2..7a0207e56693 100644 --- a/drivers/scsi/bfa/fcpim.c +++ b/drivers/scsi/bfa/fcpim.c @@ -422,7 +422,7 @@ bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_itnim_prli_response, (void *)itnim, FC_MAX_PDUSZ, - FC_RA_TOV); + FC_ELS_TOV); itnim->stats.prli_sent++; bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT); diff --git a/drivers/scsi/bfa/fcs_fabric.h b/drivers/scsi/bfa/fcs_fabric.h index ed532db14e86..432ab8ab8c3c 100644 --- a/drivers/scsi/bfa/fcs_fabric.h +++ b/drivers/scsi/bfa/fcs_fabric.h @@ -26,6 +26,8 @@ #include #include +#define BFA_FCS_BRCD_SWITCH_OUI 0x051e + /* * fcs friend functions: only between fcs modules */ @@ -60,6 +62,7 @@ void bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, wwn_t fabric_name); +u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname); #endif /* __FCS_FABRIC_H__ */ diff --git a/drivers/scsi/bfa/fdmi.c b/drivers/scsi/bfa/fdmi.c index 8f17076d1a87..2b50eabf4b1e 100644 --- a/drivers/scsi/bfa/fdmi.c +++ b/drivers/scsi/bfa/fdmi.c @@ -532,7 +532,7 @@ bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, (len + attr_len), &fchs, bfa_fcs_port_fdmi_rhba_response, (void *)fdmi, - FC_MAX_PDUSZ, FC_RA_TOV); + FC_MAX_PDUSZ, FC_FCCT_TOV); bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT); } @@ -823,7 +823,7 @@ bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len + attr_len, &fchs, bfa_fcs_port_fdmi_rprt_response, (void *)fdmi, - FC_MAX_PDUSZ, FC_RA_TOV); + FC_MAX_PDUSZ, FC_FCCT_TOV); bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT); } @@ -1043,7 +1043,7 @@ bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len + attr_len, &fchs, bfa_fcs_port_fdmi_rpa_response, (void *)fdmi, - FC_MAX_PDUSZ, FC_RA_TOV); + FC_MAX_PDUSZ, FC_FCCT_TOV); bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT); } diff --git a/drivers/scsi/bfa/include/protocol/fc.h b/drivers/scsi/bfa/include/protocol/fc.h index 8d1038035a76..436dd7c5643a 100644 --- a/drivers/scsi/bfa/include/protocol/fc.h +++ b/drivers/scsi/bfa/include/protocol/fc.h @@ -1080,6 +1080,7 @@ struct fc_alpabm_s{ #define FC_REC_TOV (FC_ED_TOV + 1) #define FC_RA_TOV 10 #define FC_ELS_TOV (2 * FC_RA_TOV) +#define FC_FCCT_TOV (3 * FC_RA_TOV) /* * virtual fabric related defines diff --git a/drivers/scsi/bfa/ms.c b/drivers/scsi/bfa/ms.c index e776bcb49604..1d579ef26122 100644 --- a/drivers/scsi/bfa/ms.c +++ b/drivers/scsi/bfa/ms.c @@ -361,7 +361,7 @@ bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response, - (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV); bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); } @@ -560,7 +560,7 @@ bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response, - (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV); bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); } @@ -640,7 +640,7 @@ bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response, - (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)ms, FC_MAX_PDUSZ, FC_ELS_TOV); port->stats.ms_plogi_sent++; bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); diff --git a/drivers/scsi/bfa/ns.c b/drivers/scsi/bfa/ns.c index 2d6d2d6ff8dc..ae0edcc86ed5 100644 --- a/drivers/scsi/bfa/ns.c +++ b/drivers/scsi/bfa/ns.c @@ -664,7 +664,7 @@ bfa_fcs_port_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_plogi_response, - (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)ns, FC_MAX_PDUSZ, FC_ELS_TOV); port->stats.ns_plogi_sent++; bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT); @@ -791,7 +791,7 @@ bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rspn_id_response, - (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV); port->stats.ns_rspnid_sent++; @@ -865,7 +865,7 @@ bfa_fcs_port_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rft_id_response, - (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV); port->stats.ns_rftid_sent++; bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT); @@ -943,7 +943,7 @@ bfa_fcs_port_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rff_id_response, - (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV); port->stats.ns_rffid_sent++; bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT); @@ -1029,7 +1029,7 @@ bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_gid_ft_response, (void *)ns, bfa_fcxp_get_maxrsp(port->fcs->bfa), - FC_RA_TOV); + FC_FCCT_TOV); port->stats.ns_gidft_sent++; diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/rport.c index 7b096f2e3836..2796403222e1 100644 --- a/drivers/scsi/bfa/rport.c +++ b/drivers/scsi/bfa/rport.c @@ -1378,7 +1378,7 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response, - (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV); rport->stats.plogis++; bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); @@ -1519,7 +1519,7 @@ bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response, - rport, FC_MAX_PDUSZ, FC_RA_TOV); + rport, FC_MAX_PDUSZ, FC_ELS_TOV); rport->stats.adisc_sent++; bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); @@ -1580,7 +1580,7 @@ bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response, - (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV); bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); } @@ -1692,7 +1692,7 @@ bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ, - FC_ED_TOV); + FC_ELS_TOV); rport->stats.logos++; bfa_fcxp_discard(rport->fcxp); diff --git a/drivers/scsi/bfa/rport_ftrs.c b/drivers/scsi/bfa/rport_ftrs.c index ae7bba67ae2a..acecab83f82f 100644 --- a/drivers/scsi/bfa/rport_ftrs.c +++ b/drivers/scsi/bfa/rport_ftrs.c @@ -73,6 +73,7 @@ static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) { struct bfa_fcs_rport_s *rport = rpf->rport; + struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric; bfa_trc(rport->fcs, rport->pwwn); bfa_trc(rport->fcs, rport->pid); @@ -80,12 +81,16 @@ bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) switch (event) { case RPFSM_EVENT_RPORT_ONLINE: - if (!BFA_FCS_PID_IS_WKA(rport->pid)) { + /* Send RPSC2 to a Brocade fabric only. */ + if ((!BFA_FCS_PID_IS_WKA(rport->pid)) && + ((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) || + (bfa_fcs_fabric_get_switch_oui(fabric) == + BFA_FCS_BRCD_SWITCH_OUI))) { bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); rpf->rpsc_retries = 0; bfa_fcs_rpf_send_rpsc2(rpf, NULL); - break; - }; + } + break; case RPFSM_EVENT_RPORT_OFFLINE: break; @@ -307,7 +312,7 @@ bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response, - rpf, FC_MAX_PDUSZ, FC_RA_TOV); + rpf, FC_MAX_PDUSZ, FC_ELS_TOV); rport->stats.rpsc_sent++; bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT); diff --git a/drivers/scsi/bfa/scn.c b/drivers/scsi/bfa/scn.c index 8fe09ba88a91..8a60129e6307 100644 --- a/drivers/scsi/bfa/scn.c +++ b/drivers/scsi/bfa/scn.c @@ -218,7 +218,7 @@ bfa_fcs_port_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced) bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, bfa_fcs_port_scn_scr_response, - (void *)scn, FC_MAX_PDUSZ, FC_RA_TOV); + (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV); bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT); } -- cgit v1.2.3 From 7c8146510c9cacdaaeb273b5fef6b9201d933bc1 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:50:38 -0700 Subject: [SCSI] bfa: fix interrupt coalescing setting Do not update the coalesce flag of the intr_attr struct in driver config area on config response. This is to prevent the coalesce flag being reported as on after an ioc disable/enable even if it was set to off before disable. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_iocfc.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c index 6f54bea356c6..0776d74d40de 100644 --- a/drivers/scsi/bfa/bfa_iocfc.c +++ b/drivers/scsi/bfa/bfa_iocfc.c @@ -113,7 +113,6 @@ bfa_iocfc_send_cfg(void *bfa_arg) bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS); bfa_trc(bfa, cfg->fwcfg.num_cqs); - iocfc->cfgdone = BFA_FALSE; bfa_iocfc_reset_queues(bfa); /** @@ -144,6 +143,15 @@ bfa_iocfc_send_cfg(void *bfa_arg) bfa_os_htons(cfg->drvcfg.num_rspq_elems); } + /** + * Enable interrupt coalescing if it is driver init path + * and not ioc disable/enable path. + */ + if (!iocfc->cfgdone) + cfg_info->intr_attr.coalesce = BFA_TRUE; + + iocfc->cfgdone = BFA_FALSE; + /** * dma map IOC configuration itself */ @@ -364,7 +372,6 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa) struct bfa_iocfc_s *iocfc = &bfa->iocfc; struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; struct bfa_iocfc_fwcfg_s *fwcfg = &cfgrsp->fwcfg; - struct bfi_iocfc_cfg_s *cfginfo = iocfc->cfginfo; fwcfg->num_cqs = fwcfg->num_cqs; fwcfg->num_ioim_reqs = bfa_os_ntohs(fwcfg->num_ioim_reqs); @@ -373,10 +380,6 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa) fwcfg->num_uf_bufs = bfa_os_ntohs(fwcfg->num_uf_bufs); fwcfg->num_rports = bfa_os_ntohs(fwcfg->num_rports); - cfginfo->intr_attr.coalesce = cfgrsp->intr_attr.coalesce; - cfginfo->intr_attr.delay = bfa_os_ntohs(cfgrsp->intr_attr.delay); - cfginfo->intr_attr.latency = bfa_os_ntohs(cfgrsp->intr_attr.latency); - iocfc->cfgdone = BFA_TRUE; /** @@ -737,10 +740,20 @@ bfa_adapter_get_id(struct bfa_s *bfa) void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr) { - struct bfa_iocfc_s *iocfc = &bfa->iocfc; + struct bfa_iocfc_s *iocfc = &bfa->iocfc; + + attr->intr_attr.coalesce = iocfc->cfginfo->intr_attr.coalesce; + + attr->intr_attr.delay = iocfc->cfginfo->intr_attr.delay ? + bfa_os_ntohs(iocfc->cfginfo->intr_attr.delay) : + bfa_os_ntohs(iocfc->cfgrsp->intr_attr.delay); + + attr->intr_attr.latency = iocfc->cfginfo->intr_attr.latency ? + bfa_os_ntohs(iocfc->cfginfo->intr_attr.latency) : + bfa_os_ntohs(iocfc->cfgrsp->intr_attr.latency); + + attr->config = iocfc->cfg; - attr->intr_attr = iocfc->cfginfo->intr_attr; - attr->config = iocfc->cfg; } bfa_status_t @@ -749,7 +762,10 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr) struct bfa_iocfc_s *iocfc = &bfa->iocfc; struct bfi_iocfc_set_intr_req_s *m; - iocfc->cfginfo->intr_attr = *attr; + iocfc->cfginfo->intr_attr.coalesce = attr->coalesce; + iocfc->cfginfo->intr_attr.delay = bfa_os_htons(attr->delay); + iocfc->cfginfo->intr_attr.latency = bfa_os_htons(attr->latency); + if (!bfa_iocfc_is_operational(bfa)) return BFA_STATUS_OK; @@ -759,9 +775,10 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr) bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ, bfa_lpuid(bfa)); - m->coalesce = attr->coalesce; - m->delay = bfa_os_htons(attr->delay); - m->latency = bfa_os_htons(attr->latency); + m->coalesce = iocfc->cfginfo->intr_attr.coalesce; + m->delay = iocfc->cfginfo->intr_attr.delay; + m->latency = iocfc->cfginfo->intr_attr.latency; + bfa_trc(bfa, attr->delay); bfa_trc(bfa, attr->latency); -- cgit v1.2.3 From c507341713114e2510ad7621088b359367adf1ce Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:51:28 -0700 Subject: [SCSI] bfa: fix rport speed setting When a rport goes offline, its speed setting was not reset. Subsequently, if the rport was not deleted due to it coming back online within rport del timeout, previously discovered speed would continue to show up. The fix is to reset the speed when processing rport offline transition. In rport attributes, rport's with unknown speed were indicated as TRL enforced. The right thing do to would be to use TRL default speed to determine if TRL is enforced, when TRL is enabled. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/lport_api.c | 30 +++++++++++++++++++++--------- drivers/scsi/bfa/rport_api.c | 11 ++++++++--- drivers/scsi/bfa/rport_ftrs.c | 1 + 3 files changed, 30 insertions(+), 12 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/lport_api.c b/drivers/scsi/bfa/lport_api.c index d3907d184e2b..72b3f508d0e9 100644 --- a/drivers/scsi/bfa/lport_api.c +++ b/drivers/scsi/bfa/lport_api.c @@ -137,6 +137,8 @@ bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port, wwn_t rport_wwns[], /* * Iterate's through all the rport's in the given port to * determine the maximum operating speed. + * + * To be used in TRL Functionality only */ enum bfa_pport_speed bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port) @@ -146,7 +148,8 @@ bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port) struct bfa_fcs_s *fcs; enum bfa_pport_speed max_speed = 0; struct bfa_pport_attr_s pport_attr; - enum bfa_pport_speed pport_speed; + enum bfa_pport_speed pport_speed, rport_speed; + bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); if (port == NULL) return 0; @@ -164,19 +167,28 @@ bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port) qe = bfa_q_first(qh); while (qe != qh) { - rport = (struct bfa_fcs_rport_s *)qe; - if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) - || (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE)) { + rport = (struct bfa_fcs_rport_s *) qe; + if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) || + (bfa_fcs_rport_get_state(rport) == + BFA_RPORT_OFFLINE)) { qe = bfa_q_next(qe); continue; } - if ((rport->rpf.rpsc_speed == BFA_PPORT_SPEED_8GBPS) - || (rport->rpf.rpsc_speed > pport_speed)) { - max_speed = rport->rpf.rpsc_speed; + rport_speed = rport->rpf.rpsc_speed; + if ((trl_enabled) && (rport_speed == + BFA_PPORT_SPEED_UNKNOWN)) { + /* Use default ratelim speed setting */ + rport_speed = + bfa_fcport_get_ratelim_speed(port->fcs->bfa); + } + + if ((rport_speed == BFA_PPORT_SPEED_8GBPS) || + (rport_speed > pport_speed)) { + max_speed = rport_speed; break; - } else if (rport->rpf.rpsc_speed > max_speed) { - max_speed = rport->rpf.rpsc_speed; + } else if (rport_speed > max_speed) { + max_speed = rport_speed; } qe = bfa_q_next(qe); diff --git a/drivers/scsi/bfa/rport_api.c b/drivers/scsi/bfa/rport_api.c index a441f41d2a64..15e0c470afd9 100644 --- a/drivers/scsi/bfa/rport_api.c +++ b/drivers/scsi/bfa/rport_api.c @@ -83,6 +83,7 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, { struct bfa_rport_qos_attr_s qos_attr; struct bfa_fcs_port_s *port = rport->port; + enum bfa_pport_speed rport_speed = rport->rpf.rpsc_speed; bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s)); @@ -102,10 +103,14 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, rport_attr->qos_attr = qos_attr; rport_attr->trl_enforced = BFA_FALSE; + if (bfa_fcport_is_ratelim(port->fcs->bfa)) { - if ((rport->rpf.rpsc_speed == BFA_PPORT_SPEED_UNKNOWN) || - (rport->rpf.rpsc_speed < - bfa_fcs_port_get_rport_max_speed(port))) + if (rport_speed == BFA_PPORT_SPEED_UNKNOWN) { + /* Use default ratelim speed setting */ + rport_speed = + bfa_fcport_get_ratelim_speed(rport->fcs->bfa); + } + if (rport_speed < bfa_fcs_port_get_rport_max_speed(port)) rport_attr->trl_enforced = BFA_TRUE; } diff --git a/drivers/scsi/bfa/rport_ftrs.c b/drivers/scsi/bfa/rport_ftrs.c index acecab83f82f..f2a9361ce9a4 100644 --- a/drivers/scsi/bfa/rport_ftrs.c +++ b/drivers/scsi/bfa/rport_ftrs.c @@ -274,6 +274,7 @@ void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport) if (__fcs_min_cfg(rport->port->fcs)) return; + rport->rpf.rpsc_speed = 0; bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE); } -- cgit v1.2.3 From 41188cf5a60a24bf54df5be70142f0928f413788 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:52:00 -0700 Subject: [SCSI] bfa: fix prli retry issues Add a max retry limit for PRLI retries. Max retry limit (5) is same as used in rport PLOGI. Once the retries are exhausted, invoke rport offline so that existing logic of rport re-discovery can kick-in. Also fixed a bug in rport.c where one less retry was happening. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/fcpim.c | 13 +++++++++++-- drivers/scsi/bfa/fcs_rport.h | 2 ++ drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h | 1 + drivers/scsi/bfa/rport.c | 4 +--- 4 files changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/fcpim.c index 7a0207e56693..d090f7a6368a 100644 --- a/drivers/scsi/bfa/fcpim.c +++ b/drivers/scsi/bfa/fcpim.c @@ -110,6 +110,7 @@ bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim, switch (event) { case BFA_FCS_ITNIM_SM_ONLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send); + itnim->prli_retries = 0; bfa_fcs_itnim_send_prli(itnim, NULL); break; @@ -218,8 +219,16 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim, switch (event) { case BFA_FCS_ITNIM_SM_TIMEOUT: - bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send); - bfa_fcs_itnim_send_prli(itnim, NULL); + if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) { + itnim->prli_retries++; + bfa_trc(itnim->fcs, itnim->prli_retries); + bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send); + bfa_fcs_itnim_send_prli(itnim, NULL); + } else { + /* invoke target offline */ + bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); + bfa_fcs_rport_logo_imp(itnim->rport); + } break; case BFA_FCS_ITNIM_SM_OFFLINE: diff --git a/drivers/scsi/bfa/fcs_rport.h b/drivers/scsi/bfa/fcs_rport.h index 9c8d1d292380..5242ee0f03c6 100644 --- a/drivers/scsi/bfa/fcs_rport.h +++ b/drivers/scsi/bfa/fcs_rport.h @@ -24,6 +24,8 @@ #include +#define BFA_FCS_RPORT_MAX_RETRIES (5) + void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, u16 len); void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport); diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h index e719f2c3eb35..9a35ecf5cdf0 100644 --- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h @@ -41,6 +41,7 @@ struct bfa_fcs_itnim_s { struct bfa_fcs_s *fcs; /* fcs instance */ struct bfa_timer_s timer; /* timer functions */ struct bfa_itnim_s *bfa_itnim; /* BFA itnim struct */ + u32 prli_retries; /* max prli retry attempts */ bfa_boolean_t seq_rec; /* seq recovery support */ bfa_boolean_t rec_support; /* REC supported */ bfa_boolean_t conf_comp; /* FCP_CONF support */ diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/rport.c index 2796403222e1..4e1fff21a5bc 100644 --- a/drivers/scsi/bfa/rport.c +++ b/drivers/scsi/bfa/rport.c @@ -36,8 +36,6 @@ BFA_TRC_FILE(FCS, RPORT); -#define BFA_FCS_RPORT_MAX_RETRIES (5) - /* In millisecs */ static u32 bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000; @@ -356,8 +354,8 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, */ case RPSM_EVENT_TIMEOUT: - rport->plogi_retries++; if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) { + rport->plogi_retries++; bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); bfa_fcs_rport_send_plogi(rport, NULL); } else { -- cgit v1.2.3 From 3e98cc013fc4902df5f9d9defe1856df0f0cb657 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:52:46 -0700 Subject: [SCSI] bfa: add PBC port disable handling Add PBC port disable handling in BFA and return the appropriate status from BFA APIs. In bfa_fcs_lport.c, handle OFFLINE event to avoid BFA_ASSERT. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcport.c | 38 +++++++++++++++++++++++++++++++++----- drivers/scsi/bfa/bfa_fcs_lport.c | 3 +++ 2 files changed, 36 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index 18d33072bec5..d3b5efba8af0 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1380,6 +1381,14 @@ bfa_status_t bfa_fcport_enable(struct bfa_s *bfa) { struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + struct bfa_iocfc_s *iocfc = &bfa->iocfc; + struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; + + /* if port is PBC disabled, return error */ + if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) { + bfa_trc(bfa, fcport->pwwn); + return BFA_STATUS_PBC; + } if (fcport->diag_busy) return BFA_STATUS_DIAG_BUSY; @@ -1394,6 +1403,16 @@ bfa_fcport_enable(struct bfa_s *bfa) bfa_status_t bfa_fcport_disable(struct bfa_s *bfa) { + struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + struct bfa_iocfc_s *iocfc = &bfa->iocfc; + struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; + + /* if port is PBC disabled, return error */ + if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) { + bfa_trc(bfa, fcport->pwwn); + return BFA_STATUS_PBC; + } + bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE); return BFA_STATUS_OK; } @@ -1584,6 +1603,8 @@ void bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr) { struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + struct bfa_iocfc_s *iocfc = &bfa->iocfc; + struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; bfa_os_memset(attr, 0, sizeof(struct bfa_pport_attr_s)); @@ -1618,11 +1639,18 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr) attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa); attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa); - attr->port_state = bfa_sm_to_state(hal_pport_sm_table, fcport->sm); - if (bfa_ioc_is_disabled(&fcport->bfa->ioc)) - attr->port_state = BFA_PPORT_ST_IOCDIS; - else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc)) - attr->port_state = BFA_PPORT_ST_FWMISMATCH; + + /* PBC Disabled State */ + if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) + attr->port_state = BFA_PPORT_ST_PREBOOT_DISABLED; + else { + attr->port_state = bfa_sm_to_state( + hal_pport_sm_table, fcport->sm); + if (bfa_ioc_is_disabled(&fcport->bfa->ioc)) + attr->port_state = BFA_PPORT_ST_IOCDIS; + else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc)) + attr->port_state = BFA_PPORT_ST_FWMISMATCH; + } } #define BFA_FCPORT_STATS_TOV 1000 diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 7c1251c682d8..35df20e68a52 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -135,6 +135,9 @@ bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event) bfa_fcs_port_deleted(port); break; + case BFA_FCS_PORT_SM_OFFLINE: + break; + default: bfa_sm_fault(port->fcs, event); } -- cgit v1.2.3 From 9aeb6802ddc06b66fc1a58a882fa54bba37040b3 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:53:40 -0700 Subject: [SCSI] bfa: update to support firmware configuation Update related data structures to support firmeare configuration. Add AEN events related to firmware configuation. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc.c | 6 +- drivers/scsi/bfa/bfa_ioc.h | 1 + drivers/scsi/bfa/bfa_log_module.c | 86 +++++++++++++++++++++++++ drivers/scsi/bfa/include/aen/bfa_aen_ioc.h | 8 +++ drivers/scsi/bfa/include/cs/bfa_debug.h | 3 +- drivers/scsi/bfa/include/defs/bfa_defs_ioc.h | 7 +- drivers/scsi/bfa/include/defs/bfa_defs_status.h | 3 + drivers/scsi/bfa/include/log/bfa_log_linux.h | 6 +- 8 files changed, 112 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 1600f747eb6c..c4922fb995d5 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -71,8 +71,6 @@ bfa_boolean_t bfa_auto_recover = BFA_TRUE; /* * forward declarations */ -static void bfa_ioc_aen_post(struct bfa_ioc_s *bfa, - enum bfa_ioc_aen_event event); static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc); static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc); static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force); @@ -1902,7 +1900,7 @@ bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc) /** * Send AEN notification */ -static void +void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event) { union bfa_aen_data_u aen_data; @@ -2052,7 +2050,7 @@ bfa_ioc_recover(struct bfa_ioc_s *ioc) #else -static void +void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event) { } diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 2425c00a72d3..cae05b251c99 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -297,6 +297,7 @@ void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr); bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr); +void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event); /* * bfa mfg wwn API functions diff --git a/drivers/scsi/bfa/bfa_log_module.c b/drivers/scsi/bfa/bfa_log_module.c index 5c154d341d69..cf577ef7cb97 100644 --- a/drivers/scsi/bfa/bfa_log_module.c +++ b/drivers/scsi/bfa/bfa_log_module.c @@ -110,6 +110,27 @@ struct bfa_log_msgdef_s bfa_log_msg_array[] = { "Running firmware version is incompatible with the driver version.", (0), 0}, +{BFA_AEN_IOC_FWCFG_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWCFG_ERROR", + "Link initialization failed due to firmware configuration read error:" + " WWN = %s.", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_AEN_IOC_INVALID_VENDOR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_VENDOR", + "Unsupported switch vendor. Link initialization failed: WWN = %s.", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_AEN_IOC_INVALID_NWWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_NWWN", + "Invalid NWWN. Link initialization failed: NWWN = 00:00:00:00:00:00:00:00.", + (0), 0}, + +{BFA_AEN_IOC_INVALID_PWWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_PWWN", + "Invalid PWWN. Link initialization failed: PWWN = 00:00:00:00:00:00:00:00.", + (0), 0}, + @@ -347,6 +368,22 @@ struct bfa_log_msgdef_s bfa_log_msg_array[] = { ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) | (BFA_LOG_D << BFA_LOG_ARG2) | 0), 3}, +{BFA_LOG_HAL_DRIVER_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_INFO, "HAL_DRIVER_ERROR", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_HAL_DRIVER_CONFIG_ERROR, + BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, + "HAL_DRIVER_CONFIG_ERROR", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_HAL_MBOX_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_INFO, "HAL_MBOX_ERROR", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + @@ -412,6 +449,55 @@ struct bfa_log_msgdef_s bfa_log_msg_array[] = { ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) | (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3}, +{BFA_LOG_LINUX_DRIVER_CONFIG_ERROR, + BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, + "LINUX_DRIVER_CONFIG_ERROR", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_LINUX_BNA_STATE_MACHINE, + BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, + "LINUX_BNA_STATE_MACHINE", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_LINUX_IOC_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_INFO, "LINUX_IOC_ERROR", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_LINUX_RESOURCE_ALLOC_ERROR, + BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, + "LINUX_RESOURCE_ALLOC_ERROR", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_LINUX_RING_BUFFER_ERROR, + BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, + "LINUX_RING_BUFFER_ERROR", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_LINUX_DRIVER_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_ERROR, "LINUX_DRIVER_ERROR", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_LINUX_DRIVER_INFO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_INFO, "LINUX_DRIVER_INFO", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_LINUX_DRIVER_DIAG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_INFO, "LINUX_DRIVER_DIAG", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + +{BFA_LOG_LINUX_DRIVER_AEN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, + BFA_LOG_INFO, "LINUX_DRIVER_AEN", + "%s", + ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, + diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h b/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h index 71378b446b69..4daf96faa266 100644 --- a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h +++ b/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h @@ -32,6 +32,14 @@ BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_DISABLE) #define BFA_AEN_IOC_FWMISMATCH \ BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWMISMATCH) +#define BFA_AEN_IOC_FWCFG_ERROR \ + BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWCFG_ERROR) +#define BFA_AEN_IOC_INVALID_VENDOR \ + BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_VENDOR) +#define BFA_AEN_IOC_INVALID_NWWN \ + BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_NWWN) +#define BFA_AEN_IOC_INVALID_PWWN \ + BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_PWWN) #endif diff --git a/drivers/scsi/bfa/include/cs/bfa_debug.h b/drivers/scsi/bfa/include/cs/bfa_debug.h index 441be86b1b0f..75a911ea7936 100644 --- a/drivers/scsi/bfa/include/cs/bfa_debug.h +++ b/drivers/scsi/bfa/include/cs/bfa_debug.h @@ -28,7 +28,8 @@ } while (0) #define bfa_sm_fault(__mod, __event) do { \ - bfa_sm_panic((__mod)->logm, __LINE__, __FILE__, __event); \ + bfa_trc(__mod, (((uint32_t)0xDEAD << 16) | __event)); \ + bfa_sm_panic((__mod)->logm, __LINE__, __FILE__, __event); \ } while (0) #ifndef BFA_PERF_BUILD diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h index 8d8e6a966537..add0a05d941d 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h @@ -126,7 +126,7 @@ struct bfa_ioc_attr_s { struct bfa_ioc_driver_attr_s driver_attr; /* driver attr */ struct bfa_ioc_pci_attr_s pci_attr; u8 port_id; /* port number */ - u8 rsvd[7]; /*!< 64bit align */ + u8 rsvd[7]; /* 64bit align */ }; /** @@ -138,6 +138,11 @@ enum bfa_ioc_aen_event { BFA_IOC_AEN_ENABLE = 3, /* IOC enabled event */ BFA_IOC_AEN_DISABLE = 4, /* IOC disabled event */ BFA_IOC_AEN_FWMISMATCH = 5, /* IOC firmware mismatch */ + BFA_IOC_AEN_FWCFG_ERROR = 6, /* IOC firmware config error */ + BFA_IOC_AEN_INVALID_VENDOR = 7, + BFA_IOC_AEN_INVALID_NWWN = 8, /* Zero NWWN */ + BFA_IOC_AEN_INVALID_PWWN = 9 /* Zero PWWN */ + }; /** diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h index 7cef900707c5..c8bc60ad2df6 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_status.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_status.h @@ -254,6 +254,9 @@ enum bfa_status { * Teaming mode */ BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot * configuration */ + BFA_STATUS_DEVID_MISSING = 155, /* Boot image is not for the adapter(s) + * installed */ + BFA_STATUS_BAD_FWCFG = 156, /* Bad firmware configuration */ BFA_STATUS_MAX_VAL /* Unknown error code */ }; #define bfa_status_t enum bfa_status diff --git a/drivers/scsi/bfa/include/log/bfa_log_linux.h b/drivers/scsi/bfa/include/log/bfa_log_linux.h index bd451db4c30a..44bc89768bda 100644 --- a/drivers/scsi/bfa/include/log/bfa_log_linux.h +++ b/drivers/scsi/bfa/include/log/bfa_log_linux.h @@ -53,8 +53,10 @@ (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 16) #define BFA_LOG_LINUX_DRIVER_ERROR \ (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 17) -#define BFA_LOG_LINUX_DRIVER_DIAG \ +#define BFA_LOG_LINUX_DRIVER_INFO \ (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 18) -#define BFA_LOG_LINUX_DRIVER_AEN \ +#define BFA_LOG_LINUX_DRIVER_DIAG \ (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 19) +#define BFA_LOG_LINUX_DRIVER_AEN \ + (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 20) #endif -- cgit v1.2.3 From df2a52a6c8c4995e0bec0b739ddb2f51664837dd Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:54:39 -0700 Subject: [SCSI] bfa: fix chip and memory initialization Clear PSS memory reset that is set as part of power-on-reset (pci reset). Complete PMM memory reset before BISTR start. Clear EDRAM BISTR start bit after fixed delay. BISTR DONE bit status is not getting set. Use a fixed 1ms delay for BISTR now. Expose PMM IT memory definitions to host. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc_ct.c | 25 +++++++++++++++++++++++++ drivers/scsi/bfa/include/bfi/bfi_ctreg.h | 3 +++ 2 files changed, 28 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 17bd1513b34e..68f027da001e 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -376,10 +376,35 @@ bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc) bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk | __APP_PLL_425_ENABLE); + /** + * PSS memory reset is asserted at power-on-reset. Need to clear + * this before running EDRAM BISTR + */ + if (ioc->cna) { + bfa_reg_write((rb + PMM_1T_RESET_REG_P0), __PMM_1T_RESET_P); + bfa_reg_write((rb + PMM_1T_RESET_REG_P1), __PMM_1T_RESET_P); + } + + r32 = bfa_reg_read((rb + PSS_CTL_REG)); + r32 &= ~__PSS_LMEM_RESET; + bfa_reg_write((rb + PSS_CTL_REG), r32); + bfa_os_udelay(1000); + + if (ioc->cna) { + bfa_reg_write((rb + PMM_1T_RESET_REG_P0), 0); + bfa_reg_write((rb + PMM_1T_RESET_REG_P1), 0); + } + bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START); bfa_os_udelay(1000); r32 = bfa_reg_read((rb + MBIST_STAT_REG)); bfa_trc(ioc, r32); + + /** + * Clear BISTR + */ + bfa_reg_write((rb + MBIST_CTL_REG), 0); + /* * release semaphore. */ diff --git a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h b/drivers/scsi/bfa/include/bfi/bfi_ctreg.h index 57a8497105af..c0ef5a93b797 100644 --- a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h +++ b/drivers/scsi/bfa/include/bfi/bfi_ctreg.h @@ -455,6 +455,9 @@ enum { #define __PSS_LPU0_RAM_ERR 0x00000001 #define ERR_SET_REG 0x00018818 #define __PSS_ERR_STATUS_SET 0x003fffff +#define PMM_1T_RESET_REG_P0 0x0002381c +#define __PMM_1T_RESET_P 0x00000001 +#define PMM_1T_RESET_REG_P1 0x00023c1c #define HQM_QSET0_RXQ_DRBL_P0 0x00038000 #define __RXQ0_ADD_VECTORS_P 0x80000000 #define __RXQ0_STOP_P 0x40000000 -- cgit v1.2.3 From 4b5e759dca9fb26d921c1267283350004dbf197b Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:55:41 -0700 Subject: [SCSI] bfa: fix uf post and rport fcpim state machine BFA UF module did not hold lock when seding uf post buffer message to firmware causing CPE-Q corruption. Fix is to check present of FCS and if FCS present hold lock while posting UF buffers. Handle PRLO with sending acc to it and relogin with rport. Discard fcxp before any state change. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_uf.c | 5 +- drivers/scsi/bfa/fcpim.c | 16 +++--- drivers/scsi/bfa/fcs_rport.h | 1 + drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h | 1 + drivers/scsi/bfa/rport.c | 76 +++++++++++++++++++++++++++- 5 files changed, 89 insertions(+), 10 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_uf.c b/drivers/scsi/bfa/bfa_uf.c index b2a37fc952de..b9a9a686ef6a 100644 --- a/drivers/scsi/bfa/bfa_uf.c +++ b/drivers/scsi/bfa/bfa_uf.c @@ -251,7 +251,10 @@ uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m) (struct fchs_s *) buf, pld_w0); } - bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf); + if (bfa->fcs) + __bfa_cb_uf_recv(uf, BFA_TRUE); + else + bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf); } static void diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/fcpim.c index d090f7a6368a..6b8976ad22fa 100644 --- a/drivers/scsi/bfa/fcpim.c +++ b/drivers/scsi/bfa/fcpim.c @@ -175,8 +175,12 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim, switch (event) { case BFA_FCS_ITNIM_SM_RSP_OK: - bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online); - bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec); + if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) { + bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); + } else { + bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online); + bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec); + } break; case BFA_FCS_ITNIM_SM_RSP_ERROR: @@ -194,9 +198,7 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim, case BFA_FCS_ITNIM_SM_INITIATOR: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); - /* - * dont discard fcxp. accept will reach same state - */ + bfa_fcxp_discard(itnim->fcxp); break; case BFA_FCS_ITNIM_SM_DELETE: @@ -476,7 +478,7 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, BFA_RPORT_INITIATOR; itnim->stats.prli_rsp_acc++; bfa_sm_send_event(itnim, - BFA_FCS_ITNIM_SM_INITIATOR); + BFA_FCS_ITNIM_SM_RSP_OK); return; } @@ -803,7 +805,7 @@ bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs, switch (els_cmd->els_code) { case FC_ELS_PRLO: - /* bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_PRLO); */ + bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id); break; default: diff --git a/drivers/scsi/bfa/fcs_rport.h b/drivers/scsi/bfa/fcs_rport.h index 5242ee0f03c6..e634fb7a69b8 100644 --- a/drivers/scsi/bfa/fcs_rport.h +++ b/drivers/scsi/bfa/fcs_rport.h @@ -43,6 +43,7 @@ void bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, struct fc_logi_s *plogi); void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport); +void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id); void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport); void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport); void bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport); diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h index 702b95b76c2d..3027fc6c7722 100644 --- a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h @@ -58,6 +58,7 @@ struct bfa_fcs_rport_s { u16 reply_oxid; /* OX_ID of inbound requests */ enum fc_cos fc_cos; /* FC classes of service supp */ bfa_boolean_t cisc; /* CISC capable device */ + bfa_boolean_t prlo; /* processing prlo or LOGO */ wwn_t pwwn; /* port wwn of rport */ wwn_t nwwn; /* node wwn of rport */ struct bfa_rport_symname_s psym_name; /* port symbolic name */ diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/rport.c index 4e1fff21a5bc..9b4c2c9a644b 100644 --- a/drivers/scsi/bfa/rport.c +++ b/drivers/scsi/bfa/rport.c @@ -93,6 +93,7 @@ static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, u8 reason_code_expl); static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, u16 len); +static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport); /** * fcs_rport_sm FCS rport state machine events */ @@ -113,7 +114,8 @@ enum rport_event { RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */ RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */ RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */ - RPSM_EVENT_ADDRESS_DISC = 16 /* Need to Discover rport's PID */ + RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */ + RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */ }; static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, @@ -373,6 +375,7 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_free(rport); break; + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_LOGO_RCVD: break; @@ -428,6 +431,13 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event) case RPSM_EVENT_LOGO_RCVD: bfa_fcs_rport_send_logo_acc(rport); + /* + * !! fall through !! + */ + case RPSM_EVENT_PRLO_RCVD: + if (rport->prlo == BFA_TRUE) + bfa_fcs_rport_send_prlo_acc(rport); + bfa_fcxp_discard(rport->fcxp); /* * !! fall through !! @@ -502,6 +512,9 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_online_action(rport); break; + case RPSM_EVENT_PRLO_RCVD: + break; + case RPSM_EVENT_LOGO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); bfa_rport_offline(rport->bfa_rport); @@ -580,6 +593,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcs_rport_offline_action(rport); break; @@ -622,6 +636,7 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_fcs_rport_offline_action(rport); @@ -688,6 +703,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcxp_discard(rport->fcxp); bfa_fcs_rport_offline_action(rport); @@ -738,6 +754,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_fcs_rport_offline_action(rport); @@ -809,6 +826,7 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); bfa_fcxp_discard(rport->fcxp); bfa_fcs_rport_offline_action(rport); @@ -841,6 +859,7 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_ADDRESS_CHANGE: break; @@ -892,6 +911,7 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_SCN: case RPSM_EVENT_LOGO_IMP: case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_ADDRESS_CHANGE: /** * rport is already going offline. @@ -951,6 +971,7 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_SCN: case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: /** * Ignore, already offline. */ @@ -976,8 +997,11 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, switch (event) { case RPSM_EVENT_HCB_OFFLINE: case RPSM_EVENT_ADDRESS_CHANGE: - if (rport->pid) + if (rport->pid && (rport->prlo == BFA_TRUE)) + bfa_fcs_rport_send_prlo_acc(rport); + if (rport->pid && (rport->prlo == BFA_FALSE)) bfa_fcs_rport_send_logo_acc(rport); + /* * If the lport is online and if the rport is not a well known * address port, we try to re-discover the r-port. @@ -1011,6 +1035,7 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: /** * Ignore - already processing a LOGO. */ @@ -1040,6 +1065,7 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_ADDRESS_CHANGE: break; @@ -1073,6 +1099,7 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport, break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); bfa_fcs_rport_free(rport); @@ -1121,6 +1148,7 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_LOGO_IMP: break; @@ -1172,6 +1200,7 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_SCN: case RPSM_EVENT_LOGO_RCVD: + case RPSM_EVENT_PRLO_RCVD: case RPSM_EVENT_PLOGI_SEND: break; @@ -1248,6 +1277,10 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_send_logo_acc(rport); break; + case RPSM_EVENT_PRLO_RCVD: + bfa_fcs_rport_send_prlo_acc(rport); + break; + case RPSM_EVENT_PLOGI_COMP: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); bfa_timer_stop(&rport->timer); @@ -1320,6 +1353,10 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_del_timeout); break; + case RPSM_EVENT_PRLO_RCVD: + bfa_fcs_rport_send_prlo_acc(rport); + break; + case RPSM_EVENT_SCN: /** * ignore, wait for NS query response @@ -2182,6 +2219,7 @@ bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs) rport->reply_oxid = fchs->ox_id; bfa_trc(rport->fcs, rport->reply_oxid); + rport->prlo = BFA_FALSE; rport->stats.logo_rcvd++; bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD); } @@ -2551,6 +2589,30 @@ bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, } } +/* Send best case acc to prlo */ +static void +bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport) +{ + struct bfa_fcs_port_s *port = rport->port; + struct fchs_s fchs; + struct bfa_fcxp_s *fcxp; + int len; + + bfa_trc(rport->fcs, rport->pid); + + fcxp = bfa_fcs_fcxp_alloc(port->fcs); + if (!fcxp) + return; + + len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), + rport->pid, bfa_fcs_port_get_fcid(port), + rport->reply_oxid, 0); + + bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, + port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, + NULL, NULL, FC_MAX_PDUSZ, 0); +} + /* * Send a LS reject */ @@ -2602,3 +2664,13 @@ bfa_fcs_rport_set_del_timeout(u8 rport_tmo) if (rport_tmo > 0) bfa_fcs_rport_del_timeout = rport_tmo * 1000; } + +void +bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id) +{ + bfa_trc(rport->fcs, rport->pid); + + rport->prlo = BFA_TRUE; + rport->reply_oxid = ox_id; + bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD); +} -- cgit v1.2.3 From 36d345a703b7b3f80a56ee37abb7908c52d1cd67 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:57:33 -0700 Subject: [SCSI] bfa: add dynamic queue selection Add new bfa functionality to support dynamic queue selection (IO redirection). IO redirection can only be enabled when QoS is disabled. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_cb_ioim_macros.h | 7 +++++- drivers/scsi/bfa/bfa_fcpim.c | 24 ++++++++++++++++++++ drivers/scsi/bfa/bfa_fcpim_priv.h | 5 ++++- drivers/scsi/bfa/bfa_fcport.c | 13 ++++++++++- drivers/scsi/bfa/bfa_hw_cb.c | 7 +++++- drivers/scsi/bfa/bfa_hw_ct.c | 7 +++++- drivers/scsi/bfa/bfa_intr.c | 1 + drivers/scsi/bfa/bfa_iocfc.c | 2 ++ drivers/scsi/bfa/bfa_iocfc.h | 9 +++++++- drivers/scsi/bfa/bfa_ioim.c | 29 +++++++++++++++---------- drivers/scsi/bfa/bfad_im.c | 9 ++++++++ drivers/scsi/bfa/include/bfa_fcpim.h | 20 ++++++++++++++++- drivers/scsi/bfa/include/bfa_svc.h | 1 + drivers/scsi/bfa/include/defs/bfa_defs_driver.h | 2 +- 14 files changed, 117 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_cb_ioim_macros.h b/drivers/scsi/bfa/bfa_cb_ioim_macros.h index 53a616f5f50d..3906ed926966 100644 --- a/drivers/scsi/bfa/bfa_cb_ioim_macros.h +++ b/drivers/scsi/bfa/bfa_cb_ioim_macros.h @@ -171,6 +171,11 @@ bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio) return cmnd->cmd_len; } - +/** + * Assign queue to be used for the I/O request. This value depends on whether + * the driver wants to use the queues via any specific algorithm. Currently, + * this is not supported. + */ +#define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE #endif /* __BFA_HCB_IOIM_MACROS_H__ */ diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 12849e9071cd..8c703d8dc94b 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -167,4 +167,28 @@ bfa_fcpim_qdepth_get(struct bfa_s *bfa) return fcpim->q_depth; } +void +bfa_fcpim_update_ioredirect(struct bfa_s *bfa) +{ + bfa_boolean_t ioredirect; + + /* + * IO redirection is turned off when QoS is enabled and vice versa + */ + ioredirect = bfa_fcport_is_qos_enabled(bfa) ? BFA_FALSE : BFA_TRUE; + /* + * Notify the bfad module of a possible state change in + * IO redirection capability, due to a QoS state change. bfad will + * check on the support for io redirection and update the + * fcpim's ioredirect state accordingly. + */ + bfa_cb_ioredirect_state_change((void *)(bfa->bfad), ioredirect); +} + +void +bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state) +{ + struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); + fcpim->ioredirect = state; +} diff --git a/drivers/scsi/bfa/bfa_fcpim_priv.h b/drivers/scsi/bfa/bfa_fcpim_priv.h index 3db39da72427..762516cb5cb2 100644 --- a/drivers/scsi/bfa/bfa_fcpim_priv.h +++ b/drivers/scsi/bfa/bfa_fcpim_priv.h @@ -49,7 +49,8 @@ struct bfa_fcpim_mod_s { int num_tskim_reqs; u32 path_tov; u16 q_depth; - u16 rsvd; + u8 reqq; /* Request queue to be used */ + u8 rsvd; struct list_head itnim_q; /* queue of active itnim */ struct list_head ioim_free_q; /* free IO resources */ struct list_head ioim_resfree_q; /* IOs waiting for f/w */ @@ -58,6 +59,7 @@ struct bfa_fcpim_mod_s { u32 ios_active; /* current active IOs */ u32 delay_comp; struct bfa_fcpim_stats_s stats; + bfa_boolean_t ioredirect; }; struct bfa_ioim_s; @@ -82,6 +84,7 @@ struct bfa_ioim_s { struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */ bfa_cb_cbfn_t io_cbfn; /* IO completion handler */ struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */ + u8 reqq; /* Request queue for I/O */ }; struct bfa_ioim_sp_s { diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index d3b5efba8af0..e0e7a0dda545 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -1857,8 +1857,13 @@ bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off) bfa_trc(bfa, ioc_type); - if (ioc_type == BFA_IOC_TYPE_FC) + if (ioc_type == BFA_IOC_TYPE_FC) { fcport->cfg.qos_enabled = on_off; + /** + * Notify fcpim of the change in QoS state + */ + bfa_fcpim_update_ioredirect(bfa); + } } void @@ -1942,4 +1947,10 @@ bfa_fcport_is_linkup(struct bfa_s *bfa) return bfa_sm_cmp_state(BFA_FCPORT_MOD(bfa), bfa_fcport_sm_linkup); } +bfa_boolean_t +bfa_fcport_is_qos_enabled(struct bfa_s *bfa) +{ + struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + return fcport->cfg.qos_enabled; +} diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c index 871a4e28575c..edfd729445cf 100644 --- a/drivers/scsi/bfa/bfa_hw_cb.c +++ b/drivers/scsi/bfa/bfa_hw_cb.c @@ -152,4 +152,9 @@ bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; } - +void +bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end) +{ + *start = BFA_MSIX_RME_Q0; + *end = BFA_MSIX_RME_Q7; +} diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c index 76ceb9a4bf2f..a357fb3066fd 100644 --- a/drivers/scsi/bfa/bfa_hw_ct.c +++ b/drivers/scsi/bfa/bfa_hw_ct.c @@ -168,4 +168,9 @@ bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) bfa_ioc_isr_mode_set(&bfa->ioc, msix); } - +void +bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end) +{ + *start = BFA_MSIX_RME_Q0; + *end = BFA_MSIX_RME_Q3; +} diff --git a/drivers/scsi/bfa/bfa_intr.c b/drivers/scsi/bfa/bfa_intr.c index 0eba3f930d5b..493678889b24 100644 --- a/drivers/scsi/bfa/bfa_intr.c +++ b/drivers/scsi/bfa/bfa_intr.c @@ -134,6 +134,7 @@ bfa_isr_enable(struct bfa_s *bfa) bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask); bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask); + bfa->iocfc.intr_mask = ~intr_unmask; bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0); } diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c index 0776d74d40de..90820be99864 100644 --- a/drivers/scsi/bfa/bfa_iocfc.c +++ b/drivers/scsi/bfa/bfa_iocfc.c @@ -187,6 +187,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall; iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set; iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs; + iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range; } else { iocfc->hwif.hw_reginit = bfa_hwcb_reginit; iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack; @@ -196,6 +197,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall; iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set; iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs; + iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range; } iocfc->hwif.hw_reginit(bfa); diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h index 2b281037fd79..74a6a048d1fd 100644 --- a/drivers/scsi/bfa/bfa_iocfc.h +++ b/drivers/scsi/bfa/bfa_iocfc.h @@ -63,6 +63,8 @@ struct bfa_hwif_s { void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix); void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs, u32 *maxvec); + void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start, + u32 *end); }; typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status); @@ -104,7 +106,8 @@ struct bfa_iocfc_s { struct bfa_hwif_s hwif; bfa_cb_iocfc_t updateq_cbfn; /* bios callback function */ - void *updateq_cbarg; /* bios callback arg */ + void *updateq_cbarg; /* bios callback arg */ + u32 intr_mask; }; #define bfa_lpuid(__bfa) bfa_ioc_portid(&(__bfa)->ioc) @@ -119,6 +122,8 @@ struct bfa_iocfc_s { #define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \ ((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, \ __nvecs, __maxvec)) +#define bfa_msix_get_rme_range(__bfa, __start, __end) \ + ((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end)) /* * FC specific IOC functions. @@ -154,6 +159,7 @@ void bfa_hwcb_msix_uninstall(struct bfa_s *bfa); void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix); void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs, u32 *maxvec); +void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end); void bfa_hwct_reginit(struct bfa_s *bfa); void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq); void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq); @@ -163,6 +169,7 @@ void bfa_hwct_msix_uninstall(struct bfa_s *bfa); void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix); void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs, u32 *maxvec); +void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end); void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len); void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi, diff --git a/drivers/scsi/bfa/bfa_ioim.c b/drivers/scsi/bfa/bfa_ioim.c index 687f3d6e252b..680b87d8f0d9 100644 --- a/drivers/scsi/bfa/bfa_ioim.c +++ b/drivers/scsi/bfa/bfa_ioim.c @@ -234,8 +234,8 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) bfa_sm_set_state(ioim, bfa_ioim_sm_abort); else { bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull); - bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq, - &ioim->iosp->reqq_wait); + bfa_reqq_wait(ioim->bfa, ioim->reqq, + &ioim->iosp->reqq_wait); } break; @@ -247,8 +247,8 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup); else { bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull); - bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq, - &ioim->iosp->reqq_wait); + bfa_reqq_wait(ioim->bfa, ioim->reqq, + &ioim->iosp->reqq_wait); } break; @@ -305,7 +305,7 @@ bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup); else { bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull); - bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq, + bfa_reqq_wait(ioim->bfa, ioim->reqq, &ioim->iosp->reqq_wait); } break; @@ -738,9 +738,9 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) /** * check for room in queue to send request now */ - m = bfa_reqq_next(ioim->bfa, itnim->reqq); + m = bfa_reqq_next(ioim->bfa, ioim->reqq); if (!m) { - bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq, + bfa_reqq_wait(ioim->bfa, ioim->reqq, &ioim->iosp->reqq_wait); return BFA_FALSE; } @@ -832,7 +832,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) /** * queue I/O message to firmware */ - bfa_reqq_produce(ioim->bfa, itnim->reqq); + bfa_reqq_produce(ioim->bfa, ioim->reqq); return BFA_TRUE; } @@ -930,14 +930,13 @@ bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim) static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim) { - struct bfa_itnim_s *itnim = ioim->itnim; struct bfi_ioim_abort_req_s *m; enum bfi_ioim_h2i msgop; /** * check for room in queue to send request now */ - m = bfa_reqq_next(ioim->bfa, itnim->reqq); + m = bfa_reqq_next(ioim->bfa, ioim->reqq); if (!m) return BFA_FALSE; @@ -956,7 +955,7 @@ bfa_ioim_send_abort(struct bfa_ioim_s *ioim) /** * queue I/O message to firmware */ - bfa_reqq_produce(ioim->bfa, itnim->reqq); + bfa_reqq_produce(ioim->bfa, ioim->reqq); return BFA_TRUE; } @@ -1306,6 +1305,14 @@ void bfa_ioim_start(struct bfa_ioim_s *ioim) { bfa_trc_fp(ioim->bfa, ioim->iotag); + + /** + * Obtain the queue over which this request has to be issued + */ + ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ? + bfa_cb_ioim_get_reqq(ioim->dio) : + bfa_itnim_get_reqq(ioim); + bfa_sm_send_event(ioim, BFA_IOIM_SM_START); } diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 943bc4b37284..ffbec9ba21b7 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -702,6 +702,15 @@ bfad_im_probe_undo(struct bfad_s *bfad) } } +/** + * Call back function to handle IO redirection state change + */ +void +bfa_cb_ioredirect_state_change(void *hcb_bfad, bfa_boolean_t ioredirect) +{ + /* Do nothing */ +} + struct Scsi_Host * bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad) { diff --git a/drivers/scsi/bfa/include/bfa_fcpim.h b/drivers/scsi/bfa/include/bfa_fcpim.h index 04789795fa53..4bc9453081df 100644 --- a/drivers/scsi/bfa/include/bfa_fcpim.h +++ b/drivers/scsi/bfa/include/bfa_fcpim.h @@ -42,6 +42,24 @@ u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa); bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_fcpim_stats_s *modstats); bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa); +void bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state); +void bfa_fcpim_update_ioredirect(struct bfa_s *bfa); +void bfa_cb_ioredirect_state_change(void *hcb_bfad, bfa_boolean_t ioredirect); + +#define bfa_fcpim_ioredirect_enabled(__bfa) \ + (((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect) + +#define bfa_fcpim_get_next_reqq(__bfa, __qid) \ +{ \ + struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa); \ + __fcpim->reqq++; \ + __fcpim->reqq &= (BFI_IOC_MAX_CQS - 1); \ + *(__qid) = __fcpim->reqq; \ +} + +#define bfa_iocfc_map_msg_to_qid(__msg, __qid) \ + *(__qid) = (u8)((__msg) & (BFI_IOC_MAX_CQS - 1)); + /* * bfa itnim API functions @@ -56,6 +74,7 @@ void bfa_itnim_get_stats(struct bfa_itnim_s *itnim, struct bfa_itnim_hal_stats_s *stats); void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim); +#define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq) /** * BFA completion callback for bfa_itnim_online(). @@ -156,4 +175,3 @@ void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, enum bfi_tskim_status tsk_status); #endif /* __BFA_FCPIM_H__ */ - diff --git a/drivers/scsi/bfa/include/bfa_svc.h b/drivers/scsi/bfa/include/bfa_svc.h index 1349b99a3c6d..7840943d73b0 100644 --- a/drivers/scsi/bfa/include/bfa_svc.h +++ b/drivers/scsi/bfa/include/bfa_svc.h @@ -215,6 +215,7 @@ bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg); bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg); +bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa); /* * bfa rport API functions diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h b/drivers/scsi/bfa/include/defs/bfa_defs_driver.h index 50382dd2ab41..7d00d00d3969 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_driver.h @@ -29,7 +29,7 @@ struct bfa_driver_stats_s { u16 tm_target_reset; u16 tm_bus_reset; u16 ioc_restart; /* IOC restart count */ - u16 io_pending; /* outstanding io count per-IOC */ + u16 rsvd; u64 control_req; u64 input_req; u64 output_req; -- cgit v1.2.3 From db954c04cbebd7d719927118c7f58eddd8dd9913 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:58:01 -0700 Subject: [SCSI] bfa: fix link state structure When the FCoE Linkup event is sent to the host, the link_state (struct bfa_pport_link_s) structure is copied to the RME buf to be sent to the host. But the size of this structure(164 bytes) is larger than the reserved RME buffer size(128 byes). The following changes reduce the size of the structure to be less than RME buffer size(128 bytes): - Remove the trunk and loop info from link_state structure, because both trunk and loop are not supported. - Combine qos_vc_attr and fcf into an union. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcport.c | 15 +++++++++------ drivers/scsi/bfa/include/defs/bfa_defs_pport.h | 22 +++------------------- 2 files changed, 12 insertions(+), 25 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index e0e7a0dda545..c855e225af16 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -311,10 +311,12 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport, if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) { - bfa_trc(fcport->bfa, pevent->link_state.fcf.fipenabled); - bfa_trc(fcport->bfa, pevent->link_state.fcf.fipfailed); + bfa_trc(fcport->bfa, + pevent->link_state.vc_fcf.fcf.fipenabled); + bfa_trc(fcport->bfa, + pevent->link_state.vc_fcf.fcf.fipfailed); - if (pevent->link_state.fcf.fipfailed) + if (pevent->link_state.vc_fcf.fcf.fipfailed) bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_FIP_FCF_DISC, 0, "FIP FCF Discovery Failed"); @@ -960,14 +962,15 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport) fcport->topology = pevent->link_state.topology; if (fcport->topology == BFA_PPORT_TOPOLOGY_LOOP) - fcport->myalpa = - pevent->link_state.tl.loop_info.myalpa; + fcport->myalpa = 0; /* * QoS Details */ bfa_os_assign(fcport->qos_attr, pevent->link_state.qos_attr); - bfa_os_assign(fcport->qos_vc_attr, pevent->link_state.qos_vc_attr); + bfa_os_assign(fcport->qos_vc_attr, + pevent->link_state.vc_fcf.qos_vc_attr); + bfa_trc(fcport->bfa, fcport->speed); bfa_trc(fcport->bfa, fcport->topology); diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h index 2c2cec5ee278..2de675839c2f 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h @@ -384,26 +384,10 @@ struct bfa_pport_link_s { u8 trunked; /* Trunked or not (1 or 0) */ u8 resvd[3]; struct bfa_qos_attr_s qos_attr; /* QoS Attributes */ - struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */ union { - struct { - u8 tmaster;/* Trunk Master or - * not (1 or 0) */ - u8 tlinks; /* Trunk links bitmap - * (linkup) */ - u8 resv1; /* Reserved */ - } trunk_info; - - struct { - u8 myalpa; /* alpa claimed */ - u8 login_req; /* Login required or - * not (1 or 0) */ - u8 alpabm_val;/* alpa bitmap valid - * or not (1 or 0) */ - struct fc_alpabm_s alpabm; /* alpa bitmap */ - } loop_info; - } tl; - struct bfa_fcport_fcf_s fcf; /*!< FCF information (for FCoE) */ + struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */ + struct bfa_fcport_fcf_s fcf; /* FCF information (for FCoE) */ + } vc_fcf; }; #endif /* __BFA_DEFS_PPORT_H__ */ -- cgit v1.2.3 From 56d218fc93ede28a2a5b71c5db334f193b39988f Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:58:45 -0700 Subject: [SCSI] bfa: fix possible IO double completion While processing the ioim in callback functions, the ioim is still in io_q. During this time, if the itnim goes offline, the ioim is requeued from itnim->io_q into itnim->delay_comp_q although the request is already completed. This results in requeing the ioim into the callback queue if the ioim is not freed by the time the ioim is requeued. This results in double completion of the ioim. To fix this, whenever a response is received from firmware for an ioim, deque it from io_q and enque to fcpim->comp_q. This will eliminate any possibility of itnim picking any ioim for which the response is already received. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioim.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_ioim.c b/drivers/scsi/bfa/bfa_ioim.c index 680b87d8f0d9..4148ae09f998 100644 --- a/drivers/scsi/bfa/bfa_ioim.c +++ b/drivers/scsi/bfa/bfa_ioim.c @@ -133,6 +133,8 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_IOTOV: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_pathtov, ioim); break; @@ -182,6 +184,8 @@ bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_ABORT: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, ioim); break; @@ -189,6 +193,8 @@ bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_HWFAIL: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, ioim); break; @@ -210,18 +216,24 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) switch (event) { case BFA_IOIM_SM_COMP_GOOD: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_good_comp, ioim); break; case BFA_IOIM_SM_COMP: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp, ioim); break; case BFA_IOIM_SM_DONE: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp, ioim); break; @@ -254,6 +266,8 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_HWFAIL: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, ioim); break; @@ -287,12 +301,16 @@ bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_ABORT_COMP: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, ioim); break; case BFA_IOIM_SM_COMP_UTAG: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, ioim); break; @@ -312,6 +330,8 @@ bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_HWFAIL: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, ioim); break; @@ -365,6 +385,8 @@ bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_HWFAIL: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, ioim); break; @@ -399,6 +421,8 @@ bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_ABORT: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); bfa_reqq_wcancel(&ioim->iosp->reqq_wait); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, ioim); break; @@ -414,6 +438,8 @@ bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_HWFAIL: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); bfa_reqq_wcancel(&ioim->iosp->reqq_wait); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, ioim); break; @@ -448,6 +474,8 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_COMP: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); bfa_reqq_wcancel(&ioim->iosp->reqq_wait); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, ioim); break; @@ -455,6 +483,8 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_DONE: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free); bfa_reqq_wcancel(&ioim->iosp->reqq_wait); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, ioim); break; @@ -462,6 +492,8 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_HWFAIL: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); bfa_reqq_wcancel(&ioim->iosp->reqq_wait); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, ioim); break; @@ -511,6 +543,8 @@ bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) case BFA_IOIM_SM_HWFAIL: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); bfa_reqq_wcancel(&ioim->iosp->reqq_wait); + list_del(&ioim->qe); + list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, ioim); break; -- cgit v1.2.3 From 07b2838669dc7704e02e079b1a96602656893d78 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:59:24 -0700 Subject: [SCSI] bfa: update to support BOFM Update bfa driver API and data structure to support BOFM (IBM BladeCenter Open Fabric Manager). Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc.c | 44 +++++++++++-------------- drivers/scsi/bfa/include/bfa.h | 2 ++ drivers/scsi/bfa/include/bfi/bfi_ioc.h | 2 +- drivers/scsi/bfa/include/defs/bfa_defs_status.h | 16 +++++++-- 4 files changed, 36 insertions(+), 28 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index c4922fb995d5..8e78f20110a5 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -84,6 +84,7 @@ static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force); static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc); static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc); static void bfa_ioc_recover(struct bfa_ioc_s *ioc); +static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc); static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); @@ -429,6 +430,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event) switch (event) { case IOC_E_FWRSP_GETATTR: bfa_ioc_timer_stop(ioc); + bfa_ioc_check_attr_wwns(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_op); break; @@ -977,8 +979,13 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force) /** * If IOC function is disabled and firmware version is same, * just re-enable IOC. + * + * If option rom, IOC must not be in operational state. With + * convergence, IOC will be in operational state when 2nd driver + * is loaded. */ - if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) { + if (ioc_fwstate == BFI_IOC_DISABLED || + (!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) { bfa_trc(ioc, ioc_fwstate); /** @@ -1281,6 +1288,7 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param) bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_INITING); } + bfa_ioc_msgflush(ioc); bfa_ioc_download_fw(ioc, boot_type, boot_param); /** @@ -1788,28 +1796,17 @@ void bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model) { struct bfi_ioc_attr_s *ioc_attr; - u8 nports; - u8 max_speed; bfa_assert(model); bfa_os_memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN); ioc_attr = ioc->attr; - nports = bfa_ioc_get_nports(ioc); - max_speed = bfa_ioc_speed_sup(ioc); - /** * model name */ - if (max_speed == 10) { - strcpy(model, "BR-10?0"); - model[5] = '0' + nports; - } else { - strcpy(model, "Brocade-??5"); - model[8] = '0' + max_speed; - model[9] = '0' + nports; - } + snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u", + BFA_MFG_NAME, ioc_attr->card_type); } enum bfa_ioc_state @@ -2048,19 +2045,16 @@ bfa_ioc_recover(struct bfa_ioc_s *ioc) bfa_fsm_send_event(ioc, IOC_E_HBFAIL); } -#else - -void -bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event) -{ -} - static void -bfa_ioc_recover(struct bfa_ioc_s *ioc) +bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc) { - bfa_assert(0); + if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL) + return; + + if (ioc->attr->nwwn == 0) + bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_NWWN); + if (ioc->attr->pwwn == 0) + bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_PWWN); } #endif - - diff --git a/drivers/scsi/bfa/include/bfa.h b/drivers/scsi/bfa/include/bfa.h index 9519a6d81045..d52b32f5695c 100644 --- a/drivers/scsi/bfa/include/bfa.h +++ b/drivers/scsi/bfa/include/bfa.h @@ -126,6 +126,8 @@ struct bfa_sge_s { bfa_ioc_get_type(&(__bfa)->ioc) #define bfa_get_mac(__bfa) \ bfa_ioc_get_mac(&(__bfa)->ioc) +#define bfa_get_mfg_mac(__bfa) \ + bfa_ioc_get_mfg_mac(&(__bfa)->ioc) #define bfa_get_fw_clock_res(__bfa) \ ((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res) diff --git a/drivers/scsi/bfa/include/bfi/bfi_ioc.h b/drivers/scsi/bfa/include/bfi/bfi_ioc.h index 7c5e6d5716df..450ded6e9bc2 100644 --- a/drivers/scsi/bfa/include/bfi/bfi_ioc.h +++ b/drivers/scsi/bfa/include/bfi/bfi_ioc.h @@ -50,7 +50,7 @@ struct bfi_ioc_getattr_req_s { struct bfi_ioc_attr_s { wwn_t mfg_pwwn; /* Mfg port wwn */ wwn_t mfg_nwwn; /* Mfg node wwn */ - mac_t mfg_mac; + mac_t mfg_mac; /* Mfg mac */ u16 rsvd_a; wwn_t pwwn; wwn_t nwwn; diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h index c8bc60ad2df6..6eb4e62096fc 100644 --- a/drivers/scsi/bfa/include/defs/bfa_defs_status.h +++ b/drivers/scsi/bfa/include/defs/bfa_defs_status.h @@ -256,8 +256,20 @@ enum bfa_status { * configuration */ BFA_STATUS_DEVID_MISSING = 155, /* Boot image is not for the adapter(s) * installed */ - BFA_STATUS_BAD_FWCFG = 156, /* Bad firmware configuration */ - BFA_STATUS_MAX_VAL /* Unknown error code */ + BFA_STATUS_BAD_FWCFG = 156, /* Bad firmware configuration */ + BFA_STATUS_CREATE_FILE = 157, /* Failed to create temporary file */ + BFA_STATUS_INVALID_VENDOR = 158, /* Invalid switch vendor */ + BFA_STATUS_SFP_NOT_READY = 159, /* SFP info is not ready. Retry */ + BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 160, /* Topology command not + * applicable to CNA */ + BFA_STATUS_BOOT_CODE_UPDATED = 161, /* reboot -- -r is needed after + * boot code updated */ + BFA_STATUS_BOOT_VERSION = 162, /* Boot code version not compatible with + * the driver installed */ + BFA_STATUS_CARDTYPE_MISSING = 163, /* Boot image is not for the + * adapter(s) installed */ + BFA_STATUS_INVALID_CARDTYPE = 164, /* Invalid card type provided */ + BFA_STATUS_MAX_VAL /* Unknown error code */ }; #define bfa_status_t enum bfa_status -- cgit v1.2.3 From 604158ade0d5378622541232a007bf975c8bd03f Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 19:59:49 -0700 Subject: [SCSI] bfa: add description for module parameters Add description for bfa driver module parameters. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad.c | 33 ++++++++++++++++++++++++++++++--- drivers/scsi/bfa/bfad_intr.c | 4 ++++ 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 37f886d27922..a17800e6277d 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -54,31 +54,58 @@ static int bfa_io_max_sge = BFAD_IO_MAX_SGE; static int log_level = BFA_LOG_WARNING; static int ioc_auto_recover = BFA_TRUE; static int ipfc_enable = BFA_FALSE; -static int ipfc_mtu = -1; static int fdmi_enable = BFA_TRUE; int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH; int bfa_linkup_delay = -1; module_param(os_name, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(os_name, "OS name of the hba host machine"); module_param(os_patch, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(os_patch, "OS patch level of the hba host machine"); module_param(host_name, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(host_name, "Hostname of the hba host machine"); module_param(num_rports, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(num_rports, "Max number of rports supported per port" + " (physical/logical), default=1024"); module_param(num_ios, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(num_ios, "Max number of ioim requests, default=2000"); module_param(num_tms, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(num_tms, "Max number of task im requests, default=128"); module_param(num_fcxps, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(num_fcxps, "Max number of fcxp requests, default=64"); module_param(num_ufbufs, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame buffers," + " default=64"); module_param(reqq_size, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(reqq_size, "Max number of request queue elements," + " default=256"); module_param(rspq_size, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(rspq_size, "Max number of response queue elements," + " default=64"); module_param(num_sgpgs, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(num_sgpgs, "Number of scatter/gather pages, default=2048"); module_param(rport_del_timeout, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs," + " Range[>0]"); module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32," + " Range[>0]"); module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255"); module_param(log_level, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(log_level, "Driver log level, default=3," + " Range[Critical:1|Error:2|Warning:3|Info:4]"); module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1," + " Range[off:0|on:1]"); module_param(ipfc_enable, int, S_IRUGO | S_IWUSR); -module_param(ipfc_mtu, int, S_IRUGO | S_IWUSR); -module_param(fdmi_enable, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ipfc_enable, "Enable IPoFC, default=0, Range[off:0|on:1]"); module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for boot" + " port. Otherwise Range[>0]"); +module_param(fdmi_enable, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1," + " Range[false:0|true:1]"); /* * Stores the module parm num_sgpgs value; diff --git a/drivers/scsi/bfa/bfad_intr.c b/drivers/scsi/bfa/bfad_intr.c index fed27d163655..56a351584f0c 100644 --- a/drivers/scsi/bfa/bfad_intr.c +++ b/drivers/scsi/bfa/bfad_intr.c @@ -26,7 +26,11 @@ BFA_TRC_FILE(LDRV, INTR); static int msix_disable_cb; static int msix_disable_ct; module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(msix_disable_cb, "Disable MSIX for Brocade-415/425/815/825" + " cards, default=0, Range[false:0|true:1]"); module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(msix_disable_ct, "Disable MSIX for Brocade-1010/1020/804" + " cards, default=0, Range[false:0|true:1]"); /** * Line based interrupt handler. */ -- cgit v1.2.3 From ba8345821ac34d1630e99db7d4835db8ab20f50b Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 20:00:24 -0700 Subject: [SCSI] bfa: add ioc state checking This patch adds ioc state checking while enabling a port. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcport.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index c855e225af16..f0933d8d1eda 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -1393,6 +1393,9 @@ bfa_fcport_enable(struct bfa_s *bfa) return BFA_STATUS_PBC; } + if (bfa_ioc_is_disabled(&bfa->ioc)) + return BFA_STATUS_IOC_DISABLED; + if (fcport->diag_busy) return BFA_STATUS_DIAG_BUSY; else if (bfa_sm_cmp_state -- cgit v1.2.3 From 8a4adf1c906ee07a01cb47297130a71489f2e4f0 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 20:01:07 -0700 Subject: [SCSI] bfa: fix wrong arg to callback This patch fixes the issue of passing wrong argument to callback function. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index 6773e2282ddc..c7e69f1e56e3 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -407,7 +407,7 @@ bfa_port_hbfail(void *arg) */ if (port->stats_busy) { if (port->stats_cbfn) - port->stats_cbfn(port->dev, BFA_STATUS_FAILED); + port->stats_cbfn(port->stats_cbarg, BFA_STATUS_FAILED); port->stats_cbfn = NULL; port->stats_busy = BFA_FALSE; } @@ -417,7 +417,7 @@ bfa_port_hbfail(void *arg) */ if (port->endis_pending) { if (port->endis_cbfn) - port->endis_cbfn(port->dev, BFA_STATUS_FAILED); + port->endis_cbfn(port->endis_cbarg, BFA_STATUS_FAILED); port->endis_cbfn = NULL; port->endis_pending = BFA_FALSE; } -- cgit v1.2.3 From c54d557c3f6a7bbf833a8f9cffad88f34513a7c4 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 20:01:49 -0700 Subject: [SCSI] bfa: vport fixes This patch fixes 3 bugs in vport create/delete. 1) Replace scsi_add_host() with scsi_add_host_with_dma() 2) Fix rmmod hang when there are vports configured. This is due to a race condition between the workqueue destroy in pci remove context and the vport delete works being handled. The fix is to use a counter to track the vport delete work, so that workqueue destroy will not be called until all configured vports are deleted from workqueue. 3) Fix rmmmod crash when there are PBC vport configured. PBC is not allowed to be deleted dynamically. However, if someone try to delete it, it leaves the vport is wrong state. The fix is to restore the vport back to original state when the attempt to delete pbc vport delete is failed. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad_attr.c | 5 ++++- drivers/scsi/bfa/bfad_drv.h | 1 + drivers/scsi/bfa/bfad_im.c | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 871a30363560..0818eb07ef88 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -473,8 +473,11 @@ bfad_im_vport_delete(struct fc_vport *fc_vport) rc = bfa_fcs_vport_delete(&vport->fcs_vport); spin_unlock_irqrestore(&bfad->bfad_lock, flags); - if (rc == BFA_STATUS_PBC) + if (rc == BFA_STATUS_PBC) { + vport->drv_port.flags &= ~BFAD_PORT_DELETE; + vport->comp_del = NULL; return -1; + } wait_for_completion(vport->comp_del); diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 8629f64a5287..dcf28830feef 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -185,6 +185,7 @@ struct bfad_s { bfa_boolean_t ipfc_enabled; struct fc_host_statistics link_stats; struct list_head pbc_pcfg_list; + atomic_t wq_reqcnt; }; struct bfad_pcfg_s { diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index ffbec9ba21b7..678120b70460 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -554,7 +554,7 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port, im_port->shost->transportt = bfad_im_scsi_vport_transport_template; - error = scsi_add_host(im_port->shost, dev); + error = scsi_add_host_with_dma(im_port->shost, dev, &bfad->pcidev->dev); if (error) { printk(KERN_WARNING "scsi_add_host failure %d\n", error); goto out_fc_rel; @@ -598,10 +598,12 @@ bfad_im_port_delete_handler(struct work_struct *work) { struct bfad_im_port_s *im_port = container_of(work, struct bfad_im_port_s, port_delete_work); + struct bfad_s *bfad = im_port->bfad; if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) { im_port->flags |= BFAD_PORT_DELETE; fc_vport_terminate(im_port->fc_vport); + atomic_dec(&bfad->wq_reqcnt); } } @@ -634,8 +636,11 @@ bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port) { struct bfad_im_port_s *im_port = port->im_port; - queue_work(bfad->im->drv_workq, + if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) { + atomic_inc(&bfad->wq_reqcnt); + queue_work(bfad->im->drv_workq, &im_port->port_delete_work); + } } void @@ -696,6 +701,12 @@ void bfad_im_probe_undo(struct bfad_s *bfad) { if (bfad->im) { + while (atomic_read(&bfad->wq_reqcnt)) { + printk(KERN_INFO "bfa %s: waiting workq processing," + " wq_reqcnt:%x\n", bfad->pci_name, + atomic_read(&bfad->wq_reqcnt)); + schedule_timeout_uninterruptible(HZ); + } bfad_os_destroy_workq(bfad->im); kfree(bfad->im); bfad->im = NULL; -- cgit v1.2.3 From 08a17ced7a78064f4f03de7d68b8cd32581f0510 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 20:02:31 -0700 Subject: [SCSI] bfa: update driver version string Update driver version to 2.2.2.1 Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index dcf28830feef..fb6ac1d3fd17 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -46,7 +46,7 @@ #ifdef BFA_DRIVER_VERSION #define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION #else -#define BFAD_DRIVER_VERSION "2.1.2.1" +#define BFAD_DRIVER_VERSION "2.2.2.1" #endif -- cgit v1.2.3 From ab2a9ba189e889b3e8990e52e90d2cd9606b2aa1 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Thu, 8 Jul 2010 20:02:55 -0700 Subject: [SCSI] bfa: add debugfs support - Add debugfs support to obtain firmware trace, driver trace and read/write to registers. - debugfs hierarchy: /sys/kernel/debug/bfa/host# where the host number corresponds to the one under /sys/class/scsi_host/host# - Following are the new debugfs entries added: drvtrc: collect current driver trace fwtrc: collect current firmware trace. fwsave: collect last saved fw trace as a result of firmware crash. regwr: write one word to chip register regrd: read one or more words from chip register. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/Makefile | 2 +- drivers/scsi/bfa/bfad.c | 12 + drivers/scsi/bfa/bfad_debugfs.c | 547 ++++++++++++++++++++++++++++++++++++++++ drivers/scsi/bfa/bfad_drv.h | 12 +- 4 files changed, 571 insertions(+), 2 deletions(-) create mode 100644 drivers/scsi/bfa/bfad_debugfs.c (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile index 17e06cae71b2..ac3fdf02d5f6 100644 --- a/drivers/scsi/bfa/Makefile +++ b/drivers/scsi/bfa/Makefile @@ -1,7 +1,7 @@ obj-$(CONFIG_SCSI_BFA_FC) := bfa.o bfa-y := bfad.o bfad_intr.o bfad_os.o bfad_im.o bfad_attr.o bfad_fwimg.o - +bfa-y += bfad_debugfs.o bfa-y += bfa_core.o bfa_ioc.o bfa_ioc_ct.o bfa_ioc_cb.o bfa_iocfc.o bfa_fcxp.o bfa-y += bfa_lps.o bfa_hw_cb.o bfa_hw_ct.o bfa_intr.o bfa_timer.o bfa_rport.o bfa-y += bfa_fcport.o bfa_port.o bfa_uf.o bfa_sgpg.o bfa_module.o bfa_ioim.o diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index a17800e6277d..915a29d6c7ad 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -57,6 +57,7 @@ static int ipfc_enable = BFA_FALSE; static int fdmi_enable = BFA_TRUE; int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH; int bfa_linkup_delay = -1; +int bfa_debugfs_enable = 1; module_param(os_name, charp, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(os_name, "OS name of the hba host machine"); @@ -106,6 +107,9 @@ MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for boot" module_param(fdmi_enable, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1," " Range[false:0|true:1]"); +module_param(bfa_debugfs_enable, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1," + " Range[false:0|true:1]"); /* * Stores the module parm num_sgpgs value; @@ -903,6 +907,10 @@ bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role) bfad->pport.roles |= BFA_PORT_ROLE_FCP_IM; } + /* Setup the debugfs node for this scsi_host */ + if (bfa_debugfs_enable) + bfad_debugfs_init(&bfad->pport); + bfad->bfad_flags |= BFAD_CFG_PPORT_DONE; out: @@ -912,6 +920,10 @@ out: void bfad_uncfg_pport(struct bfad_s *bfad) { + /* Remove the debugfs node for this scsi_host */ + kfree(bfad->regdata); + bfad_debugfs_exit(&bfad->pport); + if ((bfad->pport.roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) { bfad_ipfc_port_delete(bfad, &bfad->pport); bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IPFC; diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c new file mode 100644 index 000000000000..4b82f12aad62 --- /dev/null +++ b/drivers/scsi/bfa/bfad_debugfs.c @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + * + * Linux driver for Brocade Fibre Channel Host Bus Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include + +#include +#include + +/* + * BFA debufs interface + * + * To access the interface, debugfs file system should be mounted + * if not already mounted using: + * mount -t debugfs none /sys/kernel/debug + * + * BFA Hierarchy: + * - bfa/host# + * where the host number corresponds to the one under /sys/class/scsi_host/host# + * + * Debugging service available per host: + * fwtrc: To collect current firmware trace. + * drvtrc: To collect current driver trace + * fwsave: To collect last saved fw trace as a result of firmware crash. + * regwr: To write one word to chip register + * regrd: To read one or more words from chip register. + */ + +struct bfad_debug_info { + char *debug_buffer; + void *i_private; + int buffer_len; +}; + +static int +bfad_debugfs_open_drvtrc(struct inode *inode, struct file *file) +{ + struct bfad_port_s *port = inode->i_private; + struct bfad_s *bfad = port->bfad; + struct bfad_debug_info *debug; + + debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL); + if (!debug) + return -ENOMEM; + + debug->debug_buffer = (void *) bfad->trcmod; + debug->buffer_len = sizeof(struct bfa_trc_mod_s); + + file->private_data = debug; + + return 0; +} + +static int +bfad_debugfs_open_fwtrc(struct inode *inode, struct file *file) +{ + struct bfad_port_s *port = inode->i_private; + struct bfad_s *bfad = port->bfad; + struct bfad_debug_info *fw_debug; + unsigned long flags; + int rc; + + fw_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL); + if (!fw_debug) + return -ENOMEM; + + fw_debug->buffer_len = sizeof(struct bfa_trc_mod_s); + + fw_debug->debug_buffer = vmalloc(fw_debug->buffer_len); + if (!fw_debug->debug_buffer) { + kfree(fw_debug); + printk(KERN_INFO "bfad[%d]: Failed to allocate fwtrc buffer\n", + bfad->inst_no); + return -ENOMEM; + } + + memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len); + + spin_lock_irqsave(&bfad->bfad_lock, flags); + rc = bfa_debug_fwtrc(&bfad->bfa, + fw_debug->debug_buffer, + &fw_debug->buffer_len); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + if (rc != BFA_STATUS_OK) { + vfree(fw_debug->debug_buffer); + fw_debug->debug_buffer = NULL; + kfree(fw_debug); + printk(KERN_INFO "bfad[%d]: Failed to collect fwtrc\n", + bfad->inst_no); + return -ENOMEM; + } + + file->private_data = fw_debug; + + return 0; +} + +static int +bfad_debugfs_open_fwsave(struct inode *inode, struct file *file) +{ + struct bfad_port_s *port = inode->i_private; + struct bfad_s *bfad = port->bfad; + struct bfad_debug_info *fw_debug; + unsigned long flags; + int rc; + + fw_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL); + if (!fw_debug) + return -ENOMEM; + + fw_debug->buffer_len = sizeof(struct bfa_trc_mod_s); + + fw_debug->debug_buffer = vmalloc(fw_debug->buffer_len); + if (!fw_debug->debug_buffer) { + kfree(fw_debug); + printk(KERN_INFO "bfad[%d]: Failed to allocate fwsave buffer\n", + bfad->inst_no); + return -ENOMEM; + } + + memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len); + + spin_lock_irqsave(&bfad->bfad_lock, flags); + rc = bfa_debug_fwsave(&bfad->bfa, + fw_debug->debug_buffer, + &fw_debug->buffer_len); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + if (rc != BFA_STATUS_OK) { + vfree(fw_debug->debug_buffer); + fw_debug->debug_buffer = NULL; + kfree(fw_debug); + printk(KERN_INFO "bfad[%d]: Failed to collect fwsave\n", + bfad->inst_no); + return -ENOMEM; + } + + file->private_data = fw_debug; + + return 0; +} + +static int +bfad_debugfs_open_reg(struct inode *inode, struct file *file) +{ + struct bfad_debug_info *reg_debug; + + reg_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL); + if (!reg_debug) + return -ENOMEM; + + reg_debug->i_private = inode->i_private; + + file->private_data = reg_debug; + + return 0; +} + +/* Changes the current file position */ +static loff_t +bfad_debugfs_lseek(struct file *file, loff_t offset, int orig) +{ + struct bfad_debug_info *debug; + loff_t pos = file->f_pos; + + debug = file->private_data; + + switch (orig) { + case 0: + file->f_pos = offset; + break; + case 1: + file->f_pos += offset; + break; + case 2: + file->f_pos = debug->buffer_len - offset; + break; + default: + return -EINVAL; + } + + if (file->f_pos < 0 || file->f_pos > debug->buffer_len) { + file->f_pos = pos; + return -EINVAL; + } + + return file->f_pos; +} + +static ssize_t +bfad_debugfs_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *pos) +{ + struct bfad_debug_info *debug = file->private_data; + + if (!debug || !debug->debug_buffer) + return 0; + + return memory_read_from_buffer(buf, nbytes, pos, + debug->debug_buffer, debug->buffer_len); +} + +#define BFA_REG_CT_ADDRSZ (0x40000) +#define BFA_REG_CB_ADDRSZ (0x20000) +#define BFA_REG_ADDRSZ(__bfa) \ + ((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ? \ + BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ) +#define BFA_REG_ADDRMSK(__bfa) ((uint32_t)(BFA_REG_ADDRSZ(__bfa) - 1)) + +static bfa_status_t +bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len) +{ + u8 area; + + /* check [16:15] */ + area = (offset >> 15) & 0x7; + if (area == 0) { + /* PCIe core register */ + if ((offset + (len<<2)) > 0x8000) /* 8k dwords or 32KB */ + return BFA_STATUS_EINVAL; + } else if (area == 0x1) { + /* CB 32 KB memory page */ + if ((offset + (len<<2)) > 0x10000) /* 8k dwords or 32KB */ + return BFA_STATUS_EINVAL; + } else { + /* CB register space 64KB */ + if ((offset + (len<<2)) > BFA_REG_ADDRMSK(bfa)) + return BFA_STATUS_EINVAL; + } + return BFA_STATUS_OK; +} + +static ssize_t +bfad_debugfs_read_regrd(struct file *file, char __user *buf, + size_t nbytes, loff_t *pos) +{ + struct bfad_debug_info *regrd_debug = file->private_data; + struct bfad_port_s *port = (struct bfad_port_s *)regrd_debug->i_private; + struct bfad_s *bfad = port->bfad; + ssize_t rc; + + if (!bfad->regdata) + return 0; + + rc = memory_read_from_buffer(buf, nbytes, pos, + bfad->regdata, bfad->reglen); + + if ((*pos + nbytes) >= bfad->reglen) { + kfree(bfad->regdata); + bfad->regdata = NULL; + bfad->reglen = 0; + } + + return rc; +} + +static ssize_t +bfad_debugfs_write_regrd(struct file *file, const char __user *buf, + size_t nbytes, loff_t *ppos) +{ + struct bfad_debug_info *regrd_debug = file->private_data; + struct bfad_port_s *port = (struct bfad_port_s *)regrd_debug->i_private; + struct bfad_s *bfad = port->bfad; + struct bfa_s *bfa = &bfad->bfa; + struct bfa_ioc_s *ioc = &bfa->ioc; + int addr, len, rc, i; + u32 *regbuf; + void __iomem *rb, *reg_addr; + unsigned long flags; + + rc = sscanf(buf, "%x:%x", &addr, &len); + if (rc < 2) { + printk(KERN_INFO + "bfad[%d]: %s failed to read user buf\n", + bfad->inst_no, __func__); + return -EINVAL; + } + + kfree(bfad->regdata); + bfad->regdata = NULL; + bfad->reglen = 0; + + bfad->regdata = kzalloc(len << 2, GFP_KERNEL); + if (!bfad->regdata) { + printk(KERN_INFO "bfad[%d]: Failed to allocate regrd buffer\n", + bfad->inst_no); + return -ENOMEM; + } + + bfad->reglen = len << 2; + rb = bfa_ioc_bar0(ioc); + addr &= BFA_REG_ADDRMSK(bfa); + + /* offset and len sanity check */ + rc = bfad_reg_offset_check(bfa, addr, len); + if (rc) { + printk(KERN_INFO "bfad[%d]: Failed reg offset check\n", + bfad->inst_no); + kfree(bfad->regdata); + bfad->regdata = NULL; + bfad->reglen = 0; + return -EINVAL; + } + + reg_addr = rb + addr; + regbuf = (u32 *)bfad->regdata; + spin_lock_irqsave(&bfad->bfad_lock, flags); + for (i = 0; i < len; i++) { + *regbuf = bfa_reg_read(reg_addr); + regbuf++; + reg_addr += sizeof(u32); + } + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + + return nbytes; +} + +static ssize_t +bfad_debugfs_write_regwr(struct file *file, const char __user *buf, + size_t nbytes, loff_t *ppos) +{ + struct bfad_debug_info *debug = file->private_data; + struct bfad_port_s *port = (struct bfad_port_s *)debug->i_private; + struct bfad_s *bfad = port->bfad; + struct bfa_s *bfa = &bfad->bfa; + struct bfa_ioc_s *ioc = &bfa->ioc; + int addr, val, rc; + void __iomem *reg_addr; + unsigned long flags; + + rc = sscanf(buf, "%x:%x", &addr, &val); + if (rc < 2) { + printk(KERN_INFO + "bfad[%d]: %s failed to read user buf\n", + bfad->inst_no, __func__); + return -EINVAL; + } + + addr &= BFA_REG_ADDRMSK(bfa); /* offset only 17 bit and word align */ + + /* offset and len sanity check */ + rc = bfad_reg_offset_check(bfa, addr, 1); + if (rc) { + printk(KERN_INFO + "bfad[%d]: Failed reg offset check\n", + bfad->inst_no); + return -EINVAL; + } + + reg_addr = (uint32_t *) ((uint8_t *) bfa_ioc_bar0(ioc) + addr); + spin_lock_irqsave(&bfad->bfad_lock, flags); + bfa_reg_write(reg_addr, val); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + + return nbytes; +} + +static int +bfad_debugfs_release(struct inode *inode, struct file *file) +{ + struct bfad_debug_info *debug = file->private_data; + + if (!debug) + return 0; + + file->private_data = NULL; + kfree(debug); + return 0; +} + +static int +bfad_debugfs_release_fwtrc(struct inode *inode, struct file *file) +{ + struct bfad_debug_info *fw_debug = file->private_data; + + if (!fw_debug) + return 0; + + if (fw_debug->debug_buffer) + vfree(fw_debug->debug_buffer); + + file->private_data = NULL; + kfree(fw_debug); + return 0; +} + +static const struct file_operations bfad_debugfs_op_drvtrc = { + .owner = THIS_MODULE, + .open = bfad_debugfs_open_drvtrc, + .llseek = bfad_debugfs_lseek, + .read = bfad_debugfs_read, + .release = bfad_debugfs_release, +}; + +static const struct file_operations bfad_debugfs_op_fwtrc = { + .owner = THIS_MODULE, + .open = bfad_debugfs_open_fwtrc, + .llseek = bfad_debugfs_lseek, + .read = bfad_debugfs_read, + .release = bfad_debugfs_release_fwtrc, +}; + +static const struct file_operations bfad_debugfs_op_fwsave = { + .owner = THIS_MODULE, + .open = bfad_debugfs_open_fwsave, + .llseek = bfad_debugfs_lseek, + .read = bfad_debugfs_read, + .release = bfad_debugfs_release_fwtrc, +}; + +static const struct file_operations bfad_debugfs_op_regrd = { + .owner = THIS_MODULE, + .open = bfad_debugfs_open_reg, + .llseek = bfad_debugfs_lseek, + .read = bfad_debugfs_read_regrd, + .write = bfad_debugfs_write_regrd, + .release = bfad_debugfs_release, +}; + +static const struct file_operations bfad_debugfs_op_regwr = { + .owner = THIS_MODULE, + .open = bfad_debugfs_open_reg, + .llseek = bfad_debugfs_lseek, + .write = bfad_debugfs_write_regwr, + .release = bfad_debugfs_release, +}; + +struct bfad_debugfs_entry { + const char *name; + mode_t mode; + const struct file_operations *fops; +}; + +static const struct bfad_debugfs_entry bfad_debugfs_files[] = { + { "drvtrc", S_IFREG|S_IRUGO, &bfad_debugfs_op_drvtrc, }, + { "fwtrc", S_IFREG|S_IRUGO, &bfad_debugfs_op_fwtrc, }, + { "fwsave", S_IFREG|S_IRUGO, &bfad_debugfs_op_fwsave, }, + { "regrd", S_IFREG|S_IRUGO|S_IWUSR, &bfad_debugfs_op_regrd, }, + { "regwr", S_IFREG|S_IWUSR, &bfad_debugfs_op_regwr, }, +}; + +static struct dentry *bfa_debugfs_root; +static atomic_t bfa_debugfs_port_count; + +inline void +bfad_debugfs_init(struct bfad_port_s *port) +{ + struct bfad_im_port_s *im_port = port->im_port; + struct bfad_s *bfad = im_port->bfad; + struct Scsi_Host *shost = im_port->shost; + const struct bfad_debugfs_entry *file; + char name[16]; + int i; + + if (!bfa_debugfs_enable) + return; + + /* Setup the BFA debugfs root directory*/ + if (!bfa_debugfs_root) { + bfa_debugfs_root = debugfs_create_dir("bfa", NULL); + atomic_set(&bfa_debugfs_port_count, 0); + if (!bfa_debugfs_root) { + printk(KERN_WARNING + "BFA debugfs root dir creation failed\n"); + goto err; + } + } + + /* + * Setup the host# directory for the port, + * corresponds to the scsi_host num of this port. + */ + snprintf(name, sizeof(name), "host%d", shost->host_no); + if (!port->port_debugfs_root) { + port->port_debugfs_root = + debugfs_create_dir(name, bfa_debugfs_root); + if (!port->port_debugfs_root) { + printk(KERN_WARNING + "BFA host root dir creation failed\n"); + goto err; + } + + atomic_inc(&bfa_debugfs_port_count); + + for (i = 0; i < ARRAY_SIZE(bfad_debugfs_files); i++) { + file = &bfad_debugfs_files[i]; + bfad->bfad_dentry_files[i] = + debugfs_create_file(file->name, + file->mode, + port->port_debugfs_root, + port, + file->fops); + if (!bfad->bfad_dentry_files[i]) { + printk(KERN_WARNING + "BFA host%d: create %s entry failed\n", + shost->host_no, file->name); + goto err; + } + } + } + +err: + return; +} + +inline void +bfad_debugfs_exit(struct bfad_port_s *port) +{ + struct bfad_im_port_s *im_port = port->im_port; + struct bfad_s *bfad = im_port->bfad; + int i; + + for (i = 0; i < ARRAY_SIZE(bfad_debugfs_files); i++) { + if (bfad->bfad_dentry_files[i]) { + debugfs_remove(bfad->bfad_dentry_files[i]); + bfad->bfad_dentry_files[i] = NULL; + } + } + + /* + * Remove the host# directory for the port, + * corresponds to the scsi_host num of this port. + */ + if (port->port_debugfs_root) { + debugfs_remove(port->port_debugfs_root); + port->port_debugfs_root = NULL; + atomic_dec(&bfa_debugfs_port_count); + } + + /* Remove the BFA debugfs root directory */ + if (atomic_read(&bfa_debugfs_port_count) == 0) { + debugfs_remove(bfa_debugfs_root); + bfa_debugfs_root = NULL; + } +} diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index fb6ac1d3fd17..465b8b86ec9c 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -111,6 +111,9 @@ struct bfad_port_s { struct bfad_im_port_s *im_port; /* IM specific data */ struct bfad_tm_port_s *tm_port; /* TM specific data */ struct bfad_ipfc_port_s *ipfc_port; /* IPFC specific data */ + + /* port debugfs specific data */ + struct dentry *port_debugfs_root; }; /* @@ -186,6 +189,10 @@ struct bfad_s { struct fc_host_statistics link_stats; struct list_head pbc_pcfg_list; atomic_t wq_reqcnt; + /* debugfs specific data */ + char *regdata; + u32 reglen; + struct dentry *bfad_dentry_files[5]; }; struct bfad_pcfg_s { @@ -276,7 +283,9 @@ void bfad_drv_uninit(struct bfad_s *bfad); void bfad_drv_log_level_set(struct bfad_s *bfad); bfa_status_t bfad_fc4_module_init(void); void bfad_fc4_module_exit(void); -int bfad_worker (void *ptr); +int bfad_worker(void *ptr); +void bfad_debugfs_init(struct bfad_port_s *port); +void bfad_debugfs_exit(struct bfad_port_s *port); void bfad_pci_remove(struct pci_dev *pdev); int bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid); @@ -289,6 +298,7 @@ extern struct list_head bfad_list; extern int bfa_lun_queue_depth; extern int bfad_supported_fc4s; extern int bfa_linkup_delay; +extern int bfa_debugfs_enable; extern struct mutex bfad_mutex; #endif /* __BFAD_DRV_H__ */ -- cgit v1.2.3 From e349fa35363fa96f11addecb67e0f8a6edfb0e3a Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Sat, 10 Jul 2010 14:48:36 +0530 Subject: [SCSI] qla4xxx: set driver ddb state correctly in process_ddb_changed If fw ddb state is ACTIVE mark driver ddb stat as ONLINE and unblock iscsi session. Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 5510df8a7fa6..8947743e54d7 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -1487,7 +1487,10 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, ddb_entry->fw_ddb_device_state, state, fw_ddb_index)); if (old_fw_ddb_device_state == state && state == DDB_DS_SESSION_ACTIVE) { - /* Do nothing, state not changed. */ + if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { + atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); + iscsi_unblock_session(ddb_entry->sess); + } return QLA_SUCCESS; } -- cgit v1.2.3 From 363863256a711819130ea4ac210ee001bc80c3b2 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Sat, 10 Jul 2010 14:49:01 +0530 Subject: [SCSI] qla4xxx: unblock iscsi session after setting ddb state online. Once the device goes *missing*, driver blocks the session ie iscsi_block_session() to stall the I/O. So after device comes back *online*, driver needs to unblock the session ie iscsi_unblock_session(), else I/Os will fail even if ddb_state is ONLINE. Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 8947743e54d7..16565226f55c 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -993,6 +993,7 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha) DEBUG2(printk ("scsi%ld: %s: ddb index [%d] marked " "ONLINE\n", ha->host_no, __func__, ddb_entry->fw_ddb_index)); + iscsi_unblock_session(ddb_entry->sess); } else if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) qla4xxx_mark_device_missing(ha, ddb_entry); } -- cgit v1.2.3 From b966346c344f592c8e6a84c9c274a7dedbc057ad Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Sat, 10 Jul 2010 14:49:19 +0530 Subject: [SCSI] qla4xxx: correct return status in function qla4xxx_fw_ready Handle fw_state "auto discovery in progress" correctly to avoid marking adapter as offline. Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 16565226f55c..d5254054b2c8 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -399,6 +399,7 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) DEBUG2(printk("scsi%ld: %s: FW initialized, but " "auto-discovery still in process\n", ha->host_no, __func__)); + ready = 1; } return ready; -- cgit v1.2.3 From beabe7c18338a5112fbca9a6dbcc921f9cce6325 Mon Sep 17 00:00:00 2001 From: Prasanna Mumbai Date: Sat, 10 Jul 2010 14:49:38 +0530 Subject: [SCSI] qla4xxx: Fix the freeing of the buffer allocated for DMA Fixed the DMA allocated memory freeing which wasn't taken care in many cases. Signed-off-by: Prasanna Mumbai Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 38 ++++++++++++++++++++++++-------------- drivers/scsi/qla4xxx/ql4_mbx.c | 15 ++++++++------- 2 files changed, 32 insertions(+), 21 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index d5254054b2c8..4a332c32d71e 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -444,17 +444,17 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, if (fw_ddb_entry == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); - return NULL; + goto exit_get_ddb_entry_no_free; } if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, fw_ddb_entry_dma, NULL, NULL, &device_state, NULL, NULL, NULL) == - QLA_ERROR) { + QLA_ERROR) { DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for " "fw_ddb_index %d\n", ha->host_no, __func__, fw_ddb_index)); - return NULL; + goto exit_get_ddb_entry; } /* Allocate DDB if not already allocated. */ @@ -472,6 +472,7 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, } } + /* if not found allocate new ddb */ if (!found) { DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating " "new ddb\n", ha->host_no, __func__, @@ -480,10 +481,11 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); } - /* if not found allocate new ddb */ +exit_get_ddb_entry: dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, fw_ddb_entry_dma); +exit_get_ddb_entry_no_free: return ddb_entry; } @@ -511,7 +513,8 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, if (ddb_entry == NULL) { DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no, __func__)); - goto exit_update_ddb; + + goto exit_update_ddb_no_free; } /* Make sure the dma buffer is valid */ @@ -522,7 +525,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); - goto exit_update_ddb; + goto exit_update_ddb_no_free; } if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, @@ -530,7 +533,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, &ddb_entry->fw_ddb_device_state, &conn_err, &ddb_entry->tcp_source_port_num, &ddb_entry->connection_id) == - QLA_ERROR) { + QLA_ERROR) { DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for " "fw_ddb_index %d\n", ha->host_no, __func__, fw_ddb_index)); @@ -605,6 +608,7 @@ exit_update_ddb: dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, fw_ddb_entry_dma); +exit_update_ddb_no_free: return status; } @@ -689,7 +693,7 @@ int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err) **/ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) { - int status = QLA_SUCCESS; + int status = QLA_ERROR; uint32_t fw_ddb_index = 0; uint32_t next_fw_ddb_index = 0; uint32_t ddb_state; @@ -705,7 +709,8 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) if (fw_ddb_entry == NULL) { DEBUG2(dev_info(&ha->pdev->dev, "%s: DMA alloc failed\n", __func__)); - return QLA_ERROR; + + goto exit_build_ddb_list_no_free; } dev_info(&ha->pdev->dev, "Initializing DDBs ...\n"); @@ -720,7 +725,7 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) DEBUG2(printk("scsi%ld: %s: get_ddb_entry, " "fw_ddb_index %d failed", ha->host_no, __func__, fw_ddb_index)); - return QLA_ERROR; + goto exit_build_ddb_list; } DEBUG2(printk("scsi%ld: %s: Getting DDB[%d] ddbstate=0x%x, " @@ -750,7 +755,7 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) "get_ddb_entry %d failed\n", ha->host_no, __func__, fw_ddb_index)); - return QLA_ERROR; + goto exit_build_ddb_list; } } } @@ -770,7 +775,7 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) DEBUG2(printk("scsi%ld: %s: Unable to allocate memory " "for device at fw_ddb_index %d\n", ha->host_no, __func__, fw_ddb_index)); - return QLA_ERROR; + goto exit_build_ddb_list; } /* Fill in the device structure */ if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) == @@ -778,11 +783,10 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) ha->fw_ddb_index_map[fw_ddb_index] = (struct ddb_entry *)INVALID_ENTRY; - DEBUG2(printk("scsi%ld: %s: update_ddb_entry failed " "for fw_ddb_index %d.\n", ha->host_no, __func__, fw_ddb_index)); - return QLA_ERROR; + goto exit_build_ddb_list; } next_one: @@ -792,8 +796,14 @@ next_one: break; } + status = QLA_SUCCESS; dev_info(&ha->pdev->dev, "DDB list done..\n"); +exit_build_ddb_list: + dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, + fw_ddb_entry_dma); + +exit_build_ddb_list_no_free: return status; } diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 75496fb0ae75..54db6cbbd942 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -317,7 +317,7 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) if (init_fw_cb == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no, __func__)); - return 10; + goto exit_init_fw_cb_no_free; } memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk)); @@ -373,7 +373,7 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) exit_init_fw_cb: dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), init_fw_cb, init_fw_cb_dma); - +exit_init_fw_cb_no_free: return status; } @@ -394,7 +394,7 @@ int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha) if (init_fw_cb == NULL) { printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no, __func__); - return 10; + return QLA_ERROR; } /* Get Initialize Firmware Control Block. */ @@ -1019,16 +1019,16 @@ int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port) DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); ret_val = QLA_ERROR; - goto qla4xxx_send_tgts_exit; + goto exit_send_tgts_no_free; } ret_val = qla4xxx_get_default_ddb(ha, fw_ddb_entry_dma); if (ret_val != QLA_SUCCESS) - goto qla4xxx_send_tgts_exit; + goto exit_send_tgts; ret_val = qla4xxx_req_ddb_entry(ha, &ddb_index); if (ret_val != QLA_SUCCESS) - goto qla4xxx_send_tgts_exit; + goto exit_send_tgts; memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias)); @@ -1050,9 +1050,10 @@ int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port) ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma); -qla4xxx_send_tgts_exit: +exit_send_tgts: dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, fw_ddb_entry_dma); +exit_send_tgts_no_free: return ret_val; } -- cgit v1.2.3 From dbaf82ece08bf93ae5200f03efd87c4f1fc453f1 Mon Sep 17 00:00:00 2001 From: Ravi Anand Date: Sat, 10 Jul 2010 14:50:32 +0530 Subject: [SCSI] qla4xxx: Handle one H/W Interrupt at a time Handle one H/W Interrupt at a time to prevent holding off H/W lock for longer period of time. Signed-off-by: Ravi Anand Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 428802616e33..3e1c990f5e20 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -118,7 +118,7 @@ #define DRIVER_NAME "qla4xxx" #define MAX_LINKED_CMDS_PER_LUN 3 -#define MAX_REQS_SERVICED_PER_INTR 16 +#define MAX_REQS_SERVICED_PER_INTR 1 #define ISCSI_IPADDR_SIZE 4 /* IP address size */ #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ -- cgit v1.2.3 From f4f5df23bf72208d0c2f1d8be629839924c2f4c2 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Wed, 28 Jul 2010 15:53:44 +0530 Subject: [SCSI] qla4xxx: Added support for ISP82XX Signed-off-by: Vikas Chaudhary Signed-off-by: Karen Higgins Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/Kconfig | 8 +- drivers/scsi/qla4xxx/Makefile | 2 +- drivers/scsi/qla4xxx/ql4_def.h | 141 ++- drivers/scsi/qla4xxx/ql4_fw.h | 139 ++- drivers/scsi/qla4xxx/ql4_glbl.h | 106 +- drivers/scsi/qla4xxx/ql4_init.c | 136 ++- drivers/scsi/qla4xxx/ql4_inline.h | 2 +- drivers/scsi/qla4xxx/ql4_iocb.c | 73 +- drivers/scsi/qla4xxx/ql4_isr.c | 388 ++++++- drivers/scsi/qla4xxx/ql4_mbx.c | 172 ++- drivers/scsi/qla4xxx/ql4_nvram.c | 2 +- drivers/scsi/qla4xxx/ql4_nvram.h | 10 +- drivers/scsi/qla4xxx/ql4_nx.c | 2321 +++++++++++++++++++++++++++++++++++++ drivers/scsi/qla4xxx/ql4_nx.h | 779 +++++++++++++ drivers/scsi/qla4xxx/ql4_os.c | 678 ++++++++--- 15 files changed, 4600 insertions(+), 357 deletions(-) create mode 100644 drivers/scsi/qla4xxx/ql4_nx.c create mode 100644 drivers/scsi/qla4xxx/ql4_nx.h (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig index 69cbff3f57cf..2c33ce6eac1e 100644 --- a/drivers/scsi/qla4xxx/Kconfig +++ b/drivers/scsi/qla4xxx/Kconfig @@ -1,7 +1,7 @@ config SCSI_QLA_ISCSI - tristate "QLogic ISP4XXX host adapter family support" - depends on PCI && SCSI && NET + tristate "QLogic ISP4XXX and ISP82XX host adapter family support" + depends on PCI && SCSI select SCSI_ISCSI_ATTRS ---help--- - This driver supports the QLogic 40xx (ISP4XXX) iSCSI host - adapter family. + This driver supports the QLogic 40xx (ISP4XXX) and 8022 (ISP82XX) + iSCSI host adapter family. diff --git a/drivers/scsi/qla4xxx/Makefile b/drivers/scsi/qla4xxx/Makefile index 86ea37baa0fc..0339ff03a535 100644 --- a/drivers/scsi/qla4xxx/Makefile +++ b/drivers/scsi/qla4xxx/Makefile @@ -1,5 +1,5 @@ qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \ - ql4_nvram.o ql4_dbg.o + ql4_nx.o ql4_nvram.o ql4_dbg.o obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 3e1c990f5e20..a79da8dd2064 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -33,6 +33,8 @@ #include #include +#include "ql4_dbg.h" +#include "ql4_nx.h" #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 @@ -46,6 +48,10 @@ #define PCI_DEVICE_ID_QLOGIC_ISP4032 0x4032 #endif +#ifndef PCI_DEVICE_ID_QLOGIC_ISP8022 +#define PCI_DEVICE_ID_QLOGIC_ISP8022 0x8022 +#endif + #define QLA_SUCCESS 0 #define QLA_ERROR 1 @@ -85,15 +91,22 @@ #define BIT_30 0x40000000 #define BIT_31 0x80000000 +/** + * Macros to help code, maintain, etc. + **/ +#define ql4_printk(level, ha, format, arg...) \ + dev_printk(level , &((ha)->pdev->dev) , format , ## arg) + + /* * Host adapter default definitions ***********************************/ #define MAX_HBAS 16 #define MAX_BUSES 1 -#define MAX_TARGETS (MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES) +#define MAX_TARGETS MAX_DEV_DB_ENTRIES #define MAX_LUNS 0xffff #define MAX_AEN_ENTRIES 256 /* should be > EXT_DEF_MAX_AEN_QUEUE */ -#define MAX_DDB_ENTRIES (MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES) +#define MAX_DDB_ENTRIES MAX_DEV_DB_ENTRIES #define MAX_PDU_ENTRIES 32 #define INVALID_ENTRY 0xFFFF #define MAX_CMDS_TO_RISC 1024 @@ -134,7 +147,7 @@ #define SOFT_RESET_TOV 30 #define RESET_INTR_TOV 3 #define SEMAPHORE_TOV 10 -#define ADAPTER_INIT_TOV 120 +#define ADAPTER_INIT_TOV 30 #define ADAPTER_RESET_TOV 180 #define EXTEND_CMD_TOV 60 #define WAIT_CMD_TOV 30 @@ -184,8 +197,6 @@ struct srb { uint16_t iocb_tov; uint16_t iocb_cnt; /* Number of used iocbs */ uint16_t cc_stat; - u_long r_start; /* Time we recieve a cmd from OS */ - u_long u_start; /* Time when we handed the cmd to F/W */ /* Used for extended sense / status continuation */ uint8_t *req_sense_ptr; @@ -221,7 +232,6 @@ struct ddb_entry { unsigned long dev_scan_wait_to_start_relogin; unsigned long dev_scan_wait_to_complete_relogin; - uint16_t os_target_id; /* Target ID */ uint16_t fw_ddb_index; /* DDB firmware index */ uint16_t options; uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */ @@ -285,6 +295,67 @@ struct ddb_entry { #include "ql4_fw.h" #include "ql4_nvram.h" +struct ql82xx_hw_data { + /* Offsets for flash/nvram access (set to ~0 if not used). */ + uint32_t flash_conf_off; + uint32_t flash_data_off; + + uint32_t fdt_wrt_disable; + uint32_t fdt_erase_cmd; + uint32_t fdt_block_size; + uint32_t fdt_unprotect_sec_cmd; + uint32_t fdt_protect_sec_cmd; + + uint32_t flt_region_flt; + uint32_t flt_region_fdt; + uint32_t flt_region_boot; + uint32_t flt_region_bootload; + uint32_t flt_region_fw; + uint32_t reserved; +}; + +struct qla4_8xxx_legacy_intr_set { + uint32_t int_vec_bit; + uint32_t tgt_status_reg; + uint32_t tgt_mask_reg; + uint32_t pci_int_reg; +}; + +/* MSI-X Support */ + +#define QLA_MSIX_DEFAULT 0x00 +#define QLA_MSIX_RSP_Q 0x01 + +#define QLA_MSIX_ENTRIES 2 +#define QLA_MIDX_DEFAULT 0 +#define QLA_MIDX_RSP_Q 1 + +struct ql4_msix_entry { + int have_irq; + uint16_t msix_vector; + uint16_t msix_entry; +}; + +/* + * ISP Operations + */ +struct isp_operations { + int (*iospace_config) (struct scsi_qla_host *ha); + void (*pci_config) (struct scsi_qla_host *); + void (*disable_intrs) (struct scsi_qla_host *); + void (*enable_intrs) (struct scsi_qla_host *); + int (*start_firmware) (struct scsi_qla_host *); + irqreturn_t (*intr_handler) (int , void *); + void (*interrupt_service_routine) (struct scsi_qla_host *, uint32_t); + int (*reset_chip) (struct scsi_qla_host *); + int (*reset_firmware) (struct scsi_qla_host *); + void (*queue_iocb) (struct scsi_qla_host *); + void (*complete_iocb) (struct scsi_qla_host *); + uint16_t (*rd_shdw_req_q_out) (struct scsi_qla_host *); + uint16_t (*rd_shdw_rsp_q_in) (struct scsi_qla_host *); + int (*get_sys_info) (struct scsi_qla_host *); +}; + /* * Linux Host Adapter structure */ @@ -296,28 +367,39 @@ struct scsi_qla_host { #define AF_INIT_DONE 1 /* 0x00000002 */ #define AF_MBOX_COMMAND 2 /* 0x00000004 */ #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ +#define AF_DPC_SCHEDULED 5 /* 0x00000020 */ #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ #define AF_LINK_UP 8 /* 0x00000100 */ #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ #define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ +#define AF_HBA_GOING_AWAY 12 /* 0x00001000 */ +#define AF_INTx_ENABLED 15 /* 0x00008000 */ +#define AF_MSI_ENABLED 16 /* 0x00010000 */ +#define AF_MSIX_ENABLED 17 /* 0x00020000 */ +#define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ + unsigned long dpc_flags; #define DPC_RESET_HA 1 /* 0x00000002 */ #define DPC_RETRY_RESET_HA 2 /* 0x00000004 */ #define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */ -#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */ +#define DPC_RESET_HA_FW_CONTEXT 4 /* 0x00000010 */ #define DPC_RESET_HA_INTR 5 /* 0x00000020 */ #define DPC_ISNS_RESTART 7 /* 0x00000080 */ #define DPC_AEN 9 /* 0x00000200 */ #define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ #define DPC_LINK_CHANGED 18 /* 0x00040000 */ +#define DPC_RESET_ACTIVE 20 /* 0x00040000 */ +#define DPC_HA_UNRECOVERABLE 21 /* 0x00080000 ISP-82xx only*/ +#define DPC_HA_NEED_QUIESCENT 22 /* 0x00100000 ISP-82xx only*/ + struct Scsi_Host *host; /* pointer to host data */ uint32_t tot_ddbs; - uint16_t iocb_cnt; + uint16_t iocb_cnt; /* SRB cache. */ #define SRB_MIN_REQ 128 @@ -332,14 +414,13 @@ struct scsi_qla_host { #define MIN_IOBASE_LEN 0x100 uint16_t req_q_count; - uint8_t rsvd1[2]; unsigned long host_no; /* NVRAM registers */ struct eeprom_data *nvram; spinlock_t hardware_lock ____cacheline_aligned; - uint32_t eeprom_cmd_data; + uint32_t eeprom_cmd_data; /* Counters for general statistics */ uint64_t isr_count; @@ -375,7 +456,6 @@ struct scsi_qla_host { uint8_t alias[32]; uint8_t name_string[256]; uint8_t heartbeat_interval; - uint8_t rsvd; /* --- From FlashSysInfo --- */ uint8_t my_mac[MAC_ADDR_LEN]; @@ -469,6 +549,40 @@ struct scsi_qla_host { struct in6_addr ipv6_addr0; struct in6_addr ipv6_addr1; struct in6_addr ipv6_default_router_addr; + + /* qla82xx specific fields */ + struct device_reg_82xx __iomem *qla4_8xxx_reg; /* Base I/O address */ + unsigned long nx_pcibase; /* Base I/O address */ + uint8_t *nx_db_rd_ptr; /* Doorbell read pointer */ + unsigned long nx_db_wr_ptr; /* Door bell write pointer */ + unsigned long first_page_group_start; + unsigned long first_page_group_end; + + uint32_t crb_win; + uint32_t curr_window; + uint32_t ddr_mn_window; + unsigned long mn_win_crb; + unsigned long ms_win_crb; + int qdr_sn_window; + rwlock_t hw_lock; + uint16_t func_num; + int link_width; + + struct qla4_8xxx_legacy_intr_set nx_legacy_intr; + u32 nx_crb_mask; + + uint8_t revision_id; + uint32_t fw_heartbeat_counter; + + struct isp_operations *isp_ops; + struct ql82xx_hw_data hw; + + struct ql4_msix_entry msix_entries[QLA_MSIX_ENTRIES]; + + uint32_t nx_dev_init_timeout; + uint32_t nx_reset_timeout; + + struct completion mbx_intr_comp; }; static inline int is_ipv4_enabled(struct scsi_qla_host *ha) @@ -496,6 +610,11 @@ static inline int is_qla4032(struct scsi_qla_host *ha) return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032; } +static inline int is_qla8022(struct scsi_qla_host *ha) +{ + return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; +} + static inline int adapter_up(struct scsi_qla_host *ha) { return (test_bit(AF_ONLINE, &ha->flags) != 0) && diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 855226e08665..c94c9ddfb3a6 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -11,7 +11,7 @@ #define MAX_PRST_DEV_DB_ENTRIES 64 #define MIN_DISC_DEV_DB_ENTRY MAX_PRST_DEV_DB_ENTRIES -#define MAX_DEV_DB_ENTRIES 512 +#define MAX_DEV_DB_ENTRIES 512 /************************************************************************* * @@ -37,6 +37,33 @@ struct host_mem_cfg_regs { __le32 rsrvd1[31]; /* 0x84-0xFF */ }; +/* + * ISP 82xx I/O Register Set structure definitions. + */ +struct device_reg_82xx { + __le32 req_q_out; /* 0x0000 (R): Request Queue out-Pointer. */ + __le32 reserve1[63]; /* Request Queue out-Pointer. (64 * 4) */ + __le32 rsp_q_in; /* 0x0100 (R/W): Response Queue In-Pointer. */ + __le32 reserve2[63]; /* Response Queue In-Pointer. */ + __le32 rsp_q_out; /* 0x0200 (R/W): Response Queue Out-Pointer. */ + __le32 reserve3[63]; /* Response Queue Out-Pointer. */ + + __le32 mailbox_in[8]; /* 0x0300 (R/W): Mail box In registers */ + __le32 reserve4[24]; + __le32 hint; /* 0x0380 (R/W): Host interrupt register */ +#define HINT_MBX_INT_PENDING BIT_0 + __le32 reserve5[31]; + __le32 mailbox_out[8]; /* 0x0400 (R): Mail box Out registers */ + __le32 reserve6[56]; + + __le32 host_status; /* Offset 0x500 (R): host status */ +#define HSRX_RISC_MB_INT BIT_0 /* RISC to Host Mailbox interrupt */ +#define HSRX_RISC_IOCB_INT BIT_1 /* RISC to Host IOCB interrupt */ + + __le32 host_int; /* Offset 0x0504 (R/W): Interrupt status. */ +#define ISRX_82XX_RISC_INT BIT_0 /* RISC interrupt. */ +}; + /* remote register set (access via PCI memory read/write) */ struct isp_reg { #define MBOX_REG_COUNT 8 @@ -206,6 +233,79 @@ union external_hw_config_reg { uint32_t Asuint32_t; }; +/* 82XX Support start */ +/* 82xx Default FLT Addresses */ +#define FA_FLASH_LAYOUT_ADDR_82 0xFC400 +#define FA_FLASH_DESCR_ADDR_82 0xFC000 +#define FA_BOOT_LOAD_ADDR_82 0x04000 +#define FA_BOOT_CODE_ADDR_82 0x20000 +#define FA_RISC_CODE_ADDR_82 0x40000 +#define FA_GOLD_RISC_CODE_ADDR_82 0x80000 + +/* Flash Description Table */ +struct qla_fdt_layout { + uint8_t sig[4]; + uint16_t version; + uint16_t len; + uint16_t checksum; + uint8_t unused1[2]; + uint8_t model[16]; + uint16_t man_id; + uint16_t id; + uint8_t flags; + uint8_t erase_cmd; + uint8_t alt_erase_cmd; + uint8_t wrt_enable_cmd; + uint8_t wrt_enable_bits; + uint8_t wrt_sts_reg_cmd; + uint8_t unprotect_sec_cmd; + uint8_t read_man_id_cmd; + uint32_t block_size; + uint32_t alt_block_size; + uint32_t flash_size; + uint32_t wrt_enable_data; + uint8_t read_id_addr_len; + uint8_t wrt_disable_bits; + uint8_t read_dev_id_len; + uint8_t chip_erase_cmd; + uint16_t read_timeout; + uint8_t protect_sec_cmd; + uint8_t unused2[65]; +}; + +/* Flash Layout Table */ + +struct qla_flt_location { + uint8_t sig[4]; + uint16_t start_lo; + uint16_t start_hi; + uint8_t version; + uint8_t unused[5]; + uint16_t checksum; +}; + +struct qla_flt_header { + uint16_t version; + uint16_t length; + uint16_t checksum; + uint16_t unused; +}; + +/* 82xx FLT Regions */ +#define FLT_REG_FDT 0x1a +#define FLT_REG_FLT 0x1c +#define FLT_REG_BOOTLOAD_82 0x72 +#define FLT_REG_FW_82 0x74 +#define FLT_REG_GOLD_FW_82 0x75 +#define FLT_REG_BOOT_CODE_82 0x78 + +struct qla_flt_region { + uint32_t code; + uint32_t size; + uint32_t start; + uint32_t end; +}; + /************************************************************************* * * Mailbox Commands Structures and Definitions @@ -215,6 +315,10 @@ union external_hw_config_reg { /* Mailbox command definitions */ #define MBOX_CMD_ABOUT_FW 0x0009 #define MBOX_CMD_PING 0x000B +#define MBOX_CMD_ENABLE_INTRS 0x0010 +#define INTR_DISABLE 0 +#define INTR_ENABLE 1 +#define MBOX_CMD_STOP_FW 0x0014 #define MBOX_CMD_ABORT_TASK 0x0015 #define MBOX_CMD_LUN_RESET 0x0016 #define MBOX_CMD_TARGET_WARM_RESET 0x0017 @@ -243,6 +347,7 @@ union external_hw_config_reg { #define DDB_DS_LOGIN_IN_PROCESS 0x07 #define MBOX_CMD_GET_FW_STATE 0x0069 #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A +#define MBOX_CMD_GET_SYS_INFO 0x0078 #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 #define MBOX_CMD_SET_ACB 0x0088 #define MBOX_CMD_GET_ACB 0x0089 @@ -318,6 +423,15 @@ union external_hw_config_reg { #define MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR 0x8022 #define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027 +/* ACB State Defines */ +#define ACB_STATE_UNCONFIGURED 0x00 +#define ACB_STATE_INVALID 0x01 +#define ACB_STATE_ACQUIRING 0x02 +#define ACB_STATE_TENTATIVE 0x03 +#define ACB_STATE_DEPRICATED 0x04 +#define ACB_STATE_VALID 0x05 +#define ACB_STATE_DISABLING 0x06 + /*************************************************************************/ /* Host Adapter Initialization Control Block (from host) */ @@ -558,6 +672,20 @@ struct flash_sys_info { uint32_t reserved1[39]; /* 170-1ff */ }; /* 200 */ +struct mbx_sys_info { + uint8_t board_id_str[16]; /* Keep board ID string first */ + /* in this structure for GUI. */ + uint16_t board_id; /* board ID code */ + uint16_t phys_port_cnt; /* number of physical network ports */ + uint16_t port_num; /* network port for this PCI function */ + /* (port 0 is first port) */ + uint8_t mac_addr[6]; /* MAC address for this PCI function */ + uint32_t iscsi_pci_func_cnt; /* number of iSCSI PCI functions */ + uint32_t pci_func; /* this PCI function */ + unsigned char serial_number[16]; /* serial number string */ + uint8_t reserved[16]; +}; + struct crash_record { uint16_t fw_major_version; /* 00 - 01 */ uint16_t fw_minor_version; /* 02 - 03 */ @@ -814,4 +942,13 @@ struct passthru_status { uint8_t res4[16]; /* 30-3F */ }; +/* + * ISP queue - response queue entry definition. + */ +struct response { + uint8_t data[60]; + uint32_t signature; +#define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */ +}; + #endif /* _QLA4X_FW_H */ diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index c4636f6cb3cb..c9cd5d6db982 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -10,31 +10,32 @@ struct iscsi_cls_conn; -void qla4xxx_hw_reset(struct scsi_qla_host *ha); +int qla4xxx_hw_reset(struct scsi_qla_host *ha); int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); -int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb); -int qla4xxx_initialize_adapter(struct scsi_qla_host * ha, +int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb); +int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, uint8_t renew_ddb_list); int qla4xxx_soft_reset(struct scsi_qla_host *ha); irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); -void qla4xxx_free_ddb_list(struct scsi_qla_host * ha); -void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen); +void qla4xxx_free_ddb_list(struct scsi_qla_host *ha); +void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry); +void qla4xxx_process_aen(struct scsi_qla_host *ha, uint8_t process_aen); -int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha); -int qla4xxx_relogin_device(struct scsi_qla_host * ha, - struct ddb_entry * ddb_entry); +int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host *ha); +int qla4xxx_relogin_device(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry); int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb); -int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, +int qla4xxx_reset_lun(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry, int lun); -int qla4xxx_reset_target(struct scsi_qla_host * ha, - struct ddb_entry * ddb_entry); -int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, +int qla4xxx_reset_target(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry); +int qla4xxx_get_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, uint32_t offset, uint32_t len); -int qla4xxx_get_firmware_status(struct scsi_qla_host * ha); -int qla4xxx_get_firmware_state(struct scsi_qla_host * ha); -int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha); +int qla4xxx_get_firmware_status(struct scsi_qla_host *ha); +int qla4xxx_get_firmware_state(struct scsi_qla_host *ha); +int qla4xxx_initialize_fw_cb(struct scsi_qla_host *ha); /* FIXME: Goodness! this really wants a small struct to hold the * parameters. On x86 the args will get passed on the stack! */ @@ -54,20 +55,20 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry); -u16 rd_nvram_word(struct scsi_qla_host * ha, int offset); -void qla4xxx_get_crash_record(struct scsi_qla_host * ha); +u16 rd_nvram_word(struct scsi_qla_host *ha, int offset); +void qla4xxx_get_crash_record(struct scsi_qla_host *ha); struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha); int qla4xxx_add_sess(struct ddb_entry *); void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); -int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha); +int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha); int qla4xxx_get_fw_version(struct scsi_qla_host * ha); -void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha, +void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha, uint32_t intr_status); -int qla4xxx_init_rings(struct scsi_qla_host * ha); -struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, - uint32_t index); +int qla4xxx_init_rings(struct scsi_qla_host *ha); void qla4xxx_srb_compl(struct kref *ref); -int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); +struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, + uint32_t index); +int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha); int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, uint32_t state, uint32_t conn_error); void qla4xxx_dump_buffer(void *b, uint32_t size); @@ -75,8 +76,65 @@ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod); int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err); +int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, + uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts); + +void qla4xxx_queue_iocb(struct scsi_qla_host *ha); +void qla4xxx_complete_iocb(struct scsi_qla_host *ha); +int qla4xxx_get_sys_info(struct scsi_qla_host *ha); +int qla4xxx_iospace_config(struct scsi_qla_host *ha); +void qla4xxx_pci_config(struct scsi_qla_host *ha); +int qla4xxx_start_firmware(struct scsi_qla_host *ha); +irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); +uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha); +uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha); +int qla4xxx_request_irqs(struct scsi_qla_host *ha); +void qla4xxx_free_irqs(struct scsi_qla_host *ha); +void qla4xxx_process_response_queue(struct scsi_qla_host *ha); +void qla4xxx_wake_dpc(struct scsi_qla_host *ha); +void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha); + +void qla4_8xxx_pci_config(struct scsi_qla_host *); +int qla4_8xxx_iospace_config(struct scsi_qla_host *ha); +int qla4_8xxx_load_risc(struct scsi_qla_host *); +irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id); +void qla4_8xxx_queue_iocb(struct scsi_qla_host *ha); +void qla4_8xxx_complete_iocb(struct scsi_qla_host *ha); + +int qla4_8xxx_crb_win_lock(struct scsi_qla_host *); +void qla4_8xxx_crb_win_unlock(struct scsi_qla_host *); +int qla4_8xxx_pci_get_crb_addr_2M(struct scsi_qla_host *, ulong *); +void qla4_8xxx_wr_32(struct scsi_qla_host *, ulong, u32); +int qla4_8xxx_rd_32(struct scsi_qla_host *, ulong); +int qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *, u64, void *, int); +int qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha, u64, void *, int); +int qla4_8xxx_isp_reset(struct scsi_qla_host *ha); +void qla4_8xxx_interrupt_service_routine(struct scsi_qla_host *ha, + uint32_t intr_status); +uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha); +uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha); +int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha); +void qla4_8xxx_watchdog(struct scsi_qla_host *ha); +int qla4_8xxx_stop_firmware(struct scsi_qla_host *ha); +int qla4_8xxx_get_flash_info(struct scsi_qla_host *ha); +void qla4_8xxx_enable_intrs(struct scsi_qla_host *ha); +void qla4_8xxx_disable_intrs(struct scsi_qla_host *ha); +int qla4_8xxx_enable_msix(struct scsi_qla_host *ha); +void qla4_8xxx_disable_msix(struct scsi_qla_host *ha); +irqreturn_t qla4_8xxx_msi_handler(int irq, void *dev_id); +irqreturn_t qla4_8xxx_default_intr_handler(int irq, void *dev_id); +irqreturn_t qla4_8xxx_msix_rsp_q(int irq, void *dev_id); +void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha); +void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha); +int qla4_8xxx_idc_lock(struct scsi_qla_host *ha); +void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha); +int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha); +void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha); +void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha); + extern int ql4xextended_error_logging; extern int ql4xdiscoverywait; extern int ql4xdontresethba; -extern int ql4_mod_unload; +extern int ql4xenablemsix; + #endif /* _QLA4x_GBL_H */ diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 4a332c32d71e..539546df0376 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -11,8 +11,8 @@ #include "ql4_dbg.h" #include "ql4_inline.h" -static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, - uint32_t fw_ddb_index); +static struct ddb_entry *qla4xxx_alloc_ddb(struct scsi_qla_host *ha, + uint32_t fw_ddb_index); static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) { @@ -51,8 +51,8 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) * This routine deallocates and unlinks the specified ddb_entry from the * adapter's **/ -static void qla4xxx_free_ddb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry) +void qla4xxx_free_ddb(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry) { /* Remove device entry from list */ list_del_init(&ddb_entry->list); @@ -85,6 +85,25 @@ void qla4xxx_free_ddb_list(struct scsi_qla_host *ha) } } +/** + * qla4xxx_init_response_q_entries() - Initializes response queue entries. + * @ha: HA context + * + * Beginning of request ring has initialization control block already built + * by nvram config routine. + **/ +static void qla4xxx_init_response_q_entries(struct scsi_qla_host *ha) +{ + uint16_t cnt; + struct response *pkt; + + pkt = (struct response *)ha->response_ptr; + for (cnt = 0; cnt < RESPONSE_QUEUE_DEPTH; cnt++) { + pkt->signature = RESPONSE_PROCESSED; + pkt++; + } +} + /** * qla4xxx_init_rings - initialize hw queues * @ha: pointer to host adapter structure. @@ -109,19 +128,31 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha) ha->response_out = 0; ha->response_ptr = &ha->response_ring[ha->response_out]; - /* - * Initialize DMA Shadow registers. The firmware is really supposed to - * take care of this, but on some uniprocessor systems, the shadow - * registers aren't cleared-- causing the interrupt_handler to think - * there are responses to be processed when there aren't. - */ - ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0); - ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0); - wmb(); + if (is_qla8022(ha)) { + writel(0, + (unsigned long __iomem *)&ha->qla4_8xxx_reg->req_q_out); + writel(0, + (unsigned long __iomem *)&ha->qla4_8xxx_reg->rsp_q_in); + writel(0, + (unsigned long __iomem *)&ha->qla4_8xxx_reg->rsp_q_out); + } else { + /* + * Initialize DMA Shadow registers. The firmware is really + * supposed to take care of this, but on some uniprocessor + * systems, the shadow registers aren't cleared-- causing + * the interrupt_handler to think there are responses to be + * processed when there aren't. + */ + ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0); + ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0); + wmb(); - writel(0, &ha->reg->req_q_in); - writel(0, &ha->reg->rsp_q_out); - readl(&ha->reg->rsp_q_out); + writel(0, &ha->reg->req_q_in); + writel(0, &ha->reg->rsp_q_out); + readl(&ha->reg->rsp_q_out); + } + + qla4xxx_init_response_q_entries(ha); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -129,11 +160,11 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha) } /** - * qla4xxx_validate_mac_address - validate adapter MAC address(es) + * qla4xxx_get_sys_info - validate adapter MAC address(es) * @ha: pointer to host adapter structure. * **/ -static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) +int qla4xxx_get_sys_info(struct scsi_qla_host *ha) { struct flash_sys_info *sys_info; dma_addr_t sys_info_dma; @@ -145,7 +176,7 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", ha->host_no, __func__)); - goto exit_validate_mac_no_free; + goto exit_get_sys_info_no_free; } memset(sys_info, 0, sizeof(*sys_info)); @@ -155,7 +186,7 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) DEBUG2(printk("scsi%ld: %s: get_flash FLASH_OFFSET_SYS_INFO " "failed\n", ha->host_no, __func__)); - goto exit_validate_mac; + goto exit_get_sys_info; } /* Save M.A.C. address & serial_number */ @@ -168,11 +199,11 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) status = QLA_SUCCESS; - exit_validate_mac: +exit_get_sys_info: dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info, sys_info_dma); - exit_validate_mac_no_free: +exit_get_sys_info_no_free: return status; } @@ -584,21 +615,19 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, min(sizeof(ddb_entry->link_local_ipv6_addr), sizeof(fw_ddb_entry->link_local_ipv6_addr))); - DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d " - "State %04x ConnErr %08x IP %pI6 " + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x" + " ConnErr %08x IP %pI6 " ":%04d \"%s\"\n", __func__, fw_ddb_index, - ddb_entry->os_target_id, ddb_entry->fw_ddb_device_state, conn_err, fw_ddb_entry->ip_addr, le16_to_cpu(fw_ddb_entry->port), fw_ddb_entry->iscsi_name)); } else - DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d " - "State %04x ConnErr %08x IP %pI4 " + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x" + " ConnErr %08x IP %pI4 " ":%04d \"%s\"\n", __func__, fw_ddb_index, - ddb_entry->os_target_id, ddb_entry->fw_ddb_device_state, conn_err, fw_ddb_entry->ip_addr, le16_to_cpu(fw_ddb_entry->port), @@ -984,7 +1013,7 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) } /** - * qla4xxx_update_ddb_list - update the driver ddb list + * qla4xxx_reinitialize_ddb_list - update the driver ddb list * @ha: pointer to host adapter structure. * * This routine obtains device information from the F/W database after @@ -1028,7 +1057,7 @@ int qla4xxx_relogin_device(struct scsi_qla_host *ha, (uint16_t)RELOGIN_TOV); atomic_set(&ddb_entry->relogin_timer, relogin_timer); - DEBUG2(printk("scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no, + DEBUG2(printk("scsi%ld: Relogin ddb [%d]. TOV=%d\n", ha->host_no, ddb_entry->fw_ddb_index, relogin_timer)); qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0); @@ -1085,7 +1114,16 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha) return QLA_SUCCESS; } -static void qla4x00_pci_config(struct scsi_qla_host *ha) +/** + * qla4_8xxx_pci_config() - Setup ISP82xx PCI configuration registers. + * @ha: HA context + */ +void qla4_8xxx_pci_config(struct scsi_qla_host *ha) +{ + pci_set_master(ha->pdev); +} + +void qla4xxx_pci_config(struct scsi_qla_host *ha) { uint16_t w; int status; @@ -1216,7 +1254,7 @@ int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) * This routine performs the necessary steps to start the firmware for * the QLA4010 adapter. **/ -static int qla4xxx_start_firmware(struct scsi_qla_host *ha) +int qla4xxx_start_firmware(struct scsi_qla_host *ha) { unsigned long flags = 0; uint32_t mbox_status; @@ -1295,7 +1333,8 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha) if (soft_reset) { DEBUG(printk("scsi%ld: %s: Issue Soft Reset\n", ha->host_no, __func__)); - status = qla4xxx_soft_reset(ha); + status = qla4xxx_soft_reset(ha); /* NOTE: acquires drvr + * lock again, but ok */ if (status == QLA_ERROR) { DEBUG(printk("scsi%d: %s: Soft Reset failed!\n", ha->host_no, __func__)); @@ -1316,7 +1355,6 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha) ql4xxx_unlock_drvr(ha); if (status == QLA_SUCCESS) { - qla4xxx_get_fw_version(ha); if (test_and_clear_bit(AF_GET_CRASH_RECORD, &ha->flags)) qla4xxx_get_crash_record(ha); } else { @@ -1343,18 +1381,21 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int status = QLA_ERROR; int8_t ip_address[IP_ADDR_LEN] = {0} ; - clear_bit(AF_ONLINE, &ha->flags); ha->eeprom_cmd_data = 0; - qla4x00_pci_config(ha); + ql4_printk(KERN_INFO, ha, "Configuring PCI space...\n"); + ha->isp_ops->pci_config(ha); - qla4xxx_disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); /* Initialize the Host adapter request/response queues and firmware */ - if (qla4xxx_start_firmware(ha) == QLA_ERROR) + if (ha->isp_ops->start_firmware(ha) == QLA_ERROR) + goto exit_init_hba; + + if (qla4xxx_get_fw_version(ha) == QLA_ERROR) goto exit_init_hba; - if (qla4xxx_validate_mac_address(ha) == QLA_ERROR) + if (ha->isp_ops->get_sys_info(ha) == QLA_ERROR) goto exit_init_hba; if (qla4xxx_init_local_data(ha) == QLA_ERROR) @@ -1407,6 +1448,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, exit_init_online: set_bit(AF_ONLINE, &ha->flags); exit_init_hba: + DEBUG2(printk("scsi%ld: initialize adapter: %s\n", ha->host_no, + status == QLA_ERROR ? "FAILED" : "SUCCEDED")); return status; } @@ -1558,9 +1601,20 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, atomic_set(&ddb_entry->relogin_timer, 0); atomic_set(&ddb_entry->retry_relogin_timer, ddb_entry->default_time2wait + 4); + DEBUG(printk("scsi%ld: %s: ddb[%d] " + "initiate relogin after %d seconds\n", + ha->host_no, __func__, + ddb_entry->fw_ddb_index, + ddb_entry->default_time2wait + 4)); + } else { + DEBUG(printk("scsi%ld: %s: ddb[%d] " + "relogin not initiated, state = %d, " + "ddb_entry->flags = 0x%lx\n", + ha->host_no, __func__, + ddb_entry->fw_ddb_index, + ddb_entry->fw_ddb_device_state, + ddb_entry->flags)); } } - return QLA_SUCCESS; } - diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h index 6375eb017dd3..9471ac755000 100644 --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h @@ -29,7 +29,7 @@ qla4xxx_lookup_ddb_by_fw_index(struct scsi_qla_host *ha, uint32_t fw_ddb_index) ddb_entry = ha->fw_ddb_index_map[fw_ddb_index]; } - DEBUG3(printk("scsi%d: %s: index [%d], ddb_entry = %p\n", + DEBUG3(printk("scsi%d: %s: ddb [%d], ddb_entry = %p\n", ha->host_no, __func__, fw_ddb_index, ddb_entry)); return ddb_entry; diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index e66f3f263f49..f89973deac5b 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -108,8 +108,7 @@ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, wmb(); /* Tell ISP it's got a new I/O request */ - writel(ha->request_in, &ha->reg->req_q_in); - readl(&ha->reg->req_q_in); + ha->isp_ops->queue_iocb(ha); exit_send_marker: spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -193,6 +192,72 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb, } } +/** + * qla4_8xxx_queue_iocb - Tell ISP it's got new request(s) + * @ha: pointer to host adapter structure. + * + * This routine notifies the ISP that one or more new request + * queue entries have been placed on the request queue. + **/ +void qla4_8xxx_queue_iocb(struct scsi_qla_host *ha) +{ + uint32_t dbval = 0; + unsigned long wtime; + + dbval = 0x14 | (ha->func_num << 5); + dbval = dbval | (0 << 8) | (ha->request_in << 16); + writel(dbval, (unsigned long __iomem *)ha->nx_db_wr_ptr); + wmb(); + + wtime = jiffies + (2 * HZ); + while (readl((void __iomem *)ha->nx_db_rd_ptr) != dbval && + !time_after_eq(jiffies, wtime)) { + writel(dbval, (unsigned long __iomem *)ha->nx_db_wr_ptr); + wmb(); + } +} + +/** + * qla4_8xxx_complete_iocb - Tell ISP we're done with response(s) + * @ha: pointer to host adapter structure. + * + * This routine notifies the ISP that one or more response/completion + * queue entries have been processed by the driver. + * This also clears the interrupt. + **/ +void qla4_8xxx_complete_iocb(struct scsi_qla_host *ha) +{ + writel(ha->response_out, &ha->qla4_8xxx_reg->rsp_q_out); + readl(&ha->qla4_8xxx_reg->rsp_q_out); +} + +/** + * qla4xxx_queue_iocb - Tell ISP it's got new request(s) + * @ha: pointer to host adapter structure. + * + * This routine is notifies the ISP that one or more new request + * queue entries have been placed on the request queue. + **/ +void qla4xxx_queue_iocb(struct scsi_qla_host *ha) +{ + writel(ha->request_in, &ha->reg->req_q_in); + readl(&ha->reg->req_q_in); +} + +/** + * qla4xxx_complete_iocb - Tell ISP we're done with response(s) + * @ha: pointer to host adapter structure. + * + * This routine is notifies the ISP that one or more response/completion + * queue entries have been processed by the driver. + * This also clears the interrupt. + **/ +void qla4xxx_complete_iocb(struct scsi_qla_host *ha) +{ + writel(ha->response_out, &ha->reg->rsp_q_out); + readl(&ha->reg->rsp_q_out); +} + /** * qla4xxx_send_command_to_isp - issues command to HBA * @ha: pointer to host adapter structure. @@ -310,9 +375,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) srb->iocb_cnt = req_cnt; ha->req_q_count -= req_cnt; - /* Debug print statements */ - writel(ha->request_in, &ha->reg->req_q_in); - readl(&ha->reg->req_q_in); + ha->isp_ops->queue_iocb(ha); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_SUCCESS; diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 596c3031483c..68d7942bf2e3 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -118,7 +118,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); if (!srb) { - /* FIXMEdg: Don't we need to reset ISP in this case??? */ DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Status Entry invalid " "handle 0x%x, sp=%p. This cmd may have already " "been completed.\n", ha->host_no, __func__, @@ -293,6 +292,10 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, case SCS_DEVICE_LOGGED_OUT: case SCS_DEVICE_UNAVAILABLE: + DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: SCS_DEVICE " + "state: 0x%x\n", ha->host_no, + cmd->device->channel, cmd->device->id, + cmd->device->lun, sts_entry->completionStatus)); /* * Mark device missing so that we won't continue to * send I/O to this device. We should get a ddb @@ -339,16 +342,14 @@ status_entry_exit: * This routine process response queue completions in interrupt context. * Hardware_lock locked upon entry **/ -static void qla4xxx_process_response_queue(struct scsi_qla_host * ha) +void qla4xxx_process_response_queue(struct scsi_qla_host *ha) { uint32_t count = 0; struct srb *srb = NULL; struct status_entry *sts_entry; /* Process all responses from response queue */ - while ((ha->response_in = - (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in)) != - ha->response_out) { + while ((ha->response_ptr->signature != RESPONSE_PROCESSED)) { sts_entry = (struct status_entry *) ha->response_ptr; count++; @@ -413,14 +414,14 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha) sts_entry->hdr.entryType)); goto exit_prq_error; } + ((struct response *)sts_entry)->signature = RESPONSE_PROCESSED; + wmb(); } /* - * Done with responses, update the ISP For QLA4010, this also clears - * the interrupt. + * Tell ISP we're done with response(s). This also clears the interrupt. */ - writel(ha->response_out, &ha->reg->rsp_q_out); - readl(&ha->reg->rsp_q_out); + ha->isp_ops->complete_iocb(ha); return; @@ -430,9 +431,7 @@ exit_prq_invalid_handle: sts_entry->completionStatus)); exit_prq_error: - writel(ha->response_out, &ha->reg->rsp_q_out); - readl(&ha->reg->rsp_q_out); - + ha->isp_ops->complete_iocb(ha); set_bit(DPC_RESET_HA, &ha->dpc_flags); } @@ -448,7 +447,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, uint32_t mbox_status) { int i; - uint32_t mbox_stat2, mbox_stat3; + uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; if ((mbox_status == MBOX_STS_BUSY) || (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) || @@ -460,27 +459,37 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, * Copy all mailbox registers to a temporary * location and set mailbox command done flag */ - for (i = 1; i < ha->mbox_status_count; i++) - ha->mbox_status[i] = - readl(&ha->reg->mailbox[i]); + for (i = 0; i < ha->mbox_status_count; i++) + ha->mbox_status[i] = is_qla8022(ha) + ? readl(&ha->qla4_8xxx_reg->mailbox_out[i]) + : readl(&ha->reg->mailbox[i]); set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); + + if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) + complete(&ha->mbx_intr_comp); } } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { + for (i = 0; i < MBOX_AEN_REG_COUNT; i++) + mbox_sts[i] = is_qla8022(ha) + ? readl(&ha->qla4_8xxx_reg->mailbox_out[i]) + : readl(&ha->reg->mailbox[i]); + /* Immediately process the AENs that don't require much work. * Only queue the database_changed AENs */ if (ha->aen_log.count < MAX_AEN_ENTRIES) { for (i = 0; i < MBOX_AEN_REG_COUNT; i++) ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] = - readl(&ha->reg->mailbox[i]); + mbox_sts[i]; ha->aen_log.count++; } switch (mbox_status) { case MBOX_ASTS_SYSTEM_ERROR: /* Log Mailbox registers */ + ql4_printk(KERN_INFO, ha, "%s: System Err\n", __func__); if (ql4xdontresethba) { - DEBUG2(printk("%s:Dont Reset HBA\n", - __func__)); + DEBUG2(printk("scsi%ld: %s:Don't Reset HBA\n", + ha->host_no, __func__)); } else { set_bit(AF_GET_CRASH_RECORD, &ha->flags); set_bit(DPC_RESET_HA, &ha->dpc_flags); @@ -502,18 +511,15 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, if (test_bit(AF_INIT_DONE, &ha->flags)) set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); - DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter" - " LINK UP\n", ha->host_no, - mbox_status)); + ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__); break; case MBOX_ASTS_LINK_DOWN: clear_bit(AF_LINK_UP, &ha->flags); - set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); + if (test_bit(AF_INIT_DONE, &ha->flags)) + set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); - DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter" - " LINK DOWN\n", ha->host_no, - mbox_status)); + ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__); break; case MBOX_ASTS_HEARTBEAT: @@ -539,12 +545,17 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, break; case MBOX_ASTS_IP_ADDR_STATE_CHANGED: - mbox_stat2 = readl(&ha->reg->mailbox[2]); - mbox_stat3 = readl(&ha->reg->mailbox[3]); - - if ((mbox_stat3 == 5) && (mbox_stat2 == 3)) + printk("scsi%ld: AEN %04x, mbox_sts[2]=%04x, " + "mbox_sts[3]=%04x\n", ha->host_no, mbox_sts[0], + mbox_sts[2], mbox_sts[3]); + + /* mbox_sts[2] = Old ACB state + * mbox_sts[3] = new ACB state */ + if ((mbox_sts[3] == ACB_STATE_VALID) && + (mbox_sts[2] == ACB_STATE_TENTATIVE)) set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); - else if ((mbox_stat3 == 2) && (mbox_stat2 == 5)) + else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) && + (mbox_sts[2] == ACB_STATE_VALID)) set_bit(DPC_RESET_HA, &ha->dpc_flags); break; @@ -553,9 +564,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, /* No action */ DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x, " "mbox_sts[1]=%04x, mbox_sts[2]=%04x\n", - ha->host_no, mbox_status, - readl(&ha->reg->mailbox[1]), - readl(&ha->reg->mailbox[2]))); + ha->host_no, mbox_sts[0], + mbox_sts[1], mbox_sts[2])); break; case MBOX_ASTS_SELF_TEST_FAILED: @@ -563,10 +573,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, /* No action */ DEBUG2(printk("scsi%ld: AEN %04x, mbox_sts[1]=%04x, " "mbox_sts[2]=%04x, mbox_sts[3]=%04x\n", - ha->host_no, mbox_status, - readl(&ha->reg->mailbox[1]), - readl(&ha->reg->mailbox[2]), - readl(&ha->reg->mailbox[3]))); + ha->host_no, mbox_sts[0], mbox_sts[1], + mbox_sts[2], mbox_sts[3])); break; case MBOX_ASTS_DATABASE_CHANGED: @@ -577,21 +585,17 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, /* decrement available counter */ ha->aen_q_count--; - for (i = 1; i < MBOX_AEN_REG_COUNT; i++) + for (i = 0; i < MBOX_AEN_REG_COUNT; i++) ha->aen_q[ha->aen_in].mbox_sts[i] = - readl(&ha->reg->mailbox[i]); - - ha->aen_q[ha->aen_in].mbox_sts[0] = mbox_status; + mbox_sts[i]; /* print debug message */ DEBUG2(printk("scsi%ld: AEN[%d] %04x queued" - " mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n", - ha->host_no, ha->aen_in, - mbox_status, - ha->aen_q[ha->aen_in].mbox_sts[1], - ha->aen_q[ha->aen_in].mbox_sts[2], - ha->aen_q[ha->aen_in].mbox_sts[3], - ha->aen_q[ha->aen_in]. mbox_sts[4])); + " mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n", + ha->host_no, ha->aen_in, mbox_sts[0], + mbox_sts[1], mbox_sts[2], mbox_sts[3], + mbox_sts[4])); + /* advance pointer */ ha->aen_in++; if (ha->aen_in == MAX_AEN_ENTRIES) @@ -603,18 +607,16 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, DEBUG2(printk("scsi%ld: %s: aen %04x, queue " "overflowed! AEN LOST!!\n", ha->host_no, __func__, - mbox_status)); + mbox_sts[0])); DEBUG2(printk("scsi%ld: DUMP AEN QUEUE\n", ha->host_no)); for (i = 0; i < MAX_AEN_ENTRIES; i++) { DEBUG2(printk("AEN[%d] %04x %04x %04x " - "%04x\n", i, - ha->aen_q[i].mbox_sts[0], - ha->aen_q[i].mbox_sts[1], - ha->aen_q[i].mbox_sts[2], - ha->aen_q[i].mbox_sts[3])); + "%04x\n", i, mbox_sts[0], + mbox_sts[1], mbox_sts[2], + mbox_sts[3])); } } break; @@ -622,7 +624,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, default: DEBUG2(printk(KERN_WARNING "scsi%ld: AEN %04x UNKNOWN\n", - ha->host_no, mbox_status)); + ha->host_no, mbox_sts[0])); break; } } else { @@ -633,6 +635,30 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, } } +/** + * qla4_8xxx_interrupt_service_routine - isr + * @ha: pointer to host adapter structure. + * + * This is the main interrupt service routine. + * hardware_lock locked upon entry. runs in interrupt context. + **/ +void qla4_8xxx_interrupt_service_routine(struct scsi_qla_host *ha, + uint32_t intr_status) +{ + /* Process response queue interrupt. */ + if (intr_status & HSRX_RISC_IOCB_INT) + qla4xxx_process_response_queue(ha); + + /* Process mailbox/asynch event interrupt.*/ + if (intr_status & HSRX_RISC_MB_INT) + qla4xxx_isr_decode_mailbox(ha, + readl(&ha->qla4_8xxx_reg->mailbox_out[0])); + + /* clear the interrupt */ + writel(0, &ha->qla4_8xxx_reg->host_int); + readl(&ha->qla4_8xxx_reg->host_int); +} + /** * qla4xxx_interrupt_service_routine - isr * @ha: pointer to host adapter structure. @@ -659,6 +685,28 @@ void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha, } } +/** + * qla4_8xxx_spurious_interrupt - processes spurious interrupt + * @ha: pointer to host adapter structure. + * @reqs_count: . + * + **/ +static void qla4_8xxx_spurious_interrupt(struct scsi_qla_host *ha, + uint8_t reqs_count) +{ + if (reqs_count) + return; + + DEBUG2(ql4_printk(KERN_INFO, ha, "Spurious Interrupt\n")); + if (is_qla8022(ha)) { + writel(0, &ha->qla4_8xxx_reg->host_int); + if (test_bit(AF_INTx_ENABLED, &ha->flags)) + qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, + 0xfbff); + } + ha->spurious_int_count++; +} + /** * qla4xxx_intr_handler - hardware interrupt handler. * @irq: Unused @@ -689,15 +737,14 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) /* * Read interrupt status */ - if (le32_to_cpu(ha->shadow_regs->rsp_q_in) != + if (ha->isp_ops->rd_shdw_rsp_q_in(ha) != ha->response_out) intr_status = CSR_SCSI_COMPLETION_INTR; else intr_status = readl(&ha->reg->ctrl_status); if ((intr_status & - (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == - 0) { + (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == 0) { if (reqs_count == 0) ha->spurious_int_count++; break; @@ -739,22 +786,159 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) &ha->reg->ctrl_status); readl(&ha->reg->ctrl_status); - if (!ql4_mod_unload) + if (!test_bit(AF_HBA_GOING_AWAY, &ha->flags)) set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); break; } else if (intr_status & INTR_PENDING) { - qla4xxx_interrupt_service_routine(ha, intr_status); + ha->isp_ops->interrupt_service_routine(ha, intr_status); ha->total_io_count++; if (++reqs_count == MAX_REQS_SERVICED_PER_INTR) break; + } + } + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return IRQ_HANDLED; +} + +/** + * qla4_8xxx_intr_handler - hardware interrupt handler. + * @irq: Unused + * @dev_id: Pointer to host adapter structure + **/ +irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id) +{ + struct scsi_qla_host *ha = dev_id; + uint32_t intr_status; + uint32_t status; + unsigned long flags = 0; + uint8_t reqs_count = 0; + + ha->isr_count++; + status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); + if (!(status & ha->nx_legacy_intr.int_vec_bit)) + return IRQ_NONE; + + status = qla4_8xxx_rd_32(ha, ISR_INT_STATE_REG); + if (!ISR_IS_LEGACY_INTR_TRIGGERED(status)) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s legacy Int not triggered\n", __func__)); + return IRQ_NONE; + } + + /* clear the interrupt */ + qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff); + + /* read twice to ensure write is flushed */ + qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); + qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); + + spin_lock_irqsave(&ha->hardware_lock, flags); + while (1) { + if (!(readl(&ha->qla4_8xxx_reg->host_int) & + ISRX_82XX_RISC_INT)) { + qla4_8xxx_spurious_interrupt(ha, reqs_count); + break; + } + intr_status = readl(&ha->qla4_8xxx_reg->host_status); + if ((intr_status & + (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) { + qla4_8xxx_spurious_interrupt(ha, reqs_count); + break; + } + + ha->isp_ops->interrupt_service_routine(ha, intr_status); + + /* Enable Interrupt */ + qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); - intr_status = 0; + if (++reqs_count == MAX_REQS_SERVICED_PER_INTR) + break; + } + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return IRQ_HANDLED; +} + +irqreturn_t +qla4_8xxx_msi_handler(int irq, void *dev_id) +{ + struct scsi_qla_host *ha; + + ha = (struct scsi_qla_host *) dev_id; + if (!ha) { + DEBUG2(printk(KERN_INFO + "qla4xxx: MSIX: Interrupt with NULL host ptr\n")); + return IRQ_NONE; + } + + ha->isr_count++; + /* clear the interrupt */ + qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff); + + /* read twice to ensure write is flushed */ + qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); + qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); + + return qla4_8xxx_default_intr_handler(irq, dev_id); +} + +/** + * qla4_8xxx_default_intr_handler - hardware interrupt handler. + * @irq: Unused + * @dev_id: Pointer to host adapter structure + * + * This interrupt handler is called directly for MSI-X, and + * called indirectly for MSI. + **/ +irqreturn_t +qla4_8xxx_default_intr_handler(int irq, void *dev_id) +{ + struct scsi_qla_host *ha = dev_id; + unsigned long flags; + uint32_t intr_status; + uint8_t reqs_count = 0; + + spin_lock_irqsave(&ha->hardware_lock, flags); + while (1) { + if (!(readl(&ha->qla4_8xxx_reg->host_int) & + ISRX_82XX_RISC_INT)) { + qla4_8xxx_spurious_interrupt(ha, reqs_count); + break; + } + + intr_status = readl(&ha->qla4_8xxx_reg->host_status); + if ((intr_status & + (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) { + qla4_8xxx_spurious_interrupt(ha, reqs_count); + break; } + + ha->isp_ops->interrupt_service_routine(ha, intr_status); + + if (++reqs_count == MAX_REQS_SERVICED_PER_INTR) + break; } + ha->isr_count++; spin_unlock_irqrestore(&ha->hardware_lock, flags); + return IRQ_HANDLED; +} +irqreturn_t +qla4_8xxx_msix_rsp_q(int irq, void *dev_id) +{ + struct scsi_qla_host *ha = dev_id; + unsigned long flags; + + spin_lock_irqsave(&ha->hardware_lock, flags); + qla4xxx_process_response_queue(ha); + writel(0, &ha->qla4_8xxx_reg->host_int); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + ha->isr_count++; return IRQ_HANDLED; } @@ -825,7 +1009,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) ((ddb_entry->default_time2wait + 4) * HZ); - DEBUG2(printk("scsi%ld: ddb index [%d] initate" + DEBUG2(printk("scsi%ld: ddb [%d] initate" " RELOGIN after %d seconds\n", ha->host_no, ddb_entry->fw_ddb_index, @@ -847,3 +1031,81 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) spin_unlock_irqrestore(&ha->hardware_lock, flags); } +int qla4xxx_request_irqs(struct scsi_qla_host *ha) +{ + int ret; + + if (!is_qla8022(ha)) + goto try_intx; + + if (ql4xenablemsix == 2) + goto try_msi; + + if (ql4xenablemsix == 0 || ql4xenablemsix != 1) + goto try_intx; + + /* Trying MSI-X */ + ret = qla4_8xxx_enable_msix(ha); + if (!ret) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "MSI-X: Enabled (0x%X).\n", ha->revision_id)); + goto irq_attached; + } + + ql4_printk(KERN_WARNING, ha, + "MSI-X: Falling back-to MSI mode -- %d.\n", ret); + +try_msi: + /* Trying MSI */ + ret = pci_enable_msi(ha->pdev); + if (!ret) { + ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler, + IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha); + if (!ret) { + DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n")); + set_bit(AF_MSI_ENABLED, &ha->flags); + goto irq_attached; + } else { + ql4_printk(KERN_WARNING, ha, + "MSI: Failed to reserve interrupt %d " + "already in use.\n", ha->pdev->irq); + pci_disable_msi(ha->pdev); + } + } + ql4_printk(KERN_WARNING, ha, + "MSI: Falling back-to INTx mode -- %d.\n", ret); + +try_intx: + /* Trying INTx */ + ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, + IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha); + if (!ret) { + DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n")); + set_bit(AF_INTx_ENABLED, &ha->flags); + goto irq_attached; + + } else { + ql4_printk(KERN_WARNING, ha, + "INTx: Failed to reserve interrupt %d already in" + " use.\n", ha->pdev->irq); + return ret; + } + +irq_attached: + set_bit(AF_IRQ_ATTACHED, &ha->flags); + ha->host->irq = ha->pdev->irq; + ql4_printk(KERN_INFO, ha, "%s: irq %d attached\n", + __func__, ha->pdev->irq); + return ret; +} + +void qla4xxx_free_irqs(struct scsi_qla_host *ha) +{ + if (test_bit(AF_MSIX_ENABLED, &ha->flags)) + qla4_8xxx_disable_msix(ha); + else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) { + free_irq(ha->pdev->irq, ha); + pci_disable_msi(ha->pdev); + } else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags)) + free_irq(ha->pdev->irq, ha); +} diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 54db6cbbd942..0d3a65268419 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -19,13 +19,13 @@ * @mbx_cmd: data pointer for mailbox in registers. * @mbx_sts: data pointer for mailbox out registers. * - * This routine sssue mailbox commands and waits for completion. + * This routine isssue mailbox commands and waits for completion. * If outCount is 0, this routine completes successfully WITHOUT waiting * for the mailbox command to complete. **/ -static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, - uint8_t outCount, uint32_t *mbx_cmd, - uint32_t *mbx_sts) +int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, + uint8_t outCount, uint32_t *mbx_cmd, + uint32_t *mbx_sts) { int status = QLA_ERROR; uint8_t i; @@ -59,32 +59,66 @@ static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, } /* To prevent overwriting mailbox registers for a command that has - * not yet been serviced, check to see if a previously issued - * mailbox command is interrupting. + * not yet been serviced, check to see if an active command + * (AEN, IOCB, etc.) is interrupting, then service it. * ----------------------------------------------------------------- */ spin_lock_irqsave(&ha->hardware_lock, flags); - intr_status = readl(&ha->reg->ctrl_status); - if (intr_status & CSR_SCSI_PROCESSOR_INTR) { - /* Service existing interrupt */ - qla4xxx_interrupt_service_routine(ha, intr_status); - clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); + + if (is_qla8022(ha)) { + intr_status = readl(&ha->qla4_8xxx_reg->host_int); + if (intr_status & ISRX_82XX_RISC_INT) { + /* Service existing interrupt */ + DEBUG2(printk("scsi%ld: %s: " + "servicing existing interrupt\n", + ha->host_no, __func__)); + intr_status = readl(&ha->qla4_8xxx_reg->host_status); + ha->isp_ops->interrupt_service_routine(ha, intr_status); + clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); + if (test_bit(AF_INTERRUPTS_ON, &ha->flags) && + test_bit(AF_INTx_ENABLED, &ha->flags)) + qla4_8xxx_wr_32(ha, + ha->nx_legacy_intr.tgt_mask_reg, + 0xfbff); + } + } else { + intr_status = readl(&ha->reg->ctrl_status); + if (intr_status & CSR_SCSI_PROCESSOR_INTR) { + /* Service existing interrupt */ + ha->isp_ops->interrupt_service_routine(ha, intr_status); + clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); + } } - /* Send the mailbox command to the firmware */ ha->mbox_status_count = outCount; for (i = 0; i < outCount; i++) ha->mbox_status[i] = 0; - /* Load all mailbox registers, except mailbox 0. */ - for (i = 1; i < inCount; i++) - writel(mbx_cmd[i], &ha->reg->mailbox[i]); + if (is_qla8022(ha)) { + /* Load all mailbox registers, except mailbox 0. */ + DEBUG5( + printk("scsi%ld: %s: Cmd ", ha->host_no, __func__); + for (i = 0; i < inCount; i++) + printk("mb%d=%04x ", i, mbx_cmd[i]); + printk("\n")); + + for (i = 1; i < inCount; i++) + writel(mbx_cmd[i], &ha->qla4_8xxx_reg->mailbox_in[i]); + writel(mbx_cmd[0], &ha->qla4_8xxx_reg->mailbox_in[0]); + readl(&ha->qla4_8xxx_reg->mailbox_in[0]); + writel(HINT_MBX_INT_PENDING, &ha->qla4_8xxx_reg->hint); + } else { + /* Load all mailbox registers, except mailbox 0. */ + for (i = 1; i < inCount; i++) + writel(mbx_cmd[i], &ha->reg->mailbox[i]); + + /* Wakeup firmware */ + writel(mbx_cmd[0], &ha->reg->mailbox[0]); + readl(&ha->reg->mailbox[0]); + writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status); + readl(&ha->reg->ctrl_status); + } - /* Wakeup firmware */ - writel(mbx_cmd[0], &ha->reg->mailbox[0]); - readl(&ha->reg->mailbox[0]); - writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status); - readl(&ha->reg->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Wait for completion */ @@ -98,26 +132,66 @@ static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, status = QLA_SUCCESS; goto mbox_exit; } - /* Wait for command to complete */ - wait_count = jiffies + MBOX_TOV * HZ; - while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { - if (time_after_eq(jiffies, wait_count)) - break; - spin_lock_irqsave(&ha->hardware_lock, flags); - intr_status = readl(&ha->reg->ctrl_status); - if (intr_status & INTR_PENDING) { + /* + * Wait for completion: Poll or completion queue + */ + if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && + test_bit(AF_INTERRUPTS_ON, &ha->flags) && + test_bit(AF_ONLINE, &ha->flags) && + !test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { + /* Do not poll for completion. Use completion queue */ + set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); + wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ); + clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); + } else { + /* Poll for command to complete */ + wait_count = jiffies + MBOX_TOV * HZ; + while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { + if (time_after_eq(jiffies, wait_count)) + break; /* * Service the interrupt. * The ISR will save the mailbox status registers * to a temporary storage location in the adapter * structure. */ - ha->mbox_status_count = outCount; - qla4xxx_interrupt_service_routine(ha, intr_status); + + spin_lock_irqsave(&ha->hardware_lock, flags); + if (is_qla8022(ha)) { + intr_status = + readl(&ha->qla4_8xxx_reg->host_int); + if (intr_status & ISRX_82XX_RISC_INT) { + ha->mbox_status_count = outCount; + intr_status = + readl(&ha->qla4_8xxx_reg->host_status); + ha->isp_ops->interrupt_service_routine( + ha, intr_status); + if (test_bit(AF_INTERRUPTS_ON, + &ha->flags) && + test_bit(AF_INTx_ENABLED, + &ha->flags)) + qla4_8xxx_wr_32(ha, + ha->nx_legacy_intr.tgt_mask_reg, + 0xfbff); + } + } else { + intr_status = readl(&ha->reg->ctrl_status); + if (intr_status & INTR_PENDING) { + /* + * Service the interrupt. + * The ISR will save the mailbox status + * registers to a temporary storage + * location in the adapter structure. + */ + ha->mbox_status_count = outCount; + ha->isp_ops->interrupt_service_routine( + ha, intr_status); + } + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + msleep(10); } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - msleep(10); } /* Check for mailbox timeout. */ @@ -172,7 +246,7 @@ mbox_exit: return status; } -uint8_t +static uint8_t qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) { @@ -196,7 +270,7 @@ qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, return QLA_SUCCESS; } -uint8_t +static uint8_t qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) { @@ -218,7 +292,7 @@ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, return QLA_SUCCESS; } -void +static void qla4xxx_update_local_ip(struct scsi_qla_host *ha, struct addr_ctrl_blk *init_fw_cb) { @@ -256,7 +330,7 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, } } -uint8_t +static uint8_t qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, uint32_t *mbox_sts, @@ -445,7 +519,7 @@ int qla4xxx_get_firmware_state(struct scsi_qla_host * ha) DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n", ha->host_no, __func__, ha->firmware_state);) - return QLA_SUCCESS; + return QLA_SUCCESS; } /** @@ -470,6 +544,10 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) mbox_sts[0])); return QLA_ERROR; } + + ql4_printk(KERN_INFO, ha, "%ld firmare IOCBs available (%d).\n", + ha->host_no, mbox_cmd[2]); + return QLA_SUCCESS; } @@ -500,7 +578,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, /* Make sure the device index is valid */ if (fw_ddb_index >= MAX_DDB_ENTRIES) { - DEBUG2(printk("scsi%ld: %s: index [%d] out of range.\n", + DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n", ha->host_no, __func__, fw_ddb_index)); goto exit_get_fwddb; } @@ -521,7 +599,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, goto exit_get_fwddb; } if (fw_ddb_index != mbox_sts[1]) { - DEBUG2(printk("scsi%ld: %s: index mismatch [%d] != [%d].\n", + DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n", ha->host_no, __func__, fw_ddb_index, mbox_sts[1])); goto exit_get_fwddb; @@ -590,6 +668,7 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, { uint32_t mbox_cmd[MBOX_REG_COUNT]; uint32_t mbox_sts[MBOX_REG_COUNT]; + int status; /* Do not wait for completion. The firmware will send us an * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. @@ -603,7 +682,12 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, mbox_cmd[3] = MSDW(fw_ddb_entry_dma); mbox_cmd[4] = sizeof(struct dev_db_entry); - return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], + &mbox_sts[0]); + DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n", + ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);) + + return status; } /** @@ -817,8 +901,8 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) /** * qla4xxx_reset_lun - issues LUN Reset * @ha: Pointer to host adapter structure. - * @db_entry: Pointer to device database entry - * @un_entry: Pointer to lun entry structure + * @ddb_entry: Pointer to device database entry + * @lun: lun number * * This routine performs a LUN RESET on the specified target/lun. * The caller must ensure that the ddb_entry and lun_entry pointers @@ -832,7 +916,7 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, int status = QLA_SUCCESS; DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, - ddb_entry->os_target_id, lun)); + ddb_entry->fw_ddb_index, lun)); /* * Send lun reset command to ISP, so that the ISP will return all @@ -872,7 +956,7 @@ int qla4xxx_reset_target(struct scsi_qla_host *ha, int status = QLA_SUCCESS; DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no, - ddb_entry->os_target_id)); + ddb_entry->fw_ddb_index)); /* * Send target reset command to ISP, so that the ISP will return all diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c index 7fe0482ecf03..f0d0fbf88aa2 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.c +++ b/drivers/scsi/qla4xxx/ql4_nvram.c @@ -149,7 +149,7 @@ static int eeprom_readword(int eepromAddr, u16 * value, /* Hardware_lock must be set before calling */ u16 rd_nvram_word(struct scsi_qla_host * ha, int offset) { - u16 val; + u16 val = 0; /* NOTE: NVRAM uses half-word addresses */ eeprom_readword(offset, &val, ha); diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h index b47b4fc59d83..7a8fc66a760d 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.h +++ b/drivers/scsi/qla4xxx/ql4_nvram.h @@ -8,9 +8,9 @@ #ifndef _QL4XNVRM_H_ #define _QL4XNVRM_H_ -/* +/** * AM29LV Flash definitions - */ + **/ #define FM93C56A_SIZE_8 0x100 #define FM93C56A_SIZE_16 0x80 #define FM93C66A_SIZE_8 0x200 @@ -19,7 +19,7 @@ #define FM93C56A_START 0x1 -// Commands +/* Commands */ #define FM93C56A_READ 0x2 #define FM93C56A_WEN 0x0 #define FM93C56A_WRITE 0x1 @@ -62,9 +62,9 @@ #define AUBURN_EEPROM_CLK_RISE 0x1 #define AUBURN_EEPROM_CLK_FALL 0x0 -/* */ +/**/ /* EEPROM format */ -/* */ +/**/ struct bios_params { uint16_t SpinUpDelay:1; uint16_t BIOSDisable:1; diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c new file mode 100644 index 000000000000..3e119ae78397 --- /dev/null +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -0,0 +1,2321 @@ +/* + * QLogic iSCSI HBA Driver + * Copyright (c) 2003-2009 QLogic Corporation + * + * See LICENSE.qla4xxx for copyright and licensing details. + */ +#include +#include +#include "ql4_def.h" +#include "ql4_glbl.h" + +#define MASK(n) DMA_BIT_MASK(n) +#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) +#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) +#define MS_WIN(addr) (addr & 0x0ffc0000) +#define QLA82XX_PCI_MN_2M (0) +#define QLA82XX_PCI_MS_2M (0x80000) +#define QLA82XX_PCI_OCM0_2M (0xc0000) +#define VALID_OCM_ADDR(addr) (((addr) & 0x3f800) != 0x3f800) +#define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) + +/* CRB window related */ +#define CRB_BLK(off) ((off >> 20) & 0x3f) +#define CRB_SUBBLK(off) ((off >> 16) & 0xf) +#define CRB_WINDOW_2M (0x130060) +#define CRB_HI(off) ((qla4_8xxx_crb_hub_agt[CRB_BLK(off)] << 20) | \ + ((off) & 0xf0000)) +#define QLA82XX_PCI_CAMQM_2M_END (0x04800800UL) +#define QLA82XX_PCI_CAMQM_2M_BASE (0x000ff800UL) +#define CRB_INDIRECT_2M (0x1e0000UL) + +static inline void __iomem * +qla4_8xxx_pci_base_offsetfset(struct scsi_qla_host *ha, unsigned long off) +{ + if ((off < ha->first_page_group_end) && + (off >= ha->first_page_group_start)) + return (void __iomem *)(ha->nx_pcibase + off); + + return NULL; +} + +#define MAX_CRB_XFORM 60 +static unsigned long crb_addr_xform[MAX_CRB_XFORM]; +static int qla4_8xxx_crb_table_initialized; + +#define qla4_8xxx_crb_addr_transform(name) \ + (crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \ + QLA82XX_HW_CRB_HUB_AGT_ADR_##name << 20) +static void +qla4_8xxx_crb_addr_transform_setup(void) +{ + qla4_8xxx_crb_addr_transform(XDMA); + qla4_8xxx_crb_addr_transform(TIMR); + qla4_8xxx_crb_addr_transform(SRE); + qla4_8xxx_crb_addr_transform(SQN3); + qla4_8xxx_crb_addr_transform(SQN2); + qla4_8xxx_crb_addr_transform(SQN1); + qla4_8xxx_crb_addr_transform(SQN0); + qla4_8xxx_crb_addr_transform(SQS3); + qla4_8xxx_crb_addr_transform(SQS2); + qla4_8xxx_crb_addr_transform(SQS1); + qla4_8xxx_crb_addr_transform(SQS0); + qla4_8xxx_crb_addr_transform(RPMX7); + qla4_8xxx_crb_addr_transform(RPMX6); + qla4_8xxx_crb_addr_transform(RPMX5); + qla4_8xxx_crb_addr_transform(RPMX4); + qla4_8xxx_crb_addr_transform(RPMX3); + qla4_8xxx_crb_addr_transform(RPMX2); + qla4_8xxx_crb_addr_transform(RPMX1); + qla4_8xxx_crb_addr_transform(RPMX0); + qla4_8xxx_crb_addr_transform(ROMUSB); + qla4_8xxx_crb_addr_transform(SN); + qla4_8xxx_crb_addr_transform(QMN); + qla4_8xxx_crb_addr_transform(QMS); + qla4_8xxx_crb_addr_transform(PGNI); + qla4_8xxx_crb_addr_transform(PGND); + qla4_8xxx_crb_addr_transform(PGN3); + qla4_8xxx_crb_addr_transform(PGN2); + qla4_8xxx_crb_addr_transform(PGN1); + qla4_8xxx_crb_addr_transform(PGN0); + qla4_8xxx_crb_addr_transform(PGSI); + qla4_8xxx_crb_addr_transform(PGSD); + qla4_8xxx_crb_addr_transform(PGS3); + qla4_8xxx_crb_addr_transform(PGS2); + qla4_8xxx_crb_addr_transform(PGS1); + qla4_8xxx_crb_addr_transform(PGS0); + qla4_8xxx_crb_addr_transform(PS); + qla4_8xxx_crb_addr_transform(PH); + qla4_8xxx_crb_addr_transform(NIU); + qla4_8xxx_crb_addr_transform(I2Q); + qla4_8xxx_crb_addr_transform(EG); + qla4_8xxx_crb_addr_transform(MN); + qla4_8xxx_crb_addr_transform(MS); + qla4_8xxx_crb_addr_transform(CAS2); + qla4_8xxx_crb_addr_transform(CAS1); + qla4_8xxx_crb_addr_transform(CAS0); + qla4_8xxx_crb_addr_transform(CAM); + qla4_8xxx_crb_addr_transform(C2C1); + qla4_8xxx_crb_addr_transform(C2C0); + qla4_8xxx_crb_addr_transform(SMB); + qla4_8xxx_crb_addr_transform(OCM0); + qla4_8xxx_crb_addr_transform(I2C0); + + qla4_8xxx_crb_table_initialized = 1; +} + +static struct crb_128M_2M_block_map crb_128M_2M_map[64] = { + {{{0, 0, 0, 0} } }, /* 0: PCI */ + {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ + {1, 0x0110000, 0x0120000, 0x130000}, + {1, 0x0120000, 0x0122000, 0x124000}, + {1, 0x0130000, 0x0132000, 0x126000}, + {1, 0x0140000, 0x0142000, 0x128000}, + {1, 0x0150000, 0x0152000, 0x12a000}, + {1, 0x0160000, 0x0170000, 0x110000}, + {1, 0x0170000, 0x0172000, 0x12e000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x01e0000, 0x01e0800, 0x122000}, + {0, 0x0000000, 0x0000000, 0x000000} } }, + {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */ + {{{0, 0, 0, 0} } }, /* 3: */ + {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */ + {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */ + {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */ + {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */ + {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */ + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x08f0000, 0x08f2000, 0x172000} } }, + {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/ + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x09f0000, 0x09f2000, 0x176000} } }, + {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/ + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x0af0000, 0x0af2000, 0x17a000} } }, + {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/ + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x0bf0000, 0x0bf2000, 0x17e000} } }, + {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */ + {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */ + {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */ + {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */ + {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */ + {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */ + {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */ + {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */ + {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */ + {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */ + {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */ + {{{0, 0, 0, 0} } }, /* 23: */ + {{{0, 0, 0, 0} } }, /* 24: */ + {{{0, 0, 0, 0} } }, /* 25: */ + {{{0, 0, 0, 0} } }, /* 26: */ + {{{0, 0, 0, 0} } }, /* 27: */ + {{{0, 0, 0, 0} } }, /* 28: */ + {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */ + {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */ + {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */ + {{{0} } }, /* 32: PCI */ + {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */ + {1, 0x2110000, 0x2120000, 0x130000}, + {1, 0x2120000, 0x2122000, 0x124000}, + {1, 0x2130000, 0x2132000, 0x126000}, + {1, 0x2140000, 0x2142000, 0x128000}, + {1, 0x2150000, 0x2152000, 0x12a000}, + {1, 0x2160000, 0x2170000, 0x110000}, + {1, 0x2170000, 0x2172000, 0x12e000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000} } }, + {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */ + {{{0} } }, /* 35: */ + {{{0} } }, /* 36: */ + {{{0} } }, /* 37: */ + {{{0} } }, /* 38: */ + {{{0} } }, /* 39: */ + {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */ + {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */ + {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */ + {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */ + {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */ + {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */ + {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */ + {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */ + {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */ + {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */ + {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */ + {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */ + {{{0} } }, /* 52: */ + {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */ + {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */ + {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */ + {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */ + {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */ + {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */ + {{{0} } }, /* 59: I2C0 */ + {{{0} } }, /* 60: I2C1 */ + {{{1, 0x3d00000, 0x3d04000, 0x1dc000} } },/* 61: LPC */ + {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */ + {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */ +}; + +/* + * top 12 bits of crb internal address (hub, agent) + */ +static unsigned qla4_8xxx_crb_hub_agt[64] = { + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_PS, + QLA82XX_HW_CRB_HUB_AGT_ADR_MN, + QLA82XX_HW_CRB_HUB_AGT_ADR_MS, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_SRE, + QLA82XX_HW_CRB_HUB_AGT_ADR_NIU, + QLA82XX_HW_CRB_HUB_AGT_ADR_QMN, + QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0, + QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1, + QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2, + QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3, + QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q, + QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR, + QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4, + QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGND, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI, + QLA82XX_HW_CRB_HUB_AGT_ADR_SN, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_EG, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_PS, + QLA82XX_HW_CRB_HUB_AGT_ADR_CAM, + 0, + 0, + 0, + 0, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7, + QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA, + QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q, + QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8, + QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9, + QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_SMB, + QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0, + QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1, + 0, + QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC, + 0, +}; + +/* Device states */ +static char *qdev_state[] = { + "Unknown", + "Cold", + "Initializing", + "Ready", + "Need Reset", + "Need Quiescent", + "Failed", + "Quiescent", +}; + +/* + * In: 'off' is offset from CRB space in 128M pci map + * Out: 'off' is 2M pci map addr + * side effect: lock crb window + */ +static void +qla4_8xxx_pci_set_crbwindow_2M(struct scsi_qla_host *ha, ulong *off) +{ + u32 win_read; + + ha->crb_win = CRB_HI(*off); + writel(ha->crb_win, + (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); + + /* Read back value to make sure write has gone through before trying + * to use it. */ + win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); + if (win_read != ha->crb_win) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: Written crbwin (0x%x) != Read crbwin (0x%x)," + " off=0x%lx\n", __func__, ha->crb_win, win_read, *off)); + } + *off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase; +} + +void +qla4_8xxx_wr_32(struct scsi_qla_host *ha, ulong off, u32 data) +{ + unsigned long flags = 0; + int rv; + + rv = qla4_8xxx_pci_get_crb_addr_2M(ha, &off); + + BUG_ON(rv == -1); + + if (rv == 1) { + write_lock_irqsave(&ha->hw_lock, flags); + qla4_8xxx_crb_win_lock(ha); + qla4_8xxx_pci_set_crbwindow_2M(ha, &off); + } + + writel(data, (void __iomem *)off); + + if (rv == 1) { + qla4_8xxx_crb_win_unlock(ha); + write_unlock_irqrestore(&ha->hw_lock, flags); + } +} + +int +qla4_8xxx_rd_32(struct scsi_qla_host *ha, ulong off) +{ + unsigned long flags = 0; + int rv; + u32 data; + + rv = qla4_8xxx_pci_get_crb_addr_2M(ha, &off); + + BUG_ON(rv == -1); + + if (rv == 1) { + write_lock_irqsave(&ha->hw_lock, flags); + qla4_8xxx_crb_win_lock(ha); + qla4_8xxx_pci_set_crbwindow_2M(ha, &off); + } + data = readl((void __iomem *)off); + + if (rv == 1) { + qla4_8xxx_crb_win_unlock(ha); + write_unlock_irqrestore(&ha->hw_lock, flags); + } + return data; +} + +#define CRB_WIN_LOCK_TIMEOUT 100000000 + +int qla4_8xxx_crb_win_lock(struct scsi_qla_host *ha) +{ + int i; + int done = 0, timeout = 0; + + while (!done) { + /* acquire semaphore3 from PCI HW block */ + done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK)); + if (done == 1) + break; + if (timeout >= CRB_WIN_LOCK_TIMEOUT) + return -1; + + timeout++; + + /* Yield CPU */ + if (!in_interrupt()) + schedule(); + else { + for (i = 0; i < 20; i++) + cpu_relax(); /*This a nop instr on i386*/ + } + } + qla4_8xxx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num); + return 0; +} + +void qla4_8xxx_crb_win_unlock(struct scsi_qla_host *ha) +{ + qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); +} + +#define IDC_LOCK_TIMEOUT 100000000 + +/** + * qla4_8xxx_idc_lock - hw_lock + * @ha: pointer to adapter structure + * + * General purpose lock used to synchronize access to + * CRB_DEV_STATE, CRB_DEV_REF_COUNT, etc. + **/ +int qla4_8xxx_idc_lock(struct scsi_qla_host *ha) +{ + int i; + int done = 0, timeout = 0; + + while (!done) { + /* acquire semaphore5 from PCI HW block */ + done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_LOCK)); + if (done == 1) + break; + if (timeout >= IDC_LOCK_TIMEOUT) + return -1; + + timeout++; + + /* Yield CPU */ + if (!in_interrupt()) + schedule(); + else { + for (i = 0; i < 20; i++) + cpu_relax(); /*This a nop instr on i386*/ + } + } + return 0; +} + +void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha) +{ + qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK)); +} + +int +qla4_8xxx_pci_get_crb_addr_2M(struct scsi_qla_host *ha, ulong *off) +{ + struct crb_128M_2M_sub_block_map *m; + + if (*off >= QLA82XX_CRB_MAX) + return -1; + + if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) { + *off = (*off - QLA82XX_PCI_CAMQM) + + QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase; + return 0; + } + + if (*off < QLA82XX_PCI_CRBSPACE) + return -1; + + *off -= QLA82XX_PCI_CRBSPACE; + /* + * Try direct map + */ + + m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; + + if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { + *off = *off + m->start_2M - m->start_128M + ha->nx_pcibase; + return 0; + } + + /* + * Not in direct map, use crb window + */ + return 1; +} + +/* PCI Windowing for DDR regions. */ +#define QLA82XX_ADDR_IN_RANGE(addr, low, high) \ + (((addr) <= (high)) && ((addr) >= (low))) + +/* +* check memory access boundary. +* used by test agent. support ddr access only for now +*/ +static unsigned long +qla4_8xxx_pci_mem_bound_check(struct scsi_qla_host *ha, + unsigned long long addr, int size) +{ + if (!QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, + QLA82XX_ADDR_DDR_NET_MAX) || + !QLA82XX_ADDR_IN_RANGE(addr + size - 1, + QLA82XX_ADDR_DDR_NET, QLA82XX_ADDR_DDR_NET_MAX) || + ((size != 1) && (size != 2) && (size != 4) && (size != 8))) { + return 0; + } + return 1; +} + +static int qla4_8xxx_pci_set_window_warning_count; + +static unsigned long +qla4_8xxx_pci_set_window(struct scsi_qla_host *ha, unsigned long long addr) +{ + int window; + u32 win_read; + + if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, + QLA82XX_ADDR_DDR_NET_MAX)) { + /* DDR network side */ + window = MN_WIN(addr); + ha->ddr_mn_window = window; + qla4_8xxx_wr_32(ha, ha->mn_win_crb | + QLA82XX_PCI_CRBSPACE, window); + win_read = qla4_8xxx_rd_32(ha, ha->mn_win_crb | + QLA82XX_PCI_CRBSPACE); + if ((win_read << 17) != window) { + ql4_printk(KERN_WARNING, ha, + "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n", + __func__, window, win_read); + } + addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET; + } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0, + QLA82XX_ADDR_OCM0_MAX)) { + unsigned int temp1; + /* if bits 19:18&17:11 are on */ + if ((addr & 0x00ff800) == 0xff800) { + printk("%s: QM access not handled.\n", __func__); + addr = -1UL; + } + + window = OCM_WIN(addr); + ha->ddr_mn_window = window; + qla4_8xxx_wr_32(ha, ha->mn_win_crb | + QLA82XX_PCI_CRBSPACE, window); + win_read = qla4_8xxx_rd_32(ha, ha->mn_win_crb | + QLA82XX_PCI_CRBSPACE); + temp1 = ((window & 0x1FF) << 7) | + ((window & 0x0FFFE0000) >> 17); + if (win_read != temp1) { + printk("%s: Written OCMwin (0x%x) != Read" + " OCMwin (0x%x)\n", __func__, temp1, win_read); + } + addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M; + + } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, + QLA82XX_P3_ADDR_QDR_NET_MAX)) { + /* QDR network side */ + window = MS_WIN(addr); + ha->qdr_sn_window = window; + qla4_8xxx_wr_32(ha, ha->ms_win_crb | + QLA82XX_PCI_CRBSPACE, window); + win_read = qla4_8xxx_rd_32(ha, + ha->ms_win_crb | QLA82XX_PCI_CRBSPACE); + if (win_read != window) { + printk("%s: Written MSwin (0x%x) != Read " + "MSwin (0x%x)\n", __func__, window, win_read); + } + addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_QDR_NET; + + } else { + /* + * peg gdb frequently accesses memory that doesn't exist, + * this limits the chit chat so debugging isn't slowed down. + */ + if ((qla4_8xxx_pci_set_window_warning_count++ < 8) || + (qla4_8xxx_pci_set_window_warning_count%64 == 0)) { + printk("%s: Warning:%s Unknown address range!\n", + __func__, DRIVER_NAME); + } + addr = -1UL; + } + return addr; +} + +/* check if address is in the same windows as the previous access */ +static int qla4_8xxx_pci_is_same_window(struct scsi_qla_host *ha, + unsigned long long addr) +{ + int window; + unsigned long long qdr_max; + + qdr_max = QLA82XX_P3_ADDR_QDR_NET_MAX; + + if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, + QLA82XX_ADDR_DDR_NET_MAX)) { + /* DDR network side */ + BUG(); /* MN access can not come here */ + } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0, + QLA82XX_ADDR_OCM0_MAX)) { + return 1; + } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM1, + QLA82XX_ADDR_OCM1_MAX)) { + return 1; + } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, + qdr_max)) { + /* QDR network side */ + window = ((addr - QLA82XX_ADDR_QDR_NET) >> 22) & 0x3f; + if (ha->qdr_sn_window == window) + return 1; + } + + return 0; +} + +static int qla4_8xxx_pci_mem_read_direct(struct scsi_qla_host *ha, + u64 off, void *data, int size) +{ + unsigned long flags; + void __iomem *addr; + int ret = 0; + u64 start; + void __iomem *mem_ptr = NULL; + unsigned long mem_base; + unsigned long mem_page; + + write_lock_irqsave(&ha->hw_lock, flags); + + /* + * If attempting to access unknown address or straddle hw windows, + * do not access. + */ + start = qla4_8xxx_pci_set_window(ha, off); + if ((start == -1UL) || + (qla4_8xxx_pci_is_same_window(ha, off + size - 1) == 0)) { + write_unlock_irqrestore(&ha->hw_lock, flags); + printk(KERN_ERR"%s out of bound pci memory access. " + "offset is 0x%llx\n", DRIVER_NAME, off); + return -1; + } + + addr = qla4_8xxx_pci_base_offsetfset(ha, start); + if (!addr) { + write_unlock_irqrestore(&ha->hw_lock, flags); + mem_base = pci_resource_start(ha->pdev, 0); + mem_page = start & PAGE_MASK; + /* Map two pages whenever user tries to access addresses in two + consecutive pages. + */ + if (mem_page != ((start + size - 1) & PAGE_MASK)) + mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); + else + mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); + + if (mem_ptr == NULL) { + *(u8 *)data = 0; + return -1; + } + addr = mem_ptr; + addr += start & (PAGE_SIZE - 1); + write_lock_irqsave(&ha->hw_lock, flags); + } + + switch (size) { + case 1: + *(u8 *)data = readb(addr); + break; + case 2: + *(u16 *)data = readw(addr); + break; + case 4: + *(u32 *)data = readl(addr); + break; + case 8: + *(u64 *)data = readq(addr); + break; + default: + ret = -1; + break; + } + write_unlock_irqrestore(&ha->hw_lock, flags); + + if (mem_ptr) + iounmap(mem_ptr); + return ret; +} + +static int +qla4_8xxx_pci_mem_write_direct(struct scsi_qla_host *ha, u64 off, + void *data, int size) +{ + unsigned long flags; + void __iomem *addr; + int ret = 0; + u64 start; + void __iomem *mem_ptr = NULL; + unsigned long mem_base; + unsigned long mem_page; + + write_lock_irqsave(&ha->hw_lock, flags); + + /* + * If attempting to access unknown address or straddle hw windows, + * do not access. + */ + start = qla4_8xxx_pci_set_window(ha, off); + if ((start == -1UL) || + (qla4_8xxx_pci_is_same_window(ha, off + size - 1) == 0)) { + write_unlock_irqrestore(&ha->hw_lock, flags); + printk(KERN_ERR"%s out of bound pci memory access. " + "offset is 0x%llx\n", DRIVER_NAME, off); + return -1; + } + + addr = qla4_8xxx_pci_base_offsetfset(ha, start); + if (!addr) { + write_unlock_irqrestore(&ha->hw_lock, flags); + mem_base = pci_resource_start(ha->pdev, 0); + mem_page = start & PAGE_MASK; + /* Map two pages whenever user tries to access addresses in two + consecutive pages. + */ + if (mem_page != ((start + size - 1) & PAGE_MASK)) + mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); + else + mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); + if (mem_ptr == NULL) + return -1; + + addr = mem_ptr; + addr += start & (PAGE_SIZE - 1); + write_lock_irqsave(&ha->hw_lock, flags); + } + + switch (size) { + case 1: + writeb(*(u8 *)data, addr); + break; + case 2: + writew(*(u16 *)data, addr); + break; + case 4: + writel(*(u32 *)data, addr); + break; + case 8: + writeq(*(u64 *)data, addr); + break; + default: + ret = -1; + break; + } + write_unlock_irqrestore(&ha->hw_lock, flags); + if (mem_ptr) + iounmap(mem_ptr); + return ret; +} + +#define MTU_FUDGE_FACTOR 100 + +static unsigned long +qla4_8xxx_decode_crb_addr(unsigned long addr) +{ + int i; + unsigned long base_addr, offset, pci_base; + + if (!qla4_8xxx_crb_table_initialized) + qla4_8xxx_crb_addr_transform_setup(); + + pci_base = ADDR_ERROR; + base_addr = addr & 0xfff00000; + offset = addr & 0x000fffff; + + for (i = 0; i < MAX_CRB_XFORM; i++) { + if (crb_addr_xform[i] == base_addr) { + pci_base = i << 20; + break; + } + } + if (pci_base == ADDR_ERROR) + return pci_base; + else + return pci_base + offset; +} + +static long rom_max_timeout = 100; +static long qla4_8xxx_rom_lock_timeout = 100; + +static int +qla4_8xxx_rom_lock(struct scsi_qla_host *ha) +{ + int i; + int done = 0, timeout = 0; + + while (!done) { + /* acquire semaphore2 from PCI HW block */ + + done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); + if (done == 1) + break; + if (timeout >= qla4_8xxx_rom_lock_timeout) + return -1; + + timeout++; + + /* Yield CPU */ + if (!in_interrupt()) + schedule(); + else { + for (i = 0; i < 20; i++) + cpu_relax(); /*This a nop instr on i386*/ + } + } + qla4_8xxx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER); + return 0; +} + +static void +qla4_8xxx_rom_unlock(struct scsi_qla_host *ha) +{ + qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); +} + +static int +qla4_8xxx_wait_rom_done(struct scsi_qla_host *ha) +{ + long timeout = 0; + long done = 0 ; + + while (done == 0) { + done = qla4_8xxx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS); + done &= 2; + timeout++; + if (timeout >= rom_max_timeout) { + printk("%s: Timeout reached waiting for rom done", + DRIVER_NAME); + return -1; + } + } + return 0; +} + +static int +qla4_8xxx_do_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp) +{ + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr); + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3); + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0xb); + if (qla4_8xxx_wait_rom_done(ha)) { + printk("%s: Error waiting for rom done\n", DRIVER_NAME); + return -1; + } + /* reset abyte_cnt and dummy_byte_cnt */ + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + udelay(10); + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0); + + *valp = qla4_8xxx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA); + return 0; +} + +static int +qla4_8xxx_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp) +{ + int ret, loops = 0; + + while ((qla4_8xxx_rom_lock(ha) != 0) && (loops < 50000)) { + udelay(100); + loops++; + } + if (loops >= 50000) { + printk("%s: qla4_8xxx_rom_lock failed\n", DRIVER_NAME); + return -1; + } + ret = qla4_8xxx_do_rom_fast_read(ha, addr, valp); + qla4_8xxx_rom_unlock(ha); + return ret; +} + +/** + * This routine does CRB initialize sequence + * to put the ISP into operational state + **/ +static int +qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) +{ + int addr, val; + int i ; + struct crb_addr_pair *buf; + unsigned long off; + unsigned offset, n; + + struct crb_addr_pair { + long addr; + long data; + }; + + /* Halt all the indiviual PEGs and other blocks of the ISP */ + qla4_8xxx_rom_lock(ha); + if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) + /* don't reset CAM block on reset */ + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); + else + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff); + + qla4_8xxx_rom_unlock(ha); + + /* Read the signature value from the flash. + * Offset 0: Contain signature (0xcafecafe) + * Offset 4: Offset and number of addr/value pairs + * that present in CRB initialize sequence + */ + if (qla4_8xxx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL || + qla4_8xxx_rom_fast_read(ha, 4, &n) != 0) { + ql4_printk(KERN_WARNING, ha, + "[ERROR] Reading crb_init area: n: %08x\n", n); + return -1; + } + + /* Offset in flash = lower 16 bits + * Number of enteries = upper 16 bits + */ + offset = n & 0xffffU; + n = (n >> 16) & 0xffffU; + + /* number of addr/value pair should not exceed 1024 enteries */ + if (n >= 1024) { + ql4_printk(KERN_WARNING, ha, + "%s: %s:n=0x%x [ERROR] Card flash not initialized.\n", + DRIVER_NAME, __func__, n); + return -1; + } + + ql4_printk(KERN_INFO, ha, + "%s: %d CRB init values found in ROM.\n", DRIVER_NAME, n); + + buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL); + if (buf == NULL) { + ql4_printk(KERN_WARNING, ha, + "%s: [ERROR] Unable to malloc memory.\n", DRIVER_NAME); + return -1; + } + + for (i = 0; i < n; i++) { + if (qla4_8xxx_rom_fast_read(ha, 8*i + 4*offset, &val) != 0 || + qla4_8xxx_rom_fast_read(ha, 8*i + 4*offset + 4, &addr) != + 0) { + kfree(buf); + return -1; + } + + buf[i].addr = addr; + buf[i].data = val; + } + + for (i = 0; i < n; i++) { + /* Translate internal CRB initialization + * address to PCI bus address + */ + off = qla4_8xxx_decode_crb_addr((unsigned long)buf[i].addr) + + QLA82XX_PCI_CRBSPACE; + /* Not all CRB addr/value pair to be written, + * some of them are skipped + */ + + /* skip if LS bit is set*/ + if (off & 0x1) { + DEBUG2(ql4_printk(KERN_WARNING, ha, + "Skip CRB init replay for offset = 0x%lx\n", off)); + continue; + } + + /* skipping cold reboot MAGIC */ + if (off == QLA82XX_CAM_RAM(0x1fc)) + continue; + + /* do not reset PCI */ + if (off == (ROMUSB_GLB + 0xbc)) + continue; + + /* skip core clock, so that firmware can increase the clock */ + if (off == (ROMUSB_GLB + 0xc8)) + continue; + + /* skip the function enable register */ + if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION)) + continue; + + if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION2)) + continue; + + if ((off & 0x0ff00000) == QLA82XX_CRB_SMB) + continue; + + if ((off & 0x0ff00000) == QLA82XX_CRB_DDR_NET) + continue; + + if (off == ADDR_ERROR) { + ql4_printk(KERN_WARNING, ha, + "%s: [ERROR] Unknown addr: 0x%08lx\n", + DRIVER_NAME, buf[i].addr); + continue; + } + + qla4_8xxx_wr_32(ha, off, buf[i].data); + + /* ISP requires much bigger delay to settle down, + * else crb_window returns 0xffffffff + */ + if (off == QLA82XX_ROMUSB_GLB_SW_RESET) + msleep(1000); + + /* ISP requires millisec delay between + * successive CRB register updation + */ + msleep(1); + } + + kfree(buf); + + /* Resetting the data and instruction cache */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0xec, 0x1e); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0x4c, 8); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_I+0x4c, 8); + + /* Clear all protocol processing engines */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0x8, 0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0xc, 0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0x8, 0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0xc, 0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0x8, 0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0xc, 0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0x8, 0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0xc, 0); + + return 0; +} + +static int qla4_8xxx_check_for_bad_spd(struct scsi_qla_host *ha) +{ + u32 val = 0; + val = qla4_8xxx_rd_32(ha, BOOT_LOADER_DIMM_STATUS) ; + val &= QLA82XX_BOOT_LOADER_MN_ISSUE; + if (val & QLA82XX_PEG_TUNE_MN_SPD_ZEROED) { + printk("Memory DIMM SPD not programmed. Assumed valid.\n"); + return 1; + } else if (val) { + printk("Memory DIMM type incorrect. Info:%08X.\n", val); + return 2; + } + return 0; +} + +static int +qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start) +{ + int i; + long size = 0; + long flashaddr, memaddr; + u64 data; + u32 high, low; + + flashaddr = memaddr = ha->hw.flt_region_bootload; + size = (image_start - flashaddr)/8; + + DEBUG2(printk("scsi%ld: %s: bootldr=0x%lx, fw_image=0x%x\n", + ha->host_no, __func__, flashaddr, image_start)); + + for (i = 0; i < size; i++) { + if ((qla4_8xxx_rom_fast_read(ha, flashaddr, (int *)&low)) || + (qla4_8xxx_rom_fast_read(ha, flashaddr + 4, + (int *)&high))) { + return -1; + } + data = ((u64)high << 32) | low ; + qla4_8xxx_pci_mem_write_2M(ha, memaddr, &data, 8); + flashaddr += 8; + memaddr += 8; + + if (i%0x1000 == 0) + msleep(1); + + } + + udelay(100); + + read_lock(&ha->hw_lock); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); + read_unlock(&ha->hw_lock); + + return 0; +} + +static int qla4_8xxx_load_fw(struct scsi_qla_host *ha, uint32_t image_start) +{ + u32 rst; + + qla4_8xxx_wr_32(ha, CRB_CMDPEG_STATE, 0); + if (qla4_8xxx_pinit_from_rom(ha, 0) != QLA_SUCCESS) { + printk(KERN_WARNING "%s: Error during CRB Initialization\n", + __func__); + return QLA_ERROR; + } + + udelay(500); + + /* at this point, QM is in reset. This could be a problem if there are + * incoming d* transition queue messages. QM/PCIE could wedge. + * To get around this, QM is brought out of reset. + */ + + rst = qla4_8xxx_rd_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET); + /* unreset qm */ + rst &= ~(1 << 28); + qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, rst); + + if (qla4_8xxx_load_from_flash(ha, image_start)) { + printk("%s: Error trying to load fw from flash!\n", __func__); + return QLA_ERROR; + } + + return QLA_SUCCESS; +} + +int +qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *ha, + u64 off, void *data, int size) +{ + int i, j = 0, k, start, end, loop, sz[2], off0[2]; + int shift_amount; + uint32_t temp; + uint64_t off8, val, mem_crb, word[2] = {0, 0}; + + /* + * If not MN, go check for MS or invalid. + */ + + if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) + mem_crb = QLA82XX_CRB_QDR_NET; + else { + mem_crb = QLA82XX_CRB_DDR_NET; + if (qla4_8xxx_pci_mem_bound_check(ha, off, size) == 0) + return qla4_8xxx_pci_mem_read_direct(ha, + off, data, size); + } + + + off8 = off & 0xfffffff0; + off0[0] = off & 0xf; + sz[0] = (size < (16 - off0[0])) ? size : (16 - off0[0]); + shift_amount = 4; + + loop = ((off0[0] + size - 1) >> shift_amount) + 1; + off0[1] = 0; + sz[1] = size - sz[0]; + + for (i = 0; i < loop; i++) { + temp = off8 + (i << shift_amount); + qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); + temp = 0; + qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); + temp = MIU_TA_CTL_ENABLE; + qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); + temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; + qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); + + for (j = 0; j < MAX_CTL_CHECK; j++) { + temp = qla4_8xxx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); + if ((temp & MIU_TA_CTL_BUSY) == 0) + break; + } + + if (j >= MAX_CTL_CHECK) { + if (printk_ratelimit()) + ql4_printk(KERN_ERR, ha, + "failed to read through agent\n"); + break; + } + + start = off0[i] >> 2; + end = (off0[i] + sz[i] - 1) >> 2; + for (k = start; k <= end; k++) { + temp = qla4_8xxx_rd_32(ha, + mem_crb + MIU_TEST_AGT_RDDATA(k)); + word[i] |= ((uint64_t)temp << (32 * (k & 1))); + } + } + + if (j >= MAX_CTL_CHECK) + return -1; + + if ((off0[0] & 7) == 0) { + val = word[0]; + } else { + val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | + ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); + } + + switch (size) { + case 1: + *(uint8_t *)data = val; + break; + case 2: + *(uint16_t *)data = val; + break; + case 4: + *(uint32_t *)data = val; + break; + case 8: + *(uint64_t *)data = val; + break; + } + return 0; +} + +int +qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha, + u64 off, void *data, int size) +{ + int i, j, ret = 0, loop, sz[2], off0; + int scale, shift_amount, startword; + uint32_t temp; + uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; + + /* + * If not MN, go check for MS or invalid. + */ + if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) + mem_crb = QLA82XX_CRB_QDR_NET; + else { + mem_crb = QLA82XX_CRB_DDR_NET; + if (qla4_8xxx_pci_mem_bound_check(ha, off, size) == 0) + return qla4_8xxx_pci_mem_write_direct(ha, + off, data, size); + } + + off0 = off & 0x7; + sz[0] = (size < (8 - off0)) ? size : (8 - off0); + sz[1] = size - sz[0]; + + off8 = off & 0xfffffff0; + loop = (((off & 0xf) + size - 1) >> 4) + 1; + shift_amount = 4; + scale = 2; + startword = (off & 0xf)/8; + + for (i = 0; i < loop; i++) { + if (qla4_8xxx_pci_mem_read_2M(ha, off8 + + (i << shift_amount), &word[i * scale], 8)) + return -1; + } + + switch (size) { + case 1: + tmpw = *((uint8_t *)data); + break; + case 2: + tmpw = *((uint16_t *)data); + break; + case 4: + tmpw = *((uint32_t *)data); + break; + case 8: + default: + tmpw = *((uint64_t *)data); + break; + } + + if (sz[0] == 8) + word[startword] = tmpw; + else { + word[startword] &= + ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); + word[startword] |= tmpw << (off0 * 8); + } + + if (sz[1] != 0) { + word[startword+1] &= ~(~0ULL << (sz[1] * 8)); + word[startword+1] |= tmpw >> (sz[0] * 8); + } + + for (i = 0; i < loop; i++) { + temp = off8 + (i << shift_amount); + qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); + temp = 0; + qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); + temp = word[i * scale] & 0xffffffff; + qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); + temp = (word[i * scale] >> 32) & 0xffffffff; + qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); + temp = word[i*scale + 1] & 0xffffffff; + qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_UPPER_LO, + temp); + temp = (word[i*scale + 1] >> 32) & 0xffffffff; + qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_UPPER_HI, + temp); + + temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; + qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); + temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; + qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); + + for (j = 0; j < MAX_CTL_CHECK; j++) { + temp = qla4_8xxx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); + if ((temp & MIU_TA_CTL_BUSY) == 0) + break; + } + + if (j >= MAX_CTL_CHECK) { + if (printk_ratelimit()) + ql4_printk(KERN_ERR, ha, + "failed to write through agent\n"); + ret = -1; + break; + } + } + + return ret; +} + +static int qla4_8xxx_cmdpeg_ready(struct scsi_qla_host *ha, int pegtune_val) +{ + u32 val = 0; + int retries = 60; + + if (!pegtune_val) { + do { + val = qla4_8xxx_rd_32(ha, CRB_CMDPEG_STATE); + if ((val == PHAN_INITIALIZE_COMPLETE) || + (val == PHAN_INITIALIZE_ACK)) + return 0; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(500); + + } while (--retries); + + qla4_8xxx_check_for_bad_spd(ha); + + if (!retries) { + pegtune_val = qla4_8xxx_rd_32(ha, + QLA82XX_ROMUSB_GLB_PEGTUNE_DONE); + printk(KERN_WARNING "%s: init failed, " + "pegtune_val = %x\n", __func__, pegtune_val); + return -1; + } + } + return 0; +} + +static int qla4_8xxx_rcvpeg_ready(struct scsi_qla_host *ha) +{ + uint32_t state = 0; + int loops = 0; + + /* Window 1 call */ + read_lock(&ha->hw_lock); + state = qla4_8xxx_rd_32(ha, CRB_RCVPEG_STATE); + read_unlock(&ha->hw_lock); + + while ((state != PHAN_PEG_RCV_INITIALIZED) && (loops < 30000)) { + udelay(100); + /* Window 1 call */ + read_lock(&ha->hw_lock); + state = qla4_8xxx_rd_32(ha, CRB_RCVPEG_STATE); + read_unlock(&ha->hw_lock); + + loops++; + } + + if (loops >= 30000) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "Receive Peg initialization not complete: 0x%x.\n", state)); + return QLA_ERROR; + } + + return QLA_SUCCESS; +} + +static inline void +qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) +{ + uint32_t drv_active; + + drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); + drv_active |= (1 << (ha->func_num * 4)); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); +} + +void +qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) +{ + uint32_t drv_active; + + drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); + drv_active &= ~(1 << (ha->func_num * 4)); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); +} + +static inline int +qla4_8xxx_need_reset(struct scsi_qla_host *ha) +{ + uint32_t drv_state; + int rval; + + drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + rval = drv_state & (1 << (ha->func_num * 4)); + return rval; +} + +static inline void +qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha) +{ + uint32_t drv_state; + + drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + drv_state |= (1 << (ha->func_num * 4)); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); +} + +static inline void +qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha) +{ + uint32_t drv_state; + + drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + drv_state &= ~(1 << (ha->func_num * 4)); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); +} + +static inline void +qla4_8xxx_set_qsnt_ready(struct scsi_qla_host *ha) +{ + uint32_t qsnt_state; + + qsnt_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + qsnt_state |= (2 << (ha->func_num * 4)); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state); +} + + +static int +qla4_8xxx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start) +{ + int pcie_cap; + uint16_t lnk; + + /* scrub dma mask expansion register */ + qla4_8xxx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555); + + /* Overwrite stale initialization register values */ + qla4_8xxx_wr_32(ha, CRB_CMDPEG_STATE, 0); + qla4_8xxx_wr_32(ha, CRB_RCVPEG_STATE, 0); + qla4_8xxx_wr_32(ha, QLA82XX_PEG_HALT_STATUS1, 0); + qla4_8xxx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0); + + if (qla4_8xxx_load_fw(ha, image_start) != QLA_SUCCESS) { + printk("%s: Error trying to start fw!\n", __func__); + return QLA_ERROR; + } + + /* Handshake with the card before we register the devices. */ + if (qla4_8xxx_cmdpeg_ready(ha, 0) != QLA_SUCCESS) { + printk("%s: Error during card handshake!\n", __func__); + return QLA_ERROR; + } + + /* Negotiated Link width */ + pcie_cap = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); + pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk); + ha->link_width = (lnk >> 4) & 0x3f; + + /* Synchronize with Receive peg */ + return qla4_8xxx_rcvpeg_ready(ha); +} + +static int +qla4_8xxx_try_start_fw(struct scsi_qla_host *ha) +{ + int rval = QLA_ERROR; + + /* + * FW Load priority: + * 1) Operational firmware residing in flash. + * 2) Fail + */ + + ql4_printk(KERN_INFO, ha, + "FW: Retrieving flash offsets from FLT/FDT ...\n"); + rval = qla4_8xxx_get_flash_info(ha); + if (rval != QLA_SUCCESS) + return rval; + + ql4_printk(KERN_INFO, ha, + "FW: Attempting to load firmware from flash...\n"); + rval = qla4_8xxx_start_firmware(ha, ha->hw.flt_region_fw); + if (rval == QLA_SUCCESS) + return rval; + + ql4_printk(KERN_ERR, ha, "FW: Load firmware from flash FAILED...\n"); + + return rval; +} + +/** + * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw + * @ha: pointer to adapter structure + * + * Note: IDC lock must be held upon entry + **/ +static int +qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) +{ + int rval, i, timeout; + uint32_t old_count, count; + + if (qla4_8xxx_need_reset(ha)) + goto dev_initialize; + + old_count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); + + for (i = 0; i < 10; i++) { + timeout = msleep_interruptible(200); + if (timeout) { + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_FAILED); + return QLA_ERROR; + } + + count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); + if (count != old_count) + goto dev_ready; + } + +dev_initialize: + /* set to DEV_INITIALIZING */ + ql4_printk(KERN_INFO, ha, "HW State: INITIALIZING\n"); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_INITIALIZING); + + /* Driver that sets device state to initializating sets IDC version */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); + + qla4_8xxx_idc_unlock(ha); + rval = qla4_8xxx_try_start_fw(ha); + qla4_8xxx_idc_lock(ha); + + if (rval != QLA_SUCCESS) { + ql4_printk(KERN_INFO, ha, "HW State: FAILED\n"); + qla4_8xxx_clear_drv_active(ha); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED); + return rval; + } + +dev_ready: + ql4_printk(KERN_INFO, ha, "HW State: READY\n"); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY); + + return QLA_SUCCESS; +} + +/** + * qla4_8xxx_need_reset_handler - Code to start reset sequence + * @ha: pointer to adapter structure + * + * Note: IDC lock must be held upon entry + **/ +static void +qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) +{ + uint32_t dev_state, drv_state, drv_active; + unsigned long reset_timeout; + + ql4_printk(KERN_INFO, ha, + "Performing ISP error recovery\n"); + + if (test_and_clear_bit(AF_ONLINE, &ha->flags)) { + qla4_8xxx_idc_unlock(ha); + ha->isp_ops->disable_intrs(ha); + qla4_8xxx_idc_lock(ha); + } + + qla4_8xxx_set_rst_ready(ha); + + /* wait for 10 seconds for reset ack from all functions */ + reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); + + drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); + + ql4_printk(KERN_INFO, ha, + "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", + __func__, ha->host_no, drv_state, drv_active); + + while (drv_state != drv_active) { + if (time_after_eq(jiffies, reset_timeout)) { + printk("%s: RESET TIMEOUT!\n", DRIVER_NAME); + break; + } + + qla4_8xxx_idc_unlock(ha); + msleep(1000); + qla4_8xxx_idc_lock(ha); + + drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); + } + + dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + ql4_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state, + dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); + + /* Force to DEV_COLD unless someone else is starting a reset */ + if (dev_state != QLA82XX_DEV_INITIALIZING) { + ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); + } +} + +/** + * qla4_8xxx_need_qsnt_handler - Code to start qsnt + * @ha: pointer to adapter structure + **/ +void +qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha) +{ + qla4_8xxx_idc_lock(ha); + qla4_8xxx_set_qsnt_ready(ha); + qla4_8xxx_idc_unlock(ha); +} + +/** + * qla4_8xxx_device_state_handler - Adapter state machine + * @ha: pointer to host adapter structure. + * + * Note: IDC lock must be UNLOCKED upon entry + **/ +int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) +{ + uint32_t dev_state; + int rval = QLA_SUCCESS; + unsigned long dev_init_timeout; + + if (!test_bit(AF_INIT_DONE, &ha->flags)) + qla4_8xxx_set_drv_active(ha); + + dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, + dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); + + /* wait for 30 seconds for device to go ready */ + dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); + + while (1) { + qla4_8xxx_idc_lock(ha); + + if (time_after_eq(jiffies, dev_init_timeout)) { + ql4_printk(KERN_WARNING, ha, "Device init failed!\n"); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_FAILED); + } + + dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + ql4_printk(KERN_INFO, ha, + "2:Device state is 0x%x = %s\n", dev_state, + dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); + + /* NOTE: Make sure idc unlocked upon exit of switch statement */ + switch (dev_state) { + case QLA82XX_DEV_READY: + qla4_8xxx_idc_unlock(ha); + goto exit; + case QLA82XX_DEV_COLD: + rval = qla4_8xxx_device_bootstrap(ha); + qla4_8xxx_idc_unlock(ha); + goto exit; + case QLA82XX_DEV_INITIALIZING: + qla4_8xxx_idc_unlock(ha); + msleep(1000); + break; + case QLA82XX_DEV_NEED_RESET: + if (!ql4xdontresethba) { + qla4_8xxx_need_reset_handler(ha); + /* Update timeout value after need + * reset handler */ + dev_init_timeout = jiffies + + (ha->nx_dev_init_timeout * HZ); + } + qla4_8xxx_idc_unlock(ha); + break; + case QLA82XX_DEV_NEED_QUIESCENT: + qla4_8xxx_idc_unlock(ha); + /* idc locked/unlocked in handler */ + qla4_8xxx_need_qsnt_handler(ha); + qla4_8xxx_idc_lock(ha); + /* fall thru needs idc_locked */ + case QLA82XX_DEV_QUIESCENT: + qla4_8xxx_idc_unlock(ha); + msleep(1000); + break; + case QLA82XX_DEV_FAILED: + qla4_8xxx_idc_unlock(ha); + qla4xxx_dead_adapter_cleanup(ha); + rval = QLA_ERROR; + goto exit; + default: + qla4_8xxx_idc_unlock(ha); + qla4xxx_dead_adapter_cleanup(ha); + rval = QLA_ERROR; + goto exit; + } + } +exit: + return rval; +} + +int qla4_8xxx_load_risc(struct scsi_qla_host *ha) +{ + int retval; + retval = qla4_8xxx_device_state_handler(ha); + + if (retval == QLA_SUCCESS && + !test_bit(AF_INIT_DONE, &ha->flags)) { + retval = qla4xxx_request_irqs(ha); + if (retval != QLA_SUCCESS) { + ql4_printk(KERN_WARNING, ha, + "Failed to reserve interrupt %d already in use.\n", + ha->pdev->irq); + } else { + set_bit(AF_IRQ_ATTACHED, &ha->flags); + ha->host->irq = ha->pdev->irq; + ql4_printk(KERN_INFO, ha, "%s: irq %d attached\n", + __func__, ha->pdev->irq); + } + } + return retval; +} + +/*****************************************************************************/ +/* Flash Manipulation Routines */ +/*****************************************************************************/ + +#define OPTROM_BURST_SIZE 0x1000 +#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) + +#define FARX_DATA_FLAG BIT_31 +#define FARX_ACCESS_FLASH_CONF 0x7FFD0000 +#define FARX_ACCESS_FLASH_DATA 0x7FF00000 + +static inline uint32_t +flash_conf_addr(struct ql82xx_hw_data *hw, uint32_t faddr) +{ + return hw->flash_conf_off | faddr; +} + +static inline uint32_t +flash_data_addr(struct ql82xx_hw_data *hw, uint32_t faddr) +{ + return hw->flash_data_off | faddr; +} + +static uint32_t * +qla4_8xxx_read_flash_data(struct scsi_qla_host *ha, uint32_t *dwptr, + uint32_t faddr, uint32_t length) +{ + uint32_t i; + uint32_t val; + int loops = 0; + while ((qla4_8xxx_rom_lock(ha) != 0) && (loops < 50000)) { + udelay(100); + cond_resched(); + loops++; + } + if (loops >= 50000) { + ql4_printk(KERN_WARNING, ha, "ROM lock failed\n"); + return dwptr; + } + + /* Dword reads to flash. */ + for (i = 0; i < length/4; i++, faddr += 4) { + if (qla4_8xxx_do_rom_fast_read(ha, faddr, &val)) { + ql4_printk(KERN_WARNING, ha, + "Do ROM fast read failed\n"); + goto done_read; + } + dwptr[i] = __constant_cpu_to_le32(val); + } + +done_read: + qla4_8xxx_rom_unlock(ha); + return dwptr; +} + +/** + * Address and length are byte address + **/ +static uint8_t * +qla4_8xxx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, + uint32_t offset, uint32_t length) +{ + qla4_8xxx_read_flash_data(ha, (uint32_t *)buf, offset, length); + return buf; +} + +static int +qla4_8xxx_find_flt_start(struct scsi_qla_host *ha, uint32_t *start) +{ + const char *loc, *locations[] = { "DEF", "PCI" }; + + /* + * FLT-location structure resides after the last PCI region. + */ + + /* Begin with sane defaults. */ + loc = locations[0]; + *start = FA_FLASH_LAYOUT_ADDR_82; + + DEBUG2(ql4_printk(KERN_INFO, ha, "FLTL[%s] = 0x%x.\n", loc, *start)); + return QLA_SUCCESS; +} + +static void +qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr) +{ + const char *loc, *locations[] = { "DEF", "FLT" }; + uint16_t *wptr; + uint16_t cnt, chksum; + uint32_t start; + struct qla_flt_header *flt; + struct qla_flt_region *region; + struct ql82xx_hw_data *hw = &ha->hw; + + hw->flt_region_flt = flt_addr; + wptr = (uint16_t *)ha->request_ring; + flt = (struct qla_flt_header *)ha->request_ring; + region = (struct qla_flt_region *)&flt[1]; + qla4_8xxx_read_optrom_data(ha, (uint8_t *)ha->request_ring, + flt_addr << 2, OPTROM_BURST_SIZE); + if (*wptr == __constant_cpu_to_le16(0xffff)) + goto no_flash_data; + if (flt->version != __constant_cpu_to_le16(1)) { + DEBUG2(ql4_printk(KERN_INFO, ha, "Unsupported FLT detected: " + "version=0x%x length=0x%x checksum=0x%x.\n", + le16_to_cpu(flt->version), le16_to_cpu(flt->length), + le16_to_cpu(flt->checksum))); + goto no_flash_data; + } + + cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; + for (chksum = 0; cnt; cnt--) + chksum += le16_to_cpu(*wptr++); + if (chksum) { + DEBUG2(ql4_printk(KERN_INFO, ha, "Inconsistent FLT detected: " + "version=0x%x length=0x%x checksum=0x%x.\n", + le16_to_cpu(flt->version), le16_to_cpu(flt->length), + chksum)); + goto no_flash_data; + } + + loc = locations[1]; + cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); + for ( ; cnt; cnt--, region++) { + /* Store addresses as DWORD offsets. */ + start = le32_to_cpu(region->start) >> 2; + + DEBUG3(ql4_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x " + "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start, + le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size))); + + switch (le32_to_cpu(region->code) & 0xff) { + case FLT_REG_FDT: + hw->flt_region_fdt = start; + break; + case FLT_REG_BOOT_CODE_82: + hw->flt_region_boot = start; + break; + case FLT_REG_FW_82: + hw->flt_region_fw = start; + break; + case FLT_REG_BOOTLOAD_82: + hw->flt_region_bootload = start; + break; + } + } + goto done; + +no_flash_data: + /* Use hardcoded defaults. */ + loc = locations[0]; + + hw->flt_region_fdt = FA_FLASH_DESCR_ADDR_82; + hw->flt_region_boot = FA_BOOT_CODE_ADDR_82; + hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82; + hw->flt_region_fw = FA_RISC_CODE_ADDR_82; +done: + DEBUG2(ql4_printk(KERN_INFO, ha, "FLT[%s]: flt=0x%x fdt=0x%x " + "boot=0x%x bootload=0x%x fw=0x%x\n", loc, hw->flt_region_flt, + hw->flt_region_fdt, hw->flt_region_boot, hw->flt_region_bootload, + hw->flt_region_fw)); +} + +static void +qla4_8xxx_get_fdt_info(struct scsi_qla_host *ha) +{ +#define FLASH_BLK_SIZE_4K 0x1000 +#define FLASH_BLK_SIZE_32K 0x8000 +#define FLASH_BLK_SIZE_64K 0x10000 + const char *loc, *locations[] = { "MID", "FDT" }; + uint16_t cnt, chksum; + uint16_t *wptr; + struct qla_fdt_layout *fdt; + uint16_t mid, fid; + struct ql82xx_hw_data *hw = &ha->hw; + + hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; + hw->flash_data_off = FARX_ACCESS_FLASH_DATA; + + wptr = (uint16_t *)ha->request_ring; + fdt = (struct qla_fdt_layout *)ha->request_ring; + qla4_8xxx_read_optrom_data(ha, (uint8_t *)ha->request_ring, + hw->flt_region_fdt << 2, OPTROM_BURST_SIZE); + + if (*wptr == __constant_cpu_to_le16(0xffff)) + goto no_flash_data; + + if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || + fdt->sig[3] != 'D') + goto no_flash_data; + + for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1; + cnt++) + chksum += le16_to_cpu(*wptr++); + + if (chksum) { + DEBUG2(ql4_printk(KERN_INFO, ha, "Inconsistent FDT detected: " + "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0], + le16_to_cpu(fdt->version))); + goto no_flash_data; + } + + loc = locations[1]; + mid = le16_to_cpu(fdt->man_id); + fid = le16_to_cpu(fdt->id); + hw->fdt_wrt_disable = fdt->wrt_disable_bits; + hw->fdt_erase_cmd = flash_conf_addr(hw, 0x0300 | fdt->erase_cmd); + hw->fdt_block_size = le32_to_cpu(fdt->block_size); + + if (fdt->unprotect_sec_cmd) { + hw->fdt_unprotect_sec_cmd = flash_conf_addr(hw, 0x0300 | + fdt->unprotect_sec_cmd); + hw->fdt_protect_sec_cmd = fdt->protect_sec_cmd ? + flash_conf_addr(hw, 0x0300 | fdt->protect_sec_cmd) : + flash_conf_addr(hw, 0x0336); + } + goto done; + +no_flash_data: + loc = locations[0]; + hw->fdt_block_size = FLASH_BLK_SIZE_64K; +done: + DEBUG2(ql4_printk(KERN_INFO, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " + "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid, + hw->fdt_erase_cmd, hw->fdt_protect_sec_cmd, + hw->fdt_unprotect_sec_cmd, hw->fdt_wrt_disable, + hw->fdt_block_size)); +} + +static void +qla4_8xxx_get_idc_param(struct scsi_qla_host *ha) +{ +#define QLA82XX_IDC_PARAM_ADDR 0x003e885c + uint32_t *wptr; + + if (!is_qla8022(ha)) + return; + wptr = (uint32_t *)ha->request_ring; + qla4_8xxx_read_optrom_data(ha, (uint8_t *)ha->request_ring, + QLA82XX_IDC_PARAM_ADDR , 8); + + if (*wptr == __constant_cpu_to_le32(0xffffffff)) { + ha->nx_dev_init_timeout = ROM_DEV_INIT_TIMEOUT; + ha->nx_reset_timeout = ROM_DRV_RESET_ACK_TIMEOUT; + } else { + ha->nx_dev_init_timeout = le32_to_cpu(*wptr++); + ha->nx_reset_timeout = le32_to_cpu(*wptr); + } + + DEBUG2(ql4_printk(KERN_DEBUG, ha, + "ha->nx_dev_init_timeout = %d\n", ha->nx_dev_init_timeout)); + DEBUG2(ql4_printk(KERN_DEBUG, ha, + "ha->nx_reset_timeout = %d\n", ha->nx_reset_timeout)); + return; +} + +int +qla4_8xxx_get_flash_info(struct scsi_qla_host *ha) +{ + int ret; + uint32_t flt_addr; + + ret = qla4_8xxx_find_flt_start(ha, &flt_addr); + if (ret != QLA_SUCCESS) + return ret; + + qla4_8xxx_get_flt_info(ha, flt_addr); + qla4_8xxx_get_fdt_info(ha); + qla4_8xxx_get_idc_param(ha); + + return QLA_SUCCESS; +} + +/** + * qla4_8xxx_stop_firmware - stops firmware on specified adapter instance + * @ha: pointer to host adapter structure. + * + * Remarks: + * For iSCSI, throws away all I/O and AENs into bit bucket, so they will + * not be available after successful return. Driver must cleanup potential + * outstanding I/O's after calling this funcion. + **/ +int +qla4_8xxx_stop_firmware(struct scsi_qla_host *ha) +{ + int status; + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + + mbox_cmd[0] = MBOX_CMD_STOP_FW; + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, + &mbox_cmd[0], &mbox_sts[0]); + + DEBUG2(printk("scsi%ld: %s: status = %d\n", ha->host_no, + __func__, status)); + return status; +} + +/** + * qla4_8xxx_isp_reset - Resets ISP and aborts all outstanding commands. + * @ha: pointer to host adapter structure. + **/ +int +qla4_8xxx_isp_reset(struct scsi_qla_host *ha) +{ + int rval; + uint32_t dev_state; + + qla4_8xxx_idc_lock(ha); + dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + + if (dev_state == QLA82XX_DEV_READY) { + ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_NEED_RESET); + } else + ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); + + qla4_8xxx_idc_unlock(ha); + + rval = qla4_8xxx_device_state_handler(ha); + + qla4_8xxx_idc_lock(ha); + qla4_8xxx_clear_rst_ready(ha); + qla4_8xxx_idc_unlock(ha); + + return rval; +} + +/** + * qla4_8xxx_get_sys_info - get adapter MAC address(es) and serial number + * @ha: pointer to host adapter structure. + * + **/ +int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) +{ + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + struct mbx_sys_info *sys_info; + dma_addr_t sys_info_dma; + int status = QLA_ERROR; + + sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info), + &sys_info_dma, GFP_KERNEL); + if (sys_info == NULL) { + DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", + ha->host_no, __func__)); + return status; + } + + memset(sys_info, 0, sizeof(*sys_info)); + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + + mbox_cmd[0] = MBOX_CMD_GET_SYS_INFO; + mbox_cmd[1] = LSDW(sys_info_dma); + mbox_cmd[2] = MSDW(sys_info_dma); + mbox_cmd[4] = sizeof(*sys_info); + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 6, &mbox_cmd[0], + &mbox_sts[0]) != QLA_SUCCESS) { + DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO failed\n", + ha->host_no, __func__)); + goto exit_validate_mac82; + } + + if (mbox_sts[4] < sizeof(*sys_info)) { + DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" + " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); + goto exit_validate_mac82; + + } + + /* Save M.A.C. address & serial_number */ + memcpy(ha->my_mac, &sys_info->mac_addr[0], + min(sizeof(ha->my_mac), sizeof(sys_info->mac_addr))); + memcpy(ha->serial_number, &sys_info->serial_number, + min(sizeof(ha->serial_number), sizeof(sys_info->serial_number))); + + DEBUG2(printk("scsi%ld: %s: " + "mac %02x:%02x:%02x:%02x:%02x:%02x " + "serial %s\n", ha->host_no, __func__, + ha->my_mac[0], ha->my_mac[1], ha->my_mac[2], + ha->my_mac[3], ha->my_mac[4], ha->my_mac[5], + ha->serial_number)); + + status = QLA_SUCCESS; + +exit_validate_mac82: + dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info, + sys_info_dma); + return status; +} + +/* Interrupt handling helpers. */ + +static int +qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha) +{ + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s\n", __func__)); + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_ENABLE_INTRS; + mbox_cmd[1] = INTR_ENABLE; + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], + &mbox_sts[0]) != QLA_SUCCESS) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: MBOX_CMD_ENABLE_INTRS failed (0x%04x)\n", + __func__, mbox_sts[0])); + return QLA_ERROR; + } + return QLA_SUCCESS; +} + +static int +qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha) +{ + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s\n", __func__)); + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_ENABLE_INTRS; + mbox_cmd[1] = INTR_DISABLE; + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], + &mbox_sts[0]) != QLA_SUCCESS) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: MBOX_CMD_ENABLE_INTRS failed (0x%04x)\n", + __func__, mbox_sts[0])); + return QLA_ERROR; + } + + return QLA_SUCCESS; +} + +void +qla4_8xxx_enable_intrs(struct scsi_qla_host *ha) +{ + qla4_8xxx_mbx_intr_enable(ha); + + spin_lock_irq(&ha->hardware_lock); + /* BIT 10 - reset */ + qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); + spin_unlock_irq(&ha->hardware_lock); + set_bit(AF_INTERRUPTS_ON, &ha->flags); +} + +void +qla4_8xxx_disable_intrs(struct scsi_qla_host *ha) +{ + if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) + qla4_8xxx_mbx_intr_disable(ha); + + spin_lock_irq(&ha->hardware_lock); + /* BIT 10 - set */ + qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400); + spin_unlock_irq(&ha->hardware_lock); + clear_bit(AF_INTERRUPTS_ON, &ha->flags); +} + +struct ql4_init_msix_entry { + uint16_t entry; + uint16_t index; + const char *name; + irq_handler_t handler; +}; + +static struct ql4_init_msix_entry qla4_8xxx_msix_entries[QLA_MSIX_ENTRIES] = { + { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT, + "qla4xxx (default)", + (irq_handler_t)qla4_8xxx_default_intr_handler }, + { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q, + "qla4xxx (rsp_q)", (irq_handler_t)qla4_8xxx_msix_rsp_q }, +}; + +void +qla4_8xxx_disable_msix(struct scsi_qla_host *ha) +{ + int i; + struct ql4_msix_entry *qentry; + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) { + qentry = &ha->msix_entries[qla4_8xxx_msix_entries[i].index]; + if (qentry->have_irq) { + free_irq(qentry->msix_vector, ha); + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %s\n", + __func__, qla4_8xxx_msix_entries[i].name)); + } + } + pci_disable_msix(ha->pdev); + clear_bit(AF_MSIX_ENABLED, &ha->flags); +} + +int +qla4_8xxx_enable_msix(struct scsi_qla_host *ha) +{ + int i, ret; + struct msix_entry entries[QLA_MSIX_ENTRIES]; + struct ql4_msix_entry *qentry; + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) + entries[i].entry = qla4_8xxx_msix_entries[i].entry; + + ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries)); + if (ret) { + ql4_printk(KERN_WARNING, ha, + "MSI-X: Failed to enable support -- %d/%d\n", + QLA_MSIX_ENTRIES, ret); + goto msix_out; + } + set_bit(AF_MSIX_ENABLED, &ha->flags); + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) { + qentry = &ha->msix_entries[qla4_8xxx_msix_entries[i].index]; + qentry->msix_vector = entries[i].vector; + qentry->msix_entry = entries[i].entry; + qentry->have_irq = 0; + ret = request_irq(qentry->msix_vector, + qla4_8xxx_msix_entries[i].handler, 0, + qla4_8xxx_msix_entries[i].name, ha); + if (ret) { + ql4_printk(KERN_WARNING, ha, + "MSI-X: Unable to register handler -- %x/%d.\n", + qla4_8xxx_msix_entries[i].index, ret); + qla4_8xxx_disable_msix(ha); + goto msix_out; + } + qentry->have_irq = 1; + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %s\n", + __func__, qla4_8xxx_msix_entries[i].name)); + } +msix_out: + return ret; +} diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h new file mode 100644 index 000000000000..931ad3f1e918 --- /dev/null +++ b/drivers/scsi/qla4xxx/ql4_nx.h @@ -0,0 +1,779 @@ +/* + * QLogic Fibre Channel HBA Driver + * Copyright (c) 2003-2008 QLogic Corporation + * + * See LICENSE.qla2xxx for copyright and licensing details. + */ +#ifndef __QLA_NX_H +#define __QLA_NX_H + +/* + * Following are the states of the Phantom. Phantom will set them and + * Host will read to check if the fields are correct. +*/ +#define PHAN_INITIALIZE_FAILED 0xffff +#define PHAN_INITIALIZE_COMPLETE 0xff01 + +/* Host writes the following to notify that it has done the init-handshake */ +#define PHAN_INITIALIZE_ACK 0xf00f +#define PHAN_PEG_RCV_INITIALIZED 0xff01 + +/*CRB_RELATED*/ +#define QLA82XX_CRB_BASE QLA82XX_CAM_RAM(0x200) +#define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X)) + +#define CRB_CMDPEG_STATE QLA82XX_REG(0x50) +#define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) +#define BOOT_LOADER_DIMM_STATUS QLA82XX_REG(0x54) +#define CRB_DMA_SHIFT QLA82XX_REG(0xcc) + +#define QLA82XX_HW_H0_CH_HUB_ADR 0x05 +#define QLA82XX_HW_H1_CH_HUB_ADR 0x0E +#define QLA82XX_HW_H2_CH_HUB_ADR 0x03 +#define QLA82XX_HW_H3_CH_HUB_ADR 0x01 +#define QLA82XX_HW_H4_CH_HUB_ADR 0x06 +#define QLA82XX_HW_H5_CH_HUB_ADR 0x07 +#define QLA82XX_HW_H6_CH_HUB_ADR 0x08 + +/* Hub 0 */ +#define QLA82XX_HW_MN_CRB_AGT_ADR 0x15 +#define QLA82XX_HW_MS_CRB_AGT_ADR 0x25 + +/* Hub 1 */ +#define QLA82XX_HW_PS_CRB_AGT_ADR 0x73 +#define QLA82XX_HW_QMS_CRB_AGT_ADR 0x00 +#define QLA82XX_HW_RPMX3_CRB_AGT_ADR 0x0b +#define QLA82XX_HW_SQGS0_CRB_AGT_ADR 0x01 +#define QLA82XX_HW_SQGS1_CRB_AGT_ADR 0x02 +#define QLA82XX_HW_SQGS2_CRB_AGT_ADR 0x03 +#define QLA82XX_HW_SQGS3_CRB_AGT_ADR 0x04 +#define QLA82XX_HW_C2C0_CRB_AGT_ADR 0x58 +#define QLA82XX_HW_C2C1_CRB_AGT_ADR 0x59 +#define QLA82XX_HW_C2C2_CRB_AGT_ADR 0x5a +#define QLA82XX_HW_RPMX2_CRB_AGT_ADR 0x0a +#define QLA82XX_HW_RPMX4_CRB_AGT_ADR 0x0c +#define QLA82XX_HW_RPMX7_CRB_AGT_ADR 0x0f +#define QLA82XX_HW_RPMX9_CRB_AGT_ADR 0x12 +#define QLA82XX_HW_SMB_CRB_AGT_ADR 0x18 + +/* Hub 2 */ +#define QLA82XX_HW_NIU_CRB_AGT_ADR 0x31 +#define QLA82XX_HW_I2C0_CRB_AGT_ADR 0x19 +#define QLA82XX_HW_I2C1_CRB_AGT_ADR 0x29 + +#define QLA82XX_HW_SN_CRB_AGT_ADR 0x10 +#define QLA82XX_HW_I2Q_CRB_AGT_ADR 0x20 +#define QLA82XX_HW_LPC_CRB_AGT_ADR 0x22 +#define QLA82XX_HW_ROMUSB_CRB_AGT_ADR 0x21 +#define QLA82XX_HW_QM_CRB_AGT_ADR 0x66 +#define QLA82XX_HW_SQG0_CRB_AGT_ADR 0x60 +#define QLA82XX_HW_SQG1_CRB_AGT_ADR 0x61 +#define QLA82XX_HW_SQG2_CRB_AGT_ADR 0x62 +#define QLA82XX_HW_SQG3_CRB_AGT_ADR 0x63 +#define QLA82XX_HW_RPMX1_CRB_AGT_ADR 0x09 +#define QLA82XX_HW_RPMX5_CRB_AGT_ADR 0x0d +#define QLA82XX_HW_RPMX6_CRB_AGT_ADR 0x0e +#define QLA82XX_HW_RPMX8_CRB_AGT_ADR 0x11 + +/* Hub 3 */ +#define QLA82XX_HW_PH_CRB_AGT_ADR 0x1A +#define QLA82XX_HW_SRE_CRB_AGT_ADR 0x50 +#define QLA82XX_HW_EG_CRB_AGT_ADR 0x51 +#define QLA82XX_HW_RPMX0_CRB_AGT_ADR 0x08 + +/* Hub 4 */ +#define QLA82XX_HW_PEGN0_CRB_AGT_ADR 0x40 +#define QLA82XX_HW_PEGN1_CRB_AGT_ADR 0x41 +#define QLA82XX_HW_PEGN2_CRB_AGT_ADR 0x42 +#define QLA82XX_HW_PEGN3_CRB_AGT_ADR 0x43 +#define QLA82XX_HW_PEGNI_CRB_AGT_ADR 0x44 +#define QLA82XX_HW_PEGND_CRB_AGT_ADR 0x45 +#define QLA82XX_HW_PEGNC_CRB_AGT_ADR 0x46 +#define QLA82XX_HW_PEGR0_CRB_AGT_ADR 0x47 +#define QLA82XX_HW_PEGR1_CRB_AGT_ADR 0x48 +#define QLA82XX_HW_PEGR2_CRB_AGT_ADR 0x49 +#define QLA82XX_HW_PEGR3_CRB_AGT_ADR 0x4a +#define QLA82XX_HW_PEGN4_CRB_AGT_ADR 0x4b + +/* Hub 5 */ +#define QLA82XX_HW_PEGS0_CRB_AGT_ADR 0x40 +#define QLA82XX_HW_PEGS1_CRB_AGT_ADR 0x41 +#define QLA82XX_HW_PEGS2_CRB_AGT_ADR 0x42 +#define QLA82XX_HW_PEGS3_CRB_AGT_ADR 0x43 + +#define QLA82XX_HW_PEGSI_CRB_AGT_ADR 0x44 +#define QLA82XX_HW_PEGSD_CRB_AGT_ADR 0x45 +#define QLA82XX_HW_PEGSC_CRB_AGT_ADR 0x46 + +/* Hub 6 */ +#define QLA82XX_HW_CAS0_CRB_AGT_ADR 0x46 +#define QLA82XX_HW_CAS1_CRB_AGT_ADR 0x47 +#define QLA82XX_HW_CAS2_CRB_AGT_ADR 0x48 +#define QLA82XX_HW_CAS3_CRB_AGT_ADR 0x49 +#define QLA82XX_HW_NCM_CRB_AGT_ADR 0x16 +#define QLA82XX_HW_TMR_CRB_AGT_ADR 0x17 +#define QLA82XX_HW_XDMA_CRB_AGT_ADR 0x05 +#define QLA82XX_HW_OCM0_CRB_AGT_ADR 0x06 +#define QLA82XX_HW_OCM1_CRB_AGT_ADR 0x07 + +/* This field defines PCI/X adr [25:20] of agents on the CRB */ +/* */ +#define QLA82XX_HW_PX_MAP_CRB_PH 0 +#define QLA82XX_HW_PX_MAP_CRB_PS 1 +#define QLA82XX_HW_PX_MAP_CRB_MN 2 +#define QLA82XX_HW_PX_MAP_CRB_MS 3 +#define QLA82XX_HW_PX_MAP_CRB_SRE 5 +#define QLA82XX_HW_PX_MAP_CRB_NIU 6 +#define QLA82XX_HW_PX_MAP_CRB_QMN 7 +#define QLA82XX_HW_PX_MAP_CRB_SQN0 8 +#define QLA82XX_HW_PX_MAP_CRB_SQN1 9 +#define QLA82XX_HW_PX_MAP_CRB_SQN2 10 +#define QLA82XX_HW_PX_MAP_CRB_SQN3 11 +#define QLA82XX_HW_PX_MAP_CRB_QMS 12 +#define QLA82XX_HW_PX_MAP_CRB_SQS0 13 +#define QLA82XX_HW_PX_MAP_CRB_SQS1 14 +#define QLA82XX_HW_PX_MAP_CRB_SQS2 15 +#define QLA82XX_HW_PX_MAP_CRB_SQS3 16 +#define QLA82XX_HW_PX_MAP_CRB_PGN0 17 +#define QLA82XX_HW_PX_MAP_CRB_PGN1 18 +#define QLA82XX_HW_PX_MAP_CRB_PGN2 19 +#define QLA82XX_HW_PX_MAP_CRB_PGN3 20 +#define QLA82XX_HW_PX_MAP_CRB_PGN4 QLA82XX_HW_PX_MAP_CRB_SQS2 +#define QLA82XX_HW_PX_MAP_CRB_PGND 21 +#define QLA82XX_HW_PX_MAP_CRB_PGNI 22 +#define QLA82XX_HW_PX_MAP_CRB_PGS0 23 +#define QLA82XX_HW_PX_MAP_CRB_PGS1 24 +#define QLA82XX_HW_PX_MAP_CRB_PGS2 25 +#define QLA82XX_HW_PX_MAP_CRB_PGS3 26 +#define QLA82XX_HW_PX_MAP_CRB_PGSD 27 +#define QLA82XX_HW_PX_MAP_CRB_PGSI 28 +#define QLA82XX_HW_PX_MAP_CRB_SN 29 +#define QLA82XX_HW_PX_MAP_CRB_EG 31 +#define QLA82XX_HW_PX_MAP_CRB_PH2 32 +#define QLA82XX_HW_PX_MAP_CRB_PS2 33 +#define QLA82XX_HW_PX_MAP_CRB_CAM 34 +#define QLA82XX_HW_PX_MAP_CRB_CAS0 35 +#define QLA82XX_HW_PX_MAP_CRB_CAS1 36 +#define QLA82XX_HW_PX_MAP_CRB_CAS2 37 +#define QLA82XX_HW_PX_MAP_CRB_C2C0 38 +#define QLA82XX_HW_PX_MAP_CRB_C2C1 39 +#define QLA82XX_HW_PX_MAP_CRB_TIMR 40 +#define QLA82XX_HW_PX_MAP_CRB_RPMX1 42 +#define QLA82XX_HW_PX_MAP_CRB_RPMX2 43 +#define QLA82XX_HW_PX_MAP_CRB_RPMX3 44 +#define QLA82XX_HW_PX_MAP_CRB_RPMX4 45 +#define QLA82XX_HW_PX_MAP_CRB_RPMX5 46 +#define QLA82XX_HW_PX_MAP_CRB_RPMX6 47 +#define QLA82XX_HW_PX_MAP_CRB_RPMX7 48 +#define QLA82XX_HW_PX_MAP_CRB_XDMA 49 +#define QLA82XX_HW_PX_MAP_CRB_I2Q 50 +#define QLA82XX_HW_PX_MAP_CRB_ROMUSB 51 +#define QLA82XX_HW_PX_MAP_CRB_CAS3 52 +#define QLA82XX_HW_PX_MAP_CRB_RPMX0 53 +#define QLA82XX_HW_PX_MAP_CRB_RPMX8 54 +#define QLA82XX_HW_PX_MAP_CRB_RPMX9 55 +#define QLA82XX_HW_PX_MAP_CRB_OCM0 56 +#define QLA82XX_HW_PX_MAP_CRB_OCM1 57 +#define QLA82XX_HW_PX_MAP_CRB_SMB 58 +#define QLA82XX_HW_PX_MAP_CRB_I2C0 59 +#define QLA82XX_HW_PX_MAP_CRB_I2C1 60 +#define QLA82XX_HW_PX_MAP_CRB_LPC 61 +#define QLA82XX_HW_PX_MAP_CRB_PGNC 62 +#define QLA82XX_HW_PX_MAP_CRB_PGR0 63 +#define QLA82XX_HW_PX_MAP_CRB_PGR1 4 +#define QLA82XX_HW_PX_MAP_CRB_PGR2 30 +#define QLA82XX_HW_PX_MAP_CRB_PGR3 41 + +/* This field defines CRB adr [31:20] of the agents */ +/* */ + +#define QLA82XX_HW_CRB_HUB_AGT_ADR_MN ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ + QLA82XX_HW_MN_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PH ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PH_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_MS ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ + QLA82XX_HW_MS_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PS_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SS_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX3_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_QMS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_QMS_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS0 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SQGS0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS1 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SQGS1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS2 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SQGS2_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS3 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SQGS3_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_C2C0 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_C2C0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_C2C1 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_C2C1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX2_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX4_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX7_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX9_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SMB ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SMB_CRB_AGT_ADR) + +#define QLA82XX_HW_CRB_HUB_AGT_ADR_NIU ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ + QLA82XX_HW_NIU_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0 ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ + QLA82XX_HW_I2C0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1 ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ + QLA82XX_HW_I2C1_CRB_AGT_ADR) + +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SRE ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SRE_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_EG ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_EG_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_QMN ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_QM_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SQG0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SQG1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SQG2_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SQG3_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX5_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX6_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_RPMX8_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_CAS0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_CAS1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS2 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_CAS2_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS3 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ + QLA82XX_HW_CAS3_CRB_AGT_ADR) + +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGNI_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGND ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGND_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGN0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGN1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGN2_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGN3_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGN4_CRB_AGT_ADR) + +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGNC_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR0 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGR0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR1 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGR1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR2 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGR2_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR3 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGR3_CRB_AGT_ADR) + +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGSI_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSD ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGSD_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGS0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGS1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGS2_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGS3_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSC ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ + QLA82XX_HW_PEGSC_CRB_AGT_ADR) + +#define QLA82XX_HW_CRB_HUB_AGT_ADR_CAM ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_NCM_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_TMR_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_XDMA_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_SN ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_SN_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_I2Q_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_ROMUSB_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0 ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_OCM0_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_OCM1 ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_OCM1_CRB_AGT_ADR) +#define QLA82XX_HW_CRB_HUB_AGT_ADR_LPC ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ + QLA82XX_HW_LPC_CRB_AGT_ADR) + +#define ROMUSB_GLB (QLA82XX_CRB_ROMUSB + 0x00000) +#define QLA82XX_ROMUSB_GLB_PEGTUNE_DONE (ROMUSB_GLB + 0x005c) +#define QLA82XX_ROMUSB_GLB_STATUS (ROMUSB_GLB + 0x0004) +#define QLA82XX_ROMUSB_GLB_SW_RESET (ROMUSB_GLB + 0x0008) +#define QLA82XX_ROMUSB_ROM_ADDRESS (ROMUSB_ROM + 0x0008) +#define QLA82XX_ROMUSB_ROM_WDATA (ROMUSB_ROM + 0x000c) +#define QLA82XX_ROMUSB_ROM_ABYTE_CNT (ROMUSB_ROM + 0x0010) +#define QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014) +#define QLA82XX_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018) + +#define ROMUSB_ROM (QLA82XX_CRB_ROMUSB + 0x10000) +#define QLA82XX_ROMUSB_ROM_INSTR_OPCODE (ROMUSB_ROM + 0x0004) +#define QLA82XX_ROMUSB_GLB_CAS_RST (ROMUSB_GLB + 0x0038) + +/* Lock IDs for ROM lock */ +#define ROM_LOCK_DRIVER 0x0d417340 + +#define QLA82XX_PCI_CRB_WINDOWSIZE 0x00100000 /* all are 1MB windows */ +#define QLA82XX_PCI_CRB_WINDOW(A) (QLA82XX_PCI_CRBSPACE + \ + (A)*QLA82XX_PCI_CRB_WINDOWSIZE) + +#define QLA82XX_CRB_C2C_0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C0) +#define QLA82XX_CRB_C2C_1 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C1) +#define QLA82XX_CRB_C2C_2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C2) +#define QLA82XX_CRB_CAM \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAM) +#define QLA82XX_CRB_CASPER \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS) +#define QLA82XX_CRB_CASPER_0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS0) +#define QLA82XX_CRB_CASPER_1 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS1) +#define QLA82XX_CRB_CASPER_2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS2) +#define QLA82XX_CRB_DDR_MD \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_MS) +#define QLA82XX_CRB_DDR_NET \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_MN) +#define QLA82XX_CRB_EPG \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_EG) +#define QLA82XX_CRB_I2Q \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2Q) +#define QLA82XX_CRB_NIU \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_NIU) +/* HACK upon HACK upon HACK (for PCIE builds) */ +#define QLA82XX_CRB_PCIX_HOST \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PH) +#define QLA82XX_CRB_PCIX_HOST2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PH2) +#define QLA82XX_CRB_PCIX_MD \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PS) +#define QLA82XX_CRB_PCIE QLA82XX_CRB_PCIX_MD +/* window 1 pcie slot */ +#define QLA82XX_CRB_PCIE2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PS2) + +#define QLA82XX_CRB_PEG_MD_0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS0) +#define QLA82XX_CRB_PEG_MD_1 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS1) +#define QLA82XX_CRB_PEG_MD_2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS2) +#define QLA82XX_CRB_PEG_MD_3 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS3) +#define QLA82XX_CRB_PEG_MD_3 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS3) +#define QLA82XX_CRB_PEG_MD_D \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGSD) +#define QLA82XX_CRB_PEG_MD_I \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGSI) +#define QLA82XX_CRB_PEG_NET_0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN0) +#define QLA82XX_CRB_PEG_NET_1 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN1) +#define QLA82XX_CRB_PEG_NET_2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN2) +#define QLA82XX_CRB_PEG_NET_3 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN3) +#define QLA82XX_CRB_PEG_NET_4 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN4) +#define QLA82XX_CRB_PEG_NET_D \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGND) +#define QLA82XX_CRB_PEG_NET_I \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGNI) +#define QLA82XX_CRB_PQM_MD \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_QMS) +#define QLA82XX_CRB_PQM_NET \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_QMN) +#define QLA82XX_CRB_QDR_MD \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SS) +#define QLA82XX_CRB_QDR_NET \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SN) +#define QLA82XX_CRB_ROMUSB \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_ROMUSB) +#define QLA82XX_CRB_RPMX_0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX0) +#define QLA82XX_CRB_RPMX_1 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX1) +#define QLA82XX_CRB_RPMX_2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX2) +#define QLA82XX_CRB_RPMX_3 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX3) +#define QLA82XX_CRB_RPMX_4 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX4) +#define QLA82XX_CRB_RPMX_5 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX5) +#define QLA82XX_CRB_RPMX_6 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX6) +#define QLA82XX_CRB_RPMX_7 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX7) +#define QLA82XX_CRB_SQM_MD_0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS0) +#define QLA82XX_CRB_SQM_MD_1 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS1) +#define QLA82XX_CRB_SQM_MD_2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS2) +#define QLA82XX_CRB_SQM_MD_3 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS3) +#define QLA82XX_CRB_SQM_NET_0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN0) +#define QLA82XX_CRB_SQM_NET_1 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN1) +#define QLA82XX_CRB_SQM_NET_2 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN2) +#define QLA82XX_CRB_SQM_NET_3 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN3) +#define QLA82XX_CRB_SRE \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SRE) +#define QLA82XX_CRB_TIMER \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_TIMR) +#define QLA82XX_CRB_XDMA \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_XDMA) +#define QLA82XX_CRB_I2C0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2C0) +#define QLA82XX_CRB_I2C1 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2C1) +#define QLA82XX_CRB_OCM0 \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_OCM0) +#define QLA82XX_CRB_SMB \ + QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SMB) + +#define QLA82XX_CRB_MAX QLA82XX_PCI_CRB_WINDOW(64) + +/* + * ====================== BASE ADDRESSES ON-CHIP ====================== + * Base addresses of major components on-chip. + * ====================== BASE ADDRESSES ON-CHIP ====================== + */ +#define QLA82XX_ADDR_DDR_NET (0x0000000000000000ULL) +#define QLA82XX_ADDR_DDR_NET_MAX (0x000000000fffffffULL) + +/* Imbus address bit used to indicate a host address. This bit is + * eliminated by the pcie bar and bar select before presentation + * over pcie. */ +/* host memory via IMBUS */ +#define QLA82XX_P2_ADDR_PCIE (0x0000000800000000ULL) +#define QLA82XX_P3_ADDR_PCIE (0x0000008000000000ULL) +#define QLA82XX_ADDR_PCIE_MAX (0x0000000FFFFFFFFFULL) +#define QLA82XX_ADDR_OCM0 (0x0000000200000000ULL) +#define QLA82XX_ADDR_OCM0_MAX (0x00000002000fffffULL) +#define QLA82XX_ADDR_OCM1 (0x0000000200400000ULL) +#define QLA82XX_ADDR_OCM1_MAX (0x00000002004fffffULL) +#define QLA82XX_ADDR_QDR_NET (0x0000000300000000ULL) + +#define QLA82XX_P2_ADDR_QDR_NET_MAX (0x00000003001fffffULL) +#define QLA82XX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL) + +#define QLA82XX_PCI_CRBSPACE (unsigned long)0x06000000 +#define QLA82XX_PCI_DIRECT_CRB (unsigned long)0x04400000 +#define QLA82XX_PCI_CAMQM (unsigned long)0x04800000 +#define QLA82XX_PCI_CAMQM_MAX (unsigned long)0x04ffffff +#define QLA82XX_PCI_DDR_NET (unsigned long)0x00000000 +#define QLA82XX_PCI_QDR_NET (unsigned long)0x04000000 +#define QLA82XX_PCI_QDR_NET_MAX (unsigned long)0x043fffff + +/* + * Register offsets for MN + */ +#define MIU_CONTROL (0x000) +#define MIU_TAG (0x004) +#define MIU_TEST_AGT_CTRL (0x090) +#define MIU_TEST_AGT_ADDR_LO (0x094) +#define MIU_TEST_AGT_ADDR_HI (0x098) +#define MIU_TEST_AGT_WRDATA_LO (0x0a0) +#define MIU_TEST_AGT_WRDATA_HI (0x0a4) +#define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i))) +#define MIU_TEST_AGT_RDDATA_LO (0x0a8) +#define MIU_TEST_AGT_RDDATA_HI (0x0ac) +#define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i))) +#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8 +#define MIU_TEST_AGT_UPPER_ADDR(off) (0) + +/* MIU_TEST_AGT_CTRL flags. work for SIU as well */ +#define MIU_TA_CTL_START 1 +#define MIU_TA_CTL_ENABLE 2 +#define MIU_TA_CTL_WRITE 4 +#define MIU_TA_CTL_BUSY 8 + +/*CAM RAM */ +# define QLA82XX_CAM_RAM_BASE (QLA82XX_CRB_CAM + 0x02000) +# define QLA82XX_CAM_RAM(reg) (QLA82XX_CAM_RAM_BASE + (reg)) + +#define QLA82XX_PEG_TUNE_MN_SPD_ZEROED 0x80000000 +#define QLA82XX_BOOT_LOADER_MN_ISSUE 0xff00ffff +#define QLA82XX_PORT_MODE_ADDR (QLA82XX_CAM_RAM(0x24)) +#define QLA82XX_PEG_HALT_STATUS1 (QLA82XX_CAM_RAM(0xa8)) +#define QLA82XX_PEG_HALT_STATUS2 (QLA82XX_CAM_RAM(0xac)) +#define QLA82XX_PEG_ALIVE_COUNTER (QLA82XX_CAM_RAM(0xb0)) + +#define HALT_STATUS_UNRECOVERABLE 0x80000000 +#define HALT_STATUS_RECOVERABLE 0x40000000 + + +#define QLA82XX_ROM_LOCK_ID (QLA82XX_CAM_RAM(0x100)) +#define QLA82XX_CRB_WIN_LOCK_ID (QLA82XX_CAM_RAM(0x124)) +#define QLA82XX_FW_VERSION_MAJOR (QLA82XX_CAM_RAM(0x150)) +#define QLA82XX_FW_VERSION_MINOR (QLA82XX_CAM_RAM(0x154)) +#define QLA82XX_FW_VERSION_SUB (QLA82XX_CAM_RAM(0x158)) +#define QLA82XX_PCIE_REG(reg) (QLA82XX_CRB_PCIE + (reg)) + +/* Driver Coexistence Defines */ +#define QLA82XX_CRB_DRV_ACTIVE (QLA82XX_CAM_RAM(0x138)) +#define QLA82XX_CRB_DEV_STATE (QLA82XX_CAM_RAM(0x140)) +#define QLA82XX_CRB_DEV_PART_INFO (QLA82XX_CAM_RAM(0x14c)) +#define QLA82XX_CRB_DRV_IDC_VERSION (QLA82XX_CAM_RAM(0x174)) +#define QLA82XX_CRB_DRV_STATE (QLA82XX_CAM_RAM(0x144)) +#define QLA82XX_CRB_DRV_SCRATCH (QLA82XX_CAM_RAM(0x148)) +#define QLA82XX_CRB_DEV_PART_INFO (QLA82XX_CAM_RAM(0x14c)) + +/* Every driver should use these Device State */ +#define QLA82XX_DEV_COLD 1 +#define QLA82XX_DEV_INITIALIZING 2 +#define QLA82XX_DEV_READY 3 +#define QLA82XX_DEV_NEED_RESET 4 +#define QLA82XX_DEV_NEED_QUIESCENT 5 +#define QLA82XX_DEV_FAILED 6 +#define QLA82XX_DEV_QUIESCENT 7 +#define MAX_STATES 8 /* Increment if new state added */ + +#define QLA82XX_IDC_VERSION 0x1 +#define ROM_DEV_INIT_TIMEOUT 30 +#define ROM_DRV_RESET_ACK_TIMEOUT 10 + +#define PCIE_SETUP_FUNCTION (0x12040) +#define PCIE_SETUP_FUNCTION2 (0x12048) + +#define QLA82XX_PCIX_PS_REG(reg) (QLA82XX_CRB_PCIX_MD + (reg)) +#define QLA82XX_PCIX_PS2_REG(reg) (QLA82XX_CRB_PCIE2 + (reg)) + +#define PCIE_SEM2_LOCK (0x1c010) /* Flash lock */ +#define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */ +#define PCIE_SEM5_LOCK (0x1c028) /* Coexistence lock */ +#define PCIE_SEM5_UNLOCK (0x1c02c) /* Coexistence unlock */ +#define PCIE_SEM7_LOCK (0x1c038) /* crb win lock */ +#define PCIE_SEM7_UNLOCK (0x1c03c) /* crbwin unlock*/ + +/* + * The PCI VendorID and DeviceID for our board. + */ +#define QLA82XX_MSIX_TBL_SPACE 8192 +#define QLA82XX_PCI_REG_MSIX_TBL 0x44 +#define QLA82XX_PCI_MSIX_CONTROL 0x40 + +struct crb_128M_2M_sub_block_map { + unsigned valid; + unsigned start_128M; + unsigned end_128M; + unsigned start_2M; +}; + +struct crb_128M_2M_block_map { + struct crb_128M_2M_sub_block_map sub_block[16]; +}; + +struct crb_addr_pair { + long addr; + long data; +}; + +#define ADDR_ERROR ((unsigned long) 0xffffffff) +#define MAX_CTL_CHECK 1000 + +/*************************************************************************** + * PCI related defines. + **************************************************************************/ + +/* + * Interrupt related defines. + */ +#define PCIX_TARGET_STATUS (0x10118) +#define PCIX_TARGET_STATUS_F1 (0x10160) +#define PCIX_TARGET_STATUS_F2 (0x10164) +#define PCIX_TARGET_STATUS_F3 (0x10168) +#define PCIX_TARGET_STATUS_F4 (0x10360) +#define PCIX_TARGET_STATUS_F5 (0x10364) +#define PCIX_TARGET_STATUS_F6 (0x10368) +#define PCIX_TARGET_STATUS_F7 (0x1036c) + +#define PCIX_TARGET_MASK (0x10128) +#define PCIX_TARGET_MASK_F1 (0x10170) +#define PCIX_TARGET_MASK_F2 (0x10174) +#define PCIX_TARGET_MASK_F3 (0x10178) +#define PCIX_TARGET_MASK_F4 (0x10370) +#define PCIX_TARGET_MASK_F5 (0x10374) +#define PCIX_TARGET_MASK_F6 (0x10378) +#define PCIX_TARGET_MASK_F7 (0x1037c) + +/* + * Message Signaled Interrupts + */ +#define PCIX_MSI_F0 (0x13000) +#define PCIX_MSI_F1 (0x13004) +#define PCIX_MSI_F2 (0x13008) +#define PCIX_MSI_F3 (0x1300c) +#define PCIX_MSI_F4 (0x13010) +#define PCIX_MSI_F5 (0x13014) +#define PCIX_MSI_F6 (0x13018) +#define PCIX_MSI_F7 (0x1301c) +#define PCIX_MSI_F(FUNC) (0x13000 + ((FUNC) * 4)) + +/* + * + */ +#define PCIX_INT_VECTOR (0x10100) +#define PCIX_INT_MASK (0x10104) + +/* + * Interrupt state machine and other bits. + */ +#define PCIE_MISCCFG_RC (0x1206c) + + +#define ISR_INT_TARGET_STATUS \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS)) +#define ISR_INT_TARGET_STATUS_F1 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F1)) +#define ISR_INT_TARGET_STATUS_F2 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F2)) +#define ISR_INT_TARGET_STATUS_F3 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F3)) +#define ISR_INT_TARGET_STATUS_F4 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F4)) +#define ISR_INT_TARGET_STATUS_F5 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F5)) +#define ISR_INT_TARGET_STATUS_F6 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F6)) +#define ISR_INT_TARGET_STATUS_F7 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F7)) + +#define ISR_INT_TARGET_MASK \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK)) +#define ISR_INT_TARGET_MASK_F1 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F1)) +#define ISR_INT_TARGET_MASK_F2 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F2)) +#define ISR_INT_TARGET_MASK_F3 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F3)) +#define ISR_INT_TARGET_MASK_F4 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F4)) +#define ISR_INT_TARGET_MASK_F5 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F5)) +#define ISR_INT_TARGET_MASK_F6 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F6)) +#define ISR_INT_TARGET_MASK_F7 \ + (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F7)) + +#define ISR_INT_VECTOR (QLA82XX_PCIX_PS_REG(PCIX_INT_VECTOR)) +#define ISR_INT_MASK (QLA82XX_PCIX_PS_REG(PCIX_INT_MASK)) +#define ISR_INT_STATE_REG (QLA82XX_PCIX_PS_REG(PCIE_MISCCFG_RC)) + +#define ISR_MSI_INT_TRIGGER(FUNC) (QLA82XX_PCIX_PS_REG(PCIX_MSI_F(FUNC))) + + +#define ISR_IS_LEGACY_INTR_IDLE(VAL) (((VAL) & 0x300) == 0) +#define ISR_IS_LEGACY_INTR_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) + +/* + * PCI Interrupt Vector Values. + */ +#define PCIX_INT_VECTOR_BIT_F0 0x0080 +#define PCIX_INT_VECTOR_BIT_F1 0x0100 +#define PCIX_INT_VECTOR_BIT_F2 0x0200 +#define PCIX_INT_VECTOR_BIT_F3 0x0400 +#define PCIX_INT_VECTOR_BIT_F4 0x0800 +#define PCIX_INT_VECTOR_BIT_F5 0x1000 +#define PCIX_INT_VECTOR_BIT_F6 0x2000 +#define PCIX_INT_VECTOR_BIT_F7 0x4000 + +/* struct qla4_8xxx_legacy_intr_set defined in ql4_def.h */ + +#define QLA82XX_LEGACY_INTR_CONFIG \ +{ \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \ +} + +/* Magic number to let user know flash is programmed */ +#define QLA82XX_BDINFO_MAGIC 0x12345678 +#define FW_SIZE_OFFSET (0x3e840c) + +/* QLA82XX additions */ +#define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0) +#define MIU_TEST_AGT_WRDATA_UPPER_HI (0x0b4) + +#endif diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 38b1d38afca5..64a1288e06b4 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -30,22 +30,29 @@ static struct kmem_cache *srb_cachep; * Module parameter information and variables */ int ql4xdiscoverywait = 60; -module_param(ql4xdiscoverywait, int, S_IRUGO | S_IRUSR); +module_param(ql4xdiscoverywait, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql4xdiscoverywait, "Discovery wait time"); + int ql4xdontresethba = 0; -module_param(ql4xdontresethba, int, S_IRUGO | S_IRUSR); +module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql4xdontresethba, - "Dont reset the HBA when the driver gets 0x8002 AEN " - " default it will reset hba :0" - " set to 1 to avoid resetting HBA"); + "Don't reset the HBA for driver recovery \n" + " 0 - It will reset HBA (Default)\n" + " 1 - It will NOT reset HBA"); int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */ -module_param(ql4xextended_error_logging, int, S_IRUGO | S_IRUSR); +module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql4xextended_error_logging, "Option to enable extended error logging, " "Default is 0 - no logging, 1 - debug logging"); -int ql4_mod_unload = 0; +int ql4xenablemsix = 1; +module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(ql4xenablemsix, + "Set to enable MSI or MSI-X interrupt mechanism.\n" + " 0 = enable INTx interrupt mechanism.\n" + " 1 = enable MSI-X interrupt mechanism (Default).\n" + " 2 = enable MSI interrupt mechanism."); #define QL4_DEF_QDEPTH 32 @@ -83,6 +90,9 @@ static int qla4xxx_slave_configure(struct scsi_device *device); static void qla4xxx_slave_destroy(struct scsi_device *sdev); static void qla4xxx_scan_start(struct Scsi_Host *shost); +static struct qla4_8xxx_legacy_intr_set legacy_intr[] = + QLA82XX_LEGACY_INTR_CONFIG; + static struct scsi_host_template qla4xxx_driver_template = { .module = THIS_MODULE, .name = DRIVER_NAME, @@ -152,15 +162,12 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { atomic_set(&ddb_entry->state, DDB_STATE_DEAD); - DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count " + DEBUG2(printk("scsi%ld: %s: ddb [%d] port down retry count " "of (%d) secs exhausted, marking device DEAD.\n", ha->host_no, __func__, ddb_entry->fw_ddb_index, ha->port_down_retry_count)); - DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc " - "flags = 0x%lx\n", - ha->host_no, __func__, ha->dpc_flags)); - queue_work(ha->dpc_thread, &ha->dpc_work); + qla4xxx_wake_dpc(ha); } } @@ -362,19 +369,37 @@ static void qla4xxx_stop_timer(struct scsi_qla_host *ha) * @ha: Pointer to host adapter structure. * @ddb_entry: Pointer to device database entry * - * This routine marks a device missing and resets the relogin retry count. + * This routine marks a device missing and close connection. **/ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry) { - atomic_set(&ddb_entry->state, DDB_STATE_MISSING); - DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n", - ha->host_no, ddb_entry->bus, ddb_entry->target, - ddb_entry->fw_ddb_index)); + if ((atomic_read(&ddb_entry->state) != DDB_STATE_DEAD)) { + atomic_set(&ddb_entry->state, DDB_STATE_MISSING); + DEBUG2(printk("scsi%ld: ddb [%d] marked MISSING\n", + ha->host_no, ddb_entry->fw_ddb_index)); + } else + DEBUG2(printk("scsi%ld: ddb [%d] DEAD\n", ha->host_no, + ddb_entry->fw_ddb_index)) + iscsi_block_session(ddb_entry->sess); iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED); } +/** + * qla4xxx_mark_all_devices_missing - mark all devices as missing. + * @ha: Pointer to host adapter structure. + * + * This routine marks a device missing and resets the relogin retry count. + **/ +void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha) +{ + struct ddb_entry *ddb_entry, *ddbtemp; + list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) { + qla4xxx_mark_device_missing(ha, ddb_entry); + } +} + static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry, struct scsi_cmnd *cmd, @@ -463,7 +488,13 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, return SCSI_MLQUEUE_TARGET_BUSY; } - if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) + if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || + test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || + test_bit(DPC_RESET_HA, &ha->dpc_flags) || + test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || + test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || + !test_bit(AF_ONLINE, &ha->flags) || + test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) goto qc_host_busy; spin_unlock_irq(ha->host->host_lock); @@ -524,7 +555,15 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) ha->srb_mempool = NULL; /* release io space registers */ - if (ha->reg) + if (is_qla8022(ha)) { + if (ha->nx_pcibase) + iounmap( + (struct device_reg_82xx __iomem *)ha->nx_pcibase); + + if (ha->nx_db_wr_ptr) + iounmap( + (struct device_reg_82xx __iomem *)ha->nx_db_wr_ptr); + } else if (ha->reg) iounmap(ha->reg); pci_release_regions(ha->pdev); } @@ -599,6 +638,74 @@ mem_alloc_error_exit: return QLA_ERROR; } +/** + * qla4_8xxx_check_fw_alive - Check firmware health + * @ha: Pointer to host adapter structure. + * + * Context: Interrupt + **/ +static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) +{ + uint32_t fw_heartbeat_counter, halt_status; + + fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); + + if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { + ha->seconds_since_last_heartbeat++; + /* FW not alive after 2 seconds */ + if (ha->seconds_since_last_heartbeat == 2) { + ha->seconds_since_last_heartbeat = 0; + halt_status = qla4_8xxx_rd_32(ha, + QLA82XX_PEG_HALT_STATUS1); + /* Since we cannot change dev_state in interrupt + * context, set appropriate DPC flag then wakeup + * DPC */ + if (halt_status & HALT_STATUS_UNRECOVERABLE) + set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); + else { + printk("scsi%ld: %s: detect abort needed!\n", + ha->host_no, __func__); + set_bit(DPC_RESET_HA, &ha->dpc_flags); + } + qla4xxx_wake_dpc(ha); + } + } + ha->fw_heartbeat_counter = fw_heartbeat_counter; +} + +/** + * qla4_8xxx_watchdog - Poll dev state + * @ha: Pointer to host adapter structure. + * + * Context: Interrupt + **/ +void qla4_8xxx_watchdog(struct scsi_qla_host *ha) +{ + uint32_t dev_state; + + dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + + /* don't poll if reset is going on */ + if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags)) { + if (dev_state == QLA82XX_DEV_NEED_RESET && + !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { + printk("scsi%ld: %s: HW State: NEED RESET!\n", + ha->host_no, __func__); + set_bit(DPC_RESET_HA, &ha->dpc_flags); + qla4xxx_wake_dpc(ha); + } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && + !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { + printk("scsi%ld: %s: HW State: NEED QUIES!\n", + ha->host_no, __func__); + set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags); + qla4xxx_wake_dpc(ha); + } else { + /* Check firmware health */ + qla4_8xxx_check_fw_alive(ha); + } + } +} + /** * qla4xxx_timer - checks every second for work to do. * @ha: Pointer to host adapter structure. @@ -608,6 +715,16 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) struct ddb_entry *ddb_entry, *dtemp; int start_dpc = 0; + if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { + DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", + __func__)); + return; + } + + if (is_qla8022(ha)) { + qla4_8xxx_watchdog(ha); + } + /* Search for relogin's to time-out and port down retry. */ list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { /* Count down time between sending relogins */ @@ -624,7 +741,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); set_bit(DF_RELOGIN, &ddb_entry->flags); - DEBUG2(printk("scsi%ld: %s: index [%d]" + DEBUG2(printk("scsi%ld: %s: ddb [%d]" " login device\n", ha->host_no, __func__, ddb_entry->fw_ddb_index)); @@ -647,7 +764,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) DDB_DS_SESSION_FAILED) { /* Reset retry relogin timer */ atomic_inc(&ddb_entry->relogin_retry_count); - DEBUG2(printk("scsi%ld: index[%d] relogin" + DEBUG2(printk("scsi%ld: ddb [%d] relogin" " timed out-retrying" " relogin (%d)\n", ha->host_no, @@ -656,7 +773,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) relogin_retry_count)) ); start_dpc++; - DEBUG(printk("scsi%ld:%d:%d: index [%d] " + DEBUG(printk("scsi%ld:%d:%d: ddb [%d] " "initate relogin after" " %d seconds\n", ha->host_no, ddb_entry->bus, @@ -671,31 +788,35 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) } } - /* Check for heartbeat interval. */ - if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && - ha->heartbeat_interval != 0) { - ha->seconds_since_last_heartbeat++; - if (ha->seconds_since_last_heartbeat > - ha->heartbeat_interval + 2) - set_bit(DPC_RESET_HA, &ha->dpc_flags); + if (!is_qla8022(ha)) { + /* Check for heartbeat interval. */ + if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && + ha->heartbeat_interval != 0) { + ha->seconds_since_last_heartbeat++; + if (ha->seconds_since_last_heartbeat > + ha->heartbeat_interval + 2) + set_bit(DPC_RESET_HA, &ha->dpc_flags); + } } - /* Wakeup the dpc routine for this adapter, if needed. */ if ((start_dpc || test_bit(DPC_RESET_HA, &ha->dpc_flags) || test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || - test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || + test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || + test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || + test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || test_bit(DPC_AEN, &ha->dpc_flags)) && + !test_bit(AF_DPC_SCHEDULED, &ha->flags) && ha->dpc_thread) { DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" " - dpc flags = 0x%lx\n", ha->host_no, __func__, ha->dpc_flags)); - queue_work(ha->dpc_thread, &ha->dpc_work); + qla4xxx_wake_dpc(ha); } /* Reschedule timer thread to call us back in one second */ @@ -714,16 +835,15 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) { uint32_t index = 0; - int stat = QLA_SUCCESS; unsigned long flags; struct scsi_cmnd *cmd; - int wait_cnt = WAIT_CMD_TOV; /* - * Initialized for 30 seconds as we - * expect all commands to retuned - * ASAP. - */ - while (wait_cnt) { + unsigned long wtime = jiffies + (WAIT_CMD_TOV * HZ); + + DEBUG2(ql4_printk(KERN_INFO, ha, "Wait up to %d seconds for cmds to " + "complete\n", WAIT_CMD_TOV)); + + while (!time_after_eq(jiffies, wtime)) { spin_lock_irqsave(&ha->hardware_lock, flags); /* Find a command that hasn't completed. */ for (index = 0; index < ha->host->can_queue; index++) { @@ -734,31 +854,26 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) spin_unlock_irqrestore(&ha->hardware_lock, flags); /* If No Commands are pending, wait is complete */ - if (index == ha->host->can_queue) { - break; - } - - /* If we timed out on waiting for commands to come back - * return ERROR. - */ - wait_cnt--; - if (wait_cnt == 0) - stat = QLA_ERROR; - else { - msleep(1000); - } - } /* End of While (wait_cnt) */ + if (index == ha->host->can_queue) + return QLA_SUCCESS; - return stat; + msleep(1000); + } + /* If we timed out on waiting for commands to come back + * return ERROR. */ + return QLA_ERROR; } -void qla4xxx_hw_reset(struct scsi_qla_host *ha) +int qla4xxx_hw_reset(struct scsi_qla_host *ha) { uint32_t ctrl_status; unsigned long flags = 0; DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); + if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) + return QLA_ERROR; + spin_lock_irqsave(&ha->hardware_lock, flags); /* @@ -774,6 +889,7 @@ void qla4xxx_hw_reset(struct scsi_qla_host *ha) readl(&ha->reg->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); + return QLA_SUCCESS; } /** @@ -872,15 +988,16 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha) } /** - * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S. + * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S. * @ha: Pointer to host adapter structure. + * @res: returned scsi status * * This routine is called just prior to a HARD RESET to return all * outstanding commands back to the Operating System. * Caller should make sure that the following locks are released * before this calling routine: Hardware lock, and io_request_lock. **/ -static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) +static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res) { struct srb *srb; int i; @@ -890,74 +1007,116 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) for (i = 0; i < ha->host->can_queue; i++) { srb = qla4xxx_del_from_active_array(ha, i); if (srb != NULL) { - srb->cmd->result = DID_RESET << 16; + srb->cmd->result = res; kref_put(&srb->srb_ref, qla4xxx_srb_compl); } } spin_unlock_irqrestore(&ha->hardware_lock, flags); } +void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha) +{ + clear_bit(AF_ONLINE, &ha->flags); + + /* Disable the board */ + ql4_printk(KERN_INFO, ha, "Disabling the board\n"); + set_bit(AF_HBA_GOING_AWAY, &ha->flags); + + qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); + qla4xxx_mark_all_devices_missing(ha); + clear_bit(AF_INIT_DONE, &ha->flags); +} + /** * qla4xxx_recover_adapter - recovers adapter after a fatal error * @ha: Pointer to host adapter structure. - * @renew_ddb_list: Indicates what to do with the adapter's ddb list - * - * renew_ddb_list value can be 0=preserve ddb list, 1=destroy and rebuild - * ddb list. **/ -static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, - uint8_t renew_ddb_list) +static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) { - int status; + int status = QLA_ERROR; + uint8_t reset_chip = 0; /* Stall incoming I/O until we are done */ + scsi_block_requests(ha->host); clear_bit(AF_ONLINE, &ha->flags); - DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no, - __func__)); + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__)); - /* Wait for outstanding commands to complete. - * Stalls the driver for max 30 secs - */ - status = qla4xxx_cmd_wait(ha); + set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); - qla4xxx_disable_intrs(ha); + if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) + reset_chip = 1; - /* Flush any pending ddb changed AENs */ - qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); + /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific) + * do not reset adapter, jump to initialize_adapter */ + if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { + status = QLA_SUCCESS; + goto recover_ha_init_adapter; + } - qla4xxx_flush_active_srbs(ha); + /* For the ISP-82xx adapter, issue a stop_firmware if invoked + * from eh_host_reset or ioctl module */ + if (is_qla8022(ha) && !reset_chip && + test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) { + + DEBUG2(ql4_printk(KERN_INFO, ha, + "scsi%ld: %s - Performing stop_firmware...\n", + ha->host_no, __func__)); + status = ha->isp_ops->reset_firmware(ha); + if (status == QLA_SUCCESS) { + qla4xxx_cmd_wait(ha); + ha->isp_ops->disable_intrs(ha); + qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); + qla4xxx_abort_active_cmds(ha, DID_RESET << 16); + } else { + /* If the stop_firmware fails then + * reset the entire chip */ + reset_chip = 1; + clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); + set_bit(DPC_RESET_HA, &ha->dpc_flags); + } + } - /* Reset the firmware. If successful, function - * returns with ISP interrupts enabled. - */ - DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", - ha->host_no, __func__)); - if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) - status = qla4xxx_soft_reset(ha); - else - status = QLA_ERROR; + /* Issue full chip reset if recovering from a catastrophic error, + * or if stop_firmware fails for ISP-82xx. + * This is the default case for ISP-4xxx */ + if (!is_qla8022(ha) || reset_chip) { + qla4xxx_cmd_wait(ha); + qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); + qla4xxx_abort_active_cmds(ha, DID_RESET << 16); + DEBUG2(ql4_printk(KERN_INFO, ha, + "scsi%ld: %s - Performing chip reset..\n", + ha->host_no, __func__)); + status = ha->isp_ops->reset_chip(ha); + } /* Flush any pending ddb changed AENs */ qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); - /* Re-initialize firmware. If successful, function returns - * with ISP interrupts enabled */ +recover_ha_init_adapter: + /* Upon successful firmware/chip reset, re-initialize the adapter */ if (status == QLA_SUCCESS) { - DEBUG2(printk("scsi%ld: %s - Initializing adapter..\n", - ha->host_no, __func__)); - - /* If successful, AF_ONLINE flag set in - * qla4xxx_initialize_adapter */ - status = qla4xxx_initialize_adapter(ha, renew_ddb_list); + /* For ISP-4xxx, force function 1 to always initialize + * before function 3 to prevent both funcions from + * stepping on top of the other */ + if (!is_qla8022(ha) && (ha->mac_index == 3)) + ssleep(6); + + /* NOTE: AF_ONLINE flag set upon successful completion of + * qla4xxx_initialize_adapter */ + status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); } - /* Failed adapter initialization? - * Retry reset_ha only if invoked via DPC (DPC_RESET_HA) */ - if ((test_bit(AF_ONLINE, &ha->flags) == 0) && - (test_bit(DPC_RESET_HA, &ha->dpc_flags))) { + /* Retry failed adapter initialization, if necessary + * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific) + * case to prevent ping-pong resets between functions */ + if (!test_bit(AF_ONLINE, &ha->flags) && + !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { /* Adapter initialization failed, see if we can retry - * resetting the ha */ + * resetting the ha. + * Since we don't want to block the DPC for too long + * with multiple resets in the same thread, + * utilize DPC to retry */ if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; DEBUG2(printk("scsi%ld: recover adapter - retrying " @@ -982,29 +1141,43 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, DEBUG2(printk("scsi%ld: recover adapter " "failed - board disabled\n", ha->host_no)); - qla4xxx_flush_active_srbs(ha); + qla4xxx_dead_adapter_cleanup(ha); clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); clear_bit(DPC_RESET_HA, &ha->dpc_flags); - clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, + clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); status = QLA_ERROR; } } } else { clear_bit(DPC_RESET_HA, &ha->dpc_flags); - clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags); + clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); } ha->adapter_error_count++; - if (status == QLA_SUCCESS) - qla4xxx_enable_intrs(ha); + if (test_bit(AF_ONLINE, &ha->flags)) + ha->isp_ops->enable_intrs(ha); + + scsi_unblock_requests(ha->host); + + clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); + DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no, + status == QLA_ERROR ? "FAILED" : "SUCCEDED")); - DEBUG2(printk("scsi%ld: recover adapter .. DONE\n", ha->host_no)); return status; } +void qla4xxx_wake_dpc(struct scsi_qla_host *ha) +{ + if (ha->dpc_thread && + !test_bit(AF_DPC_SCHEDULED, &ha->flags)) { + set_bit(AF_DPC_SCHEDULED, &ha->flags); + queue_work(ha->dpc_thread, &ha->dpc_work); + } +} + /** * qla4xxx_do_dpc - dpc routine * @data: in our case pointer to adapter structure @@ -1024,21 +1197,47 @@ static void qla4xxx_do_dpc(struct work_struct *work) int status = QLA_ERROR; DEBUG2(printk("scsi%ld: %s: DPC handler waking up." - "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n", - ha->host_no, __func__, ha->flags, ha->dpc_flags, - readw(&ha->reg->ctrl_status))); + "flags = 0x%08lx, dpc_flags = 0x%08lx\n", + ha->host_no, __func__, ha->flags, ha->dpc_flags)) /* Initialization not yet finished. Don't do anything yet. */ if (!test_bit(AF_INIT_DONE, &ha->flags)) return; - if (adapter_up(ha) || - test_bit(DPC_RESET_HA, &ha->dpc_flags) || + /* HBA is in the process of being permanently disabled. + * Don't process anything */ + if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) + return; + + if (is_qla8022(ha)) { + if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { + qla4_8xxx_idc_lock(ha); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_FAILED); + qla4_8xxx_idc_unlock(ha); + ql4_printk(KERN_INFO, ha, "HW State: FAILED\n"); + qla4_8xxx_device_state_handler(ha); + } + if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { + qla4_8xxx_need_qsnt_handler(ha); + } + } + + if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) && + (test_bit(DPC_RESET_HA, &ha->dpc_flags) || test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || - test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { - if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || - test_bit(DPC_RESET_HA, &ha->dpc_flags)) - qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); + test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) { + if (ql4xdontresethba) { + DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", + ha->host_no, __func__)); + clear_bit(DPC_RESET_HA, &ha->dpc_flags); + clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); + clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); + goto dpc_post_reset_ha; + } + if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || + test_bit(DPC_RESET_HA, &ha->dpc_flags)) + qla4xxx_recover_adapter(ha); if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { uint8_t wait_time = RESET_INTR_TOV; @@ -1053,18 +1252,18 @@ static void qla4xxx_do_dpc(struct work_struct *work) DEBUG2(printk("scsi%ld: %s: SR|FSR " "bit not cleared-- resetting\n", ha->host_no, __func__)); - qla4xxx_flush_active_srbs(ha); + qla4xxx_abort_active_cmds(ha, DID_RESET << 16); if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); - status = qla4xxx_initialize_adapter(ha, - PRESERVE_DDB_LIST); + status = qla4xxx_recover_adapter(ha); } clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); if (status == QLA_SUCCESS) - qla4xxx_enable_intrs(ha); + ha->isp_ops->enable_intrs(ha); } } +dpc_post_reset_ha: /* ---- process AEN? --- */ if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) qla4xxx_process_aen(ha, PROCESS_ALL_AENS); @@ -1104,11 +1303,9 @@ static void qla4xxx_do_dpc(struct work_struct *work) DDB_STATE_ONLINE); dev_info(&ha->pdev->dev, "scsi%ld: %s: ddb[%d]" - " os[%d] marked" - " ONLINE\n", + " marked ONLINE\n", ha->host_no, __func__, - ddb_entry->fw_ddb_index, - ddb_entry->os_target_id); + ddb_entry->fw_ddb_index); iscsi_unblock_session( ddb_entry->sess); @@ -1144,6 +1341,7 @@ static void qla4xxx_do_dpc(struct work_struct *work) } } } + clear_bit(AF_DPC_SCHEDULED, &ha->flags); } /** @@ -1155,30 +1353,99 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { /* Turn-off interrupts on the card. */ - qla4xxx_disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); } + /* Remove timer thread, if present */ + if (ha->timer_active) + qla4xxx_stop_timer(ha); + /* Kill the kernel thread for this host */ if (ha->dpc_thread) destroy_workqueue(ha->dpc_thread); - /* Issue Soft Reset to put firmware in unknown state */ - if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) - qla4xxx_hw_reset(ha); + /* Put firmware in known state */ + ha->isp_ops->reset_firmware(ha); - /* Remove timer thread, if present */ - if (ha->timer_active) - qla4xxx_stop_timer(ha); + if (is_qla8022(ha)) { + qla4_8xxx_idc_lock(ha); + qla4_8xxx_clear_drv_active(ha); + qla4_8xxx_idc_unlock(ha); + } /* Detach interrupts */ if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) - free_irq(ha->pdev->irq, ha); + qla4xxx_free_irqs(ha); /* free extra memory */ qla4xxx_mem_free(ha); +} + +int qla4_8xxx_iospace_config(struct scsi_qla_host *ha) +{ + int status = 0; + uint8_t revision_id; + unsigned long mem_base, mem_len, db_base, db_len; + struct pci_dev *pdev = ha->pdev; + + status = pci_request_regions(pdev, DRIVER_NAME); + if (status) { + printk(KERN_WARNING + "scsi(%ld) Failed to reserve PIO regions (%s) " + "status=%d\n", ha->host_no, pci_name(pdev), status); + goto iospace_error_exit; + } + + pci_read_config_byte(pdev, PCI_REVISION_ID, &revision_id); + DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n", + __func__, revision_id)); + ha->revision_id = revision_id; - pci_disable_device(ha->pdev); + /* remap phys address */ + mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ + mem_len = pci_resource_len(pdev, 0); + DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n", + __func__, mem_base, mem_len)); + /* mapping of pcibase pointer */ + ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len); + if (!ha->nx_pcibase) { + printk(KERN_ERR + "cannot remap MMIO (%s), aborting\n", pci_name(pdev)); + pci_release_regions(ha->pdev); + goto iospace_error_exit; + } + + /* Mapping of IO base pointer, door bell read and write pointer */ + + /* mapping of IO base pointer */ + ha->qla4_8xxx_reg = + (struct device_reg_82xx __iomem *)((uint8_t *)ha->nx_pcibase + + 0xbc000 + (ha->pdev->devfn << 11)); + + db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */ + db_len = pci_resource_len(pdev, 4); + + /* mapping of doorbell write pointer */ + ha->nx_db_wr_ptr = (unsigned long)ioremap(db_base + + (ha->pdev->devfn << 12), 4); + if (!ha->nx_db_wr_ptr) { + printk(KERN_ERR + "cannot remap MMIO doorbell-write (%s), aborting\n", + pci_name(pdev)); + goto iospace_error_exit; + } + /* mapping of doorbell read pointer */ + ha->nx_db_rd_ptr = (uint8_t *) ha->nx_pcibase + (512 * 1024) + + (ha->pdev->devfn * 8); + if (!ha->nx_db_rd_ptr) + printk(KERN_ERR + "cannot remap MMIO doorbell-read (%s), aborting\n", + pci_name(pdev)); + return 0; + +iospace_error_exit: + return -ENOMEM; } /*** @@ -1188,7 +1455,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) * This routines maps HBA's registers from the pci address space * into the kernel virtual address space for memory mapped i/o. **/ -static int qla4xxx_iospace_config(struct scsi_qla_host *ha) +int qla4xxx_iospace_config(struct scsi_qla_host *ha) { unsigned long pio, pio_len, pio_flags; unsigned long mmio, mmio_len, mmio_flags; @@ -1247,6 +1514,60 @@ iospace_error_exit: return -ENOMEM; } +static struct isp_operations qla4xxx_isp_ops = { + .iospace_config = qla4xxx_iospace_config, + .pci_config = qla4xxx_pci_config, + .disable_intrs = qla4xxx_disable_intrs, + .enable_intrs = qla4xxx_enable_intrs, + .start_firmware = qla4xxx_start_firmware, + .intr_handler = qla4xxx_intr_handler, + .interrupt_service_routine = qla4xxx_interrupt_service_routine, + .reset_chip = qla4xxx_soft_reset, + .reset_firmware = qla4xxx_hw_reset, + .queue_iocb = qla4xxx_queue_iocb, + .complete_iocb = qla4xxx_complete_iocb, + .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out, + .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in, + .get_sys_info = qla4xxx_get_sys_info, +}; + +static struct isp_operations qla4_8xxx_isp_ops = { + .iospace_config = qla4_8xxx_iospace_config, + .pci_config = qla4_8xxx_pci_config, + .disable_intrs = qla4_8xxx_disable_intrs, + .enable_intrs = qla4_8xxx_enable_intrs, + .start_firmware = qla4_8xxx_load_risc, + .intr_handler = qla4_8xxx_intr_handler, + .interrupt_service_routine = qla4_8xxx_interrupt_service_routine, + .reset_chip = qla4_8xxx_isp_reset, + .reset_firmware = qla4_8xxx_stop_firmware, + .queue_iocb = qla4_8xxx_queue_iocb, + .complete_iocb = qla4_8xxx_complete_iocb, + .rd_shdw_req_q_out = qla4_8xxx_rd_shdw_req_q_out, + .rd_shdw_rsp_q_in = qla4_8xxx_rd_shdw_rsp_q_in, + .get_sys_info = qla4_8xxx_get_sys_info, +}; + +uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) +{ + return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out); +} + +uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) +{ + return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->req_q_out)); +} + +uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) +{ + return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); +} + +uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) +{ + return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in)); +} + /** * qla4xxx_probe_adapter - callback function to probe HBA * @pdev: pointer to pci_dev structure @@ -1264,6 +1585,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, struct scsi_qla_host *ha; uint8_t init_retry_count = 0; char buf[34]; + struct qla4_8xxx_legacy_intr_set *nx_legacy_intr; if (pci_enable_device(pdev)) return -1; @@ -1284,10 +1606,28 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ha->host = host; ha->host_no = host->host_no; + /* Setup Runtime configurable options */ + if (is_qla8022(ha)) { + ha->isp_ops = &qla4_8xxx_isp_ops; + rwlock_init(&ha->hw_lock); + ha->qdr_sn_window = -1; + ha->ddr_mn_window = -1; + ha->curr_window = 255; + ha->func_num = PCI_FUNC(ha->pdev->devfn); + nx_legacy_intr = &legacy_intr[ha->func_num]; + ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit; + ha->nx_legacy_intr.tgt_status_reg = + nx_legacy_intr->tgt_status_reg; + ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg; + ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; + } else { + ha->isp_ops = &qla4xxx_isp_ops; + } + /* Configure PCI I/O space. */ - ret = qla4xxx_iospace_config(ha); + ret = ha->isp_ops->iospace_config(ha); if (ret) - goto probe_failed; + goto probe_failed_ioconfig; dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n", pdev->device, pdev->irq, ha->reg); @@ -1299,6 +1639,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, INIT_LIST_HEAD(&ha->free_srb_q); mutex_init(&ha->mbox_sem); + init_completion(&ha->mbx_intr_comp); spin_lock_init(&ha->hardware_lock); @@ -1311,19 +1652,27 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, goto probe_failed; } + if (is_qla8022(ha)) + (void) qla4_8xxx_get_flash_info(ha); + /* * Initialize the Host adapter request/response queues and * firmware * NOTE: interrupts enabled upon successful completion */ status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); - while (status == QLA_ERROR && init_retry_count++ < MAX_INIT_RETRIES) { + while ((!test_bit(AF_ONLINE, &ha->flags)) && + init_retry_count++ < MAX_INIT_RETRIES) { DEBUG2(printk("scsi: %s: retrying adapter initialization " "(%d)\n", __func__, init_retry_count)); - qla4xxx_soft_reset(ha); + + if (ha->isp_ops->reset_chip(ha) == QLA_ERROR) + continue; + status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); } - if (status == QLA_ERROR) { + + if (!test_bit(AF_ONLINE, &ha->flags)) { dev_warn(&ha->pdev->dev, "Failed to initialize adapter\n"); ret = -ENODEV; @@ -1356,18 +1705,21 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, } INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); - ret = request_irq(pdev->irq, qla4xxx_intr_handler, - IRQF_DISABLED | IRQF_SHARED, "qla4xxx", ha); - if (ret) { - dev_warn(&ha->pdev->dev, "Failed to reserve interrupt %d" - " already in use.\n", pdev->irq); - goto probe_failed; + /* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc + * (which is called indirectly by qla4xxx_initialize_adapter), + * so that irqs will be registered after crbinit but before + * mbx_intr_enable. + */ + if (!is_qla8022(ha)) { + ret = qla4xxx_request_irqs(ha); + if (ret) { + ql4_printk(KERN_WARNING, ha, "Failed to reserve " + "interrupt %d already in use.\n", pdev->irq); + goto probe_failed; + } } - set_bit(AF_IRQ_ATTACHED, &ha->flags); - host->irq = pdev->irq; - DEBUG(printk("scsi%d: irq %d attached\n", ha->host_no, ha->pdev->irq)); - qla4xxx_enable_intrs(ha); + ha->isp_ops->enable_intrs(ha); /* Start timer thread. */ qla4xxx_start_timer(ha, qla4xxx_timer, 1); @@ -1391,6 +1743,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, probe_failed: qla4xxx_free_adapter(ha); + +probe_failed_ioconfig: scsi_host_put(ha->host); probe_disable_device: @@ -1409,10 +1763,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) ha = pci_get_drvdata(pdev); - qla4xxx_disable_intrs(ha); - - while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) - ssleep(1); + set_bit(AF_HBA_GOING_AWAY, &ha->flags); /* remove devs from iscsi_sessions to scsi_devices */ qla4xxx_free_ddb_list(ha); @@ -1423,6 +1774,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) scsi_host_put(ha->host); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } @@ -1479,7 +1831,8 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev) * * This routine removes and returns the srb at the specified index **/ -struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index) +struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, + uint32_t index) { struct srb *srb = NULL; struct scsi_cmnd *cmd = NULL; @@ -1769,6 +2122,12 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) ha = (struct scsi_qla_host *) cmd->device->host->hostdata; + if (ql4xdontresethba) { + DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", + ha->host_no, __func__)); + return FAILED; + } + dev_info(&ha->pdev->dev, "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); @@ -1781,11 +2140,14 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) return FAILED; } - /* make sure the dpc thread is stopped while we reset the hba */ - clear_bit(AF_ONLINE, &ha->flags); - flush_workqueue(ha->dpc_thread); + if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) { + if (is_qla8022(ha)) + set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); + else + set_bit(DPC_RESET_HA, &ha->dpc_flags); + } - if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) + if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS) return_status = SUCCESS; dev_info(&ha->pdev->dev, "HOST RESET %s.\n", @@ -1794,7 +2156,6 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) return return_status; } - static struct pci_device_id qla4xxx_pci_tbl[] = { { .vendor = PCI_VENDOR_ID_QLOGIC, @@ -1814,6 +2175,12 @@ static struct pci_device_id qla4xxx_pci_tbl[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, + { + .vendor = PCI_VENDOR_ID_QLOGIC, + .device = PCI_DEVICE_ID_QLOGIC_ISP8022, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, {0, 0}, }; MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); @@ -1869,7 +2236,6 @@ no_srp_cache: static void __exit qla4xxx_module_exit(void) { - ql4_mod_unload = 1; pci_unregister_driver(&qla4xxx_pci_driver); iscsi_unregister_transport(&qla4xxx_iscsi_transport); kmem_cache_destroy(srb_cachep); -- cgit v1.2.3 From c2660df310a3c445194748b54f51b7224639e742 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Sat, 10 Jul 2010 14:51:02 +0530 Subject: [SCSI] qla4xxx: replace all dev_info, dev_warn, dev_err with ql4_printk Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 50 ++++++++++++++++----------------- drivers/scsi/qla4xxx/ql4_isr.c | 8 +++--- drivers/scsi/qla4xxx/ql4_mbx.c | 4 +-- drivers/scsi/qla4xxx/ql4_os.c | 62 +++++++++++++++++++++-------------------- 4 files changed, 63 insertions(+), 61 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 539546df0376..5fc19c44bada 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -297,7 +297,7 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) uint32_t timeout_count; int ready = 0; - DEBUG2(dev_info(&ha->pdev->dev, "Waiting for Firmware Ready..\n")); + DEBUG2(ql4_printk(KERN_INFO, ha, "Waiting for Firmware Ready..\n")); for (timeout_count = ADAPTER_INIT_TOV; timeout_count > 0; timeout_count--) { if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags)) @@ -370,29 +370,29 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) if (!qla4xxx_wait_for_ip_config(ha) || timeout_count == 1) { - DEBUG2(dev_info(&ha->pdev->dev, - "Firmware Ready..\n")); + DEBUG2(ql4_printk(KERN_INFO, ha, + "Firmware Ready..\n")); /* The firmware is ready to process SCSI commands. */ - DEBUG2(dev_info(&ha->pdev->dev, + DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: MEDIA TYPE" " - %s\n", ha->host_no, __func__, (ha->addl_fw_state & FW_ADDSTATE_OPTICAL_MEDIA) != 0 ? "OPTICAL" : "COPPER")); - DEBUG2(dev_info(&ha->pdev->dev, + DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: DHCPv4 STATE" " Enabled %s\n", ha->host_no, __func__, (ha->addl_fw_state & FW_ADDSTATE_DHCPv4_ENABLED) != 0 ? "YES" : "NO")); - DEBUG2(dev_info(&ha->pdev->dev, + DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: LINK %s\n", ha->host_no, __func__, (ha->addl_fw_state & FW_ADDSTATE_LINK_UP) != 0 ? "UP" : "DOWN")); - DEBUG2(dev_info(&ha->pdev->dev, + DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: %s: iSNS Service " "Started %s\n", ha->host_no, __func__, @@ -445,7 +445,7 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) { int status = QLA_ERROR; - dev_info(&ha->pdev->dev, "Initializing firmware..\n"); + ql4_printk(KERN_INFO, ha, "Initializing firmware..\n"); if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) { DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware " "control block\n", ha->host_no, __func__)); @@ -694,18 +694,18 @@ int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err) err_code = ((conn_err & 0x00ff0000) >> 16); login_rsp_sts_class = ((conn_err & 0x0000ff00) >> 8); if (err_code == 0x1c || err_code == 0x06) { - DEBUG2(dev_info(&ha->pdev->dev, - ": conn_err=0x%08x, send target completed" - " or access denied failure\n", conn_err)); + DEBUG2(ql4_printk(KERN_INFO, ha, + ": conn_err=0x%08x, send target completed" + " or access denied failure\n", conn_err)); relogin = 0; } if ((err_code == 0x08) && (login_rsp_sts_class == 0x02)) { /* Login Response PDU returned an error. Login Response Status in Error Code Detail indicates login should not be retried.*/ - DEBUG2(dev_info(&ha->pdev->dev, - ": conn_err=0x%08x, do not retry relogin\n", - conn_err)); + DEBUG2(ql4_printk(KERN_INFO, ha, + ": conn_err=0x%08x, do not retry relogin\n", + conn_err)); relogin = 0; } @@ -736,13 +736,13 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), &fw_ddb_entry_dma, GFP_KERNEL); if (fw_ddb_entry == NULL) { - DEBUG2(dev_info(&ha->pdev->dev, "%s: DMA alloc failed\n", + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DMA alloc failed\n", __func__)); goto exit_build_ddb_list_no_free; } - dev_info(&ha->pdev->dev, "Initializing DDBs ...\n"); + ql4_printk(KERN_INFO, ha, "Initializing DDBs ...\n"); for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index = next_fw_ddb_index) { /* First, let's see if a device exists here */ @@ -826,7 +826,7 @@ next_one: } status = QLA_SUCCESS; - dev_info(&ha->pdev->dev, "DDB list done..\n"); + ql4_printk(KERN_INFO, ha, "DDB list done..\n"); exit_build_ddb_list: dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, @@ -1080,17 +1080,17 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha) } /* Get EEPRom Parameters from NVRAM and validate */ - dev_info(&ha->pdev->dev, "Configuring NVRAM ...\n"); + ql4_printk(KERN_INFO, ha, "Configuring NVRAM ...\n"); if (qla4xxx_is_nvram_configuration_valid(ha) == QLA_SUCCESS) { spin_lock_irqsave(&ha->hardware_lock, flags); extHwConfig.Asuint32_t = rd_nvram_word(ha, eeprom_ext_hw_conf_offset(ha)); spin_unlock_irqrestore(&ha->hardware_lock, flags); } else { - dev_warn(&ha->pdev->dev, - "scsi%ld: %s: EEProm checksum invalid. " - "Please update your EEPROM\n", ha->host_no, - __func__); + ql4_printk(KERN_WARNING, ha, + "scsi%ld: %s: EEProm checksum invalid. " + "Please update your EEPROM\n", ha->host_no, + __func__); /* Attempt to set defaults */ if (is_qla4010(ha)) @@ -1128,7 +1128,7 @@ void qla4xxx_pci_config(struct scsi_qla_host *ha) uint16_t w; int status; - dev_info(&ha->pdev->dev, "Configuring PCI space...\n"); + ql4_printk(KERN_INFO, ha, "Configuring PCI space...\n"); pci_set_master(ha->pdev); status = pci_set_mwi(ha->pdev); @@ -1150,7 +1150,7 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) unsigned long flags; uint32_t mbox_status; - dev_info(&ha->pdev->dev, "Starting firmware ...\n"); + ql4_printk(KERN_INFO, ha, "Starting firmware ...\n"); /* * Start firmware from flash ROM @@ -1569,7 +1569,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, } else { /* Device went away, mark device missing */ if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) { - DEBUG2(dev_info(&ha->pdev->dev, "%s mark missing " + DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing " "ddb_entry 0x%p sess 0x%p conn 0x%p\n", __func__, ddb_entry, ddb_entry->sess, ddb_entry->conn)); diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 68d7942bf2e3..aa65697a86b4 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -122,8 +122,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, "handle 0x%x, sp=%p. This cmd may have already " "been completed.\n", ha->host_no, __func__, le32_to_cpu(sts_entry->handle), srb)); - dev_warn(&ha->pdev->dev, "%s invalid status entry:" - " handle=0x%0x\n", __func__, sts_entry->handle); + ql4_printk(KERN_WARNING, ha, "%s invalid status entry:" + " handle=0x%0x\n", __func__, sts_entry->handle); set_bit(DPC_RESET_HA, &ha->dpc_flags); return; } @@ -134,8 +134,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, "OS pkt->handle=%d srb=%p srb->state:%d\n", ha->host_no, __func__, sts_entry->handle, srb, srb->state)); - dev_warn(&ha->pdev->dev, "Command is NULL:" - " already returned to OS (srb=%p)\n", srb); + ql4_printk(KERN_WARNING, ha, "Command is NULL:" + " already returned to OS (srb=%p)\n", srb); return; } diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 0d3a65268419..940ee561ee0a 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -607,7 +607,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, if (fw_ddb_entry) { options = le16_to_cpu(fw_ddb_entry->options); if (options & DDB_OPT_IPV6_DEVICE) { - dev_info(&ha->pdev->dev, "%s: DDB[%d] MB0 %04x Tot %d " + ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " "Next %d State %04x ConnErr %08x %pI6 " ":%04d \"%s\"\n", __func__, fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3], @@ -616,7 +616,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, le16_to_cpu(fw_ddb_entry->port), fw_ddb_entry->iscsi_name); } else { - dev_info(&ha->pdev->dev, "%s: DDB[%d] MB0 %04x Tot %d " + ql4_printk(KERN_INFO, ha, "%s: DDB[%d] MB0 %04x Tot %d " "Next %d State %04x ConnErr %08x %pI4 " ":%04d \"%s\"\n", __func__, fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3], diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 64a1288e06b4..daf5a4bf9b0a 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -588,8 +588,8 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha) ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len, &ha->queues_dma, GFP_KERNEL); if (ha->queues == NULL) { - dev_warn(&ha->pdev->dev, - "Memory Allocation failed - queues.\n"); + ql4_printk(KERN_WARNING, ha, + "Memory Allocation failed - queues.\n"); goto mem_alloc_error_exit; } @@ -625,8 +625,8 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha) ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab, mempool_free_slab, srb_cachep); if (ha->srb_mempool == NULL) { - dev_warn(&ha->pdev->dev, - "Memory Allocation failed - SRB Pool.\n"); + ql4_printk(KERN_WARNING, ha, + "Memory Allocation failed - SRB Pool.\n"); goto mem_alloc_error_exit; } @@ -1301,7 +1301,7 @@ dpc_post_reset_ha: DDB_DS_SESSION_ACTIVE) { atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); - dev_info(&ha->pdev->dev, + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" " marked ONLINE\n", ha->host_no, __func__, @@ -1465,12 +1465,12 @@ int qla4xxx_iospace_config(struct scsi_qla_host *ha) pio_flags = pci_resource_flags(ha->pdev, 0); if (pio_flags & IORESOURCE_IO) { if (pio_len < MIN_IOBASE_LEN) { - dev_warn(&ha->pdev->dev, + ql4_printk(KERN_WARNING, ha, "Invalid PCI I/O region size\n"); pio = 0; } } else { - dev_warn(&ha->pdev->dev, "region #0 not a PIO resource\n"); + ql4_printk(KERN_WARNING, ha, "region #0 not a PIO resource\n"); pio = 0; } @@ -1480,20 +1480,21 @@ int qla4xxx_iospace_config(struct scsi_qla_host *ha) mmio_flags = pci_resource_flags(ha->pdev, 1); if (!(mmio_flags & IORESOURCE_MEM)) { - dev_err(&ha->pdev->dev, - "region #0 not an MMIO resource, aborting\n"); + ql4_printk(KERN_ERR, ha, + "region #0 not an MMIO resource, aborting\n"); goto iospace_error_exit; } + if (mmio_len < MIN_IOBASE_LEN) { - dev_err(&ha->pdev->dev, - "Invalid PCI mem region size, aborting\n"); + ql4_printk(KERN_ERR, ha, + "Invalid PCI mem region size, aborting\n"); goto iospace_error_exit; } if (pci_request_regions(ha->pdev, DRIVER_NAME)) { - dev_warn(&ha->pdev->dev, - "Failed to reserve PIO/MMIO regions\n"); + ql4_printk(KERN_WARNING, ha, + "Failed to reserve PIO/MMIO regions\n"); goto iospace_error_exit; } @@ -1502,8 +1503,8 @@ int qla4xxx_iospace_config(struct scsi_qla_host *ha) ha->pio_length = pio_len; ha->reg = ioremap(mmio, MIN_IOBASE_LEN); if (!ha->reg) { - dev_err(&ha->pdev->dev, - "cannot remap MMIO, aborting\n"); + ql4_printk(KERN_ERR, ha, + "cannot remap MMIO, aborting\n"); goto iospace_error_exit; } @@ -1629,7 +1630,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, if (ret) goto probe_failed_ioconfig; - dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n", + ql4_printk(KERN_INFO, ha, "Found an ISP%04x, irq %d, iobase 0x%p\n", pdev->device, pdev->irq, ha->reg); qla4xxx_config_dma_addressing(ha); @@ -1645,8 +1646,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, /* Allocate dma buffers */ if (qla4xxx_mem_alloc(ha)) { - dev_warn(&ha->pdev->dev, - "[ERROR] Failed to allocate memory for adapter\n"); + ql4_printk(KERN_WARNING, ha, + "[ERROR] Failed to allocate memory for adapter\n"); ret = -ENOMEM; goto probe_failed; @@ -1673,7 +1674,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, } if (!test_bit(AF_ONLINE, &ha->flags)) { - dev_warn(&ha->pdev->dev, "Failed to initialize adapter\n"); + ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n"); ret = -ENODEV; goto probe_failed; @@ -1689,8 +1690,9 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ret = scsi_init_shared_tag_map(host, MAX_SRBS); if (ret) { - dev_warn(&ha->pdev->dev, "scsi_init_shared_tag_map failed\n"); - goto probe_failed; + ql4_printk(KERN_WARNING, ha, + "scsi_init_shared_tag_map failed\n"); + goto probe_failed; } /* Startup the kernel thread for this host adapter. */ @@ -1699,7 +1701,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no); ha->dpc_thread = create_singlethread_workqueue(buf); if (!ha->dpc_thread) { - dev_warn(&ha->pdev->dev, "Unable to start DPC thread!\n"); + ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n"); ret = -ENODEV; goto probe_failed; } @@ -1958,7 +1960,7 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) int ret = SUCCESS; int wait = 0; - dev_info(&ha->pdev->dev, + ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Abort command issued cmd=%p, pid=%ld\n", ha->host_no, id, lun, cmd, serial); @@ -1990,7 +1992,7 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) } } - dev_info(&ha->pdev->dev, + ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Abort command - %s\n", ha->host_no, id, lun, (ret == SUCCESS) ? "succeded" : "failed"); @@ -2013,7 +2015,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) if (!ddb_entry) return ret; - dev_info(&ha->pdev->dev, + ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); @@ -2026,13 +2028,13 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) /* FIXME: wait for hba to go online */ stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun); if (stat != QLA_SUCCESS) { - dev_info(&ha->pdev->dev, "DEVICE RESET FAILED. %d\n", stat); + ql4_printk(KERN_INFO, ha, "DEVICE RESET FAILED. %d\n", stat); goto eh_dev_reset_done; } if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), cmd->device)) { - dev_info(&ha->pdev->dev, + ql4_printk(KERN_INFO, ha, "DEVICE RESET FAILED - waiting for " "commands.\n"); goto eh_dev_reset_done; @@ -2043,7 +2045,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) MM_LUN_RESET) != QLA_SUCCESS) goto eh_dev_reset_done; - dev_info(&ha->pdev->dev, + ql4_printk(KERN_INFO, ha, "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); @@ -2128,7 +2130,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) return FAILED; } - dev_info(&ha->pdev->dev, + ql4_printk(KERN_INFO, ha, "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); @@ -2150,7 +2152,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS) return_status = SUCCESS; - dev_info(&ha->pdev->dev, "HOST RESET %s.\n", + ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n", return_status == FAILED ? "FAILED" : "SUCCEDED"); return return_status; -- cgit v1.2.3 From bb6f7d5b71356be560ea84dd5a721f083d3a9e8e Mon Sep 17 00:00:00 2001 From: Karen Higgins Date: Sat, 10 Jul 2010 14:51:17 +0530 Subject: [SCSI] qla4xxx: wait for device_ready before device discovery Signed-off-by: Karen Higgins Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 5fc19c44bada..e6b73b9fcc5a 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -991,6 +991,9 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) qla4xxx_flush_AENS(ha); + /* Wait for an AEN */ + qla4xxx_devices_ready(ha); + /* * First perform device discovery for active * fw ddb indexes and build @@ -999,9 +1002,6 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) if ((status = qla4xxx_build_ddb_list(ha)) == QLA_ERROR) return status; - /* Wait for an AEN */ - qla4xxx_devices_ready(ha); - /* * Targets can come online after the inital discovery, so processing * the aens here will catch them. -- cgit v1.2.3 From 3b2bef1fc85f127a99ad6b90a94b033fdc57341c Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Sat, 10 Jul 2010 14:51:30 +0530 Subject: [SCSI] iscsi_transport: added new iscsi_param to display target alias in sysfs Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 3 +++ drivers/scsi/qla4xxx/ql4_os.c | 7 ++++++- drivers/scsi/scsi_transport_iscsi.c | 6 ++++-- include/scsi/iscsi_if.h | 2 ++ 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index e6b73b9fcc5a..266ebd45396d 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -594,6 +594,9 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0], min(sizeof(ddb_entry->iscsi_name), sizeof(fw_ddb_entry->iscsi_name))); + memcpy(&ddb_entry->iscsi_alias[0], &fw_ddb_entry->iscsi_alias[0], + min(sizeof(ddb_entry->iscsi_alias), + sizeof(fw_ddb_entry->iscsi_alias))); memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0], min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr))); diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index daf5a4bf9b0a..821384147a41 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -126,7 +126,8 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { .caps = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD | CAP_DATA_PATH_OFFLOAD, .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | - ISCSI_TARGET_NAME | ISCSI_TPGT, + ISCSI_TARGET_NAME | ISCSI_TPGT | + ISCSI_TARGET_ALIAS, .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | ISCSI_HOST_INITIATOR_NAME, @@ -210,6 +211,10 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess, case ISCSI_PARAM_TPGT: len = sprintf(buf, "%u\n", ddb_entry->tpgt); break; + case ISCSI_PARAM_TARGET_ALIAS: + len = snprintf(buf, PAGE_SIZE - 1, "%s\n", + ddb_entry->iscsi_alias); + break; default: return -ENOSYS; } diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 1e6d4793542c..b9aec304872c 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -31,7 +31,7 @@ #include #include -#define ISCSI_SESSION_ATTRS 22 +#define ISCSI_SESSION_ATTRS 23 #define ISCSI_CONN_ATTRS 13 #define ISCSI_HOST_ATTRS 4 @@ -1763,7 +1763,8 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0); iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0); iscsi_session_attr(tgt_reset_tmo, ISCSI_PARAM_TGT_RESET_TMO, 0); iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0); -iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0) +iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0); +iscsi_session_attr(targetalias, ISCSI_PARAM_TARGET_ALIAS, 0); static ssize_t show_priv_session_state(struct device *dev, struct device_attribute *attr, @@ -2006,6 +2007,7 @@ iscsi_register_transport(struct iscsi_transport *tt) SETUP_SESSION_RD_ATTR(tgt_reset_tmo,ISCSI_TGT_RESET_TMO); SETUP_SESSION_RD_ATTR(ifacename, ISCSI_IFACE_NAME); SETUP_SESSION_RD_ATTR(initiatorname, ISCSI_INITIATOR_NAME); + SETUP_SESSION_RD_ATTR(targetalias, ISCSI_TARGET_ALIAS); SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); SETUP_PRIV_SESSION_RD_ATTR(state); diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 66d377b9c72b..a8631acd37c3 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -313,6 +313,7 @@ enum iscsi_param { ISCSI_PARAM_INITIATOR_NAME, ISCSI_PARAM_TGT_RESET_TMO, + ISCSI_PARAM_TARGET_ALIAS, /* must always be last */ ISCSI_PARAM_MAX, }; @@ -353,6 +354,7 @@ enum iscsi_param { #define ISCSI_ISID (1ULL << ISCSI_PARAM_ISID) #define ISCSI_INITIATOR_NAME (1ULL << ISCSI_PARAM_INITIATOR_NAME) #define ISCSI_TGT_RESET_TMO (1ULL << ISCSI_PARAM_TGT_RESET_TMO) +#define ISCSI_TARGET_ALIAS (1ULL << ISCSI_PARAM_TARGET_ALIAS) /* iSCSI HBA params */ enum iscsi_host_param { -- cgit v1.2.3 From 4b6c83f57874c2ac10b450ba0f57db0a0f22db67 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Sat, 10 Jul 2010 14:51:47 +0530 Subject: [SCSI] qla4xxx: Update driver version to 5.02.00-k2 Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 28a6c494a2e8..c905dbd75331 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k1" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k2" -- cgit v1.2.3 From 660bdddb52843d361e47c30294366ae0deac821b Mon Sep 17 00:00:00 2001 From: Cyril Jayaprakash Date: Mon, 12 Jul 2010 00:42:00 +0530 Subject: [SCSI] pmcraid : Remove unnecessary casts for void * pointers Signed-off-by: Cyril Jayaprakash Acked-by: Anil Ravindranath Signed-off-by: James Bottomley --- drivers/scsi/pmcraid.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 9ebcea3643b2..ecc45c8b4e6b 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3599,8 +3599,7 @@ static int pmcraid_chr_open(struct inode *inode, struct file *filep) */ static int pmcraid_chr_release(struct inode *inode, struct file *filep) { - struct pmcraid_instance *pinstance = - ((struct pmcraid_instance *)filep->private_data); + struct pmcraid_instance *pinstance = filep->private_data; filep->private_data = NULL; fasync_helper(-1, filep, 0, &pinstance->aen_queue); @@ -3619,7 +3618,7 @@ static int pmcraid_chr_fasync(int fd, struct file *filep, int mode) struct pmcraid_instance *pinstance; int rc; - pinstance = (struct pmcraid_instance *)filep->private_data; + pinstance = filep->private_data; mutex_lock(&pinstance->aen_queue_lock); rc = fasync_helper(fd, filep, mode, &pinstance->aen_queue); mutex_unlock(&pinstance->aen_queue_lock); @@ -4110,7 +4109,7 @@ static long pmcraid_chr_ioctl( return retval; } - pinstance = (struct pmcraid_instance *)filep->private_data; + pinstance = filep->private_data; if (!pinstance) { pmcraid_info("adapter instance is not found\n"); -- cgit v1.2.3 From 48813cf989eb8695fe84df30207fc8ff5f15783c Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Wed, 14 Jul 2010 13:12:57 +0300 Subject: [SCSI] aic7xxx: Remove OS utility wrappers This patch removes malloc(), free(), and printf() wrappers from the aic7xxx SCSI driver. I didn't use pr_debug for printf because of some 'clever' uses of printf don't compile with the pr_debug. I didn't fix the overeager uses of GFP_ATOMIC either because I wanted to keep this patch as simple as possible. [jejb:fixed up checkpatch errors and fixed up missed conversion] Signed-off-by: Pekka Enberg Acked-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7770.c | 12 +- drivers/scsi/aic7xxx/aic7770_osm.c | 2 +- drivers/scsi/aic7xxx/aic79xx_core.c | 624 ++++++++++++++++----------------- drivers/scsi/aic7xxx/aic79xx_osm.c | 108 +++--- drivers/scsi/aic7xxx/aic79xx_osm.h | 7 - drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 8 +- drivers/scsi/aic7xxx/aic79xx_pci.c | 56 +-- drivers/scsi/aic7xxx/aic79xx_proc.c | 13 +- drivers/scsi/aic7xxx/aic7xxx_93cx6.c | 10 +- drivers/scsi/aic7xxx/aic7xxx_core.c | 430 +++++++++++------------ drivers/scsi/aic7xxx/aic7xxx_osm.c | 76 ++-- drivers/scsi/aic7xxx/aic7xxx_osm.h | 7 - drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 8 +- drivers/scsi/aic7xxx/aic7xxx_pci.c | 74 ++-- drivers/scsi/aic7xxx/aic7xxx_proc.c | 15 +- 15 files changed, 712 insertions(+), 738 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c index 6d86a9be538f..5000bd69c13f 100644 --- a/drivers/scsi/aic7xxx/aic7770.c +++ b/drivers/scsi/aic7xxx/aic7770.c @@ -170,7 +170,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) case 15: break; default: - printf("aic7770_config: invalid irq setting %d\n", intdef); + printk("aic7770_config: invalid irq setting %d\n", intdef); return (ENXIO); } @@ -221,7 +221,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) break; } if (have_seeprom == 0) { - free(ahc->seep_config, M_DEVBUF); + kfree(ahc->seep_config); ahc->seep_config = NULL; } @@ -293,7 +293,7 @@ aha2840_load_seeprom(struct ahc_softc *ahc) sc = ahc->seep_config; if (bootverbose) - printf("%s: Reading SEEPROM...", ahc_name(ahc)); + printk("%s: Reading SEEPROM...", ahc_name(ahc)); have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, /*start_addr*/0, sizeof(*sc)/2); @@ -301,16 +301,16 @@ aha2840_load_seeprom(struct ahc_softc *ahc) if (ahc_verify_cksum(sc) == 0) { if(bootverbose) - printf ("checksum error\n"); + printk ("checksum error\n"); have_seeprom = 0; } else if (bootverbose) { - printf("done.\n"); + printk("done.\n"); } } if (!have_seeprom) { if (bootverbose) - printf("%s: No SEEPROM available\n", ahc_name(ahc)); + printk("%s: No SEEPROM available\n", ahc_name(ahc)); ahc->flags |= AHC_USEDEFAULTS; } else { /* diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index f220e5e436ab..0cb8ef64b5ce 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c @@ -85,7 +85,7 @@ aic7770_probe(struct device *dev) int error; sprintf(buf, "ahc_eisa:%d", eisaBase >> 12); - name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); + name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); if (name == NULL) return (ENOMEM); strcpy(name, buf); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 78971db5b60e..3233bf564435 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -289,7 +289,7 @@ ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) || ahd->dst_mode == AHD_MODE_UNKNOWN) panic("Setting mode prior to saving it.\n"); if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) - printf("%s: Setting mode 0x%x\n", ahd_name(ahd), + printk("%s: Setting mode 0x%x\n", ahd_name(ahd), ahd_build_mode_state(ahd, src, dst)); #endif ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst)); @@ -307,7 +307,7 @@ ahd_update_modes(struct ahd_softc *ahd) mode_ptr = ahd_inb(ahd, MODE_PTR); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) - printf("Reading mode 0x%x\n", mode_ptr); + printk("Reading mode 0x%x\n", mode_ptr); #endif ahd_extract_mode_state(ahd, mode_ptr, &src, &dst); ahd_known_modes(ahd, src, dst); @@ -877,7 +877,7 @@ ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) uint64_t host_dataptr; host_dataptr = ahd_le64toh(scb->hscb->dataptr); - printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n", + printk("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n", ahd_name(ahd), SCB_GET_TAG(scb), scb->hscb->scsiid, ahd_le32toh(scb->hscb->hscb_busaddr), @@ -1174,7 +1174,7 @@ ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_FIFOS) != 0) - printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo); + printk("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo); #endif saved_modes = ahd_save_modes(ahd); ahd_set_modes(ahd, fifo, fifo); @@ -1215,7 +1215,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) scbid = ahd_inw(ahd, GSFIFO); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - GSFIFO SCB %d invalid\n", + printk("%s: Warning - GSFIFO SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -1339,7 +1339,7 @@ rescan_fifos: next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - DMA-up and complete " + printk("%s: Warning - DMA-up and complete " "SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -1360,7 +1360,7 @@ rescan_fifos: next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - Complete Qfrz SCB %d invalid\n", + printk("%s: Warning - Complete Qfrz SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -1377,7 +1377,7 @@ rescan_fifos: next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - Complete SCB %d invalid\n", + printk("%s: Warning - Complete SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -1682,7 +1682,7 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) scb_index = ahd_le16toh(completion->tag); scb = ahd_lookup_scb(ahd, scb_index); if (scb == NULL) { - printf("%s: WARNING no command for scb %d " + printk("%s: WARNING no command for scb %d " "(cmdcmplt)\nQOUTPOS = %d\n", ahd_name(ahd), scb_index, ahd->qoutfifonext); @@ -1714,7 +1714,7 @@ ahd_handle_hwerrint(struct ahd_softc *ahd) error = ahd_inb(ahd, ERROR); for (i = 0; i < num_errors; i++) { if ((error & ahd_hard_errors[i].errno) != 0) - printf("%s: hwerrint, %s\n", + printk("%s: hwerrint, %s\n", ahd_name(ahd), ahd_hard_errors[i].errmesg); } @@ -1747,7 +1747,7 @@ ahd_dump_sglist(struct scb *scb) addr = ahd_le64toh(sg_list[i].addr); len = ahd_le32toh(sg_list[i].len); - printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", + printk("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, (uint32_t)((addr >> 32) & 0xFFFFFFFF), (uint32_t)(addr & 0xFFFFFFFF), @@ -1763,7 +1763,7 @@ ahd_dump_sglist(struct scb *scb) uint32_t len; len = ahd_le32toh(sg_list[i].len); - printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", + printk("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, (len & AHD_SG_HIGH_ADDR_MASK) >> 24, ahd_le32toh(sg_list[i].addr), @@ -1802,7 +1802,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_update_modes(ahd); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: Handle Seqint Called for code %d\n", + printk("%s: Handle Seqint Called for code %d\n", ahd_name(ahd), seqintcode); #endif switch (seqintcode) { @@ -1836,18 +1836,18 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) - printf("%s: Assuming LQIPHASE_NLQ with " + printk("%s: Assuming LQIPHASE_NLQ with " "P0 assertion\n", ahd_name(ahd)); #endif } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) - printf("%s: Entering NONPACK\n", ahd_name(ahd)); + printk("%s: Entering NONPACK\n", ahd_name(ahd)); #endif break; } case INVALID_SEQINT: - printf("%s: Invalid Sequencer interrupt occurred, " + printk("%s: Invalid Sequencer interrupt occurred, " "resetting channel.\n", ahd_name(ahd)); #ifdef AHD_DEBUG @@ -1866,8 +1866,8 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) if (scb != NULL) ahd_print_path(ahd, scb); else - printf("%s: ", ahd_name(ahd)); - printf("SCB %d Packetized Status Overrun", scbid); + printk("%s: ", ahd_name(ahd)); + printk("SCB %d Packetized Status Overrun", scbid); ahd_dump_card_state(ahd); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); break; @@ -1881,7 +1881,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { ahd_dump_card_state(ahd); - printf("CFG4ISTAT: Free SCB %d referenced", scbid); + printk("CFG4ISTAT: Free SCB %d referenced", scbid); panic("For safety"); } ahd_outq(ahd, HADDR, scb->sense_busaddr); @@ -1896,7 +1896,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) u_int bus_phase; bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK; - printf("%s: ILLEGAL_PHASE 0x%x\n", + printk("%s: ILLEGAL_PHASE 0x%x\n", ahd_name(ahd), bus_phase); switch (bus_phase) { @@ -1908,7 +1908,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) case P_STATUS: case P_MESGIN: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - printf("%s: Issued Bus Reset.\n", ahd_name(ahd)); + printk("%s: Issued Bus Reset.\n", ahd_name(ahd)); break; case P_COMMAND: { @@ -1933,7 +1933,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) scbid = ahd_get_scbptr(ahd); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("Invalid phase with no valid SCB. " + printk("Invalid phase with no valid SCB. " "Resetting bus.\n"); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); @@ -1997,7 +1997,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { ahd_print_path(ahd, scb); - printf("Unexpected command phase from " + printk("Unexpected command phase from " "packetized target\n"); } #endif @@ -2013,7 +2013,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { - printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd), + printk("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd), ahd_inb(ahd, MODE_PTR)); } #endif @@ -2049,7 +2049,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { - printf("%s: PDATA_REINIT - DFCNTRL = 0x%x " + printk("%s: PDATA_REINIT - DFCNTRL = 0x%x " "SG_CACHE_SHADOW = 0x%x\n", ahd_name(ahd), ahd_inb(ahd, DFCNTRL), ahd_inb(ahd, SG_CACHE_SHADOW)); @@ -2082,7 +2082,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK; if (bus_phase != P_MESGIN && bus_phase != P_MESGOUT) { - printf("ahd_intr: HOST_MSG_LOOP bad " + printk("ahd_intr: HOST_MSG_LOOP bad " "phase 0x%x\n", bus_phase); /* * Probably transitioned to bus free before @@ -2131,29 +2131,29 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); - printf("%s:%c:%d: no active SCB for reconnecting " + printk("%s:%c:%d: no active SCB for reconnecting " "target - issuing BUS DEVICE RESET\n", ahd_name(ahd), 'A', ahd_inb(ahd, SELID) >> 4); - printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " + printk("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " "REG0 == 0x%x ACCUM = 0x%x\n", ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN), ahd_inw(ahd, REG0), ahd_inb(ahd, ACCUM)); - printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " + printk("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " "SINDEX == 0x%x\n", ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd), ahd_find_busy_tcl(ahd, BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN))), ahd_inw(ahd, SINDEX)); - printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " + printk("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " "SCB_CONTROL == 0x%x\n", ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID), ahd_inb_scbram(ahd, SCB_LUN), ahd_inb_scbram(ahd, SCB_CONTROL)); - printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n", + printk("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n", ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI)); - printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0)); - printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0)); + printk("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0)); + printk("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0)); ahd_dump_card_state(ahd); ahd->msgout_buf[0] = MSG_BUS_DEV_RESET; ahd->msgout_len = 1; @@ -2181,7 +2181,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) u_int lastphase; lastphase = ahd_inb(ahd, LASTPHASE); - printf("%s:%c:%d: unknown scsi bus phase %x, " + printk("%s:%c:%d: unknown scsi bus phase %x, " "lastphase = 0x%x. Attempting to continue\n", ahd_name(ahd), 'A', SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)), @@ -2193,7 +2193,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) u_int lastphase; lastphase = ahd_inb(ahd, LASTPHASE); - printf("%s:%c:%d: Missed busfree. " + printk("%s:%c:%d: Missed busfree. " "Lastphase = 0x%x, Curphase = 0x%x\n", ahd_name(ahd), 'A', SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)), @@ -2223,11 +2223,11 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) lastphase = ahd_inb(ahd, LASTPHASE); if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { ahd_print_path(ahd, scb); - printf("data overrun detected %s. Tag == 0x%x.\n", + printk("data overrun detected %s. Tag == 0x%x.\n", ahd_lookup_phase_entry(lastphase)->phasemsg, SCB_GET_TAG(scb)); ahd_print_path(ahd, scb); - printf("%s seen Data Phase. Length = %ld. " + printk("%s seen Data Phase. Length = %ld. " "NumSGs = %d.\n", ahd_inb(ahd, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", @@ -2252,7 +2252,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) u_int scbid; ahd_fetch_devinfo(ahd, &devinfo); - printf("%s:%c:%d:%d: Attempt to issue message failed\n", + printk("%s:%c:%d:%d: Attempt to issue message failed\n", ahd_name(ahd), devinfo.channel, devinfo.target, devinfo.lun); scbid = ahd_get_scbptr(ahd); @@ -2285,7 +2285,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) cam_status error; ahd_print_path(ahd, scb); - printf("Task Management Func 0x%x Complete\n", + printk("Task Management Func 0x%x Complete\n", scb->hscb->task_management); lun = CAM_LUN_WILDCARD; tag = SCB_LIST_NULL; @@ -2341,7 +2341,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) * the QINFIFO if it is still there. */ ahd_print_path(ahd, scb); - printf("SCB completes before TMF\n"); + printk("SCB completes before TMF\n"); /* * Handle losing the race. Wait until any * current selection completes. We will then @@ -2366,7 +2366,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) case TRACEPOINT1: case TRACEPOINT2: case TRACEPOINT3: - printf("%s: Tracepoint %d\n", ahd_name(ahd), + printk("%s: Tracepoint %d\n", ahd_name(ahd), seqintcode - TRACEPOINT0); break; case NO_SEQINT: @@ -2375,7 +2375,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_handle_hwerrint(ahd); break; default: - printf("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd), + printk("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd), seqintcode); break; } @@ -2440,7 +2440,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) u_int now_lvd; now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40; - printf("%s: Transceiver State Has Changed to %s mode\n", + printk("%s: Transceiver State Has Changed to %s mode\n", ahd_name(ahd), now_lvd ? "LVD" : "SE"); ahd_outb(ahd, CLRSINT0, CLRIOERR); /* @@ -2452,12 +2452,12 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ahd_unpause(ahd); } else if ((status0 & OVERRUN) != 0) { - printf("%s: SCSI offset overrun detected. Resetting bus.\n", + printk("%s: SCSI offset overrun detected. Resetting bus.\n", ahd_name(ahd)); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); } else if ((status & SCSIRSTI) != 0) { - printf("%s: Someone reset channel A\n", ahd_name(ahd)); + printk("%s: Someone reset channel A\n", ahd_name(ahd)); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE); } else if ((status & SCSIPERR) != 0) { @@ -2467,7 +2467,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ahd_handle_transmission_error(ahd); } else if (lqostat0 != 0) { - printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); + printk("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); ahd_outb(ahd, CLRLQOINT0, lqostat0); if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) ahd_outb(ahd, CLRLQOINT1, 0); @@ -2497,7 +2497,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) scbid = ahd_inw(ahd, WAITING_TID_HEAD); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: ahd_intr - referenced scb not " + printk("%s: ahd_intr - referenced scb not " "valid during SELTO scb(0x%x)\n", ahd_name(ahd), scbid); ahd_dump_card_state(ahd); @@ -2506,7 +2506,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SELTO) != 0) { ahd_print_path(ahd, scb); - printf("Saw Selection Timeout for SCB 0x%x\n", + printk("Saw Selection Timeout for SCB 0x%x\n", scbid); } #endif @@ -2534,7 +2534,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ahd_iocell_first_selection(ahd); ahd_unpause(ahd); } else if (status3 != 0) { - printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n", + printk("%s: SCSI Cell parity error SSTAT3 == 0x%x\n", ahd_name(ahd), status3); ahd_outb(ahd, CLRSINT3, status3); } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) { @@ -2587,7 +2587,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) scbid = ahd_get_scbptr(ahd); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Invalid SCB %d in DFF%d " + printk("%s: Invalid SCB %d in DFF%d " "during unexpected busfree\n", ahd_name(ahd), scbid, mode); packetized = 0; @@ -2620,7 +2620,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("Saw Busfree. Busfreetime = 0x%x.\n", + printk("Saw Busfree. Busfreetime = 0x%x.\n", busfreetime); #endif /* @@ -2661,7 +2661,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ahd_unpause(ahd); } } else { - printf("%s: Missing case in ahd_handle_scsiint. status = %x\n", + printk("%s: Missing case in ahd_handle_scsiint. status = %x\n", ahd_name(ahd), status); ahd_dump_card_state(ahd); ahd_clear_intstat(ahd); @@ -2697,7 +2697,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) || (lqistate == 0x29)) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { - printf("%s: NLQCRC found via LQISTATE\n", + printk("%s: NLQCRC found via LQISTATE\n", ahd_name(ahd)); } #endif @@ -2729,18 +2729,18 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) cur_col = 0; if (silent == FALSE) { - printf("%s: Transmission error detected\n", ahd_name(ahd)); + printk("%s: Transmission error detected\n", ahd_name(ahd)); ahd_lqistat1_print(lqistat1, &cur_col, 50); ahd_lastphase_print(lastphase, &cur_col, 50); ahd_scsisigi_print(curphase, &cur_col, 50); ahd_perrdiag_print(perrdiag, &cur_col, 50); - printf("\n"); + printk("\n"); ahd_dump_card_state(ahd); } if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) { if (silent == FALSE) { - printf("%s: Gross protocol error during incoming " + printk("%s: Gross protocol error during incoming " "packet. lqistat1 == 0x%x. Resetting bus.\n", ahd_name(ahd), lqistat1); } @@ -2769,7 +2769,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) * (SPI4R09 10.7.3.3.3) */ ahd_outb(ahd, LQCTL2, LQIRETRY); - printf("LQIRetry for LQICRCI_LQ to release ACK\n"); + printk("LQIRetry for LQICRCI_LQ to release ACK\n"); } else if ((lqistat1 & LQICRCI_NLQ) != 0) { /* * We detected a CRC error in a NON-LQ packet. @@ -2817,22 +2817,22 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) * Busfree detection is enabled. */ if (silent == FALSE) - printf("LQICRC_NLQ\n"); + printk("LQICRC_NLQ\n"); if (scb == NULL) { - printf("%s: No SCB valid for LQICRC_NLQ. " + printk("%s: No SCB valid for LQICRC_NLQ. " "Resetting bus\n", ahd_name(ahd)); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); return; } } else if ((lqistat1 & LQIBADLQI) != 0) { - printf("Need to handle BADLQI!\n"); + printk("Need to handle BADLQI!\n"); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); return; } else if ((perrdiag & (PARITYERR|PREVPHASE)) == PARITYERR) { if ((curphase & ~P_DATAIN_DT) != 0) { /* Ack the byte. So we can continue. */ if (silent == FALSE) - printf("Acking %s to clear perror\n", + printk("Acking %s to clear perror\n", ahd_lookup_phase_entry(curphase)->phasemsg); ahd_inb(ahd, SCSIDAT); } @@ -2877,10 +2877,10 @@ ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1) if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0 && (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) { if ((lqistat1 & LQIPHASE_LQ) != 0) { - printf("LQIRETRY for LQIPHASE_LQ\n"); + printk("LQIRETRY for LQIPHASE_LQ\n"); ahd_outb(ahd, LQCTL2, LQIRETRY); } else if ((lqistat1 & LQIPHASE_NLQ) != 0) { - printf("LQIRETRY for LQIPHASE_NLQ\n"); + printk("LQIRETRY for LQIPHASE_NLQ\n"); ahd_outb(ahd, LQCTL2, LQIRETRY); } else panic("ahd_handle_lqiphase_error: No phase errors\n"); @@ -2888,7 +2888,7 @@ ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1) ahd_outb(ahd, CLRINT, CLRSCSIINT); ahd_unpause(ahd); } else { - printf("Reseting Channel for LQI Phase error\n"); + printk("Reseting Channel for LQI Phase error\n"); ahd_dump_card_state(ahd); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); } @@ -2976,7 +2976,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) if (scb->crc_retry_count < AHD_MAX_LQ_CRC_ERRORS) { if (SCB_IS_SILENT(scb) == FALSE) { ahd_print_path(ahd, scb); - printf("Probable outgoing LQ CRC error. " + printk("Probable outgoing LQ CRC error. " "Retrying command\n"); } scb->crc_retry_count++; @@ -2998,7 +2998,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) ahd_outb(ahd, CLRSINT1, CLRSCSIPERR|CLRBUSFREE); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MASKED_ERRORS) != 0) - printf("%s: Parity on last REQ detected " + printk("%s: Parity on last REQ detected " "during busfree phase.\n", ahd_name(ahd)); #endif @@ -3012,7 +3012,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) scbid = ahd_get_scbptr(ahd); scb = ahd_lookup_scb(ahd, scbid); ahd_print_path(ahd, scb); - printf("Unexpected PKT busfree condition\n"); + printk("Unexpected PKT busfree condition\n"); ahd_dump_card_state(ahd); ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A', SCB_GET_LUN(scb), SCB_GET_TAG(scb), @@ -3021,7 +3021,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) /* Return restarting the sequencer. */ return (1); } - printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd)); + printk("%s: Unexpected PKT busfree condition\n", ahd_name(ahd)); ahd_dump_card_state(ahd); /* Restart the sequencer. */ return (1); @@ -3076,14 +3076,14 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) if (scb == NULL) { ahd_print_devinfo(ahd, &devinfo); - printf("Abort for unidentified " + printk("Abort for unidentified " "connection completed.\n"); /* restart the sequencer. */ return (1); } sent_msg = ahd->msgout_buf[ahd->msgout_index - 1]; ahd_print_path(ahd, scb); - printf("SCB %d - Abort%s Completed.\n", + printk("SCB %d - Abort%s Completed.\n", SCB_GET_TAG(scb), sent_msg == MSG_ABORT_TAG ? "" : " Tag"); @@ -3109,7 +3109,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) found = ahd_abort_scbs(ahd, target, 'A', saved_lun, tag, ROLE_INITIATOR, CAM_REQ_ABORTED); - printf("found == 0x%x\n", found); + printk("found == 0x%x\n", found); printerror = 0; } else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_BUS_DEV_RESET, TRUE)) { @@ -3147,7 +3147,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("PPR negotiation rejected busfree.\n"); + printk("PPR negotiation rejected busfree.\n"); #endif tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, devinfo.our_scsiid, @@ -3191,7 +3191,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("WDTR negotiation rejected busfree.\n"); + printk("WDTR negotiation rejected busfree.\n"); #endif ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, @@ -3216,7 +3216,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("SDTR negotiation rejected busfree.\n"); + printk("SDTR negotiation rejected busfree.\n"); #endif ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, @@ -3240,7 +3240,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("Expected IDE Busfree\n"); + printk("Expected IDE Busfree\n"); #endif printerror = 0; } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_QASREJ_BUSFREE) @@ -3249,7 +3249,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("Expected QAS Reject Busfree\n"); + printk("Expected QAS Reject Busfree\n"); #endif printerror = 0; } @@ -3275,7 +3275,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) } else { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("PPR Negotiation Busfree.\n"); + printk("PPR Negotiation Busfree.\n"); #endif ahd_done(ahd, scb); } @@ -3302,9 +3302,9 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) * We had not fully identified this connection, * so we cannot abort anything. */ - printf("%s: ", ahd_name(ahd)); + printk("%s: ", ahd_name(ahd)); } - printf("Unexpected busfree %s, %d SCBs aborted, " + printk("Unexpected busfree %s, %d SCBs aborted, " "PRGMCNT == 0x%x\n", ahd_lookup_phase_entry(lastphase)->phasemsg, aborted, @@ -3342,7 +3342,7 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) * to match. */ ahd_print_devinfo(ahd, &devinfo); - printf("Target did not send an IDENTIFY message. " + printk("Target did not send an IDENTIFY message. " "LASTPHASE = 0x%x.\n", lastphase); scb = NULL; } else if (scb == NULL) { @@ -3351,13 +3351,13 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) * transaction. Print an error and reset the bus. */ ahd_print_devinfo(ahd, &devinfo); - printf("No SCB found during protocol violation\n"); + printk("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { ahd_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahd_print_path(ahd, scb); - printf("No or incomplete CDB sent to device.\n"); + printk("No or incomplete CDB sent to device.\n"); } else if ((ahd_inb_scbram(ahd, SCB_CONTROL) & STATUS_RCVD) == 0) { /* @@ -3368,10 +3368,10 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) * message. */ ahd_print_path(ahd, scb); - printf("Completed command without status.\n"); + printk("Completed command without status.\n"); } else { ahd_print_path(ahd, scb); - printf("Unknown protocol violation.\n"); + printk("Unknown protocol violation.\n"); ahd_dump_card_state(ahd); } } @@ -3385,7 +3385,7 @@ proto_violation_reset: * it away with a bus reset. */ found = ahd_reset_channel(ahd, 'A', TRUE); - printf("%s: Issued Channel %c Bus Reset. " + printk("%s: Issued Channel %c Bus Reset. " "%d SCBs aborted\n", ahd_name(ahd), 'A', found); } else { /* @@ -3407,7 +3407,7 @@ proto_violation_reset: ahd_print_path(ahd, scb); scb->flags |= SCB_ABORT; } - printf("Protocol violation %s. Attempting to abort.\n", + printk("Protocol violation %s. Attempting to abort.\n", ahd_lookup_phase_entry(curphase)->phasemsg); } } @@ -3425,7 +3425,7 @@ ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, devinfo); - printf("Forcing renegotiation\n"); + printk("Forcing renegotiation\n"); } #endif targ_info = ahd_fetch_transinfo(ahd, @@ -3486,7 +3486,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) break; if (steps > AHD_MAX_STEPS) { - printf("%s: Infinite loop in critical section\n" + printk("%s: Infinite loop in critical section\n" "%s: First Instruction 0x%x now 0x%x\n", ahd_name(ahd), ahd_name(ahd), first_instr, seqaddr); @@ -3497,7 +3497,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) steps++; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: Single stepping at 0x%x\n", ahd_name(ahd), + printk("%s: Single stepping at 0x%x\n", ahd_name(ahd), seqaddr); #endif if (stepping == FALSE) { @@ -3601,16 +3601,16 @@ ahd_print_scb(struct scb *scb) int i; hscb = scb->hscb; - printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", + printk("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", (void *)scb, hscb->control, hscb->scsiid, hscb->lun, hscb->cdb_len); - printf("Shared Data: "); + printk("Shared Data: "); for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++) - printf("%#02x", hscb->shared_data.idata.cdb[i]); - printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", + printk("%#02x", hscb->shared_data.idata.cdb[i]); + printk(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF), ahd_le32toh(hscb->datacnt), @@ -3637,7 +3637,7 @@ ahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel) && ahd->enabled_targets[scsi_id] != master_tstate) panic("%s: ahd_alloc_tstate - Target already allocated", ahd_name(ahd)); - tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT); + tstate = kmalloc(sizeof(*tstate), GFP_ATOMIC); if (tstate == NULL) return (NULL); @@ -3682,7 +3682,7 @@ ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force) tstate = ahd->enabled_targets[scsi_id]; if (tstate != NULL) - free(tstate, M_DEVBUF); + kfree(tstate); ahd->enabled_targets[scsi_id] = NULL; } #endif @@ -3942,37 +3942,37 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, if (offset != 0) { int options; - printf("%s: target %d synchronous with " + printk("%s: target %d synchronous with " "period = 0x%x, offset = 0x%x", ahd_name(ahd), devinfo->target, period, offset); options = 0; if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) { - printf("(RDSTRM"); + printk("(RDSTRM"); options++; } if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { - printf("%s", options ? "|DT" : "(DT"); + printk("%s", options ? "|DT" : "(DT"); options++; } if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { - printf("%s", options ? "|IU" : "(IU"); + printk("%s", options ? "|IU" : "(IU"); options++; } if ((ppr_options & MSG_EXT_PPR_RTI) != 0) { - printf("%s", options ? "|RTI" : "(RTI"); + printk("%s", options ? "|RTI" : "(RTI"); options++; } if ((ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) { - printf("%s", options ? "|QAS" : "(QAS"); + printk("%s", options ? "|QAS" : "(QAS"); options++; } if (options != 0) - printf(")\n"); + printk(")\n"); else - printf("\n"); + printk("\n"); } else { - printf("%s: target %d using " + printk("%s: target %d using " "asynchronous transfers%s\n", ahd_name(ahd), devinfo->target, (ppr_options & MSG_EXT_PPR_QAS_REQ) != 0 @@ -4000,7 +4000,7 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, devinfo); - printf("Expecting IU Change busfree\n"); + printk("Expecting IU Change busfree\n"); } #endif ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE @@ -4009,7 +4009,7 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, if ((old_ppr & MSG_EXT_PPR_IU_REQ) != 0) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("PPR with IU_REQ outstanding\n"); + printk("PPR with IU_REQ outstanding\n"); #endif ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE; } @@ -4061,7 +4061,7 @@ ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_send_async(ahd, devinfo->channel, devinfo->target, CAM_LUN_WILDCARD, AC_TRANSFER_NEG); if (bootverbose) { - printf("%s: target %d using %dbit transfers\n", + printk("%s: target %d using %dbit transfers\n", ahd_name(ahd), devinfo->target, 8 * (0x01 << width)); } @@ -4337,7 +4337,7 @@ ahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) void ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) { - printf("%s:%c:%d:%d: ", ahd_name(ahd), 'A', + printk("%s:%c:%d:%d: ", ahd_name(ahd), 'A', devinfo->target, devinfo->lun); } @@ -4419,11 +4419,11 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("Setting up for Parity Error delivery\n"); + printk("Setting up for Parity Error delivery\n"); #endif return; } else if (scb == NULL) { - printf("%s: WARNING. No pending message for " + printk("%s: WARNING. No pending message for " "I_T msgin. Issuing NO-OP\n", ahd_name(ahd)); ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP; ahd->msgout_len++; @@ -4454,7 +4454,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd->msgout_buf[ahd->msgout_index++] = MSG_BUS_DEV_RESET; ahd->msgout_len++; ahd_print_path(ahd, scb); - printf("Bus Device Reset Message Sent\n"); + printk("Bus Device Reset Message Sent\n"); /* * Clear our selection hardware in advance of * the busfree. We may have an entry in the waiting @@ -4472,7 +4472,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, } ahd->msgout_len++; ahd_print_path(ahd, scb); - printf("Abort%s Message Sent\n", + printk("Abort%s Message Sent\n", (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : ""); /* * Clear our selection hardware in advance of @@ -4493,9 +4493,9 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, */ ahd_outb(ahd, SCSISEQ0, 0); } else { - printf("ahd_intr: AWAITING_MSG for an SCB that " + printk("ahd_intr: AWAITING_MSG for an SCB that " "does not have a waiting message\n"); - printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, + printk("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, devinfo->target_mask); panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x " "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control, @@ -4577,7 +4577,7 @@ ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) if (bootverbose) { ahd_print_devinfo(ahd, devinfo); - printf("Ensuring async\n"); + printk("Ensuring async\n"); } } /* Target initiated PPR is not allowed in the SCSI spec */ @@ -4624,7 +4624,7 @@ ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd->msgout_buf + ahd->msgout_index, period, offset); ahd->msgout_len += 5; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", + printk("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, period, offset); } @@ -4642,7 +4642,7 @@ ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd->msgout_buf + ahd->msgout_index, bus_width); ahd->msgout_len += 4; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending WDTR %x\n", + printk("(%s:%c:%d:%d): Sending WDTR %x\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, bus_width); } @@ -4671,7 +4671,7 @@ ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, bus_width, ppr_options); ahd->msgout_len += 8; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " + printk("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " "offset %x, ppr_options %x\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, bus_width, period, offset, ppr_options); @@ -4721,7 +4721,7 @@ ahd_handle_message_phase(struct ahd_softc *ahd) bus_phase = ahd_inb(ahd, LASTPHASE); if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0) { - printf("LQIRETRY for LQIPHASE_OUTPKT\n"); + printk("LQIRETRY for LQIPHASE_OUTPKT\n"); ahd_outb(ahd, LQCTL2, LQIRETRY); } reswitch: @@ -4738,14 +4738,14 @@ reswitch: #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, &devinfo); - printf("INITIATOR_MSG_OUT"); + printk("INITIATOR_MSG_OUT"); } #endif phasemis = bus_phase != P_MESGOUT; if (phasemis) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { - printf(" PHASEMIS %s\n", + printk(" PHASEMIS %s\n", ahd_lookup_phase_entry(bus_phase) ->phasemsg); } @@ -4772,7 +4772,7 @@ reswitch: ahd_outb(ahd, CLRSINT1, CLRREQINIT); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", ahd->send_msg_perror); + printk(" byte 0x%x\n", ahd->send_msg_perror); #endif /* * If we are notifying the target of a CRC error @@ -4813,7 +4813,7 @@ reswitch: ahd_outb(ahd, CLRSINT1, CLRREQINIT); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", + printk(" byte 0x%x\n", ahd->msgout_buf[ahd->msgout_index]); #endif ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++]); @@ -4828,14 +4828,14 @@ reswitch: #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, &devinfo); - printf("INITIATOR_MSG_IN"); + printk("INITIATOR_MSG_IN"); } #endif phasemis = bus_phase != P_MESGIN; if (phasemis) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { - printf(" PHASEMIS %s\n", + printk(" PHASEMIS %s\n", ahd_lookup_phase_entry(bus_phase) ->phasemsg); } @@ -4856,7 +4856,7 @@ reswitch: ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", + printk(" byte 0x%x\n", ahd->msgin_buf[ahd->msgin_index]); #endif @@ -4878,7 +4878,7 @@ reswitch: #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, &devinfo); - printf("Asserting ATN for response\n"); + printk("Asserting ATN for response\n"); } #endif ahd_assert_atn(ahd); @@ -5026,7 +5026,7 @@ reswitch: if (end_session) { if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) { - printf("%s: Returning to Idle Loop\n", + printk("%s: Returning to Idle Loop\n", ahd_name(ahd)); ahd_clear_msg_state(ahd); @@ -5178,7 +5178,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ahd_validate_offset(ahd, tinfo, period, &offset, tinfo->curr.width, devinfo->role); if (bootverbose) { - printf("(%s:%c:%d:%d): Received " + printk("(%s:%c:%d:%d): Received " "SDTR period %x, offset %x\n\t" "Filtered to period %x, offset %x\n", ahd_name(ahd), devinfo->channel, @@ -5208,7 +5208,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) */ if (bootverbose && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated SDTR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -5250,7 +5250,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ahd_validate_width(ahd, tinfo, &bus_width, devinfo->role); if (bootverbose) { - printf("(%s:%c:%d:%d): Received WDTR " + printk("(%s:%c:%d:%d): Received WDTR " "%x filtered to %x\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, @@ -5266,7 +5266,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) */ if (saved_width > bus_width) { reject = TRUE; - printf("(%s:%c:%d:%d): requested %dBit " + printk("(%s:%c:%d:%d): requested %dBit " "transfers. Rejecting...\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, @@ -5279,7 +5279,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) */ if (bootverbose && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated WDTR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -5391,12 +5391,12 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) } } else { if (devinfo->role != ROLE_TARGET) - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated PPR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); else - printf("(%s:%c:%d:%d): Initiator " + printk("(%s:%c:%d:%d): Initiator " "Initiated PPR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -5408,7 +5408,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) response = TRUE; } if (bootverbose) { - printf("(%s:%c:%d:%d): Received PPR width %x, " + printk("(%s:%c:%d:%d): Received PPR width %x, " "period %x, offset %x,options %x\n" "\tFiltered to width %x, period %x, " "offset %x, options %x\n", @@ -5484,7 +5484,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) case MSG_QAS_REQUEST: #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("%s: QAS request. SCSISIGI == 0x%x\n", + printk("%s: QAS request. SCSISIGI == 0x%x\n", ahd_name(ahd), ahd_inb(ahd, SCSISIGI)); #endif ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE; @@ -5549,7 +5549,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) * off these options. */ if (bootverbose) { - printf("(%s:%c:%d:%d): PPR Rejected. " + printk("(%s:%c:%d:%d): PPR Rejected. " "Trying simple U160 PPR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -5564,7 +5564,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) * Attempt to negotiate SPI-2 style. */ if (bootverbose) { - printf("(%s:%c:%d:%d): PPR Rejected. " + printk("(%s:%c:%d:%d): PPR Rejected. " "Trying WDTR/SDTR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -5581,7 +5581,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) { /* note 8bit xfers */ - printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using " + printk("(%s:%c:%d:%d): refuses WIDE negotiation. Using " "8bit transfers\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, @@ -5609,7 +5609,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) /*offset*/0, /*ppr_options*/0, AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, /*paused*/TRUE); - printf("(%s:%c:%d:%d): refuses synchronous negotiation. " + printk("(%s:%c:%d:%d): refuses synchronous negotiation. " "Using asynchronous transfers\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -5620,13 +5620,13 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) tag_type = (scb->hscb->control & MSG_SIMPLE_TASK); if (tag_type == MSG_SIMPLE_TASK) { - printf("(%s:%c:%d:%d): refuses tagged commands. " + printk("(%s:%c:%d:%d): refuses tagged commands. " "Performing non-tagged I/O\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_NONE); mask = ~0x23; } else { - printf("(%s:%c:%d:%d): refuses %s tagged commands. " + printk("(%s:%c:%d:%d): refuses %s tagged commands. " "Performing simple queue tagged I/O only\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, tag_type == MSG_ORDERED_TASK @@ -5677,7 +5677,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) /* * Otherwise, we ignore it. */ - printf("%s:%c:%d: Message reject for %x -- ignored\n", + printk("%s:%c:%d: Message reject for %x -- ignored\n", ahd_name(ahd), devinfo->channel, devinfo->target, last_msg); } @@ -5864,7 +5864,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) ahd_delay(100); if (wait == 0) { ahd_print_path(ahd, scb); - printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); + printk("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT); } saved_modes = ahd_save_modes(ahd); @@ -5978,7 +5978,7 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, CAM_LUN_WILDCARD, AC_SENT_BDR); if (message != NULL && bootverbose) - printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), + printk("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), message, devinfo->channel, devinfo->target, found); } @@ -6074,23 +6074,22 @@ ahd_alloc(void *platform_arg, char *name) struct ahd_softc *ahd; #ifndef __FreeBSD__ - ahd = malloc(sizeof(*ahd), M_DEVBUF, M_NOWAIT); + ahd = kmalloc(sizeof(*ahd), GFP_ATOMIC); if (!ahd) { - printf("aic7xxx: cannot malloc softc!\n"); - free(name, M_DEVBUF); + printk("aic7xxx: cannot malloc softc!\n"); + kfree(name); return NULL; } #else ahd = device_get_softc((device_t)platform_arg); #endif memset(ahd, 0, sizeof(*ahd)); - ahd->seep_config = malloc(sizeof(*ahd->seep_config), - M_DEVBUF, M_NOWAIT); + ahd->seep_config = kmalloc(sizeof(*ahd->seep_config), GFP_ATOMIC); if (ahd->seep_config == NULL) { #ifndef __FreeBSD__ - free(ahd, M_DEVBUF); + kfree(ahd); #endif - free(name, M_DEVBUF); + kfree(name); return (NULL); } LIST_INIT(&ahd->pending_scbs); @@ -6120,7 +6119,7 @@ ahd_alloc(void *platform_arg, char *name) } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MEMORY) != 0) { - printf("%s: scb size = 0x%x, hscb size = 0x%x\n", + printk("%s: scb size = 0x%x, hscb size = 0x%x\n", ahd_name(ahd), (u_int)sizeof(struct scb), (u_int)sizeof(struct hardware_scb)); } @@ -6147,7 +6146,7 @@ void ahd_set_name(struct ahd_softc *ahd, char *name) { if (ahd->name != NULL) - free(ahd->name, M_DEVBUF); + kfree(ahd->name); ahd->name = name; } @@ -6201,27 +6200,27 @@ ahd_free(struct ahd_softc *ahd) lstate = tstate->enabled_luns[j]; if (lstate != NULL) { xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); + kfree(lstate); } } #endif - free(tstate, M_DEVBUF); + kfree(tstate); } } #ifdef AHD_TARGET_MODE if (ahd->black_hole != NULL) { xpt_free_path(ahd->black_hole->path); - free(ahd->black_hole, M_DEVBUF); + kfree(ahd->black_hole); } #endif if (ahd->name != NULL) - free(ahd->name, M_DEVBUF); + kfree(ahd->name); if (ahd->seep_config != NULL) - free(ahd->seep_config, M_DEVBUF); + kfree(ahd->seep_config); if (ahd->saved_stack != NULL) - free(ahd->saved_stack, M_DEVBUF); + kfree(ahd->saved_stack); #ifndef __FreeBSD__ - free(ahd, M_DEVBUF); + kfree(ahd); #endif return; } @@ -6300,7 +6299,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit) } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK)); if (wait == 0) { - printf("%s: WARNING - Failed chip reset! " + printk("%s: WARNING - Failed chip reset! " "Trying to initialize anyway.\n", ahd_name(ahd)); } ahd_outb(ahd, HCNTRL, ahd->pause); @@ -6422,7 +6421,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) /* Determine the number of hardware SCBs and initialize them */ scb_data->maxhscbs = ahd_probe_scbs(ahd); if (scb_data->maxhscbs == 0) { - printf("%s: No SCB space found\n", ahd_name(ahd)); + printk("%s: No SCB space found\n", ahd_name(ahd)); return (ENXIO); } @@ -6465,7 +6464,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MEMORY) != 0) - printf("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd), + printk("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd), ahd_sglist_allocsize(ahd)); #endif @@ -6489,7 +6488,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) ahd_alloc_scbs(ahd); if (scb_data->numscbs == 0) { - printf("%s: ahd_init_scbdata - " + printk("%s: ahd_init_scbdata - " "Unable to allocate initial scbs\n", ahd_name(ahd)); goto error_exit; @@ -6564,7 +6563,7 @@ ahd_fini_scbdata(struct ahd_softc *ahd) sns_map->dmamap); ahd_dmamem_free(ahd, scb_data->sense_dmat, sns_map->vaddr, sns_map->dmamap); - free(sns_map, M_DEVBUF); + kfree(sns_map); } ahd_dma_tag_destroy(ahd, scb_data->sense_dmat); /* FALLTHROUGH */ @@ -6579,7 +6578,7 @@ ahd_fini_scbdata(struct ahd_softc *ahd) sg_map->dmamap); ahd_dmamem_free(ahd, scb_data->sg_dmat, sg_map->vaddr, sg_map->dmamap); - free(sg_map, M_DEVBUF); + kfree(sg_map); } ahd_dma_tag_destroy(ahd, scb_data->sg_dmat); /* FALLTHROUGH */ @@ -6594,7 +6593,7 @@ ahd_fini_scbdata(struct ahd_softc *ahd) hscb_map->dmamap); ahd_dmamem_free(ahd, scb_data->hscb_dmat, hscb_map->vaddr, hscb_map->dmamap); - free(hscb_map, M_DEVBUF); + kfree(hscb_map); } ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat); /* FALLTHROUGH */ @@ -6624,7 +6623,7 @@ ahd_setup_iocell_workaround(struct ahd_softc *ahd) ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI)); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: Setting up iocell workaround\n", ahd_name(ahd)); + printk("%s: Setting up iocell workaround\n", ahd_name(ahd)); #endif ahd_restore_modes(ahd, saved_modes); ahd->flags &= ~AHD_HAD_FIRST_SEL; @@ -6644,14 +6643,14 @@ ahd_iocell_first_selection(struct ahd_softc *ahd) ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: iocell first selection\n", ahd_name(ahd)); + printk("%s: iocell first selection\n", ahd_name(ahd)); #endif if ((sblkctl & ENAB40) != 0) { ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: BYPASS now disabled\n", ahd_name(ahd)); + printk("%s: BYPASS now disabled\n", ahd_name(ahd)); #endif } ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI)); @@ -6833,7 +6832,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset]; hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb)); } else { - hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT); + hscb_map = kmalloc(sizeof(*hscb_map), GFP_ATOMIC); if (hscb_map == NULL) return; @@ -6842,7 +6841,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat, (void **)&hscb_map->vaddr, BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) { - free(hscb_map, M_DEVBUF); + kfree(hscb_map); return; } @@ -6866,7 +6865,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) segs = sg_map->vaddr + offset; sg_busaddr = sg_map->physaddr + offset; } else { - sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); + sg_map = kmalloc(sizeof(*sg_map), GFP_ATOMIC); if (sg_map == NULL) return; @@ -6875,7 +6874,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat, (void **)&sg_map->vaddr, BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) { - free(sg_map, M_DEVBUF); + kfree(sg_map); return; } @@ -6891,7 +6890,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd); #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_MEMORY) - printf("Mapped SG data\n"); + printk("Mapped SG data\n"); #endif } @@ -6903,7 +6902,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) sense_data = sense_map->vaddr + offset; sense_busaddr = sense_map->physaddr + offset; } else { - sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT); + sense_map = kmalloc(sizeof(*sense_map), GFP_ATOMIC); if (sense_map == NULL) return; @@ -6912,7 +6911,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat, (void **)&sense_map->vaddr, BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) { - free(sense_map, M_DEVBUF); + kfree(sense_map); return; } @@ -6927,7 +6926,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE; #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_MEMORY) - printf("Mapped sense data\n"); + printk("Mapped sense data\n"); #endif } @@ -6941,15 +6940,13 @@ ahd_alloc_scbs(struct ahd_softc *ahd) int error; #endif - next_scb = (struct scb *)malloc(sizeof(*next_scb), - M_DEVBUF, M_NOWAIT); + next_scb = kmalloc(sizeof(*next_scb), GFP_ATOMIC); if (next_scb == NULL) break; - pdata = (struct scb_platform_data *)malloc(sizeof(*pdata), - M_DEVBUF, M_NOWAIT); + pdata = kmalloc(sizeof(*pdata), GFP_ATOMIC); if (pdata == NULL) { - free(next_scb, M_DEVBUF); + kfree(next_scb); break; } next_scb->platform_data = pdata; @@ -6979,8 +6976,8 @@ ahd_alloc_scbs(struct ahd_softc *ahd) error = ahd_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, &next_scb->dmamap); if (error != 0) { - free(next_scb, M_DEVBUF); - free(pdata, M_DEVBUF); + kfree(next_scb); + kfree(pdata); break; } #endif @@ -7077,8 +7074,7 @@ ahd_init(struct ahd_softc *ahd) AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); ahd->stack_size = ahd_probe_stack_size(ahd); - ahd->saved_stack = malloc(ahd->stack_size * sizeof(uint16_t), - M_DEVBUF, M_NOWAIT); + ahd->saved_stack = kmalloc(ahd->stack_size * sizeof(uint16_t), GFP_ATOMIC); if (ahd->saved_stack == NULL) return (ENOMEM); @@ -7224,20 +7220,20 @@ ahd_init(struct ahd_softc *ahd) error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, CURSENSE_ENB); if (error != 0) { - printf("%s: current sensing timeout 1\n", ahd_name(ahd)); + printk("%s: current sensing timeout 1\n", ahd_name(ahd)); goto init_done; } for (i = 20, fstat = FLX_FSTAT_BUSY; (fstat & FLX_FSTAT_BUSY) != 0 && i; i--) { error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT, &fstat); if (error != 0) { - printf("%s: current sensing timeout 2\n", + printk("%s: current sensing timeout 2\n", ahd_name(ahd)); goto init_done; } } if (i == 0) { - printf("%s: Timedout during current-sensing test\n", + printk("%s: Timedout during current-sensing test\n", ahd_name(ahd)); goto init_done; } @@ -7245,7 +7241,7 @@ ahd_init(struct ahd_softc *ahd) /* Latch Current Sensing status. */ error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT, ¤t_sensing); if (error != 0) { - printf("%s: current sensing timeout 3\n", ahd_name(ahd)); + printk("%s: current sensing timeout 3\n", ahd_name(ahd)); goto init_done; } @@ -7254,7 +7250,7 @@ ahd_init(struct ahd_softc *ahd) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) { - printf("%s: current_sensing == 0x%x\n", + printk("%s: current_sensing == 0x%x\n", ahd_name(ahd), current_sensing); } #endif @@ -7271,13 +7267,13 @@ ahd_init(struct ahd_softc *ahd) case FLX_CSTAT_OKAY: if (warn_user == 0 && bootverbose == 0) break; - printf("%s: %s Channel %s\n", ahd_name(ahd), + printk("%s: %s Channel %s\n", ahd_name(ahd), channel_strings[i], termstat_strings[term_stat]); break; } } if (warn_user) { - printf("%s: WARNING. Termination is not configured correctly.\n" + printk("%s: WARNING. Termination is not configured correctly.\n" "%s: WARNING. SCSI bus operations may FAIL.\n", ahd_name(ahd), ahd_name(ahd)); } @@ -7393,7 +7389,7 @@ ahd_chip_init(struct ahd_softc *ahd) } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd), + printk("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd), WRTBIASCTL_HP_DEFAULT); #endif } @@ -7622,9 +7618,9 @@ ahd_chip_init(struct ahd_softc *ahd) ahd_outb(ahd, NEGCONOPTS, negodat3); negodat3 = ahd_inb(ahd, NEGCONOPTS); if (!(negodat3 & ENSLOWCRC)) - printf("aic79xx: failed to set the SLOWCRC bit\n"); + printk("aic79xx: failed to set the SLOWCRC bit\n"); else - printf("aic79xx: SLOWCRC bit set\n"); + printk("aic79xx: SLOWCRC bit set\n"); } } @@ -7646,7 +7642,7 @@ ahd_default_config(struct ahd_softc *ahd) * data for any target mode initiator. */ if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) { - printf("%s: unable to allocate ahd_tmode_tstate. " + printk("%s: unable to allocate ahd_tmode_tstate. " "Failing attach\n", ahd_name(ahd)); return (ENOMEM); } @@ -7725,7 +7721,7 @@ ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc) * data for any target mode initiator. */ if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) { - printf("%s: unable to allocate ahd_tmode_tstate. " + printk("%s: unable to allocate ahd_tmode_tstate. " "Failing attach\n", ahd_name(ahd)); return (ENOMEM); } @@ -7795,7 +7791,7 @@ ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc) user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width, + printk("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width, user_tinfo->period, user_tinfo->offset, user_tinfo->ppr_options); #endif @@ -7951,7 +7947,7 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)); if (maxloops == 0) { - printf("Infinite interrupt loop, INTSTAT = %x", + printk("Infinite interrupt loop, INTSTAT = %x", ahd_inb(ahd, INTSTAT)); } ahd->qfreeze_cnt++; @@ -8241,7 +8237,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, prev_scb = NULL; if (action == SEARCH_PRINT) { - printf("qinstart = %d qinfifonext = %d\nQINFIFO:", + printk("qinstart = %d qinfifonext = %d\nQINFIFO:", qinstart, ahd->qinfifonext); } @@ -8256,7 +8252,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, while (qinpos != qintail) { scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); if (scb == NULL) { - printf("qinpos = %d, SCB index = %d\n", + printk("qinpos = %d, SCB index = %d\n", qinpos, ahd->qinfifo[qinpos]); panic("Loop 1\n"); } @@ -8269,13 +8265,13 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, switch (action) { case SEARCH_COMPLETE: if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in qinfifo\n"); + printk("Inactive SCB in qinfifo\n"); ahd_done_with_status(ahd, scb, status); /* FALLTHROUGH */ case SEARCH_REMOVE: break; case SEARCH_PRINT: - printf(" 0x%x", ahd->qinfifo[qinpos]); + printk(" 0x%x", ahd->qinfifo[qinpos]); /* FALLTHROUGH */ case SEARCH_COUNT: ahd_qinfifo_requeue(ahd, prev_scb, scb); @@ -8292,7 +8288,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); if (action == SEARCH_PRINT) - printf("\nWAITING_TID_QUEUES:\n"); + printk("\nWAITING_TID_QUEUES:\n"); /* * Search waiting for selection lists. We traverse the @@ -8320,7 +8316,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, panic("TID LIST LOOP"); if (scbid >= ahd->scb_data.numscbs) { - printf("%s: Waiting TID List inconsistency. " + printk("%s: Waiting TID List inconsistency. " "SCB index == 0x%x, yet numscbs == 0x%x.", ahd_name(ahd), scbid, ahd->scb_data.numscbs); ahd_dump_card_state(ahd); @@ -8328,7 +8324,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, } scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: SCB = 0x%x Not Active!\n", + printk("%s: SCB = 0x%x Not Active!\n", ahd_name(ahd), scbid); panic("Waiting TID List traversal\n"); } @@ -8344,7 +8340,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, * We found a list of scbs that needs to be searched. */ if (action == SEARCH_PRINT) - printf(" %d ( ", SCB_GET_TARGET(ahd, scb)); + printk(" %d ( ", SCB_GET_TARGET(ahd, scb)); tid_head = scbid; found += ahd_search_scb_list(ahd, target, channel, lun, tag, role, status, @@ -8365,14 +8361,14 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, switch (action) { case SEARCH_COMPLETE: if ((mk_msg_scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB pending MK_MSG\n"); + printk("Inactive SCB pending MK_MSG\n"); ahd_done_with_status(ahd, mk_msg_scb, status); /* FALLTHROUGH */ case SEARCH_REMOVE: { u_int tail_offset; - printf("Removing MK_MSG scb\n"); + printk("Removing MK_MSG scb\n"); /* * Reset our tail to the tail of the @@ -8390,7 +8386,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, break; } case SEARCH_PRINT: - printf(" 0x%x", SCB_GET_TAG(scb)); + printk(" 0x%x", SCB_GET_TAG(scb)); /* FALLTHROUGH */ case SEARCH_COUNT: break; @@ -8407,7 +8403,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, * queue with a pending MK_MESSAGE scb, we * must queue the MK_MESSAGE scb. */ - printf("Queueing mk_msg_scb\n"); + printk("Queueing mk_msg_scb\n"); tid_head = ahd_inw(ahd, MK_MESSAGE_SCB); seq_flags2 &= ~PENDING_MK_MESSAGE; ahd_outb(ahd, SEQ_FLAGS2, seq_flags2); @@ -8418,7 +8414,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, if (!SCBID_IS_NULL(tid_head)) tid_prev = tid_head; if (action == SEARCH_PRINT) - printf(")\n"); + printk(")\n"); } /* Restore saved state. */ @@ -8446,7 +8442,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, *list_tail = SCB_LIST_NULL; for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) { if (scbid >= ahd->scb_data.numscbs) { - printf("%s:SCB List inconsistency. " + printk("%s:SCB List inconsistency. " "SCB == 0x%x, yet numscbs == 0x%x.", ahd_name(ahd), scbid, ahd->scb_data.numscbs); ahd_dump_card_state(ahd); @@ -8454,7 +8450,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, } scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: SCB = %d Not Active!\n", + printk("%s: SCB = %d Not Active!\n", ahd_name(ahd), scbid); panic("Waiting List traversal\n"); } @@ -8470,7 +8466,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, switch (action) { case SEARCH_COMPLETE: if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in Waiting List\n"); + printk("Inactive SCB in Waiting List\n"); ahd_done_with_status(ahd, scb, status); /* FALLTHROUGH */ case SEARCH_REMOVE: @@ -8480,7 +8476,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, *list_head = next; break; case SEARCH_PRINT: - printf("0x%x ", scbid); + printk("0x%x ", scbid); case SEARCH_COUNT: prev = scbid; break; @@ -8668,7 +8664,7 @@ ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel, if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP) ahd_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB on pending list\n"); + printk("Inactive SCB on pending list\n"); ahd_done(ahd, scbp); found++; } @@ -8725,7 +8721,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) * Check if the last bus reset is cleared */ if (ahd->flags & AHD_BUS_RESET_ACTIVE) { - printf("%s: bus reset still active\n", + printk("%s: bus reset still active\n", ahd_name(ahd)); return 0; } @@ -8900,7 +8896,7 @@ ahd_stat_timer(void *arg) ahd_enable_coalescing(ahd, enint_coal); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_INT_COALESCING) != 0) - printf("%s: Interrupt coalescing " + printk("%s: Interrupt coalescing " "now %sabled. Cmds %d\n", ahd_name(ahd), (enint_coal & ENINT_COALESCE) ? "en" : "dis", @@ -8975,9 +8971,9 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SENSE) != 0) { ahd_print_path(ahd, scb); - printf("SCB 0x%x Received PKT Status of 0x%x\n", + printk("SCB 0x%x Received PKT Status of 0x%x\n", SCB_GET_TAG(scb), siu->status); - printf("\tflags = 0x%x, sense len = 0x%x, " + printk("\tflags = 0x%x, sense len = 0x%x, " "pktfail = 0x%x\n", siu->flags, scsi_4btoul(siu->sense_length), scsi_4btoul(siu->pkt_failures_length)); @@ -8986,27 +8982,27 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) if ((siu->flags & SIU_RSPVALID) != 0) { ahd_print_path(ahd, scb); if (scsi_4btoul(siu->pkt_failures_length) < 4) { - printf("Unable to parse pkt_failures\n"); + printk("Unable to parse pkt_failures\n"); } else { switch (SIU_PKTFAIL_CODE(siu)) { case SIU_PFC_NONE: - printf("No packet failure found\n"); + printk("No packet failure found\n"); break; case SIU_PFC_CIU_FIELDS_INVALID: - printf("Invalid Command IU Field\n"); + printk("Invalid Command IU Field\n"); break; case SIU_PFC_TMF_NOT_SUPPORTED: - printf("TMF not supportd\n"); + printk("TMF not supportd\n"); break; case SIU_PFC_TMF_FAILED: - printf("TMF failed\n"); + printk("TMF failed\n"); break; case SIU_PFC_INVALID_TYPE_CODE: - printf("Invalid L_Q Type code\n"); + printk("Invalid L_Q Type code\n"); break; case SIU_PFC_ILLEGAL_REQUEST: - printf("Illegal request\n"); + printk("Illegal request\n"); default: break; } @@ -9019,7 +9015,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) scb->flags |= SCB_PKT_SENSE; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SENSE) != 0) - printf("Sense data available\n"); + printk("Sense data available\n"); #endif } ahd_done(ahd, scb); @@ -9037,7 +9033,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_SENSE) { ahd_print_path(ahd, scb); - printf("SCB %d: requests Check Status\n", + printk("SCB %d: requests Check Status\n", SCB_GET_TAG(scb)); } #endif @@ -9065,7 +9061,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_SENSE) { ahd_print_path(ahd, scb); - printf("Sending Sense\n"); + printk("Sending Sense\n"); } #endif scb->sg_count = 0; @@ -9117,7 +9113,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) break; } case SCSI_STATUS_OK: - printf("%s: Interrupted for staus of 0???\n", + printk("%s: Interrupted for staus of 0???\n", ahd_name(ahd)); /* FALLTHROUGH */ default: @@ -9192,7 +9188,7 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) return; } else if ((resid_sgptr & SG_OVERRUN_RESID) != 0) { ahd_print_path(ahd, scb); - printf("data overrun detected Tag == 0x%x.\n", + printk("data overrun detected Tag == 0x%x.\n", SCB_GET_TAG(scb)); ahd_freeze_devq(ahd, scb); ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); @@ -9232,7 +9228,7 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { ahd_print_path(ahd, scb); - printf("Handled %sResidual of %d bytes\n", + printk("Handled %sResidual of %d bytes\n", (scb->flags & SCB_SENSE) ? "Sense " : "", resid); } #endif @@ -9272,7 +9268,7 @@ ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate, if (pending == AHD_TMODE_EVENT_BUFFER_SIZE) { xpt_print_path(lstate->path); - printf("immediate event %x:%x lost\n", + printk("immediate event %x:%x lost\n", lstate->event_buffer[lstate->event_r_idx].event_type, lstate->event_buffer[lstate->event_r_idx].event_arg); lstate->event_r_idx++; @@ -9344,7 +9340,7 @@ ahd_dumpseq(struct ahd_softc* ahd) uint8_t ins_bytes[4]; ahd_insb(ahd, SEQRAM, ins_bytes, 4); - printf("0x%08x\n", ins_bytes[0] << 24 + printk("0x%08x\n", ins_bytes[0] << 24 | ins_bytes[1] << 16 | ins_bytes[2] << 8 | ins_bytes[3]); @@ -9372,7 +9368,7 @@ ahd_loadseq(struct ahd_softc *ahd) uint8_t download_consts[DOWNLOAD_CONST_COUNT]; if (bootverbose) - printf("%s: Downloading Sequencer Program...", + printk("%s: Downloading Sequencer Program...", ahd_name(ahd)); #if DOWNLOAD_CONST_COUNT != 8 @@ -9498,7 +9494,7 @@ ahd_loadseq(struct ahd_softc *ahd) if (cs_count != 0) { cs_count *= sizeof(struct cs); - ahd->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT); + ahd->critical_sections = kmalloc(cs_count, GFP_ATOMIC); if (ahd->critical_sections == NULL) panic("ahd_loadseq: Could not malloc"); memcpy(ahd->critical_sections, cs_table, cs_count); @@ -9506,8 +9502,8 @@ ahd_loadseq(struct ahd_softc *ahd) ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE); if (bootverbose) { - printf(" %d instructions downloaded\n", downloaded); - printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", + printk(" %d instructions downloaded\n", downloaded); + printk("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", ahd_name(ahd), ahd->features, ahd->bugs, ahd->flags); } } @@ -9690,12 +9686,12 @@ ahd_print_register(const ahd_reg_parse_entry_t *table, u_int num_entries, u_int printed_mask; if (cur_column != NULL && *cur_column >= wrap_point) { - printf("\n"); + printk("\n"); *cur_column = 0; } - printed = printf("%s[0x%x]", name, value); + printed = printk("%s[0x%x]", name, value); if (table == NULL) { - printed += printf(" "); + printed += printk(" "); *cur_column += printed; return (printed); } @@ -9710,7 +9706,7 @@ ahd_print_register(const ahd_reg_parse_entry_t *table, u_int num_entries, == table[entry].mask)) continue; - printed += printf("%s%s", + printed += printk("%s%s", printed_mask == 0 ? ":(" : "|", table[entry].name); printed_mask |= table[entry].mask; @@ -9721,9 +9717,9 @@ ahd_print_register(const ahd_reg_parse_entry_t *table, u_int num_entries, break; } if (printed_mask != 0) - printed += printf(") "); + printed += printk(") "); else - printed += printf(" "); + printed += printk(" "); if (cur_column != NULL) *cur_column += printed; return (printed); @@ -9749,17 +9745,17 @@ ahd_dump_card_state(struct ahd_softc *ahd) } saved_modes = ahd_save_modes(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" + printk(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", ahd_name(ahd), ahd_inw(ahd, CURADDR), ahd_build_mode_state(ahd, ahd->saved_src_mode, ahd->saved_dst_mode)); if (paused) - printf("Card was paused\n"); + printk("Card was paused\n"); if (ahd_check_cmdcmpltqueues(ahd)) - printf("Completions are pending\n"); + printk("Completions are pending\n"); /* * Mode independent registers. @@ -9801,8 +9797,8 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50); ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50); ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50); - printf("\n"); - printf("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x " + printk("\n"); + printk("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x " "CURRSCB 0x%x NEXTSCB 0x%x\n", ahd->scb_data.numscbs, ahd_inw(ahd, CMDS_PENDING), ahd_inw(ahd, LASTSCB), ahd_inw(ahd, CURRSCB), @@ -9813,12 +9809,12 @@ ahd_dump_card_state(struct ahd_softc *ahd) CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT); saved_scb_index = ahd_get_scbptr(ahd); - printf("Pending list:"); + printk("Pending list:"); i = 0; LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) { if (i++ > AHD_SCB_MAX) break; - cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb), + cur_col = printk("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb), ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT)); ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL), @@ -9826,16 +9822,16 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID), &cur_col, 60); } - printf("\nTotal %d\n", i); + printk("\nTotal %d\n", i); - printf("Kernel Free SCB list: "); + printk("Kernel Free SCB list: "); i = 0; TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) { struct scb *list_scb; list_scb = scb; do { - printf("%d ", SCB_GET_TAG(list_scb)); + printk("%d ", SCB_GET_TAG(list_scb)); list_scb = LIST_NEXT(list_scb, collision_links); } while (list_scb && i++ < AHD_SCB_MAX); } @@ -9843,49 +9839,49 @@ ahd_dump_card_state(struct ahd_softc *ahd) LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) { if (i++ > AHD_SCB_MAX) break; - printf("%d ", SCB_GET_TAG(scb)); + printk("%d ", SCB_GET_TAG(scb)); } - printf("\n"); + printk("\n"); - printf("Sequencer Complete DMA-inprog list: "); + printk("Sequencer Complete DMA-inprog list: "); scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD); i = 0; while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); + printk("%d ", scb_index); scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } - printf("\n"); + printk("\n"); - printf("Sequencer Complete list: "); + printk("Sequencer Complete list: "); scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD); i = 0; while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); + printk("%d ", scb_index); scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } - printf("\n"); + printk("\n"); - printf("Sequencer DMA-Up and Complete list: "); + printk("Sequencer DMA-Up and Complete list: "); scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); i = 0; while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); + printk("%d ", scb_index); scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } - printf("\n"); - printf("Sequencer On QFreeze and Complete list: "); + printk("\n"); + printk("Sequencer On QFreeze and Complete list: "); scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); i = 0; while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); + printk("%d ", scb_index); scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } - printf("\n"); + printk("\n"); ahd_set_scbptr(ahd, saved_scb_index); dffstat = ahd_inb(ahd, DFFSTAT); for (i = 0; i < 2; i++) { @@ -9896,7 +9892,7 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); fifo_scbptr = ahd_get_scbptr(ahd); - printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n", + printk("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n", ahd_name(ahd), i, (dffstat & (FIFO0FREE << i)) ? "Free" : "Active", ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr); @@ -9912,20 +9908,20 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_soffcnt_print(ahd_inb(ahd, SOFFCNT), &cur_col, 50); ahd_mdffstat_print(ahd_inb(ahd, MDFFSTAT), &cur_col, 50); if (cur_col > 50) { - printf("\n"); + printk("\n"); cur_col = 0; } - cur_col += printf("SHADDR = 0x%x%x, SHCNT = 0x%x ", + cur_col += printk("SHADDR = 0x%x%x, SHCNT = 0x%x ", ahd_inl(ahd, SHADDR+4), ahd_inl(ahd, SHADDR), (ahd_inb(ahd, SHCNT) | (ahd_inb(ahd, SHCNT + 1) << 8) | (ahd_inb(ahd, SHCNT + 2) << 16))); if (cur_col > 50) { - printf("\n"); + printk("\n"); cur_col = 0; } - cur_col += printf("HADDR = 0x%x%x, HCNT = 0x%x ", + cur_col += printk("HADDR = 0x%x%x, HCNT = 0x%x ", ahd_inl(ahd, HADDR+4), ahd_inl(ahd, HADDR), (ahd_inb(ahd, HCNT) @@ -9940,52 +9936,52 @@ ahd_dump_card_state(struct ahd_softc *ahd) } #endif } - printf("\nLQIN: "); + printk("\nLQIN: "); for (i = 0; i < 20; i++) - printf("0x%x ", ahd_inb(ahd, LQIN + i)); - printf("\n"); + printk("0x%x ", ahd_inb(ahd, LQIN + i)); + printk("\n"); ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - printf("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n", + printk("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n", ahd_name(ahd), ahd_inb(ahd, LQISTATE), ahd_inb(ahd, LQOSTATE), ahd_inb(ahd, OPTIONMODE)); - printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n", + printk("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n", ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT), ahd_inb(ahd, MAXCMDCNT)); - printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n", + printk("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n", ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN)); ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50); - printf("\n"); + printk("\n"); ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); cur_col = 0; ahd_ccscbctl_print(ahd_inb(ahd, CCSCBCTL), &cur_col, 50); - printf("\n"); + printk("\n"); ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); - printf("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n", + printk("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n", ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX), ahd_inw(ahd, DINDEX)); - printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n", + printk("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n", ahd_name(ahd), ahd_get_scbptr(ahd), ahd_inw_scbram(ahd, SCB_NEXT), ahd_inw_scbram(ahd, SCB_NEXT2)); - printf("CDB %x %x %x %x %x %x\n", + printk("CDB %x %x %x %x %x %x\n", ahd_inb_scbram(ahd, SCB_CDB_STORE), ahd_inb_scbram(ahd, SCB_CDB_STORE+1), ahd_inb_scbram(ahd, SCB_CDB_STORE+2), ahd_inb_scbram(ahd, SCB_CDB_STORE+3), ahd_inb_scbram(ahd, SCB_CDB_STORE+4), ahd_inb_scbram(ahd, SCB_CDB_STORE+5)); - printf("STACK:"); + printk("STACK:"); for (i = 0; i < ahd->stack_size; i++) { ahd->saved_stack[i] = ahd_inb(ahd, STACK)|(ahd_inb(ahd, STACK) << 8); - printf(" 0x%x", ahd->saved_stack[i]); + printk(" 0x%x", ahd->saved_stack[i]); } for (i = ahd->stack_size-1; i >= 0; i--) { ahd_outb(ahd, STACK, ahd->saved_stack[i] & 0xFF); ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF); } - printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); + printk("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); ahd_restore_modes(ahd, saved_modes); if (paused == 0) ahd_unpause(ahd); @@ -10004,8 +10000,8 @@ ahd_dump_scbs(struct ahd_softc *ahd) saved_scb_index = ahd_get_scbptr(ahd); for (i = 0; i < AHD_SCB_MAX; i++) { ahd_set_scbptr(ahd, i); - printf("%3d", i); - printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n", + printk("%3d", i); + printk("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n", ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb_scbram(ahd, SCB_SCSIID), ahd_inw_scbram(ahd, SCB_NEXT), @@ -10013,7 +10009,7 @@ ahd_dump_scbs(struct ahd_softc *ahd) ahd_inl_scbram(ahd, SCB_SGPTR), ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR)); } - printf("\n"); + printk("\n"); ahd_set_scbptr(ahd, saved_scb_index); ahd_restore_modes(ahd, saved_modes); } @@ -10383,7 +10379,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { u_long s; - printf("Configuring Target Mode\n"); + printk("Configuring Target Mode\n"); ahd_lock(ahd, &s); if (LIST_FIRST(&ahd->pending_scbs) != NULL) { ccb->ccb_h.status = CAM_BUSY; @@ -10412,7 +10408,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) /* Are we already enabled?? */ if (lstate != NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Lun already enabled\n"); + printk("Lun already enabled\n"); ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; return; } @@ -10424,7 +10420,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) * specific commands. */ ccb->ccb_h.status = CAM_REQ_INVALID; - printf("Non-zero Group Codes\n"); + printk("Non-zero Group Codes\n"); return; } @@ -10436,15 +10432,15 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) tstate = ahd_alloc_tstate(ahd, target, channel); if (tstate == NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate tstate\n"); + printk("Couldn't allocate tstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } } - lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT); + lstate = kmalloc(sizeof(*lstate), GFP_ATOMIC); if (lstate == NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate lstate\n"); + printk("Couldn't allocate lstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } @@ -10454,9 +10450,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) xpt_path_target_id(ccb->ccb_h.path), xpt_path_lun_id(ccb->ccb_h.path)); if (status != CAM_REQ_CMP) { - free(lstate, M_DEVBUF); + kfree(lstate); xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate path\n"); + printk("Couldn't allocate path\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } @@ -10524,7 +10520,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) ahd_unlock(ahd, &s); ccb->ccb_h.status = CAM_REQ_CMP; xpt_print_path(ccb->ccb_h.path); - printf("Lun now enabled for target mode\n"); + printk("Lun now enabled for target mode\n"); } else { struct scb *scb; int i, empty; @@ -10543,7 +10539,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) ccbh = &scb->io_ctx->ccb_h; if (ccbh->func_code == XPT_CONT_TARGET_IO && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ - printf("CTIO pending\n"); + printk("CTIO pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; ahd_unlock(ahd, &s); return; @@ -10551,12 +10547,12 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) } if (SLIST_FIRST(&lstate->accept_tios) != NULL) { - printf("ATIOs pending\n"); + printk("ATIOs pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; } if (SLIST_FIRST(&lstate->immed_notifies) != NULL) { - printf("INOTs pending\n"); + printk("INOTs pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; } @@ -10566,9 +10562,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) } xpt_print_path(ccb->ccb_h.path); - printf("Target mode disabled\n"); + printk("Target mode disabled\n"); xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); + kfree(lstate); ahd_pause(ahd); /* Can we clean up the target too? */ @@ -10615,7 +10611,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) ahd_outb(ahd, SCSISEQ1, scsiseq1); if ((ahd->features & AHD_MULTIROLE) == 0) { - printf("Configuring Initiator Mode\n"); + printk("Configuring Initiator Mode\n"); ahd->flags &= ~AHD_TARGETROLE; ahd->flags |= AHD_INITIATORROLE; ahd_pause(ahd); @@ -10749,7 +10745,7 @@ ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd) ahd->flags &= ~AHD_TQINFIFO_BLOCKED; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_TQIN) != 0) - printf("Incoming command from %d for %d:%d%s\n", + printk("Incoming command from %d for %d:%d%s\n", initiator, target, lun, lstate == ahd->black_hole ? "(Black Holed)" : ""); #endif @@ -10796,7 +10792,7 @@ ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd) default: /* Only copy the opcode. */ atio->cdb_len = 1; - printf("Reserved or VU command code type encountered\n"); + printk("Reserved or VU command code type encountered\n"); break; } @@ -10813,7 +10809,7 @@ ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_TQIN) != 0) - printf("Received Immediate Command %d:%d:%d - %p\n", + printk("Received Immediate Command %d:%d:%d - %p\n", initiator, target, lun, ahd->pending_device); #endif ahd->pending_device = lstate; diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 4c41332a354b..88ad8482ef59 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -674,7 +674,7 @@ ahd_linux_slave_alloc(struct scsi_device *sdev) struct ahd_linux_device *dev; if (bootverbose) - printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id); + printk("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id); dev = scsi_transport_device_data(sdev); memset(dev, 0, sizeof(*dev)); @@ -798,10 +798,10 @@ ahd_linux_dev_reset(struct scsi_cmnd *cmd) scmd_printk(KERN_INFO, cmd, "Attempting to queue a TARGET RESET message:"); - printf("CDB:"); + printk("CDB:"); for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) - printf(" 0x%x", cmd->cmnd[cdb_byte]); - printf("\n"); + printk(" 0x%x", cmd->cmnd[cdb_byte]); + printk("\n"); /* * Determine if we currently own this command. @@ -857,16 +857,16 @@ ahd_linux_dev_reset(struct scsi_cmnd *cmd) ahd->platform_data->eh_done = &done; ahd_unlock(ahd, &flags); - printf("%s: Device reset code sleeping\n", ahd_name(ahd)); + printk("%s: Device reset code sleeping\n", ahd_name(ahd)); if (!wait_for_completion_timeout(&done, 5 * HZ)) { ahd_lock(ahd, &flags); ahd->platform_data->eh_done = NULL; ahd_unlock(ahd, &flags); - printf("%s: Device reset timer expired (active %d)\n", + printk("%s: Device reset timer expired (active %d)\n", ahd_name(ahd), dev->active); retval = FAILED; } - printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); + printk("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); return (retval); } @@ -884,7 +884,7 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd) ahd = *(struct ahd_softc **)cmd->device->host->hostdata; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) - printf("%s: Bus reset called for cmd %p\n", + printk("%s: Bus reset called for cmd %p\n", ahd_name(ahd), cmd); #endif ahd_lock(ahd, &flags); @@ -894,7 +894,7 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd) ahd_unlock(ahd, &flags); if (bootverbose) - printf("%s: SCSI bus reset delivered. " + printk("%s: SCSI bus reset delivered. " "%d SCBs aborted.\n", ahd_name(ahd), found); return (SUCCESS); @@ -935,7 +935,7 @@ ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, { bus_dma_tag_t dmat; - dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); + dmat = kmalloc(sizeof(*dmat), GFP_ATOMIC); if (dmat == NULL) return (ENOMEM); @@ -956,7 +956,7 @@ ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, void ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat) { - free(dmat, M_DEVBUF); + kfree(dmat); } int @@ -1019,7 +1019,7 @@ ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) iocell_info = (uint8_t*)&aic79xx_iocell_info[instance]; iocell_info[index] = value & 0xFFFF; if (bootverbose) - printf("iocell[%d:%ld] = %d\n", instance, index, value); + printk("iocell[%d:%ld] = %d\n", instance, index, value); } } @@ -1029,7 +1029,7 @@ ahd_linux_setup_tag_info_global(char *p) int tags, i, j; tags = simple_strtoul(p + 1, NULL, 0) & 0xff; - printf("Setting Global Tags= %d\n", tags); + printk("Setting Global Tags= %d\n", tags); for (i = 0; i < ARRAY_SIZE(aic79xx_tag_info); i++) { for (j = 0; j < AHD_NUM_TARGETS; j++) { @@ -1047,7 +1047,7 @@ ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) && (targ < AHD_NUM_TARGETS)) { aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF; if (bootverbose) - printf("tag_info[%d:%d] = %d\n", instance, targ, value); + printk("tag_info[%d:%d] = %d\n", instance, targ, value); } } @@ -1088,7 +1088,7 @@ ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, if (targ == -1) targ = 0; } else { - printf("Malformed Option %s\n", + printk("Malformed Option %s\n", opt_name); done = TRUE; } @@ -1246,7 +1246,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa ahd_set_unit(ahd, ahd_linux_unit++); ahd_unlock(ahd, &s); sprintf(buf, "scsi%d", host->host_no); - new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); + new_name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); if (new_name != NULL) { strcpy(new_name, buf); ahd_set_name(ahd, new_name); @@ -1322,7 +1322,7 @@ int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) { ahd->platform_data = - malloc(sizeof(struct ahd_platform_data), M_DEVBUF, M_NOWAIT); + kmalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC); if (ahd->platform_data == NULL) return (ENOMEM); memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); @@ -1364,7 +1364,7 @@ ahd_platform_free(struct ahd_softc *ahd) if (ahd->platform_data->host) scsi_host_put(ahd->platform_data->host); - free(ahd->platform_data, M_DEVBUF); + kfree(ahd->platform_data); } } @@ -1502,7 +1502,7 @@ ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) if (ahd->unit >= ARRAY_SIZE(aic79xx_tag_info)) { if (warned_user == 0) { - printf(KERN_WARNING + printk(KERN_WARNING "aic79xx: WARNING: Insufficient tag_info instances\n" "aic79xx: for installed controllers. Using defaults\n" "aic79xx: Please update the aic79xx_tag_info array in\n" @@ -1544,7 +1544,7 @@ ahd_linux_device_queue_depth(struct scsi_device *sdev) ahd_send_async(ahd, devinfo.channel, devinfo.target, devinfo.lun, AC_TRANSFER_NEG); ahd_print_devinfo(ahd, &devinfo); - printf("Tagged Queuing enabled. Depth %d\n", tags); + printk("Tagged Queuing enabled. Depth %d\n", tags); } else { ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_NONE); ahd_send_async(ahd, devinfo.channel, devinfo.target, @@ -1794,7 +1794,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) struct ahd_linux_device *dev; if ((scb->flags & SCB_ACTIVE) == 0) { - printf("SCB %d done'd twice\n", SCB_GET_TAG(scb)); + printk("SCB %d done'd twice\n", SCB_GET_TAG(scb)); ahd_dump_card_state(ahd); panic("Stopping for safety"); } @@ -1825,7 +1825,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { ahd_print_path(ahd, scb); - printf("Set CAM_UNCOR_PARITY\n"); + printk("Set CAM_UNCOR_PARITY\n"); } #endif ahd_set_transaction_status(scb, CAM_UNCOR_PARITY); @@ -1843,12 +1843,12 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) u_int i; ahd_print_path(ahd, scb); - printf("CDB:"); + printk("CDB:"); for (i = 0; i < scb->io_ctx->cmd_len; i++) - printf(" 0x%x", scb->io_ctx->cmnd[i]); - printf("\n"); + printk(" 0x%x", scb->io_ctx->cmnd[i]); + printk("\n"); ahd_print_path(ahd, scb); - printf("Saw underflow (%ld of %ld bytes). " + printk("Saw underflow (%ld of %ld bytes). " "Treated as error\n", ahd_get_residual(scb), ahd_get_transfer_length(scb)); @@ -1881,7 +1881,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) dev->commands_since_idle_or_otag = 0; if ((scb->flags & SCB_RECOVERY_SCB) != 0) { - printf("Recovery SCB completes\n"); + printk("Recovery SCB completes\n"); if (ahd_get_transaction_status(scb) == CAM_BDR_SENT || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); @@ -1963,14 +1963,14 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, if (ahd_debug & AHD_SHOW_SENSE) { int i; - printf("Copied %d bytes of sense data at %d:", + printk("Copied %d bytes of sense data at %d:", sense_size, sense_offset); for (i = 0; i < sense_size; i++) { if ((i & 0xF) == 0) - printf("\n"); - printf("0x%x ", cmd->sense_buffer[i]); + printk("\n"); + printk("0x%x ", cmd->sense_buffer[i]); } - printf("\n"); + printk("\n"); } #endif } @@ -1995,7 +1995,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_QFULL) != 0) { ahd_print_path(ahd, scb); - printf("Dropping tag count to %d\n", + printk("Dropping tag count to %d\n", dev->active); } #endif @@ -2014,7 +2014,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, == AHD_LOCK_TAGS_COUNT) { dev->maxtags = dev->active; ahd_print_path(ahd, scb); - printf("Locking max tag count at %d\n", + printk("Locking max tag count at %d\n", dev->active); } } else { @@ -2138,7 +2138,7 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) } if (do_fallback) { - printf("%s: device overrun (status %x) on %d:%d:%d\n", + printk("%s: device overrun (status %x) on %d:%d:%d\n", ahd_name(ahd), status, cmd->device->channel, cmd->device->id, cmd->device->lun); } @@ -2187,10 +2187,10 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) scmd_printk(KERN_INFO, cmd, "Attempting to queue an ABORT message:"); - printf("CDB:"); + printk("CDB:"); for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) - printf(" 0x%x", cmd->cmnd[cdb_byte]); - printf("\n"); + printk(" 0x%x", cmd->cmnd[cdb_byte]); + printk("\n"); ahd_lock(ahd, &flags); @@ -2249,7 +2249,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) goto no_cmd; } - printf("%s: At time of recovery, card was %spaused\n", + printk("%s: At time of recovery, card was %spaused\n", ahd_name(ahd), was_paused ? "" : "not "); ahd_dump_card_state(ahd); @@ -2260,7 +2260,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) pending_scb->hscb->tag, ROLE_INITIATOR, CAM_REQ_ABORTED, SEARCH_COMPLETE) > 0) { - printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", + printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", ahd_name(ahd), cmd->device->channel, cmd->device->id, cmd->device->lun); retval = SUCCESS; @@ -2355,7 +2355,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) ahd_qinfifo_requeue_tail(ahd, pending_scb); ahd_set_scbptr(ahd, saved_scbptr); ahd_print_path(ahd, pending_scb); - printf("Device is disconnected, re-queuing SCB\n"); + printk("Device is disconnected, re-queuing SCB\n"); wait = TRUE; } else { scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n"); @@ -2380,21 +2380,21 @@ done: ahd->platform_data->eh_done = &done; ahd_unlock(ahd, &flags); - printf("%s: Recovery code sleeping\n", ahd_name(ahd)); + printk("%s: Recovery code sleeping\n", ahd_name(ahd)); if (!wait_for_completion_timeout(&done, 5 * HZ)) { ahd_lock(ahd, &flags); ahd->platform_data->eh_done = NULL; ahd_unlock(ahd, &flags); - printf("%s: Timer Expired (active %d)\n", + printk("%s: Timer Expired (active %d)\n", ahd_name(ahd), dev->active); retval = FAILED; } - printf("Recovery code awake\n"); + printk("Recovery code awake\n"); } else ahd_unlock(ahd, &flags); if (retval != SUCCESS) - printf("%s: Command abort returning 0x%x\n", + printk("%s: Command abort returning 0x%x\n", ahd_name(ahd), retval); return retval; @@ -2431,7 +2431,7 @@ static void ahd_linux_set_period(struct scsi_target *starget, int period) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: set period to %d\n", ahd_name(ahd), period); + printk("%s: set period to %d\n", ahd_name(ahd), period); #endif if (offset == 0) offset = MAX_OFFSET; @@ -2484,7 +2484,7 @@ static void ahd_linux_set_offset(struct scsi_target *starget, int offset) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: set offset to %d\n", ahd_name(ahd), offset); + printk("%s: set offset to %d\n", ahd_name(ahd), offset); #endif ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, @@ -2520,7 +2520,7 @@ static void ahd_linux_set_dt(struct scsi_target *starget, int dt) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: %s DT\n", ahd_name(ahd), + printk("%s: %s DT\n", ahd_name(ahd), dt ? "enabling" : "disabling"); #endif if (dt && spi_max_width(starget)) { @@ -2562,7 +2562,7 @@ static void ahd_linux_set_qas(struct scsi_target *starget, int qas) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: %s QAS\n", ahd_name(ahd), + printk("%s: %s QAS\n", ahd_name(ahd), qas ? "enabling" : "disabling"); #endif @@ -2601,7 +2601,7 @@ static void ahd_linux_set_iu(struct scsi_target *starget, int iu) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: %s IU\n", ahd_name(ahd), + printk("%s: %s IU\n", ahd_name(ahd), iu ? "enabling" : "disabling"); #endif @@ -2641,7 +2641,7 @@ static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: %s Read Streaming\n", ahd_name(ahd), + printk("%s: %s Read Streaming\n", ahd_name(ahd), rdstrm ? "enabling" : "disabling"); #endif @@ -2677,7 +2677,7 @@ static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: %s Write Flow Control\n", ahd_name(ahd), + printk("%s: %s Write Flow Control\n", ahd_name(ahd), wrflow ? "enabling" : "disabling"); #endif @@ -2714,14 +2714,14 @@ static void ahd_linux_set_rti(struct scsi_target *starget, int rti) if ((ahd->features & AHD_RTI) == 0) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: RTI not available\n", ahd_name(ahd)); + printk("%s: RTI not available\n", ahd_name(ahd)); #endif return; } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: %s RTI\n", ahd_name(ahd), + printk("%s: %s RTI\n", ahd_name(ahd), rti ? "enabling" : "disabling"); #endif @@ -2757,7 +2757,7 @@ static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_DV) != 0) - printf("%s: %s Precompensation\n", ahd_name(ahd), + printk("%s: %s Precompensation\n", ahd_name(ahd), pcomp ? "Enable" : "Disable"); #endif diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 55c1fe07969f..28e43498cdff 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -363,13 +363,6 @@ struct ahd_platform_data { resource_size_t mem_busaddr; /* Mem Base Addr */ }; -/************************** OS Utility Wrappers *******************************/ -#define printf printk -#define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 -#define malloc(size, type, flags) kmalloc(size, flags) -#define free(ptr, type) kfree(ptr) - void ahd_delay(long); /***************************** Low Level I/O **********************************/ diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 8f686122d54e..3c85873b14b9 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -178,7 +178,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ahd_get_pci_bus(pci), ahd_get_pci_slot(pci), ahd_get_pci_function(pci)); - name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); + name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); if (name == NULL) return (-ENOMEM); strcpy(name, buf); @@ -333,7 +333,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) if (ahd_pci_test_register_access(ahd) != 0) { - printf("aic79xx: PCI Device %d:%d:%d " + printk("aic79xx: PCI Device %d:%d:%d " "failed memory mapped test. Using PIO.\n", ahd_get_pci_bus(ahd->dev_softc), ahd_get_pci_slot(ahd->dev_softc), @@ -346,7 +346,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) } else command |= PCIM_CMD_MEMEN; } else if (bootverbose) { - printf("aic79xx: PCI%d:%d:%d MEM region 0x%llx " + printk("aic79xx: PCI%d:%d:%d MEM region 0x%llx " "unavailable. Cannot memory map device.\n", ahd_get_pci_bus(ahd->dev_softc), ahd_get_pci_slot(ahd->dev_softc), @@ -365,7 +365,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) ahd->bshs[1].ioport = (u_long)base2; command |= PCIM_CMD_PORTEN; } else { - printf("aic79xx: PCI%d:%d:%d IO regions 0x%llx and " + printk("aic79xx: PCI%d:%d:%d IO regions 0x%llx and " "0x%llx unavailable. Cannot map device.\n", ahd_get_pci_bus(ahd->dev_softc), ahd_get_pci_slot(ahd->dev_softc), diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 90a04a37b4f7..14b5f8d0e7f4 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -338,7 +338,7 @@ ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry) */ if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { if (bootverbose) - printf("%s: Enabling 39Bit Addressing\n", + printk("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); @@ -528,7 +528,7 @@ ahd_check_extport(struct ahd_softc *ahd) * Fetch VPD for this function and parse it. */ if (bootverbose) - printf("%s: Reading VPD from SEEPROM...", + printk("%s: Reading VPD from SEEPROM...", ahd_name(ahd)); /* Address is always in units of 16bit words */ @@ -541,12 +541,12 @@ ahd_check_extport(struct ahd_softc *ahd) if (error == 0) error = ahd_parse_vpddata(ahd, &vpd); if (bootverbose) - printf("%s: VPD parsing %s\n", + printk("%s: VPD parsing %s\n", ahd_name(ahd), error == 0 ? "successful" : "failed"); if (bootverbose) - printf("%s: Reading SEEPROM...", ahd_name(ahd)); + printk("%s: Reading SEEPROM...", ahd_name(ahd)); /* Address is always in units of 16bit words */ start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A'); @@ -556,16 +556,16 @@ ahd_check_extport(struct ahd_softc *ahd) /*bytestream*/FALSE); if (error != 0) { - printf("Unable to read SEEPROM\n"); + printk("Unable to read SEEPROM\n"); have_seeprom = 0; } else { have_seeprom = ahd_verify_cksum(sc); if (bootverbose) { if (have_seeprom == 0) - printf ("checksum error\n"); + printk ("checksum error\n"); else - printf ("done.\n"); + printk ("done.\n"); } } ahd_release_seeprom(ahd); @@ -615,21 +615,21 @@ ahd_check_extport(struct ahd_softc *ahd) uint16_t *sc_data; int i; - printf("%s: Seeprom Contents:", ahd_name(ahd)); + printk("%s: Seeprom Contents:", ahd_name(ahd)); sc_data = (uint16_t *)sc; for (i = 0; i < (sizeof(*sc)); i += 2) - printf("\n\t0x%.4x", sc_data[i]); - printf("\n"); + printk("\n\t0x%.4x", sc_data[i]); + printk("\n"); } #endif if (!have_seeprom) { if (bootverbose) - printf("%s: No SEEPROM available.\n", ahd_name(ahd)); + printk("%s: No SEEPROM available.\n", ahd_name(ahd)); ahd->flags |= AHD_USEDEFAULTS; error = ahd_default_config(ahd); adapter_control = CFAUTOTERM|CFSEAUTOTERM; - free(ahd->seep_config, M_DEVBUF); + kfree(ahd->seep_config); ahd->seep_config = NULL; } else { error = ahd_parse_cfgdata(ahd, sc); @@ -656,7 +656,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) if ((ahd->flags & AHD_STPWLEVEL_A) != 0) devconfig |= STPWLEVEL; if (bootverbose) - printf("%s: STPWLEVEL is %s\n", + printk("%s: STPWLEVEL is %s\n", ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off"); ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); @@ -671,7 +671,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl); if ((adapter_control & CFAUTOTERM) == 0) { if (bootverbose) - printf("%s: Manual Primary Termination\n", + printk("%s: Manual Primary Termination\n", ahd_name(ahd)); termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH); if ((adapter_control & CFSTERM) != 0) @@ -679,14 +679,14 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) if ((adapter_control & CFWSTERM) != 0) termctl |= FLX_TERMCTL_ENPRIHIGH; } else if (error != 0) { - printf("%s: Primary Auto-Term Sensing failed! " + printk("%s: Primary Auto-Term Sensing failed! " "Using Defaults.\n", ahd_name(ahd)); termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH; } if ((adapter_control & CFSEAUTOTERM) == 0) { if (bootverbose) - printf("%s: Manual Secondary Termination\n", + printk("%s: Manual Secondary Termination\n", ahd_name(ahd)); termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH); if ((adapter_control & CFSELOWTERM) != 0) @@ -694,7 +694,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) if ((adapter_control & CFSEHIGHTERM) != 0) termctl |= FLX_TERMCTL_ENSECHIGH; } else if (error != 0) { - printf("%s: Secondary Auto-Term Sensing failed! " + printk("%s: Secondary Auto-Term Sensing failed! " "Using Defaults.\n", ahd_name(ahd)); termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH; } @@ -714,22 +714,22 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl); if (error != 0) { - printf("%s: Unable to set termination settings!\n", + printk("%s: Unable to set termination settings!\n", ahd_name(ahd)); } else if (bootverbose) { - printf("%s: Primary High byte termination %sabled\n", + printk("%s: Primary High byte termination %sabled\n", ahd_name(ahd), (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis"); - printf("%s: Primary Low byte termination %sabled\n", + printk("%s: Primary Low byte termination %sabled\n", ahd_name(ahd), (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis"); - printf("%s: Secondary High byte termination %sabled\n", + printk("%s: Secondary High byte termination %sabled\n", ahd_name(ahd), (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis"); - printf("%s: Secondary Low byte termination %sabled\n", + printk("%s: Secondary Low byte termination %sabled\n", ahd_name(ahd), (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis"); } @@ -805,7 +805,7 @@ ahd_pci_intr(struct ahd_softc *ahd) if ((intstat & PCIINT) == 0) return; - printf("%s: PCI error Interrupt\n", ahd_name(ahd)); + printk("%s: PCI error Interrupt\n", ahd_name(ahd)); saved_modes = ahd_save_modes(ahd); ahd_dump_card_state(ahd); ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); @@ -832,7 +832,7 @@ ahd_pci_intr(struct ahd_softc *ahd) s = pci_status_strings[bit]; if (i == 7/*TARG*/ && bit == 3) s = "%s: Signaled Target Abort\n"; - printf(s, ahd_name(ahd), pci_status_source[i]); + printk(s, ahd_name(ahd), pci_status_source[i]); } } } @@ -862,7 +862,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) */ pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS, /*bytes*/2); - printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", + printk("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", ahd_name(ahd), pcix_status); saved_modes = ahd_save_modes(ahd); for (i = 0; i < 4; i++) { @@ -891,7 +891,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) static const char *s; s = split_status_strings[bit]; - printf(s, ahd_name(ahd), + printk(s, ahd_name(ahd), split_status_source[i]); } @@ -902,7 +902,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) static const char *s; s = split_status_strings[bit]; - printf(s, ahd_name(ahd), "SG"); + printk(s, ahd_name(ahd), "SG"); } } } @@ -950,7 +950,7 @@ ahd_aic790X_setup(struct ahd_softc *ahd) pci = ahd->dev_softc; rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev < ID_AIC7902_PCI_REV_A4) { - printf("%s: Unable to attach to unsupported chip revision %d\n", + printk("%s: Unable to attach to unsupported chip revision %d\n", ahd_name(ahd), rev); ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); return (ENXIO); diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index 014bed716e7c..59c85d5a153a 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c @@ -272,33 +272,32 @@ ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length) saved_modes = ahd_save_modes(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); if (length != sizeof(struct seeprom_config)) { - printf("ahd_proc_write_seeprom: incorrect buffer size\n"); + printk("ahd_proc_write_seeprom: incorrect buffer size\n"); goto done; } have_seeprom = ahd_verify_cksum((struct seeprom_config*)buffer); if (have_seeprom == 0) { - printf("ahd_proc_write_seeprom: cksum verification failed\n"); + printk("ahd_proc_write_seeprom: cksum verification failed\n"); goto done; } have_seeprom = ahd_acquire_seeprom(ahd); if (!have_seeprom) { - printf("ahd_proc_write_seeprom: No Serial EEPROM\n"); + printk("ahd_proc_write_seeprom: No Serial EEPROM\n"); goto done; } else { u_int start_addr; if (ahd->seep_config == NULL) { - ahd->seep_config = malloc(sizeof(*ahd->seep_config), - M_DEVBUF, M_NOWAIT); + ahd->seep_config = kmalloc(sizeof(*ahd->seep_config), GFP_ATOMIC); if (ahd->seep_config == NULL) { - printf("aic79xx: Unable to allocate serial " + printk("aic79xx: Unable to allocate serial " "eeprom buffer. Write failing\n"); goto done; } } - printf("aic79xx: Writing Serial EEPROM\n"); + printk("aic79xx: Writing Serial EEPROM\n"); start_addr = 32 * (ahd->channel - 'A'); ahd_write_seeprom(ahd, (u_int16_t *)buffer, start_addr, sizeof(struct seeprom_config)/2); diff --git a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c index dd11999b77b6..9e85a7ef9c8e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c +++ b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c @@ -207,14 +207,14 @@ ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, reset_seeprom(sd); } #ifdef AHC_DUMP_EEPROM - printf("\nSerial EEPROM:\n\t"); + printk("\nSerial EEPROM:\n\t"); for (k = 0; k < count; k = k + 1) { if (((k % 8) == 0) && (k != 0)) { - printf ("\n\t"); + printk(KERN_CONT "\n\t"); } - printf (" 0x%x", buf[k]); + printk(KERN_CONT " 0x%x", buf[k]); } - printf ("\n"); + printk(KERN_CONT "\n"); #endif return (1); } @@ -240,7 +240,7 @@ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, ewen = &seeprom_long_ewen; ewds = &seeprom_long_ewds; } else { - printf("ahc_write_seeprom: unsupported seeprom type %d\n", + printk("ahc_write_seeprom: unsupported seeprom type %d\n", sd->sd_chip); return (0); } diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 45aa728a76b2..3f5a542a7793 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -910,7 +910,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc) scb = ahc_lookup_scb(ahc, scb_index); if (scb == NULL) { - printf("%s: WARNING no command for scb %d " + printk("%s: WARNING no command for scb %d " "(cmdcmplt)\nQOUTPOS = %d\n", ahc_name(ahc), scb_index, (ahc->qoutfifonext - 1) & 0xFF); @@ -964,7 +964,7 @@ ahc_handle_brkadrint(struct ahc_softc *ahc) error = ahc_inb(ahc, ERROR); for (i = 0; error != 1 && i < num_errors; i++) error >>= 1; - printf("%s: brkadrint, %s at seqaddr = 0x%x\n", + printk("%s: brkadrint, %s at seqaddr = 0x%x\n", ahc_name(ahc), ahc_hard_errors[i].errmesg, ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); @@ -1021,7 +1021,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) scb = ahc_lookup_scb(ahc, scb_index); if (scb == NULL) { ahc_print_devinfo(ahc, &devinfo); - printf("ahc_intr - referenced scb " + printk("ahc_intr - referenced scb " "not valid during seqint 0x%x scb(%d)\n", intstat, scb_index); ahc_dump_card_state(ahc); @@ -1049,7 +1049,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) ahc_set_scsi_status(scb, hscb->shared_data.status.scsi_status); switch (hscb->shared_data.status.scsi_status) { case SCSI_STATUS_OK: - printf("%s: Interrupted for staus of 0???\n", + printk("%s: Interrupted for staus of 0???\n", ahc_name(ahc)); break; case SCSI_STATUS_CMD_TERMINATED: @@ -1063,7 +1063,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_SENSE) { ahc_print_path(ahc, scb); - printf("SCB %d: requests Check Status\n", + printk("SCB %d: requests Check Status\n", scb->hscb->tag); } #endif @@ -1086,7 +1086,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_SENSE) { ahc_print_path(ahc, scb); - printf("Sending Sense\n"); + printk("Sending Sense\n"); } #endif sg->addr = ahc_get_sense_bufaddr(ahc, scb); @@ -1162,29 +1162,29 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); - printf("%s:%c:%d: no active SCB for reconnecting " + printk("%s:%c:%d: no active SCB for reconnecting " "target - issuing BUS DEVICE RESET\n", ahc_name(ahc), devinfo.channel, devinfo.target); - printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " + printk("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " "ARG_1 == 0x%x ACCUM = 0x%x\n", ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN), ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM)); - printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " + printk("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " "SINDEX == 0x%x\n", ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR), ahc_index_busy_tcl(ahc, BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN))), ahc_inb(ahc, SINDEX)); - printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " + printk("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n", ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID), ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG), ahc_inb(ahc, SCB_CONTROL)); - printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", + printk("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI)); - printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); - printf("SEQCTL == 0x%x\n", ahc_inb(ahc, SEQCTL)); + printk("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0)); + printk("SEQCTL == 0x%x\n", ahc_inb(ahc, SEQCTL)); ahc_dump_card_state(ahc); ahc->msgout_buf[0] = MSG_BUS_DEV_RESET; ahc->msgout_len = 1; @@ -1197,7 +1197,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) case SEND_REJECT: { u_int rejbyte = ahc_inb(ahc, ACCUM); - printf("%s:%c:%d: Warning - unknown message received from " + printk("%s:%c:%d: Warning - unknown message received from " "target (0x%x). Rejecting\n", ahc_name(ahc), devinfo.channel, devinfo.target, rejbyte); break; @@ -1218,7 +1218,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) u_int lastphase; lastphase = ahc_inb(ahc, LASTPHASE); - printf("%s:%c:%d: unknown scsi bus phase %x, " + printk("%s:%c:%d: unknown scsi bus phase %x, " "lastphase = 0x%x. Attempting to continue\n", ahc_name(ahc), devinfo.channel, devinfo.target, lastphase, ahc_inb(ahc, SCSISIGI)); @@ -1229,7 +1229,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) u_int lastphase; lastphase = ahc_inb(ahc, LASTPHASE); - printf("%s:%c:%d: Missed busfree. " + printk("%s:%c:%d: Missed busfree. " "Lastphase = 0x%x, Curphase = 0x%x\n", ahc_name(ahc), devinfo.channel, devinfo.target, lastphase, ahc_inb(ahc, SCSISIGI)); @@ -1257,7 +1257,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; if (bus_phase != P_MESGIN && bus_phase != P_MESGOUT) { - printf("ahc_intr: HOST_MSG_LOOP bad " + printk("ahc_intr: HOST_MSG_LOOP bad " "phase 0x%x\n", bus_phase); /* @@ -1359,7 +1359,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) u_int scb_index; ahc_print_devinfo(ahc, &devinfo); - printf("Unable to clear parity error. " + printk("Unable to clear parity error. " "Resetting bus.\n"); scb_index = ahc_inb(ahc, SCB_TAG); scb = ahc_lookup_scb(ahc, scb_index); @@ -1395,18 +1395,18 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) break; } ahc_print_path(ahc, scb); - printf("data overrun detected %s." + printk("data overrun detected %s." " Tag == 0x%x.\n", ahc_phase_table[i].phasemsg, scb->hscb->tag); ahc_print_path(ahc, scb); - printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", + printk("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", ahc_get_transfer_length(scb), scb->sg_count); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { - printf("sg[%d] - Addr 0x%x%x : Length %d\n", + printk("sg[%d] - Addr 0x%x%x : Length %d\n", i, (ahc_le32toh(scb->sg_list[i].len) >> 24 & SG_HIGH_ADDR_BITS), @@ -1453,7 +1453,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) { u_int scbindex; - printf("%s:%c:%d:%d: Attempt to issue message failed\n", + printk("%s:%c:%d:%d: Attempt to issue message failed\n", ahc_name(ahc), devinfo.channel, devinfo.target, devinfo.lun); scbindex = ahc_inb(ahc, SCB_TAG); @@ -1473,7 +1473,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) } case NO_FREE_SCB: { - printf("%s: No free or disconnected SCBs\n", ahc_name(ahc)); + printk("%s: No free or disconnected SCBs\n", ahc_name(ahc)); ahc_dump_card_state(ahc); panic("for safety"); break; @@ -1483,7 +1483,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) u_int scbptr; scbptr = ahc_inb(ahc, SCBPTR); - printf("Bogus TAG after DMA. SCBPTR %d, tag %d, our tag %d\n", + printk("Bogus TAG after DMA. SCBPTR %d, tag %d, our tag %d\n", scbptr, ahc_inb(ahc, ARG_1), ahc->scb_data->hscbs[scbptr].tag); ahc_dump_card_state(ahc); @@ -1492,12 +1492,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) } case OUT_OF_RANGE: { - printf("%s: BTT calculation out of range\n", ahc_name(ahc)); - printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " + printk("%s: BTT calculation out of range\n", ahc_name(ahc)); + printk("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " "ARG_1 == 0x%x ACCUM = 0x%x\n", ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN), ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM)); - printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " + printk("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " "SINDEX == 0x%x\n, A == 0x%x\n", ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR), ahc_index_busy_tcl(ahc, @@ -1505,19 +1505,19 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) ahc_inb(ahc, SAVED_LUN))), ahc_inb(ahc, SINDEX), ahc_inb(ahc, ACCUM)); - printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " + printk("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n", ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID), ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG), ahc_inb(ahc, SCB_CONTROL)); - printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", + printk("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n", ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI)); ahc_dump_card_state(ahc); panic("for safety"); break; } default: - printf("ahc_intr: seqint, " + printk("ahc_intr: seqint, " "intstat == 0x%x, scsisigi = 0x%x\n", intstat, ahc_inb(ahc, SCSISIGI)); break; @@ -1562,7 +1562,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) intr_channel = (cur_channel == 'A') ? 'B' : 'A'; } if (status == 0) { - printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc)); + printk("%s: Spurious SCSI interrupt\n", ahc_name(ahc)); ahc_outb(ahc, CLRINT, CLRSCSIINT); ahc_unpause(ahc); return; @@ -1583,7 +1583,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) int now_lvd; now_lvd = ahc_inb(ahc, SBLKCTL) & ENAB40; - printf("%s: Transceiver State Has Changed to %s mode\n", + printk("%s: Transceiver State Has Changed to %s mode\n", ahc_name(ahc), now_lvd ? "LVD" : "SE"); ahc_outb(ahc, CLRSINT0, CLRIOERR); /* @@ -1599,7 +1599,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) ahc_reset_channel(ahc, intr_channel, /*Initiate Reset*/now_lvd == 0); } else if ((status & SCSIRSTI) != 0) { - printf("%s: Someone reset channel %c\n", + printk("%s: Someone reset channel %c\n", ahc_name(ahc), intr_channel); if (intr_channel != cur_channel) ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); @@ -1659,26 +1659,26 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) ahc_print_path(ahc, scb); scb->flags |= SCB_TRANSMISSION_ERROR; } else - printf("%s:%c:%d: ", ahc_name(ahc), intr_channel, + printk("%s:%c:%d: ", ahc_name(ahc), intr_channel, SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID))); scsirate = ahc_inb(ahc, SCSIRATE); if (silent == FALSE) { - printf("parity error detected %s. " + printk("parity error detected %s. " "SEQADDR(0x%x) SCSIRATE(0x%x)\n", ahc_phase_table[i].phasemsg, ahc_inw(ahc, SEQADDR0), scsirate); if ((ahc->features & AHC_DT) != 0) { if ((sstat2 & CRCVALERR) != 0) - printf("\tCRC Value Mismatch\n"); + printk("\tCRC Value Mismatch\n"); if ((sstat2 & CRCENDERR) != 0) - printf("\tNo terminal CRC packet " + printk("\tNo terminal CRC packet " "recevied\n"); if ((sstat2 & CRCREQERR) != 0) - printf("\tIllegal CRC packet " + printk("\tIllegal CRC packet " "request\n"); if ((sstat2 & DUAL_EDGE_ERR) != 0) - printf("\tUnexpected %sDT Data Phase\n", + printk("\tUnexpected %sDT Data Phase\n", (scsirate & SINGLE_EDGE) ? "" : "non-"); } @@ -1746,7 +1746,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) scb = ahc_lookup_scb(ahc, scb_index); if (scb == NULL) { - printf("%s: ahc_intr - referenced scb not " + printk("%s: ahc_intr - referenced scb not " "valid during SELTO scb(%d, %d)\n", ahc_name(ahc), scbptr, scb_index); ahc_dump_card_state(ahc); @@ -1755,7 +1755,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_SELTO) != 0) { ahc_print_path(ahc, scb); - printf("Saw Selection Timeout for SCB 0x%x\n", + printk("Saw Selection Timeout for SCB 0x%x\n", scb_index); } #endif @@ -1831,7 +1831,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) == MSG_ABORT_TAG) tag = scb->hscb->tag; ahc_print_path(ahc, scb); - printf("SCB %d - Abort%s Completed.\n", + printk("SCB %d - Abort%s Completed.\n", scb->hscb->tag, tag == SCB_LIST_NULL ? "" : " Tag"); ahc_abort_scbs(ahc, target, channel, @@ -1934,7 +1934,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) * We had not fully identified this connection, * so we cannot abort anything. */ - printf("%s: ", ahc_name(ahc)); + printk("%s: ", ahc_name(ahc)); } for (i = 0; i < num_phases; i++) { if (lastphase == ahc_phase_table[i].phase) @@ -1949,7 +1949,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) */ ahc_force_renegotiation(ahc, &devinfo); } - printf("Unexpected busfree %s\n" + printk("Unexpected busfree %s\n" "SEQADDR == 0x%x\n", ahc_phase_table[i].phasemsg, ahc_inb(ahc, SEQADDR0) @@ -1958,7 +1958,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) ahc_outb(ahc, CLRINT, CLRSCSIINT); ahc_restart(ahc); } else { - printf("%s: Missing case in ahc_handle_scsiint. status = %x\n", + printk("%s: Missing case in ahc_handle_scsiint. status = %x\n", ahc_name(ahc), status); ahc_outb(ahc, CLRINT, CLRSCSIINT); } @@ -2025,7 +2025,7 @@ ahc_clear_critical_section(struct ahc_softc *ahc) break; if (steps > AHC_MAX_STEPS) { - printf("%s: Infinite loop in critical section\n", + printk("%s: Infinite loop in critical section\n", ahc_name(ahc)); ahc_dump_card_state(ahc); panic("critical section loop"); @@ -2104,23 +2104,23 @@ ahc_print_scb(struct scb *scb) struct hardware_scb *hscb = scb->hscb; - printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", + printk("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", (void *)scb, hscb->control, hscb->scsiid, hscb->lun, hscb->cdb_len); - printf("Shared Data: "); + printk("Shared Data: "); for (i = 0; i < sizeof(hscb->shared_data.cdb); i++) - printf("%#02x", hscb->shared_data.cdb[i]); - printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n", + printk("%#02x", hscb->shared_data.cdb[i]); + printk(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n", ahc_le32toh(hscb->dataptr), ahc_le32toh(hscb->datacnt), ahc_le32toh(hscb->sgptr), hscb->tag); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { - printf("sg[%d] - Addr 0x%x%x : Length %d\n", + printk("sg[%d] - Addr 0x%x%x : Length %d\n", i, (ahc_le32toh(scb->sg_list[i].len) >> 24 & SG_HIGH_ADDR_BITS), @@ -2152,8 +2152,7 @@ ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel) && ahc->enabled_targets[scsi_id] != master_tstate) panic("%s: ahc_alloc_tstate - Target already allocated", ahc_name(ahc)); - tstate = (struct ahc_tmode_tstate*)malloc(sizeof(*tstate), - M_DEVBUF, M_NOWAIT); + tstate = kmalloc(sizeof(*tstate), GFP_ATOMIC); if (tstate == NULL) return (NULL); @@ -2202,7 +2201,7 @@ ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force) scsi_id += 8; tstate = ahc->enabled_targets[scsi_id]; if (tstate != NULL) - free(tstate, M_DEVBUF); + kfree(tstate); ahc->enabled_targets[scsi_id] = NULL; } #endif @@ -2589,13 +2588,13 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, CAM_LUN_WILDCARD, AC_TRANSFER_NEG); if (bootverbose) { if (offset != 0) { - printf("%s: target %d synchronous at %sMHz%s, " + printk("%s: target %d synchronous at %sMHz%s, " "offset = 0x%x\n", ahc_name(ahc), devinfo->target, syncrate->rate, (ppr_options & MSG_EXT_PPR_DT_REQ) ? " DT" : "", offset); } else { - printf("%s: target %d using " + printk("%s: target %d using " "asynchronous transfers\n", ahc_name(ahc), devinfo->target); } @@ -2658,7 +2657,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc_send_async(ahc, devinfo->channel, devinfo->target, CAM_LUN_WILDCARD, AC_TRANSFER_NEG); if (bootverbose) { - printf("%s: target %d using %dbit transfers\n", + printk("%s: target %d using %dbit transfers\n", ahc_name(ahc), devinfo->target, 8 * (0x01 << width)); } @@ -2835,7 +2834,7 @@ ahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target, void ahc_print_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) { - printf("%s:%c:%d:%d: ", ahc_name(ahc), devinfo->channel, + printk("%s:%c:%d:%d: ", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); } @@ -2907,7 +2906,7 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc->msgout_buf[ahc->msgout_index++] = MSG_BUS_DEV_RESET; ahc->msgout_len++; ahc_print_path(ahc, scb); - printf("Bus Device Reset Message Sent\n"); + printk("Bus Device Reset Message Sent\n"); /* * Clear our selection hardware in advance of * the busfree. We may have an entry in the waiting @@ -2923,7 +2922,7 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT; ahc->msgout_len++; ahc_print_path(ahc, scb); - printf("Abort%s Message Sent\n", + printk("Abort%s Message Sent\n", (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : ""); /* * Clear our selection hardware in advance of @@ -2936,9 +2935,9 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) { ahc_build_transfer_msg(ahc, devinfo); } else { - printf("ahc_intr: AWAITING_MSG for an SCB that " + printk("ahc_intr: AWAITING_MSG for an SCB that " "does not have a waiting message\n"); - printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, + printk("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, devinfo->target_mask); panic("SCB = %d, SCB Control = %x, MSG_OUT = %x " "SCB flags = %x", scb->hscb->tag, scb->hscb->control, @@ -3019,7 +3018,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) if (bootverbose) { ahc_print_devinfo(ahc, devinfo); - printf("Ensuring async\n"); + printk("Ensuring async\n"); } } @@ -3067,7 +3066,7 @@ ahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc->msgout_buf + ahc->msgout_index, period, offset); ahc->msgout_len += 5; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", + printk("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun, period, offset); } @@ -3085,7 +3084,7 @@ ahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc->msgout_buf + ahc->msgout_index, bus_width); ahc->msgout_len += 4; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending WDTR %x\n", + printk("(%s:%c:%d:%d): Sending WDTR %x\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun, bus_width); } @@ -3107,7 +3106,7 @@ ahc_construct_ppr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, bus_width, ppr_options); ahc->msgout_len += 8; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " + printk("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " "offset %x, ppr_options %x\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun, bus_width, period, offset, ppr_options); @@ -3160,7 +3159,7 @@ ahc_handle_proto_violation(struct ahc_softc *ahc) * to match. */ ahc_print_devinfo(ahc, &devinfo); - printf("Target did not send an IDENTIFY message. " + printk("Target did not send an IDENTIFY message. " "LASTPHASE = 0x%x.\n", lastphase); scb = NULL; } else if (scb == NULL) { @@ -3169,13 +3168,13 @@ ahc_handle_proto_violation(struct ahc_softc *ahc) * transaction. Print an error and reset the bus. */ ahc_print_devinfo(ahc, &devinfo); - printf("No SCB found during protocol violation\n"); + printk("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { ahc_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahc_print_path(ahc, scb); - printf("No or incomplete CDB sent to device.\n"); + printk("No or incomplete CDB sent to device.\n"); } else if ((ahc_inb(ahc, SCB_CONTROL) & STATUS_RCVD) == 0) { /* * The target never bothered to provide status to @@ -3185,10 +3184,10 @@ ahc_handle_proto_violation(struct ahc_softc *ahc) * message. */ ahc_print_path(ahc, scb); - printf("Completed command without status.\n"); + printk("Completed command without status.\n"); } else { ahc_print_path(ahc, scb); - printf("Unknown protocol violation.\n"); + printk("Unknown protocol violation.\n"); ahc_dump_card_state(ahc); } } @@ -3202,7 +3201,7 @@ proto_violation_reset: * it away with a bus reset. */ found = ahc_reset_channel(ahc, 'A', TRUE); - printf("%s: Issued Channel %c Bus Reset. " + printk("%s: Issued Channel %c Bus Reset. " "%d SCBs aborted\n", ahc_name(ahc), 'A', found); } else { /* @@ -3224,7 +3223,7 @@ proto_violation_reset: ahc_print_path(ahc, scb); scb->flags |= SCB_ABORT; } - printf("Protocol violation %s. Attempting to abort.\n", + printk("Protocol violation %s. Attempting to abort.\n", ahc_lookup_phase_entry(curphase)->phasemsg); } } @@ -3257,14 +3256,14 @@ reswitch: #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { ahc_print_devinfo(ahc, &devinfo); - printf("INITIATOR_MSG_OUT"); + printk("INITIATOR_MSG_OUT"); } #endif phasemis = bus_phase != P_MESGOUT; if (phasemis) { #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { - printf(" PHASEMIS %s\n", + printk(" PHASEMIS %s\n", ahc_lookup_phase_entry(bus_phase) ->phasemsg); } @@ -3291,7 +3290,7 @@ reswitch: ahc_outb(ahc, CLRSINT1, CLRREQINIT); #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", ahc->send_msg_perror); + printk(" byte 0x%x\n", ahc->send_msg_perror); #endif ahc_outb(ahc, SCSIDATL, MSG_PARITY_ERROR); break; @@ -3321,7 +3320,7 @@ reswitch: ahc_outb(ahc, CLRSINT1, CLRREQINIT); #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", + printk(" byte 0x%x\n", ahc->msgout_buf[ahc->msgout_index]); #endif ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); @@ -3335,14 +3334,14 @@ reswitch: #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { ahc_print_devinfo(ahc, &devinfo); - printf("INITIATOR_MSG_IN"); + printk("INITIATOR_MSG_IN"); } #endif phasemis = bus_phase != P_MESGIN; if (phasemis) { #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { - printf(" PHASEMIS %s\n", + printk(" PHASEMIS %s\n", ahc_lookup_phase_entry(bus_phase) ->phasemsg); } @@ -3363,7 +3362,7 @@ reswitch: ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIBUSL); #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", + printk(" byte 0x%x\n", ahc->msgin_buf[ahc->msgin_index]); #endif @@ -3385,7 +3384,7 @@ reswitch: #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) { ahc_print_devinfo(ahc, &devinfo); - printf("Asserting ATN for response\n"); + printk("Asserting ATN for response\n"); } #endif ahc_assert_atn(ahc); @@ -3666,7 +3665,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) targ_scsirate & WIDEXFER, devinfo->role); if (bootverbose) { - printf("(%s:%c:%d:%d): Received " + printk("(%s:%c:%d:%d): Received " "SDTR period %x, offset %x\n\t" "Filtered to period %x, offset %x\n", ahc_name(ahc), devinfo->channel, @@ -3697,7 +3696,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) */ if (bootverbose && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated SDTR\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); @@ -3739,7 +3738,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) ahc_validate_width(ahc, tinfo, &bus_width, devinfo->role); if (bootverbose) { - printf("(%s:%c:%d:%d): Received WDTR " + printk("(%s:%c:%d:%d): Received WDTR " "%x filtered to %x\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun, @@ -3755,7 +3754,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) */ if (saved_width > bus_width) { reject = TRUE; - printf("(%s:%c:%d:%d): requested %dBit " + printk("(%s:%c:%d:%d): requested %dBit " "transfers. Rejecting...\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun, @@ -3768,7 +3767,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) */ if (bootverbose && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated WDTR\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); @@ -3886,12 +3885,12 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) } } else { if (devinfo->role != ROLE_TARGET) - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated PPR\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); else - printf("(%s:%c:%d:%d): Initiator " + printk("(%s:%c:%d:%d): Initiator " "Initiated PPR\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); @@ -3903,7 +3902,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) response = TRUE; } if (bootverbose) { - printf("(%s:%c:%d:%d): Received PPR width %x, " + printk("(%s:%c:%d:%d): Received PPR width %x, " "period %x, offset %x,options %x\n" "\tFiltered to width %x, period %x, " "offset %x, options %x\n", @@ -4033,7 +4032,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) * Attempt to negotiate SPI-2 style. */ if (bootverbose) { - printf("(%s:%c:%d:%d): PPR Rejected. " + printk("(%s:%c:%d:%d): PPR Rejected. " "Trying WDTR/SDTR\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); @@ -4049,7 +4048,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) { /* note 8bit xfers */ - printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using " + printk("(%s:%c:%d:%d): refuses WIDE negotiation. Using " "8bit transfers\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, @@ -4077,7 +4076,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) /*offset*/0, /*ppr_options*/0, AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, /*paused*/TRUE); - printf("(%s:%c:%d:%d): refuses synchronous negotiation. " + printk("(%s:%c:%d:%d): refuses synchronous negotiation. " "Using asynchronous transfers\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); @@ -4088,13 +4087,13 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) tag_type = (scb->hscb->control & MSG_SIMPLE_TASK); if (tag_type == MSG_SIMPLE_TASK) { - printf("(%s:%c:%d:%d): refuses tagged commands. " + printk("(%s:%c:%d:%d): refuses tagged commands. " "Performing non-tagged I/O\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); ahc_set_tags(ahc, scb->io_ctx, devinfo, AHC_QUEUE_NONE); mask = ~0x23; } else { - printf("(%s:%c:%d:%d): refuses %s tagged commands. " + printk("(%s:%c:%d:%d): refuses %s tagged commands. " "Performing simple queue tagged I/O only\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun, tag_type == MSG_ORDERED_TASK @@ -4144,7 +4143,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) /* * Otherwise, we ignore it. */ - printf("%s:%c:%d: Message reject for %x -- ignored\n", + printk("%s:%c:%d: Message reject for %x -- ignored\n", ahc_name(ahc), devinfo->channel, devinfo->target, last_msg); } @@ -4369,7 +4368,7 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, if (message != NULL && (verbose_level <= bootverbose)) - printf("%s: %s on %c:%d. %d SCBs aborted\n", ahc_name(ahc), + printk("%s: %s on %c:%d. %d SCBs aborted\n", ahc_name(ahc), message, devinfo->channel, devinfo->target, found); } @@ -4408,23 +4407,22 @@ ahc_alloc(void *platform_arg, char *name) int i; #ifndef __FreeBSD__ - ahc = malloc(sizeof(*ahc), M_DEVBUF, M_NOWAIT); + ahc = kmalloc(sizeof(*ahc), GFP_ATOMIC); if (!ahc) { - printf("aic7xxx: cannot malloc softc!\n"); - free(name, M_DEVBUF); + printk("aic7xxx: cannot malloc softc!\n"); + kfree(name); return NULL; } #else ahc = device_get_softc((device_t)platform_arg); #endif memset(ahc, 0, sizeof(*ahc)); - ahc->seep_config = malloc(sizeof(*ahc->seep_config), - M_DEVBUF, M_NOWAIT); + ahc->seep_config = kmalloc(sizeof(*ahc->seep_config), GFP_ATOMIC); if (ahc->seep_config == NULL) { #ifndef __FreeBSD__ - free(ahc, M_DEVBUF); + kfree(ahc); #endif - free(name, M_DEVBUF); + kfree(name); return (NULL); } LIST_INIT(&ahc->pending_scbs); @@ -4466,8 +4464,7 @@ ahc_softc_init(struct ahc_softc *ahc) ahc->pause = ahc->unpause | PAUSE; /* XXX The shared scb data stuff should be deprecated */ if (ahc->scb_data == NULL) { - ahc->scb_data = malloc(sizeof(*ahc->scb_data), - M_DEVBUF, M_NOWAIT); + ahc->scb_data = kmalloc(sizeof(*ahc->scb_data), GFP_ATOMIC); if (ahc->scb_data == NULL) return (ENOMEM); memset(ahc->scb_data, 0, sizeof(*ahc->scb_data)); @@ -4486,7 +4483,7 @@ void ahc_set_name(struct ahc_softc *ahc, char *name) { if (ahc->name != NULL) - free(ahc->name, M_DEVBUF); + kfree(ahc->name); ahc->name = name; } @@ -4540,25 +4537,25 @@ ahc_free(struct ahc_softc *ahc) lstate = tstate->enabled_luns[j]; if (lstate != NULL) { xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); + kfree(lstate); } } #endif - free(tstate, M_DEVBUF); + kfree(tstate); } } #ifdef AHC_TARGET_MODE if (ahc->black_hole != NULL) { xpt_free_path(ahc->black_hole->path); - free(ahc->black_hole, M_DEVBUF); + kfree(ahc->black_hole); } #endif if (ahc->name != NULL) - free(ahc->name, M_DEVBUF); + kfree(ahc->name); if (ahc->seep_config != NULL) - free(ahc->seep_config, M_DEVBUF); + kfree(ahc->seep_config); #ifndef __FreeBSD__ - free(ahc, M_DEVBUF); + kfree(ahc); #endif return; } @@ -4633,7 +4630,7 @@ ahc_reset(struct ahc_softc *ahc, int reinit) } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK)); if (wait == 0) { - printf("%s: WARNING - Failed chip reset! " + printk("%s: WARNING - Failed chip reset! " "Trying to initialize anyway.\n", ahc_name(ahc)); } ahc_outb(ahc, HCNTRL, ahc->pause); @@ -4656,7 +4653,7 @@ ahc_reset(struct ahc_softc *ahc, int reinit) ahc->features |= AHC_TWIN; break; default: - printf(" Unsupported adapter type. Ignoring\n"); + printk(" Unsupported adapter type. Ignoring\n"); return(-1); } @@ -4783,9 +4780,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) SLIST_INIT(&scb_data->sg_maps); /* Allocate SCB resources */ - scb_data->scbarray = - (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, - M_DEVBUF, M_NOWAIT); + scb_data->scbarray = (struct scb *)kmalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, GFP_ATOMIC); if (scb_data->scbarray == NULL) return (ENOMEM); memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC); @@ -4794,7 +4789,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) scb_data->maxhscbs = ahc_probe_scbs(ahc); if (ahc->scb_data->maxhscbs == 0) { - printf("%s: No SCB space found\n", ahc_name(ahc)); + printk("%s: No SCB space found\n", ahc_name(ahc)); return (ENXIO); } @@ -4892,7 +4887,7 @@ ahc_init_scbdata(struct ahc_softc *ahc) ahc_alloc_scbs(ahc); if (scb_data->numscbs == 0) { - printf("%s: ahc_init_scbdata - " + printk("%s: ahc_init_scbdata - " "Unable to allocate initial scbs\n", ahc_name(ahc)); goto error_exit; @@ -4935,7 +4930,7 @@ ahc_fini_scbdata(struct ahc_softc *ahc) ahc_dmamem_free(ahc, scb_data->sg_dmat, sg_map->sg_vaddr, sg_map->sg_dmamap); - free(sg_map, M_DEVBUF); + kfree(sg_map); } ahc_dma_tag_destroy(ahc, scb_data->sg_dmat); } @@ -4964,7 +4959,7 @@ ahc_fini_scbdata(struct ahc_softc *ahc) break; } if (scb_data->scbarray != NULL) - free(scb_data->scbarray, M_DEVBUF); + kfree(scb_data->scbarray); } static void @@ -4985,7 +4980,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) next_scb = &scb_data->scbarray[scb_data->numscbs]; - sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); + sg_map = kmalloc(sizeof(*sg_map), GFP_ATOMIC); if (sg_map == NULL) return; @@ -4994,7 +4989,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) if (ahc_dmamem_alloc(ahc, scb_data->sg_dmat, (void **)&sg_map->sg_vaddr, BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { - free(sg_map, M_DEVBUF); + kfree(sg_map); return; } @@ -5014,8 +5009,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) #ifndef __linux__ int error; #endif - pdata = (struct scb_platform_data *)malloc(sizeof(*pdata), - M_DEVBUF, M_NOWAIT); + pdata = kmalloc(sizeof(*pdata), GFP_ATOMIC); if (pdata == NULL) break; next_scb->platform_data = pdata; @@ -5244,7 +5238,7 @@ ahc_chip_init(struct ahc_softc *ahc) * in "fast" mode. */ if (bootverbose) - printf("%s: Downloading Sequencer Program...", + printk("%s: Downloading Sequencer Program...", ahc_name(ahc)); error = ahc_loadseq(ahc); @@ -5290,22 +5284,22 @@ ahc_init(struct ahc_softc *ahc) #endif #ifdef AHC_PRINT_SRAM - printf("Scratch Ram:"); + printk("Scratch Ram:"); for (i = 0x20; i < 0x5f; i++) { if (((i % 8) == 0) && (i != 0)) { - printf ("\n "); + printk ("\n "); } - printf (" 0x%x", ahc_inb(ahc, i)); + printk (" 0x%x", ahc_inb(ahc, i)); } if ((ahc->features & AHC_MORE_SRAM) != 0) { for (i = 0x70; i < 0x7f; i++) { if (((i % 8) == 0) && (i != 0)) { - printf ("\n "); + printk ("\n "); } - printf (" 0x%x", ahc_inb(ahc, i)); + printk (" 0x%x", ahc_inb(ahc, i)); } } - printf ("\n"); + printk ("\n"); /* * Reading uninitialized scratch ram may * generate parity errors. @@ -5419,14 +5413,14 @@ ahc_init(struct ahc_softc *ahc) * data for any target mode initiator. */ if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) { - printf("%s: unable to allocate ahc_tmode_tstate. " + printk("%s: unable to allocate ahc_tmode_tstate. " "Failing attach\n", ahc_name(ahc)); return (ENOMEM); } if ((ahc->features & AHC_TWIN) != 0) { if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) { - printf("%s: unable to allocate ahc_tmode_tstate. " + printk("%s: unable to allocate ahc_tmode_tstate. " "Failing attach\n", ahc_name(ahc)); return (ENOMEM); } @@ -5440,7 +5434,7 @@ ahc_init(struct ahc_softc *ahc) #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_MISC) { - printf("%s: hardware scb %u bytes; kernel scb %u bytes; " + printk("%s: hardware scb %u bytes; kernel scb %u bytes; " "ahc_dma %u bytes\n", ahc_name(ahc), (u_int)sizeof(struct hardware_scb), @@ -5470,7 +5464,7 @@ ahc_init(struct ahc_softc *ahc) /* Grab the disconnection disable table and invert it for our needs */ if ((ahc->flags & AHC_USEDEFAULTS) != 0) { - printf("%s: Host Adapter Bios disabled. Using default SCSI " + printk("%s: Host Adapter Bios disabled. Using default SCSI " "device parameters\n", ahc_name(ahc)); ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B| AHC_TERM_ENB_A|AHC_TERM_ENB_B; @@ -5651,7 +5645,7 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc) && ((intstat & INT_PEND) != 0 || (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)) != 0)); if (maxloops == 0) { - printf("Infinite interrupt loop, INTSTAT = %x", + printk("Infinite interrupt loop, INTSTAT = %x", ahc_inb(ahc, INTSTAT)); } ahc_platform_flushwork(ahc); @@ -5910,7 +5904,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, while (qinpos != qintail) { scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinpos]); if (scb == NULL) { - printf("qinpos = %d, SCB index = %d\n", + printk("qinpos = %d, SCB index = %d\n", qinpos, ahc->qinfifo[qinpos]); panic("Loop 1\n"); } @@ -5933,7 +5927,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, if (cstat != CAM_REQ_CMP) ahc_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in qinfifo\n"); + printk("Inactive SCB in qinfifo\n"); ahc_done(ahc, scb); /* FALLTHROUGH */ @@ -5976,7 +5970,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinstart]); if (scb == NULL) { - printf("found = %d, qinstart = %d, qinfifionext = %d\n", + printk("found = %d, qinstart = %d, qinfifionext = %d\n", found, qinstart, ahc->qinfifonext); panic("First/Second Qinfifo fixup\n"); } @@ -6014,7 +6008,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, ahc_outb(ahc, SCBPTR, next); scb_index = ahc_inb(ahc, SCB_TAG); if (scb_index >= ahc->scb_data->numscbs) { - printf("Waiting List inconsistency. " + printk("Waiting List inconsistency. " "SCB index == %d, yet numscbs == %d.", scb_index, ahc->scb_data->numscbs); ahc_dump_card_state(ahc); @@ -6022,7 +6016,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, } scb = ahc_lookup_scb(ahc, scb_index); if (scb == NULL) { - printf("scb_index = %d, next = %d\n", + printk("scb_index = %d, next = %d\n", scb_index, next); panic("Waiting List traversal\n"); } @@ -6046,7 +6040,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, if (cstat != CAM_REQ_CMP) ahc_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in Waiting List\n"); + printk("Inactive SCB in Waiting List\n"); ahc_done(ahc, scb); /* FALLTHROUGH */ } @@ -6153,7 +6147,7 @@ ahc_search_untagged_queues(struct ahc_softc *ahc, ahc_io_ctx_t ctx, if (cstat != CAM_REQ_CMP) ahc_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in untaggedQ\n"); + printk("Inactive SCB in untaggedQ\n"); ahc_done(ahc, scb); break; } @@ -6200,7 +6194,7 @@ ahc_search_disc_list(struct ahc_softc *ahc, int target, char channel, ahc_outb(ahc, SCBPTR, next); scb_index = ahc_inb(ahc, SCB_TAG); if (scb_index >= ahc->scb_data->numscbs) { - printf("Disconnected List inconsistency. " + printk("Disconnected List inconsistency. " "SCB index == %d, yet numscbs == %d.", scb_index, ahc->scb_data->numscbs); ahc_dump_card_state(ahc); @@ -6456,7 +6450,7 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel, if (ahc_get_transaction_status(scbp) != CAM_REQ_CMP) ahc_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB on pending list\n"); + printk("Inactive SCB on pending list\n"); ahc_done(ahc, scbp); found++; } @@ -6734,7 +6728,7 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb) #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { ahc_print_path(ahc, scb); - printf("Handled %sResidual of %d bytes\n", + printk("Handled %sResidual of %d bytes\n", (scb->flags & SCB_SENSE) ? "Sense " : "", resid); } #endif @@ -6774,7 +6768,7 @@ ahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate, if (pending == AHC_TMODE_EVENT_BUFFER_SIZE) { xpt_print_path(lstate->path); - printf("immediate event %x:%x lost\n", + printk("immediate event %x:%x lost\n", lstate->event_buffer[lstate->event_r_idx].event_type, lstate->event_buffer[lstate->event_r_idx].event_arg); lstate->event_r_idx++; @@ -6844,7 +6838,7 @@ ahc_dumpseq(struct ahc_softc* ahc) uint8_t ins_bytes[4]; ahc_insb(ahc, SEQRAM, ins_bytes, 4); - printf("0x%08x\n", ins_bytes[0] << 24 + printk("0x%08x\n", ins_bytes[0] << 24 | ins_bytes[1] << 16 | ins_bytes[2] << 8 | ins_bytes[3]); @@ -6912,7 +6906,7 @@ ahc_loadseq(struct ahc_softc *ahc) * storage capacity for this chip. Fail * the load. */ - printf("\n%s: Program too large for instruction memory " + printk("\n%s: Program too large for instruction memory " "size of %d!\n", ahc_name(ahc), ahc->instruction_ram_size); return (ENOMEM); @@ -6947,7 +6941,7 @@ ahc_loadseq(struct ahc_softc *ahc) if (cs_count != 0) { cs_count *= sizeof(struct cs); - ahc->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT); + ahc->critical_sections = kmalloc(cs_count, GFP_ATOMIC); if (ahc->critical_sections == NULL) panic("ahc_loadseq: Could not malloc"); memcpy(ahc->critical_sections, cs_table, cs_count); @@ -6955,8 +6949,8 @@ ahc_loadseq(struct ahc_softc *ahc) ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE); if (bootverbose) { - printf(" %d instructions downloaded\n", downloaded); - printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", + printk(" %d instructions downloaded\n", downloaded); + printk("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", ahc_name(ahc), ahc->features, ahc->bugs, ahc->flags); } return (0); @@ -7132,12 +7126,12 @@ ahc_print_register(const ahc_reg_parse_entry_t *table, u_int num_entries, u_int printed_mask; if (cur_column != NULL && *cur_column >= wrap_point) { - printf("\n"); + printk("\n"); *cur_column = 0; } - printed = printf("%s[0x%x]", name, value); + printed = printk("%s[0x%x]", name, value); if (table == NULL) { - printed += printf(" "); + printed += printk(" "); *cur_column += printed; return (printed); } @@ -7152,7 +7146,7 @@ ahc_print_register(const ahc_reg_parse_entry_t *table, u_int num_entries, == table[entry].mask)) continue; - printed += printf("%s%s", + printed += printk("%s%s", printed_mask == 0 ? ":(" : "|", table[entry].name); printed_mask |= table[entry].mask; @@ -7163,9 +7157,9 @@ ahc_print_register(const ahc_reg_parse_entry_t *table, u_int num_entries, break; } if (printed_mask != 0) - printed += printf(") "); + printed += printk(") "); else - printed += printf(" "); + printed += printk(" "); if (cur_column != NULL) *cur_column += printed; return (printed); @@ -7197,16 +7191,16 @@ ahc_dump_card_state(struct ahc_softc *ahc) saved_scbptr = ahc_inb(ahc, SCBPTR); last_phase = ahc_inb(ahc, LASTPHASE); - printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" + printk(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" "%s: Dumping Card State %s, at SEQADDR 0x%x\n", ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg, ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); if (paused) - printf("Card was paused\n"); - printf("ACCUM = 0x%x, SINDEX = 0x%x, DINDEX = 0x%x, ARG_2 = 0x%x\n", + printk("Card was paused\n"); + printk("ACCUM = 0x%x, SINDEX = 0x%x, DINDEX = 0x%x, ARG_2 = 0x%x\n", ahc_inb(ahc, ACCUM), ahc_inb(ahc, SINDEX), ahc_inb(ahc, DINDEX), ahc_inb(ahc, ARG_2)); - printf("HCNT = 0x%x SCBPTR = 0x%x\n", ahc_inb(ahc, HCNT), + printk("HCNT = 0x%x SCBPTR = 0x%x\n", ahc_inb(ahc, HCNT), ahc_inb(ahc, SCBPTR)); cur_col = 0; if ((ahc->features & AHC_DT) != 0) @@ -7230,15 +7224,15 @@ ahc_dump_card_state(struct ahc_softc *ahc) ahc_dfcntrl_print(ahc_inb(ahc, DFCNTRL), &cur_col, 50); ahc_dfstatus_print(ahc_inb(ahc, DFSTATUS), &cur_col, 50); if (cur_col != 0) - printf("\n"); - printf("STACK:"); + printk("\n"); + printk("STACK:"); for (i = 0; i < STACK_SIZE; i++) - printf(" 0x%x", ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8)); - printf("\nSCB count = %d\n", ahc->scb_data->numscbs); - printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag); - printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB)); + printk(" 0x%x", ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8)); + printk("\nSCB count = %d\n", ahc->scb_data->numscbs); + printk("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag); + printk("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB)); /* QINFIFO */ - printf("QINFIFO entries: "); + printk("QINFIFO entries: "); if ((ahc->features & AHC_QUEUE_REGS) != 0) { qinpos = ahc_inb(ahc, SNSCB_QOFF); ahc_outb(ahc, SNSCB_QOFF, qinpos); @@ -7246,109 +7240,109 @@ ahc_dump_card_state(struct ahc_softc *ahc) qinpos = ahc_inb(ahc, QINPOS); qintail = ahc->qinfifonext; while (qinpos != qintail) { - printf("%d ", ahc->qinfifo[qinpos]); + printk("%d ", ahc->qinfifo[qinpos]); qinpos++; } - printf("\n"); + printk("\n"); - printf("Waiting Queue entries: "); + printk("Waiting Queue entries: "); scb_index = ahc_inb(ahc, WAITING_SCBH); i = 0; while (scb_index != SCB_LIST_NULL && i++ < 256) { ahc_outb(ahc, SCBPTR, scb_index); - printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); + printk("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); scb_index = ahc_inb(ahc, SCB_NEXT); } - printf("\n"); + printk("\n"); - printf("Disconnected Queue entries: "); + printk("Disconnected Queue entries: "); scb_index = ahc_inb(ahc, DISCONNECTED_SCBH); i = 0; while (scb_index != SCB_LIST_NULL && i++ < 256) { ahc_outb(ahc, SCBPTR, scb_index); - printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); + printk("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG)); scb_index = ahc_inb(ahc, SCB_NEXT); } - printf("\n"); + printk("\n"); ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD); - printf("QOUTFIFO entries: "); + printk("QOUTFIFO entries: "); qoutpos = ahc->qoutfifonext; i = 0; while (ahc->qoutfifo[qoutpos] != SCB_LIST_NULL && i++ < 256) { - printf("%d ", ahc->qoutfifo[qoutpos]); + printk("%d ", ahc->qoutfifo[qoutpos]); qoutpos++; } - printf("\n"); + printk("\n"); - printf("Sequencer Free SCB List: "); + printk("Sequencer Free SCB List: "); scb_index = ahc_inb(ahc, FREE_SCBH); i = 0; while (scb_index != SCB_LIST_NULL && i++ < 256) { ahc_outb(ahc, SCBPTR, scb_index); - printf("%d ", scb_index); + printk("%d ", scb_index); scb_index = ahc_inb(ahc, SCB_NEXT); } - printf("\n"); + printk("\n"); - printf("Sequencer SCB Info: "); + printk("Sequencer SCB Info: "); for (i = 0; i < ahc->scb_data->maxhscbs; i++) { ahc_outb(ahc, SCBPTR, i); - cur_col = printf("\n%3d ", i); + cur_col = printk("\n%3d ", i); ahc_scb_control_print(ahc_inb(ahc, SCB_CONTROL), &cur_col, 60); ahc_scb_scsiid_print(ahc_inb(ahc, SCB_SCSIID), &cur_col, 60); ahc_scb_lun_print(ahc_inb(ahc, SCB_LUN), &cur_col, 60); ahc_scb_tag_print(ahc_inb(ahc, SCB_TAG), &cur_col, 60); } - printf("\n"); + printk("\n"); - printf("Pending list: "); + printk("Pending list: "); i = 0; LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) { if (i++ > 256) break; - cur_col = printf("\n%3d ", scb->hscb->tag); + cur_col = printk("\n%3d ", scb->hscb->tag); ahc_scb_control_print(scb->hscb->control, &cur_col, 60); ahc_scb_scsiid_print(scb->hscb->scsiid, &cur_col, 60); ahc_scb_lun_print(scb->hscb->lun, &cur_col, 60); if ((ahc->flags & AHC_PAGESCBS) == 0) { ahc_outb(ahc, SCBPTR, scb->hscb->tag); - printf("("); + printk("("); ahc_scb_control_print(ahc_inb(ahc, SCB_CONTROL), &cur_col, 60); ahc_scb_tag_print(ahc_inb(ahc, SCB_TAG), &cur_col, 60); - printf(")"); + printk(")"); } } - printf("\n"); + printk("\n"); - printf("Kernel Free SCB list: "); + printk("Kernel Free SCB list: "); i = 0; SLIST_FOREACH(scb, &ahc->scb_data->free_scbs, links.sle) { if (i++ > 256) break; - printf("%d ", scb->hscb->tag); + printk("%d ", scb->hscb->tag); } - printf("\n"); + printk("\n"); maxtarget = (ahc->features & (AHC_WIDE|AHC_TWIN)) ? 15 : 7; for (target = 0; target <= maxtarget; target++) { untagged_q = &ahc->untagged_queues[target]; if (TAILQ_FIRST(untagged_q) == NULL) continue; - printf("Untagged Q(%d): ", target); + printk("Untagged Q(%d): ", target); i = 0; TAILQ_FOREACH(scb, untagged_q, links.tqe) { if (i++ > 256) break; - printf("%d ", scb->hscb->tag); + printk("%d ", scb->hscb->tag); } - printf("\n"); + printk("\n"); } ahc_platform_dump_card_state(ahc); - printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); + printk("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); ahc_outb(ahc, SCBPTR, saved_scbptr); if (paused == 0) ahc_unpause(ahc); @@ -7489,7 +7483,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) u_long s; ahc_flag saved_flags; - printf("Configuring Target Mode\n"); + printk("Configuring Target Mode\n"); ahc_lock(ahc, &s); if (LIST_FIRST(&ahc->pending_scbs) != NULL) { ccb->ccb_h.status = CAM_BUSY; @@ -7535,7 +7529,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) /* Are we already enabled?? */ if (lstate != NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Lun already enabled\n"); + printk("Lun already enabled\n"); ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; return; } @@ -7547,7 +7541,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) * specific commands. */ ccb->ccb_h.status = CAM_REQ_INVALID; - printf("Non-zero Group Codes\n"); + printk("Non-zero Group Codes\n"); return; } @@ -7559,15 +7553,15 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) tstate = ahc_alloc_tstate(ahc, target, channel); if (tstate == NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate tstate\n"); + printk("Couldn't allocate tstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } } - lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT); + lstate = kmalloc(sizeof(*lstate), GFP_ATOMIC); if (lstate == NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate lstate\n"); + printk("Couldn't allocate lstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } @@ -7577,9 +7571,9 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) xpt_path_target_id(ccb->ccb_h.path), xpt_path_lun_id(ccb->ccb_h.path)); if (status != CAM_REQ_CMP) { - free(lstate, M_DEVBUF); + kfree(lstate); xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate path\n"); + printk("Couldn't allocate path\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } @@ -7654,7 +7648,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) ahc_unlock(ahc, &s); ccb->ccb_h.status = CAM_REQ_CMP; xpt_print_path(ccb->ccb_h.path); - printf("Lun now enabled for target mode\n"); + printk("Lun now enabled for target mode\n"); } else { struct scb *scb; int i, empty; @@ -7673,7 +7667,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) ccbh = &scb->io_ctx->ccb_h; if (ccbh->func_code == XPT_CONT_TARGET_IO && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ - printf("CTIO pending\n"); + printk("CTIO pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; ahc_unlock(ahc, &s); return; @@ -7681,12 +7675,12 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) } if (SLIST_FIRST(&lstate->accept_tios) != NULL) { - printf("ATIOs pending\n"); + printk("ATIOs pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; } if (SLIST_FIRST(&lstate->immed_notifies) != NULL) { - printf("INOTs pending\n"); + printk("INOTs pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; } @@ -7696,9 +7690,9 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) } xpt_print_path(ccb->ccb_h.path); - printf("Target mode disabled\n"); + printk("Target mode disabled\n"); xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); + kfree(lstate); ahc_pause(ahc); /* Can we clean up the target too? */ @@ -7750,7 +7744,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) ahc_outb(ahc, SCSISEQ, scsiseq); if ((ahc->features & AHC_MULTIROLE) == 0) { - printf("Configuring Initiator Mode\n"); + printk("Configuring Initiator Mode\n"); ahc->flags &= ~AHC_TARGETROLE; ahc->flags |= AHC_INITIATORROLE; /* @@ -7897,12 +7891,12 @@ ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd) * Wait for more ATIOs from the peripheral driver for this lun. */ if (bootverbose) - printf("%s: ATIOs exhausted\n", ahc_name(ahc)); + printk("%s: ATIOs exhausted\n", ahc_name(ahc)); return (1); } else ahc->flags &= ~AHC_TQINFIFO_BLOCKED; #if 0 - printf("Incoming command from %d for %d:%d%s\n", + printk("Incoming command from %d for %d:%d%s\n", initiator, target, lun, lstate == ahc->black_hole ? "(Black Holed)" : ""); #endif @@ -7949,7 +7943,7 @@ ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd) default: /* Only copy the opcode. */ atio->cdb_len = 1; - printf("Reserved or VU command code type encountered\n"); + printk("Reserved or VU command code type encountered\n"); break; } @@ -7965,7 +7959,7 @@ ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd) * to this accept tio. */ #if 0 - printf("Received Immediate Command %d:%d:%d - %p\n", + printk("Received Immediate Command %d:%d:%d - %p\n", initiator, target, lun, ahc->pending_device); #endif ahc->pending_device = lstate; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 5e42dac23505..aeea7a61478e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -653,7 +653,7 @@ ahc_linux_slave_alloc(struct scsi_device *sdev) struct ahc_linux_device *dev; if (bootverbose) - printf("%s: Slave Alloc %d\n", ahc_name(ahc), sdev->id); + printk("%s: Slave Alloc %d\n", ahc_name(ahc), sdev->id); dev = scsi_transport_device_data(sdev); memset(dev, 0, sizeof(*dev)); @@ -755,7 +755,7 @@ ahc_linux_abort(struct scsi_cmnd *cmd) error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT); if (error != 0) - printf("aic7xxx_abort returns 0x%x\n", error); + printk("aic7xxx_abort returns 0x%x\n", error); return (error); } @@ -769,7 +769,7 @@ ahc_linux_dev_reset(struct scsi_cmnd *cmd) error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET); if (error != 0) - printf("aic7xxx_dev_reset returns 0x%x\n", error); + printk("aic7xxx_dev_reset returns 0x%x\n", error); return (error); } @@ -791,7 +791,7 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd) ahc_unlock(ahc, &flags); if (bootverbose) - printf("%s: SCSI bus reset delivered. " + printk("%s: SCSI bus reset delivered. " "%d SCBs aborted.\n", ahc_name(ahc), found); return SUCCESS; @@ -840,7 +840,7 @@ ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent, { bus_dma_tag_t dmat; - dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); + dmat = kmalloc(sizeof(*dmat), GFP_ATOMIC); if (dmat == NULL) return (ENOMEM); @@ -861,7 +861,7 @@ ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent, void ahc_dma_tag_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat) { - free(dmat, M_DEVBUF); + kfree(dmat); } int @@ -918,7 +918,7 @@ ahc_linux_setup_tag_info_global(char *p) int tags, i, j; tags = simple_strtoul(p + 1, NULL, 0) & 0xff; - printf("Setting Global Tags= %d\n", tags); + printk("Setting Global Tags= %d\n", tags); for (i = 0; i < ARRAY_SIZE(aic7xxx_tag_info); i++) { for (j = 0; j < AHC_NUM_TARGETS; j++) { @@ -936,7 +936,7 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) && (targ < AHC_NUM_TARGETS)) { aic7xxx_tag_info[instance].tag_commands[targ] = value & 0xff; if (bootverbose) - printf("tag_info[%d:%d] = %d\n", instance, targ, value); + printk("tag_info[%d:%d] = %d\n", instance, targ, value); } } @@ -977,7 +977,7 @@ ahc_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, if (targ == -1) targ = 0; } else { - printf("Malformed Option %s\n", + printk("Malformed Option %s\n", opt_name); done = TRUE; } @@ -1120,7 +1120,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa ahc_set_unit(ahc, ahc_linux_unit++); ahc_unlock(ahc, &s); sprintf(buf, "scsi%d", host->host_no); - new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); + new_name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); if (new_name != NULL) { strcpy(new_name, buf); ahc_set_name(ahc, new_name); @@ -1220,7 +1220,7 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) { ahc->platform_data = - malloc(sizeof(struct ahc_platform_data), M_DEVBUF, M_NOWAIT); + kmalloc(sizeof(struct ahc_platform_data), GFP_ATOMIC); if (ahc->platform_data == NULL) return (ENOMEM); memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); @@ -1264,7 +1264,7 @@ ahc_platform_free(struct ahc_softc *ahc) if (ahc->platform_data->host) scsi_host_put(ahc->platform_data->host); - free(ahc->platform_data, M_DEVBUF); + kfree(ahc->platform_data); } } @@ -1378,7 +1378,7 @@ ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) if (ahc->unit >= ARRAY_SIZE(aic7xxx_tag_info)) { if (warned_user == 0) { - printf(KERN_WARNING + printk(KERN_WARNING "aic7xxx: WARNING: Insufficient tag_info instances\n" "aic7xxx: for installed controllers. Using defaults\n" "aic7xxx: Please update the aic7xxx_tag_info array in\n" @@ -1421,7 +1421,7 @@ ahc_linux_device_queue_depth(struct scsi_device *sdev) ahc_send_async(ahc, devinfo.channel, devinfo.target, devinfo.lun, AC_TRANSFER_NEG); ahc_print_devinfo(ahc, &devinfo); - printf("Tagged Queuing enabled. Depth %d\n", tags); + printk("Tagged Queuing enabled. Depth %d\n", tags); } else { ahc_platform_set_tags(ahc, sdev, &devinfo, AHC_QUEUE_NONE); ahc_send_async(ahc, devinfo.channel, devinfo.target, @@ -1735,7 +1735,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) * not have been dispatched to the controller, so * only check the SCB_ACTIVE flag for tagged transactions. */ - printf("SCB %d done'd twice\n", scb->hscb->tag); + printk("SCB %d done'd twice\n", scb->hscb->tag); ahc_dump_card_state(ahc); panic("Stopping for safety"); } @@ -1765,7 +1765,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { ahc_print_path(ahc, scb); - printf("Set CAM_UNCOR_PARITY\n"); + printk("Set CAM_UNCOR_PARITY\n"); } #endif ahc_set_transaction_status(scb, CAM_UNCOR_PARITY); @@ -1783,12 +1783,12 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) u_int i; ahc_print_path(ahc, scb); - printf("CDB:"); + printk("CDB:"); for (i = 0; i < scb->io_ctx->cmd_len; i++) - printf(" 0x%x", scb->io_ctx->cmnd[i]); - printf("\n"); + printk(" 0x%x", scb->io_ctx->cmnd[i]); + printk("\n"); ahc_print_path(ahc, scb); - printf("Saw underflow (%ld of %ld bytes). " + printk("Saw underflow (%ld of %ld bytes). " "Treated as error\n", ahc_get_residual(scb), ahc_get_transfer_length(scb)); @@ -1821,7 +1821,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) dev->commands_since_idle_or_otag = 0; if ((scb->flags & SCB_RECOVERY_SCB) != 0) { - printf("Recovery SCB completes\n"); + printk("Recovery SCB completes\n"); if (ahc_get_transaction_status(scb) == CAM_BDR_SENT || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); @@ -1886,14 +1886,14 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, if (ahc_debug & AHC_SHOW_SENSE) { int i; - printf("Copied %d bytes of sense data:", + printk("Copied %d bytes of sense data:", sense_size); for (i = 0; i < sense_size; i++) { if ((i & 0xF) == 0) - printf("\n"); - printf("0x%x ", cmd->sense_buffer[i]); + printk("\n"); + printk("0x%x ", cmd->sense_buffer[i]); } - printf("\n"); + printk("\n"); } #endif } @@ -1918,7 +1918,7 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, dev->openings = 0; /* ahc_print_path(ahc, scb); - printf("Dropping tag count to %d\n", dev->active); + printk("Dropping tag count to %d\n", dev->active); */ if (dev->active == dev->tags_on_last_queuefull) { @@ -1935,7 +1935,7 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, == AHC_LOCK_TAGS_COUNT) { dev->maxtags = dev->active; ahc_print_path(ahc, scb); - printf("Locking max tag count at %d\n", + printk("Locking max tag count at %d\n", dev->active); } } else { @@ -2100,10 +2100,10 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) scmd_printk(KERN_INFO, cmd, "Attempting to queue a%s message\n", flag == SCB_ABORT ? "n ABORT" : " TARGET RESET"); - printf("CDB:"); + printk("CDB:"); for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++) - printf(" 0x%x", cmd->cmnd[cdb_byte]); - printf("\n"); + printk(" 0x%x", cmd->cmnd[cdb_byte]); + printk("\n"); ahc_lock(ahc, &flags); @@ -2121,7 +2121,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) * No target device for this command exists, * so we must not still own the command. */ - printf("%s:%d:%d:%d: Is not an active device\n", + printk("%s:%d:%d:%d: Is not an active device\n", ahc_name(ahc), cmd->device->channel, cmd->device->id, cmd->device->lun); retval = SUCCESS; @@ -2133,7 +2133,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) cmd->device->channel + 'A', cmd->device->lun, CAM_REQ_ABORTED, SEARCH_COMPLETE) != 0) { - printf("%s:%d:%d:%d: Command found on untagged queue\n", + printk("%s:%d:%d:%d: Command found on untagged queue\n", ahc_name(ahc), cmd->device->channel, cmd->device->id, cmd->device->lun); retval = SUCCESS; @@ -2187,7 +2187,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) goto no_cmd; } - printf("%s: At time of recovery, card was %spaused\n", + printk("%s: At time of recovery, card was %spaused\n", ahc_name(ahc), was_paused ? "" : "not "); ahc_dump_card_state(ahc); @@ -2199,7 +2199,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) pending_scb->hscb->tag, ROLE_INITIATOR, CAM_REQ_ABORTED, SEARCH_COMPLETE) > 0) { - printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", + printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", ahc_name(ahc), cmd->device->channel, cmd->device->id, cmd->device->lun); retval = SUCCESS; @@ -2313,7 +2313,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) ahc_qinfifo_requeue_tail(ahc, pending_scb); ahc_outb(ahc, SCBPTR, saved_scbptr); ahc_print_path(ahc, pending_scb); - printf("Device is disconnected, re-queuing SCB\n"); + printk("Device is disconnected, re-queuing SCB\n"); wait = TRUE; } else { scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n"); @@ -2338,16 +2338,16 @@ done: ahc->platform_data->eh_done = &done; ahc_unlock(ahc, &flags); - printf("Recovery code sleeping\n"); + printk("Recovery code sleeping\n"); if (!wait_for_completion_timeout(&done, 5 * HZ)) { ahc_lock(ahc, &flags); ahc->platform_data->eh_done = NULL; ahc_unlock(ahc, &flags); - printf("Timer Expired\n"); + printk("Timer Expired\n"); retval = FAILED; } - printf("Recovery code awake\n"); + printk("Recovery code awake\n"); } else ahc_unlock(ahc, &flags); return (retval); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 56f07e527b48..bca0fb83f553 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -368,13 +368,6 @@ struct ahc_platform_data { resource_size_t mem_busaddr; /* Mem Base Addr */ }; -/************************** OS Utility Wrappers *******************************/ -#define printf printk -#define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 -#define malloc(size, type, flags) kmalloc(size, flags) -#define free(ptr, type) kfree(ptr) - void ahc_delay(long); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 78fc70c24e07..ee05e8410754 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -225,7 +225,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ahc_get_pci_bus(pci), ahc_get_pci_slot(pci), ahc_get_pci_function(pci)); - name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); + name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); if (name == NULL) return (-ENOMEM); strcpy(name, buf); @@ -412,7 +412,7 @@ ahc_pci_map_registers(struct ahc_softc *ahc) */ if (ahc_pci_test_register_access(ahc) != 0) { - printf("aic7xxx: PCI Device %d:%d:%d " + printk("aic7xxx: PCI Device %d:%d:%d " "failed memory mapped test. Using PIO.\n", ahc_get_pci_bus(ahc->dev_softc), ahc_get_pci_slot(ahc->dev_softc), @@ -425,7 +425,7 @@ ahc_pci_map_registers(struct ahc_softc *ahc) } else command |= PCIM_CMD_MEMEN; } else { - printf("aic7xxx: PCI%d:%d:%d MEM region 0x%llx " + printk("aic7xxx: PCI%d:%d:%d MEM region 0x%llx " "unavailable. Cannot memory map device.\n", ahc_get_pci_bus(ahc->dev_softc), ahc_get_pci_slot(ahc->dev_softc), @@ -444,7 +444,7 @@ ahc_pci_map_registers(struct ahc_softc *ahc) ahc->bsh.ioport = (u_long)base; command |= PCIM_CMD_PORTEN; } else { - printf("aic7xxx: PCI%d:%d:%d IO region 0x%llx[0..255] " + printk("aic7xxx: PCI%d:%d:%d IO region 0x%llx[0..255] " "unavailable. Cannot map device.\n", ahc_get_pci_bus(ahc->dev_softc), ahc_get_pci_slot(ahc->dev_softc), diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 27014b9de126..2b11a4272364 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -752,7 +752,7 @@ ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry) if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { if (bootverbose) - printf("%s: Enabling 39Bit Addressing\n", + printk("%s: Enabling 39Bit Addressing\n", ahc_name(ahc)); devconfig |= DACEN; } @@ -896,7 +896,7 @@ ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry) /* See if someone else set us up already */ if ((ahc->flags & AHC_NO_BIOS_INIT) == 0 && scsiseq != 0) { - printf("%s: Using left over BIOS settings\n", + printk("%s: Using left over BIOS settings\n", ahc_name(ahc)); ahc->flags &= ~AHC_USEDEFAULTS; ahc->flags |= AHC_BIOS_ENABLED; @@ -1155,7 +1155,7 @@ done: ahc_outb(ahc, CLRINT, CLRPARERR); ahc_outb(ahc, CLRINT, CLRBRKADRINT); if (bootverbose && enable) { - printf("%s: External SRAM, %s access%s, %dbytes/SCB\n", + printk("%s: External SRAM, %s access%s, %dbytes/SCB\n", ahc_name(ahc), fast ? "fast" : "slow", pcheck ? ", parity checking enabled" : "", large ? 64 : 32); @@ -1292,7 +1292,7 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) if (have_seeprom) { if (bootverbose) - printf("%s: Reading SEEPROM...", ahc_name(ahc)); + printk("%s: Reading SEEPROM...", ahc_name(ahc)); for (;;) { u_int start_addr; @@ -1309,9 +1309,9 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) if (have_seeprom != 0 || sd.sd_chip == C56_66) { if (bootverbose) { if (have_seeprom == 0) - printf ("checksum error\n"); + printk ("checksum error\n"); else - printf ("done.\n"); + printk ("done.\n"); } break; } @@ -1362,9 +1362,9 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) if (!have_seeprom) { if (bootverbose) - printf("%s: No SEEPROM available.\n", ahc_name(ahc)); + printk("%s: No SEEPROM available.\n", ahc_name(ahc)); ahc->flags |= AHC_USEDEFAULTS; - free(ahc->seep_config, M_DEVBUF); + kfree(ahc->seep_config); ahc->seep_config = NULL; sc = NULL; } else { @@ -1399,7 +1399,7 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) if ((sc->adapter_control & CFSTERM) != 0) *sxfrctl1 |= STPWEN; if (bootverbose) - printf("%s: Low byte termination %sabled\n", + printk("%s: Low byte termination %sabled\n", ahc_name(ahc), (*sxfrctl1 & STPWEN) ? "en" : "dis"); } @@ -1569,7 +1569,7 @@ configure_termination(struct ahc_softc *ahc, &eeprom_present); if ((adapter_control & CFSEAUTOTERM) == 0) { if (bootverbose) - printf("%s: Manual SE Termination\n", + printk("%s: Manual SE Termination\n", ahc_name(ahc)); enableSEC_low = (adapter_control & CFSELOWTERM); enableSEC_high = @@ -1577,7 +1577,7 @@ configure_termination(struct ahc_softc *ahc, } if ((adapter_control & CFAUTOTERM) == 0) { if (bootverbose) - printf("%s: Manual LVD Termination\n", + printk("%s: Manual LVD Termination\n", ahc_name(ahc)); enablePRI_low = (adapter_control & CFSTERM); enablePRI_high = (adapter_control & CFWSTERM); @@ -1604,19 +1604,19 @@ configure_termination(struct ahc_softc *ahc, if (bootverbose && (ahc->features & AHC_ULTRA2) == 0) { - printf("%s: internal 50 cable %s present", + printk("%s: internal 50 cable %s present", ahc_name(ahc), internal50_present ? "is":"not"); if ((ahc->features & AHC_WIDE) != 0) - printf(", internal 68 cable %s present", + printk(", internal 68 cable %s present", internal68_present ? "is":"not"); - printf("\n%s: external cable %s present\n", + printk("\n%s: external cable %s present\n", ahc_name(ahc), externalcable_present ? "is":"not"); } if (bootverbose) - printf("%s: BIOS eeprom %s present\n", + printk("%s: BIOS eeprom %s present\n", ahc_name(ahc), eeprom_present ? "is" : "not"); if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { @@ -1642,7 +1642,7 @@ configure_termination(struct ahc_softc *ahc, && (internal50_present != 0) && (internal68_present != 0) && (externalcable_present != 0)) { - printf("%s: Illegal cable configuration!!. " + printk("%s: Illegal cable configuration!!. " "Only two connectors on the " "adapter may be used at a " "time!\n", ahc_name(ahc)); @@ -1664,10 +1664,10 @@ configure_termination(struct ahc_softc *ahc, brddat |= BRDDAT6; if (bootverbose) { if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) - printf("%s: 68 pin termination " + printk("%s: 68 pin termination " "Enabled\n", ahc_name(ahc)); else - printf("%s: %sHigh byte termination " + printk("%s: %sHigh byte termination " "Enabled\n", ahc_name(ahc), enableSEC_high ? "Secondary " : ""); @@ -1683,10 +1683,10 @@ configure_termination(struct ahc_softc *ahc, *sxfrctl1 |= STPWEN; if (bootverbose) { if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) - printf("%s: 50 pin termination " + printk("%s: 50 pin termination " "Enabled\n", ahc_name(ahc)); else - printf("%s: %sLow byte termination " + printk("%s: %sLow byte termination " "Enabled\n", ahc_name(ahc), enableSEC_low ? "Secondary " : ""); @@ -1696,7 +1696,7 @@ configure_termination(struct ahc_softc *ahc, if (enablePRI_low != 0) { *sxfrctl1 |= STPWEN; if (bootverbose) - printf("%s: Primary Low Byte termination " + printk("%s: Primary Low Byte termination " "Enabled\n", ahc_name(ahc)); } @@ -1709,7 +1709,7 @@ configure_termination(struct ahc_softc *ahc, if (enablePRI_high != 0) { brddat |= BRDDAT4; if (bootverbose) - printf("%s: Primary High Byte " + printk("%s: Primary High Byte " "termination Enabled\n", ahc_name(ahc)); } @@ -1721,7 +1721,7 @@ configure_termination(struct ahc_softc *ahc, *sxfrctl1 |= STPWEN; if (bootverbose) - printf("%s: %sLow byte termination Enabled\n", + printk("%s: %sLow byte termination Enabled\n", ahc_name(ahc), (ahc->features & AHC_ULTRA2) ? "Primary " : ""); @@ -1731,7 +1731,7 @@ configure_termination(struct ahc_softc *ahc, && (ahc->features & AHC_WIDE) != 0) { brddat |= BRDDAT6; if (bootverbose) - printf("%s: %sHigh byte termination Enabled\n", + printk("%s: %sHigh byte termination Enabled\n", ahc_name(ahc), (ahc->features & AHC_ULTRA2) ? "Secondary " : ""); @@ -1937,29 +1937,29 @@ ahc_pci_intr(struct ahc_softc *ahc) status1 = ahc_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", + printk("%s: PCI error Interrupt at seqaddr = 0x%x\n", ahc_name(ahc), ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); if (status1 & DPE) { ahc->pci_target_perr_count++; - printf("%s: Data Parity Error Detected during address " + printk("%s: Data Parity Error Detected during address " "or write data phase\n", ahc_name(ahc)); } if (status1 & SSE) { - printf("%s: Signal System Error Detected\n", ahc_name(ahc)); + printk("%s: Signal System Error Detected\n", ahc_name(ahc)); } if (status1 & RMA) { - printf("%s: Received a Master Abort\n", ahc_name(ahc)); + printk("%s: Received a Master Abort\n", ahc_name(ahc)); } if (status1 & RTA) { - printf("%s: Received a Target Abort\n", ahc_name(ahc)); + printk("%s: Received a Target Abort\n", ahc_name(ahc)); } if (status1 & STA) { - printf("%s: Signaled a Target Abort\n", ahc_name(ahc)); + printk("%s: Signaled a Target Abort\n", ahc_name(ahc)); } if (status1 & DPR) { - printf("%s: Data Parity Error has been reported via PERR#\n", + printk("%s: Data Parity Error has been reported via PERR#\n", ahc_name(ahc)); } @@ -1968,14 +1968,14 @@ ahc_pci_intr(struct ahc_softc *ahc) status1, /*bytes*/1); if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { - printf("%s: Latched PCIERR interrupt with " + printk("%s: Latched PCIERR interrupt with " "no status bits set\n", ahc_name(ahc)); } else { ahc_outb(ahc, CLRINT, CLRPARERR); } if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) { - printf( + printk( "%s: WARNING WARNING WARNING WARNING\n" "%s: Too many PCI parity errors observed as a target.\n" "%s: Some device on this bus is generating bad parity.\n" @@ -2386,7 +2386,7 @@ ahc_aha29160C_setup(struct ahc_softc *ahc) static int ahc_raid_setup(struct ahc_softc *ahc) { - printf("RAID functionality unsupported\n"); + printk("RAID functionality unsupported\n"); return (ENXIO); } @@ -2404,7 +2404,7 @@ ahc_aha394XX_setup(struct ahc_softc *ahc) ahc->channel = 'B'; break; default: - printf("adapter at unexpected slot %d\n" + printk("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); ahc->channel = 'A'; @@ -2429,7 +2429,7 @@ ahc_aha398XX_setup(struct ahc_softc *ahc) ahc->channel = 'C'; break; default: - printf("adapter at unexpected slot %d\n" + printk("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); ahc->channel = 'A'; @@ -2459,7 +2459,7 @@ ahc_aha494XX_setup(struct ahc_softc *ahc) ahc->channel = 'D'; break; default: - printf("adapter at unexpected slot %d\n" + printk("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); ahc->channel = 'A'; diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index e92991a7c485..f2525f8ed1c7 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c @@ -248,13 +248,13 @@ ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length) ahc_pause(ahc); if (length != sizeof(struct seeprom_config)) { - printf("ahc_proc_write_seeprom: incorrect buffer size\n"); + printk("ahc_proc_write_seeprom: incorrect buffer size\n"); goto done; } have_seeprom = ahc_verify_cksum((struct seeprom_config*)buffer); if (have_seeprom == 0) { - printf("ahc_proc_write_seeprom: cksum verification failed\n"); + printk("ahc_proc_write_seeprom: cksum verification failed\n"); goto done; } @@ -290,26 +290,25 @@ ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length) sd.sd_DI = DI_2840; have_seeprom = TRUE; } else { - printf("ahc_proc_write_seeprom: unsupported adapter type\n"); + printk("ahc_proc_write_seeprom: unsupported adapter type\n"); goto done; } if (!have_seeprom) { - printf("ahc_proc_write_seeprom: No Serial EEPROM\n"); + printk("ahc_proc_write_seeprom: No Serial EEPROM\n"); goto done; } else { u_int start_addr; if (ahc->seep_config == NULL) { - ahc->seep_config = malloc(sizeof(*ahc->seep_config), - M_DEVBUF, M_NOWAIT); + ahc->seep_config = kmalloc(sizeof(*ahc->seep_config), GFP_ATOMIC); if (ahc->seep_config == NULL) { - printf("aic7xxx: Unable to allocate serial " + printk("aic7xxx: Unable to allocate serial " "eeprom buffer. Write failing\n"); goto done; } } - printf("aic7xxx: Writing Serial EEPROM\n"); + printk("aic7xxx: Writing Serial EEPROM\n"); start_addr = 32 * (ahc->channel - 'A'); ahc_write_seeprom(&sd, (u_int16_t *)buffer, start_addr, sizeof(struct seeprom_config)/2); -- cgit v1.2.3 From bbe56c734cc1ecccd7b2b143e1767bf2b1eafc76 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 27 Jul 2010 12:30:24 -0500 Subject: [SCSI] arcmsr: fix up bin_attr functions Commit commit 2c3c8bea608866d8bd9dcf92657d57fdcac011c5 Author: Chris Wright Date: Wed May 12 18:28:57 2010 -0700 sysfs: add struct file* to bin_attr callbacks Added an extra struct file * parameter at the beginning, which the arcmsr binary attribute additions didn't have. Fix this to prevent nasty crashes. Cc: Nick Cheng Signed-off-by: James Bottomley --- drivers/scsi/arcmsr/arcmsr_attr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 69f8346aa288..07fdfe57e38e 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -59,7 +59,8 @@ struct device_attribute *arcmsr_host_attrs[]; -static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, + struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) @@ -105,7 +106,8 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, return (allxfer_len); } -static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, + struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) @@ -153,7 +155,8 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, } } -static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp, + struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) -- cgit v1.2.3 From 457ff3b7dc3796d8778286217ad304ff122e948f Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:16:00 +0530 Subject: [SCSI] be2iscsi: Fix warnings from new checkpatch.pl The latest checkpatch.pl throws some new warnings. Fixing it to get rid of a bunch of warnings Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be.h | 6 +- drivers/scsi/be2iscsi/be_cmds.c | 24 +++---- drivers/scsi/be2iscsi/be_cmds.h | 20 +++--- drivers/scsi/be2iscsi/be_iscsi.c | 32 ++++----- drivers/scsi/be2iscsi/be_main.c | 141 ++++++++++++++++++++------------------- drivers/scsi/be2iscsi/be_main.h | 20 +++--- drivers/scsi/be2iscsi/be_mgmt.c | 6 +- 7 files changed, 126 insertions(+), 123 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 136b49cea791..1cb8a5e85c7f 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -128,8 +128,8 @@ struct be_ctrl_info { #define mcc_timeout 120000 /* 5s timeout */ /* Returns number of pages spanned by the data starting at the given addr */ -#define PAGES_4K_SPANNED(_address, size) \ - ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \ +#define PAGES_4K_SPANNED(_address, size) \ + ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \ (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K)) /* Byte offset into the page corresponding to given address */ @@ -137,7 +137,7 @@ struct be_ctrl_info { ((size_t)(addr) & (PAGE_SIZE_4K-1)) /* Returns bit offset within a DWORD of a bitfield */ -#define AMAP_BIT_OFFSET(_struct, field) \ +#define AMAP_BIT_OFFSET(_struct, field) \ (((size_t)&(((_struct *)0)->field))%32) /* Returns the bit mask of the field that is NOT shifted into location. */ diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index cda6642c7368..4f19030c1e3e 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -151,20 +151,20 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, { switch (evt->port_link_status) { case ASYNC_EVENT_LINK_DOWN: - SE_DEBUG(DBG_LVL_1, "Link Down on Physical Port %d \n", - evt->physical_port); + SE_DEBUG(DBG_LVL_1, "Link Down on Physical Port %d\n", + evt->physical_port); phba->state |= BE_ADAPTER_LINK_DOWN; iscsi_host_for_each_session(phba->shost, be2iscsi_fail_session); break; case ASYNC_EVENT_LINK_UP: phba->state = BE_ADAPTER_UP; - SE_DEBUG(DBG_LVL_1, "Link UP on Physical Port %d \n", + SE_DEBUG(DBG_LVL_1, "Link UP on Physical Port %d\n", evt->physical_port); break; default: SE_DEBUG(DBG_LVL_1, "Unexpected Async Notification %d on" - "Physical Port %d \n", + "Physical Port %d\n", evt->port_link_status, evt->physical_port); } @@ -199,7 +199,7 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) else SE_DEBUG(DBG_LVL_1, " Unsupported Async Event, flags" - " = 0x%08x \n", compl->flags); + " = 0x%08x\n", compl->flags); } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { status = be_mcc_compl_process(ctrl, compl); @@ -286,7 +286,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) status = be_mbox_db_ready_wait(ctrl); if (status != 0) { - SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 1\n"); + SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed\n"); return status; } val = 0; @@ -297,14 +297,14 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) status = be_mbox_db_ready_wait(ctrl); if (status != 0) { - SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 2\n"); + SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed\n"); return status; } if (be_mcc_compl_is_new(compl)) { status = be_mcc_compl_process(ctrl, &mbox->compl); be_mcc_compl_use(compl); if (status) { - SE_DEBUG(DBG_LVL_1, "After be_mcc_compl_process \n"); + SE_DEBUG(DBG_LVL_1, "After be_mcc_compl_process\n"); return status; } } else { @@ -500,7 +500,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) status = be_mbox_notify(ctrl); if (status) - SE_DEBUG(DBG_LVL_1, "be_cmd_fw_initialize Failed \n"); + SE_DEBUG(DBG_LVL_1, "be_cmd_fw_initialize Failed\n"); spin_unlock(&ctrl->mbox_lock); return status; @@ -517,7 +517,7 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, void *ctxt = &req->context; int status; - SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_cq_create \n"); + SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_cq_create\n"); spin_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); @@ -550,7 +550,7 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, cq->id = le16_to_cpu(resp->cq_id); cq->created = true; } else - SE_DEBUG(DBG_LVL_1, "In be_cmd_cq_create, status=ox%08x \n", + SE_DEBUG(DBG_LVL_1, "In be_cmd_cq_create, status=ox%08x\n", status); spin_unlock(&ctrl->mbox_lock); @@ -619,7 +619,7 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, u8 subsys = 0, opcode = 0; int status; - SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_q_destroy \n"); + SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_q_destroy\n"); spin_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 49fcc787ee8b..f94df6cdebc8 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -47,8 +47,8 @@ struct be_mcc_wrb { #define CQE_FLAGS_VALID_MASK (1 << 31) #define CQE_FLAGS_ASYNC_MASK (1 << 30) -#define CQE_FLAGS_COMPLETED_MASK (1 << 28) -#define CQE_FLAGS_CONSUMED_MASK (1 << 27) +#define CQE_FLAGS_COMPLETED_MASK (1 << 28) +#define CQE_FLAGS_CONSUMED_MASK (1 << 27) /* Completion Status */ #define MCC_STATUS_SUCCESS 0x0 @@ -143,14 +143,14 @@ struct be_mcc_mailbox { */ #define OPCODE_COMMON_CQ_CREATE 12 #define OPCODE_COMMON_EQ_CREATE 13 -#define OPCODE_COMMON_MCC_CREATE 21 -#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32 +#define OPCODE_COMMON_MCC_CREATE 21 +#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32 #define OPCODE_COMMON_GET_FW_VERSION 35 #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 #define OPCODE_COMMON_FIRMWARE_CONFIG 42 -#define OPCODE_COMMON_MCC_DESTROY 53 -#define OPCODE_COMMON_CQ_DESTROY 54 -#define OPCODE_COMMON_EQ_DESTROY 55 +#define OPCODE_COMMON_MCC_DESTROY 53 +#define OPCODE_COMMON_CQ_DESTROY 54 +#define OPCODE_COMMON_EQ_DESTROY 55 #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 #define OPCODE_COMMON_FUNCTION_RESET 61 @@ -164,9 +164,9 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7 #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61 #define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64 -#define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 +#define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 #define OPCODE_COMMON_ISCSI_WRBQ_CREATE 66 -#define OPCODE_COMMON_ISCSI_WRBQ_DESTROY 67 +#define OPCODE_COMMON_ISCSI_WRBQ_DESTROY 67 struct be_cmd_req_hdr { u8 opcode; /* dword 0 */ @@ -875,7 +875,7 @@ struct be_fw_cfg { */ #define UNSOL_HDR_NOTIFY 28 /* Unsolicited header notify.*/ #define UNSOL_DATA_NOTIFY 29 /* Unsolicited data notify.*/ -#define UNSOL_DATA_DIGEST_ERROR_NOTIFY 30 /* Unsolicited data digest +#define UNSOL_DATA_DIGEST_ERROR_NOTIFY 30 /* Unsolicited data digest * error notify. */ #define DRIVERMSG_NOTIFY 31 /* TCP acknowledge based diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 454027ccbf16..d9321ee01534 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -52,7 +52,7 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, SE_DEBUG(DBG_LVL_8, "In beiscsi_session_create\n"); if (!ep) { - SE_DEBUG(DBG_LVL_1, "beiscsi_session_create: invalid ep \n"); + SE_DEBUG(DBG_LVL_1, "beiscsi_session_create: invalid ep\n"); return NULL; } beiscsi_ep = ep->dd_data; @@ -157,7 +157,7 @@ static int beiscsi_bindconn_cid(struct beiscsi_hba *phba, "Connection table already occupied. Detected clash\n"); return -EINVAL; } else { - SE_DEBUG(DBG_LVL_8, "phba->conn_table[%d]=%p(beiscsi_conn) \n", + SE_DEBUG(DBG_LVL_8, "phba->conn_table[%d]=%p(beiscsi_conn)\n", cid, beiscsi_conn); phba->conn_table[cid] = beiscsi_conn; } @@ -196,7 +196,7 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, if (beiscsi_ep->phba != phba) { SE_DEBUG(DBG_LVL_8, - "beiscsi_ep->hba=%p not equal to phba=%p \n", + "beiscsi_ep->hba=%p not equal to phba=%p\n", beiscsi_ep->phba, phba); return -EEXIST; } @@ -204,7 +204,7 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; beiscsi_conn->ep = beiscsi_ep; beiscsi_ep->conn = beiscsi_conn; - SE_DEBUG(DBG_LVL_8, "beiscsi_conn=%p conn=%p ep_cid=%d \n", + SE_DEBUG(DBG_LVL_8, "beiscsi_conn=%p conn=%p ep_cid=%d\n", beiscsi_conn, conn, beiscsi_ep->ep_cid); return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid); } @@ -308,7 +308,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, case ISCSI_HOST_PARAM_HWADDRESS: tag = be_cmd_get_mac_addr(phba); if (!tag) { - SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed \n"); + SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); return -1; } else wait_event_interruptible(phba->ctrl.mcc_wait[tag], @@ -319,7 +319,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; if (status || extd_status) { SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" - " status = %d extd_status = %d \n", + " status = %d extd_status = %d\n", status, extd_status); free_mcc_tag(&phba->ctrl, tag); return -1; @@ -493,7 +493,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, SE_DEBUG(DBG_LVL_1, "No free cid available\n"); return ret; } - SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ", + SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d\n", beiscsi_ep->ep_cid); phba->ep_array[beiscsi_ep->ep_cid - phba->fw_config.iscsi_cid_start] = ep; @@ -507,7 +507,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep); if (!tag) { SE_DEBUG(DBG_LVL_1, - "mgmt_open_connection Failed for cid=%d \n", + "mgmt_open_connection Failed for cid=%d\n", beiscsi_ep->ep_cid); } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], @@ -526,7 +526,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, wrb = queue_get_wrb(mccq, wrb_num); free_mcc_tag(&phba->ctrl, tag); - ptcpcnct_out = embedded_payload(wrb); + ptcpcnct_out = embedded_payload(wrb); beiscsi_ep = ep->dd_data; beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; beiscsi_ep->cid_vld = 1; @@ -556,18 +556,18 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, struct iscsi_endpoint *ep; int ret; - SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect \n"); + SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect\n"); if (shost) phba = iscsi_host_priv(shost); else { ret = -ENXIO; - SE_DEBUG(DBG_LVL_1, "shost is NULL \n"); + SE_DEBUG(DBG_LVL_1, "shost is NULL\n"); return ERR_PTR(ret); } if (phba->state != BE_ADAPTER_UP) { ret = -EBUSY; - SE_DEBUG(DBG_LVL_1, "The Adapter state is Not UP \n"); + SE_DEBUG(DBG_LVL_1, "The Adapter state is Not UP\n"); return ERR_PTR(ret); } @@ -581,7 +581,7 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, beiscsi_ep->phba = phba; beiscsi_ep->openiscsi_ep = ep; if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) { - SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn \n"); + SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn\n"); ret = -ENOMEM; goto free_ep; } @@ -624,7 +624,7 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag); if (!tag) { - SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x", + SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x\n", beiscsi_ep->ep_cid); ret = -1; } else { @@ -646,7 +646,7 @@ static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba, if (phba->conn_table[cid]) phba->conn_table[cid] = NULL; else { - SE_DEBUG(DBG_LVL_8, "Connection table Not occupied. \n"); + SE_DEBUG(DBG_LVL_8, "Connection table Not occupied.\n"); return -EINVAL; } return 0; @@ -687,7 +687,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) savecfg_flag); if (!tag) { SE_DEBUG(DBG_LVL_1, - "mgmt_invalidate_connection Failed for cid=%d \n", + "mgmt_invalidate_connection Failed for cid=%d\n", beiscsi_ep->ep_cid); } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 0d35bf6c6acc..001888b0c842 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -216,7 +216,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) shost = iscsi_host_alloc(&beiscsi_sht, sizeof(*phba), 0); if (!shost) { dev_err(&pcidev->dev, "beiscsi_hba_alloc -" - "iscsi_host_alloc failed \n"); + "iscsi_host_alloc failed\n"); return NULL; } shost->dma_boundary = pcidev->dma_mask; @@ -371,7 +371,7 @@ static void beiscsi_get_params(struct beiscsi_hba *phba) + BE2_TMFS) / 512) + 1) * 512; phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024) ? 1024 : phba->params.num_eq_entries; - SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d \n", + SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d\n", phba->params.num_eq_entries); phba->params.num_cq_entries = (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2 @@ -692,7 +692,7 @@ beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, break; default: shost_printk(KERN_WARNING, phba->shost, - "Unrecognized opcode 0x%x in async msg \n", + "Unrecognized opcode 0x%x in async msg\n", (ppdu-> dw[offsetof(struct amap_pdu_base, opcode) / 32] & PDUBASE_OPCODE_MASK)); @@ -711,7 +711,7 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) if (phba->io_sgl_hndl_avbl) { SE_DEBUG(DBG_LVL_8, - "In alloc_io_sgl_handle,io_sgl_alloc_index=%d \n", + "In alloc_io_sgl_handle,io_sgl_alloc_index=%d\n", phba->io_sgl_alloc_index); psgl_handle = phba->io_sgl_hndl_base[phba-> io_sgl_alloc_index]; @@ -730,7 +730,7 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) static void free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) { - SE_DEBUG(DBG_LVL_8, "In free_,io_sgl_free_index=%d \n", + SE_DEBUG(DBG_LVL_8, "In free_,io_sgl_free_index=%d\n", phba->io_sgl_free_index); if (phba->io_sgl_hndl_base[phba->io_sgl_free_index]) { /* @@ -739,7 +739,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) */ SE_DEBUG(DBG_LVL_8, "Double Free in IO SGL io_sgl_free_index=%d," - "value there=%p \n", phba->io_sgl_free_index, + "value there=%p\n", phba->io_sgl_free_index, phba->io_sgl_hndl_base[phba->io_sgl_free_index]); return; } @@ -804,7 +804,7 @@ free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, SE_DEBUG(DBG_LVL_8, "FREE WRB: pwrb_handle=%p free_index=0x%x" - "wrb_handles_available=%d \n", + "wrb_handles_available=%d\n", pwrb_handle, pwrb_context->free_index, pwrb_context->wrb_handles_available); } @@ -816,7 +816,7 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) if (phba->eh_sgl_hndl_avbl) { psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index]; phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL; - SE_DEBUG(DBG_LVL_8, "mgmt_sgl_alloc_index=%d=0x%x \n", + SE_DEBUG(DBG_LVL_8, "mgmt_sgl_alloc_index=%d=0x%x\n", phba->eh_sgl_alloc_index, phba->eh_sgl_alloc_index); phba->eh_sgl_hndl_avbl--; if (phba->eh_sgl_alloc_index == @@ -834,7 +834,7 @@ void free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) { - SE_DEBUG(DBG_LVL_8, "In free_mgmt_sgl_handle,eh_sgl_free_index=%d \n", + SE_DEBUG(DBG_LVL_8, "In free_mgmt_sgl_handle,eh_sgl_free_index=%d\n", phba->eh_sgl_free_index); if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) { /* @@ -842,7 +842,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) * failed in xmit_task or alloc_pdu. */ SE_DEBUG(DBG_LVL_8, - "Double Free in eh SGL ,eh_sgl_free_index=%d \n", + "Double Free in eh SGL ,eh_sgl_free_index=%d\n", phba->eh_sgl_free_index); return; } @@ -1081,7 +1081,7 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, case HWH_TYPE_LOGIN: SE_DEBUG(DBG_LVL_1, "\t\t No HWH_TYPE_LOGIN Expected in hwi_complete_cmd" - "- Solicited path \n"); + "- Solicited path\n"); break; case HWH_TYPE_NOP: @@ -1164,7 +1164,7 @@ hwi_get_async_handle(struct beiscsi_hba *phba, default: pbusy_list = NULL; shost_printk(KERN_WARNING, phba->shost, - "Unexpected code=%d \n", + "Unexpected code=%d\n", pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, code) / 32] & PDUCQE_CODE_MASK); return NULL; @@ -1552,7 +1552,7 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) else SE_DEBUG(DBG_LVL_1, " Unsupported Async Event, flags" - " = 0x%08x \n", mcc_compl->flags); + " = 0x%08x\n", mcc_compl->flags); } else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) { be_mcc_compl_process_isr(&phba->ctrl, mcc_compl); atomic_dec(&phba->ctrl.mcc_obj.q.used); @@ -1611,7 +1611,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) hwi_complete_cmd(beiscsi_conn, phba, sol); break; case DRIVERMSG_NOTIFY: - SE_DEBUG(DBG_LVL_8, "Received DRIVERMSG_NOTIFY \n"); + SE_DEBUG(DBG_LVL_8, "Received DRIVERMSG_NOTIFY\n"); dmsg = (struct dmsg_cqe *)sol; hwi_complete_drvr_msgs(beiscsi_conn, phba, sol); break; @@ -1782,9 +1782,9 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, sg_len = sg_dma_len(sg); addr = (u64) sg_dma_address(sg); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, - (addr & 0xFFFFFFFF)); + ((u32)(addr & 0xFFFFFFFF))); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, - (addr >> 32)); + ((u32)(addr >> 32))); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, sg_len); sge_len = sg_len; @@ -1794,9 +1794,9 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, sg_len = sg_dma_len(sg); addr = (u64) sg_dma_address(sg); AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_lo, pwrb, - (addr & 0xFFFFFFFF)); + ((u32)(addr & 0xFFFFFFFF))); AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_hi, pwrb, - (addr >> 32)); + ((u32)(addr >> 32))); AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_len, pwrb, sg_len); } @@ -1872,9 +1872,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) addr = 0; } AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, - (addr & 0xFFFFFFFF)); + ((u32)(addr & 0xFFFFFFFF))); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, - (addr >> 32)); + ((u32)(addr >> 32))); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, task->data_count); @@ -1904,9 +1904,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) psgl++; if (task->data) { AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, - (addr & 0xFFFFFFFF)); + ((u32)(addr & 0xFFFFFFFF))); AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, - (addr >> 32)); + ((u32)(addr >> 32))); } AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106); } @@ -2054,7 +2054,8 @@ free_mem: mem_descr->mem_array[j - 1].size, mem_descr->mem_array[j - 1]. virtual_address, - mem_descr->mem_array[j - 1]. + (unsigned long)mem_descr-> + mem_array[j - 1]. bus_address.u.a64.address); } if (i) { @@ -2223,10 +2224,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) if (mem_descr->mem_array[0].virtual_address) { SE_DEBUG(DBG_LVL_8, "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_BUF" - "va=%p \n", mem_descr->mem_array[0].virtual_address); + "va=%p\n", mem_descr->mem_array[0].virtual_address); } else shost_printk(KERN_WARNING, phba->shost, - "No Virtual address \n"); + "No Virtual address\n"); pasync_ctx->async_header.va_base = mem_descr->mem_array[0].virtual_address; @@ -2239,10 +2240,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) if (mem_descr->mem_array[0].virtual_address) { SE_DEBUG(DBG_LVL_8, "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_RING" - "va=%p \n", mem_descr->mem_array[0].virtual_address); + "va=%p\n", mem_descr->mem_array[0].virtual_address); } else shost_printk(KERN_WARNING, phba->shost, - "No Virtual address \n"); + "No Virtual address\n"); pasync_ctx->async_header.ring_base = mem_descr->mem_array[0].virtual_address; @@ -2251,10 +2252,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) if (mem_descr->mem_array[0].virtual_address) { SE_DEBUG(DBG_LVL_8, "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_HANDLE" - "va=%p \n", mem_descr->mem_array[0].virtual_address); + "va=%p\n", mem_descr->mem_array[0].virtual_address); } else shost_printk(KERN_WARNING, phba->shost, - "No Virtual address \n"); + "No Virtual address\n"); pasync_ctx->async_header.handle_base = mem_descr->mem_array[0].virtual_address; @@ -2266,10 +2267,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) if (mem_descr->mem_array[0].virtual_address) { SE_DEBUG(DBG_LVL_8, "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_BUF" - "va=%p \n", mem_descr->mem_array[0].virtual_address); + "va=%p\n", mem_descr->mem_array[0].virtual_address); } else shost_printk(KERN_WARNING, phba->shost, - "No Virtual address \n"); + "No Virtual address\n"); pasync_ctx->async_data.va_base = mem_descr->mem_array[0].virtual_address; pasync_ctx->async_data.pa_base.u.a64.address = @@ -2280,10 +2281,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) if (mem_descr->mem_array[0].virtual_address) { SE_DEBUG(DBG_LVL_8, "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_RING" - "va=%p \n", mem_descr->mem_array[0].virtual_address); + "va=%p\n", mem_descr->mem_array[0].virtual_address); } else shost_printk(KERN_WARNING, phba->shost, - "No Virtual address \n"); + "No Virtual address\n"); pasync_ctx->async_data.ring_base = mem_descr->mem_array[0].virtual_address; @@ -2292,7 +2293,7 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) mem_descr += HWI_MEM_ASYNC_DATA_HANDLE; if (!mem_descr->mem_array[0].virtual_address) shost_printk(KERN_WARNING, phba->shost, - "No Virtual address \n"); + "No Virtual address\n"); pasync_ctx->async_data.handle_base = mem_descr->mem_array[0].virtual_address; @@ -2364,7 +2365,7 @@ be_sgl_create_contiguous(void *virtual_address, WARN_ON(!sgl); sgl->va = virtual_address; - sgl->dma = physical_address; + sgl->dma = (unsigned long)physical_address; sgl->size = length; return 0; @@ -2447,7 +2448,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, sizeof(struct be_eq_entry), eq_vaddress); if (ret) { shost_printk(KERN_ERR, phba->shost, - "be_fill_queue Failed for EQ \n"); + "be_fill_queue Failed for EQ\n"); goto create_eq_error; } @@ -2457,7 +2458,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, if (ret) { shost_printk(KERN_ERR, phba->shost, "beiscsi_cmd_eq_create" - "Failedfor EQ \n"); + "Failedfor EQ\n"); goto create_eq_error; } SE_DEBUG(DBG_LVL_8, "eqid = %d\n", phwi_context->be_eq[i].q.id); @@ -2505,7 +2506,7 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba, sizeof(struct sol_cqe), cq_vaddress); if (ret) { shost_printk(KERN_ERR, phba->shost, - "be_fill_queue Failed for ISCSI CQ \n"); + "be_fill_queue Failed for ISCSI CQ\n"); goto create_cq_error; } @@ -2515,7 +2516,7 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba, if (ret) { shost_printk(KERN_ERR, phba->shost, "beiscsi_cmd_eq_create" - "Failed for ISCSI CQ \n"); + "Failed for ISCSI CQ\n"); goto create_cq_error; } SE_DEBUG(DBG_LVL_8, "iscsi cq_id is %d for eq_id %d\n", @@ -2565,7 +2566,8 @@ beiscsi_create_def_hdr(struct beiscsi_hba *phba, "be_fill_queue Failed for DEF PDU HDR\n"); return ret; } - mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address; + mem->dma = (unsigned long)mem_descr->mem_array[idx]. + bus_address.u.a64.address; ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq, def_pdu_ring_sz, phba->params.defpdu_hdr_sz); @@ -2609,7 +2611,8 @@ beiscsi_create_def_data(struct beiscsi_hba *phba, "be_fill_queue Failed for DEF PDU DATA\n"); return ret; } - mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address; + mem->dma = (unsigned long)mem_descr->mem_array[idx]. + bus_address.u.a64.address; ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq, def_pdu_ring_sz, phba->params.defpdu_data_sz); @@ -2623,7 +2626,7 @@ beiscsi_create_def_data(struct beiscsi_hba *phba, SE_DEBUG(DBG_LVL_8, "iscsi def data id is %d\n", phwi_context->be_def_dataq.id); hwi_post_async_buffers(phba, 0); - SE_DEBUG(DBG_LVL_8, "DEFAULT PDU DATA RING CREATED \n"); + SE_DEBUG(DBG_LVL_8, "DEFAULT PDU DATA RING CREATED\n"); return 0; } @@ -2655,7 +2658,7 @@ beiscsi_post_pages(struct beiscsi_hba *phba) } pm_arr++; } - SE_DEBUG(DBG_LVL_8, "POSTED PAGES \n"); + SE_DEBUG(DBG_LVL_8, "POSTED PAGES\n"); return 0; } @@ -2885,7 +2888,7 @@ static int find_num_cpus(void) if (num_cpus >= MAX_CPUS) num_cpus = MAX_CPUS - 1; - SE_DEBUG(DBG_LVL_8, "num_cpus = %d \n", num_cpus); + SE_DEBUG(DBG_LVL_8, "num_cpus = %d\n", num_cpus); return num_cpus; } @@ -2908,7 +2911,7 @@ static int hwi_init_port(struct beiscsi_hba *phba) status = beiscsi_create_eqs(phba, phwi_context); if (status != 0) { - shost_printk(KERN_ERR, phba->shost, "EQ not created \n"); + shost_printk(KERN_ERR, phba->shost, "EQ not created\n"); goto error; } @@ -2919,7 +2922,7 @@ static int hwi_init_port(struct beiscsi_hba *phba) status = mgmt_check_supported_fw(ctrl, phba); if (status != 0) { shost_printk(KERN_ERR, phba->shost, - "Unsupported fw version \n"); + "Unsupported fw version\n"); goto error; } @@ -2975,7 +2978,7 @@ static int hwi_init_controller(struct beiscsi_hba *phba) if (1 == phba->init_mem[HWI_MEM_ADDN_CONTEXT].num_elements) { phwi_ctrlr->phwi_ctxt = (struct hwi_context_memory *)phba-> init_mem[HWI_MEM_ADDN_CONTEXT].mem_array[0].virtual_address; - SE_DEBUG(DBG_LVL_8, " phwi_ctrlr->phwi_ctxt=%p \n", + SE_DEBUG(DBG_LVL_8, " phwi_ctrlr->phwi_ctxt=%p\n", phwi_ctrlr->phwi_ctxt); } else { shost_printk(KERN_ERR, phba->shost, @@ -3008,8 +3011,8 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba) pci_free_consistent(phba->pcidev, mem_descr->mem_array[j - 1].size, mem_descr->mem_array[j - 1].virtual_address, - mem_descr->mem_array[j - 1].bus_address. - u.a64.address); + (unsigned long)mem_descr->mem_array[j - 1]. + bus_address.u.a64.address); } kfree(mem_descr->mem_array); mem_descr++; @@ -3025,7 +3028,7 @@ static int beiscsi_init_controller(struct beiscsi_hba *phba) ret = beiscsi_get_memory(phba); if (ret < 0) { shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe -" - "Failed in beiscsi_alloc_memory \n"); + "Failed in beiscsi_alloc_memory\n"); return ret; } @@ -3102,12 +3105,12 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) } SE_DEBUG(DBG_LVL_8, "phba->io_sgl_hndl_avbl=%d" - "phba->eh_sgl_hndl_avbl=%d \n", + "phba->eh_sgl_hndl_avbl=%d\n", phba->io_sgl_hndl_avbl, phba->eh_sgl_hndl_avbl); mem_descr_sg = phba->init_mem; mem_descr_sg += HWI_MEM_SGE; - SE_DEBUG(DBG_LVL_8, "\n mem_descr_sg->num_elements=%d \n", + SE_DEBUG(DBG_LVL_8, "\n mem_descr_sg->num_elements=%d\n", mem_descr_sg->num_elements); arr_index = 0; idx = 0; @@ -3156,7 +3159,7 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) if (!phba->ep_array) { shost_printk(KERN_ERR, phba->shost, "Failed to allocate memory in " - "hba_setup_cid_tbls \n"); + "hba_setup_cid_tbls\n"); kfree(phba->cid_array); return -ENOMEM; } @@ -3185,21 +3188,21 @@ static unsigned char hwi_enable_intr(struct beiscsi_hba *phba) addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); reg = ioread32(addr); - SE_DEBUG(DBG_LVL_8, "reg =x%08x \n", reg); + SE_DEBUG(DBG_LVL_8, "reg =x%08x\n", reg); enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; if (!enabled) { reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; - SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr); + SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p\n", reg, addr); iowrite32(reg, addr); if (!phba->msix_enabled) { eq = &phwi_context->be_eq[0].q; - SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); + SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id); hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); } else { for (i = 0; i <= phba->num_cpus; i++) { eq = &phwi_context->be_eq[i].q; - SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); + SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id); hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); } } @@ -3220,7 +3223,7 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) iowrite32(reg, addr); } else shost_printk(KERN_WARNING, phba->shost, - "In hwi_disable_intr, Already Disabled \n"); + "In hwi_disable_intr, Already Disabled\n"); } static int beiscsi_init_port(struct beiscsi_hba *phba) @@ -3231,14 +3234,14 @@ static int beiscsi_init_port(struct beiscsi_hba *phba) if (ret < 0) { shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe - Failed in" - "beiscsi_init_controller \n"); + "beiscsi_init_controller\n"); return ret; } ret = beiscsi_init_sgl_handle(phba); if (ret < 0) { shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe - Failed in" - "beiscsi_init_sgl_handle \n"); + "beiscsi_init_sgl_handle\n"); goto do_cleanup_ctrlr; } @@ -3297,7 +3300,7 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba) mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0); if (mgmt_status) shost_printk(KERN_WARNING, phba->shost, - "mgmt_epfw_cleanup FAILED \n"); + "mgmt_epfw_cleanup FAILED\n"); hwi_purge_eq(phba); hwi_cleanup(phba); @@ -3487,7 +3490,7 @@ free_hndls: io_task->pwrb_handle = NULL; pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, io_task->bhs_pa.u.a64.address); - SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed \n"); + SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed\n"); return -ENOMEM; } @@ -3654,7 +3657,7 @@ static int beiscsi_mtask(struct iscsi_task *task) break; default: - SE_DEBUG(DBG_LVL_1, "opcode =%d Not supported \n", + SE_DEBUG(DBG_LVL_1, "opcode =%d Not supported\n", task->hdr->opcode & ISCSI_OPCODE_MASK); return -EINVAL; } @@ -3696,7 +3699,7 @@ static int beiscsi_task_xmit(struct iscsi_task *task) sg = scsi_sglist(sc); if (sc->sc_data_direction == DMA_TO_DEVICE) { writedir = 1; - SE_DEBUG(DBG_LVL_4, "task->imm_count=0x%08x \n", + SE_DEBUG(DBG_LVL_4, "task->imm_count=0x%08x\n", task->imm_count); } else writedir = 0; @@ -3713,7 +3716,7 @@ static void beiscsi_remove(struct pci_dev *pcidev) phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); if (!phba) { - dev_err(&pcidev->dev, "beiscsi_remove called with no phba \n"); + dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n"); return; } @@ -3782,7 +3785,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, phba = beiscsi_hba_alloc(pcidev); if (!phba) { dev_err(&pcidev->dev, "beiscsi_dev_probe-" - " Failed in beiscsi_hba_alloc \n"); + " Failed in beiscsi_hba_alloc\n"); goto disable_pci; } @@ -3805,7 +3808,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, else num_cpus = 1; phba->num_cpus = num_cpus; - SE_DEBUG(DBG_LVL_8, "num_cpus = %d \n", phba->num_cpus); + SE_DEBUG(DBG_LVL_8, "num_cpus = %d\n", phba->num_cpus); if (enable_msix) beiscsi_msix_enable(phba); @@ -3877,7 +3880,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, "Failed to hwi_enable_intr\n"); goto free_ctrlr; } - SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED \n\n\n"); + SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); return 0; free_ctrlr: @@ -3989,7 +3992,7 @@ static int __init beiscsi_module_init(void) "transport.\n"); return -ENOMEM; } - SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p \n", + SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p\n", &beiscsi_iscsi_transport); ret = pci_register_driver(&beiscsi_pci_driver); diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 87ec21280a37..e6ddddbbae7a 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -39,7 +39,7 @@ "Linux iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" -#define BE_VENDOR_ID 0x19A2 +#define BE_VENDOR_ID 0x19A2 /* DEVICE ID's for BE2 */ #define BE_DEVICE_ID1 0x212 #define OC_DEVICE_ID1 0x702 @@ -68,8 +68,8 @@ #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ #define BEISCSI_NUM_DEVICES_SUPPORTED 0x01 #define BEISCSI_MAX_FRAGS_INIT 192 -#define BE_NUM_MSIX_ENTRIES 1 -#define MPU_EP_SEMAPHORE 0xac +#define BE_NUM_MSIX_ENTRIES 1 +#define MPU_EP_SEMAPHORE 0xac #define BE_SENSE_INFO_SIZE 258 #define BE_ISCSI_PDU_HEADER_SIZE 64 @@ -105,7 +105,7 @@ do { \ #define HWI_GET_ASYNC_PDU_CTX(phwi) (phwi->phwi_ctxt->pasync_ctx) /********* Memory BAR register ************/ -#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc +#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc /** * Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt * Disable" may still globally block interrupts in addition to individual @@ -116,7 +116,7 @@ do { \ #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ /********* ISR0 Register offset **********/ -#define CEV_ISR0_OFFSET 0xC18 +#define CEV_ISR0_OFFSET 0xC18 #define CEV_ISR_SIZE 4 /** @@ -139,12 +139,12 @@ do { \ #define DB_EQ_REARM_SHIFT (29) /* bit 29 */ /********* Compl Q door bell *************/ -#define DB_CQ_OFFSET 0x120 +#define DB_CQ_OFFSET 0x120 #define DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ /* Number of event entries processed */ -#define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ +#define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ /* Rearm bit */ -#define DB_CQ_REARM_SHIFT (29) /* bit 29 */ +#define DB_CQ_REARM_SHIFT (29) /* bit 29 */ #define GET_HWI_CONTROLLER_WS(pc) (pc->phwi_ctrlr) #define HWI_GET_DEF_BUFQ_ID(pc) (((struct hwi_controller *)\ @@ -161,12 +161,12 @@ enum be_mem_enum { HWI_MEM_WRBH, HWI_MEM_SGLH, HWI_MEM_SGE, - HWI_MEM_ASYNC_HEADER_BUF, /* 5 */ + HWI_MEM_ASYNC_HEADER_BUF, /* 5 */ HWI_MEM_ASYNC_DATA_BUF, HWI_MEM_ASYNC_HEADER_RING, HWI_MEM_ASYNC_DATA_RING, HWI_MEM_ASYNC_HEADER_HANDLE, - HWI_MEM_ASYNC_DATA_HANDLE, /* 10 */ + HWI_MEM_ASYNC_DATA_HANDLE, /* 10 */ HWI_MEM_ASYNC_PDU_CONTEXT, ISCSI_MEM_GLOBAL_HEADER, SE_MEM_MAX diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 350cbeaae160..7d4ac5c1a868 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -58,7 +58,7 @@ unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, } } else { shost_printk(KERN_WARNING, phba->shost, - "Failed in mgmt_get_fw_config \n"); + "Failed in mgmt_get_fw_config\n"); } spin_unlock(&ctrl->mbox_lock); @@ -167,7 +167,7 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, &nonemb_cmd.dma); if (nonemb_cmd.va == NULL) { SE_DEBUG(DBG_LVL_1, - "Failed to allocate memory for mgmt_invalidate_icds\n"); + "Failed to alloc memory for mgmt_invalidate_icds\n"); spin_unlock(&ctrl->mbox_lock); return 0; } @@ -339,7 +339,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, if (phba->nxt_cqid == phba->num_cpus) phba->nxt_cqid = 0; req->cq_id = phwi_context->be_cq[i].id; - SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d \n", i, req->cq_id); + SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d\n", i, req->cq_id); req->defq_id = def_hdr_id; req->hdr_ring_id = def_hdr_id; req->data_ring_id = def_data_id; -- cgit v1.2.3 From d3ad2bb31c26d7314fad98da8abb04f4fa24ed16 Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:16:38 +0530 Subject: [SCSI] be2iscsi: Fixing return values This patch fixes the return values as per comment from Mike Christie Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_cmds.c | 12 ++++++------ drivers/scsi/be2iscsi/be_iscsi.c | 12 ++++++------ drivers/scsi/be2iscsi/be_main.c | 4 ++-- drivers/scsi/be2iscsi/be_mgmt.c | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 4f19030c1e3e..9cc1f5573150 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -98,7 +98,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, dev_err(&ctrl->pdev->dev, "error in cmd completion: status(compl/extd)=%d/%d\n", compl_status, extd_status); - return -1; + return -EBUSY; } return 0; } @@ -231,7 +231,7 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba) } if (i == mcc_timeout) { dev_err(&phba->pcidev->dev, "mccq poll timed out\n"); - return -1; + return -EBUSY; } return 0; } @@ -257,7 +257,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) if (cnt > 6000000) { dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n"); - return -1; + return -EBUSY; } if (cnt > 50) { @@ -309,7 +309,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) } } else { dev_err(&ctrl->pdev->dev, "invalid mailbox completion\n"); - return -1; + return -EBUSY; } return 0; } @@ -355,7 +355,7 @@ static int be_mbox_notify_wait(struct beiscsi_hba *phba) return status; } else { dev_err(&phba->pcidev->dev, "invalid mailbox completion\n"); - return -1; + return -EBUSY; } return 0; } @@ -652,7 +652,7 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, default: spin_unlock(&ctrl->mbox_lock); BUG(); - return -1; + return -ENXIO; } be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); if (queue_type != QTYPE_SGL) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index d9321ee01534..cd1b8301036d 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -230,7 +230,7 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, if (!beiscsi_ep) { SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_get_param , no beiscsi_ep\n"); - return -1; + return -ENODEV; } switch (param) { @@ -309,7 +309,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, tag = be_cmd_get_mac_addr(phba); if (!tag) { SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); - return -1; + return -EAGAIN; } else wait_event_interruptible(phba->ctrl.mcc_wait[tag], phba->ctrl.mcc_numtag[tag]); @@ -322,7 +322,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, " status = %d extd_status = %d\n", status, extd_status); free_mcc_tag(&phba->ctrl, tag); - return -1; + return -EAGAIN; } else { wrb = queue_get_wrb(mccq, wrb_num); free_mcc_tag(&phba->ctrl, tag); @@ -485,7 +485,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, struct tcp_connect_and_offload_out *ptcpcnct_out; unsigned short status, extd_status; unsigned int tag, wrb_num; - int ret = -1; + int ret = -ENOMEM; SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn\n"); beiscsi_ep->ep_cid = beiscsi_get_cid(phba); @@ -536,7 +536,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, free_ep: beiscsi_free_ep(beiscsi_ep); - return -1; + return -EBUSY; } /** @@ -626,7 +626,7 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) if (!tag) { SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x\n", beiscsi_ep->ep_cid); - ret = -1; + ret = -EAGAIN; } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], phba->ctrl.mcc_numtag[tag]); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 001888b0c842..e6259d7498f3 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -2681,7 +2681,7 @@ static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q, mem->size = len * entry_size; mem->va = pci_alloc_consistent(phba->pcidev, mem->size, &mem->dma); if (!mem->va) - return -1; + return -ENOMEM; memset(mem->va, 0, mem->size); return 0; } @@ -2877,7 +2877,7 @@ mcc_cq_destroy: mcc_cq_free: be_queue_free(phba, cq); err: - return -1; + return -ENOMEM; } static int find_num_cpus(void) diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 7d4ac5c1a868..ff8b1cd6fec4 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -81,7 +81,7 @@ unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl, SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for mgmt_check_supported_fw" "\n"); - return -1; + return -ENOMEM; } nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); req = nonemb_cmd.va; -- cgit v1.2.3 From 03a1231009927b7168d6d86a7a7f6c7f9b4be85a Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:17:16 +0530 Subject: [SCSI] be2iscsi: Fixing the return type of functions Fixing some functions return values that did not match with the possible return values Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_cmds.h | 2 +- drivers/scsi/be2iscsi/be_main.c | 2 +- drivers/scsi/be2iscsi/be_mgmt.c | 13 ++++++------- drivers/scsi/be2iscsi/be_mgmt.h | 10 +++++----- 4 files changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index f94df6cdebc8..30a293f52ef7 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -423,7 +423,7 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba, struct be_queue_info *cq); int be_poll_mcc(struct be_ctrl_info *ctrl); -unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl, +int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba); void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index e6259d7498f3..3b54dc72371e 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3295,7 +3295,7 @@ static void hwi_purge_eq(struct beiscsi_hba *phba) static void beiscsi_clean_port(struct beiscsi_hba *phba) { - unsigned char mgmt_status; + int mgmt_status; mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0); if (mgmt_status) diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index ff8b1cd6fec4..dcb70fac2fce 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -21,7 +21,7 @@ #include "be_mgmt.h" #include "be_iscsi.h" -unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, +int mgmt_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) { struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); @@ -65,7 +65,7 @@ unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, return status; } -unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl, +int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) { struct be_dma_mem nonemb_cmd; @@ -117,8 +117,7 @@ unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl, return status; } - -unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) +int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) { struct be_ctrl_info *ctrl = &phba->ctrl; struct be_mcc_wrb *wrb = wrb_from_mccq(phba); @@ -144,7 +143,7 @@ unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) return status; } -unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, +unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, struct invalidate_command_table *inv_tbl, unsigned int num_invalidate, unsigned int cid) { @@ -202,7 +201,7 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, return tag; } -unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, +unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, struct beiscsi_endpoint *beiscsi_ep, unsigned short cid, unsigned short issue_reset, @@ -239,7 +238,7 @@ unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, return tag; } -unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, +unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, unsigned short cid, unsigned int upload_flag) { struct be_ctrl_info *ctrl = &phba->ctrl; diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 3d316b82feb1..74b885a4b836 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h @@ -86,14 +86,14 @@ struct mcc_wrb { struct mcc_wrb_payload payload; }; -unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute); +int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute); int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr, struct beiscsi_endpoint *beiscsi_ep); -unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, +unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, unsigned short cid, unsigned int upload_flag); -unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, +unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, struct invalidate_command_table *inv_tbl, unsigned int num_invalidate, unsigned int cid); @@ -237,10 +237,10 @@ struct beiscsi_endpoint { u16 cid_vld; }; -unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, +int mgmt_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); -unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, +unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, struct beiscsi_endpoint *beiscsi_ep, unsigned short cid, unsigned short issue_reset, -- cgit v1.2.3 From f5ed7bd4c6ca5fcec77d3007779d38f63cbb95f4 Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:18:01 +0530 Subject: [SCSI] be2iscsi: pass the return from beiscsi_open_conn This patch passes on the value returned by beiscsi_open_conn Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_iscsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index cd1b8301036d..4f3c2a4079df 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -580,9 +580,9 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, beiscsi_ep = ep->dd_data; beiscsi_ep->phba = phba; beiscsi_ep->openiscsi_ep = ep; - if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) { + ret = beiscsi_open_conn(ep, NULL, dst_addr, non_blocking); + if (ret) { SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn\n"); - ret = -ENOMEM; goto free_ep; } -- cgit v1.2.3 From 1f92638f074f7c6776fb2b565f252573f2b5488c Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:22:27 +0530 Subject: [SCSI] be2iscsi: Fix for freeing cid This patch frees up the allocated cid and returns error if allocation of tag fails. Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_iscsi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 4f3c2a4079df..de79b7cf804d 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -509,6 +509,8 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed for cid=%d\n", beiscsi_ep->ep_cid); + beiscsi_put_cid(phba, beiscsi_ep->ep_cid); + return -EAGAIN; } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], phba->ctrl.mcc_numtag[tag]); -- cgit v1.2.3 From 238f6b7255c68d2774795c97b32701c09fd1e543 Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:23:22 +0530 Subject: [SCSI] be2iscsi: No return value for hwi_enable_intr hwi_enable_intr need not return any value. This patch fixes the that and removes code designed to handle a failure return value Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 3b54dc72371e..26ac049c0c85 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3172,7 +3172,7 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) return 0; } -static unsigned char hwi_enable_intr(struct beiscsi_hba *phba) +static void hwi_enable_intr(struct beiscsi_hba *phba) { struct be_ctrl_info *ctrl = &phba->ctrl; struct hwi_controller *phwi_ctrlr; @@ -3207,7 +3207,6 @@ static unsigned char hwi_enable_intr(struct beiscsi_hba *phba) } } } - return true; } static void hwi_disable_intr(struct beiscsi_hba *phba) @@ -3773,7 +3772,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, struct hwi_controller *phwi_ctrlr; struct hwi_context_memory *phwi_context; struct be_eq_obj *pbe_eq; - int ret, msix_vec, num_cpus, i; + int ret, num_cpus, i; ret = beiscsi_enable_pci(pcidev); if (ret < 0) { @@ -3874,25 +3873,10 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, "Failed to beiscsi_init_irqs\n"); goto free_blkenbld; } - ret = hwi_enable_intr(phba); - if (ret < 0) { - shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" - "Failed to hwi_enable_intr\n"); - goto free_ctrlr; - } + hwi_enable_intr(phba); SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); return 0; -free_ctrlr: - if (phba->msix_enabled) { - for (i = 0; i <= phba->num_cpus; i++) { - msix_vec = phba->msix_entries[i].vector; - free_irq(msix_vec, &phwi_context->be_eq[i]); - } - } else - if (phba->pcidev->irq) - free_irq(phba->pcidev->irq, phba); - pci_disable_msix(phba->pcidev); free_blkenbld: destroy_workqueue(phba->wq); if (blk_iopoll_enabled) @@ -3910,6 +3894,8 @@ free_port: phba->ctrl.mbox_mem_alloced.dma); beiscsi_unmap_pci_function(phba); hba_free: + if (phba->msix_enabled) + pci_disable_msix(phba->pcidev); iscsi_host_remove(phba->shost); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); -- cgit v1.2.3 From 4f5af07e1bc4ae64b7a7ead5bf60f40a3115ceeb Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:23:55 +0530 Subject: [SCSI] be2iscsi: Fix to handle request_irq failure This patch handles request_irq failures by properly cleaning up Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 26ac049c0c85..67a7e3f7bae6 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -616,7 +616,7 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) struct pci_dev *pcidev = phba->pcidev; struct hwi_controller *phwi_ctrlr; struct hwi_context_memory *phwi_context; - int ret, msix_vec, i = 0; + int ret, msix_vec, i, j; char desc[32]; phwi_ctrlr = phba->phwi_ctrlr; @@ -628,10 +628,25 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) msix_vec = phba->msix_entries[i].vector; ret = request_irq(msix_vec, be_isr_msix, 0, desc, &phwi_context->be_eq[i]); + if (ret) { + shost_printk(KERN_ERR, phba->shost, + "beiscsi_init_irqs-Failed to" + "register msix for i = %d\n", i); + if (!i) + return ret; + goto free_msix_irqs; + } } msix_vec = phba->msix_entries[i].vector; ret = request_irq(msix_vec, be_isr_mcc, 0, "beiscsi_msix_mcc", &phwi_context->be_eq[i]); + if (ret) { + shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-" + "Failed to register beiscsi_msix_mcc\n"); + i++; + goto free_msix_irqs; + } + } else { ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, "beiscsi", phba); @@ -642,6 +657,10 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) } } return 0; +free_msix_irqs: + for (j = i - 1; j == 0; j++) + free_irq(msix_vec, &phwi_context->be_eq[j]); + return ret; } static void hwi_ring_cq_db(struct beiscsi_hba *phba, -- cgit v1.2.3 From 5db3f33d687c5a4ba589bf3af98c786399c6e213 Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:24:22 +0530 Subject: [SCSI] be2iscsi: Free tags allocated This patch frees tags that are already allocated in case of failure Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_mgmt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index dcb70fac2fce..3036d9ee7902 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -168,6 +168,7 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, SE_DEBUG(DBG_LVL_1, "Failed to alloc memory for mgmt_invalidate_icds\n"); spin_unlock(&ctrl->mbox_lock); + free_mcc_tag(&phba->ctrl, tag); return 0; } nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); @@ -330,6 +331,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n", dst_addr->sa_family); spin_unlock(&ctrl->mbox_lock); + free_mcc_tag(&phba->ctrl, tag); return -EINVAL; } -- cgit v1.2.3 From e9b911935033ea9e28a2f7a274c9a81db1f8d91a Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:24:53 +0530 Subject: [SCSI] be2iscsi: Adding crashdump support These changes allow the driver to support crashdump. We need to reset the chip incase of a crashdump Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_cmds.c | 80 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/be2iscsi/be_cmds.h | 3 ++ drivers/scsi/be2iscsi/be_main.c | 50 ++++++++++++++++++++++++++ drivers/scsi/be2iscsi/be_main.h | 9 ++++- 4 files changed, 141 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 9cc1f5573150..7c7537335c88 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -19,6 +19,86 @@ #include "be_mgmt.h" #include "be_main.h" +int beiscsi_pci_soft_reset(struct beiscsi_hba *phba) +{ + u32 sreset; + u8 *pci_reset_offset = 0; + u8 *pci_online0_offset = 0; + u8 *pci_online1_offset = 0; + u32 pconline0 = 0; + u32 pconline1 = 0; + u32 i; + + pci_reset_offset = (u8 *)phba->pci_va + BE2_SOFT_RESET; + pci_online0_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE0; + pci_online1_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE1; + sreset = readl((void *)pci_reset_offset); + sreset |= BE2_SET_RESET; + writel(sreset, (void *)pci_reset_offset); + + i = 0; + while (sreset & BE2_SET_RESET) { + if (i > 64) + break; + msleep(100); + sreset = readl((void *)pci_reset_offset); + i++; + } + + if (sreset & BE2_SET_RESET) { + printk(KERN_ERR "Soft Reset did not deassert\n"); + return -EIO; + } + pconline1 = BE2_MPU_IRAM_ONLINE; + writel(pconline0, (void *)pci_online0_offset); + writel(pconline1, (void *)pci_online1_offset); + + sreset = BE2_SET_RESET; + writel(sreset, (void *)pci_reset_offset); + + i = 0; + while (sreset & BE2_SET_RESET) { + if (i > 64) + break; + msleep(1); + sreset = readl((void *)pci_reset_offset); + i++; + } + if (sreset & BE2_SET_RESET) { + printk(KERN_ERR "MPU Online Soft Reset did not deassert\n"); + return -EIO; + } + return 0; +} + +int be_chk_reset_complete(struct beiscsi_hba *phba) +{ + unsigned int num_loop; + u8 *mpu_sem = 0; + u32 status; + + num_loop = 1000; + mpu_sem = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; + msleep(5000); + + while (num_loop) { + status = readl((void *)mpu_sem); + + if ((status & 0x80000000) || (status & 0x0000FFFF) == 0xC000) + break; + msleep(60); + num_loop--; + } + + if ((status & 0x80000000) || (!num_loop)) { + printk(KERN_ERR "Failed in be_chk_reset_complete" + "status = 0x%x\n", status); + return -EIO; + } + + return 0; +} + void be_mcc_notify(struct beiscsi_hba *phba) { struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 30a293f52ef7..0df19cb58a39 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -901,6 +901,9 @@ struct be_fw_cfg { * the cxn */ +int beiscsi_pci_soft_reset(struct beiscsi_hba *phba); +int be_chk_reset_complete(struct beiscsi_hba *phba); + void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, bool embedded, u8 sge_cnt); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 67a7e3f7bae6..1a22125f5202 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -41,6 +41,8 @@ static unsigned int be_iopoll_budget = 10; static unsigned int be_max_phys_size = 64; static unsigned int enable_msix = 1; +static unsigned int gcrashmode = 0; +static unsigned int num_hba = 0; MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR); @@ -3731,6 +3733,8 @@ static void beiscsi_remove(struct pci_dev *pcidev) struct hwi_context_memory *phwi_context; struct be_eq_obj *pbe_eq; unsigned int i, msix_vec; + u8 *real_offset = 0; + u32 value = 0; phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); if (!phba) { @@ -3759,6 +3763,14 @@ static void beiscsi_remove(struct pci_dev *pcidev) beiscsi_clean_port(phba); beiscsi_free_mem(phba); + real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; + + value = readl((void *)real_offset); + + if (value & 0x00010000) { + value &= 0xfffeffff; + writel(value, (void *)real_offset); + } beiscsi_unmap_pci_function(phba); pci_free_consistent(phba->pcidev, phba->ctrl.mbox_mem_alloced.size, @@ -3792,6 +3804,8 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, struct hwi_context_memory *phwi_context; struct be_eq_obj *pbe_eq; int ret, num_cpus, i; + u8 *real_offset = 0; + u32 value = 0; ret = beiscsi_enable_pci(pcidev); if (ret < 0) { @@ -3837,6 +3851,33 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, goto hba_free; } + if (!num_hba) { + real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; + value = readl((void *)real_offset); + if (value & 0x00010000) { + gcrashmode++; + shost_printk(KERN_ERR, phba->shost, + "Loading Driver in crashdump mode\n"); + ret = beiscsi_pci_soft_reset(phba); + if (ret) { + shost_printk(KERN_ERR, phba->shost, + "Reset Failed. Aborting Crashdump\n"); + goto hba_free; + } + ret = be_chk_reset_complete(phba); + if (ret) { + shost_printk(KERN_ERR, phba->shost, + "Failed to get out of reset." + "Aborting Crashdump\n"); + goto hba_free; + } + } else { + value |= 0x00010000; + writel(value, (void *)real_offset); + num_hba++; + } + } + spin_lock_init(&phba->io_sgl_lock); spin_lock_init(&phba->mgmt_sgl_lock); spin_lock_init(&phba->isr_lock); @@ -3907,6 +3948,15 @@ free_twq: beiscsi_clean_port(phba); beiscsi_free_mem(phba); free_port: + real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; + + value = readl((void *)real_offset); + + if (value & 0x00010000) { + value &= 0xfffeffff; + writel(value, (void *)real_offset); + } + pci_free_consistent(phba->pcidev, phba->ctrl.mbox_mem_alloced.size, phba->ctrl.mbox_mem_alloced.va, diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index e6ddddbbae7a..05ad76e48d80 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -69,7 +69,14 @@ #define BEISCSI_NUM_DEVICES_SUPPORTED 0x01 #define BEISCSI_MAX_FRAGS_INIT 192 #define BE_NUM_MSIX_ENTRIES 1 -#define MPU_EP_SEMAPHORE 0xac + +#define MPU_EP_CONTROL 0 +#define MPU_EP_SEMAPHORE 0xac +#define BE2_SOFT_RESET 0x5c +#define BE2_PCI_ONLINE0 0xb0 +#define BE2_PCI_ONLINE1 0xb4 +#define BE2_SET_RESET 0x80 +#define BE2_MPU_IRAM_ONLINE 0x00000080 #define BE_SENSE_INFO_SIZE 258 #define BE_ISCSI_PDU_HEADER_SIZE 64 -- cgit v1.2.3 From d2cecf0dcb2eb066756e0303d9f162ebe20d0591 Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:25:40 +0530 Subject: [SCSI] be2iscsi: Maintain same ITT across login This patch ensures that the same ITT is maintained across all login pdu's Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 41 ++++++++++++++++++++++++++++++++++++----- drivers/scsi/be2iscsi/be_main.h | 1 + 2 files changed, 37 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 1a22125f5202..fdd9161096c1 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3452,14 +3452,12 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) return -ENOMEM; io_task->bhs_pa.u.a64.address = paddr; io_task->libiscsi_itt = (itt_t)task->itt; - io_task->pwrb_handle = alloc_wrb_handle(phba, - beiscsi_conn->beiscsi_conn_cid - - phba->fw_config.iscsi_cid_start - ); io_task->conn = beiscsi_conn; task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr; task->hdr_max = sizeof(struct be_cmd_bhs); + io_task->psgl_handle = NULL; + io_task->psgl_handle = NULL; if (task->sc) { spin_lock(&phba->io_sgl_lock); @@ -3467,6 +3465,11 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) spin_unlock(&phba->io_sgl_lock); if (!io_task->psgl_handle) goto free_hndls; + io_task->pwrb_handle = alloc_wrb_handle(phba, + beiscsi_conn->beiscsi_conn_cid - + phba->fw_config.iscsi_cid_start); + if (!io_task->pwrb_handle) + goto free_io_hndls; } else { io_task->scsi_cmnd = NULL; if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { @@ -3481,9 +3484,20 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) beiscsi_conn->login_in_progress = 1; beiscsi_conn->plogin_sgl_handle = io_task->psgl_handle; + io_task->pwrb_handle = + alloc_wrb_handle(phba, + beiscsi_conn->beiscsi_conn_cid - + phba->fw_config.iscsi_cid_start); + if (!io_task->pwrb_handle) + goto free_io_hndls; + beiscsi_conn->plogin_wrb_handle = + io_task->pwrb_handle; + } else { io_task->psgl_handle = beiscsi_conn->plogin_sgl_handle; + io_task->pwrb_handle = + beiscsi_conn->plogin_wrb_handle; } } else { spin_lock(&phba->mgmt_sgl_lock); @@ -3491,6 +3505,13 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) spin_unlock(&phba->mgmt_sgl_lock); if (!io_task->psgl_handle) goto free_hndls; + io_task->pwrb_handle = + alloc_wrb_handle(phba, + beiscsi_conn->beiscsi_conn_cid - + phba->fw_config.iscsi_cid_start); + if (!io_task->pwrb_handle) + goto free_mgmt_hndls; + } } itt = (itt_t) cpu_to_be32(((unsigned int)io_task->pwrb_handle-> @@ -3501,12 +3522,22 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) io_task->cmd_bhs->iscsi_hdr.itt = itt; return 0; +free_io_hndls: + spin_lock(&phba->io_sgl_lock); + free_io_sgl_handle(phba, io_task->psgl_handle); + spin_unlock(&phba->io_sgl_lock); + goto free_hndls; +free_mgmt_hndls: + spin_lock(&phba->mgmt_sgl_lock); + free_mgmt_sgl_handle(phba, io_task->psgl_handle); + spin_unlock(&phba->mgmt_sgl_lock); free_hndls: phwi_ctrlr = phba->phwi_ctrlr; pwrb_context = &phwi_ctrlr->wrb_context[ beiscsi_conn->beiscsi_conn_cid - phba->fw_config.iscsi_cid_start]; - free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); + if (io_task->pwrb_handle) + free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); io_task->pwrb_handle = NULL; pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, io_task->bhs_pa.u.a64.address); diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 05ad76e48d80..08996d008ba6 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -359,6 +359,7 @@ struct beiscsi_conn { u32 beiscsi_conn_cid; struct beiscsi_endpoint *ep; unsigned short login_in_progress; + struct wrb_handle *plogin_wrb_handle; struct sgl_handle *plogin_sgl_handle; struct beiscsi_session *beiscsi_sess; struct iscsi_task *task; -- cgit v1.2.3 From 42f43c419e1881b543faf20182cad0f789b73d2f Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:26:45 +0530 Subject: [SCSI] be2iscsi: Limit max_xmit_length This patch limits max_xmit_length to 64K incase older utilities are used Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_iscsi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index de79b7cf804d..a131a576a102 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -277,6 +277,10 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, if (session->max_burst > 262144) session->max_burst = 262144; break; + case ISCSI_PARAM_MAX_XMIT_DLENGTH: + if ((conn->max_xmit_dlength > 65536) || + (conn->max_xmit_dlength == 0)) + conn->max_xmit_dlength = 65536; default: return 0; } -- cgit v1.2.3 From 0aa094331b19e54f928e2ac083285ff68d91c69b Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:27:16 +0530 Subject: [SCSI] be2iscsi: Remove debug print in IO path This patch removes a Debug Print in the IO path Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index fdd9161096c1..b70b4ba72076 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3744,8 +3744,6 @@ static int beiscsi_task_xmit(struct iscsi_task *task) SE_DEBUG(DBG_LVL_1, " scsi_dma_map Failed\n") return num_sg; } - SE_DEBUG(DBG_LVL_4, "xferlen=0x%08x scmd=%p num_sg=%d sernum=%lu\n", - (scsi_bufflen(sc)), sc, num_sg, sc->serial_number); xferlen = scsi_bufflen(sc); sg = scsi_sglist(sc); if (sc->sc_data_direction == DMA_TO_DEVICE) { -- cgit v1.2.3 From 3cbb7a74a76e45f5e410367259844e8266fba6ec Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:27:47 +0530 Subject: [SCSI] be2iscsi: Fix for premature buffer free This patch fixes a bug where the buffer was being freed as soon as submission to HW is done. Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_iscsi.c | 24 ++++++++++++++++++++- drivers/scsi/be2iscsi/be_main.c | 41 ++++++++++++++++++++++++++++++++---- drivers/scsi/be2iscsi/be_mgmt.c | 45 +++++++++++++++++++--------------------- drivers/scsi/be2iscsi/be_mgmt.h | 9 +++++--- 4 files changed, 87 insertions(+), 32 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index a131a576a102..6d63e7b312cf 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -488,6 +488,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, struct be_mcc_wrb *wrb; struct tcp_connect_and_offload_out *ptcpcnct_out; unsigned short status, extd_status; + struct be_dma_mem nonemb_cmd; unsigned int tag, wrb_num; int ret = -ENOMEM; @@ -504,16 +505,31 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl * 2)) { SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); + beiscsi_put_cid(phba, beiscsi_ep->ep_cid); goto free_ep; } beiscsi_ep->cid_vld = 0; - tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep); + nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, + sizeof(struct tcp_connect_and_offload_in), + &nonemb_cmd.dma); + if (nonemb_cmd.va == NULL) { + SE_DEBUG(DBG_LVL_1, + "Failed to allocate memory for mgmt_open_connection" + "\n"); + beiscsi_put_cid(phba, beiscsi_ep->ep_cid); + return -ENOMEM; + } + nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in); + memset(nonemb_cmd.va, 0, nonemb_cmd.size); + tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd); if (!tag) { SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed for cid=%d\n", beiscsi_ep->ep_cid); beiscsi_put_cid(phba, beiscsi_ep->ep_cid); + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); return -EAGAIN; } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], @@ -526,7 +542,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed" " status = %d extd_status = %d\n", status, extd_status); + beiscsi_put_cid(phba, beiscsi_ep->ep_cid); free_mcc_tag(&phba->ctrl, tag); + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); goto free_ep; } else { wrb = queue_get_wrb(mccq, wrb_num); @@ -538,6 +557,9 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, beiscsi_ep->cid_vld = 1; SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); } + beiscsi_put_cid(phba, beiscsi_ep->ep_cid); + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); return 0; free_ep: diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index b70b4ba72076..7436c5ad5697 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -71,6 +71,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) struct beiscsi_hba *phba; struct iscsi_session *session; struct invalidate_command_table *inv_tbl; + struct be_dma_mem nonemb_cmd; unsigned int cid, tag, num_invalidate; cls_session = starget_to_session(scsi_target(sc->device)); @@ -101,18 +102,34 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) inv_tbl->cid = cid; inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; num_invalidate = 1; - tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); + nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, + sizeof(struct invalidate_commands_params_in), + &nonemb_cmd.dma); + if (nonemb_cmd.va == NULL) { + SE_DEBUG(DBG_LVL_1, + "Failed to allocate memory for" + "mgmt_invalidate_icds\n"); + return FAILED; + } + nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); + + tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, + cid, &nonemb_cmd); if (!tag) { shost_printk(KERN_WARNING, phba->shost, "mgmt_invalidate_icds could not be" " submitted\n"); + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); + return FAILED; } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], phba->ctrl.mcc_numtag[tag]); free_mcc_tag(&phba->ctrl, tag); } - + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); return iscsi_eh_abort(sc); } @@ -126,6 +143,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) struct iscsi_session *session; struct iscsi_cls_session *cls_session; struct invalidate_command_table *inv_tbl; + struct be_dma_mem nonemb_cmd; unsigned int cid, tag, i, num_invalidate; int rc = FAILED; @@ -160,18 +178,33 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) spin_unlock_bh(&session->lock); inv_tbl = phba->inv_tbl; - tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); + nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, + sizeof(struct invalidate_commands_params_in), + &nonemb_cmd.dma); + if (nonemb_cmd.va == NULL) { + SE_DEBUG(DBG_LVL_1, + "Failed to allocate memory for" + "mgmt_invalidate_icds\n"); + return FAILED; + } + nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); + memset(nonemb_cmd.va, 0, nonemb_cmd.size); + tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, + cid, &nonemb_cmd); if (!tag) { shost_printk(KERN_WARNING, phba->shost, "mgmt_invalidate_icds could not be" " submitted\n"); + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); return FAILED; } else { wait_event_interruptible(phba->ctrl.mcc_wait[tag], phba->ctrl.mcc_numtag[tag]); free_mcc_tag(&phba->ctrl, tag); } - + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); return iscsi_eh_device_reset(sc); unlock: spin_unlock_bh(&session->lock); diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 3036d9ee7902..3f3fab91a7d1 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -50,7 +50,7 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, pfw_cfg->ulp[0].sq_count; if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { SE_DEBUG(DBG_LVL_8, - "FW reported MAX CXNS as %d \t" + "FW reported MAX CXNS as %d\t" "Max Supported = %d.\n", phba->fw_config.iscsi_cid_count, BE2_MAX_SESSIONS); @@ -145,9 +145,10 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, struct invalidate_command_table *inv_tbl, - unsigned int num_invalidate, unsigned int cid) + unsigned int num_invalidate, unsigned int cid, + struct be_dma_mem *nonemb_cmd) + { - struct be_dma_mem nonemb_cmd; struct be_ctrl_info *ctrl = &phba->ctrl; struct be_mcc_wrb *wrb; struct be_sge *sge; @@ -161,18 +162,7 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, return tag; } - nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, - sizeof(struct invalidate_commands_params_in), - &nonemb_cmd.dma); - if (nonemb_cmd.va == NULL) { - SE_DEBUG(DBG_LVL_1, - "Failed to alloc memory for mgmt_invalidate_icds\n"); - spin_unlock(&ctrl->mbox_lock); - free_mcc_tag(&phba->ctrl, tag); - return 0; - } - nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); - req = nonemb_cmd.va; + req = nonemb_cmd->va; memset(req, 0, sizeof(*req)); wrb = wrb_from_mccq(phba); sge = nonembedded_sgl(wrb); @@ -190,15 +180,12 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, req->icd_count++; inv_tbl++; } - sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); - sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); - sge->len = cpu_to_le32(nonemb_cmd.size); + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); be_mcc_notify(phba); spin_unlock(&ctrl->mbox_lock); - if (nonemb_cmd.va) - pci_free_consistent(ctrl->pdev, nonemb_cmd.size, - nonemb_cmd.va, nonemb_cmd.dma); return tag; } @@ -269,7 +256,9 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr, - struct beiscsi_endpoint *beiscsi_ep) + struct beiscsi_endpoint *beiscsi_ep, + struct be_dma_mem *nonemb_cmd) + { struct hwi_controller *phwi_ctrlr; struct hwi_context_memory *phwi_context; @@ -285,6 +274,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, unsigned int tag = 0; unsigned int i; unsigned short cid = beiscsi_ep->ep_cid; + struct be_sge *sge; phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; @@ -300,10 +290,14 @@ int mgmt_open_connection(struct beiscsi_hba *phba, return tag; } wrb = wrb_from_mccq(phba); - req = embedded_payload(wrb); + memset(wrb, 0, sizeof(*wrb)); + sge = nonembedded_sgl(wrb); + + req = nonemb_cmd->va; + memset(req, 0, sizeof(*req)); wrb->tag0 |= tag; - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 1); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, sizeof(*req)); @@ -347,6 +341,9 @@ int mgmt_open_connection(struct beiscsi_hba *phba, req->do_offload = 1; req->dataout_template_pa.lo = ptemplate_address->lo; req->dataout_template_pa.hi = ptemplate_address->hi; + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); be_mcc_notify(phba); spin_unlock(&ctrl->mbox_lock); return tag; diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 74b885a4b836..b9acedf78653 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h @@ -87,15 +87,18 @@ struct mcc_wrb { }; int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute); -int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr, - struct beiscsi_endpoint *beiscsi_ep); +int mgmt_open_connection(struct beiscsi_hba *phba, + struct sockaddr *dst_addr, + struct beiscsi_endpoint *beiscsi_ep, + struct be_dma_mem *nonemb_cmd); unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, unsigned short cid, unsigned int upload_flag); unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, struct invalidate_command_table *inv_tbl, - unsigned int num_invalidate, unsigned int cid); + unsigned int num_invalidate, unsigned int cid, + struct be_dma_mem *nonemb_cmd); struct iscsi_invalidate_connection_params_in { struct be_cmd_req_hdr hdr; -- cgit v1.2.3 From b38c1e8bd19340e1a5b712287a8d61da26225d5b Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:28:13 +0530 Subject: [SCSI] be2iscsi: The extended shift must be 16 Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_cmds.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 0df19cb58a39..40641d0845f4 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -56,7 +56,7 @@ struct be_mcc_wrb { #define CQE_STATUS_COMPL_MASK 0xFFFF #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ #define CQE_STATUS_EXTD_MASK 0xFFFF -#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */ +#define CQE_STATUS_EXTD_SHIFT 16 /* bits 0 - 15 */ struct be_mcc_compl { u32 status; /* dword 0 */ -- cgit v1.2.3 From 82c57028e4bf6e2755de91b36223f57406746fa8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 May 2010 10:29:52 -0700 Subject: [SCSI] scsi: add Kconfig dependency on NET be2iscsi driver should #include linux/if_ether.h since it uses sysfs_format_mac(). It should also depend on NET since it selects SCSI_ISCSI_ATTRS, which depends on NET. These changes fix a build error when CONFIG_NET is not enabled: ERROR: "sysfs_format_mac" [drivers/scsi/be2iscsi/be2iscsi.ko] undefined! Signed-off-by: Randy Dunlap Acked-by: Jayamohan Kallickal Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/Kconfig | 2 +- drivers/scsi/be2iscsi/be_main.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig index 2952fcd008ea..84c275fb9f6b 100644 --- a/drivers/scsi/be2iscsi/Kconfig +++ b/drivers/scsi/be2iscsi/Kconfig @@ -1,6 +1,6 @@ config BE2ISCSI tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2" - depends on PCI && SCSI + depends on PCI && SCSI && NET select SCSI_ISCSI_ATTRS help diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 08996d008ba6..c643bb3736fc 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From 1df79ca4223632113f14618833b8bb1727a8ca15 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Wed, 14 Jul 2010 10:49:43 -0700 Subject: [SCSI] ipr: fix transition to operational for new adapters The method of transitioning to operational for new adapters includes using initialization stages. The current stage is indicated via a register read. The final good stage in the sequence is "operational" but does not necessarily indicate that the driver can proceed. There is another bit that gets set in the adapter->host interrupt register when the adapter has completed enough of its bringup such that it can accept commands. The driver was not checking that bit before proceeding which led to intermittent errors and adapter resets. The fix is to check the "transition to operational" bit in the interrupt register after detecting that the initialization stage is "operational" and only proceed if both are set. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index ce839c8eeea3..f73007db2bec 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7169,12 +7169,15 @@ static int ipr_reset_next_stage(struct ipr_cmnd *ipr_cmd) stage_time = ioa_cfg->transop_timeout; ipr_cmd->job_step = ipr_ioafp_identify_hrrq; } else if (stage == IPR_IPL_INIT_STAGE_TRANSOP) { - ipr_cmd->job_step = ipr_ioafp_identify_hrrq; - maskval = IPR_PCII_IPL_STAGE_CHANGE; - maskval = (maskval << 32) | IPR_PCII_IOA_TRANS_TO_OPER; - writeq(maskval, ioa_cfg->regs.set_interrupt_mask_reg); - int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); - return IPR_RC_JOB_CONTINUE; + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); + if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { + ipr_cmd->job_step = ipr_ioafp_identify_hrrq; + maskval = IPR_PCII_IPL_STAGE_CHANGE; + maskval = (maskval << 32) | IPR_PCII_IOA_TRANS_TO_OPER; + writeq(maskval, ioa_cfg->regs.set_interrupt_mask_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); + return IPR_RC_JOB_CONTINUE; + } } ipr_cmd->timer.data = (unsigned long) ipr_cmd; -- cgit v1.2.3 From 75576bb9b208d7c66822f310cdef9ca2d72c879c Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Wed, 14 Jul 2010 10:50:14 -0700 Subject: [SCSI] ipr: fix resource type update and add sdev and shost attributes Setting the resource type in the ipr_update_res_entry function was incorrect in that the top 4 bits were masked off. The assignment has been updated to no longer mask those bits. Then, two new attributes were added to allow the user space utilities to more easily get information. The resource_type sdev attribute is set for all devices in the adapter's configuration table and indicates the type of device. The fw_type shost attribute indicates the firmware type supported by the adapter. Finally, the resource_path attribute was changed to be mode S_IRUGO. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index f73007db2bec..52568588039f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1168,7 +1168,7 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res, if (res->ioa_cfg->sis64) { res->flags = cfgtew->u.cfgte64->flags; res->res_flags = cfgtew->u.cfgte64->res_flags; - res->type = cfgtew->u.cfgte64->res_type & 0x0f; + res->type = cfgtew->u.cfgte64->res_type; memcpy(&res->std_inq_data, &cfgtew->u.cfgte64->std_inq_data, sizeof(struct ipr_std_inq_data)); @@ -3762,6 +3762,36 @@ static struct device_attribute ipr_update_fw_attr = { .store = ipr_store_update_fw }; +/** + * ipr_show_fw_type - Show the adapter's firmware type. + * @dev: class device struct + * @buf: buffer + * + * Return value: + * number of bytes printed to buffer + **/ +static ssize_t ipr_show_fw_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata; + unsigned long lock_flags = 0; + int len; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + len = snprintf(buf, PAGE_SIZE, "%d\n", ioa_cfg->sis64); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return len; +} + +static struct device_attribute ipr_ioa_fw_type_attr = { + .attr = { + .name = "fw_type", + .mode = S_IRUGO, + }, + .show = ipr_show_fw_type +}; + static struct device_attribute *ipr_ioa_attrs[] = { &ipr_fw_version_attr, &ipr_log_level_attr, @@ -3769,6 +3799,7 @@ static struct device_attribute *ipr_ioa_attrs[] = { &ipr_ioa_state_attr, &ipr_ioa_reset_attr, &ipr_update_fw_attr, + &ipr_ioa_fw_type_attr, NULL, }; @@ -4122,14 +4153,49 @@ static ssize_t ipr_show_resource_path(struct device *dev, struct device_attribut static struct device_attribute ipr_resource_path_attr = { .attr = { .name = "resource_path", - .mode = S_IRUSR, + .mode = S_IRUGO, }, .show = ipr_show_resource_path }; +/** + * ipr_show_resource_type - Show the resource type for this device. + * @dev: device struct + * @buf: buffer + * + * Return value: + * number of bytes printed to buffer + **/ +static ssize_t ipr_show_resource_type(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; + struct ipr_resource_entry *res; + unsigned long lock_flags = 0; + ssize_t len = -ENXIO; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + res = (struct ipr_resource_entry *)sdev->hostdata; + + if (res) + len = snprintf(buf, PAGE_SIZE, "%x\n", res->type); + + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return len; +} + +static struct device_attribute ipr_resource_type_attr = { + .attr = { + .name = "resource_type", + .mode = S_IRUGO, + }, + .show = ipr_show_resource_type +}; + static struct device_attribute *ipr_dev_attrs[] = { &ipr_adapter_handle_attr, &ipr_resource_path_attr, + &ipr_resource_type_attr, NULL, }; -- cgit v1.2.3 From 589a52d6a97e01c5ff6c244ee6c8ea57726c610f Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Jul 2010 15:30:54 -0400 Subject: [SCSI] lpfc 8.3.15: BSG, Discovery, and Misc fixes - BSG interface related: - Fix node reference count if node is active - Warn if we're overwriting an active CT context - Discovery related: - Clear "Ignore Reg Login" flag when purging mailbox queue - Pay attention to return code for fc_block_scsi_eh() - Stall device loss code if we're almost done when it fires (we're logged in, but PRLI is outstanding) - Bugs - Correct DIF code for endianness issues - Correct where we had missed points to check txq on i/o completion/cleanup Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_bsg.c | 27 +++++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_els.c | 5 +++++ drivers/scsi/lpfc/lpfc_hbadisc.c | 5 +++-- drivers/scsi/lpfc/lpfc_scsi.c | 38 +++++++++++++++++++++++++++++++++----- drivers/scsi/lpfc/lpfc_sli.c | 20 ++++++++------------ 5 files changed, 76 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 55f984166dbc..d521569e6620 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -962,10 +962,22 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (phba->sli_rev == LPFC_SLI_REV4) { evt_dat->immed_dat = phba->ctx_idx; phba->ctx_idx = (phba->ctx_idx + 1) % 64; + /* Provide warning for over-run of the ct_ctx array */ + if (phba->ct_ctx[evt_dat->immed_dat].flags & + UNSOL_VALID) + lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, + "2717 CT context array entry " + "[%d] over-run: oxid:x%x, " + "sid:x%x\n", phba->ctx_idx, + phba->ct_ctx[ + evt_dat->immed_dat].oxid, + phba->ct_ctx[ + evt_dat->immed_dat].SID); phba->ct_ctx[evt_dat->immed_dat].oxid = piocbq->iocb.ulpContext; phba->ct_ctx[evt_dat->immed_dat].SID = piocbq->iocb.un.rcvels.remoteID; + phba->ct_ctx[evt_dat->immed_dat].flags = UNSOL_VALID; } else evt_dat->immed_dat = piocbq->iocb.ulpContext; @@ -1323,6 +1335,21 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, rc = IOCB_ERROR; goto issue_ct_rsp_exit; } + + /* Check if the ndlp is active */ + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + rc = -IOCB_ERROR; + goto issue_ct_rsp_exit; + } + + /* get a refernece count so the ndlp doesn't go away while + * we respond + */ + if (!lpfc_nlp_get(ndlp)) { + rc = -IOCB_ERROR; + goto issue_ct_rsp_exit; + } + icmd->un.ulpWord[3] = ndlp->nlp_rpi; /* The exchange is done, mark the entry as invalid */ phba->ct_ctx[tag].flags &= ~UNSOL_VALID; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 017c933d60ab..f80156246e51 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -6962,6 +6962,7 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL; unsigned long iflag = 0; + struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; spin_lock_irqsave(&phba->hbalock, iflag); spin_lock(&phba->sli4_hba.abts_sgl_list_lock); @@ -6974,6 +6975,10 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, sglq_entry->state = SGL_FREED; spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); spin_unlock_irqrestore(&phba->hbalock, iflag); + + /* Check if TXQ queue needs to be serviced */ + if (pring->txq_cnt) + lpfc_worker_wake_up(phba); return; } } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 9fcad20491ef..a610464da16e 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -276,7 +276,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) !(ndlp->nlp_flag & NLP_DELAY_TMO) && !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && - (ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE)) + (ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) && + (ndlp->nlp_state != NLP_STE_PRLI_ISSUE)) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); lpfc_unregister_unused_fcf(phba); @@ -587,7 +588,7 @@ lpfc_work_done(struct lpfc_hba *phba) (status & HA_RXMASK)); } - if (phba->pport->work_port_events & WORKER_SERVICE_TXQ) + if (pring->txq_cnt) lpfc_drain_txq(phba); /* * Turn on Ring interrupts diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 7b66b71a14fe..d6089c985c3f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -623,6 +623,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, unsigned long iflag = 0; struct lpfc_iocbq *iocbq; int i; + struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; spin_lock_irqsave(&phba->hbalock, iflag); spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock); @@ -651,6 +652,8 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, psb = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); psb->exch_busy = 0; spin_unlock_irqrestore(&phba->hbalock, iflag); + if (pring->txq_cnt) + lpfc_worker_wake_up(phba); return; } @@ -1322,6 +1325,10 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); pde5->reftag = reftag; + /* Endian convertion if necessary for PDE5 */ + pde5->word0 = cpu_to_le32(pde5->word0); + pde5->reftag = cpu_to_le32(pde5->reftag); + /* advance bpl and increment bde count */ num_bde++; bpl++; @@ -1340,6 +1347,11 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde6_ai, pde6, 1); bf_set(pde6_apptagval, pde6, apptagval); + /* Endian convertion if necessary for PDE6 */ + pde6->word0 = cpu_to_le32(pde6->word0); + pde6->word1 = cpu_to_le32(pde6->word1); + pde6->word2 = cpu_to_le32(pde6->word2); + /* advance bpl and increment bde count */ num_bde++; bpl++; @@ -1447,6 +1459,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); pde5->reftag = reftag; + /* Endian convertion if necessary for PDE5 */ + pde5->word0 = cpu_to_le32(pde5->word0); + pde5->reftag = cpu_to_le32(pde5->reftag); + /* advance bpl and increment bde count */ num_bde++; bpl++; @@ -1463,6 +1479,11 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde6_ai, pde6, 1); bf_set(pde6_apptagval, pde6, apptagval); + /* Endian convertion if necessary for PDE6 */ + pde6->word0 = cpu_to_le32(pde6->word0); + pde6->word1 = cpu_to_le32(pde6->word1); + pde6->word2 = cpu_to_le32(pde6->word2); + /* advance bpl and increment bde count */ num_bde++; bpl++; @@ -1474,7 +1495,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, prot_bde->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr)); protgroup_len = sg_dma_len(sgpe); - /* must be integer multiple of the DIF block length */ BUG_ON(protgroup_len % 8); @@ -3047,7 +3067,9 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) int ret = SUCCESS; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); - fc_block_scsi_eh(cmnd); + ret = fc_block_scsi_eh(cmnd); + if (ret) + return ret; lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; BUG_ON(!lpfc_cmd); @@ -3365,7 +3387,9 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) return FAILED; } pnode = rdata->pnode; - fc_block_scsi_eh(cmnd); + status = fc_block_scsi_eh(cmnd); + if (status) + return status; status = lpfc_chk_tgt_mapped(vport, cmnd); if (status == FAILED) { @@ -3430,7 +3454,9 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) return FAILED; } pnode = rdata->pnode; - fc_block_scsi_eh(cmnd); + status = fc_block_scsi_eh(cmnd); + if (status) + return status; status = lpfc_chk_tgt_mapped(vport, cmnd); if (status == FAILED) { @@ -3496,7 +3522,9 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) fc_host_post_vendor_event(shost, fc_get_event_number(), sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); - fc_block_scsi_eh(cmnd); + ret = fc_block_scsi_eh(cmnd); + if (ret) + return ret; /* * Since the driver manages a single bus device, reset all diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7ddf52682271..086f95261605 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -601,15 +601,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); /* Check if TXQ queue needs to be serviced */ - if (pring->txq_cnt) { - spin_lock_irqsave( - &phba->pport->work_port_lock, iflag); - phba->pport->work_port_events |= - WORKER_SERVICE_TXQ; + if (pring->txq_cnt) lpfc_worker_wake_up(phba); - spin_unlock_irqrestore( - &phba->pport->work_port_lock, iflag); - } } } @@ -12757,6 +12750,7 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) LPFC_MBOXQ_t *mb, *nextmb; struct lpfc_dmabuf *mp; struct lpfc_nodelist *ndlp; + struct Scsi_Host *shost = lpfc_shost_from_vport(vport); spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { @@ -12778,6 +12772,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) } ndlp = (struct lpfc_nodelist *) mb->context2; if (ndlp) { + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; + spin_unlock_irq(shost->host_lock); lpfc_nlp_put(ndlp); mb->context2 = NULL; } @@ -12793,6 +12790,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) { ndlp = (struct lpfc_nodelist *) mb->context2; if (ndlp) { + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; + spin_unlock_irq(shost->host_lock); lpfc_nlp_put(ndlp); mb->context2 = NULL; } @@ -12879,10 +12879,6 @@ lpfc_drain_txq(struct lpfc_hba *phba) spin_unlock_irqrestore(&phba->hbalock, iflags); } - spin_lock_irqsave(&phba->pport->work_port_lock, iflags); - phba->pport->work_port_events &= ~WORKER_SERVICE_TXQ; - spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags); - /* Cancel all the IOCBs that cannot be issued */ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED); -- cgit v1.2.3 From 3804dc84b8c11038ef75d97fd11e43658f623665 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Jul 2010 15:31:37 -0400 Subject: [SCSI] lpfc 8.3.15: FCoE Related Fixes FCoE Related Fixes - Correct find-next-FCF routine so that it searches at next FCF rather than current one. - Enhanced round-robin FCF failover algorithm to re-start on "New FCF" async event - Update the manner in which we look at FCFs while they may be in their discovery state. - Use LPFC_FCOE_NULL_VID macro when checkinf for valid vlan_id for FCF Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 24 +++++++++--------- drivers/scsi/lpfc/lpfc_hbadisc.c | 28 ++++++++++++++------ drivers/scsi/lpfc/lpfc_init.c | 22 ++++++++-------- drivers/scsi/lpfc/lpfc_mbox.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 55 +++++++++++++++++++++++++++++++++++----- drivers/scsi/lpfc/lpfc_sli4.h | 1 + 6 files changed, 92 insertions(+), 40 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index f80156246e51..afbed6bc31f0 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -813,18 +813,21 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, - "2760 FLOGI exhausted FCF " - "round robin failover list, " - "retry FLOGI on the current " - "registered FCF index:%d\n", + "2760 Completed one round " + "of FLOGI FCF round robin " + "failover list, retry FLOGI " + "on currently registered " + "FCF index:%d\n", phba->fcf.current_rec.fcf_indx); - spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag &= ~FCF_DISCOVERY; - spin_unlock_irq(&phba->hbalock); } else { + lpfc_printf_log(phba, KERN_INFO, + LOG_FIP | LOG_ELS, + "2794 FLOGI FCF round robin " + "failover to FCF index x%x\n", + fcf_index); rc = lpfc_sli4_fcf_rr_read_fcf_rec(phba, fcf_index); - if (rc) { + if (rc) lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, "2761 FLOGI round " @@ -833,10 +836,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "rc:x%x, fcf_index:" "%d\n", rc, phba->fcf.current_rec.fcf_indx); - spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag &= ~FCF_DISCOVERY; - spin_unlock_irq(&phba->hbalock); - } else + else goto out; } } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index a610464da16e..92498e488f4f 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1572,7 +1572,7 @@ lpfc_sli4_new_fcf_random_select(struct lpfc_hba *phba, uint32_t fcf_cnt) } /** - * lpfc_mbx_cmpl_read_fcf_record - Completion handler for read_fcf mbox. + * lpfc_sli4_fcf_rec_mbox_parse - Parse read_fcf mbox command. * @phba: pointer to lpfc hba data structure. * @mboxq: pointer to mailbox object. * @next_fcf_index: pointer to holder of next fcf index. @@ -2026,9 +2026,14 @@ read_next_fcf: memcpy(&phba->fcf.current_rec, &phba->fcf.failover_rec, sizeof(struct lpfc_fcf_rec)); - /* mark the FCF fast failover completed */ + /* + * Mark the fast FCF failover rediscovery completed + * and the start of the first round of the roundrobin + * FCF failover. + */ spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; + phba->fcf.fcf_flag &= + ~(FCF_REDISC_FOV | FCF_REDISC_RRU); spin_unlock_irq(&phba->hbalock); /* * Set up the initial registered FCF index for FLOGI @@ -2074,9 +2079,14 @@ read_next_fcf: * through the FCF scanning process. */ - /* mark the initial FCF discovery completed */ + /* + * Mark the initial FCF discovery completed and + * the start of the first round of the roundrobin + * FCF failover. + */ spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag &= ~FCF_INIT_DISC; + phba->fcf.fcf_flag &= + ~(FCF_INIT_DISC | FCF_REDISC_RRU); spin_unlock_irq(&phba->hbalock); /* * Set up the initial registered FCF index for FLOGI @@ -2206,7 +2216,7 @@ lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) goto out; /* If FCF discovery period is over, no need to proceed */ - if (phba->fcf.fcf_flag & FCF_DISCOVERY) + if (!(phba->fcf.fcf_flag & FCF_DISCOVERY)) goto out; /* Parse the FCF record from the non-embedded mailbox command */ @@ -5331,13 +5341,15 @@ void lpfc_unregister_unused_fcf(struct lpfc_hba *phba) { /* - * If HBA is not running in FIP mode or if HBA does not support - * FCoE or if FCF is not registered, do nothing. + * If HBA is not running in FIP mode, if HBA does not support + * FCoE, if FCF discovery is ongoing, or if FCF has not been + * registered, do nothing. */ spin_lock_irq(&phba->hbalock); if (!(phba->hba_flag & HBA_FCOE_SUPPORT) || !(phba->fcf.fcf_flag & FCF_REGISTERED) || !(phba->hba_flag & HBA_FIP_SUPPORT) || + (phba->fcf.fcf_flag & FCF_DISCOVERY) || (phba->pport->port_state == LPFC_FLOGI)) { spin_unlock_irq(&phba->hbalock); return; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index fb06933f8e6c..2786ee3b605d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -3357,22 +3357,14 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, "evt_tag:x%x, fcf_index:x%x\n", acqe_fcoe->event_tag, acqe_fcoe->index); + /* If the FCF discovery is in progress, do nothing. */ spin_lock_irq(&phba->hbalock); - if ((phba->fcf.fcf_flag & FCF_SCAN_DONE) || - (phba->hba_flag & FCF_DISC_INPROGRESS)) { - /* - * If the current FCF is in discovered state or - * FCF discovery is in progress, do nothing. - */ + if (phba->hba_flag & FCF_DISC_INPROGRESS) { spin_unlock_irq(&phba->hbalock); break; } - + /* If fast FCF failover rescan event is pending, do nothing */ if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { - /* - * If fast FCF failover rescan event is pending, - * do nothing. - */ spin_unlock_irq(&phba->hbalock); break; } @@ -3393,7 +3385,13 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, acqe_fcoe->index); rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index); } - + /* If the FCF has been in discovered state, do nothing. */ + spin_lock_irq(&phba->hbalock); + if (phba->fcf.fcf_flag & FCF_SCAN_DONE) { + spin_unlock_irq(&phba->hbalock); + break; + } + spin_unlock_irq(&phba->hbalock); /* Otherwise, scan the entire FCF table and re-discover SAN */ lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2770 Start FCF table scan due to new FCF " diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index cb5d93b41b50..9c2c7c7140c7 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -2045,7 +2045,7 @@ lpfc_reg_fcfi(struct lpfc_hba *phba, struct lpfcMboxq *mbox) phba->fcf.current_rec.fcf_indx); /* reg_fcf addr mode is bit wise inverted value of fcf addr_mode */ bf_set(lpfc_reg_fcfi_mam, reg_fcfi, (~phba->fcf.addr_mode) & 0x3); - if (phba->fcf.current_rec.vlan_id != 0xFFFF) { + if (phba->fcf.current_rec.vlan_id != LPFC_FCOE_NULL_VID) { bf_set(lpfc_reg_fcfi_vv, reg_fcfi, 1); bf_set(lpfc_reg_fcfi_vlan_tag, reg_fcfi, phba->fcf.current_rec.vlan_id); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 086f95261605..e758eae0d0fd 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -12405,19 +12405,47 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba) { uint16_t next_fcf_index; - /* Search from the currently registered FCF index */ + /* Search start from next bit of currently registered FCF index */ + next_fcf_index = (phba->fcf.current_rec.fcf_indx + 1) % + LPFC_SLI4_FCF_TBL_INDX_MAX; next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask, LPFC_SLI4_FCF_TBL_INDX_MAX, - phba->fcf.current_rec.fcf_indx); + next_fcf_index); + /* Wrap around condition on phba->fcf.fcf_rr_bmask */ if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask, LPFC_SLI4_FCF_TBL_INDX_MAX, 0); - /* Round robin failover stop condition */ - if ((next_fcf_index == phba->fcf.fcf_rr_init_indx) || - (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)) + + /* Check roundrobin failover list empty condition */ + if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) { + lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, + "2844 No roundrobin failover FCF available\n"); return LPFC_FCOE_FCF_NEXT_NONE; + } + + /* Check roundrobin failover index bmask stop condition */ + if (next_fcf_index == phba->fcf.fcf_rr_init_indx) { + if (!(phba->fcf.fcf_flag & FCF_REDISC_RRU)) { + lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, + "2847 Round robin failover FCF index " + "search hit stop condition:x%x\n", + next_fcf_index); + return LPFC_FCOE_FCF_NEXT_NONE; + } + /* The roundrobin failover index bmask updated, start over */ + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2848 Round robin failover FCF index bmask " + "updated, start over\n"); + spin_lock_irq(&phba->hbalock); + phba->fcf.fcf_flag &= ~FCF_REDISC_RRU; + spin_unlock_irq(&phba->hbalock); + return phba->fcf.fcf_rr_init_indx; + } + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2845 Get next round robin failover " + "FCF index x%x\n", next_fcf_index); return next_fcf_index; } @@ -12447,11 +12475,20 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index) /* Set the eligible FCF record index bmask */ set_bit(fcf_index, phba->fcf.fcf_rr_bmask); + /* Set the roundrobin index bmask updated */ + spin_lock_irq(&phba->hbalock); + phba->fcf.fcf_flag |= FCF_REDISC_RRU; + spin_unlock_irq(&phba->hbalock); + + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2790 Set FCF index x%x to round robin failover " + "bmask\n", fcf_index); + return 0; } /** - * lpfc_sli4_fcf_rr_index_set - Clear bmask from eligible fcf record index + * lpfc_sli4_fcf_rr_index_clear - Clear bmask from eligible fcf record index * @phba: pointer to lpfc hba data structure. * * This routine clears the FCF record index from the eligible bmask for @@ -12472,6 +12509,10 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index) } /* Clear the eligible FCF record index bmask */ clear_bit(fcf_index, phba->fcf.fcf_rr_bmask); + + lpfc_printf_log(phba, KERN_INFO, LOG_FIP, + "2791 Clear FCF index x%x from round robin failover " + "bmask\n", fcf_index); } /** @@ -12534,7 +12575,7 @@ lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) } /** - * lpfc_sli4_redisc_all_fcf - Request to rediscover entire FCF table by port. + * lpfc_sli4_redisc_fcf_table - Request to rediscover entire FCF table by port. * @phba: pointer to lpfc hba data structure. * * This routine is invoked to request for rediscovery of the entire FCF table diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index c916079fbb35..a3b24d99a2a7 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -163,6 +163,7 @@ struct lpfc_fcf { #define FCF_REDISC_PEND 0x80 /* FCF rediscovery pending */ #define FCF_REDISC_EVT 0x100 /* FCF rediscovery event to worker thread */ #define FCF_REDISC_FOV 0x200 /* Post FCF rediscovery fast failover */ +#define FCF_REDISC_RRU 0x400 /* Roundrobin bitmap updated */ uint32_t addr_mode; uint16_t fcf_rr_init_indx; uint32_t eligible_fcf_cnt; -- cgit v1.2.3 From 7dc517df3ace15b5a29b331abe0af86ed4836236 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Jul 2010 15:32:10 -0400 Subject: [SCSI] lpfc 8.3.15: Add target queue depth throttling Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 3 ++- drivers/scsi/lpfc/lpfc_attr.c | 12 +++++++++++- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 15 ++++++++------- 4 files changed, 22 insertions(+), 10 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index bb40fcbe17c5..3482d5a5aed2 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -48,7 +48,7 @@ struct lpfc_sli2_slim; #define LPFC_TGTQ_INTERVAL 40000 /* Min amount of time between tgt queue depth change in millisecs */ #define LPFC_TGTQ_RAMPUP_PCENT 5 /* Target queue rampup in percentage */ -#define LPFC_MIN_TGT_QDEPTH 100 +#define LPFC_MIN_TGT_QDEPTH 10 #define LPFC_MAX_TGT_QDEPTH 0xFFFF #define LPFC_MAX_BUCKET_COUNT 20 /* Maximum no. of buckets for stat data @@ -400,6 +400,7 @@ struct lpfc_vport { uint32_t cfg_max_luns; uint32_t cfg_enable_da_id; uint32_t cfg_max_scsicmpl_time; + uint32_t cfg_tgt_queue_depth; uint32_t dev_loss_tmo_changed; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index a7c6b7390554..868874c28f99 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2207,6 +2207,13 @@ LPFC_VPORT_ATTR_R(enable_da_id, 0, 0, 1, LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 128, "Max number of FCP commands we can queue to a specific LUN"); +/* +# tgt_queue_depth: This parameter is used to limit the number of outstanding +# commands per target port. Value range is [10,65535]. Default value is 65535. +*/ +LPFC_VPORT_ATTR_R(tgt_queue_depth, 65535, 10, 65535, + "Max number of FCP commands we can queue to a specific target port"); + /* # hba_queue_depth: This parameter is used to limit the number of outstanding # commands per lpfc HBA. Value range is [32,8192]. If this parameter @@ -3122,7 +3129,7 @@ lpfc_max_scsicmpl_time_set(struct lpfc_vport *vport, int val) continue; if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) continue; - ndlp->cmd_qdepth = LPFC_MAX_TGT_QDEPTH; + ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; } spin_unlock_irq(shost->host_lock); return 0; @@ -3326,6 +3333,7 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_temp_sensor, &dev_attr_lpfc_log_verbose, &dev_attr_lpfc_lun_queue_depth, + &dev_attr_lpfc_tgt_queue_depth, &dev_attr_lpfc_hba_queue_depth, &dev_attr_lpfc_peer_port_login, &dev_attr_lpfc_nodev_tmo, @@ -3387,6 +3395,7 @@ struct device_attribute *lpfc_vport_attrs[] = { &dev_attr_lpfc_drvr_version, &dev_attr_lpfc_log_verbose, &dev_attr_lpfc_lun_queue_depth, + &dev_attr_lpfc_tgt_queue_depth, &dev_attr_lpfc_nodev_tmo, &dev_attr_lpfc_devloss_tmo, &dev_attr_lpfc_hba_queue_depth, @@ -4575,6 +4584,7 @@ lpfc_get_vport_cfgparam(struct lpfc_vport *vport) { lpfc_log_verbose_init(vport, lpfc_log_verbose); lpfc_lun_queue_depth_init(vport, lpfc_lun_queue_depth); + lpfc_tgt_queue_depth_init(vport, lpfc_tgt_queue_depth); lpfc_devloss_tmo_init(vport, lpfc_devloss_tmo); lpfc_nodev_tmo_init(vport, lpfc_nodev_tmo); lpfc_peer_port_login_init(vport, lpfc_peer_port_login); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 92498e488f4f..0639c994349c 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -3583,7 +3583,7 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, kref_init(&ndlp->kref); NLP_INT_NODE_ACT(ndlp); atomic_set(&ndlp->cmd_pending, 0); - ndlp->cmd_qdepth = LPFC_MAX_TGT_QDEPTH; + ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; } struct lpfc_nodelist * diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index d6089c985c3f..c818a7255962 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -2458,14 +2458,16 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, } spin_unlock_irqrestore(shost->host_lock, flags); } else if (pnode && NLP_CHK_NODE_ACT(pnode)) { - if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) && + if ((pnode->cmd_qdepth < vport->cfg_tgt_queue_depth) && time_after(jiffies, pnode->last_change_time + msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) { spin_lock_irqsave(shost->host_lock, flags); - pnode->cmd_qdepth += pnode->cmd_qdepth * - LPFC_TGTQ_RAMPUP_PCENT / 100; - if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH) - pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH; + depth = pnode->cmd_qdepth * LPFC_TGTQ_RAMPUP_PCENT + / 100; + depth = depth ? depth : 1; + pnode->cmd_qdepth += depth; + if (pnode->cmd_qdepth > vport->cfg_tgt_queue_depth) + pnode->cmd_qdepth = vport->cfg_tgt_queue_depth; pnode->last_change_time = jiffies; spin_unlock_irqrestore(shost->host_lock, flags); } @@ -2920,8 +2922,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0); goto out_fail_command; } - if (vport->cfg_max_scsicmpl_time && - (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)) + if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) goto out_host_busy; lpfc_cmd = lpfc_get_scsi_buf(phba); -- cgit v1.2.3 From 32de596074592ee8593416c83347b5a787e825c5 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 14 Jul 2010 15:32:40 -0400 Subject: [SCSI] lpfc 8.3.15: Update driver version 8.3.15 Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 33d9d8db4d35..d28830af71d8 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.14" +#define LPFC_DRIVER_VERSION "8.3.15" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" -- cgit v1.2.3 From e84d96dbb0638186feb526c32810a3400f33d0c8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 15 Jul 2010 10:20:19 +0200 Subject: [SCSI] dpt_i2o: move range check forward The check to test that "bus_no" was valid came after we had already used it as an array offset. This patch moves it forward. Signed-off-by: Dan Carpenter Signed-off-by: James Bottomley --- drivers/scsi/dpt_i2o.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index f2d4df14c311..ffc1edf5e80d 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -2640,6 +2640,13 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) continue; } bus_no = buf[0]>>16; + if (bus_no >= MAX_CHANNEL) { /* Something wrong skip it */ + printk(KERN_WARNING + "%s: Channel number %d out of range\n", + pHba->name, bus_no); + continue; + } + scsi_id = buf[1]; scsi_lun = (buf[2]>>8 )&0xff; pDev = pHba->channel[bus_no].device[scsi_id]; @@ -2668,10 +2675,6 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) adpt_i2o_report_hba_unit(pHba, d); adpt_i2o_install_device(pHba, d); - if(bus_no >= MAX_CHANNEL) { // Something wrong skip it - printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no); - continue; - } pDev = pHba->channel[bus_no].device[scsi_id]; if( pDev == NULL){ pDev = -- cgit v1.2.3 From 2cf75f1c8aa4cab3ace57f9159f1dc85cba69d38 Mon Sep 17 00:00:00 2001 From: "Yanqing_Liu@Dell.com" Date: Wed, 19 May 2010 12:31:36 -0500 Subject: [SCSI] scsi_dh_rdac: Add Dell MD36xxi controller into RDAC device list This patch is to add next generation of Dell iSCSI PowerVault controller MD36xxi into RDAC device list. Signed-off-by: Yanqing Liu Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_rdac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 5b683e429542..b9bcfa4c7d26 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -768,6 +768,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { {"DELL", "MD3000i"}, {"DELL", "MD32xx"}, {"DELL", "MD32xxi"}, + {"DELL", "MD36xxi"}, {"LSI", "INF-01-00"}, {"ENGENIO", "INF-01-00"}, {"STK", "FLEXLINE 380"}, -- cgit v1.2.3 From ba402804ac2447ad41f4919603bf3e6f6db63110 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 20 Jul 2010 15:19:10 -0700 Subject: [SCSI] libfc: fix slowpath error from WARN_ON in fc_fcp_send_data This is exposed by a mpio test using EMC CLARiiON targets when LUN tresspassing happens, the burst length from the XFER_READY for the MODE SELECT(10) is 19 bytes, much smaller than FC_MIN_MAX_PAYLOAD as 256 bytes. This patch removes the related two WARN_ON()s. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 8914f1e95b72..a0a3ae7d8611 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -580,10 +580,8 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, fsp, seq_blen, lport->lso_max, t_blen); } - WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD); if (t_blen > 512) t_blen &= ~(512 - 1); /* round down to block size */ - WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD); /* won't go below 256 */ sc = fsp->cmd; remaining = seq_blen; -- cgit v1.2.3 From e0d93c5bc47ae270ea38192c9a49f660e0406060 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Tue, 20 Jul 2010 15:19:20 -0700 Subject: [SCSI] libfc: IO errors on link down due to cable unplug In this case, sync IO fails with EIO(5) errors as:- "Thread:1 System call error:5 - Input/output error (::pwrite() failed)". This is due to IO time out while libfc doing link down processing to block all rports and if timed out IO was at last retry attempt then it fails to user with EIO error followed by these log messages. [77848.612169] host2: rport bf0015: Delete port [77848.612221] host2: rport e10aef: work delete [77848.612232] host2: rport e10002: work event 3 [77848.612422] sd 2:0:1:1: [sdi] Unhandled error code [77848.612426] sd 2:0:1:1: [sdi] Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK [77848.612431] sd 2:0:1:1: [sdi] CDB: Write(10): 2a 00 00 00 11 20 00 00 20 00 [77848.612445] end_request: I/O error, dev sdi, sector 4384 [77848.612553] sd 2:0:1:2: [sdj] Unhandled error code To fix these EIO errors, such timed out incomplete IOs needs to be re-queued without counting retry attempt and this patch does that using DID_REQUEUE scsi code. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index a0a3ae7d8611..61a12970bd14 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1971,6 +1971,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) break; } + if (lport->state != LPORT_ST_READY && fsp->status_code != FC_COMPLETE) { + sc_cmd->result = (DID_REQUEUE << 16); + FC_FCP_DBG(fsp, "Returning DID_REQUEUE to scsi-ml\n"); + } + spin_lock_irqsave(&si->scsi_queue_lock, flags); list_del(&fsp->list); spin_unlock_irqrestore(&si->scsi_queue_lock, flags); -- cgit v1.2.3 From 9d4cbc05f32fc0a1024de2a9d5635bc9d180e4ae Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Tue, 20 Jul 2010 15:19:26 -0700 Subject: [SCSI] fcoe: cleans up fcoe_disable and fcoe_enable The fc_fabric_logoff and fc_fabric_login are redundant here after recently added fcoe_ctlr_link_down/up to these functions, therefore this patch removes logoff and login to only use link down and up here. This works best for their current usages with fcoe DCB link down or up. This also works well to avoid EIO errors when fcoe DCB link goes down as lport state moves out of ready quickly from fcoe_ctlr_link_down and that allows re-queuing timed out IOs for this case also. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 44a07593de56..d340cf2d857a 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1918,8 +1918,8 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp) rtnl_unlock(); if (fcoe) { - fc_fabric_logoff(fcoe->ctlr.lp); fcoe_ctlr_link_down(&fcoe->ctlr); + fcoe_clean_pending_queue(fcoe->ctlr.lp); } else rc = -ENODEV; @@ -1972,12 +1972,10 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp) fcoe = fcoe_hostlist_lookup_port(netdev); rtnl_unlock(); - if (fcoe) { - if (!fcoe_link_ok(fcoe->ctlr.lp)) - fcoe_ctlr_link_up(&fcoe->ctlr); - rc = fc_fabric_login(fcoe->ctlr.lp); - } else + if (!fcoe) rc = -ENODEV; + else if (!fcoe_link_ok(fcoe->ctlr.lp)) + fcoe_ctlr_link_up(&fcoe->ctlr); dev_put(netdev); out_nodev: -- cgit v1.2.3 From 519e5135e2537c9dbc1cbcc0891b0a936ff5dcd2 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Tue, 20 Jul 2010 15:19:32 -0700 Subject: [SCSI] fcoe: adds src and dest mac address checking for fcoe frames This is per FC-BB-5 Annex-D recommendation and per that if address checking fails then drop the frame. FIP code paths are already doing this so only needed for fcoe frames. The src address checking is limited to only fip mode since this might break non-fip mode used in p2p due to used OUI based addressing in some p2p code paths, going forward FIP will be the only mode, therefore limited this to only FIP mode so that it won't break non-fip p2p mode for now. -v2 Removes FCOE packet type checking since fcoe_rcv is registered to receive only FCoE type packets from netdev and it is already checked by netdev. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 20 +++++++++++++++++--- include/scsi/libfcoe.h | 10 ++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index d340cf2d857a..a120962b25b8 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1210,6 +1210,8 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, struct fcoe_interface *fcoe; struct fc_frame_header *fh; struct fcoe_percpu_s *fps; + struct fcoe_port *port; + struct ethhdr *eh; unsigned int cpu; fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); @@ -1227,9 +1229,21 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, skb_tail_pointer(skb), skb_end_pointer(skb), skb->csum, skb->dev ? skb->dev->name : ""); - /* check for FCOE packet type */ - if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { - FCOE_NETDEV_DBG(netdev, "Wrong FC type frame"); + /* check for mac addresses */ + eh = eth_hdr(skb); + port = lport_priv(lport); + if (compare_ether_addr(eh->h_dest, port->data_src_addr) && + compare_ether_addr(eh->h_dest, fcoe->ctlr.ctl_src_addr) && + compare_ether_addr(eh->h_dest, (u8[6])FC_FCOE_FLOGI_MAC)) { + FCOE_NETDEV_DBG(netdev, "wrong destination mac address:%pM\n", + eh->h_dest); + goto err; + } + + if (is_fip_mode(&fcoe->ctlr) && + compare_ether_addr(eh->h_source, fcoe->ctlr.dest_addr)) { + FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n", + eh->h_source); goto err; } diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index ec13f51531f8..81aee1c4c2f3 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -170,4 +170,14 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_lport *, u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); int fcoe_libfc_config(struct fc_lport *, struct libfc_function_template *); +/** + * is_fip_mode() - returns true if FIP mode selected. + * @fip: FCoE controller. + */ +static inline bool is_fip_mode(struct fcoe_ctlr *fip) +{ + return fip->state == FIP_ST_ENABLED; +} + + #endif /* _LIBFCOE_H */ -- cgit v1.2.3 From 42e9041467cf5fd33501b91b27e26807c259c896 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:19:37 -0700 Subject: [SCSI] libfc: convert rport lookup to be RCU safe To allow LLD to do lookups on rports without grabbing a mutex, make them RCU-safe. The caller of lport->tt.rport_lookup will have the choice of holding disc_mutex or the rcu_read_lock(). Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 6 +++--- drivers/scsi/libfc/fc_rport.c | 22 ++++++++++++++++++---- include/scsi/libfc.h | 2 ++ 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index c7985da88099..d0fa9a0ddc8d 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -63,12 +63,12 @@ static void fc_disc_restart(struct fc_disc *); void fc_disc_stop_rports(struct fc_disc *disc) { struct fc_lport *lport; - struct fc_rport_priv *rdata, *next; + struct fc_rport_priv *rdata; lport = disc->lport; mutex_lock(&disc->disc_mutex); - list_for_each_entry_safe(rdata, next, &disc->rports, peers) + list_for_each_entry_rcu(rdata, &disc->rports, peers) lport->tt.rport_logoff(rdata); mutex_unlock(&disc->disc_mutex); } @@ -292,7 +292,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) * Skip ports which were never discovered. These are the dNS port * and ports which were created by PLOGI. */ - list_for_each_entry(rdata, &disc->rports, peers) { + list_for_each_entry_rcu(rdata, &disc->rports, peers) { if (!rdata->disc_id) continue; if (rdata->disc_id == disc->disc_id) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 363cde30c940..6b569732f892 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -95,13 +95,15 @@ static const char *fc_rport_state_names[] = { * fc_rport_lookup() - Lookup a remote port by port_id * @lport: The local port to lookup the remote port on * @port_id: The remote port ID to look up + * + * The caller must hold either disc_mutex or rcu_read_lock(). */ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, u32 port_id) { struct fc_rport_priv *rdata; - list_for_each_entry(rdata, &lport->disc.rports, peers) + list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) if (rdata->ids.port_id == port_id) return rdata; return NULL; @@ -146,10 +148,22 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout); INIT_WORK(&rdata->event_work, fc_rport_work); if (port_id != FC_FID_DIR_SERV) - list_add(&rdata->peers, &lport->disc.rports); + list_add_rcu(&rdata->peers, &lport->disc.rports); return rdata; } +/** + * fc_rport_free_rcu() - Free a remote port + * @rcu: The rcu_head structure inside the remote port + */ +static void fc_rport_free_rcu(struct rcu_head *rcu) +{ + struct fc_rport_priv *rdata; + + rdata = container_of(rcu, struct fc_rport_priv, rcu); + kfree(rdata); +} + /** * fc_rport_destroy() - Free a remote port after last reference is released * @kref: The remote port's kref @@ -159,7 +173,7 @@ static void fc_rport_destroy(struct kref *kref) struct fc_rport_priv *rdata; rdata = container_of(kref, struct fc_rport_priv, kref); - kfree(rdata); + call_rcu(&rdata->rcu, fc_rport_free_rcu); } /** @@ -334,7 +348,7 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); } else { FC_RPORT_DBG(rdata, "work delete\n"); - list_del(&rdata->peers); + list_del_rcu(&rdata->peers); mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 6d78df77dab6..b0310b9b3469 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -195,6 +195,7 @@ struct fc_rport_libfc_priv { * @rp_mutex: The mutex that protects the remote port * @retry_work: Handle for retries * @event_callback: Callback when READY, FAILED or LOGO states complete + * @rcu: Structure used for freeing in an RCU-safe manner */ struct fc_rport_priv { struct fc_lport *local_port; @@ -217,6 +218,7 @@ struct fc_rport_priv { struct list_head peers; struct work_struct event_work; u32 supported_classes; + struct rcu_head rcu; }; /** -- cgit v1.2.3 From f90377abcab2e305450ee76a0f9042907560c5d8 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:19:42 -0700 Subject: [SCSI] libfc: provide space for LLD after remote port structure Add pre-zeroed space after the allocation for fc_rport_priv for use by the lower-level driver. This is primarily for VN2VN FIP mode, but could be used in other ways someday. The space required is specified in lport->rport_priv_size. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 2 +- include/scsi/libfc.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6b569732f892..6d68482649c9 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -127,7 +127,7 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, if (rdata) return rdata; - rdata = kzalloc(sizeof(*rdata), GFP_KERNEL); + rdata = kzalloc(sizeof(*rdata) + lport->rport_priv_size, GFP_KERNEL); if (!rdata) return NULL; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index b0310b9b3469..fcbee8c38b0c 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -799,6 +799,7 @@ struct fc_disc { * @mfs: The maximum Fibre Channel payload size * @max_retry_count: The maximum retry attempts * @max_rport_retry_count: The maximum remote port retry attempts + * @rport_priv_size: Size needed by driver after struct fc_rport_priv * @lro_xid: The maximum XID for LRO * @lso_max: The maximum large offload send size * @fcts: FC-4 type mask @@ -848,6 +849,7 @@ struct fc_lport { u32 mfs; u8 max_retry_count; u8 max_rport_retry_count; + u16 rport_priv_size; u16 link_speed; u16 link_supported_speeds; u16 lro_xid; -- cgit v1.2.3 From fdb068c6cd6e30d43664f856d3530715a5742713 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:19:47 -0700 Subject: [SCSI] libfcoe: convert FIP to lock with mutex instead of spin lock It turns out most of the FIP work is now done from worker threads or process context now, so there's no need to use a spin lock. Change to use mutex instead of spin lock and delayed_work instead of a timer. This will make it nicer for the VN_port to VN_port feature that will interact more with the libfc layers requiring that spinlocks not be held. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 116 +++++++++++++++++++++----------------------- include/scsi/libfcoe.h | 9 +--- 2 files changed, 57 insertions(+), 68 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index f009191063f1..e510888e78ca 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -113,7 +113,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip) fip->state = FIP_ST_LINK_WAIT; fip->mode = FIP_ST_AUTO; INIT_LIST_HEAD(&fip->fcfs); - spin_lock_init(&fip->lock); + mutex_init(&fip->ctlr_mutex); fip->flogi_oxid = FC_XID_UNKNOWN; setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip); INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work); @@ -159,10 +159,10 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) cancel_work_sync(&fip->recv_work); skb_queue_purge(&fip->fip_recv_list); - spin_lock_bh(&fip->lock); + mutex_lock(&fip->ctlr_mutex); fip->state = FIP_ST_DISABLED; fcoe_ctlr_reset_fcfs(fip); - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); del_timer_sync(&fip->timer); cancel_work_sync(&fip->timer_work); } @@ -255,19 +255,19 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) */ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) { - spin_lock_bh(&fip->lock); + mutex_lock(&fip->ctlr_mutex); if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) { - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); fc_linkup(fip->lp); } else if (fip->state == FIP_ST_LINK_WAIT) { fip->state = fip->mode; - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); if (fip->state == FIP_ST_AUTO) LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); fc_linkup(fip->lp); fcoe_ctlr_solicit(fip, NULL); } else - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); } EXPORT_SYMBOL(fcoe_ctlr_link_up); @@ -300,11 +300,11 @@ int fcoe_ctlr_link_down(struct fcoe_ctlr *fip) int link_dropped; LIBFCOE_FIP_DBG(fip, "link down.\n"); - spin_lock_bh(&fip->lock); + mutex_lock(&fip->ctlr_mutex); fcoe_ctlr_reset(fip); link_dropped = fip->state != FIP_ST_LINK_WAIT; fip->state = FIP_ST_LINK_WAIT; - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); if (link_dropped) fc_linkdown(fip->lp); @@ -577,12 +577,12 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) unsigned long sel_time = 0; struct fcoe_dev_stats *stats; + stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu()); + list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2; if (fip->sel_fcf == fcf) { if (time_after(jiffies, deadline)) { - stats = per_cpu_ptr(fip->lp->dev_stats, - smp_processor_id()); stats->MissDiscAdvCount++; printk(KERN_INFO "libfcoe: host%d: " "Missing Discovery Advertisement " @@ -601,8 +601,6 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) WARN_ON(!fip->fcf_count); fip->fcf_count--; kfree(fcf); - stats = per_cpu_ptr(fip->lp->dev_stats, - smp_processor_id()); stats->VLinkFailureCount++; } else { if (time_after(next_timer, deadline)) @@ -612,6 +610,7 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) sel_time = fcf->time; } } + put_cpu(); if (sel_time && !fip->sel_fcf && !fip->sel_time) { sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); fip->sel_time = sel_time; @@ -768,7 +767,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) if (fcoe_ctlr_parse_adv(fip, skb, &new)) return; - spin_lock_bh(&fip->lock); + mutex_lock(&fip->ctlr_mutex); first = list_empty(&fip->fcfs); found = NULL; list_for_each_entry(fcf, &fip->fcfs, list) { @@ -847,7 +846,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) mod_timer(&fip->timer, fip->sel_time); } out: - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); } /** @@ -1108,11 +1107,12 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, if (is_vn_port) fc_lport_reset(vn_port); else { - spin_lock_bh(&fip->lock); + mutex_lock(&fip->ctlr_mutex); per_cpu_ptr(lport->dev_stats, - smp_processor_id())->VLinkFailureCount++; + get_cpu())->VLinkFailureCount++; + put_cpu(); fcoe_ctlr_reset(fip); - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); fc_lport_reset(fip->lp); fcoe_ctlr_solicit(fip, NULL); @@ -1166,7 +1166,7 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len) goto drop; - spin_lock_bh(&fip->lock); + mutex_lock(&fip->ctlr_mutex); state = fip->state; if (state == FIP_ST_AUTO) { fip->map_dest = 0; @@ -1174,7 +1174,7 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) state = FIP_ST_ENABLED; LIBFCOE_FIP_DBG(fip, "Using FIP mode\n"); } - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); if (state != FIP_ST_ENABLED) goto drop; @@ -1240,19 +1240,38 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) /** * fcoe_ctlr_timeout() - FIP timeout handler * @arg: The FCoE controller that timed out - * - * Ages FCFs. Triggers FCF selection if possible. Sends keep-alives. */ static void fcoe_ctlr_timeout(unsigned long arg) { struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg; + + schedule_work(&fip->timer_work); +} + +/** + * fcoe_ctlr_timer_work() - Worker thread function for timer work + * @work: Handle to a FCoE controller + * + * Ages FCFs. Triggers FCF selection if possible. + * Sends keep-alives and resets. + */ +static void fcoe_ctlr_timer_work(struct work_struct *work) +{ + struct fcoe_ctlr *fip; + struct fc_lport *vport; + u8 *mac; + u8 reset = 0; + u8 send_ctlr_ka = 0; + u8 send_port_ka = 0; struct fcoe_fcf *sel; struct fcoe_fcf *fcf; unsigned long next_timer; - spin_lock_bh(&fip->lock); + fip = container_of(work, struct fcoe_ctlr, timer_work); + + mutex_lock(&fip->ctlr_mutex); if (fip->state == FIP_ST_DISABLED) { - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); return; } @@ -1286,7 +1305,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) "FIP Fibre-Channel Forwarder timed out. " "Starting FCF discovery.\n", fip->lp->host->host_no); - fip->reset_req = 1; + reset = 1; schedule_work(&fip->timer_work); } } @@ -1294,7 +1313,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) if (sel && !sel->fd_flags) { if (time_after_eq(jiffies, fip->ctlr_ka_time)) { fip->ctlr_ka_time = jiffies + sel->fka_period; - fip->send_ctlr_ka = 1; + send_ctlr_ka = 1; } if (time_after(next_timer, fip->ctlr_ka_time)) next_timer = fip->ctlr_ka_time; @@ -1302,37 +1321,14 @@ static void fcoe_ctlr_timeout(unsigned long arg) if (time_after_eq(jiffies, fip->port_ka_time)) { fip->port_ka_time = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); - fip->send_port_ka = 1; + send_port_ka = 1; } if (time_after(next_timer, fip->port_ka_time)) next_timer = fip->port_ka_time; } if (!list_empty(&fip->fcfs)) mod_timer(&fip->timer, next_timer); - if (fip->send_ctlr_ka || fip->send_port_ka) - schedule_work(&fip->timer_work); - spin_unlock_bh(&fip->lock); -} - -/** - * fcoe_ctlr_timer_work() - Worker thread function for timer work - * @work: Handle to a FCoE controller - * - * Sends keep-alives and resets which must not - * be called from the timer directly, since they use a mutex. - */ -static void fcoe_ctlr_timer_work(struct work_struct *work) -{ - struct fcoe_ctlr *fip; - struct fc_lport *vport; - u8 *mac; - int reset; - - fip = container_of(work, struct fcoe_ctlr, timer_work); - spin_lock_bh(&fip->lock); - reset = fip->reset_req; - fip->reset_req = 0; - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); if (reset) { fc_lport_reset(fip->lp); @@ -1340,12 +1336,10 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) fcoe_ctlr_solicit(fip, NULL); } - if (fip->send_ctlr_ka) { - fip->send_ctlr_ka = 0; + if (send_ctlr_ka) fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr); - } - if (fip->send_port_ka) { - fip->send_port_ka = 0; + + if (send_port_ka) { mutex_lock(&fip->lp->lp_mutex); mac = fip->get_src_addr(fip->lp); fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac); @@ -1402,9 +1396,9 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP && fip->flogi_oxid == ntohs(fh->fh_ox_id)) { - spin_lock_bh(&fip->lock); + mutex_lock(&fip->ctlr_mutex); if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) { - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); return -EINVAL; } fip->state = FIP_ST_NON_FIP; @@ -1424,13 +1418,13 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, fip->map_dest = 0; } fip->flogi_oxid = FC_XID_UNKNOWN; - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); fc_fcoe_set_mac(fr_cb(fp)->granted_mac, fh->fh_d_id); } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { /* * Save source MAC for point-to-point responses. */ - spin_lock_bh(&fip->lock); + mutex_lock(&fip->ctlr_mutex); if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) { memcpy(fip->dest_addr, sa, ETH_ALEN); fip->map_dest = 0; @@ -1439,7 +1433,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, "Setting non-FIP mode\n"); fip->state = FIP_ST_NON_FIP; } - spin_unlock_bh(&fip->lock); + mutex_unlock(&fip->ctlr_mutex); } return 0; } diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 81aee1c4c2f3..7d18b500f2c1 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -75,14 +75,12 @@ enum fip_state { * @flogi_count: number of FLOGI attempts in AUTO mode. * @map_dest: use the FC_MAP mode for destination MAC addresses. * @spma: supports SPMA server-provided MACs mode - * @send_ctlr_ka: need to send controller keep alive - * @send_port_ka: need to send port keep alives * @dest_addr: MAC address of the selected FC forwarder. * @ctl_src_addr: the native MAC address of our local port. * @send: LLD-supplied function to handle sending FIP Ethernet frames * @update_mac: LLD-supplied function to handle changes to MAC addresses. * @get_src_addr: LLD-supplied function to supply a source MAC address. - * @lock: lock protecting this structure. + * @ctlr_mutex: lock protecting this structure. * * This structure is used by all FCoE drivers. It contains information * needed by all FCoE low-level drivers (LLDs) as well as internal state @@ -106,18 +104,15 @@ struct fcoe_ctlr { u16 user_mfs; u16 flogi_oxid; u8 flogi_count; - u8 reset_req; u8 map_dest; u8 spma; - u8 send_ctlr_ka; - u8 send_port_ka; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; void (*send)(struct fcoe_ctlr *, struct sk_buff *); void (*update_mac)(struct fc_lport *, u8 *addr); u8 * (*get_src_addr)(struct fc_lport *); - spinlock_t lock; + struct mutex ctlr_mutex; }; /** -- cgit v1.2.3 From 0685230c59b5482e04ab50e7afc51119ceaba651 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:19:53 -0700 Subject: [SCSI] libfc: add discovery-private pointer for LLD For VN_port to VN_port mode, FIP will do discovery and needs a way to find its state from the local port or discovery structure. It seems that any other LLD that implements its own discovery would also need something like this. Replace disc->lport with disc->priv, and use container_of to find the lport. We could use disc->priv for that, but container_of is smaller and faster. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 14 +++++++------- drivers/scsi/libfc/fc_libfc.h | 2 +- include/scsi/libfc.h | 9 +++++++-- 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index d0fa9a0ddc8d..04474556f2dc 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -65,7 +65,7 @@ void fc_disc_stop_rports(struct fc_disc *disc) struct fc_lport *lport; struct fc_rport_priv *rdata; - lport = disc->lport; + lport = fc_disc_lport(disc); mutex_lock(&disc->disc_mutex); list_for_each_entry_rcu(rdata, &disc->rports, peers) @@ -96,7 +96,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, LIST_HEAD(disc_ports); struct fc_disc_port *dp, *next; - lport = disc->lport; + lport = fc_disc_lport(disc); FC_DISC_DBG(disc, "Received an RSCN event\n"); @@ -275,7 +275,7 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *, */ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) { - struct fc_lport *lport = disc->lport; + struct fc_lport *lport = fc_disc_lport(disc); struct fc_rport_priv *rdata; FC_DISC_DBG(disc, "Discovery complete\n"); @@ -313,7 +313,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) */ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) { - struct fc_lport *lport = disc->lport; + struct fc_lport *lport = fc_disc_lport(disc); unsigned long delay = 0; FC_DISC_DBG(disc, "Error %ld, retries %d/%d\n", @@ -353,7 +353,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) static void fc_disc_gpn_ft_req(struct fc_disc *disc) { struct fc_frame *fp; - struct fc_lport *lport = disc->lport; + struct fc_lport *lport = fc_disc_lport(disc); WARN_ON(!fc_lport_test_ready(lport)); @@ -396,7 +396,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) struct fc_rport_identifiers ids; struct fc_rport_priv *rdata; - lport = disc->lport; + lport = fc_disc_lport(disc); disc->seq_count++; /* @@ -733,7 +733,7 @@ int fc_disc_init(struct fc_lport *lport) mutex_init(&disc->disc_mutex); INIT_LIST_HEAD(&disc->rports); - disc->lport = lport; + disc->priv = lport; return 0; } diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h index f5c0ca4b6ef8..16d2162dda1f 100644 --- a/drivers/scsi/libfc/fc_libfc.h +++ b/drivers/scsi/libfc/fc_libfc.h @@ -52,7 +52,7 @@ extern unsigned int fc_debug_logging; #define FC_DISC_DBG(disc, fmt, args...) \ FC_CHECK_LOGGING(FC_DISC_LOGGING, \ printk(KERN_INFO "host%u: disc: " fmt, \ - (disc)->lport->host->host_no, \ + fc_disc_lport(disc)->host->host_no, \ ##args)) #define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \ diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index fcbee8c38b0c..5f64e593cca8 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -739,7 +739,7 @@ struct libfc_function_template { * @buf_len: Length of the discovery buffer * @disc_id: Discovery ID * @rports: List of discovered remote ports - * @lport: The local port that discovery is for + * @priv: Private pointer for use by discovery code * @disc_mutex: Mutex that protects the discovery context * @partial_buf: Partial name buffer (if names are returned * in multiple frames) @@ -755,7 +755,7 @@ struct fc_disc { u16 disc_id; struct list_head rports; - struct fc_lport *lport; + void *priv; struct mutex disc_mutex; struct fc_gpn_ft_resp partial_buf; struct delayed_work disc_work; @@ -1003,6 +1003,11 @@ void fc_rport_terminate_io(struct fc_rport *); *****************************/ int fc_disc_init(struct fc_lport *); +static inline struct fc_lport *fc_disc_lport(struct fc_disc *disc) +{ + return container_of(disc, struct fc_lport, disc); +} + /* * FCP LAYER *****************************/ -- cgit v1.2.3 From 3d902ac09a2812b359edf633425d1327a18399e9 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:19:58 -0700 Subject: [SCSI] libfcoe: fcoe: fnic: change fcoe_ctlr_init interface to specify mode There are three modes that libfcoe currently supports, and a new one is coming. Change the fcoe_ctlr_init() interface to add the mode desired. This should not change any functionality. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 2 +- drivers/scsi/fcoe/libfcoe.c | 4 ++-- drivers/scsi/fnic/fnic_main.c | 4 ++-- include/scsi/libfcoe.h | 11 ++++++++++- 4 files changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index a120962b25b8..9d64e08305c7 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -357,7 +357,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) /* * Initialize FIP. */ - fcoe_ctlr_init(&fcoe->ctlr); + fcoe_ctlr_init(&fcoe->ctlr, FIP_MODE_AUTO); fcoe->ctlr.send = fcoe_fip_send; fcoe->ctlr.update_mac = fcoe_update_src_mac; fcoe->ctlr.get_src_addr = fcoe_get_src_mac; diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index e510888e78ca..76056e4c9297 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -108,10 +108,10 @@ static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf) * fcoe_ctlr_init() - Initialize the FCoE Controller instance * @fip: The FCoE controller to initialize */ -void fcoe_ctlr_init(struct fcoe_ctlr *fip) +void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) { fip->state = FIP_ST_LINK_WAIT; - fip->mode = FIP_ST_AUTO; + fip->mode = mode; INIT_LIST_HEAD(&fip->fcfs); mutex_init(&fip->ctlr_mutex); fip->flogi_oxid = FC_XID_UNKNOWN; diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 265e73d9cd6f..d0fe1c3345b8 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -617,7 +617,6 @@ static int __devinit fnic_probe(struct pci_dev *pdev, fnic->ctlr.send = fnic_eth_send; fnic->ctlr.update_mac = fnic_update_mac; fnic->ctlr.get_src_addr = fnic_get_mac; - fcoe_ctlr_init(&fnic->ctlr); if (fnic->config.flags & VFCF_FIP_CAPABLE) { shost_printk(KERN_INFO, fnic->lport->host, "firmware supports FIP\n"); @@ -625,10 +624,11 @@ static int __devinit fnic_probe(struct pci_dev *pdev, vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0); vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS); vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); + fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO); } else { shost_printk(KERN_INFO, fnic->lport->host, "firmware uses non-FIP mode\n"); - fnic->ctlr.mode = FIP_ST_NON_FIP; + fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_NON_FIP); } fnic->state = FNIC_IN_FC_MODE; diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 7d18b500f2c1..1a84a3182da0 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -54,6 +54,15 @@ enum fip_state { FIP_ST_ENABLED, }; +/* + * Modes: + * The mode is the state that is to be entered after link up. + * It must not change after fcoe_ctlr_init() sets it. + */ +#define FIP_MODE_AUTO FIP_ST_AUTO +#define FIP_MODE_NON_FIP FIP_ST_NON_FIP +#define FIP_MODE_FABRIC FIP_ST_ENABLED + /** * struct fcoe_ctlr - FCoE Controller and FIP state * @state: internal FIP state for network link and FIP or non-FIP mode. @@ -152,7 +161,7 @@ struct fcoe_fcf { }; /* FIP API functions */ -void fcoe_ctlr_init(struct fcoe_ctlr *); +void fcoe_ctlr_init(struct fcoe_ctlr *, enum fip_state); void fcoe_ctlr_destroy(struct fcoe_ctlr *); void fcoe_ctlr_link_up(struct fcoe_ctlr *); int fcoe_ctlr_link_down(struct fcoe_ctlr *); -- cgit v1.2.3 From 3726f3584e113697b68d3d4ff1ecf1042a06f800 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:03 -0700 Subject: [SCSI] libfc: Add local port point-to-multipoint flag For VN_port to VN_port mode, the transport sets the port_id and there's no lport FLOGI. This is similar to FC loop mode. Add a point_to_multipoint flag that indicates the local port is in point-to-multipoint mode. This skips FLOGI and discovery. It also skips resetting the port_id on resets other than link down. Add function fc_lport_set_local_id() that sets the local port_id. This is called by libfcoe on behalf of the low-level driver to set the port_id when the link comes up. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 36 +++++++++++++++++++++++++++++++++++- include/scsi/libfc.h | 2 ++ 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 79c9e3ccd341..f7bff2cad4ee 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -754,6 +754,34 @@ static void fc_lport_set_port_id(struct fc_lport *lport, u32 port_id, lport->tt.lport_set_port_id(lport, port_id, fp); } +/** + * fc_lport_set_port_id() - set the local port Port ID for point-to-multipoint + * @lport: The local port which will have its Port ID set. + * @port_id: The new port ID. + * + * Called by the lower-level driver when transport sets the local port_id. + * This is used in VN_port to VN_port mode for FCoE, and causes FLOGI and + * discovery to be skipped. + */ +void fc_lport_set_local_id(struct fc_lport *lport, u32 port_id) +{ + mutex_lock(&lport->lp_mutex); + + fc_lport_set_port_id(lport, port_id, NULL); + + switch (lport->state) { + case LPORT_ST_RESET: + case LPORT_ST_FLOGI: + if (port_id) + fc_lport_enter_ready(lport); + break; + default: + break; + } + mutex_unlock(&lport->lp_mutex); +} +EXPORT_SYMBOL(fc_lport_set_local_id); + /** * fc_lport_recv_flogi_req() - Receive a FLOGI request * @sp_in: The sequence the FLOGI is on @@ -954,7 +982,7 @@ static void fc_lport_reset_locked(struct fc_lport *lport) lport->tt.exch_mgr_reset(lport, 0, 0); fc_host_fabric_name(lport->host) = 0; - if (lport->port_id) + if (lport->port_id && (!lport->point_to_multipoint || !lport->link_up)) fc_lport_set_port_id(lport, 0, NULL); } @@ -1536,6 +1564,12 @@ void fc_lport_enter_flogi(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_FLOGI); + if (lport->point_to_multipoint) { + if (lport->port_id) + fc_lport_enter_ready(lport); + return; + } + fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) return fc_lport_error(lport, fp); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 5f64e593cca8..bd0560509ce6 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -846,6 +846,7 @@ struct fc_lport { u32 lro_enabled:1; u32 does_npiv:1; u32 npiv_enabled:1; + u32 point_to_multipoint:1; u32 mfs; u8 max_retry_count; u8 max_rport_retry_count; @@ -991,6 +992,7 @@ int fc_set_mfs(struct fc_lport *, u32 mfs); struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize); struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id); int fc_lport_bsg_request(struct fc_bsg_job *); +void fc_lport_set_local_id(struct fc_lport *, u32 port_id); /* * REMOTE PORT LAYER -- cgit v1.2.3 From a7b12a279faaad26837276065104a1f9cf60e962 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:08 -0700 Subject: [SCSI] libfc: add FLOGI state to rport for VN2VN The FIP proposal for VN_port to VN_port point-to-multipoint operation requires a FLOGI be sent to each remote port. The FLOGI is sent with the assigned S_ID and D_IDs of the local and remote ports. This and the response get FIP-encapsulated for Ethernet. Add FLOGI state to the remote port state machine. This will be skipped if not in point-to-multipoint mode. To reduce a little duplication between PLOGI and FLOGI response handling, added fc_rport_login_complete(), which handles the parameters for the rdata struct. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 4 +- drivers/scsi/libfc/fc_rport.c | 290 ++++++++++++++++++++++++++++++++++++++++-- include/scsi/fc/fc_els.h | 2 + include/scsi/libfc.h | 4 + 4 files changed, 286 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index f7bff2cad4ee..ec9850c46170 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -906,10 +906,10 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, recv = lport->tt.rport_recv_req; switch (fc_frame_payload_op(fp)) { case ELS_FLOGI: - recv = fc_lport_recv_flogi_req; + if (!lport->point_to_multipoint) + recv = fc_lport_recv_flogi_req; break; case ELS_LOGO: - fh = fc_frame_header_get(fp); if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI) recv = fc_lport_recv_logo_req; break; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6d68482649c9..4d6adf29b4f8 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -60,6 +60,7 @@ struct workqueue_struct *rport_event_queue; +static void fc_rport_enter_flogi(struct fc_rport_priv *); static void fc_rport_enter_plogi(struct fc_rport_priv *); static void fc_rport_enter_prli(struct fc_rport_priv *); static void fc_rport_enter_rtv(struct fc_rport_priv *); @@ -82,6 +83,8 @@ static void fc_rport_work(struct work_struct *); static const char *fc_rport_state_names[] = { [RPORT_ST_INIT] = "Init", + [RPORT_ST_FLOGI] = "FLOGI", + [RPORT_ST_PLOGI_WAIT] = "PLOGI_WAIT", [RPORT_ST_PLOGI] = "PLOGI", [RPORT_ST_PRLI] = "PRLI", [RPORT_ST_RTV] = "RTV", @@ -207,7 +210,7 @@ EXPORT_SYMBOL(fc_set_rport_loss_tmo); /** * fc_plogi_get_maxframe() - Get the maximum payload from the common service * parameters in a FLOGI frame - * @flp: The FLOGI payload + * @flp: The FLOGI or PLOGI payload * @maxval: The maximum frame size upper limit; this may be less than what * is in the service parameters */ @@ -344,7 +347,7 @@ static void fc_rport_work(struct work_struct *work) rdata->major_retries++; rdata->event = RPORT_EV_NONE; FC_RPORT_DBG(rdata, "work restart\n"); - fc_rport_enter_plogi(rdata); + fc_rport_enter_flogi(rdata); mutex_unlock(&rdata->rp_mutex); } else { FC_RPORT_DBG(rdata, "work delete\n"); @@ -397,7 +400,7 @@ int fc_rport_login(struct fc_rport_priv *rdata) break; default: FC_RPORT_DBG(rdata, "Login to port\n"); - fc_rport_enter_plogi(rdata); + fc_rport_enter_flogi(rdata); break; } mutex_unlock(&rdata->rp_mutex); @@ -499,6 +502,9 @@ static void fc_rport_timeout(struct work_struct *work) mutex_lock(&rdata->rp_mutex); switch (rdata->rp_state) { + case RPORT_ST_FLOGI: + fc_rport_enter_flogi(rdata); + break; case RPORT_ST_PLOGI: fc_rport_enter_plogi(rdata); break; @@ -514,6 +520,7 @@ static void fc_rport_timeout(struct work_struct *work) case RPORT_ST_ADISC: fc_rport_enter_adisc(rdata); break; + case RPORT_ST_PLOGI_WAIT: case RPORT_ST_READY: case RPORT_ST_INIT: case RPORT_ST_DELETE: @@ -538,6 +545,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) fc_rport_state(rdata), rdata->retries); switch (rdata->rp_state) { + case RPORT_ST_FLOGI: case RPORT_ST_PLOGI: case RPORT_ST_LOGO: rdata->flags &= ~FC_RP_STARTED; @@ -550,6 +558,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) case RPORT_ST_ADISC: fc_rport_enter_logo(rdata); break; + case RPORT_ST_PLOGI_WAIT: case RPORT_ST_DELETE: case RPORT_ST_READY: case RPORT_ST_INIT: @@ -592,7 +601,260 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, } /** - * fc_rport_plogi_recv_resp() - Handler for ELS PLOGI responses + * fc_rport_login_complete() - Handle parameters and completion of p-mp login. + * @rdata: The remote port which we logged into or which logged into us. + * @fp: The FLOGI or PLOGI request or response frame + * + * Returns non-zero error if a problem is detected with the frame. + * Does not free the frame. + * + * This is only used in point-to-multipoint mode for FIP currently. + */ +static int fc_rport_login_complete(struct fc_rport_priv *rdata, + struct fc_frame *fp) +{ + struct fc_lport *lport = rdata->local_port; + struct fc_els_flogi *flogi; + unsigned int e_d_tov; + u16 csp_flags; + + flogi = fc_frame_payload_get(fp, sizeof(*flogi)); + if (!flogi) + return -EINVAL; + + csp_flags = ntohs(flogi->fl_csp.sp_features); + + if (fc_frame_payload_op(fp) == ELS_FLOGI) { + if (csp_flags & FC_SP_FT_FPORT) { + FC_RPORT_DBG(rdata, "Fabric bit set in FLOGI\n"); + return -EINVAL; + } + } else { + + /* + * E_D_TOV is not valid on an incoming FLOGI request. + */ + e_d_tov = ntohl(flogi->fl_csp.sp_e_d_tov); + if (csp_flags & FC_SP_FT_EDTR) + e_d_tov /= 1000000; + if (e_d_tov > rdata->e_d_tov) + rdata->e_d_tov = e_d_tov; + } + rdata->maxframe_size = fc_plogi_get_maxframe(flogi, lport->mfs); + return 0; +} + +/** + * fc_rport_flogi_resp() - Handle response to FLOGI request for p-mp mode + * @sp: The sequence that the FLOGI was on + * @fp: The FLOGI response frame + * @rp_arg: The remote port that received the FLOGI response + */ +void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, + void *rp_arg) +{ + struct fc_rport_priv *rdata = rp_arg; + struct fc_lport *lport = rdata->local_port; + struct fc_els_flogi *flogi; + unsigned int r_a_tov; + + FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp)); + + if (fp == ERR_PTR(-FC_EX_CLOSED)) + return; + + mutex_lock(&rdata->rp_mutex); + + if (rdata->rp_state != RPORT_ST_FLOGI) { + FC_RPORT_DBG(rdata, "Received a FLOGI response, but in state " + "%s\n", fc_rport_state(rdata)); + if (IS_ERR(fp)) + goto err; + goto out; + } + + if (IS_ERR(fp)) { + fc_rport_error(rdata, fp); + goto err; + } + + if (fc_frame_payload_op(fp) != ELS_LS_ACC) + goto bad; + if (fc_rport_login_complete(rdata, fp)) + goto bad; + + flogi = fc_frame_payload_get(fp, sizeof(*flogi)); + if (!flogi) + goto bad; + r_a_tov = ntohl(flogi->fl_csp.sp_r_a_tov); + if (r_a_tov > rdata->r_a_tov) + rdata->r_a_tov = r_a_tov; + + if (rdata->ids.port_name < lport->wwpn) + fc_rport_enter_plogi(rdata); + else + fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT); +out: + fc_frame_free(fp); +err: + mutex_unlock(&rdata->rp_mutex); + kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + return; +bad: + FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); + fc_rport_error_retry(rdata, fp); + goto out; +} + +/** + * fc_rport_enter_flogi() - Send a FLOGI request to the remote port for p-mp + * @rdata: The remote port to send a FLOGI to + * + * Locking Note: The rport lock is expected to be held before calling + * this routine. + */ +static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) +{ + struct fc_lport *lport = rdata->local_port; + struct fc_frame *fp; + + if (!lport->point_to_multipoint) + return fc_rport_enter_plogi(rdata); + + FC_RPORT_DBG(rdata, "Entered FLOGI state from %s state\n", + fc_rport_state(rdata)); + + fc_rport_state_enter(rdata, RPORT_ST_FLOGI); + + fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); + if (!fp) + return fc_rport_error_retry(rdata, fp); + + if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI, + fc_rport_flogi_resp, rdata, + 2 * lport->r_a_tov)) + fc_rport_error_retry(rdata, NULL); + else + kref_get(&rdata->kref); +} + +/** + * fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode + * @lport: The local port that received the PLOGI request + * @sp: The sequence that the PLOGI request was on + * @rx_fp: The PLOGI request frame + */ +static void fc_rport_recv_flogi_req(struct fc_lport *lport, + struct fc_seq *sp, struct fc_frame *rx_fp) +{ + struct fc_disc *disc; + struct fc_els_flogi *flp; + struct fc_rport_priv *rdata; + struct fc_frame *fp = rx_fp; + struct fc_exch *ep; + struct fc_frame_header *fh; + struct fc_seq_els_data rjt_data; + u32 sid, f_ctl; + + rjt_data.fp = NULL; + fh = fc_frame_header_get(fp); + sid = ntoh24(fh->fh_s_id); + + FC_RPORT_ID_DBG(lport, sid, "Received FLOGI request\n"); + + disc = &lport->disc; + mutex_lock(&disc->disc_mutex); + + if (!lport->point_to_multipoint) { + rjt_data.reason = ELS_RJT_UNSUP; + rjt_data.explan = ELS_EXPL_NONE; + goto reject; + } + + flp = fc_frame_payload_get(fp, sizeof(*flp)); + if (!flp) { + rjt_data.reason = ELS_RJT_LOGIC; + rjt_data.explan = ELS_EXPL_INV_LEN; + goto reject; + } + + rdata = lport->tt.rport_lookup(lport, sid); + if (!rdata) { + rjt_data.reason = ELS_RJT_FIP; + rjt_data.explan = ELS_EXPL_NOT_NEIGHBOR; + goto reject; + } + mutex_lock(&rdata->rp_mutex); + + FC_RPORT_DBG(rdata, "Received FLOGI in %s state\n", + fc_rport_state(rdata)); + + switch (rdata->rp_state) { + case RPORT_ST_INIT: + case RPORT_ST_LOGO: + case RPORT_ST_DELETE: + mutex_unlock(&rdata->rp_mutex); + rjt_data.reason = ELS_RJT_FIP; + rjt_data.explan = ELS_EXPL_NOT_NEIGHBOR; + goto reject; + case RPORT_ST_FLOGI: + case RPORT_ST_PLOGI_WAIT: + case RPORT_ST_PLOGI: + break; + case RPORT_ST_PRLI: + case RPORT_ST_RTV: + case RPORT_ST_READY: + case RPORT_ST_ADISC: + /* + * Set the remote port to be deleted and to then restart. + * This queues work to be sure exchanges are reset. + */ + fc_rport_enter_delete(rdata, RPORT_EV_LOGO); + mutex_unlock(&rdata->rp_mutex); + rjt_data.reason = ELS_RJT_BUSY; + rjt_data.explan = ELS_EXPL_NONE; + goto reject; + } + if (fc_rport_login_complete(rdata, fp)) { + mutex_unlock(&rdata->rp_mutex); + rjt_data.reason = ELS_RJT_LOGIC; + rjt_data.explan = ELS_EXPL_NONE; + goto reject; + } + fc_frame_free(rx_fp); + + fp = fc_frame_alloc(lport, sizeof(*flp)); + if (!fp) + goto out; + + sp = lport->tt.seq_start_next(sp); + fc_flogi_fill(lport, fp); + flp = fc_frame_payload_get(fp, sizeof(*flp)); + flp->fl_cmd = ELS_LS_ACC; + + f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; + ep = fc_seq_exch(sp); + fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, + FC_TYPE_ELS, f_ctl, 0); + lport->tt.seq_send(lport, sp, fp); + + if (rdata->ids.port_name < lport->wwpn) + fc_rport_enter_plogi(rdata); + else + fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT); +out: + mutex_unlock(&rdata->rp_mutex); + mutex_unlock(&disc->disc_mutex); + return; + +reject: + mutex_unlock(&disc->disc_mutex); + lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + fc_frame_free(fp); +} + +/** + * fc_rport_plogi_resp() - Handler for ELS PLOGI responses * @sp: The sequence the PLOGI is on * @fp: The PLOGI response frame * @rdata_arg: The remote port that sent the PLOGI response @@ -607,7 +869,6 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_rport_priv *rdata = rdata_arg; struct fc_lport *lport = rdata->local_port; struct fc_els_flogi *plp = NULL; - unsigned int tov; u16 csp_seq; u16 cssp_seq; u8 op; @@ -635,11 +896,8 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn); rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn); - tov = ntohl(plp->fl_csp.sp_e_d_tov); - if (ntohs(plp->fl_csp.sp_features) & FC_SP_FT_EDTR) - tov /= 1000000; - if (tov > rdata->e_d_tov) - rdata->e_d_tov = tov; + if (lport->point_to_multipoint) + fc_rport_login_complete(rdata, fp); csp_seq = ntohs(plp->fl_csp.sp_tot_seq); cssp_seq = ntohs(plp->fl_cssp[3 - 1].cp_con_seq); if (cssp_seq < csp_seq) @@ -677,6 +935,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) rdata->maxframe_size = FC_MIN_MAX_PAYLOAD; fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) { + FC_RPORT_DBG(rdata, "%s frame alloc failed\n", __func__); fc_rport_error_retry(rdata, fp); return; } @@ -1041,7 +1300,7 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, get_unaligned_be64(&adisc->adisc_wwpn) != rdata->ids.port_name || get_unaligned_be64(&adisc->adisc_wwnn) != rdata->ids.node_name) { FC_RPORT_DBG(rdata, "ADISC error or mismatch\n"); - fc_rport_enter_plogi(rdata); + fc_rport_enter_flogi(rdata); } else { FC_RPORT_DBG(rdata, "ADISC OK\n"); fc_rport_enter_ready(rdata); @@ -1291,12 +1550,15 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, struct fc_seq_els_data els_data; /* - * Handle PLOGI and LOGO requests separately, since they + * Handle FLOGI, PLOGI and LOGO requests separately, since they * don't require prior login. * Check for unsupported opcodes first and reject them. * For some ops, it would be incorrect to reject with "PLOGI required". */ switch (fc_frame_payload_op(fp)) { + case ELS_FLOGI: + fc_rport_recv_flogi_req(lport, sp, fp); + break; case ELS_PLOGI: fc_rport_recv_plogi_req(lport, sp, fp); break; @@ -1386,6 +1648,9 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, case RPORT_ST_INIT: FC_RPORT_DBG(rdata, "Received PLOGI in INIT state\n"); break; + case RPORT_ST_PLOGI_WAIT: + FC_RPORT_DBG(rdata, "Received PLOGI in PLOGI_WAIT state\n"); + break; case RPORT_ST_PLOGI: FC_RPORT_DBG(rdata, "Received PLOGI in PLOGI state\n"); if (rdata->ids.port_name < lport->wwpn) { @@ -1403,6 +1668,7 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, "- ignored for now\n", rdata->rp_state); /* XXX TBD - should reset */ break; + case RPORT_ST_FLOGI: case RPORT_ST_DELETE: case RPORT_ST_LOGO: FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", diff --git a/include/scsi/fc/fc_els.h b/include/scsi/fc/fc_els.h index 70a7e92a7664..481abbd48e39 100644 --- a/include/scsi/fc/fc_els.h +++ b/include/scsi/fc/fc_els.h @@ -191,6 +191,7 @@ enum fc_els_rjt_reason { ELS_RJT_UNAB = 0x09, /* unable to perform command request */ ELS_RJT_UNSUP = 0x0b, /* command not supported */ ELS_RJT_INPROG = 0x0e, /* command already in progress */ + ELS_RJT_FIP = 0x20, /* FIP error */ ELS_RJT_VENDOR = 0xff, /* vendor specific error */ }; @@ -212,6 +213,7 @@ enum fc_els_rjt_explan { ELS_EXPL_UNAB_DATA = 0x2a, /* unable to supply requested data */ ELS_EXPL_UNSUPR = 0x2c, /* Request not supported */ ELS_EXPL_INV_LEN = 0x2d, /* Invalid payload length */ + ELS_EXPL_NOT_NEIGHBOR = 0x62, /* VN2VN_Port not in neighbor set */ /* TBD - above definitions incomplete */ }; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index bd0560509ce6..24b91c922055 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -97,6 +97,8 @@ enum fc_disc_event { /** * enum fc_rport_state - Remote port states * @RPORT_ST_INIT: Initialized + * @RPORT_ST_FLOGI: Waiting for FLOGI completion for point-to-multipoint + * @RPORT_ST_PLOGI_WAIT: Waiting for peer to login for point-to-multipoint * @RPORT_ST_PLOGI: Waiting for PLOGI completion * @RPORT_ST_PRLI: Waiting for PRLI completion * @RPORT_ST_RTV: Waiting for RTV completion @@ -107,6 +109,8 @@ enum fc_disc_event { */ enum fc_rport_state { RPORT_ST_INIT, + RPORT_ST_FLOGI, + RPORT_ST_PLOGI_WAIT, RPORT_ST_PLOGI, RPORT_ST_PRLI, RPORT_ST_RTV, -- cgit v1.2.3 From f60e12e9c778c8256a646f80603d1b88ba5ce891 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:14 -0700 Subject: [SCSI] libfc: track FIP exchanges When an exchange is received with a FIP encapsulation, we need to know that the response must be sent via FIP and what the original ELS opcode was. This becomes important for VN2VN mode, where we may receive FLOGI or LOGO from several peer VN_ports, and the LS_ACC or LS_RJT must be sent FIP-encapsulated with the correct sub-type. Add a field to the struct fc_frame, fr_encaps, to indicate the encapsulation values. That term is chosen to be neutral and LLD-agnostic in case non-FCoE/FIP LLDs might find it useful. The frame fr_encaps is transferred from the ingress frame to the exchange by fc_exch_recv_req(), and back to the outgoing frame by fc_seq_send(). This is taking the last byte in the skb->cb array. If needed, we could combine the info in sof, eof, flags, and encaps together into one field, but it'd be better to do that if and when its needed. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 ++ include/scsi/fc_frame.h | 3 +++ include/scsi/libfc.h | 2 ++ 3 files changed, 7 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 104e0fba7c43..61eabd3ce436 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -464,6 +464,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, f_ctl = ntoh24(fh->fh_f_ctl); fc_exch_setup_hdr(ep, fp, f_ctl); + fr_encaps(fp) = ep->encaps; /* * update sequence count if this frame is carrying @@ -1259,6 +1260,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, sp = fr_seq(fp); /* sequence will be held */ ep = fc_seq_exch(sp); fc_seq_send_ack(sp, fp); + ep->encaps = fr_encaps(fp); /* * Call the receive function. diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h index 15427fab8a57..29dd97d5b53a 100644 --- a/include/scsi/fc_frame.h +++ b/include/scsi/fc_frame.h @@ -51,6 +51,7 @@ #define fr_sof(fp) (fr_cb(fp)->fr_sof) #define fr_eof(fp) (fr_cb(fp)->fr_eof) #define fr_flags(fp) (fr_cb(fp)->fr_flags) +#define fr_encaps(fp) (fr_cb(fp)->fr_encaps) #define fr_max_payload(fp) (fr_cb(fp)->fr_max_payload) #define fr_fsp(fp) (fr_cb(fp)->fr_fsp) #define fr_crc(fp) (fr_cb(fp)->fr_crc) @@ -69,6 +70,7 @@ struct fcoe_rcv_info { u8 fr_sof; /* start of frame delimiter */ u8 fr_eof; /* end of frame delimiter */ u8 fr_flags; /* flags - see below */ + u8 fr_encaps; /* LLD encapsulation info (e.g. FIP) */ u8 granted_mac[ETH_ALEN]; /* FCoE MAC address */ }; @@ -97,6 +99,7 @@ static inline void fc_frame_init(struct fc_frame *fp) fr_dev(fp) = NULL; fr_seq(fp) = NULL; fr_flags(fp) = 0; + fr_encaps(fp) = 0; } struct fc_frame *fc_frame_alloc_fill(struct fc_lport *, size_t payload_len); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 24b91c922055..8d297f9a0a47 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -412,6 +412,7 @@ struct fc_seq { * @esb_stat: ESB exchange status * @r_a_tov: Resouce allocation time out value (in msecs) * @seq_id: The next sequence ID to use + * @encaps: encapsulation information for lower-level driver * @f_ctl: F_CTL flags for the sequence * @fh_type: The frame type * @class: The class of service @@ -443,6 +444,7 @@ struct fc_exch { u32 esb_stat; u32 r_a_tov; u8 seq_id; + u8 encaps; u32 f_ctl; u8 fh_type; enum fc_class class; -- cgit v1.2.3 From 9b651da900ccfe5581befb46eb06ef781a1d7e74 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:24 -0700 Subject: [SCSI] libfcoe: add state change debugging Enhancement: add debug messages at all state transitions. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 48 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 76056e4c9297..11f3db5e506b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -80,6 +80,40 @@ do { \ printk(KERN_INFO "host%d: fip: " fmt, \ (fip)->lp->host->host_no, ##args);) +static const char *fcoe_ctlr_states[] = { + [FIP_ST_DISABLED] = "DISABLED", + [FIP_ST_LINK_WAIT] = "LINK_WAIT", + [FIP_ST_AUTO] = "AUTO", + [FIP_ST_NON_FIP] = "NON_FIP", + [FIP_ST_ENABLED] = "ENABLED", +}; + +static const char *fcoe_ctlr_state(enum fip_state state) +{ + const char *cp = "unknown"; + + if (state < ARRAY_SIZE(fcoe_ctlr_states)) + cp = fcoe_ctlr_states[state]; + if (!cp) + cp = "unknown"; + return cp; +} + +/** + * fcoe_ctlr_set_state() - Set and do debug printing for the new FIP state. + * @fip: The FCoE controller + * @state: The new state + */ +static void fcoe_ctlr_set_state(struct fcoe_ctlr *fip, enum fip_state state) +{ + if (state == fip->state) + return; + if (fip->lp) + LIBFCOE_FIP_DBG(fip, "state %s -> %s\n", + fcoe_ctlr_state(fip->state), fcoe_ctlr_state(state)); + fip->state = state; +} + /** * fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid * @fcf: The FCF to check @@ -110,7 +144,7 @@ static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf) */ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) { - fip->state = FIP_ST_LINK_WAIT; + fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT); fip->mode = mode; INIT_LIST_HEAD(&fip->fcfs); mutex_init(&fip->ctlr_mutex); @@ -160,7 +194,7 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) skb_queue_purge(&fip->fip_recv_list); mutex_lock(&fip->ctlr_mutex); - fip->state = FIP_ST_DISABLED; + fcoe_ctlr_set_state(fip, FIP_ST_DISABLED); fcoe_ctlr_reset_fcfs(fip); mutex_unlock(&fip->ctlr_mutex); del_timer_sync(&fip->timer); @@ -260,7 +294,7 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) mutex_unlock(&fip->ctlr_mutex); fc_linkup(fip->lp); } else if (fip->state == FIP_ST_LINK_WAIT) { - fip->state = fip->mode; + fcoe_ctlr_set_state(fip, fip->mode); mutex_unlock(&fip->ctlr_mutex); if (fip->state == FIP_ST_AUTO) LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); @@ -303,7 +337,7 @@ int fcoe_ctlr_link_down(struct fcoe_ctlr *fip) mutex_lock(&fip->ctlr_mutex); fcoe_ctlr_reset(fip); link_dropped = fip->state != FIP_ST_LINK_WAIT; - fip->state = FIP_ST_LINK_WAIT; + fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT); mutex_unlock(&fip->ctlr_mutex); if (link_dropped) @@ -1170,7 +1204,7 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) state = fip->state; if (state == FIP_ST_AUTO) { fip->map_dest = 0; - fip->state = FIP_ST_ENABLED; + fcoe_ctlr_set_state(fip, FIP_ST_ENABLED); state = FIP_ST_ENABLED; LIBFCOE_FIP_DBG(fip, "Using FIP mode\n"); } @@ -1401,7 +1435,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, mutex_unlock(&fip->ctlr_mutex); return -EINVAL; } - fip->state = FIP_ST_NON_FIP; + fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP); LIBFCOE_FIP_DBG(fip, "received FLOGI LS_ACC using non-FIP mode\n"); @@ -1431,7 +1465,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, if (fip->state == FIP_ST_AUTO) LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. " "Setting non-FIP mode\n"); - fip->state = FIP_ST_NON_FIP; + fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP); } mutex_unlock(&fip->ctlr_mutex); } -- cgit v1.2.3 From e10f8c667b874a57512c936089092a3d1ef7ab8a Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:30 -0700 Subject: [SCSI] libfcoe: fcoe: fnic: add FIP VN2VN point-to-multipoint support The FC-BB-6 committee is proposing a new FIP usage model called VN_port to VN_port mode. It allows VN_ports to discover each other over a loss-free L2 Ethernet without any FCF or Fibre-channel fabric services. This is point-to-multipoint. There is also a variant of this called point-to-point which provides for making sure there is just one pair of ports operating over the Ethernet fabric. We add these new states: VNMP_START, _PROBE1, _PROBE2, _CLAIM, and _UP. These usually go quickly in that sequence. After waiting a random amount of time up to 100 ms in START, we select a pseudo-random proposed locally-unique port ID and send out probes in states PROBE1 and PROBE2, 100 ms apart. If no probe responses are heard, we proceed to CLAIM state 400 ms later and send a claim notification. We wait another 400 ms to receive claim responses, which give us a list of the other nodes on the network, including their FC-4 capabilities. After another 400 ms we go to VNMP_UP state and should start interoperating with any of the nodes for whic we receivec claim responses. More details are in the spec.j Add the new mode as FIP_MODE_VN2VN. The driver must specify explicitly that it wants to operate in this mode. There is no automatic detection between point-to-multipoint and fabric mode, and the local port initialization is affected, so it isn't anticipated that there will ever be any such automatic switchover. It may eventually be possible to have both fabric and VN2VN modes on the same L2 network, which may be done by two separate local VN_ports (lports). When in VN2VN mode, FIP replaces libfc's fabric-oriented discovery module with its own simple code that adds remote ports as they are discovered from incoming claim notifications and responses. These hooks are placed by fcoe_disc_init(). A linear list of discovered vn_ports is maintained under the fcoe_ctlr struct. It is expected to be short for now, and accessed infrequently. It is kept under RCU for lock-ordering reasons. The lport and/or rport mutexes may be held when we need to lookup a fcoe_vnport during an ELS send. Change fcoe_ctlr_encaps() to lookup the destination vn_port in the list of peers for the destination MAC address of the FIP-encapsulated frame. Add a new function fcoe_disc_init() to initialize just the discovery portion of libfcoe for VN2VN mode. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 16 +- drivers/scsi/fcoe/libfcoe.c | 1075 ++++++++++++++++++++++++++++++++++++++--- drivers/scsi/fnic/fnic_main.c | 7 +- include/scsi/libfcoe.h | 42 +- 4 files changed, 1071 insertions(+), 69 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 9d64e08305c7..216aba375fe1 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -315,7 +315,11 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, dev_uc_add(netdev, flogi_maddr); if (fip->spma) dev_uc_add(netdev, fip->ctl_src_addr); - dev_mc_add(netdev, FIP_ALL_ENODE_MACS); + if (fip->mode == FIP_MODE_VN2VN) { + dev_mc_add(netdev, FIP_ALL_VN2VN_MACS); + dev_mc_add(netdev, FIP_ALL_P2P_MACS); + } else + dev_mc_add(netdev, FIP_ALL_ENODE_MACS); /* * setup the receive function from ethernet driver @@ -401,7 +405,11 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) dev_uc_del(netdev, flogi_maddr); if (fip->spma) dev_uc_del(netdev, fip->ctl_src_addr); - dev_mc_del(netdev, FIP_ALL_ENODE_MACS); + if (fip->mode == FIP_MODE_VN2VN) { + dev_mc_del(netdev, FIP_ALL_VN2VN_MACS); + dev_mc_del(netdev, FIP_ALL_P2P_MACS); + } else + dev_mc_del(netdev, FIP_ALL_ENODE_MACS); /* Tell the LLD we are done w/ FCoE */ ops = netdev->netdev_ops; @@ -967,7 +975,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, } /* Initialize the library */ - rc = fcoe_libfc_config(lport, &fcoe_libfc_fcn_templ); + rc = fcoe_libfc_config(lport, &fcoe->ctlr, &fcoe_libfc_fcn_templ, 1); if (rc) { FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " "interface\n"); @@ -2533,6 +2541,8 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did, switch (op) { case ELS_FLOGI: case ELS_FDISC: + if (lport->point_to_multipoint) + break; return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp, fip, timeout); case ELS_LOGO: diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 11f3db5e506b..79df78f2b085 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,15 @@ static void fcoe_ctlr_timeout(unsigned long); static void fcoe_ctlr_timer_work(struct work_struct *); static void fcoe_ctlr_recv_work(struct work_struct *); +static void fcoe_ctlr_vn_start(struct fcoe_ctlr *); +static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *); +static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *); +static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *); + static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS; +static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS; +static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS; +static u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS; unsigned int libfcoe_debug_logging; module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); @@ -86,6 +95,11 @@ static const char *fcoe_ctlr_states[] = { [FIP_ST_AUTO] = "AUTO", [FIP_ST_NON_FIP] = "NON_FIP", [FIP_ST_ENABLED] = "ENABLED", + [FIP_ST_VNMP_START] = "VNMP_START", + [FIP_ST_VNMP_PROBE1] = "VNMP_PROBE1", + [FIP_ST_VNMP_PROBE2] = "VNMP_PROBE2", + [FIP_ST_VNMP_CLAIM] = "VNMP_CLAIM", + [FIP_ST_VNMP_UP] = "VNMP_UP", }; static const char *fcoe_ctlr_state(enum fip_state state) @@ -295,11 +309,25 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) fc_linkup(fip->lp); } else if (fip->state == FIP_ST_LINK_WAIT) { fcoe_ctlr_set_state(fip, fip->mode); - mutex_unlock(&fip->ctlr_mutex); - if (fip->state == FIP_ST_AUTO) + switch (fip->mode) { + default: + LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode); + /* fall-through */ + case FIP_MODE_AUTO: LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); - fc_linkup(fip->lp); - fcoe_ctlr_solicit(fip, NULL); + /* fall-through */ + case FIP_MODE_FABRIC: + case FIP_MODE_NON_FIP: + mutex_unlock(&fip->ctlr_mutex); + fc_linkup(fip->lp); + fcoe_ctlr_solicit(fip, NULL); + break; + case FIP_MODE_VN2VN: + fcoe_ctlr_vn_start(fip); + mutex_unlock(&fip->ctlr_mutex); + fc_linkup(fip->lp); + break; + } } else mutex_unlock(&fip->ctlr_mutex); } @@ -423,6 +451,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, * @fip: The FCoE controller for the ELS frame * @dtype: The FIP descriptor type for the frame * @skb: The FCoE ELS frame including FC header but no FCoE headers + * @d_id: The destination port ID. * * Returns non-zero error code on failure. * @@ -433,7 +462,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, * Ethernet header. The tailroom is for the FIP MAC descriptor. */ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, - u8 dtype, struct sk_buff *skb) + u8 dtype, struct sk_buff *skb, u32 d_id) { struct fip_encaps_head { struct ethhdr eth; @@ -445,21 +474,24 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, size_t dlen; u16 fip_flags; - fcf = fip->sel_fcf; - if (!fcf) - return -ENODEV; - - /* set flags according to both FCF and lport's capability on SPMA */ - fip_flags = fcf->flags; - fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA : FIP_FL_FPMA; - if (!fip_flags) - return -ENODEV; - dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */ cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap)); - memset(cap, 0, sizeof(*cap)); - memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN); + + if (lport->point_to_multipoint) { + if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest)) + return -ENODEV; + } else { + fcf = fip->sel_fcf; + if (!fcf) + return -ENODEV; + fip_flags = fcf->flags; + fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA : + FIP_FL_FPMA; + if (!fip_flags) + return -ENODEV; + memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN); + } memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN); cap->eth.h_proto = htons(ETH_P_FIP); @@ -503,19 +535,22 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, * * The caller must check that the length is a multiple of 4. * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). + * The the skb must also be an fc_frame. */ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, struct sk_buff *skb) { + struct fc_frame *fp; struct fc_frame_header *fh; u16 old_xid; u8 op; u8 mac[ETH_ALEN]; + fp = container_of(skb, struct fc_frame, skb); fh = (struct fc_frame_header *)skb->data; op = *(u8 *)(fh + 1); - if (op == ELS_FLOGI) { + if (op == ELS_FLOGI && fip->mode != FIP_MODE_VN2VN) { old_xid = fip->flogi_oxid; fip->flogi_oxid = ntohs(fh->fh_ox_id); if (fip->state == FIP_ST_AUTO) { @@ -533,9 +568,8 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, if (fip->state == FIP_ST_NON_FIP) return 0; - if (!fip->sel_fcf) + if (!fip->sel_fcf && fip->mode != FIP_MODE_VN2VN) goto drop; - switch (op) { case ELS_FLOGI: op = FIP_DT_FLOGI; @@ -546,36 +580,49 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, op = FIP_DT_FDISC; break; case ELS_LOGO: - if (fip->state != FIP_ST_ENABLED) - return 0; - if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI) - return 0; + if (fip->mode == FIP_MODE_VN2VN) { + if (fip->state != FIP_ST_VNMP_UP) + return -EINVAL; + if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI) + return -EINVAL; + } else { + if (fip->state != FIP_ST_ENABLED) + return 0; + if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI) + return 0; + } op = FIP_DT_LOGO; break; case ELS_LS_ACC: - if (fip->flogi_oxid == FC_XID_UNKNOWN) - return 0; - if (!ntoh24(fh->fh_s_id)) - return 0; - if (fip->state == FIP_ST_AUTO) - return 0; /* - * Here we must've gotten an SID by accepting an FLOGI + * If non-FIP, we may have gotten an SID by accepting an FLOGI * from a point-to-point connection. Switch to using * the source mac based on the SID. The destination * MAC in this case would have been set by receving the * FLOGI. */ - fip->flogi_oxid = FC_XID_UNKNOWN; - fc_fcoe_set_mac(mac, fh->fh_d_id); - fip->update_mac(lport, mac); + if (fip->state == FIP_ST_NON_FIP) { + if (fip->flogi_oxid == FC_XID_UNKNOWN) + return 0; + fip->flogi_oxid = FC_XID_UNKNOWN; + fc_fcoe_set_mac(mac, fh->fh_d_id); + fip->update_mac(lport, mac); + } + /* fall through */ + case ELS_LS_RJT: + op = fr_encaps(fp); + if (op) + break; return 0; default: - if (fip->state != FIP_ST_ENABLED) + if (fip->state != FIP_ST_ENABLED && + fip->state != FIP_ST_VNMP_UP) goto drop; return 0; } - if (fcoe_ctlr_encaps(fip, lport, op, skb)) + LIBFCOE_FIP_DBG(fip, "els_send op %u d_id %x\n", + op, ntoh24(fh->fh_d_id)); + if (fcoe_ctlr_encaps(fip, lport, op, skb, ntoh24(fh->fh_d_id))) goto drop; fip->send(fip, skb); return -EINPROGRESS; @@ -717,8 +764,9 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, ((struct fip_mac_desc *)desc)->fd_mac, ETH_ALEN); if (!is_valid_ether_addr(fcf->fcf_mac)) { - LIBFCOE_FIP_DBG(fip, "Invalid MAC address " - "in FIP adv\n"); + LIBFCOE_FIP_DBG(fip, + "Invalid MAC addr %pM in FIP adv\n", + fcf->fcf_mac); return -EINVAL; } desc_mask &= ~BIT(FIP_DT_MAC); @@ -944,12 +992,6 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) memcpy(granted_mac, ((struct fip_mac_desc *)desc)->fd_mac, ETH_ALEN); - if (!is_valid_ether_addr(granted_mac)) { - LIBFCOE_FIP_DBG(fip, "Invalid MAC address " - "in FIP ELS\n"); - goto drop; - } - memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); break; case FIP_DT_FLOGI: case FIP_DT_FDISC: @@ -990,10 +1032,20 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) goto drop; els_op = *(u8 *)(fh + 1); - if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP && - fip->flogi_oxid == ntohs(fh->fh_ox_id) && - els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) - fip->flogi_oxid = FC_XID_UNKNOWN; + if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) && + sub == FIP_SC_REP && els_op == ELS_LS_ACC && + fip->mode != FIP_MODE_VN2VN) { + if (!is_valid_ether_addr(granted_mac)) { + LIBFCOE_FIP_DBG(fip, + "Invalid MAC address %pM in FIP ELS\n", + granted_mac); + goto drop; + } + memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); + + if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) + fip->flogi_oxid = FC_XID_UNKNOWN; + } if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) && (!(1U << FIP_DT_MAC & desc_mask)))) { @@ -1012,6 +1064,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) fr_sof(fp) = FC_SOF_I3; fr_eof(fp) = FC_EOF_T; fr_dev(fp) = lport; + fr_encaps(fp) = els_dtype; stats = per_cpu_ptr(lport->dev_stats, get_cpu()); stats->RxFrames++; @@ -1188,8 +1241,13 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) if (skb->len < sizeof(*fiph)) goto drop; eh = eth_hdr(skb); - if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && - compare_ether_addr(eh->h_dest, FIP_ALL_ENODE_MACS)) + if (fip->mode == FIP_MODE_VN2VN) { + if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && + compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) && + compare_ether_addr(eh->h_dest, fcoe_all_p2p)) + goto drop; + } else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && + compare_ether_addr(eh->h_dest, fcoe_all_enode)) goto drop; fiph = (struct fip_header *)skb->data; op = ntohs(fiph->fip_op); @@ -1209,13 +1267,22 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) LIBFCOE_FIP_DBG(fip, "Using FIP mode\n"); } mutex_unlock(&fip->ctlr_mutex); - if (state != FIP_ST_ENABLED) + + if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN) + return fcoe_ctlr_vn_recv(fip, skb); + + if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP && + state != FIP_ST_VNMP_CLAIM) goto drop; if (op == FIP_OP_LS) { fcoe_ctlr_recv_els(fip, skb); /* consumes skb */ return 0; } + + if (state != FIP_ST_ENABLED) + goto drop; + if (op == FIP_OP_DISC && sub == FIP_SC_ADV) fcoe_ctlr_recv_adv(fip, skb); else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) @@ -1302,7 +1369,8 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) unsigned long next_timer; fip = container_of(work, struct fcoe_ctlr, timer_work); - + if (fip->mode == FIP_MODE_VN2VN) + return fcoe_ctlr_vn_timeout(fip); mutex_lock(&fip->ctlr_mutex); if (fip->state == FIP_ST_DISABLED) { mutex_unlock(&fip->ctlr_mutex); @@ -1340,7 +1408,6 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) "Starting FCF discovery.\n", fip->lp->host->host_no); reset = 1; - schedule_work(&fip->timer_work); } } @@ -1514,27 +1581,917 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], } EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); +/** + * fcoe_ctlr_rport() - return the fcoe_rport for a given fc_rport_priv + * @rdata: libfc remote port + */ +static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata) +{ + return (struct fcoe_rport *)(rdata + 1); +} + +/** + * fcoe_ctlr_vn_send() - Send a FIP VN2VN Probe Request or Reply. + * @fip: The FCoE controller + * @sub: sub-opcode for probe request, reply, or advertisement. + * @dest: The destination Ethernet MAC address + * @min_len: minimum size of the Ethernet payload to be sent + */ +static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip, + enum fip_vn2vn_subcode sub, + const u8 *dest, size_t min_len) +{ + struct sk_buff *skb; + struct fip_frame { + struct ethhdr eth; + struct fip_header fip; + struct fip_mac_desc mac; + struct fip_wwn_desc wwnn; + struct fip_vn_desc vn; + } __attribute__((packed)) *frame; + struct fip_fc4_feat *ff; + struct fip_size_desc *size; + u32 fcp_feat; + size_t len; + size_t dlen; + + len = sizeof(*frame); + dlen = 0; + if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) { + dlen = sizeof(struct fip_fc4_feat) + + sizeof(struct fip_size_desc); + len += dlen; + } + dlen += sizeof(frame->mac) + sizeof(frame->wwnn) + sizeof(frame->vn); + len = max(len, min_len + sizeof(struct ethhdr)); + + skb = dev_alloc_skb(len); + if (!skb) + return; + + frame = (struct fip_frame *)skb->data; + memset(frame, 0, len); + memcpy(frame->eth.h_dest, dest, ETH_ALEN); + memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN); + frame->eth.h_proto = htons(ETH_P_FIP); + + frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); + frame->fip.fip_op = htons(FIP_OP_VN2VN); + frame->fip.fip_subcode = sub; + frame->fip.fip_dl_len = htons(dlen / FIP_BPW); + + frame->mac.fd_desc.fip_dtype = FIP_DT_MAC; + frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW; + memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); + + frame->wwnn.fd_desc.fip_dtype = FIP_DT_NAME; + frame->wwnn.fd_desc.fip_dlen = sizeof(frame->wwnn) / FIP_BPW; + put_unaligned_be64(fip->lp->wwnn, &frame->wwnn.fd_wwn); + + frame->vn.fd_desc.fip_dtype = FIP_DT_VN_ID; + frame->vn.fd_desc.fip_dlen = sizeof(frame->vn) / FIP_BPW; + hton24(frame->vn.fd_mac, FIP_VN_FC_MAP); + hton24(frame->vn.fd_mac + 3, fip->port_id); + hton24(frame->vn.fd_fc_id, fip->port_id); + put_unaligned_be64(fip->lp->wwpn, &frame->vn.fd_wwpn); + + /* + * For claims, add FC-4 features. + * TBD: Add interface to get fc-4 types and features from libfc. + */ + if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) { + ff = (struct fip_fc4_feat *)(frame + 1); + ff->fd_desc.fip_dtype = FIP_DT_FC4F; + ff->fd_desc.fip_dlen = sizeof(*ff) / FIP_BPW; + ff->fd_fts = fip->lp->fcts; + + fcp_feat = 0; + if (fip->lp->service_params & FCP_SPPF_INIT_FCN) + fcp_feat |= FCP_FEAT_INIT; + if (fip->lp->service_params & FCP_SPPF_TARG_FCN) + fcp_feat |= FCP_FEAT_TARG; + fcp_feat <<= (FC_TYPE_FCP * 4) % 32; + ff->fd_ff.fd_feat[FC_TYPE_FCP * 4 / 32] = htonl(fcp_feat); + + size = (struct fip_size_desc *)(ff + 1); + size->fd_desc.fip_dtype = FIP_DT_FCOE_SIZE; + size->fd_desc.fip_dlen = sizeof(*size) / FIP_BPW; + size->fd_size = htons(fcoe_ctlr_fcoe_size(fip)); + } + + skb_put(skb, len); + skb->protocol = htons(ETH_P_FIP); + skb_reset_mac_header(skb); + skb_reset_network_header(skb); + + fip->send(fip, skb); +} + +/** + * fcoe_ctlr_vn_rport_callback - Event handler for rport events. + * @lport: The lport which is receiving the event + * @rdata: remote port private data + * @event: The event that occured + * + * Locking Note: The rport lock must not be held when calling this function. + */ +static void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport, + struct fc_rport_priv *rdata, + enum fc_rport_event event) +{ + struct fcoe_ctlr *fip = lport->disc.priv; + struct fcoe_rport *frport = fcoe_ctlr_rport(rdata); + + LIBFCOE_FIP_DBG(fip, "vn_rport_callback %x event %d\n", + rdata->ids.port_id, event); + + mutex_lock(&fip->ctlr_mutex); + switch (event) { + case RPORT_EV_READY: + frport->login_count = 0; + break; + case RPORT_EV_LOGO: + case RPORT_EV_FAILED: + case RPORT_EV_STOP: + frport->login_count++; + if (frport->login_count > FCOE_CTLR_VN2VN_LOGIN_LIMIT) { + LIBFCOE_FIP_DBG(fip, + "rport FLOGI limited port_id %6.6x\n", + rdata->ids.port_id); + lport->tt.rport_logoff(rdata); + } + break; + default: + break; + } + mutex_unlock(&fip->ctlr_mutex); +} + +static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = { + .event_callback = fcoe_ctlr_vn_rport_callback, +}; + +/** + * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode + * @fip: The FCoE controller + * + * Called with ctlr_mutex held. + */ +static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport) +{ + mutex_lock(&lport->disc.disc_mutex); + lport->disc.disc_callback = NULL; + mutex_unlock(&lport->disc.disc_mutex); +} + +/** + * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode + * @fip: The FCoE controller + * + * Called through the local port template for discovery. + * Called without the ctlr_mutex held. + */ +static void fcoe_ctlr_disc_stop(struct fc_lport *lport) +{ + struct fcoe_ctlr *fip = lport->disc.priv; + + mutex_lock(&fip->ctlr_mutex); + fcoe_ctlr_disc_stop_locked(lport); + mutex_unlock(&fip->ctlr_mutex); +} + +/** + * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode + * @fip: The FCoE controller + * + * Called through the local port template for discovery. + * Called without the ctlr_mutex held. + */ +static void fcoe_ctlr_disc_stop_final(struct fc_lport *lport) +{ + fcoe_ctlr_disc_stop(lport); + lport->tt.rport_flush_queue(); + synchronize_rcu(); +} + +/** + * fcoe_ctlr_vn_restart() - VN2VN probe restart with new port_id + * @fip: The FCoE controller + * + * Called with fcoe_ctlr lock held. + */ +static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip) +{ + unsigned long wait; + u32 port_id; + + fcoe_ctlr_disc_stop_locked(fip->lp); + + /* + * Get proposed port ID. + * If this is the first try after link up, use any previous port_id. + * If there was none, use the low bits of the port_name. + * On subsequent tries, get the next random one. + * Don't use reserved IDs, use another non-zero value, just as random. + */ + port_id = fip->port_id; + if (fip->probe_tries) + port_id = prandom32(&fip->rnd_state) & 0xffff; + else if (!port_id) + port_id = fip->lp->wwpn & 0xffff; + if (!port_id || port_id == 0xffff) + port_id = 1; + fip->port_id = port_id; + + if (fip->probe_tries < FIP_VN_RLIM_COUNT) { + fip->probe_tries++; + wait = random32() % FIP_VN_PROBE_WAIT; + } else + wait = FIP_VN_RLIM_INT; + mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait)); + fcoe_ctlr_set_state(fip, FIP_ST_VNMP_START); +} + +/** + * fcoe_ctlr_vn_start() - Start in VN2VN mode + * @fip: The FCoE controller + * + * Called with fcoe_ctlr lock held. + */ +static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip) +{ + fip->probe_tries = 0; + prandom32_seed(&fip->rnd_state, fip->lp->wwpn); + fcoe_ctlr_vn_restart(fip); +} + +/** + * fcoe_ctlr_vn_parse - parse probe request or response + * @fip: The FCoE controller + * @skb: incoming packet + * @rdata: buffer for resulting parsed VN entry plus fcoe_rport + * + * Returns non-zero error number on error. + * Does not consume the packet. + */ +static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip, + struct sk_buff *skb, + struct fc_rport_priv *rdata) +{ + struct fip_header *fiph; + struct fip_desc *desc = NULL; + struct fip_mac_desc *macd = NULL; + struct fip_wwn_desc *wwn = NULL; + struct fip_vn_desc *vn = NULL; + struct fip_size_desc *size = NULL; + struct fcoe_rport *frport; + size_t rlen; + size_t dlen; + u32 desc_mask = 0; + u32 dtype; + u8 sub; + + memset(rdata, 0, sizeof(*rdata) + sizeof(*frport)); + frport = fcoe_ctlr_rport(rdata); + + fiph = (struct fip_header *)skb->data; + frport->flags = ntohs(fiph->fip_flags); + + sub = fiph->fip_subcode; + switch (sub) { + case FIP_SC_VN_PROBE_REQ: + case FIP_SC_VN_PROBE_REP: + case FIP_SC_VN_BEACON: + desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | + BIT(FIP_DT_VN_ID); + break; + case FIP_SC_VN_CLAIM_NOTIFY: + case FIP_SC_VN_CLAIM_REP: + desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | + BIT(FIP_DT_VN_ID) | BIT(FIP_DT_FC4F) | + BIT(FIP_DT_FCOE_SIZE); + break; + default: + LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub); + return -EINVAL; + } + + rlen = ntohs(fiph->fip_dl_len) * 4; + if (rlen + sizeof(*fiph) > skb->len) + return -EINVAL; + + desc = (struct fip_desc *)(fiph + 1); + while (rlen > 0) { + dlen = desc->fip_dlen * FIP_BPW; + if (dlen < sizeof(*desc) || dlen > rlen) + return -EINVAL; + + dtype = desc->fip_dtype; + if (dtype < 32) { + if (!(desc_mask & BIT(dtype))) { + LIBFCOE_FIP_DBG(fip, + "unexpected or duplicated desc " + "desc type %u in " + "FIP VN2VN subtype %u\n", + dtype, sub); + return -EINVAL; + } + desc_mask &= ~BIT(dtype); + } + + switch (dtype) { + case FIP_DT_MAC: + if (dlen != sizeof(struct fip_mac_desc)) + goto len_err; + macd = (struct fip_mac_desc *)desc; + if (!is_valid_ether_addr(macd->fd_mac)) { + LIBFCOE_FIP_DBG(fip, + "Invalid MAC addr %pM in FIP VN2VN\n", + macd->fd_mac); + return -EINVAL; + } + memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN); + break; + case FIP_DT_NAME: + if (dlen != sizeof(struct fip_wwn_desc)) + goto len_err; + wwn = (struct fip_wwn_desc *)desc; + rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn); + break; + case FIP_DT_VN_ID: + if (dlen != sizeof(struct fip_vn_desc)) + goto len_err; + vn = (struct fip_vn_desc *)desc; + memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN); + rdata->ids.port_id = ntoh24(vn->fd_fc_id); + rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn); + break; + case FIP_DT_FC4F: + if (dlen != sizeof(struct fip_fc4_feat)) + goto len_err; + break; + case FIP_DT_FCOE_SIZE: + if (dlen != sizeof(struct fip_size_desc)) + goto len_err; + size = (struct fip_size_desc *)desc; + frport->fcoe_len = ntohs(size->fd_size); + break; + default: + LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x " + "in FIP probe\n", dtype); + /* standard says ignore unknown descriptors >= 128 */ + if (dtype < FIP_DT_VENDOR_BASE) + return -EINVAL; + break; + } + desc = (struct fip_desc *)((char *)desc + dlen); + rlen -= dlen; + } + return 0; + +len_err: + LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n", + dtype, dlen); + return -EINVAL; +} + +/** + * fcoe_ctlr_vn_send_claim() - send multicast FIP VN2VN Claim Notification. + * @fip: The FCoE controller + * + * Called with ctlr_mutex held. + */ +static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip) +{ + fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_NOTIFY, fcoe_all_vn2vn, 0); + fip->sol_time = jiffies; +} + +/** + * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request. + * @fip: The FCoE controller + * @rdata: parsed remote port with frport from the probe request + * + * Called with ctlr_mutex held. + */ +static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, + struct fc_rport_priv *rdata) +{ + struct fcoe_rport *frport = fcoe_ctlr_rport(rdata); + + if (rdata->ids.port_id != fip->port_id) + return; + + switch (fip->state) { + case FIP_ST_VNMP_CLAIM: + case FIP_ST_VNMP_UP: + fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP, + frport->enode_mac, 0); + break; + case FIP_ST_VNMP_PROBE1: + case FIP_ST_VNMP_PROBE2: + /* + * Decide whether to reply to the Probe. + * Our selected address is never a "recorded" one, so + * only reply if our WWPN is greater and the + * Probe's REC bit is not set. + * If we don't reply, we will change our address. + */ + if (fip->lp->wwpn > rdata->ids.port_name && + !(frport->flags & FIP_FL_REC_OR_P2P)) { + fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP, + frport->enode_mac, 0); + break; + } + /* fall through */ + case FIP_ST_VNMP_START: + fcoe_ctlr_vn_restart(fip); + break; + default: + break; + } +} + +/** + * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply. + * @fip: The FCoE controller + * @rdata: parsed remote port with frport from the probe request + * + * Called with ctlr_mutex held. + */ +static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip, + struct fc_rport_priv *rdata) +{ + if (rdata->ids.port_id != fip->port_id) + return; + switch (fip->state) { + case FIP_ST_VNMP_START: + case FIP_ST_VNMP_PROBE1: + case FIP_ST_VNMP_PROBE2: + case FIP_ST_VNMP_CLAIM: + fcoe_ctlr_vn_restart(fip); + break; + case FIP_ST_VNMP_UP: + fcoe_ctlr_vn_send_claim(fip); + break; + default: + break; + } +} + +/** + * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply. + * @fip: The FCoE controller + * @new: newly-parsed remote port with frport as a template for new rdata + * + * Called with ctlr_mutex held. + */ +static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) +{ + struct fc_lport *lport = fip->lp; + struct fc_rport_priv *rdata; + struct fc_rport_identifiers *ids; + struct fcoe_rport *frport; + u32 port_id; + + port_id = new->ids.port_id; + if (port_id == fip->port_id) + return; + + mutex_lock(&lport->disc.disc_mutex); + rdata = lport->tt.rport_create(lport, port_id); + if (!rdata) { + mutex_unlock(&lport->disc.disc_mutex); + return; + } + + rdata->ops = &fcoe_ctlr_vn_rport_ops; + rdata->disc_id = lport->disc.disc_id; + + ids = &rdata->ids; + if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) || + (ids->node_name != -1 && ids->node_name != new->ids.node_name)) + lport->tt.rport_logoff(rdata); + ids->port_name = new->ids.port_name; + ids->node_name = new->ids.node_name; + mutex_unlock(&lport->disc.disc_mutex); + + frport = fcoe_ctlr_rport(rdata); + LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n", + port_id, frport->fcoe_len ? "old" : "new"); + *frport = *fcoe_ctlr_rport(new); + frport->time = 0; +} + +/** + * fcoe_ctlr_vn_lookup() - Find VN remote port's MAC address + * @fip: The FCoE controller + * @port_id: The port_id of the remote VN_node + * @mac: buffer which will hold the VN_NODE destination MAC address, if found. + * + * Returns non-zero error if no remote port found. + */ +static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac) +{ + struct fc_lport *lport = fip->lp; + struct fc_rport_priv *rdata; + struct fcoe_rport *frport; + int ret = -1; + + rcu_read_lock(); + rdata = lport->tt.rport_lookup(lport, port_id); + if (rdata) { + frport = fcoe_ctlr_rport(rdata); + memcpy(mac, frport->enode_mac, ETH_ALEN); + ret = 0; + } + rcu_read_unlock(); + return ret; +} + +/** + * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification + * @fip: The FCoE controller + * @new: newly-parsed remote port with frport as a template for new rdata + * + * Called with ctlr_mutex held. + */ +static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip, + struct fc_rport_priv *new) +{ + struct fcoe_rport *frport = fcoe_ctlr_rport(new); + + if (frport->flags & FIP_FL_REC_OR_P2P) { + fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); + return; + } + switch (fip->state) { + case FIP_ST_VNMP_START: + case FIP_ST_VNMP_PROBE1: + case FIP_ST_VNMP_PROBE2: + if (new->ids.port_id == fip->port_id) + fcoe_ctlr_vn_restart(fip); + break; + case FIP_ST_VNMP_CLAIM: + case FIP_ST_VNMP_UP: + if (new->ids.port_id == fip->port_id) { + if (new->ids.port_name > fip->lp->wwpn) { + fcoe_ctlr_vn_restart(fip); + break; + } + fcoe_ctlr_vn_send_claim(fip); + break; + } + fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac, + min((u32)frport->fcoe_len, + fcoe_ctlr_fcoe_size(fip))); + fcoe_ctlr_vn_add(fip, new); + break; + default: + break; + } +} + +/** + * fcoe_ctlr_vn_claim_resp() - handle received Claim Response + * @fip: The FCoE controller that received the frame + * @new: newly-parsed remote port with frport from the Claim Response + * + * Called with ctlr_mutex held. + */ +static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip, + struct fc_rport_priv *new) +{ + LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n", + new->ids.port_id, fcoe_ctlr_state(fip->state)); + if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM) + fcoe_ctlr_vn_add(fip, new); +} + +/** + * fcoe_ctlr_vn_beacon() - handle received beacon. + * @fip: The FCoE controller that received the frame + * @new: newly-parsed remote port with frport from the Beacon + * + * Called with ctlr_mutex held. + */ +static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, + struct fc_rport_priv *new) +{ + struct fc_lport *lport = fip->lp; + struct fc_rport_priv *rdata; + struct fcoe_rport *frport; + + frport = fcoe_ctlr_rport(new); + if (frport->flags & FIP_FL_REC_OR_P2P) { + fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); + return; + } + mutex_lock(&lport->disc.disc_mutex); + rdata = lport->tt.rport_lookup(lport, new->ids.port_id); + if (rdata) + kref_get(&rdata->kref); + mutex_unlock(&lport->disc.disc_mutex); + if (rdata) { + if (rdata->ids.node_name == new->ids.node_name && + rdata->ids.port_name == new->ids.port_name) { + frport = fcoe_ctlr_rport(rdata); + if (!frport->time && fip->state == FIP_ST_VNMP_UP) + lport->tt.rport_login(rdata); + frport->time = jiffies; + } + kref_put(&rdata->kref, lport->tt.rport_destroy); + return; + } + if (fip->state != FIP_ST_VNMP_UP) + return; + + /* + * Beacon from a new neighbor. + * Send a claim notify if one hasn't been sent recently. + * Don't add the neighbor yet. + */ + LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n", + new->ids.port_id); + if (time_after(jiffies, + fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT))) + fcoe_ctlr_vn_send_claim(fip); +} + +/** + * fcoe_ctlr_vn_age() - Check for VN_ports without recent beacons + * @fip: The FCoE controller + * + * Called with ctlr_mutex held. + * Called only in state FIP_ST_VNMP_UP. + * Returns the soonest time for next age-out or a time far in the future. + */ +static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip) +{ + struct fc_lport *lport = fip->lp; + struct fc_rport_priv *rdata; + struct fcoe_rport *frport; + unsigned long next_time; + unsigned long deadline; + + next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10); + mutex_lock(&lport->disc.disc_mutex); + list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) { + frport = fcoe_ctlr_rport(rdata); + if (!frport->time) + continue; + deadline = frport->time + + msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10); + if (time_after_eq(jiffies, deadline)) { + frport->time = 0; + LIBFCOE_FIP_DBG(fip, + "port %16.16llx fc_id %6.6x beacon expired\n", + rdata->ids.port_name, rdata->ids.port_id); + lport->tt.rport_logoff(rdata); + } else if (time_before(deadline, next_time)) + next_time = deadline; + } + mutex_unlock(&lport->disc.disc_mutex); + return next_time; +} + +/** + * fcoe_ctlr_vn_recv() - Receive a FIP frame + * @fip: The FCoE controller that received the frame + * @skb: The received FIP frame + * + * Returns non-zero if the frame is dropped. + * Always consumes the frame. + */ +static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) +{ + struct fip_header *fiph; + enum fip_vn2vn_subcode sub; + union { + struct fc_rport_priv rdata; + struct fcoe_rport frport; + } buf; + int rc; + + fiph = (struct fip_header *)skb->data; + sub = fiph->fip_subcode; + + rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata); + if (rc) { + LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc); + goto drop; + } + + mutex_lock(&fip->ctlr_mutex); + switch (sub) { + case FIP_SC_VN_PROBE_REQ: + fcoe_ctlr_vn_probe_req(fip, &buf.rdata); + break; + case FIP_SC_VN_PROBE_REP: + fcoe_ctlr_vn_probe_reply(fip, &buf.rdata); + break; + case FIP_SC_VN_CLAIM_NOTIFY: + fcoe_ctlr_vn_claim_notify(fip, &buf.rdata); + break; + case FIP_SC_VN_CLAIM_REP: + fcoe_ctlr_vn_claim_resp(fip, &buf.rdata); + break; + case FIP_SC_VN_BEACON: + fcoe_ctlr_vn_beacon(fip, &buf.rdata); + break; + default: + LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub); + rc = -1; + break; + } + mutex_unlock(&fip->ctlr_mutex); +drop: + kfree_skb(skb); + return rc; +} + +/** + * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode. + * @fip: The FCoE controller + * + * This should never be called since we don't see RSCNs or other + * fabric-generated ELSes. + */ +static void fcoe_ctlr_disc_recv(struct fc_seq *seq, struct fc_frame *fp, + struct fc_lport *lport) +{ + struct fc_seq_els_data rjt_data; + + rjt_data.fp = NULL; + rjt_data.reason = ELS_RJT_UNSUP; + rjt_data.explan = ELS_EXPL_NONE; + lport->tt.seq_els_rsp_send(seq, ELS_LS_RJT, &rjt_data); + fc_frame_free(fp); +} + +/** + * fcoe_ctlr_disc_recv - start discovery for VN2VN mode. + * @fip: The FCoE controller + * + * This sets a flag indicating that remote ports should be created + * and started for the peers we discover. We use the disc_callback + * pointer as that flag. Peers already discovered are created here. + * + * The lport lock is held during this call. The callback must be done + * later, without holding either the lport or discovery locks. + * The fcoe_ctlr lock may also be held during this call. + */ +static void fcoe_ctlr_disc_start(void (*callback)(struct fc_lport *, + enum fc_disc_event), + struct fc_lport *lport) +{ + struct fc_disc *disc = &lport->disc; + struct fcoe_ctlr *fip = disc->priv; + + mutex_lock(&disc->disc_mutex); + disc->disc_callback = callback; + disc->disc_id = (disc->disc_id + 2) | 1; + disc->pending = 1; + schedule_work(&fip->timer_work); + mutex_unlock(&disc->disc_mutex); +} + +/** + * fcoe_ctlr_vn_disc() - report FIP VN_port discovery results after claim state. + * @fip: The FCoE controller + * + * Starts the FLOGI and PLOGI login process to each discovered rport for which + * we've received at least one beacon. + * Performs the discovery complete callback. + */ +static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip) +{ + struct fc_lport *lport = fip->lp; + struct fc_disc *disc = &lport->disc; + struct fc_rport_priv *rdata; + struct fcoe_rport *frport; + void (*callback)(struct fc_lport *, enum fc_disc_event); + + mutex_lock(&disc->disc_mutex); + callback = disc->pending ? disc->disc_callback : NULL; + disc->pending = 0; + list_for_each_entry_rcu(rdata, &disc->rports, peers) { + frport = fcoe_ctlr_rport(rdata); + if (frport->time) + lport->tt.rport_login(rdata); + } + mutex_unlock(&disc->disc_mutex); + if (callback) + callback(lport, DISC_EV_SUCCESS); +} + +/** + * fcoe_ctlr_vn_timeout - timer work function for VN2VN mode. + * @fip: The FCoE controller + */ +static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) +{ + unsigned long next_time; + u8 mac[ETH_ALEN]; + u32 new_port_id = 0; + + mutex_lock(&fip->ctlr_mutex); + switch (fip->state) { + case FIP_ST_VNMP_START: + fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1); + fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); + next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT); + break; + case FIP_ST_VNMP_PROBE1: + fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2); + fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); + next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); + break; + case FIP_ST_VNMP_PROBE2: + fcoe_ctlr_set_state(fip, FIP_ST_VNMP_CLAIM); + new_port_id = fip->port_id; + hton24(mac, FIP_VN_FC_MAP); + hton24(mac + 3, new_port_id); + fip->update_mac(fip->lp, mac); + fcoe_ctlr_vn_send_claim(fip); + next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); + break; + case FIP_ST_VNMP_CLAIM: + /* + * This may be invoked either by starting discovery so don't + * go to the next state unless it's been long enough. + */ + next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT); + if (time_after_eq(jiffies, next_time)) { + fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP); + fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON, + fcoe_all_vn2vn, 0); + next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); + fip->port_ka_time = next_time; + } + fcoe_ctlr_vn_disc(fip); + break; + case FIP_ST_VNMP_UP: + next_time = fcoe_ctlr_vn_age(fip); + if (time_after_eq(jiffies, fip->port_ka_time)) { + fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON, + fcoe_all_vn2vn, 0); + fip->port_ka_time = jiffies + + msecs_to_jiffies(FIP_VN_BEACON_INT + + (random32() % FIP_VN_BEACON_FUZZ)); + } + if (time_before(fip->port_ka_time, next_time)) + next_time = fip->port_ka_time; + break; + case FIP_ST_LINK_WAIT: + goto unlock; + default: + WARN(1, "unexpected state %d", fip->state); + goto unlock; + } + mod_timer(&fip->timer, next_time); +unlock: + mutex_unlock(&fip->ctlr_mutex); + + /* If port ID is new, notify local port after dropping ctlr_mutex */ + if (new_port_id) + fc_lport_set_local_id(fip->lp, new_port_id); +} + /** * fcoe_libfc_config() - Sets up libfc related properties for local port * @lp: The local port to configure libfc for + * @fip: The FCoE controller in use by the local port * @tt: The libfc function template + * @init_fcp: If non-zero, the FCP portion of libfc should be initialized * * Returns : 0 for success */ -int fcoe_libfc_config(struct fc_lport *lport, - struct libfc_function_template *tt) +int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip, + const struct libfc_function_template *tt, int init_fcp) { /* Set the function pointers set by the LLDD */ memcpy(&lport->tt, tt, sizeof(*tt)); - if (fc_fcp_init(lport)) + if (init_fcp && fc_fcp_init(lport)) return -ENOMEM; fc_exch_init(lport); fc_elsct_init(lport); fc_lport_init(lport); + if (fip->mode == FIP_MODE_VN2VN) + lport->rport_priv_size = sizeof(struct fcoe_rport); fc_rport_init(lport); - fc_disc_init(lport); - + if (fip->mode == FIP_MODE_VN2VN) { + lport->point_to_multipoint = 1; + lport->tt.disc_recv_req = fcoe_ctlr_disc_recv; + lport->tt.disc_start = fcoe_ctlr_disc_start; + lport->tt.disc_stop = fcoe_ctlr_disc_stop; + lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final; + mutex_init(&lport->disc.disc_mutex); + INIT_LIST_HEAD(&lport->disc.rports); + lport->disc.priv = fip; + } else { + fc_disc_init(lport); + } return 0; } EXPORT_SYMBOL_GPL(fcoe_libfc_config); - diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index d0fe1c3345b8..9eb7a9ebccae 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -673,7 +673,6 @@ static int __devinit fnic_probe(struct pci_dev *pdev, /* Start local port initiatialization */ lp->link_up = 0; - lp->tt = fnic_transport_template; lp->max_retry_count = fnic->config.flogi_retries; lp->max_rport_retry_count = fnic->config.plogi_retries; @@ -689,11 +688,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, fc_set_wwnn(lp, fnic->config.node_wwn); fc_set_wwpn(lp, fnic->config.port_wwn); - fc_lport_init(lp); - fc_exch_init(lp); - fc_elsct_init(lp); - fc_rport_init(lp); - fc_disc_init(lp); + fcoe_libfc_config(lp, &fnic->ctlr, &fnic_transport_template, 0); if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, FCPIO_HOST_EXCH_RANGE_START, FCPIO_HOST_EXCH_RANGE_END, NULL)) { diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 1a84a3182da0..06f1b5a8ed19 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,7 @@ #define FCOE_CTLR_START_DELAY 2000 /* mS after first adv. to choose FCF */ #define FCOE_CTRL_SOL_TOV 2000 /* min. solicitation interval (mS) */ #define FCOE_CTLR_FCF_LIMIT 20 /* max. number of FCF entries */ +#define FCOE_CTLR_VN2VN_LOGIN_LIMIT 3 /* max. VN2VN rport login retries */ /** * enum fip_state - internal state of FCoE controller. @@ -45,6 +47,11 @@ * @FIP_ST_AUTO: determining whether to use FIP or non-FIP mode. * @FIP_ST_NON_FIP: non-FIP mode selected. * @FIP_ST_ENABLED: FIP mode selected. + * @FIP_ST_VNMP_START: VN2VN multipath mode start, wait + * @FIP_ST_VNMP_PROBE1: VN2VN sent first probe, listening + * @FIP_ST_VNMP_PROBE2: VN2VN sent second probe, listening + * @FIP_ST_VNMP_CLAIM: VN2VN sent claim, waiting for responses + * @FIP_ST_VNMP_UP: VN2VN multipath mode operation */ enum fip_state { FIP_ST_DISABLED, @@ -52,6 +59,11 @@ enum fip_state { FIP_ST_AUTO, FIP_ST_NON_FIP, FIP_ST_ENABLED, + FIP_ST_VNMP_START, + FIP_ST_VNMP_PROBE1, + FIP_ST_VNMP_PROBE2, + FIP_ST_VNMP_CLAIM, + FIP_ST_VNMP_UP, }; /* @@ -62,6 +74,7 @@ enum fip_state { #define FIP_MODE_AUTO FIP_ST_AUTO #define FIP_MODE_NON_FIP FIP_ST_NON_FIP #define FIP_MODE_FABRIC FIP_ST_ENABLED +#define FIP_MODE_VN2VN FIP_ST_VNMP_START /** * struct fcoe_ctlr - FCoE Controller and FIP state @@ -79,11 +92,14 @@ enum fip_state { * @timer_work: &work_struct for doing keep-alives and resets. * @recv_work: &work_struct for receiving FIP frames. * @fip_recv_list: list of received FIP frames. + * @rnd_state: state for pseudo-random number generator. + * @port_id: proposed or selected local-port ID. * @user_mfs: configured maximum FC frame size, including FC header. * @flogi_oxid: exchange ID of most recent fabric login. * @flogi_count: number of FLOGI attempts in AUTO mode. * @map_dest: use the FC_MAP mode for destination MAC addresses. * @spma: supports SPMA server-provided MACs mode + * @probe_tries: number of FC_IDs probed * @dest_addr: MAC address of the selected FC forwarder. * @ctl_src_addr: the native MAC address of our local port. * @send: LLD-supplied function to handle sending FIP Ethernet frames @@ -110,11 +126,16 @@ struct fcoe_ctlr { struct work_struct timer_work; struct work_struct recv_work; struct sk_buff_head fip_recv_list; + + struct rnd_state rnd_state; + u32 port_id; + u16 user_mfs; u16 flogi_oxid; u8 flogi_count; u8 map_dest; u8 spma; + u8 probe_tries; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; @@ -160,6 +181,24 @@ struct fcoe_fcf { u8 fd_flags:1; }; +/** + * struct fcoe_rport - VN2VN remote port + * @time: time of create or last beacon packet received from node + * @fcoe_len: max FCoE frame size, not including VLAN or Ethernet headers + * @flags: flags from probe or claim + * @login_count: number of unsuccessful rport logins to this port + * @enode_mac: E_Node control MAC address + * @vn_mac: VN_Node assigned MAC address for data + */ +struct fcoe_rport { + unsigned long time; + u16 fcoe_len; + u16 flags; + u8 login_count; + u8 enode_mac[ETH_ALEN]; + u8 vn_mac[ETH_ALEN]; +}; + /* FIP API functions */ void fcoe_ctlr_init(struct fcoe_ctlr *, enum fip_state); void fcoe_ctlr_destroy(struct fcoe_ctlr *); @@ -172,7 +211,8 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_lport *, /* libfcoe funcs */ u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); -int fcoe_libfc_config(struct fc_lport *, struct libfc_function_template *); +int fcoe_libfc_config(struct fc_lport *, struct fcoe_ctlr *, + const struct libfc_function_template *, int init_fcp); /** * is_fip_mode() - returns true if FIP mode selected. -- cgit v1.2.3 From 5554345bc5275afed760631277fdab0a5a19472e Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:35 -0700 Subject: [SCSI] libfcoe: Fix FIP ELS encapsulation details for FLOGI responses When sending a FLOGI LS_ACC, which we only do in point-to-multipoint mode, the MAC descriptor should have the granted MAC set to 0x0efd00 || D_ID. When sending an LS_RJT, there should be no MAC descriptor. When sending either an LS_ACC or LS_RJT, the subcode should indicate an reply, not a request. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 79df78f2b085..4865e8181172 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -469,11 +469,15 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, struct fip_header fip; struct fip_encaps encaps; } __attribute__((packed)) *cap; + struct fc_frame_header *fh; struct fip_mac_desc *mac; struct fcoe_fcf *fcf; size_t dlen; u16 fip_flags; + u8 op; + fh = (struct fc_frame_header *)skb->data; + op = *(u8 *)(fh + 1); dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */ cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap)); memset(cap, 0, sizeof(*cap)); @@ -481,6 +485,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, if (lport->point_to_multipoint) { if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest)) return -ENODEV; + fip_flags = 0; } else { fcf = fip->sel_fcf; if (!fcf) @@ -497,26 +502,35 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); cap->fip.fip_op = htons(FIP_OP_LS); - cap->fip.fip_subcode = FIP_SC_REQ; - cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW); + if (op == ELS_LS_ACC || op == ELS_LS_RJT) + cap->fip.fip_subcode = FIP_SC_REP; + else + cap->fip.fip_subcode = FIP_SC_REQ; cap->fip.fip_flags = htons(fip_flags); cap->encaps.fd_desc.fip_dtype = dtype; cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; - mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac)); - memset(mac, 0, sizeof(*mac)); - mac->fd_desc.fip_dtype = FIP_DT_MAC; - mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; - if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) { - memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); - } else if (fip_flags & FIP_FL_SPMA) { - LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n"); - memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); - } else { - LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n"); - /* FPMA only FLOGI must leave the MAC desc set to all 0s */ + if (op != ELS_LS_RJT) { + dlen += sizeof(*mac); + mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac)); + memset(mac, 0, sizeof(*mac)); + mac->fd_desc.fip_dtype = FIP_DT_MAC; + mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; + if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) { + memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); + } else if (fip->mode == FIP_MODE_VN2VN) { + hton24(mac->fd_mac, FIP_VN_FC_MAP); + hton24(mac->fd_mac + 3, fip->port_id); + } else if (fip_flags & FIP_FL_SPMA) { + LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n"); + memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); + } else { + LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n"); + /* FPMA only FLOGI. Must leave the MAC desc zeroed. */ + } } + cap->fip.fip_dl_len = htons(dlen / FIP_BPW); skb->protocol = htons(ETH_P_FIP); skb_reset_mac_header(skb); -- cgit v1.2.3 From cd229e42eb8cdfdcbe15dfeec39c3641f62de43a Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:40 -0700 Subject: [SCSI] fcoe libfcoe: use correct FC-MAP for VN2VN mode In VN2VN mode, map_dest means to use the default VN2VN OUI. Change code that uses the default FCoE OUI to use the one set in the fcoe_ctlr struct. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 6 ++---- drivers/scsi/fcoe/libfcoe.c | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 216aba375fe1..4d3e70ab65b5 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1534,11 +1534,9 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) /* fill up mac and fcoe headers */ eh = eth_hdr(skb); eh->h_proto = htons(ETH_P_FCOE); + memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN); if (fcoe->ctlr.map_dest) - fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); - else - /* insert GW address */ - memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN); + memcpy(eh->h_dest + 3, fh->fh_d_id, 3); if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 4865e8181172..4de8ced1fee7 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -152,6 +152,20 @@ static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf) return (fcf->flags & flags) == flags; } +/** + * fcoe_ctlr_map_dest() - Set flag and OUI for mapping destination addresses + * @fip: The FCoE controller + */ +static void fcoe_ctlr_map_dest(struct fcoe_ctlr *fip) +{ + if (fip->mode == FIP_MODE_VN2VN) + hton24(fip->dest_addr, FIP_VN_FC_MAP); + else + hton24(fip->dest_addr, FIP_DEF_FC_MAP); + hton24(fip->dest_addr + 3, 0); + fip->map_dest = 1; +} + /** * fcoe_ctlr_init() - Initialize the FCoE Controller instance * @fip: The FCoE controller to initialize @@ -345,7 +359,7 @@ static void fcoe_ctlr_reset(struct fcoe_ctlr *fip) fip->port_ka_time = 0; fip->sol_time = 0; fip->flogi_oxid = FC_XID_UNKNOWN; - fip->map_dest = 0; + fcoe_ctlr_map_dest(fip); } /** @@ -573,11 +587,11 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, fip->flogi_count++; if (fip->flogi_count < 3) goto drop; - fip->map_dest = 1; + fcoe_ctlr_map_dest(fip); return 0; } if (fip->state == FIP_ST_NON_FIP) - fip->map_dest = 1; + fcoe_ctlr_map_dest(fip); } if (fip->state == FIP_ST_NON_FIP) @@ -1411,6 +1425,7 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) "Fibre-Channel Forwarder MAC %pM\n", fip->lp->host->host_no, sel->fcf_mac); memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); + fip->map_dest = 0; fip->port_ka_time = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); fip->ctlr_ka_time = jiffies + sel->fka_period; @@ -1527,7 +1542,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, * Otherwise we use the FCoE gateway addr */ if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) { - fip->map_dest = 1; + fcoe_ctlr_map_dest(fip); } else { memcpy(fip->dest_addr, sa, ETH_ALEN); fip->map_dest = 0; @@ -2426,6 +2441,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) new_port_id = fip->port_id; hton24(mac, FIP_VN_FC_MAP); hton24(mac + 3, new_port_id); + fcoe_ctlr_map_dest(fip); fip->update_mac(fip->lp, mac); fcoe_ctlr_vn_send_claim(fip); next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); -- cgit v1.2.3 From 1dd454d9e5205f9a61d51fb97159afeffa0a506c Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:46 -0700 Subject: [SCSI] fcoe: config via separate create_vn2vn module parameter Add module parameter create_vn2vn that behaves like the create parameter except that the new instance is created in FIP vn2vn mode. This can be replaced once we change create to allow modifying per-instance attributes before starting the instance. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 4d3e70ab65b5..ab6ea60f2aee 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -117,9 +117,14 @@ static void fcoe_recv_frame(struct sk_buff *skb); static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *); -module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); +module_param_call(create, fcoe_create, NULL, (void *)FIP_MODE_AUTO, S_IWUSR); __MODULE_PARM_TYPE(create, "string"); MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface"); +module_param_call(create_vn2vn, fcoe_create, NULL, + (void *)FIP_MODE_VN2VN, S_IWUSR); +__MODULE_PARM_TYPE(create_vn2vn, "string"); +MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance " + "on an Ethernet interface"); module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); __MODULE_PARM_TYPE(destroy, "string"); MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface"); @@ -341,10 +346,12 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, /** * fcoe_interface_create() - Create a FCoE interface on a net device * @netdev: The net device to create the FCoE interface on + * @fip_mode: The mode to use for FIP * * Returns: pointer to a struct fcoe_interface or NULL on error */ -static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) +static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, + enum fip_state fip_mode) { struct fcoe_interface *fcoe; int err; @@ -361,7 +368,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) /* * Initialize FIP. */ - fcoe_ctlr_init(&fcoe->ctlr, FIP_MODE_AUTO); + fcoe_ctlr_init(&fcoe->ctlr, fip_mode); fcoe->ctlr.send = fcoe_fip_send; fcoe->ctlr.update_mac = fcoe_update_src_mac; fcoe->ctlr.get_src_addr = fcoe_get_src_mac; @@ -2088,6 +2095,7 @@ static void fcoe_destroy_work(struct work_struct *work) */ static int fcoe_create(const char *buffer, struct kernel_param *kp) { + enum fip_state fip_mode = (enum fip_state)(long)kp->arg; int rc; struct fcoe_interface *fcoe; struct fc_lport *lport; @@ -2129,7 +2137,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) goto out_putdev; } - fcoe = fcoe_interface_create(netdev); + fcoe = fcoe_interface_create(netdev, fip_mode); if (!fcoe) { rc = -ENOMEM; goto out_putdev; -- cgit v1.2.3 From 079ecd8cfe95dfd28b74f3a00d66fdbcdfc8c611 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:51 -0700 Subject: [SCSI] libfc: eliminate rport LOGO state The LOGO state hasn't been used in a while, except in a brief transition to DELETE state while holding the rport mutex. All port LOGO responses have been ignored as well as any timeout if we don't get a response. So this patch just removes LOGO state and simplifies the response handler. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 88 +++++++++++-------------------------------- include/scsi/libfc.h | 2 - 2 files changed, 22 insertions(+), 68 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4d6adf29b4f8..c06d63e4a00f 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -89,7 +89,6 @@ static const char *fc_rport_state_names[] = { [RPORT_ST_PRLI] = "PRLI", [RPORT_ST_RTV] = "RTV", [RPORT_ST_READY] = "Ready", - [RPORT_ST_LOGO] = "LOGO", [RPORT_ST_ADISC] = "ADISC", [RPORT_ST_DELETE] = "Delete", }; @@ -514,9 +513,6 @@ static void fc_rport_timeout(struct work_struct *work) case RPORT_ST_RTV: fc_rport_enter_rtv(rdata); break; - case RPORT_ST_LOGO: - fc_rport_enter_logo(rdata); - break; case RPORT_ST_ADISC: fc_rport_enter_adisc(rdata); break; @@ -547,7 +543,6 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) switch (rdata->rp_state) { case RPORT_ST_FLOGI: case RPORT_ST_PLOGI: - case RPORT_ST_LOGO: rdata->flags &= ~FC_RP_STARTED; fc_rport_enter_delete(rdata, RPORT_EV_FAILED); break; @@ -791,7 +786,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, switch (rdata->rp_state) { case RPORT_ST_INIT: - case RPORT_ST_LOGO: case RPORT_ST_DELETE: mutex_unlock(&rdata->rp_mutex); rjt_data.reason = ELS_RJT_FIP; @@ -1036,52 +1030,6 @@ err: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } -/** - * fc_rport_logo_resp() - Handler for logout (LOGO) responses - * @sp: The sequence the LOGO was on - * @fp: The LOGO response frame - * @rdata_arg: The remote port that sent the LOGO response - * - * Locking Note: This function will be called without the rport lock - * held, but it will lock, call an _enter_* function or fc_rport_error - * and then unlock the rport. - */ -static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, - void *rdata_arg) -{ - struct fc_rport_priv *rdata = rdata_arg; - u8 op; - - mutex_lock(&rdata->rp_mutex); - - FC_RPORT_DBG(rdata, "Received a LOGO %s\n", fc_els_resp_type(fp)); - - if (rdata->rp_state != RPORT_ST_LOGO) { - FC_RPORT_DBG(rdata, "Received a LOGO response, but in state " - "%s\n", fc_rport_state(rdata)); - if (IS_ERR(fp)) - goto err; - goto out; - } - - if (IS_ERR(fp)) { - fc_rport_error_retry(rdata, fp); - goto err; - } - - op = fc_frame_payload_op(fp); - if (op != ELS_LS_ACC) - FC_RPORT_DBG(rdata, "Bad ELS response op %x for LOGO command\n", - op); - fc_rport_enter_delete(rdata, RPORT_EV_LOGO); - -out: - fc_frame_free(fp); -err: - mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); -} - /** * fc_rport_enter_prli() - Send Process Login (PRLI) request * @rdata: The remote port to send the PRLI request to @@ -1223,6 +1171,24 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) kref_get(&rdata->kref); } +/** + * fc_rport_logo_resp() - Handler for logout (LOGO) responses + * @sp: The sequence the LOGO was on + * @fp: The LOGO response frame + * @lport_arg: The local port + */ +static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, + void *lport_arg) +{ + struct fc_lport *lport = lport_arg; + + FC_RPORT_ID_DBG(lport, fc_seq_exch(sp)->did, + "Received a LOGO %s\n", fc_els_resp_type(fp)); + if (IS_ERR(fp)) + return; + fc_frame_free(fp); +} + /** * fc_rport_enter_logo() - Send a logout (LOGO) request * @rdata: The remote port to send the LOGO request to @@ -1235,23 +1201,14 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; - FC_RPORT_DBG(rdata, "Port entered LOGO state from %s state\n", + FC_RPORT_DBG(rdata, "Port sending LOGO from %s state\n", fc_rport_state(rdata)); - fc_rport_state_enter(rdata, RPORT_ST_LOGO); - fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo)); - if (!fp) { - fc_rport_error_retry(rdata, fp); + if (!fp) return; - } - - if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, - fc_rport_logo_resp, rdata, - 2 * lport->r_a_tov)) - fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + (void)lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, + fc_rport_logo_resp, lport, 0); } /** @@ -1670,7 +1627,6 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, break; case RPORT_ST_FLOGI: case RPORT_ST_DELETE: - case RPORT_ST_LOGO: FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", fc_rport_state(rdata)); mutex_unlock(&rdata->rp_mutex); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 8d297f9a0a47..e6f07fba432c 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -103,7 +103,6 @@ enum fc_disc_event { * @RPORT_ST_PRLI: Waiting for PRLI completion * @RPORT_ST_RTV: Waiting for RTV completion * @RPORT_ST_READY: Ready for use - * @RPORT_ST_LOGO: Remote port logout (LOGO) sent * @RPORT_ST_ADISC: Discover Address sent * @RPORT_ST_DELETE: Remote port being deleted */ @@ -115,7 +114,6 @@ enum fc_rport_state { RPORT_ST_PRLI, RPORT_ST_RTV, RPORT_ST_READY, - RPORT_ST_LOGO, RPORT_ST_ADISC, RPORT_ST_DELETE, }; -- cgit v1.2.3 From 251748a99e631a2c46edcf9e519cfc60fae8153d Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:20:56 -0700 Subject: [SCSI] libfc: add fc_frame_sid() and fc_frame_did() functions To pave the way for eliminating exchanges from incoming requests, add simple inline fc_frame_sid() and fc_frame_did() functions which get the FC_IDs from the frame header. This can be almost as efficient as getting them from the sequence/exchange. Move ntohll, htonll, ntoh24 and hton24 to since we need them there and that's included by Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 12 ++++-------- drivers/scsi/libfc/fc_rport.c | 26 ++++++------------------- include/scsi/fc_frame.h | 45 ++++++++++++++++++++++++++++++++++++++++++- include/scsi/libfc.h | 18 ----------------- 4 files changed, 54 insertions(+), 47 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index ec9850c46170..be3c2cee829f 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -800,7 +800,6 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, struct fc_lport *lport) { struct fc_frame *fp; - struct fc_frame_header *fh; struct fc_seq *sp; struct fc_exch *ep; struct fc_els_flogi *flp; @@ -813,8 +812,7 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n", fc_lport_state(lport)); - fh = fc_frame_header_get(rx_fp); - remote_fid = ntoh24(fh->fh_s_id); + remote_fid = fc_frame_sid(rx_fp); flp = fc_frame_payload_get(rx_fp, sizeof(*flp)); if (!flp) goto out; @@ -910,7 +908,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, recv = fc_lport_recv_flogi_req; break; case ELS_LOGO: - if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI) + if (fc_frame_sid(fp) == FC_FID_FLOGI) recv = fc_lport_recv_logo_req; break; case ELS_RSCN: @@ -1468,7 +1466,6 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg) { struct fc_lport *lport = lp_arg; - struct fc_frame_header *fh; struct fc_els_flogi *flp; u32 did; u16 csp_flags; @@ -1496,8 +1493,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, goto err; } - fh = fc_frame_header_get(fp); - did = ntoh24(fh->fh_d_id); + did = fc_frame_did(fp); if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { flp = fc_frame_payload_get(fp, sizeof(*flp)); if (flp) { @@ -1523,7 +1519,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, "Port (%6.6x) entered " "point-to-point mode\n", lport->host->host_no, did); - fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id), + fc_lport_ptp_setup(lport, fc_frame_sid(fp), get_unaligned_be64( &flp->fl_wwpn), get_unaligned_be64( diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index c06d63e4a00f..123493166824 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -747,13 +747,11 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, struct fc_rport_priv *rdata; struct fc_frame *fp = rx_fp; struct fc_exch *ep; - struct fc_frame_header *fh; struct fc_seq_els_data rjt_data; u32 sid, f_ctl; rjt_data.fp = NULL; - fh = fc_frame_header_get(fp); - sid = ntoh24(fh->fh_s_id); + sid = fc_frame_sid(fp); FC_RPORT_ID_DBG(lport, sid, "Received FLOGI request\n"); @@ -1430,17 +1428,14 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp) { struct fc_rport_priv *rdata; - struct fc_frame_header *fh; struct fc_seq_els_data els_data; els_data.fp = NULL; els_data.reason = ELS_RJT_UNAB; els_data.explan = ELS_EXPL_PLOGI_REQD; - fh = fc_frame_header_get(fp); - mutex_lock(&lport->disc.disc_mutex); - rdata = lport->tt.rport_lookup(lport, ntoh24(fh->fh_s_id)); + rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); if (!rdata) { mutex_unlock(&lport->disc.disc_mutex); goto reject; @@ -1555,14 +1550,12 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, struct fc_rport_priv *rdata; struct fc_frame *fp = rx_fp; struct fc_exch *ep; - struct fc_frame_header *fh; struct fc_els_flogi *pl; struct fc_seq_els_data rjt_data; u32 sid, f_ctl; rjt_data.fp = NULL; - fh = fc_frame_header_get(fp); - sid = ntoh24(fh->fh_s_id); + sid = fc_frame_sid(fp); FC_RPORT_ID_DBG(lport, sid, "Received PLOGI request\n"); @@ -1682,7 +1675,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, struct fc_lport *lport = rdata->local_port; struct fc_exch *ep; struct fc_frame *fp; - struct fc_frame_header *fh; struct { struct fc_els_prli prli; struct fc_els_spp spp; @@ -1698,12 +1690,10 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, u32 roles = FC_RPORT_ROLE_UNKNOWN; rjt_data.fp = NULL; - fh = fc_frame_header_get(rx_fp); - FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", fc_rport_state(rdata)); - len = fr_len(rx_fp) - sizeof(*fh); + len = fr_len(rx_fp) - sizeof(struct fc_frame_header); pp = fc_frame_payload_get(rx_fp, sizeof(*pp)); if (!pp) goto reject_len; @@ -1817,7 +1807,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, struct fc_frame *rx_fp) { struct fc_lport *lport = rdata->local_port; - struct fc_frame_header *fh; struct fc_exch *ep; struct fc_frame *fp; struct { @@ -1832,12 +1821,11 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, struct fc_seq_els_data rjt_data; rjt_data.fp = NULL; - fh = fc_frame_header_get(rx_fp); FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n", fc_rport_state(rdata)); - len = fr_len(rx_fp) - sizeof(*fh); + len = fr_len(rx_fp) - sizeof(struct fc_frame_header); pp = fc_frame_payload_get(rx_fp, sizeof(*pp)); if (!pp) goto reject_len; @@ -1901,14 +1889,12 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp) { - struct fc_frame_header *fh; struct fc_rport_priv *rdata; u32 sid; lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); - fh = fc_frame_header_get(fp); - sid = ntoh24(fh->fh_s_id); + sid = fc_frame_sid(fp); mutex_lock(&lport->disc.disc_mutex); rdata = lport->tt.rport_lookup(lport, sid); diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h index 29dd97d5b53a..4ad02041b667 100644 --- a/include/scsi/fc_frame.h +++ b/include/scsi/fc_frame.h @@ -30,6 +30,23 @@ #include +/* some helpful macros */ + +#define ntohll(x) be64_to_cpu(x) +#define htonll(x) cpu_to_be64(x) + +static inline u32 ntoh24(const u8 *p) +{ + return (p[0] << 16) | (p[1] << 8) | p[2]; +} + +static inline void hton24(u8 *p, u32 v) +{ + p[0] = (v >> 16) & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = v & 0xff; +} + /* * The fc_frame interface is used to pass frame data between functions. * The frame includes the data buffer, length, and SOF / EOF delimiter types. @@ -137,6 +154,16 @@ static inline int fc_frame_is_linear(struct fc_frame *fp) return !skb_is_nonlinear(fp_skb(fp)); } +/* + * Get frame header from message in fc_frame structure. + * This version doesn't do a length check. + */ +static inline +struct fc_frame_header *__fc_frame_header_get(const struct fc_frame *fp) +{ + return (struct fc_frame_header *)fr_hdr(fp); +} + /* * Get frame header from message in fc_frame structure. * This hides a cast and provides a place to add some checking. @@ -145,7 +172,23 @@ static inline struct fc_frame_header *fc_frame_header_get(const struct fc_frame *fp) { WARN_ON(fr_len(fp) < sizeof(struct fc_frame_header)); - return (struct fc_frame_header *) fr_hdr(fp); + return __fc_frame_header_get(fp); +} + +/* + * Get source FC_ID (S_ID) from frame header in message. + */ +static inline u32 fc_frame_sid(const struct fc_frame *fp) +{ + return ntoh24(__fc_frame_header_get(fp)->fh_s_id); +} + +/* + * Get destination FC_ID (D_ID) from frame header in message. + */ +static inline u32 fc_frame_did(const struct fc_frame *fp) +{ + return ntoh24(__fc_frame_header_get(fp)->fh_d_id); } /* diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index e6f07fba432c..f1ce793f33b3 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -42,24 +42,6 @@ #define FC_EX_TIMEOUT 1 /* Exchange timeout */ #define FC_EX_CLOSED 2 /* Exchange closed */ -/* some helpful macros */ - -#define ntohll(x) be64_to_cpu(x) -#define htonll(x) cpu_to_be64(x) - - -static inline u32 ntoh24(const u8 *p) -{ - return (p[0] << 16) | (p[1] << 8) | p[2]; -} - -static inline void hton24(u8 *p, u32 v) -{ - p[0] = (v >> 16) & 0xff; - p[1] = (v >> 8) & 0xff; - p[2] = v & 0xff; -} - /** * enum fc_lport_state - Local port states * @LPORT_ST_DISABLED: Disabled -- cgit v1.2.3 From 24f089e2f2c800f88039e9d536d558ec6e349fad Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:21:01 -0700 Subject: [SCSI] libfc: add fc_fill_reply_hdr() and fc_fill_hdr() Add functions to fill in an FC header given a request header. These reduces code lines in fc_lport and fc_rport and works without an exchange/sequence assigned. fc_fill_reply_hdr() fills a header for a final reply frame. fc_fill_hdr() which is similar but allows specifying the f_ctl parameter. Add defines for F_CTL values FC_FCTL_REQ and FC_FCTL_RESP. These can be used for most request and response sequences. v2 of patch adds a line to copy the frame encapsulation info from the received frame. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_elsct.c | 2 +- drivers/scsi/libfc/fc_fcp.c | 6 ++-- drivers/scsi/libfc/fc_libfc.c | 78 +++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libfc/fc_lport.c | 39 +++++++--------------- drivers/scsi/libfc/fc_rport.c | 64 +++++++++-------------------------- include/scsi/fc_encode.h | 7 ++++ include/scsi/libfc.h | 4 +++ 7 files changed, 121 insertions(+), 79 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index e9412b710fab..9b25969e2ad0 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -64,7 +64,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, } fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type, - FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); + FC_FCTL_REQ, 0); return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); } diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 61a12970bd14..eac4d09314eb 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1108,7 +1108,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, fc_fill_fc_hdr(fp, FC_RCTL_DD_UNSOL_CMD, rport->port_id, rpriv->local_port->port_id, FC_TYPE_FCP, - FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); + FC_FCTL_REQ, 0); seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, fsp, 0); @@ -1381,7 +1381,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) fr_seq(fp) = fsp->seq_ptr; fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id, rpriv->local_port->port_id, FC_TYPE_ELS, - FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); + FC_FCTL_REQ, 0); if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, fc_fcp_rec_resp, fsp, jiffies_to_msecs(FC_SCSI_REC_TOV))) { @@ -1639,7 +1639,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) fc_fill_fc_hdr(fp, FC_RCTL_ELS4_REQ, rport->port_id, rpriv->local_port->port_id, FC_TYPE_FCP, - FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); + FC_FCTL_REQ, 0); seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, fsp, jiffies_to_msecs(FC_SCSI_REC_TOV)); diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c index 39f4b6ab04b4..6a48c28e4420 100644 --- a/drivers/scsi/libfc/fc_libfc.c +++ b/drivers/scsi/libfc/fc_libfc.c @@ -23,6 +23,7 @@ #include #include +#include #include "fc_libfc.h" @@ -132,3 +133,80 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len, } return copy_len; } + +/** + * fc_fill_hdr() - fill FC header fields based on request + * @fp: reply frame containing header to be filled in + * @in_fp: request frame containing header to use in filling in reply + * @r_ctl: R_CTL value for header + * @f_ctl: F_CTL value for header, with 0 pad + * @seq_cnt: sequence count for the header, ignored if frame has a sequence + * @parm_offset: parameter / offset value + */ +void fc_fill_hdr(struct fc_frame *fp, const struct fc_frame *in_fp, + enum fc_rctl r_ctl, u32 f_ctl, u16 seq_cnt, u32 parm_offset) +{ + struct fc_frame_header *fh; + struct fc_frame_header *in_fh; + struct fc_seq *sp; + u32 fill; + + fh = __fc_frame_header_get(fp); + in_fh = __fc_frame_header_get(in_fp); + + if (f_ctl & FC_FC_END_SEQ) { + fill = -fr_len(fp) & 3; + if (fill) { + /* TODO, this may be a problem with fragmented skb */ + memset(skb_put(fp_skb(fp), fill), 0, fill); + f_ctl |= fill; + } + fr_eof(fp) = FC_EOF_T; + } else { + WARN_ON(fr_len(fp) % 4 != 0); /* no pad to non last frame */ + fr_eof(fp) = FC_EOF_N; + } + + fh->fh_r_ctl = r_ctl; + memcpy(fh->fh_d_id, in_fh->fh_s_id, sizeof(fh->fh_d_id)); + memcpy(fh->fh_s_id, in_fh->fh_d_id, sizeof(fh->fh_s_id)); + fh->fh_type = in_fh->fh_type; + hton24(fh->fh_f_ctl, f_ctl); + fh->fh_ox_id = in_fh->fh_ox_id; + fh->fh_rx_id = in_fh->fh_rx_id; + fh->fh_cs_ctl = 0; + fh->fh_df_ctl = 0; + fh->fh_parm_offset = htonl(parm_offset); + + sp = fr_seq(in_fp); + if (sp) { + fr_seq(fp) = sp; + fh->fh_seq_id = sp->id; + seq_cnt = sp->cnt; + } else { + fh->fh_seq_id = 0; + } + fh->fh_seq_cnt = ntohs(seq_cnt); + fr_sof(fp) = seq_cnt ? FC_SOF_N3 : FC_SOF_I3; + fr_encaps(fp) = fr_encaps(in_fp); +} +EXPORT_SYMBOL(fc_fill_hdr); + +/** + * fc_fill_reply_hdr() - fill FC reply header fields based on request + * @fp: reply frame containing header to be filled in + * @in_fp: request frame containing header to use in filling in reply + * @r_ctl: R_CTL value for reply + * @parm_offset: parameter / offset value + */ +void fc_fill_reply_hdr(struct fc_frame *fp, const struct fc_frame *in_fp, + enum fc_rctl r_ctl, u32 parm_offset) +{ + struct fc_seq *sp; + + sp = fr_seq(in_fp); + if (sp) + fr_seq(fp) = fr_dev(in_fp)->tt.seq_start_next(sp); + fc_fill_hdr(fp, in_fp, r_ctl, FC_FCTL_RESP, 0, parm_offset); +} +EXPORT_SYMBOL(fc_fill_reply_hdr); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index be3c2cee829f..e50a6606d4bf 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -405,11 +405,9 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, struct fc_lport *lport) { struct fc_frame *fp; - struct fc_exch *ep = fc_seq_exch(sp); unsigned int len; void *pp; void *dp; - u32 f_ctl; FC_LPORT_DBG(lport, "Received ECHO request while in state %s\n", fc_lport_state(lport)); @@ -425,11 +423,8 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, dp = fc_frame_payload_get(fp, len); memcpy(dp, pp, len); *((__be32 *)dp) = htonl(ELS_LS_ACC << 24); - sp = lport->tt.seq_start_next(sp); - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); } fc_frame_free(in_fp); } @@ -447,7 +442,6 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, struct fc_lport *lport) { struct fc_frame *fp; - struct fc_exch *ep = fc_seq_exch(sp); struct fc_els_rnid *req; struct { struct fc_els_rnid_resp rnid; @@ -457,7 +451,6 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, struct fc_seq_els_data rjt_data; u8 fmt; size_t len; - u32 f_ctl; FC_LPORT_DBG(lport, "Received RNID request while in state %s\n", fc_lport_state(lport)); @@ -490,12 +483,8 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, memcpy(&rp->gen, &lport->rnid_gen, sizeof(rp->gen)); } - sp = lport->tt.seq_start_next(sp); - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; - f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); } } fc_frame_free(in_fp); @@ -800,14 +789,13 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, struct fc_lport *lport) { struct fc_frame *fp; + struct fc_frame_header *fh; struct fc_seq *sp; - struct fc_exch *ep; struct fc_els_flogi *flp; struct fc_els_flogi *new_flp; u64 remote_wwpn; u32 remote_fid; u32 local_fid; - u32 f_ctl; FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n", fc_lport_state(lport)); @@ -843,7 +831,6 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, fp = fc_frame_alloc(lport, sizeof(*flp)); if (fp) { - sp = lport->tt.seq_start_next(fr_seq(rx_fp)); new_flp = fc_frame_payload_get(fp, sizeof(*flp)); fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI); new_flp->fl_cmd = (u8) ELS_LS_ACC; @@ -852,11 +839,11 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, * Send the response. If this fails, the originator should * repeat the sequence. */ - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; - ep = fc_seq_exch(sp); - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, remote_fid, local_fid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); + fh = fc_frame_header_get(fp); + hton24(fh->fh_s_id, local_fid); + hton24(fh->fh_d_id, remote_fid); + lport->tt.frame_send(lport, fp); } else { fc_lport_error(lport, fp); @@ -1731,8 +1718,7 @@ static int fc_lport_els_request(struct fc_bsg_job *job, hton24(fh->fh_d_id, did); hton24(fh->fh_s_id, lport->port_id); fh->fh_type = FC_TYPE_ELS; - hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | - FC_FC_END_SEQ | FC_FC_SEQ_INIT); + hton24(fh->fh_f_ctl, FC_FCTL_REQ); fh->fh_cs_ctl = 0; fh->fh_df_ctl = 0; fh->fh_parm_offset = 0; @@ -1791,8 +1777,7 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, hton24(fh->fh_d_id, did); hton24(fh->fh_s_id, lport->port_id); fh->fh_type = FC_TYPE_CT; - hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | - FC_FC_END_SEQ | FC_FC_SEQ_INIT); + hton24(fh->fh_f_ctl, FC_FCTL_REQ); fh->fh_cs_ctl = 0; fh->fh_df_ctl = 0; fh->fh_parm_offset = 0; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 123493166824..598795123211 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -746,9 +746,8 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, struct fc_els_flogi *flp; struct fc_rport_priv *rdata; struct fc_frame *fp = rx_fp; - struct fc_exch *ep; struct fc_seq_els_data rjt_data; - u32 sid, f_ctl; + u32 sid; rjt_data.fp = NULL; sid = fc_frame_sid(fp); @@ -813,7 +812,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, rjt_data.explan = ELS_EXPL_NONE; goto reject; } - fc_frame_free(rx_fp); fp = fc_frame_alloc(lport, sizeof(*flp)); if (!fp) @@ -824,11 +822,8 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, flp = fc_frame_payload_get(fp, sizeof(*flp)); flp->fl_cmd = ELS_LS_ACC; - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; - ep = fc_seq_exch(sp); - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); if (rdata->ids.port_name < lport->wwpn) fc_rport_enter_plogi(rdata); @@ -837,12 +832,13 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, out: mutex_unlock(&rdata->rp_mutex); mutex_unlock(&disc->disc_mutex); + fc_frame_free(rx_fp); return; reject: mutex_unlock(&disc->disc_mutex); lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); - fc_frame_free(fp); + fc_frame_free(rx_fp); } /** @@ -1310,10 +1306,8 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, { struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; - struct fc_exch *ep = fc_seq_exch(sp); struct fc_els_adisc *adisc; struct fc_seq_els_data rjt_data; - u32 f_ctl; FC_RPORT_DBG(rdata, "Received ADISC request\n"); @@ -1332,11 +1326,8 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, fc_adisc_fill(lport, fp); adisc = fc_frame_payload_get(fp, sizeof(*adisc)); adisc->adisc_cmd = ELS_LS_ACC; - sp = lport->tt.seq_start_next(sp); - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); drop: fc_frame_free(in_fp); } @@ -1356,13 +1347,11 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, { struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; - struct fc_exch *ep = fc_seq_exch(sp); struct fc_els_rls *rls; struct fc_els_rls_resp *rsp; struct fc_els_lesb *lesb; struct fc_seq_els_data rjt_data; struct fc_host_statistics *hst; - u32 f_ctl; FC_RPORT_DBG(rdata, "Received RLS request while in state %s\n", fc_rport_state(rdata)); @@ -1399,11 +1388,8 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, lesb->lesb_inv_crc = htonl(hst->invalid_crc_count); } - sp = lport->tt.seq_start_next(sp); - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); goto out; out_rjt: @@ -1549,10 +1535,9 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, struct fc_disc *disc; struct fc_rport_priv *rdata; struct fc_frame *fp = rx_fp; - struct fc_exch *ep; struct fc_els_flogi *pl; struct fc_seq_els_data rjt_data; - u32 sid, f_ctl; + u32 sid; rjt_data.fp = NULL; sid = fc_frame_sid(fp); @@ -1632,27 +1617,21 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, * Get session payload size from incoming PLOGI. */ rdata->maxframe_size = fc_plogi_get_maxframe(pl, lport->mfs); - fc_frame_free(rx_fp); /* * Send LS_ACC. If this fails, the originator should retry. */ - sp = lport->tt.seq_start_next(sp); - if (!sp) - goto out; fp = fc_frame_alloc(lport, sizeof(*pl)); if (!fp) goto out; fc_plogi_fill(lport, fp, ELS_LS_ACC); - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; - ep = fc_seq_exch(sp); - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); fc_rport_enter_prli(rdata); out: mutex_unlock(&rdata->rp_mutex); + fc_frame_free(rx_fp); return; reject: @@ -1673,7 +1652,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, struct fc_seq *sp, struct fc_frame *rx_fp) { struct fc_lport *lport = rdata->local_port; - struct fc_exch *ep; struct fc_frame *fp; struct { struct fc_els_prli prli; @@ -1685,7 +1663,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, unsigned int plen; enum fc_els_spp_resp resp; struct fc_seq_els_data rjt_data; - u32 f_ctl; u32 fcp_parm; u32 roles = FC_RPORT_ROLE_UNKNOWN; @@ -1714,8 +1691,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, rjt_data.explan = ELS_EXPL_INSUF_RES; goto reject; } - sp = lport->tt.seq_start_next(sp); - WARN_ON(!sp); pp = fc_frame_payload_get(fp, len); WARN_ON(!pp); memset(pp, 0, len); @@ -1768,12 +1743,8 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, /* * Send LS_ACC. If this fails, the originator should retry. */ - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; - f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; - ep = fc_seq_exch(sp); - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); switch (rdata->rp_state) { case RPORT_ST_PRLI: @@ -1817,7 +1788,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, struct fc_els_spp *spp; /* response spp */ unsigned int len; unsigned int plen; - u32 f_ctl; struct fc_seq_els_data rjt_data; rjt_data.fp = NULL; @@ -1859,11 +1829,9 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, fc_rport_enter_delete(rdata, RPORT_EV_LOGO); - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; - f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; ep = fc_seq_exch(sp); fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); + FC_TYPE_ELS, FC_FCTL_RESP, 0); lport->tt.seq_send(lport, sp, fp); goto drop; diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index 9b4867c9c2d2..6d293c846a46 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h @@ -21,6 +21,13 @@ #define _FC_ENCODE_H_ #include +/* + * F_CTL values for simple requests and responses. + */ +#define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT) +#define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \ + FC_FC_END_SEQ | FC_FC_SEQ_INIT) + struct fc_ns_rft { struct fc_ns_fid fid; /* port ID object */ struct fc_ns_fts fts; /* FC4-types object */ diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index f1ce793f33b3..a6414ec63809 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -1027,6 +1027,10 @@ struct fc_seq *fc_elsct_send(struct fc_lport *, u32 did, void *arg, u32 timer_msec); void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); +void fc_fill_reply_hdr(struct fc_frame *, const struct fc_frame *, + enum fc_rctl, u32 parm_offset); +void fc_fill_hdr(struct fc_frame *, const struct fc_frame *, + enum fc_rctl, u32 f_ctl, u16 seq_cnt, u32 parm_offset); /* -- cgit v1.2.3 From 239e81048b7dcd27448db40c845f88ac7c68424e Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:21:07 -0700 Subject: [SCSI] libfc: add interface to allocate a sequence for incoming requests For incoming ELS and FCP requests, we often don't require an exchange and sequence, however, sometimes we do. For those cases, (primarily FCP requests for targets) add a function to set up the exchange and sequence. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 25 +++++++++++++++++++++++++ include/scsi/libfc.h | 7 +++++++ 2 files changed, 32 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 61eabd3ce436..027042a6de3b 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1230,6 +1230,28 @@ free: fc_frame_free(rx_fp); } +/** + * fc_seq_assign() - Assign exchange and sequence for incoming request + * @lport: The local port that received the request + * @fp: The request frame + * + * On success, the sequence pointer will be returned and also in fr_seq(@fp). + */ +static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_exch_mgr_anchor *ema; + + WARN_ON(lport != fr_dev(fp)); + WARN_ON(fr_seq(fp)); + fr_seq(fp) = NULL; + + list_for_each_entry(ema, &lport->ema_list, ema_list) + if ((!ema->match || ema->match(fp)) && + fc_seq_lookup_recip(lport, ema->mp, fp) != FC_RJT_NONE) + break; + return fr_seq(fp); +} + /** * fc_exch_recv_req() - Handler for an incoming request where is other * end is originating the sequence @@ -2283,6 +2305,9 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_exch_abort) lport->tt.seq_exch_abort = fc_seq_exch_abort; + if (!lport->tt.seq_assign) + lport->tt.seq_assign = fc_seq_assign; + return 0; } EXPORT_SYMBOL(fc_exch_init); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index a6414ec63809..605f1d7861a7 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -555,6 +555,13 @@ struct libfc_function_template { */ struct fc_seq *(*seq_start_next)(struct fc_seq *); + /* + * Assign a sequence for an incoming request frame. + * + * STATUS: OPTIONAL + */ + struct fc_seq *(*seq_assign)(struct fc_lport *, struct fc_frame *); + /* * Reset an exchange manager, completing all sequences and exchanges. * If s_id is non-zero, reset only exchanges originating from that FID. -- cgit v1.2.3 From 922611569572d3c1aa0ed6491d21583fb3fcca22 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 20 Jul 2010 15:21:12 -0700 Subject: [SCSI] libfc: don't require a local exchange for incoming requests Incoming requests shouldn't require a local exchange if we're just going to reply with one or two frames and don't expect anything further. Don't allocate exchanges for such requests until requested by the upper-layer protocol. The sequence is always NULL for new requests, so remove that as an argument to request handlers. Also change the first argument to lport->tt.seq_els_rsp_send from the sequence pointer to the received frame pointer, to supply the exchange IDs and destination ID info. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 9 +- drivers/scsi/libfc/fc_disc.c | 19 ++--- drivers/scsi/libfc/fc_exch.c | 188 ++++++++++++++++++++++-------------------- drivers/scsi/libfc/fc_lport.c | 58 +++++-------- drivers/scsi/libfc/fc_rport.c | 112 +++++++++---------------- include/scsi/libfc.h | 16 ++-- 6 files changed, 174 insertions(+), 228 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 4de8ced1fee7..2c265fe9ab32 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -2341,20 +2341,19 @@ drop: /** * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode. - * @fip: The FCoE controller + * @lport: The local port + * @fp: The received frame * * This should never be called since we don't see RSCNs or other * fabric-generated ELSes. */ -static void fcoe_ctlr_disc_recv(struct fc_seq *seq, struct fc_frame *fp, - struct fc_lport *lport) +static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp) { struct fc_seq_els_data rjt_data; - rjt_data.fp = NULL; rjt_data.reason = ELS_RJT_UNSUP; rjt_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(seq, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); fc_frame_free(fp); } diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 04474556f2dc..32f67c4b03fc 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -75,15 +75,13 @@ void fc_disc_stop_rports(struct fc_disc *disc) /** * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) - * @sp: The sequence of the RSCN exchange + * @disc: The discovery object to which the RSCN applies * @fp: The RSCN frame - * @lport: The local port that the request will be sent on * * Locking Note: This function expects that the disc_mutex is locked * before it is called. */ -static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, - struct fc_disc *disc) +static void fc_disc_recv_rscn_req(struct fc_disc *disc, struct fc_frame *fp) { struct fc_lport *lport; struct fc_els_rscn *rp; @@ -151,7 +149,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, break; } } - lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); + lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); /* * If not doing a complete rediscovery, do GPN_ID on @@ -177,25 +175,22 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, return; reject: FC_DISC_DBG(disc, "Received a bad RSCN frame\n"); - rjt_data.fp = NULL; rjt_data.reason = ELS_RJT_LOGIC; rjt_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); fc_frame_free(fp); } /** * fc_disc_recv_req() - Handle incoming requests - * @sp: The sequence of the request exchange - * @fp: The request frame * @lport: The local port receiving the request + * @fp: The request frame * * Locking Note: This function is called from the EM and will lock * the disc_mutex before calling the handler for the * request. */ -static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, - struct fc_lport *lport) +static void fc_disc_recv_req(struct fc_lport *lport, struct fc_frame *fp) { u8 op; struct fc_disc *disc = &lport->disc; @@ -204,7 +199,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, switch (op) { case ELS_RSCN: mutex_lock(&disc->disc_mutex); - fc_disc_recv_rscn_req(sp, fp, disc); + fc_disc_recv_rscn_req(disc, fp); mutex_unlock(&disc->disc_mutex); break; default: diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 027042a6de3b..b8560ad8cf66 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -129,11 +129,11 @@ struct fc_exch_mgr_anchor { }; static void fc_exch_rrq(struct fc_exch *); -static void fc_seq_ls_acc(struct fc_seq *); -static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason, +static void fc_seq_ls_acc(struct fc_frame *); +static void fc_seq_ls_rjt(struct fc_frame *, enum fc_els_rjt_reason, enum fc_els_rjt_explan); -static void fc_exch_els_rec(struct fc_seq *, struct fc_frame *); -static void fc_exch_els_rrq(struct fc_seq *, struct fc_frame *); +static void fc_exch_els_rec(struct fc_frame *); +static void fc_exch_els_rrq(struct fc_frame *); /* * Internal implementation notes. @@ -1003,28 +1003,30 @@ static void fc_exch_set_addr(struct fc_exch *ep, /** * fc_seq_els_rsp_send() - Send an ELS response using infomation from * the existing sequence/exchange. - * @sp: The sequence/exchange to get information from + * @fp: The received frame * @els_cmd: The ELS command to be sent * @els_data: The ELS data to be sent + * + * The received frame is not freed. */ -static void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, +static void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd, struct fc_seq_els_data *els_data) { switch (els_cmd) { case ELS_LS_RJT: - fc_seq_ls_rjt(sp, els_data->reason, els_data->explan); + fc_seq_ls_rjt(fp, els_data->reason, els_data->explan); break; case ELS_LS_ACC: - fc_seq_ls_acc(sp); + fc_seq_ls_acc(fp); break; case ELS_RRQ: - fc_exch_els_rrq(sp, els_data->fp); + fc_exch_els_rrq(fp); break; case ELS_REC: - fc_exch_els_rec(sp, els_data->fp); + fc_exch_els_rec(fp); break; default: - FC_EXCH_DBG(fc_seq_exch(sp), "Invalid ELS CMD:%x\n", els_cmd); + FC_LPORT_DBG(fr_dev(fp), "Invalid ELS CMD:%x\n", els_cmd); } } @@ -1253,11 +1255,13 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_exch_recv_req() - Handler for an incoming request where is other - * end is originating the sequence + * fc_exch_recv_req() - Handler for an incoming request * @lport: The local port that received the request * @mp: The EM that the exchange is on * @fp: The request frame + * + * This is used when the other end is originating the exchange + * and the sequence. */ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, struct fc_frame *fp) @@ -1275,8 +1279,17 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, fc_frame_free(fp); return; } + fr_dev(fp) = lport; + + BUG_ON(fr_seq(fp)); /* XXX remove later */ + + /* + * If the RX_ID is 0xffff, don't allocate an exchange. + * The upper-level protocol may request one later, if needed. + */ + if (fh->fh_rx_id == htons(FC_XID_UNKNOWN)) + return lport->tt.lport_recv(lport, fp); - fr_seq(fp) = NULL; reject = fc_seq_lookup_recip(lport, mp, fp); if (reject == FC_RJT_NONE) { sp = fr_seq(fp); /* sequence will be held */ @@ -1298,7 +1311,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, if (ep->resp) ep->resp(sp, fp, ep->arg); else - lport->tt.lport_recv(lport, sp, fp); + lport->tt.lport_recv(lport, fp); fc_exch_release(ep); /* release from lookup */ } else { FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n", @@ -1566,53 +1579,55 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp) /** * fc_seq_ls_acc() - Accept sequence with LS_ACC - * @req_sp: The request sequence + * @rx_fp: The received frame, not freed here. * * If this fails due to allocation or transmit congestion, assume the * originator will repeat the sequence. */ -static void fc_seq_ls_acc(struct fc_seq *req_sp) +static void fc_seq_ls_acc(struct fc_frame *rx_fp) { - struct fc_seq *sp; + struct fc_lport *lport; struct fc_els_ls_acc *acc; struct fc_frame *fp; - sp = fc_seq_start_next(req_sp); - fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*acc)); - if (fp) { - acc = fc_frame_payload_get(fp, sizeof(*acc)); - memset(acc, 0, sizeof(*acc)); - acc->la_cmd = ELS_LS_ACC; - fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); - } + lport = fr_dev(rx_fp); + fp = fc_frame_alloc(lport, sizeof(*acc)); + if (!fp) + return; + acc = fc_frame_payload_get(fp, sizeof(*acc)); + memset(acc, 0, sizeof(*acc)); + acc->la_cmd = ELS_LS_ACC; + fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); } /** * fc_seq_ls_rjt() - Reject a sequence with ELS LS_RJT - * @req_sp: The request sequence + * @rx_fp: The received frame, not freed here. * @reason: The reason the sequence is being rejected - * @explan: The explaination for the rejection + * @explan: The explanation for the rejection * * If this fails due to allocation or transmit congestion, assume the * originator will repeat the sequence. */ -static void fc_seq_ls_rjt(struct fc_seq *req_sp, enum fc_els_rjt_reason reason, +static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason, enum fc_els_rjt_explan explan) { - struct fc_seq *sp; + struct fc_lport *lport; struct fc_els_ls_rjt *rjt; struct fc_frame *fp; - sp = fc_seq_start_next(req_sp); - fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*rjt)); - if (fp) { - rjt = fc_frame_payload_get(fp, sizeof(*rjt)); - memset(rjt, 0, sizeof(*rjt)); - rjt->er_cmd = ELS_LS_RJT; - rjt->er_reason = reason; - rjt->er_explan = explan; - fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); - } + lport = fr_dev(rx_fp); + fp = fc_frame_alloc(lport, sizeof(*rjt)); + if (!fp) + return; + rjt = fc_frame_payload_get(fp, sizeof(*rjt)); + memset(rjt, 0, sizeof(*rjt)); + rjt->er_cmd = ELS_LS_RJT; + rjt->er_reason = reason; + rjt->er_explan = explan; + fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); } /** @@ -1714,18 +1729,34 @@ void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did) } EXPORT_SYMBOL(fc_exch_mgr_reset); +/** + * fc_exch_lookup() - find an exchange + * @lport: The local port + * @xid: The exchange ID + * + * Returns exchange pointer with hold for caller, or NULL if not found. + */ +static struct fc_exch *fc_exch_lookup(struct fc_lport *lport, u32 xid) +{ + struct fc_exch_mgr_anchor *ema; + + list_for_each_entry(ema, &lport->ema_list, ema_list) + if (ema->mp->min_xid <= xid && xid <= ema->mp->max_xid) + return fc_exch_find(ema->mp, xid); + return NULL; +} + /** * fc_exch_els_rec() - Handler for ELS REC (Read Exchange Concise) requests - * @sp: The sequence the REC is on - * @rfp: The REC frame + * @rfp: The REC frame, not freed here. * * Note that the requesting port may be different than the S_ID in the request. */ -static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) +static void fc_exch_els_rec(struct fc_frame *rfp) { + struct fc_lport *lport; struct fc_frame *fp; struct fc_exch *ep; - struct fc_exch_mgr *em; struct fc_els_rec *rp; struct fc_els_rec_acc *acc; enum fc_els_rjt_reason reason = ELS_RJT_LOGIC; @@ -1734,6 +1765,7 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) u16 rxid; u16 oxid; + lport = fr_dev(rfp); rp = fc_frame_payload_get(rfp, sizeof(*rp)); explan = ELS_EXPL_INV_LEN; if (!rp) @@ -1742,35 +1774,19 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) rxid = ntohs(rp->rec_rx_id); oxid = ntohs(rp->rec_ox_id); - /* - * Currently it's hard to find the local S_ID from the exchange - * manager. This will eventually be fixed, but for now it's easier - * to lookup the subject exchange twice, once as if we were - * the initiator, and then again if we weren't. - */ - em = fc_seq_exch(sp)->em; - ep = fc_exch_find(em, oxid); + ep = fc_exch_lookup(lport, + sid == fc_host_port_id(lport->host) ? oxid : rxid); explan = ELS_EXPL_OXID_RXID; - if (ep && ep->oid == sid) { - if (ep->rxid != FC_XID_UNKNOWN && - rxid != FC_XID_UNKNOWN && - ep->rxid != rxid) - goto rel; - } else { - if (ep) - fc_exch_release(ep); - ep = NULL; - if (rxid != FC_XID_UNKNOWN) - ep = fc_exch_find(em, rxid); - if (!ep) - goto reject; - } - - fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*acc)); - if (!fp) { - fc_exch_done(sp); + if (!ep) + goto reject; + if (ep->oid != sid || oxid != ep->oxid) + goto rel; + if (rxid != FC_XID_UNKNOWN && rxid != ep->rxid) + goto rel; + fp = fc_frame_alloc(lport, sizeof(*acc)); + if (!fp) goto out; - } + acc = fc_frame_payload_get(fp, sizeof(*acc)); memset(acc, 0, sizeof(*acc)); acc->reca_cmd = ELS_LS_ACC; @@ -1785,18 +1801,16 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) acc->reca_e_stat = htonl(ep->esb_stat & (ESB_ST_RESP | ESB_ST_SEQ_INIT | ESB_ST_COMPLETE)); - sp = fc_seq_start_next(sp); - fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); + fc_fill_reply_hdr(fp, rfp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); out: fc_exch_release(ep); - fc_frame_free(rfp); return; rel: fc_exch_release(ep); reject: - fc_seq_ls_rjt(sp, reason, explan); - fc_frame_free(rfp); + fc_seq_ls_rjt(rfp, reason, explan); } /** @@ -1971,20 +1985,20 @@ retry: spin_unlock_bh(&ep->ex_lock); } - /** * fc_exch_els_rrq() - Handler for ELS RRQ (Reset Recovery Qualifier) requests - * @sp: The sequence that the RRQ is on - * @fp: The RRQ frame + * @fp: The RRQ frame, not freed here. */ -static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) +static void fc_exch_els_rrq(struct fc_frame *fp) { + struct fc_lport *lport; struct fc_exch *ep = NULL; /* request or subject exchange */ struct fc_els_rrq *rp; u32 sid; u16 xid; enum fc_els_rjt_explan explan; + lport = fr_dev(fp); rp = fc_frame_payload_get(fp, sizeof(*rp)); explan = ELS_EXPL_INV_LEN; if (!rp) @@ -1993,11 +2007,10 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) /* * lookup subject exchange. */ - ep = fc_seq_exch(sp); sid = ntoh24(rp->rrq_s_id); /* subject source */ - xid = ep->did == sid ? ntohs(rp->rrq_ox_id) : ntohs(rp->rrq_rx_id); - ep = fc_exch_find(ep->em, xid); - + xid = fc_host_port_id(lport->host) == sid ? + ntohs(rp->rrq_ox_id) : ntohs(rp->rrq_rx_id); + ep = fc_exch_lookup(lport, xid); explan = ELS_EXPL_OXID_RXID; if (!ep) goto reject; @@ -2028,15 +2041,14 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) /* * Send LS_ACC. */ - fc_seq_ls_acc(sp); + fc_seq_ls_acc(fp); goto out; unlock_reject: spin_unlock_bh(&ep->ex_lock); reject: - fc_seq_ls_rjt(sp, ELS_RJT_LOGIC, explan); + fc_seq_ls_rjt(fp, ELS_RJT_LOGIC, explan); out: - fc_frame_free(fp); if (ep) fc_exch_release(ep); /* drop hold from fc_exch_find */ } @@ -2267,7 +2279,7 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp) fc_exch_recv_seq_resp(ema->mp, fp); else if (f_ctl & FC_FC_SEQ_CTX) fc_exch_recv_resp(ema->mp, fp); - else + else /* no EX_CTX and no SEQ_CTX */ fc_exch_recv_req(lport, ema->mp, fp); break; default: diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index e50a6606d4bf..1998c03634da 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -375,34 +375,31 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) /** * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. - * @sp: The sequence in the RLIR exchange - * @fp: The RLIR request frame * @lport: Fibre Channel local port recieving the RLIR + * @fp: The RLIR request frame * * Locking Note: The lport lock is expected to be held before calling * this function. */ -static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, - struct fc_lport *lport) +static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp) { FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", fc_lport_state(lport)); - lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); + lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); fc_frame_free(fp); } /** * fc_lport_recv_echo_req() - Handle received ECHO request - * @sp: The sequence in the ECHO exchange - * @fp: ECHO request frame * @lport: The local port recieving the ECHO + * @fp: ECHO request frame * * Locking Note: The lport lock is expected to be held before calling * this function. */ -static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, - struct fc_lport *lport) +static void fc_lport_recv_echo_req(struct fc_lport *lport, + struct fc_frame *in_fp) { struct fc_frame *fp; unsigned int len; @@ -431,15 +428,14 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, /** * fc_lport_recv_rnid_req() - Handle received Request Node ID data request - * @sp: The sequence in the RNID exchange - * @fp: The RNID request frame * @lport: The local port recieving the RNID + * @fp: The RNID request frame * * Locking Note: The lport lock is expected to be held before calling * this function. */ -static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, - struct fc_lport *lport) +static void fc_lport_recv_rnid_req(struct fc_lport *lport, + struct fc_frame *in_fp) { struct fc_frame *fp; struct fc_els_rnid *req; @@ -457,10 +453,9 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, req = fc_frame_payload_get(in_fp, sizeof(*req)); if (!req) { - rjt_data.fp = NULL; rjt_data.reason = ELS_RJT_LOGIC; rjt_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); } else { fmt = req->rnid_fmt; len = sizeof(*rp); @@ -492,17 +487,15 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, /** * fc_lport_recv_logo_req() - Handle received fabric LOGO request - * @sp: The sequence in the LOGO exchange - * @fp: The LOGO request frame * @lport: The local port recieving the LOGO + * @fp: The LOGO request frame * * Locking Note: The lport lock is exected to be held before calling * this function. */ -static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, - struct fc_lport *lport) +static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) { - lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); + lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); fc_lport_enter_reset(lport); fc_frame_free(fp); } @@ -773,9 +766,8 @@ EXPORT_SYMBOL(fc_lport_set_local_id); /** * fc_lport_recv_flogi_req() - Receive a FLOGI request - * @sp_in: The sequence the FLOGI is on - * @rx_fp: The FLOGI frame * @lport: The local port that recieved the request + * @rx_fp: The FLOGI frame * * A received FLOGI request indicates a point-to-point connection. * Accept it with the common service parameters indicating our N port. @@ -784,13 +776,11 @@ EXPORT_SYMBOL(fc_lport_set_local_id); * Locking Note: The lport lock is expected to be held before calling * this function. */ -static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, - struct fc_frame *rx_fp, - struct fc_lport *lport) +static void fc_lport_recv_flogi_req(struct fc_lport *lport, + struct fc_frame *rx_fp) { struct fc_frame *fp; struct fc_frame_header *fh; - struct fc_seq *sp; struct fc_els_flogi *flp; struct fc_els_flogi *new_flp; u64 remote_wwpn; @@ -850,16 +840,13 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, } fc_lport_ptp_setup(lport, remote_fid, remote_wwpn, get_unaligned_be64(&flp->fl_wwnn)); - out: - sp = fr_seq(rx_fp); fc_frame_free(rx_fp); } /** * fc_lport_recv_req() - The generic lport request handler * @lport: The local port that received the request - * @sp: The sequence the request is on * @fp: The request frame * * This function will see if the lport handles the request or @@ -868,11 +855,10 @@ out: * Locking Note: This function should not be called with the lport * lock held becuase it will grab the lock. */ -static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, - struct fc_frame *fp) +static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); - void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *); + void (*recv)(struct fc_lport *, struct fc_frame *); mutex_lock(&lport->lp_mutex); @@ -912,19 +898,13 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, break; } - recv(sp, fp, lport); + recv(lport, fp); } else { FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", fr_eof(fp)); fc_frame_free(fp); } mutex_unlock(&lport->lp_mutex); - - /* - * The common exch_done for all request may not be good - * if any request requires longer hold on exhange. XXX - */ - lport->tt.exch_done(sp); } /** diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 598795123211..25479cc7f170 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -68,14 +68,10 @@ static void fc_rport_enter_ready(struct fc_rport_priv *); static void fc_rport_enter_logo(struct fc_rport_priv *); static void fc_rport_enter_adisc(struct fc_rport_priv *); -static void fc_rport_recv_plogi_req(struct fc_lport *, - struct fc_seq *, struct fc_frame *); -static void fc_rport_recv_prli_req(struct fc_rport_priv *, - struct fc_seq *, struct fc_frame *); -static void fc_rport_recv_prlo_req(struct fc_rport_priv *, - struct fc_seq *, struct fc_frame *); -static void fc_rport_recv_logo_req(struct fc_lport *, - struct fc_seq *, struct fc_frame *); +static void fc_rport_recv_plogi_req(struct fc_lport *, struct fc_frame *); +static void fc_rport_recv_prli_req(struct fc_rport_priv *, struct fc_frame *); +static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *); +static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *); static void fc_rport_timeout(struct work_struct *); static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *); static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *); @@ -736,11 +732,10 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) /** * fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode * @lport: The local port that received the PLOGI request - * @sp: The sequence that the PLOGI request was on * @rx_fp: The PLOGI request frame */ static void fc_rport_recv_flogi_req(struct fc_lport *lport, - struct fc_seq *sp, struct fc_frame *rx_fp) + struct fc_frame *rx_fp) { struct fc_disc *disc; struct fc_els_flogi *flp; @@ -749,7 +744,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, struct fc_seq_els_data rjt_data; u32 sid; - rjt_data.fp = NULL; sid = fc_frame_sid(fp); FC_RPORT_ID_DBG(lport, sid, "Received FLOGI request\n"); @@ -817,7 +811,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, if (!fp) goto out; - sp = lport->tt.seq_start_next(sp); fc_flogi_fill(lport, fp); flp = fc_frame_payload_get(fp, sizeof(*flp)); flp->fl_cmd = ELS_LS_ACC; @@ -837,7 +830,7 @@ out: reject: mutex_unlock(&disc->disc_mutex); - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); fc_frame_free(rx_fp); } @@ -1296,13 +1289,12 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) /** * fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests * @rdata: The remote port that sent the ADISC request - * @sp: The sequence the ADISC request was on * @in_fp: The ADISC request frame * * Locking Note: Called with the lport and rport locks held. */ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, - struct fc_seq *sp, struct fc_frame *in_fp) + struct fc_frame *in_fp) { struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; @@ -1313,10 +1305,9 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, adisc = fc_frame_payload_get(in_fp, sizeof(*adisc)); if (!adisc) { - rjt_data.fp = NULL; rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); goto drop; } @@ -1335,14 +1326,13 @@ drop: /** * fc_rport_recv_rls_req() - Handle received Read Link Status request * @rdata: The remote port that sent the RLS request - * @sp: The sequence that the RLS was on * @rx_fp: The PRLI request frame * * Locking Note: The rport lock is expected to be held before calling * this function. */ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, - struct fc_seq *sp, struct fc_frame *rx_fp) + struct fc_frame *rx_fp) { struct fc_lport *lport = rdata->local_port; @@ -1393,8 +1383,7 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, goto out; out_rjt: - rjt_data.fp = NULL; - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); out: fc_frame_free(rx_fp); } @@ -1402,7 +1391,6 @@ out: /** * fc_rport_recv_els_req() - Handler for validated ELS requests * @lport: The local port that received the ELS request - * @sp: The sequence that the ELS request was on * @fp: The ELS request frame * * Handle incoming ELS requests that require port login. @@ -1410,16 +1398,11 @@ out: * * Locking Note: Called with the lport lock held. */ -static void fc_rport_recv_els_req(struct fc_lport *lport, - struct fc_seq *sp, struct fc_frame *fp) +static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) { struct fc_rport_priv *rdata; struct fc_seq_els_data els_data; - els_data.fp = NULL; - els_data.reason = ELS_RJT_UNAB; - els_data.explan = ELS_EXPL_PLOGI_REQD; - mutex_lock(&lport->disc.disc_mutex); rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); if (!rdata) { @@ -1442,24 +1425,24 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, switch (fc_frame_payload_op(fp)) { case ELS_PRLI: - fc_rport_recv_prli_req(rdata, sp, fp); + fc_rport_recv_prli_req(rdata, fp); break; case ELS_PRLO: - fc_rport_recv_prlo_req(rdata, sp, fp); + fc_rport_recv_prlo_req(rdata, fp); break; case ELS_ADISC: - fc_rport_recv_adisc_req(rdata, sp, fp); + fc_rport_recv_adisc_req(rdata, fp); break; case ELS_RRQ: - els_data.fp = fp; - lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data); + lport->tt.seq_els_rsp_send(fp, ELS_RRQ, NULL); + fc_frame_free(fp); break; case ELS_REC: - els_data.fp = fp; - lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data); + lport->tt.seq_els_rsp_send(fp, ELS_REC, NULL); + fc_frame_free(fp); break; case ELS_RLS: - fc_rport_recv_rls_req(rdata, sp, fp); + fc_rport_recv_rls_req(rdata, fp); break; default: fc_frame_free(fp); /* can't happen */ @@ -1470,20 +1453,20 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, return; reject: - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data); + els_data.reason = ELS_RJT_UNAB; + els_data.explan = ELS_EXPL_PLOGI_REQD; + lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); } /** * fc_rport_recv_req() - Handler for requests - * @sp: The sequence the request was on - * @fp: The request frame * @lport: The local port that received the request + * @fp: The request frame * * Locking Note: Called with the lport lock held. */ -void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, - struct fc_lport *lport) +void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) { struct fc_seq_els_data els_data; @@ -1495,13 +1478,13 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, */ switch (fc_frame_payload_op(fp)) { case ELS_FLOGI: - fc_rport_recv_flogi_req(lport, sp, fp); + fc_rport_recv_flogi_req(lport, fp); break; case ELS_PLOGI: - fc_rport_recv_plogi_req(lport, sp, fp); + fc_rport_recv_plogi_req(lport, fp); break; case ELS_LOGO: - fc_rport_recv_logo_req(lport, sp, fp); + fc_rport_recv_logo_req(lport, fp); break; case ELS_PRLI: case ELS_PRLO: @@ -1509,14 +1492,13 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, case ELS_RRQ: case ELS_REC: case ELS_RLS: - fc_rport_recv_els_req(lport, sp, fp); + fc_rport_recv_els_req(lport, fp); break; default: - fc_frame_free(fp); - els_data.fp = NULL; els_data.reason = ELS_RJT_UNSUP; els_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data); + lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_frame_free(fp); break; } } @@ -1524,13 +1506,12 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, /** * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests * @lport: The local port that received the PLOGI request - * @sp: The sequence that the PLOGI request was on * @rx_fp: The PLOGI request frame * * Locking Note: The rport lock is held before calling this function. */ static void fc_rport_recv_plogi_req(struct fc_lport *lport, - struct fc_seq *sp, struct fc_frame *rx_fp) + struct fc_frame *rx_fp) { struct fc_disc *disc; struct fc_rport_priv *rdata; @@ -1539,7 +1520,6 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, struct fc_seq_els_data rjt_data; u32 sid; - rjt_data.fp = NULL; sid = fc_frame_sid(fp); FC_RPORT_ID_DBG(lport, sid, "Received PLOGI request\n"); @@ -1635,21 +1615,20 @@ out: return; reject: - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); fc_frame_free(fp); } /** * fc_rport_recv_prli_req() - Handler for process login (PRLI) requests * @rdata: The remote port that sent the PRLI request - * @sp: The sequence that the PRLI was on * @rx_fp: The PRLI request frame * * Locking Note: The rport lock is exected to be held before calling * this function. */ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, - struct fc_seq *sp, struct fc_frame *rx_fp) + struct fc_frame *rx_fp) { struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; @@ -1666,7 +1645,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, u32 fcp_parm; u32 roles = FC_RPORT_ROLE_UNKNOWN; - rjt_data.fp = NULL; FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", fc_rport_state(rdata)); @@ -1759,7 +1737,7 @@ reject_len: rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; reject: - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); drop: fc_frame_free(rx_fp); } @@ -1767,18 +1745,15 @@ drop: /** * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests * @rdata: The remote port that sent the PRLO request - * @sp: The sequence that the PRLO was on * @rx_fp: The PRLO request frame * * Locking Note: The rport lock is exected to be held before calling * this function. */ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, - struct fc_seq *sp, struct fc_frame *rx_fp) { struct fc_lport *lport = rdata->local_port; - struct fc_exch *ep; struct fc_frame *fp; struct { struct fc_els_prlo prlo; @@ -1790,8 +1765,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, unsigned int plen; struct fc_seq_els_data rjt_data; - rjt_data.fp = NULL; - FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n", fc_rport_state(rdata)); @@ -1814,8 +1787,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, goto reject; } - sp = lport->tt.seq_start_next(sp); - WARN_ON(!sp); pp = fc_frame_payload_get(fp, len); WARN_ON(!pp); memset(pp, 0, len); @@ -1829,17 +1800,15 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, fc_rport_enter_delete(rdata, RPORT_EV_LOGO); - ep = fc_seq_exch(sp); - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, FC_FCTL_RESP, 0); - lport->tt.seq_send(lport, sp, fp); + fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); goto drop; reject_len: rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; reject: - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); + lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); drop: fc_frame_free(rx_fp); } @@ -1847,20 +1816,17 @@ drop: /** * fc_rport_recv_logo_req() - Handler for logout (LOGO) requests * @lport: The local port that received the LOGO request - * @sp: The sequence that the LOGO request was on * @fp: The LOGO request frame * * Locking Note: The rport lock is exected to be held before calling * this function. */ -static void fc_rport_recv_logo_req(struct fc_lport *lport, - struct fc_seq *sp, - struct fc_frame *fp) +static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) { struct fc_rport_priv *rdata; u32 sid; - lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); + lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); sid = fc_frame_sid(fp); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 605f1d7861a7..14be49b44e84 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -249,14 +249,12 @@ struct fcoe_dev_stats { /** * struct fc_seq_els_data - ELS data used for passing ELS specific responses - * @fp: The ELS frame * @reason: The reason for rejection * @explan: The explaination of the rejection * * Mainly used by the exchange manager layer. */ struct fc_seq_els_data { - struct fc_frame *fp; enum fc_els_rjt_reason reason; enum fc_els_rjt_explan explan; }; @@ -519,12 +517,11 @@ struct libfc_function_template { struct fc_frame *); /* - * Send an ELS response using infomation from a previous - * exchange and sequence. + * Send an ELS response using infomation from the received frame. * * STATUS: OPTIONAL */ - void (*seq_els_rsp_send)(struct fc_seq *, enum fc_els_cmd, + void (*seq_els_rsp_send)(struct fc_frame *, enum fc_els_cmd, struct fc_seq_els_data *); /* @@ -583,8 +580,7 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - void (*lport_recv)(struct fc_lport *, struct fc_seq *, - struct fc_frame *); + void (*lport_recv)(struct fc_lport *, struct fc_frame *); /* * Reset the local port. @@ -646,8 +642,7 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - void (*rport_recv_req)(struct fc_seq *, struct fc_frame *, - struct fc_lport *); + void (*rport_recv_req)(struct fc_lport *, struct fc_frame *); /* * lookup an rport by it's port ID. @@ -693,8 +688,7 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - void (*disc_recv_req)(struct fc_seq *, struct fc_frame *, - struct fc_lport *); + void (*disc_recv_req)(struct fc_lport *, struct fc_frame *); /* * Start discovery for a local port. -- cgit v1.2.3 From 54a5b21da9d4d3f58770da5d1c244db9724659ee Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 20 Jul 2010 15:21:17 -0700 Subject: [SCSI] fcoe: fix offload feature flag change from netdev Currently, when FCoE netdev feature flags are toggled by the LLD, lport's corresponding flags are not updated. This causes the fc_fcp to still try to offload the I/O. This patch adds support of NETDEV_FEAT_CHANGE event in fcoe netdev device notification callback so we can update the lport offload flags appropriately. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 68 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index ab6ea60f2aee..cf9d718c731c 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -588,6 +588,50 @@ static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type) return -EINVAL; } +/** + * fcoe_netdev_features_change - Updates the lport's offload flags based + * on the LLD netdev's FCoE feature flags + */ +static void fcoe_netdev_features_change(struct fc_lport *lport, + struct net_device *netdev) +{ + mutex_lock(&lport->lp_mutex); + + if (netdev->features & NETIF_F_SG) + lport->sg_supp = 1; + else + lport->sg_supp = 0; + + if (netdev->features & NETIF_F_FCOE_CRC) { + lport->crc_offload = 1; + FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n"); + } else { + lport->crc_offload = 0; + } + + if (netdev->features & NETIF_F_FSO) { + lport->seq_offload = 1; + lport->lso_max = netdev->gso_max_size; + FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n", + lport->lso_max); + } else { + lport->seq_offload = 0; + lport->lso_max = 0; + } + + if (netdev->fcoe_ddp_xid) { + lport->lro_enabled = 1; + lport->lro_xid = netdev->fcoe_ddp_xid; + FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n", + lport->lro_xid); + } else { + lport->lro_enabled = 0; + lport->lro_xid = 0; + } + + mutex_unlock(&lport->lp_mutex); +} + /** * fcoe_netdev_config() - Set up net devive for SW FCoE * @lport: The local port that is associated with the net device @@ -624,25 +668,8 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) return -EINVAL; /* offload features support */ - if (netdev->features & NETIF_F_SG) - lport->sg_supp = 1; + fcoe_netdev_features_change(lport, netdev); - if (netdev->features & NETIF_F_FCOE_CRC) { - lport->crc_offload = 1; - FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n"); - } - if (netdev->features & NETIF_F_FSO) { - lport->seq_offload = 1; - lport->lso_max = netdev->gso_max_size; - FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n", - lport->lso_max); - } - if (netdev->fcoe_ddp_xid) { - lport->lro_enabled = 1; - lport->lro_xid = netdev->fcoe_ddp_xid; - FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n", - lport->lro_xid); - } skb_queue_head_init(&port->fcoe_pending_queue); port->fcoe_pending_queue_active = 0; setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport); @@ -1861,6 +1888,9 @@ static int fcoe_device_notification(struct notifier_block *notifier, schedule_work(&port->destroy_work); goto out; break; + case NETDEV_FEAT_CHANGE: + fcoe_netdev_features_change(lport, netdev); + break; default: FCOE_NETDEV_DBG(netdev, "Unknown event %ld " "from netdev netlink\n", event); @@ -2056,8 +2086,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) rc = -ENODEV; goto out_putdev; } - list_del(&fcoe->list); fcoe_interface_cleanup(fcoe); + list_del(&fcoe->list); /* RTNL mutex is dropped by fcoe_if_destroy */ fcoe_if_destroy(fcoe->ctlr.lp); -- cgit v1.2.3 From cf4aebcafb44a8810af10006dd4a5fcfb07bb810 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Tue, 20 Jul 2010 15:21:22 -0700 Subject: [SCSI] Revert "[SCSI] fcoe: Fix using VLAN ID in creating lport's WWWN/WWPN" This reverts commit cc0136c2e9c10e889cb36e39710c0eb10707b396. That commit introduced vlan id info to WWPN but WWPN needs to remain static as an unique port identifier in the fabric, therefore variable fabric vlan id info doesn't need to be coded inside WWPN. After this revert, port arg to fcoe_wwn_from_mac is always zero but still leaving it as-is okay to later allow users to use NAA 2 scheme with this additional port arg. Note with this patch, existing zoning using WWPN would require re-zoning this time only and later no more re-zoning due to any vlan id changes. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index cf9d718c731c..ddd2ca27e003 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -647,7 +647,6 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) u64 wwnn, wwpn; struct fcoe_interface *fcoe; struct fcoe_port *port; - int vid = 0; /* Setup lport private data to point to fcoe softc */ port = lport_priv(lport); @@ -677,20 +676,12 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) fcoe_link_speed_update(lport); if (!lport->vport) { - /* - * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN: - * For WWNN, we use NAA 1 w/ bit 27-16 of word 0 as 0. - * For WWPN, we use NAA 2 w/ bit 27-16 of word 0 from VLAN ID - */ - if (netdev->priv_flags & IFF_802_1Q_VLAN) - vid = vlan_dev_vlan_id(netdev); - if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0); fc_set_wwnn(lport, wwnn); if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, - 2, vid); + 2, 0); fc_set_wwpn(lport, wwpn); } -- cgit v1.2.3 From 7f985231d274ef3e6e4d56a2939a534906299021 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Tue, 20 Jul 2010 15:21:27 -0700 Subject: [SCSI] libfc: Add retry logic to lport state machine when receiving LS_RJT Call fc_lport_error to retry upto max retry count when FLOGI/SCR/NS gets rejected. Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 63 +++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 36 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 1998c03634da..6eb334a8a7fa 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1012,38 +1012,24 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) PTR_ERR(fp), fc_lport_state(lport), lport->retry_count); - if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { - /* - * Memory allocation failure, or the exchange timed out. - * Retry after delay - */ - if (lport->retry_count < lport->max_retry_count) { - lport->retry_count++; - if (!fp) - delay = msecs_to_jiffies(500); - else - delay = msecs_to_jiffies(lport->e_d_tov); - - schedule_delayed_work(&lport->retry_work, delay); - } else { - switch (lport->state) { - case LPORT_ST_DISABLED: - case LPORT_ST_READY: - case LPORT_ST_RESET: - case LPORT_ST_RNN_ID: - case LPORT_ST_RSNN_NN: - case LPORT_ST_RSPN_ID: - case LPORT_ST_RFT_ID: - case LPORT_ST_RFF_ID: - case LPORT_ST_SCR: - case LPORT_ST_DNS: - case LPORT_ST_FLOGI: - case LPORT_ST_LOGO: - fc_lport_enter_reset(lport); - break; - } - } - } + if (PTR_ERR(fp) == -FC_EX_CLOSED) + return; + + /* + * Memory allocation failure, or the exchange timed out + * or we received LS_RJT. + * Retry after delay + */ + if (lport->retry_count < lport->max_retry_count) { + lport->retry_count++; + if (!fp) + delay = msecs_to_jiffies(500); + else + delay = msecs_to_jiffies(lport->e_d_tov); + + schedule_delayed_work(&lport->retry_work, delay); + } else + fc_lport_enter_reset(lport); } /** @@ -1461,7 +1447,13 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, } did = fc_frame_did(fp); - if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { + + if (!did) { + FC_LPORT_DBG(lport, "Bad FLOGI response\n"); + goto out; + } + + if (fc_frame_payload_op(fp) == ELS_LS_ACC) { flp = fc_frame_payload_get(fp, sizeof(*flp)); if (flp) { mfs = ntohs(flp->fl_csp.sp_bb_data) & @@ -1500,9 +1492,8 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, fc_lport_enter_dns(lport); } } - } else { - FC_LPORT_DBG(lport, "Bad FLOGI response\n"); - } + } else + fc_lport_error(lport, fp); out: fc_frame_free(fp); -- cgit v1.2.3 From 240778e821f596a6954116107c5cc3456df84f81 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Tue, 20 Jul 2010 15:21:33 -0700 Subject: [SCSI] fcoe: remove check for zero fabric name This check prevents FCF selection in NPV mode due to zero fabric name in that case and in turn flogi fails. Though NPV mode should not have this zero and should be fixed there also but spec also does not require initiator to ensure that fabric name must be non-zero, therefore dropping this check to get flogi working in NPV mode. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 2c265fe9ab32..aa503d83092a 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -845,7 +845,7 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, } if (!fcf->fc_map || (fcf->fc_map & 0x10000)) return -EINVAL; - if (!fcf->switch_name || !fcf->fabric_name) + if (!fcf->switch_name) return -EINVAL; if (desc_mask) { LIBFCOE_FIP_DBG(fip, "adv missing descriptors mask %x\n", -- cgit v1.2.3 From caf19d38607108304cd8cc67ed21378017f69e8a Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 22 Jul 2010 09:36:51 +0900 Subject: [SCSI] sg: fix bio leak with a detached device After blk_rq_map_user is successful, if we find that a device is unavailable (was detached), we must call blk_end_request_all to free bio(s) before blk_rq_unmap_user and blk_put_request. Reported-by: "Dailey, Nate" Signed-off-by: FUJITA Tomonori Tested-by: "Dailey, Nate" Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ef752b248c4d..d4549092400c 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -729,6 +729,8 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, return k; /* probably out of space --> ENOMEM */ } if (sdp->detached) { + if (srp->bio) + blk_end_request_all(srp->rq, -EIO); sg_finish_rem_req(srp); return -ENODEV; } -- cgit v1.2.3 From fe4f0bdeea788a8ac049c097895cb2e4044f18b1 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 22 Jul 2010 16:57:43 +0530 Subject: [SCSI] iscsi_transport: Modidify recovery_tmo from sysfs Added support to modify session->recovery_tmo from sysfs Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Acked-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 43 ++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index b9aec304872c..d4b96623aa59 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1783,14 +1783,42 @@ show_priv_session_##field(struct device *dev, \ { \ struct iscsi_cls_session *session = \ iscsi_dev_to_session(dev->parent); \ + if (session->field == -1) \ + return sprintf(buf, "off\n"); \ return sprintf(buf, format"\n", session->field); \ } -#define iscsi_priv_session_attr(field, format) \ +#define iscsi_priv_session_attr_store(field) \ +static ssize_t \ +store_priv_session_##field(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + int val; \ + char *cp; \ + struct iscsi_cls_session *session = \ + iscsi_dev_to_session(dev->parent); \ + if ((session->state == ISCSI_SESSION_FREE) || \ + (session->state == ISCSI_SESSION_FAILED)) \ + return -EBUSY; \ + if (strncmp(buf, "off", 3) == 0) \ + session->field = -1; \ + else { \ + val = simple_strtoul(buf, &cp, 0); \ + if (*cp != '\0' && *cp != '\n') \ + return -EINVAL; \ + session->field = val; \ + } \ + return count; \ +} + +#define iscsi_priv_session_rw_attr(field, format) \ iscsi_priv_session_attr_show(field, format) \ -static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \ - NULL) -iscsi_priv_session_attr(recovery_tmo, "%d"); + iscsi_priv_session_attr_store(field) \ +static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUGO, \ + show_priv_session_##field, \ + store_priv_session_##field) +iscsi_priv_session_rw_attr(recovery_tmo, "%d"); /* * iSCSI host attrs @@ -1821,6 +1849,11 @@ do { \ count++; \ } while (0) +#define SETUP_PRIV_SESSION_RW_ATTR(field) \ +do { \ + priv->session_attrs[count] = &dev_attr_priv_sess_##field; \ + count++; \ +} while (0) #define SETUP_SESSION_RD_ATTR(field, param_flag) \ do { \ @@ -2008,7 +2041,7 @@ iscsi_register_transport(struct iscsi_transport *tt) SETUP_SESSION_RD_ATTR(ifacename, ISCSI_IFACE_NAME); SETUP_SESSION_RD_ATTR(initiatorname, ISCSI_INITIATOR_NAME); SETUP_SESSION_RD_ATTR(targetalias, ISCSI_TARGET_ALIAS); - SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); + SETUP_PRIV_SESSION_RW_ATTR(recovery_tmo); SETUP_PRIV_SESSION_RD_ATTR(state); BUG_ON(count > ISCSI_SESSION_ATTRS); -- cgit v1.2.3 From c01be6dcb2b5cce4feaf48035be6395e5cd7d47c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 22 Jul 2010 16:59:49 +0530 Subject: [SCSI] iscsi_transport: wait on session in error handler path wait for session to come online in eh_device_reset_handler and eh_target_reset_handler Signed-off-by: Mike Christie Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 11 ++++++++++- drivers/scsi/scsi_transport_iscsi.c | 32 ++++++++++++++++++++++++++++++++ include/scsi/scsi_transport_iscsi.h | 2 ++ 3 files changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 821384147a41..5529b2a39741 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2020,6 +2020,11 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) if (!ddb_entry) return ret; + ret = iscsi_block_scsi_eh(cmd); + if (ret) + return ret; + ret = FAILED; + ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); @@ -2072,11 +2077,15 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) { struct scsi_qla_host *ha = to_qla_host(cmd->device->host); struct ddb_entry *ddb_entry = cmd->device->hostdata; - int stat; + int stat, ret; if (!ddb_entry) return FAILED; + ret = iscsi_block_scsi_eh(cmd); + if (ret) + return ret; + starget_printk(KERN_INFO, scsi_target(cmd->device), "WARM TARGET RESET ISSUED.\n"); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index d4b96623aa59..e84026def1f4 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -30,6 +30,7 @@ #include #include #include +#include #define ISCSI_SESSION_ATTRS 23 #define ISCSI_CONN_ATTRS 13 @@ -534,6 +535,37 @@ static void iscsi_scan_session(struct work_struct *work) atomic_dec(&ihost->nr_scans); } +/** + * iscsi_block_scsi_eh - block scsi eh until session state has transistioned + * cmd: scsi cmd passed to scsi eh handler + * + * If the session is down this function will wait for the recovery + * timer to fire or for the session to be logged back in. If the + * recovery timer fires then FAST_IO_FAIL is returned. The caller + * should pass this error value to the scsi eh. + */ +int iscsi_block_scsi_eh(struct scsi_cmnd *cmd) +{ + struct iscsi_cls_session *session = + starget_to_session(scsi_target(cmd->device)); + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&session->lock, flags); + while (session->state != ISCSI_SESSION_LOGGED_IN) { + if (session->state == ISCSI_SESSION_FREE) { + ret = FAST_IO_FAIL; + break; + } + spin_unlock_irqrestore(&session->lock, flags); + msleep(1000); + spin_lock_irqsave(&session->lock, flags); + } + spin_unlock_irqrestore(&session->lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(iscsi_block_scsi_eh); + static void session_recovery_timedout(struct work_struct *work) { struct iscsi_cls_session *session = diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 349c7f30720d..7fff94b3b2a8 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -32,6 +32,7 @@ struct scsi_transport_template; struct iscsi_transport; struct iscsi_endpoint; struct Scsi_Host; +struct scsi_cmnd; struct iscsi_cls_conn; struct iscsi_conn; struct iscsi_task; @@ -255,5 +256,6 @@ extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time); extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size); extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep); extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle); +extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd); #endif -- cgit v1.2.3 From 17cf2c5d76b468ca03e59c7cf60decfcef6c08c4 Mon Sep 17 00:00:00 2001 From: Madhuranath Iyengar Date: Fri, 23 Jul 2010 15:28:22 +0500 Subject: [SCSI] qla2xxx: Don't issue set or get port param MBC if invalid port loop id Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 3a0248388505..20eaa1c42ae2 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1222,6 +1222,13 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) return -EINVAL; } + if (fcport->loop_id == FC_NO_LOOP_ID) { + DEBUG2(printk(KERN_ERR "%s(%ld): Invalid port loop id, " + "loop_id = 0x%x\n", + __func__, vha->host_no, fcport->loop_id)); + return -EINVAL; + } + if (port_param->mode) rval = qla2x00_set_idma_speed(vha, fcport->loop_id, port_param->speed, mb); -- cgit v1.2.3 From d94d10e7277069801b4e31b40770314a8421f996 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 23 Jul 2010 15:28:23 +0500 Subject: [SCSI] qla2xxx: Removed dependency for SRB structure for Marker processing Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 11 ---- drivers/scsi/qla2xxx/qla_gbl.h | 4 +- drivers/scsi/qla2xxx/qla_init.c | 73 +--------------------- drivers/scsi/qla2xxx/qla_iocb.c | 134 +++++----------------------------------- drivers/scsi/qla2xxx/qla_isr.c | 37 ----------- 5 files changed, 19 insertions(+), 240 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 2bb187e23db0..7f9f86b8140b 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -250,16 +250,6 @@ struct srb_iocb { uint32_t lun; uint32_t data; } tmf; - struct { - /* - * values for modif field below are as - * defined in mrk_entry_24xx struct - * for the modifier field in qla_fw.h. - */ - uint8_t modif; - uint16_t lun; - uint32_t data; - } marker; } u; struct timer_list timer; @@ -277,7 +267,6 @@ struct srb_iocb { #define SRB_CT_CMD 5 #define SRB_ADISC_CMD 6 #define SRB_TM_CMD 7 -#define SRB_MARKER_CMD 8 struct srb_ctx { uint16_t type; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 7ae2ee42564e..fd299911d7d6 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -59,7 +59,6 @@ extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); -extern int qla2x00_async_marker(fc_port_t *, uint16_t, uint8_t); extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, @@ -68,8 +67,7 @@ extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *, struct srb_iocb *); -extern void qla2x00_async_marker_done(struct scsi_qla_host *, fc_port_t *, - struct srb_iocb *); +extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *); extern fc_port_t * qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t ); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d0b993c8a189..5bc317070371 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -367,58 +367,6 @@ done: return rval; } -static void -qla2x00_async_marker_ctx_done(srb_t *sp) -{ - struct srb_ctx *ctx = sp->ctx; - struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd; - - qla2x00_async_marker_done(sp->fcport->vha, sp->fcport, iocb); - iocb->free(sp); -} - -int -qla2x00_async_marker(fc_port_t *fcport, uint16_t lun, uint8_t modif) -{ - struct scsi_qla_host *vha = fcport->vha; - srb_t *sp; - struct srb_ctx *ctx; - struct srb_iocb *mrk; - int rval; - - rval = QLA_FUNCTION_FAILED; - sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 0); - if (!sp) - goto done; - - ctx = sp->ctx; - ctx->type = SRB_MARKER_CMD; - ctx->name = "marker"; - mrk = ctx->u.iocb_cmd; - mrk->u.marker.lun = lun; - mrk->u.marker.modif = modif; - mrk->timeout = qla2x00_async_iocb_timeout; - mrk->done = qla2x00_async_marker_ctx_done; - - rval = qla2x00_start_sp(sp); - if (rval != QLA_SUCCESS) - goto done_free_sp; - - DEBUG2(printk(KERN_DEBUG - "scsi(%ld:%x): Async-marker - loop-id=%x " - "portid=%02x%02x%02x.\n", - fcport->vha->host_no, sp->handle, fcport->loop_id, - fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa)); - - return rval; - -done_free_sp: - mrk->free(sp); -done: - return rval; -} - void qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, uint16_t *data) @@ -500,7 +448,8 @@ qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport, lun = (uint16_t)iocb->u.tmf.lun; /* Issue Marker IOCB */ - rval = qla2x00_async_marker(fcport, lun, + rval = qla2x00_marker(vha, vha->hw->req_q_map[0], + vha->hw->rsp_q_map[0], fcport->loop_id, lun, flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) { @@ -512,24 +461,6 @@ qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport, return; } -void -qla2x00_async_marker_done(struct scsi_qla_host *vha, fc_port_t *fcport, - struct srb_iocb *iocb) -{ - /* - * Currently we dont have any specific post response processing - * for this IOCB. We'll just return success or failed - * depending on whether the IOCB command succeeded or failed. - */ - if (iocb->u.tmf.data) { - DEBUG2_3_11(printk(KERN_WARNING - "%s(%ld): Marker IOCB failed (%x).\n", - __func__, vha->host_no, iocb->u.tmf.data)); - } - - return; -} - /****************************************************************************/ /* QLogic ISP2x00 Hardware Support Functions. */ /****************************************************************************/ diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 5d0e99c2b522..370646f7b3ff 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -11,8 +11,6 @@ #include -static request_t *qla2x00_req_pkt(struct scsi_qla_host *, struct req_que *, - struct rsp_que *rsp); static void qla2x00_isp_cmd(struct scsi_qla_host *, struct req_que *); static void qla25xx_set_que(srb_t *, struct rsp_que **); @@ -474,7 +472,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); mrk24 = NULL; - mrk = (mrk_entry_t *)qla2x00_req_pkt(vha, req, rsp); + mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, 0); if (mrk == NULL) { DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n", __func__, base_vha->host_no)); @@ -520,84 +518,6 @@ qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, return (ret); } -/** - * qla2x00_req_pkt() - Retrieve a request packet from the request ring. - * @ha: HA context - * - * Note: The caller must hold the hardware lock before calling this routine. - * - * Returns NULL if function failed, else, a pointer to the request packet. - */ -static request_t * -qla2x00_req_pkt(struct scsi_qla_host *vha, struct req_que *req, - struct rsp_que *rsp) -{ - struct qla_hw_data *ha = vha->hw; - device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); - request_t *pkt = NULL; - uint16_t cnt; - uint32_t *dword_ptr; - uint32_t timer; - uint16_t req_cnt = 1; - - /* Wait 1 second for slot. */ - for (timer = HZ; timer; timer--) { - if ((req_cnt + 2) >= req->cnt) { - /* Calculate number of free request entries. */ - if (ha->mqenable) - cnt = (uint16_t) - RD_REG_DWORD(®->isp25mq.req_q_out); - else { - if (IS_QLA82XX(ha)) - cnt = (uint16_t)RD_REG_DWORD( - ®->isp82.req_q_out); - else if (IS_FWI2_CAPABLE(ha)) - cnt = (uint16_t)RD_REG_DWORD( - ®->isp24.req_q_out); - else - cnt = qla2x00_debounce_register( - ISP_REQ_Q_OUT(ha, ®->isp)); - } - if (req->ring_index < cnt) - req->cnt = cnt - req->ring_index; - else - req->cnt = req->length - - (req->ring_index - cnt); - } - /* If room for request in request ring. */ - if ((req_cnt + 2) < req->cnt) { - req->cnt--; - pkt = req->ring_ptr; - - /* Zero out packet. */ - dword_ptr = (uint32_t *)pkt; - for (cnt = 0; cnt < REQUEST_ENTRY_SIZE / 4; cnt++) - *dword_ptr++ = 0; - - /* Set entry count. */ - pkt->entry_count = 1; - - break; - } - - /* Release ring specific lock */ - spin_unlock_irq(&ha->hardware_lock); - - udelay(2); /* 2 us */ - - /* Check for pending interrupts. */ - /* During init we issue marker directly */ - if (!vha->marker_needed && !vha->flags.init_done) - qla2x00_poll(rsp); - spin_lock_irq(&ha->hardware_lock); - } - if (!pkt) { - DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__)); - } - - return (pkt); -} - /** * qla2x00_isp_cmd() - Modify the request ring pointer. * @ha: HA context @@ -1559,11 +1479,9 @@ static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) } /* Generic Control-SRB manipulation functions. */ - -static void * -qla2x00_alloc_iocbs(srb_t *sp) +void * +qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp) { - scsi_qla_host_t *vha = sp->fcport->vha; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); @@ -1573,6 +1491,10 @@ qla2x00_alloc_iocbs(srb_t *sp) pkt = NULL; req_cnt = 1; + handle = 0; + + if (!sp) + goto skip_cmd_array; /* Check for room in outstanding command list. */ handle = req->current_outstanding_cmd; @@ -1586,10 +1508,18 @@ qla2x00_alloc_iocbs(srb_t *sp) if (index == MAX_OUTSTANDING_COMMANDS) goto queuing_error; + /* Prep command array. */ + req->current_outstanding_cmd = handle; + req->outstanding_cmds[handle] = sp; + sp->handle = handle; + +skip_cmd_array: /* Check for room on request queue. */ if (req->cnt < req_cnt) { if (ha->mqenable) cnt = RD_REG_DWORD(®->isp25mq.req_q_out); + else if (IS_QLA82XX(ha)) + cnt = RD_REG_DWORD(®->isp82.req_q_out); else if (IS_FWI2_CAPABLE(ha)) cnt = RD_REG_DWORD(®->isp24.req_q_out); else @@ -1606,15 +1536,11 @@ qla2x00_alloc_iocbs(srb_t *sp) goto queuing_error; /* Prep packet */ - req->current_outstanding_cmd = handle; - req->outstanding_cmds[handle] = sp; req->cnt -= req_cnt; - pkt = req->ring_ptr; memset(pkt, 0, REQUEST_ENTRY_SIZE); pkt->entry_count = req_cnt; pkt->handle = handle; - sp->handle = handle; queuing_error: return pkt; @@ -1794,31 +1720,6 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) } } -static void -qla24xx_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk) -{ - uint16_t lun; - uint8_t modif; - struct fc_port *fcport = sp->fcport; - scsi_qla_host_t *vha = fcport->vha; - struct srb_ctx *ctx = sp->ctx; - struct srb_iocb *iocb = ctx->u.iocb_cmd; - struct req_que *req = vha->req; - - lun = iocb->u.marker.lun; - modif = iocb->u.marker.modif; - mrk->entry_type = MARKER_TYPE; - mrk->modifier = modif; - if (modif != MK_SYNC_ALL) { - mrk->nport_handle = cpu_to_le16(fcport->loop_id); - mrk->lun[1] = LSB(lun); - mrk->lun[2] = MSB(lun); - host_to_fcp_swap(mrk->lun, sizeof(mrk->lun)); - mrk->vp_index = vha->vp_idx; - mrk->handle = MAKE_HANDLE(req->id, mrk->handle); - } -} - static void qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) { @@ -1945,7 +1846,7 @@ qla2x00_start_sp(srb_t *sp) rval = QLA_FUNCTION_FAILED; spin_lock_irqsave(&ha->hardware_lock, flags); - pkt = qla2x00_alloc_iocbs(sp); + pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp); if (!pkt) goto done; @@ -1976,9 +1877,6 @@ qla2x00_start_sp(srb_t *sp) case SRB_TM_CMD: qla24xx_tm_iocb(sp, pkt); break; - case SRB_MARKER_CMD: - qla24xx_marker_iocb(sp, pkt); - break; default: break; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 8a608725eb76..ba971ac1c4e8 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1238,39 +1238,6 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, iocb->done(sp); } -static void -qla24xx_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, - struct mrk_entry_24xx *mrk) -{ - const char func[] = "MRK-IOCB"; - const char *type; - fc_port_t *fcport; - srb_t *sp; - struct srb_iocb *iocb; - struct srb_ctx *ctx; - struct sts_entry_24xx *sts = (struct sts_entry_24xx *)mrk; - - sp = qla2x00_get_sp_from_handle(vha, func, req, mrk); - if (!sp) - return; - - ctx = sp->ctx; - iocb = ctx->u.iocb_cmd; - type = ctx->name; - fcport = sp->fcport; - - if (sts->entry_status) { - iocb->u.marker.data = 1; - DEBUG2(printk(KERN_WARNING - "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n", - fcport->vha->host_no, sp->handle, type, - sts->entry_status)); - DEBUG2(qla2x00_dump_buffer((uint8_t *)mrk, sizeof(*sts))); - } - - iocb->done(sp); -} - /** * qla2x00_process_response_queue() - Process response queue entries. * @ha: SCSI driver HA context @@ -1942,10 +1909,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, qla24xx_tm_iocb_entry(vha, rsp->req, (struct tsk_mgmt_entry *)pkt); break; - case MARKER_TYPE: - qla24xx_marker_iocb_entry(vha, rsp->req, - (struct mrk_entry_24xx *)pkt); - break; case CT_IOCB_TYPE: qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags); -- cgit v1.2.3 From 2f0f3f4f06f7cfadebf58b70bd9e7f71d8fd96e4 Mon Sep 17 00:00:00 2001 From: Madhuranath Iyengar Date: Fri, 23 Jul 2010 15:28:24 +0500 Subject: [SCSI] qla2xxx: Appropriately log FCP priority data messages Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 36 +++++++++++++++++++++++++++++++++--- drivers/scsi/qla2xxx/qla_init.c | 7 ++----- drivers/scsi/qla2xxx/qla_sup.c | 25 +++++++++++++------------ 3 files changed, 48 insertions(+), 20 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 20eaa1c42ae2..d551ae19d4e1 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -41,13 +41,28 @@ qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag) int i, ret, num_valid; uint8_t *bcode; struct qla_fcp_prio_entry *pri_entry; + uint32_t *bcode_val_ptr, bcode_val; ret = 1; num_valid = 0; bcode = (uint8_t *)pri_cfg; + bcode_val_ptr = (uint32_t *)pri_cfg; + bcode_val = (uint32_t)(*bcode_val_ptr); - if (bcode[0x0] != 'H' || bcode[0x1] != 'Q' || bcode[0x2] != 'O' || - bcode[0x3] != 'S') { + if (bcode_val == 0xFFFFFFFF) { + /* No FCP Priority config data in flash */ + DEBUG2(printk(KERN_INFO + "%s: No FCP priority config data.\n", + __func__)); + return 0; + } + + if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' || + bcode[3] != 'S') { + /* Invalid FCP priority data header*/ + DEBUG2(printk(KERN_ERR + "%s: Invalid FCP Priority data header. bcode=0x%x\n", + __func__, bcode_val)); return 0; } if (flag != 1) @@ -60,8 +75,18 @@ qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag) pri_entry++; } - if (num_valid == 0) + if (num_valid == 0) { + /* No valid FCP priority data entries */ + DEBUG2(printk(KERN_ERR + "%s: No valid FCP Priority data entries.\n", + __func__)); ret = 0; + } else { + /* FCP priority data is valid */ + DEBUG2(printk(KERN_INFO + "%s: Valid FCP priority data. num entries = %d\n", + __func__, num_valid)); + } return ret; } @@ -78,6 +103,11 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) bsg_job->reply->reply_payload_rcv_len = 0; + if (!IS_QLA24XX_TYPE(ha) || !IS_QLA25XX(ha)) { + ret = -EINVAL; + goto exit_fcp_prio_cfg; + } + if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 5bc317070371..cea491bf0fc0 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -566,11 +566,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) } } - if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) { - if (qla24xx_read_fcp_prio_cfg(vha)) - qla_printk(KERN_ERR, ha, - "Unable to read FCP priority data.\n"); - } + if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) + qla24xx_read_fcp_prio_cfg(vha); return (rval); } diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index de92504d7585..3c5115f60739 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -664,6 +664,11 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; + def = 0; + if (IS_QLA25XX(ha)) + def = 1; + else if (IS_QLA81XX(ha)) + def = 2; ha->flt_region_flt = flt_addr; wptr = (uint16_t *)req->ring; flt = (struct qla_flt_header *)req->ring; @@ -691,6 +696,10 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) goto no_flash_data; } + /* Assign FCP prio region since older FLT's may not have it */ + ha->flt_region_fcp_prio = ha->flags.port0 ? + fcp_prio_cfg0[def] : fcp_prio_cfg1[def]; + loc = locations[1]; cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); for ( ; cnt; cnt--, region++) { @@ -773,13 +782,6 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) no_flash_data: /* Use hardcoded defaults. */ loc = locations[0]; - def = 0; - if (IS_QLA24XX_TYPE(ha)) - def = 0; - else if (IS_QLA25XX(ha)) - def = 1; - else if (IS_QLA81XX(ha)) - def = 2; ha->flt_region_fw = def_fw[def]; ha->flt_region_boot = def_boot[def]; ha->flt_region_vpd_nvram = def_vpd_nvram[def]; @@ -790,14 +792,13 @@ no_flash_data: ha->flt_region_fdt = def_fdt[def]; ha->flt_region_npiv_conf = ha->flags.port0 ? def_npiv_conf0[def] : def_npiv_conf1[def]; - ha->flt_region_fcp_prio = ha->flags.port0 ? - fcp_prio_cfg0[def] : fcp_prio_cfg1[def]; done: DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x " "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x " - "npiv=0x%x.\n", loc, ha->flt_region_boot, ha->flt_region_fw, - ha->flt_region_vpd_nvram, ha->flt_region_vpd, ha->flt_region_nvram, - ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_npiv_conf)); + "npiv=0x%x. fcp_prio_cfg=0x%x\n", loc, ha->flt_region_boot, + ha->flt_region_fw, ha->flt_region_vpd_nvram, ha->flt_region_vpd, + ha->flt_region_nvram, ha->flt_region_fdt, ha->flt_region_flt, + ha->flt_region_npiv_conf, ha->flt_region_fcp_prio)); } static void -- cgit v1.2.3 From e8c72ba51a159f5d1cb195d3fb47262c782939d9 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 23 Jul 2010 15:28:25 +0500 Subject: [SCSI] qla2xxx: Use GFF_ID to check FCP-SCSI FC4 type before logging into Nx_Ports The default method that qla2xxx uses is the GID_PT nameserver command to get a list of Nx_Ports. This patch adds a GFF_ID call for each port returned by GID_PT to get the FC4 type. If the FC4 type is not FCP SCSI then the qla2xxx driver will not record that port in it's port database. For switches that do not support the GFF_ID command, the behavior will be for qla2xxx to store that port anyways. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 20 ++++++++++++ drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_gs.c | 72 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_init.c | 11 ++++++- 4 files changed, 103 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 7f9f86b8140b..02c7480c99c3 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1652,8 +1652,14 @@ typedef struct { uint8_t port_name[WWN_SIZE]; uint8_t fabric_port_name[WWN_SIZE]; uint16_t fp_speed; + uint8_t fc4_type; } sw_info_t; +/* FCP-4 types */ +#define FC4_TYPE_FCP_SCSI 0x08 +#define FC4_TYPE_OTHER 0x0 +#define FC4_TYPE_UNKNOWN 0xff + /* * Fibre channel port type. */ @@ -1697,6 +1703,7 @@ typedef struct fc_port { u32 supported_classes; uint16_t vp_idx; + uint8_t fc4_type; } fc_port_t; /* @@ -1779,6 +1786,9 @@ typedef struct fc_port { #define GPSC_REQ_SIZE (16 + 8) #define GPSC_RSP_SIZE (16 + 2 + 2) +#define GFF_ID_CMD 0x011F +#define GFF_ID_REQ_SIZE (16 + 4) +#define GFF_ID_RSP_SIZE (16 + 128) /* * HBA attribute types. @@ -1980,6 +1990,11 @@ struct ct_sns_req { struct { uint8_t port_name[8]; } gpsc; + + struct { + uint8_t reserved; + uint8_t port_name[3]; + } gff_id; } req; }; @@ -2052,6 +2067,11 @@ struct ct_sns_rsp { uint16_t speeds; uint16_t speed; } gpsc; + +#define GFF_FCP_SCSI_OFFSET 7 + struct { + uint8_t fc4_features[128]; + } gff_id; } rsp; }; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index fd299911d7d6..55f4599ade63 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -441,6 +441,7 @@ extern int qla2x00_ga_nxt(scsi_qla_host_t *, fc_port_t *); extern int qla2x00_gid_pt(scsi_qla_host_t *, sw_info_t *); extern int qla2x00_gpn_id(scsi_qla_host_t *, sw_info_t *); extern int qla2x00_gnn_id(scsi_qla_host_t *, sw_info_t *); +extern void qla2x00_gff_id(scsi_qla_host_t *, sw_info_t *); extern int qla2x00_rft_id(scsi_qla_host_t *); extern int qla2x00_rff_id(scsi_qla_host_t *); extern int qla2x00_rnn_id(scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 872c55f049a5..2fabae8daec4 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1913,3 +1913,75 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list) return (rval); } + +/** + * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query. + * + * @ha: HA context + * @list: switch info entries to populate + * + */ +void +qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list) +{ + int rval; + uint16_t i; + + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + struct qla_hw_data *ha = vha->hw; + uint8_t fcp_scsi_features = 0; + + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + /* Set default FC4 Type as UNKNOWN so the default is to + * Process this port */ + list[i].fc4_type = FC4_TYPE_UNKNOWN; + + /* Do not attempt GFF_ID if we are not FWI_2 capable */ + if (!IS_FWI2_CAPABLE(ha)) + continue; + + /* Prepare common MS IOCB */ + ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE, + GFF_ID_RSP_SIZE); + + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFF_ID_CMD, + GFF_ID_RSP_SIZE); + ct_rsp = &ha->ct_sns->p.rsp; + + /* Prepare CT arguments -- port_id */ + ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain; + ct_req->req.port_id.port_id[1] = list[i].d_id.b.area; + ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa; + + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, + sizeof(ms_iocb_entry_t)); + + if (rval != QLA_SUCCESS) { + DEBUG2_3(printk(KERN_INFO + "scsi(%ld): GFF_ID issue IOCB failed " + "(%d).\n", vha->host_no, rval)); + } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, + "GPN_ID") != QLA_SUCCESS) { + DEBUG2_3(printk(KERN_INFO + "scsi(%ld): GFF_ID IOCB status had a " + "failure status code\n", vha->host_no)); + } else { + fcp_scsi_features = + ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET]; + fcp_scsi_features &= 0x0f; + + if (fcp_scsi_features) + list[i].fc4_type = FC4_TYPE_FCP_SCSI; + else + list[i].fc4_type = FC4_TYPE_OTHER; + } + + /* Last device exit. */ + if (list[i].d_id.b.rsvd_1 != 0) + break; + } +} diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index cea491bf0fc0..685c350007b0 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3078,7 +3078,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) return (rval); } - /* * qla2x00_find_all_fabric_devs * @@ -3131,6 +3130,10 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, qla2x00_gfpn_id(vha, swl) == QLA_SUCCESS) { qla2x00_gpsc(vha, swl); } + + /* If other queries succeeded probe for FC-4 type */ + if (swl) + qla2x00_gff_id(vha, swl); } swl_idx = 0; @@ -3172,6 +3175,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, memcpy(new_fcport->fabric_port_name, swl[swl_idx].fabric_port_name, WWN_SIZE); new_fcport->fp_speed = swl[swl_idx].fp_speed; + new_fcport->fc4_type = swl[swl_idx].fc4_type; if (swl[swl_idx].d_id.b.rsvd_1 != 0) { last_dev = 1; @@ -3233,6 +3237,11 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0) continue; + /* Bypass ports whose FCP-4 type is not FCP_SCSI */ + if (new_fcport->fc4_type != FC4_TYPE_FCP_SCSI && + new_fcport->fc4_type != FC4_TYPE_UNKNOWN) + continue; + /* Locate matching device in database. */ found = 0; list_for_each_entry(fcport, &vha->vp_fcports, list) { -- cgit v1.2.3 From 0f2d962f4d120e93b4d74d13c2e8038e9e4358b9 Mon Sep 17 00:00:00 2001 From: Madhuranath Iyengar Date: Fri, 23 Jul 2010 15:28:26 +0500 Subject: [SCSI] qla2xxx: Check for golden firmware and show version if available Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 18 ++++++++++++++++++ drivers/scsi/qla2xxx/qla_def.h | 2 ++ drivers/scsi/qla2xxx/qla_sup.c | 22 ++++++++++++++++++++++ 3 files changed, 42 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index fd6f7b100547..7ebf365043cf 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1186,6 +1186,21 @@ qla2x00_optrom_fw_version_show(struct device *dev, ha->fw_revision[3]); } +static ssize_t +qla2x00_optrom_gold_fw_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA81XX(ha)) + return snprintf(buf, PAGE_SIZE, "\n"); + + return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%d)\n", + ha->gold_fw_version[0], ha->gold_fw_version[1], + ha->gold_fw_version[2], ha->gold_fw_version[3]); +} + static ssize_t qla2x00_total_isp_aborts_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1336,6 +1351,8 @@ static DEVICE_ATTR(optrom_fcode_version, S_IRUGO, qla2x00_optrom_fcode_version_show, NULL); static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, NULL); +static DEVICE_ATTR(optrom_gold_fw_version, S_IRUGO, + qla2x00_optrom_gold_fw_version_show, NULL); static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show, NULL); static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, @@ -1376,6 +1393,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_vn_port_mac_address, &dev_attr_fabric_param, &dev_attr_fw_state, + &dev_attr_optrom_gold_fw_version, NULL, }; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 02c7480c99c3..7e11ccf0fe81 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2714,6 +2714,8 @@ struct qla_hw_data { uint8_t fcode_revision[16]; uint32_t fw_revision[4]; + uint32_t gold_fw_version[4]; + /* Offsets for flash/nvram access (set to ~0 if not used). */ uint32_t flash_conf_off; uint32_t flash_data_off; diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 3c5115f60739..df288dc829e0 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -2759,6 +2759,28 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) ha->fw_revision[3] = dcode[3]; } + /* Check for golden firmware and get version if available */ + if (!IS_QLA81XX(ha)) { + /* Golden firmware is not present in non 81XX adapters */ + return ret; + } + + memset(ha->gold_fw_version, 0, sizeof(ha->gold_fw_version)); + dcode = mbuf; + ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, + ha->flt_region_gold_fw << 2, 32); + + if (dcode[4] == 0xFFFFFFFF && dcode[5] == 0xFFFFFFFF && + dcode[6] == 0xFFFFFFFF && dcode[7] == 0xFFFFFFFF) { + DEBUG2(qla_printk(KERN_INFO, ha, + "%s(%ld): Unrecognized golden fw at 0x%x.\n", + __func__, vha->host_no, ha->flt_region_gold_fw * 4)); + return ret; + } + + for (i = 4; i < 8; i++) + ha->gold_fw_version[i-4] = be32_to_cpu(dcode[i]); + return ret; } -- cgit v1.2.3 From 5544213be7b4fb693730106a6d70a8cc1aa7cdf6 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 23 Jul 2010 15:28:27 +0500 Subject: [SCSI] qla2xxx: Correct extended sense-data handling. Earlier implementation did not take into account the varying sizes of data buffers returned from structures sts_entry_t and sts_entry_24xx. Sense-data after the 20th byte could be incorrect. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ba971ac1c4e8..88b5774085ad 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1320,8 +1320,9 @@ qla2x00_process_response_queue(struct rsp_que *rsp) } static inline void -qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len, - struct rsp_que *rsp) + +qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, + uint32_t sense_len, struct rsp_que *rsp) { struct scsi_cmnd *cp = sp->cmd; @@ -1330,8 +1331,8 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len, sp->request_sense_length = sense_len; sp->request_sense_ptr = cp->sense_buffer; - if (sp->request_sense_length > 32) - sense_len = 32; + if (sp->request_sense_length > par_sense_len) + sense_len = par_sense_len; memcpy(cp->sense_buffer, sense_data, sense_len); @@ -1438,7 +1439,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) uint16_t ox_id; uint8_t lscsi_status; int32_t resid; - uint32_t sense_len, rsp_info_len, resid_len, fw_resid_len; + uint32_t sense_len, par_sense_len, rsp_info_len, resid_len, + fw_resid_len; uint8_t *rsp_info, *sense_data; struct qla_hw_data *ha = vha->hw; uint32_t handle; @@ -1496,7 +1498,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) fcport = sp->fcport; ox_id = 0; - sense_len = rsp_info_len = resid_len = fw_resid_len = 0; + sense_len = par_sense_len = rsp_info_len = resid_len = + fw_resid_len = 0; if (IS_FWI2_CAPABLE(ha)) { if (scsi_status & SS_SENSE_LEN_VALID) sense_len = le32_to_cpu(sts24->sense_len); @@ -1510,6 +1513,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) sense_data = sts24->data; host_to_fcp_swap(sts24->data, sizeof(sts24->data)); ox_id = le16_to_cpu(sts24->ox_id); + par_sense_len = sizeof(sts24->data); } else { if (scsi_status & SS_SENSE_LEN_VALID) sense_len = le16_to_cpu(sts->req_sense_length); @@ -1518,13 +1522,16 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) resid_len = le32_to_cpu(sts->residual_length); rsp_info = sts->rsp_info; sense_data = sts->req_sense_data; + par_sense_len = sizeof(sts->req_sense_data); } /* Check for any FCP transport errors. */ if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { /* Sense data lies beyond any FCP RESPONSE data. */ - if (IS_FWI2_CAPABLE(ha)) + if (IS_FWI2_CAPABLE(ha)) { sense_data += rsp_info_len; + par_sense_len -= rsp_info_len; + } if (rsp_info_len > 3 && rsp_info[3]) { DEBUG2(qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): FCP I/O protocol failure " @@ -1584,7 +1591,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) if (!(scsi_status & SS_SENSE_LEN_VALID)) break; - qla2x00_handle_sense(sp, sense_data, sense_len, rsp); + qla2x00_handle_sense(sp, sense_data, par_sense_len, sense_len, + rsp); break; case CS_DATA_UNDERRUN: @@ -1648,7 +1656,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) if (!(scsi_status & SS_SENSE_LEN_VALID)) break; - qla2x00_handle_sense(sp, sense_data, sense_len, rsp); + qla2x00_handle_sense(sp, sense_data, par_sense_len, + sense_len, rsp); } break; -- cgit v1.2.3 From 03c3f563c55121292022a6e8e213ea54c20a5980 Mon Sep 17 00:00:00 2001 From: Duane Grigsby Date: Fri, 23 Jul 2010 15:28:28 +0500 Subject: [SCSI] qla2xxx: Propogate transport disrupted status for cable pull conditions for faster failover. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 88b5774085ad..ffc855f7697d 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1692,6 +1692,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) break; case CS_RESET: + cp->result = DID_TRANSPORT_DISRUPTED << 16; + break; + case CS_ABORTED: cp->result = DID_RESET << 16; break; -- cgit v1.2.3 From 14e303d98bcfe4a6075407b531b1df2f237deb28 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 23 Jul 2010 15:28:29 +0500 Subject: [SCSI] qla2xxx: Stop firmware before doing init firmware. If BIOS is enabled then drivers init firmware fails since BIOS has done the init once. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 685c350007b0..f6b1052a3834 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1402,9 +1402,10 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) if (IS_QLA82XX(ha)) { rval = ha->isp_ops->load_risc(vha, &srisc_address); - if (rval == QLA_SUCCESS) + if (rval == QLA_SUCCESS) { + qla2x00_stop_firmware(vha); goto enable_82xx_npiv; - else + } else goto failed; } -- cgit v1.2.3 From 8867048b486a64125b62f93af13a379d6d575ee2 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 23 Jul 2010 15:28:30 +0500 Subject: [SCSI] qla2xxx: Add qla2x00_free_fcports() function This function was added to encapsulate freeing the memory for all the fcports associated with a particular vha. Also added a call to qla2x00_free_fcports() to qla2x00_free_device() to free the memory for all the fcports associated with a vha during device removal. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 7 +------ drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_os.c | 13 +++++++++++++ 3 files changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 7ebf365043cf..93a4c20e2113 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1827,7 +1827,6 @@ static int qla24xx_vport_delete(struct fc_vport *fc_vport) { scsi_qla_host_t *vha = fc_vport->dd_data; - fc_port_t *fcport, *tfcport; struct qla_hw_data *ha = vha->hw; uint16_t id = vha->vp_idx; @@ -1841,11 +1840,7 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) scsi_remove_host(vha->host); - list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) { - list_del(&fcport->list); - kfree(fcport); - fcport = NULL; - } + qla2x00_free_fcports(vha); qla24xx_deallocate_vp_id(vha); diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 55f4599ade63..84441e8e267e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -122,6 +122,7 @@ extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *, extern void qla2x00_free_host(struct scsi_qla_host *); extern void qla2x00_relogin(struct scsi_qla_host *); extern void qla2x00_do_work(struct scsi_qla_host *); +extern void qla2x00_free_fcports(struct scsi_qla_host *); /* * Global Functions in qla_mid.c source file. diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5be8db748964..fcdbf7a0be55 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2487,11 +2487,24 @@ qla2x00_free_device(scsi_qla_host_t *vha) qla2x00_free_irqs(vha); + qla2x00_free_fcports(vha); + qla2x00_mem_free(ha); qla2x00_free_queues(ha); } +void qla2x00_free_fcports(struct scsi_qla_host *vha) +{ + fc_port_t *fcport, *tfcport; + + list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) { + list_del(&fcport->list); + kfree(fcport); + fcport = NULL; + } +} + static inline void qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport, int defer) -- cgit v1.2.3 From 9a15eb4b514c526cf3181ce224967ab5d8dafe77 Mon Sep 17 00:00:00 2001 From: Madhuranath Iyengar Date: Fri, 23 Jul 2010 15:28:31 +0500 Subject: [SCSI] qla2xxx: Don't issue set or get port param MBC if remote port is not logged in Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index d551ae19d4e1..518fccfbfdb2 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1259,6 +1259,13 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) return -EINVAL; } + if (fcport->flags & FCF_LOGIN_NEEDED) { + DEBUG2(printk(KERN_ERR "%s(%ld): Remote port not logged in, " + "flags = 0x%x\n", + __func__, vha->host_no, fcport->flags)); + return -EINVAL; + } + if (port_param->mode) rval = qla2x00_set_idma_speed(vha, fcport->loop_id, port_param->speed, mb); -- cgit v1.2.3 From 9bc4f4fb44d22e5edc9369c87585a3b492073b8b Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Fri, 23 Jul 2010 15:28:32 +0500 Subject: [SCSI] qla2xxx: Add CT passthru support for ISP23xx adapters Signed-off-by: Harish Zunjarrao Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 9 ----- drivers/scsi/qla2xxx/qla_iocb.c | 80 ++++++++++++++++++++++++++++++++++++++- drivers/scsi/qla2xxx/qla_isr.c | 83 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+), 10 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 518fccfbfdb2..04ead0620d5f 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -396,15 +396,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) char *type = "FC_BSG_HST_CT"; struct srb_ctx *ct; - /* pass through is supported only for ISP 4Gb or higher */ - if (!IS_FWI2_CAPABLE(ha)) { - DEBUG2(qla_printk(KERN_INFO, ha, - "scsi(%ld):Firmware is not capable to support FC " - "CT pass thru\n", vha->host_no)); - rval = -EPERM; - goto done; - } - req_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 370646f7b3ff..e27d94713bdf 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1764,6 +1764,82 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) (bsg_job->reply_payload.sg_list)); } +static void +qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) +{ + uint16_t avail_dsds; + uint32_t *cur_dsd; + struct scatterlist *sg; + int index; + uint16_t tot_dsds; + scsi_qla_host_t *vha = sp->fcport->vha; + struct qla_hw_data *ha = vha->hw; + struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; + int loop_iterartion = 0; + int cont_iocb_prsnt = 0; + int entry_count = 1; + + memset(ct_iocb, 0, sizeof(ms_iocb_entry_t)); + ct_iocb->entry_type = CT_IOCB_TYPE; + ct_iocb->entry_status = 0; + ct_iocb->handle1 = sp->handle; + SET_TARGET_ID(ha, ct_iocb->loop_id, sp->fcport->loop_id); + ct_iocb->status = __constant_cpu_to_le16(0); + ct_iocb->control_flags = __constant_cpu_to_le16(0); + ct_iocb->timeout = 0; + ct_iocb->cmd_dsd_count = + __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); + ct_iocb->total_dsd_count = + __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt + 1); + ct_iocb->req_bytecount = + cpu_to_le32(bsg_job->request_payload.payload_len); + ct_iocb->rsp_bytecount = + cpu_to_le32(bsg_job->reply_payload.payload_len); + + ct_iocb->dseg_req_address[0] = cpu_to_le32(LSD(sg_dma_address + (bsg_job->request_payload.sg_list))); + ct_iocb->dseg_req_address[1] = cpu_to_le32(MSD(sg_dma_address + (bsg_job->request_payload.sg_list))); + ct_iocb->dseg_req_length = ct_iocb->req_bytecount; + + ct_iocb->dseg_rsp_address[0] = cpu_to_le32(LSD(sg_dma_address + (bsg_job->reply_payload.sg_list))); + ct_iocb->dseg_rsp_address[1] = cpu_to_le32(MSD(sg_dma_address + (bsg_job->reply_payload.sg_list))); + ct_iocb->dseg_rsp_length = ct_iocb->rsp_bytecount; + + avail_dsds = 1; + cur_dsd = (uint32_t *)ct_iocb->dseg_rsp_address; + index = 0; + tot_dsds = bsg_job->reply_payload.sg_cnt; + + for_each_sg(bsg_job->reply_payload.sg_list, sg, tot_dsds, index) { + dma_addr_t sle_dma; + cont_a64_entry_t *cont_pkt; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + /* + * Five DSDs are available in the Cont. + * Type 1 IOCB. + */ + cont_pkt = qla2x00_prep_cont_type1_iocb(vha); + cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; + avail_dsds = 5; + cont_iocb_prsnt = 1; + entry_count++; + } + + sle_dma = sg_dma_address(sg); + *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); + loop_iterartion++; + avail_dsds--; + } + ct_iocb->entry_count = entry_count; +} + static void qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) { @@ -1867,7 +1943,9 @@ qla2x00_start_sp(srb_t *sp) qla24xx_els_iocb(sp, pkt); break; case SRB_CT_CMD: - qla24xx_ct_iocb(sp, pkt); + IS_FWI2_CAPABLE(ha) ? + qla24xx_ct_iocb(sp, pkt) : + qla2x00_ct_iocb(sp, pkt); break; case SRB_ADISC_CMD: IS_FWI2_CAPABLE(ha) ? diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ffc855f7697d..518003328226 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -983,6 +983,86 @@ logio_done: lio->done(sp); } +static void +qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, + sts_entry_t *pkt, int iocb_type) +{ + const char func[] = "CT_IOCB"; + const char *type; + struct qla_hw_data *ha = vha->hw; + srb_t *sp; + struct srb_ctx *sp_bsg; + struct fc_bsg_job *bsg_job; + uint16_t comp_status; + + sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); + if (!sp) + return; + + sp_bsg = sp->ctx; + bsg_job = sp_bsg->u.bsg_job; + + type = NULL; + switch (sp_bsg->type) { + case SRB_CT_CMD: + type = "ct pass-through"; + break; + default: + qla_printk(KERN_WARNING, ha, + "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, + sp_bsg->type); + return; + } + + comp_status = le16_to_cpu(pkt->comp_status); + + /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT + * fc payload to the caller + */ + bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + + if (comp_status != CS_COMPLETE) { + if (comp_status == CS_DATA_UNDERRUN) { + bsg_job->reply->result = DID_OK << 16; + bsg_job->reply->reply_payload_rcv_len = + le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len); + + DEBUG2(qla_printk(KERN_WARNING, ha, + "scsi(%ld): CT pass-through-%s error " + "comp_status-status=0x%x total_byte = 0x%x.\n", + vha->host_no, type, comp_status, + bsg_job->reply->reply_payload_rcv_len)); + } else { + DEBUG2(qla_printk(KERN_WARNING, ha, + "scsi(%ld): CT pass-through-%s error " + "comp_status-status=0x%x.\n", + vha->host_no, type, comp_status)); + bsg_job->reply->result = DID_ERROR << 16; + bsg_job->reply->reply_payload_rcv_len = 0; + } + DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt))); + } else { + bsg_job->reply->result = DID_OK << 16;; + bsg_job->reply->reply_payload_rcv_len = + bsg_job->reply_payload.payload_len; + bsg_job->reply_len = 0; + } + + dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); + + dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); + + if (sp_bsg->type == SRB_ELS_CMD_HST || sp_bsg->type == SRB_CT_CMD) + kfree(sp->fcport); + + kfree(sp->ctx); + mempool_free(sp, ha->srb_mempool); + bsg_job->job_done(bsg_job); +} + static void qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, struct sts_entry_24xx *pkt, int iocb_type) @@ -1303,6 +1383,9 @@ qla2x00_process_response_queue(struct rsp_que *rsp) qla2x00_mbx_iocb_entry(vha, rsp->req, (struct mbx_entry *)pkt); break; + case CT_IOCB_TYPE: + qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); + break; default: /* Type Not Supported. */ DEBUG4(printk(KERN_WARNING -- cgit v1.2.3 From 08f71e090d3f0d8136c3f350e5082f9217fb7d5b Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Fri, 23 Jul 2010 15:28:33 +0500 Subject: [SCSI] qla2xxx: Do not allow ELS Passthru commands for ISP23xx adapters Signed-off-by: Harish Zunjarrao Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 04ead0620d5f..6b863f789c4d 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -229,7 +229,7 @@ static int qla2x00_process_els(struct fc_bsg_job *bsg_job) { struct fc_rport *rport; - fc_port_t *fcport; + fc_port_t *fcport = NULL; struct Scsi_Host *host; scsi_qla_host_t *vha; struct qla_hw_data *ha; @@ -240,6 +240,29 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) uint16_t nextlid = 0; struct srb_ctx *els; + if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { + rport = bsg_job->rport; + fcport = *(fc_port_t **) rport->dd_data; + host = rport_to_shost(rport); + vha = shost_priv(host); + ha = vha->hw; + type = "FC_BSG_RPT_ELS"; + } else { + host = bsg_job->shost; + vha = shost_priv(host); + ha = vha->hw; + type = "FC_BSG_HST_ELS_NOLOGIN"; + } + + /* pass through is supported only for ISP 4Gb or higher */ + if (!IS_FWI2_CAPABLE(ha)) { + DEBUG2(qla_printk(KERN_INFO, ha, + "scsi(%ld):ELS passthru not supported for ISP23xx based " + "adapters\n", vha->host_no)); + rval = -EPERM; + goto done; + } + /* Multiple SG's are not supported for ELS requests */ if (bsg_job->request_payload.sg_cnt > 1 || bsg_job->reply_payload.sg_cnt > 1) { @@ -254,13 +277,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) /* ELS request for rport */ if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { - rport = bsg_job->rport; - fcport = *(fc_port_t **) rport->dd_data; - host = rport_to_shost(rport); - vha = shost_priv(host); - ha = vha->hw; - type = "FC_BSG_RPT_ELS"; - /* make sure the rport is logged in, * if not perform fabric login */ @@ -272,11 +288,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) goto done; } } else { - host = bsg_job->shost; - vha = shost_priv(host); - ha = vha->hw; - type = "FC_BSG_HST_ELS_NOLOGIN"; - /* Allocate a dummy fcport structure, since functions * preparing the IOCB and mailbox command retrieves port * specific information from fcport structure. For Host based -- cgit v1.2.3 From 3711333dfbeec1905c2d3521d1ed2ddcdbdbac04 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 23 Jul 2010 15:28:34 +0500 Subject: [SCSI] qla2xxx: Updates for ISP82xx. Re-organized and cleaned up the ISP82xx specific code. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 4 - drivers/scsi/qla2xxx/qla_mbx.c | 4 +- drivers/scsi/qla2xxx/qla_nx.c | 320 +++++------------------------------------ drivers/scsi/qla2xxx/qla_nx.h | 3 +- 4 files changed, 42 insertions(+), 289 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 84441e8e267e..8b0a8ca95086 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -508,16 +508,12 @@ extern int qla82xx_pci_mem_read_2M(struct qla_hw_data *, u64, void *, int); extern int qla82xx_pci_mem_write_2M(struct qla_hw_data *, u64, void *, int); extern char *qla82xx_pci_info_str(struct scsi_qla_host *, char *); extern int qla82xx_pci_region_offset(struct pci_dev *, int); -extern int qla82xx_pci_region_len(struct pci_dev *, int); extern int qla82xx_iospace_config(struct qla_hw_data *); /* Initialization related functions */ extern void qla82xx_reset_chip(struct scsi_qla_host *); extern void qla82xx_config_rings(struct scsi_qla_host *); -extern int qla82xx_nvram_config(struct scsi_qla_host *); extern int qla82xx_pinit_from_rom(scsi_qla_host_t *); -extern int qla82xx_load_firmware(scsi_qla_host_t *); -extern int qla82xx_reset_hw(scsi_qla_host_t *); extern void qla82xx_watchdog(scsi_qla_host_t *); /* Firmware and flash related functions */ diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 2f39e3093939..02a4d355db3c 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -4111,7 +4111,7 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha) "%s(%ld): entered.\n", __func__, vha->host_no)); memset(mcp, 0, sizeof(mbx_cmd_t)); - mcp->mb[0] = MBC_TOGGLE_INTR; + mcp->mb[0] = MBC_TOGGLE_INTERRUPT; mcp->mb[1] = 1; mcp->out_mb = MBX_1|MBX_0; @@ -4147,7 +4147,7 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha) "%s(%ld): entered.\n", __func__, vha->host_no)); memset(mcp, 0, sizeof(mbx_cmd_t)); - mcp->mb[0] = MBC_TOGGLE_INTR; + mcp->mb[0] = MBC_TOGGLE_INTERRUPT; mcp->mb[1] = 0; mcp->out_mb = MBX_1|MBX_0; diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index e3e3ebdfe5d9..4299df2e082c 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -797,179 +797,6 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha, return ret; } -int -qla82xx_wrmem(struct qla_hw_data *ha, u64 off, void *data, int size) -{ - int i, j, ret = 0, loop, sz[2], off0; - u32 temp; - u64 off8, mem_crb, tmpw, word[2] = {0, 0}; -#define MAX_CTL_CHECK 1000 - /* - * If not MN, go check for MS or invalid. - */ - if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) { - mem_crb = QLA82XX_CRB_QDR_NET; - } else { - mem_crb = QLA82XX_CRB_DDR_NET; - if (qla82xx_pci_mem_bound_check(ha, off, size) == 0) - return qla82xx_pci_mem_write_direct(ha, off, - data, size); - } - - off8 = off & 0xfffffff8; - off0 = off & 0x7; - sz[0] = (size < (8 - off0)) ? size : (8 - off0); - sz[1] = size - sz[0]; - loop = ((off0 + size - 1) >> 3) + 1; - - if ((size != 8) || (off0 != 0)) { - for (i = 0; i < loop; i++) { - if (qla82xx_rdmem(ha, off8 + (i << 3), &word[i], 8)) - return -1; - } - } - - switch (size) { - case 1: - tmpw = *((u8 *)data); - break; - case 2: - tmpw = *((u16 *)data); - break; - case 4: - tmpw = *((u32 *)data); - break; - case 8: - default: - tmpw = *((u64 *)data); - break; - } - - word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); - word[0] |= tmpw << (off0 * 8); - - if (loop == 2) { - word[1] &= ~(~0ULL << (sz[1] * 8)); - word[1] |= tmpw >> (sz[0] * 8); - } - - for (i = 0; i < loop; i++) { - temp = off8 + (i << 3); - qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); - temp = 0; - qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); - temp = word[i] & 0xffffffff; - qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); - temp = (word[i] >> 32) & 0xffffffff; - qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); - temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; - qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); - temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; - qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); - - for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); - if ((temp & MIU_TA_CTL_BUSY) == 0) - break; - } - - if (j >= MAX_CTL_CHECK) { - qla_printk(KERN_WARNING, ha, - "%s: Fail to write through agent\n", - QLA2XXX_DRIVER_NAME); - ret = -1; - break; - } - } - return ret; -} - -int -qla82xx_rdmem(struct qla_hw_data *ha, u64 off, void *data, int size) -{ - int i, j = 0, k, start, end, loop, sz[2], off0[2]; - u32 temp; - u64 off8, val, mem_crb, word[2] = {0, 0}; -#define MAX_CTL_CHECK 1000 - - /* - * If not MN, go check for MS or invalid. - */ - if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) - mem_crb = QLA82XX_CRB_QDR_NET; - else { - mem_crb = QLA82XX_CRB_DDR_NET; - if (qla82xx_pci_mem_bound_check(ha, off, size) == 0) - return qla82xx_pci_mem_read_direct(ha, off, - data, size); - } - - off8 = off & 0xfffffff8; - off0[0] = off & 0x7; - off0[1] = 0; - sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); - sz[1] = size - sz[0]; - loop = ((off0[0] + size - 1) >> 3) + 1; - - for (i = 0; i < loop; i++) { - temp = off8 + (i << 3); - qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); - temp = 0; - qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); - temp = MIU_TA_CTL_ENABLE; - qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); - temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; - qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); - - for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); - if ((temp & MIU_TA_CTL_BUSY) == 0) - break; - } - - if (j >= MAX_CTL_CHECK) { - qla_printk(KERN_INFO, ha, - "%s: Fail to read through agent\n", - QLA2XXX_DRIVER_NAME); - break; - } - - start = off0[i] >> 2; - end = (off0[i] + sz[i] - 1) >> 2; - for (k = start; k <= end; k++) { - temp = qla82xx_rd_32(ha, - mem_crb + MIU_TEST_AGT_RDDATA(k)); - word[i] |= ((u64)temp << (32 * k)); - } - } - - if (j >= MAX_CTL_CHECK) - return -1; - - if (sz[0] == 8) { - val = word[0]; - } else { - val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | - ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); - } - - switch (size) { - case 1: - *(u8 *)data = val; - break; - case 2: - *(u16 *)data = val; - break; - case 4: - *(u32 *)data = val; - break; - case 8: - *(u64 *)data = val; - break; - } - return 0; -} - #define MTU_FUDGE_FACTOR 100 unsigned long qla82xx_decode_crb_addr(unsigned long addr) { @@ -1347,11 +1174,6 @@ int qla82xx_pinit_from_rom(scsi_qla_host_t *vha) continue; } - if (off == (QLA82XX_CRB_PEG_NET_1 + 0x18)) { - if (!QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) - buf[i].data = 0x1020; - } - qla82xx_wr_32(ha, off, buf[i].data); /* ISP requires much bigger delay to settle down, @@ -1429,12 +1251,8 @@ qla82xx_fw_load_from_flash(struct qla_hw_data *ha) } udelay(100); read_lock(&ha->hw_lock); - if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { - qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); - qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); - } else { - qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001d); - } + qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); + qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); read_unlock(&ha->hw_lock); return 0; } @@ -1461,17 +1279,10 @@ qla82xx_pci_mem_read_2M(struct qla_hw_data *ha, off, data, size); } - if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { - off8 = off & 0xfffffff0; - off0[0] = off & 0xf; - sz[0] = (size < (16 - off0[0])) ? size : (16 - off0[0]); - shift_amount = 4; - } else { - off8 = off & 0xfffffff8; - off0[0] = off & 0x7; - sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); - shift_amount = 4; - } + off8 = off & 0xfffffff0; + off0[0] = off & 0xf; + sz[0] = (size < (16 - off0[0])) ? size : (16 - off0[0]); + shift_amount = 4; loop = ((off0[0] + size - 1) >> shift_amount) + 1; off0[1] = 0; sz[1] = size - sz[0]; @@ -1551,7 +1362,7 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, u64 off, void *data, int size) { int i, j, ret = 0, loop, sz[2], off0; - int scale, shift_amount, p3p, startword; + int scale, shift_amount, startword; uint32_t temp; uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; @@ -1571,28 +1382,16 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, sz[0] = (size < (8 - off0)) ? size : (8 - off0); sz[1] = size - sz[0]; - if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { - off8 = off & 0xfffffff0; - loop = (((off & 0xf) + size - 1) >> 4) + 1; - shift_amount = 4; - scale = 2; - p3p = 1; - startword = (off & 0xf)/8; - } else { - off8 = off & 0xfffffff8; - loop = ((off0 + size - 1) >> 3) + 1; - shift_amount = 3; - scale = 1; - p3p = 0; - startword = 0; - } - - if (p3p || (size != 8) || (off0 != 0)) { - for (i = 0; i < loop; i++) { - if (qla82xx_pci_mem_read_2M(ha, off8 + - (i << shift_amount), &word[i * scale], 8)) - return -1; - } + off8 = off & 0xfffffff0; + loop = (((off & 0xf) + size - 1) >> 4) + 1; + shift_amount = 4; + scale = 2; + startword = (off & 0xf)/8; + + for (i = 0; i < loop; i++) { + if (qla82xx_pci_mem_read_2M(ha, off8 + + (i << shift_amount), &word[i * scale], 8)) + return -1; } switch (size) { @@ -1611,26 +1410,16 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, break; } - if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { - if (sz[0] == 8) { - word[startword] = tmpw; - } else { - word[startword] &= - ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); - word[startword] |= tmpw << (off0 * 8); - } - if (sz[1] != 0) { - word[startword+1] &= ~(~0ULL << (sz[1] * 8)); - word[startword+1] |= tmpw >> (sz[0] * 8); - } + if (sz[0] == 8) { + word[startword] = tmpw; } else { - word[startword] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); + word[startword] &= + ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); word[startword] |= tmpw << (off0 * 8); - - if (loop == 2) { - word[1] &= ~(~0ULL << (sz[1] * 8)); - word[1] |= tmpw >> (sz[0] * 8); - } + } + if (sz[1] != 0) { + word[startword+1] &= ~(~0ULL << (sz[1] * 8)); + word[startword+1] |= tmpw >> (sz[0] * 8); } /* @@ -1647,14 +1436,12 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); temp = (word[i * scale] >> 32) & 0xffffffff; qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); - if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { - temp = word[i*scale + 1] & 0xffffffff; - qla82xx_wr_32(ha, mem_crb + - MIU_TEST_AGT_WRDATA_UPPER_LO, temp); - temp = (word[i*scale + 1] >> 32) & 0xffffffff; - qla82xx_wr_32(ha, mem_crb + - MIU_TEST_AGT_WRDATA_UPPER_HI, temp); - } + temp = word[i*scale + 1] & 0xffffffff; + qla82xx_wr_32(ha, mem_crb + + MIU_TEST_AGT_WRDATA_UPPER_LO, temp); + temp = (word[i*scale + 1] >> 32) & 0xffffffff; + qla82xx_wr_32(ha, mem_crb + + MIU_TEST_AGT_WRDATA_UPPER_HI, temp); temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); @@ -1804,22 +1591,6 @@ int qla82xx_pci_region_offset(struct pci_dev *pdev, int region) return val; } -int qla82xx_pci_region_len(struct pci_dev *pdev, int region) -{ - unsigned long val = 0; - u32 control; - switch (region) { - case 0: - pci_read_config_dword(pdev, QLA82XX_PCI_REG_MSIX_TBL, &control); - val = control; - break; - case 1: - val = pci_resource_len(pdev, 0) - - qla82xx_pci_region_offset(pdev, 1); - break; - } - return val; -} int qla82xx_iospace_config(struct qla_hw_data *ha) @@ -1941,12 +1712,6 @@ void qla82xx_config_rings(struct scsi_qla_host *vha) icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); - icb->version = 1; - icb->frame_payload_size = 2112; - icb->execution_throttle = 8; - icb->exchange_count = 128; - icb->login_retry_count = 8; - WRT_REG_DWORD((unsigned long __iomem *)®->req_q_out[0], 0); WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_in[0], 0); WRT_REG_DWORD((unsigned long __iomem *)®->rsp_q_out[0], 0); @@ -1999,11 +1764,8 @@ int qla82xx_fw_load_from_blob(struct qla_hw_data *ha) qla82xx_wr_32(ha, QLA82XX_CAM_RAM(0x1fc), QLA82XX_BDINFO_MAGIC); read_lock(&ha->hw_lock); - if (QLA82XX_IS_REVISION_P3PLUS(ha->chip_revision)) { - qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); - qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); - } else - qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001d); + qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); + qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); read_unlock(&ha->hw_lock); return 0; } @@ -2256,8 +2018,6 @@ qla82xx_intr_handler(int irq, void *dev_id) if (RD_REG_DWORD(®->host_int)) { stat = RD_REG_DWORD(®->host_status); - if ((stat & HSRX_RISC_INT) == 0) - break; switch (stat & 0xff) { case 0x1: @@ -2332,8 +2092,6 @@ qla82xx_msix_default(int irq, void *dev_id) do { if (RD_REG_DWORD(®->host_int)) { stat = RD_REG_DWORD(®->host_status); - if ((stat & HSRX_RISC_INT) == 0) - break; switch (stat & 0xff) { case 0x1: @@ -2583,12 +2341,6 @@ int qla82xx_load_fw(scsi_qla_host_t *vha) struct fw_blob *blob; struct qla_hw_data *ha = vha->hw; - /* Put both the PEG CMD and RCV PEG to default state - * of 0 before resetting the hardware - */ - qla82xx_wr_32(ha, CRB_CMDPEG_STATE, 0); - qla82xx_wr_32(ha, CRB_RCVPEG_STATE, 0); - if (qla82xx_pinit_from_rom(vha) != QLA_SUCCESS) { qla_printk(KERN_ERR, ha, "%s: Error during CRB Initialization\n", __func__); @@ -2669,6 +2421,12 @@ qla82xx_start_firmware(scsi_qla_host_t *vha) /* scrub dma mask expansion register */ qla82xx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555); + /* Put both the PEG CMD and RCV PEG to default state + * of 0 before resetting the hardware + */ + qla82xx_wr_32(ha, CRB_CMDPEG_STATE, 0); + qla82xx_wr_32(ha, CRB_RCVPEG_STATE, 0); + /* Overwrite stale initialization register values */ qla82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS1, 0); qla82xx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0); diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index 9a9127efadaf..420e0773e743 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -816,7 +816,6 @@ struct qla82xx_uri_data_desc{ #define QLA82XX_FLASH_ROMIMAGE 4 #define QLA82XX_UNKNOWN_ROMIMAGE 0xff -#define QLA82XX_IS_REVISION_P3PLUS(_rev_) ((_rev_) >= 0x50) #define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0) #define MIU_TEST_AGT_WRDATA_UPPER_HI (0x0b4) @@ -887,7 +886,7 @@ struct ct6_dsd { struct list_head dsd_list; }; -#define MBC_TOGGLE_INTR 0x10 +#define MBC_TOGGLE_INTERRUPT 0x10 /* Flash offset */ #define FLT_REG_BOOTLOAD_82XX 0x72 -- cgit v1.2.3 From 4d78c973ef2d21e90ff55f97489d663a0959a93f Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 23 Jul 2010 15:28:35 +0500 Subject: [SCSI] qla2xxx: Rearranged and cleaned up the code for processing the pending commands. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 10 ++++++++-- drivers/scsi/qla2xxx/qla_gbl.h | 5 +++-- drivers/scsi/qla2xxx/qla_init.c | 9 +++++++-- drivers/scsi/qla2xxx/qla_os.c | 41 +++++++---------------------------------- 4 files changed, 25 insertions(+), 40 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 7e11ccf0fe81..84e9c6b48ca3 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2981,9 +2981,15 @@ typedef struct scsi_qla_host { #define QLA_DSDS_PER_IOCB 37 +#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) + +enum nexus_wait_type { + WAIT_HOST = 0, + WAIT_TARGET, + WAIT_LUN, +}; + #include "qla_gbl.h" #include "qla_dbg.h" #include "qla_inline.h" - -#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) #endif diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 8b0a8ca95086..4688ad2a559e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -292,7 +292,9 @@ extern int qla24xx_abort_target(struct fc_port *, unsigned int, int); extern int qla24xx_lun_reset(struct fc_port *, unsigned int, int); - +extern int +qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *, unsigned int, + unsigned int, enum nexus_wait_type); extern int qla2x00_system_error(scsi_qla_host_t *); @@ -569,7 +571,6 @@ extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *); extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *); extern void qla82xx_start_iocbs(srb_t *); extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *); -extern void qla82xx_wait_for_pending_commands(scsi_qla_host_t *); /* BSG related functions */ extern int qla24xx_bsg_request(struct fc_bsg_job *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f6b1052a3834..9b58a79c4ae5 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3833,8 +3833,13 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) } /* Make sure for ISP 82XX IO DMA is complete */ - if (IS_QLA82XX(ha)) - qla82xx_wait_for_pending_commands(vha); + if (IS_QLA82XX(ha)) { + if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, + WAIT_HOST) == QLA_SUCCESS) { + DEBUG2(qla_printk(KERN_INFO, ha, + "Done wait for pending commands\n")); + } + } /* Requeue all commands in outstanding command list. */ qla2x00_abort_all_cmds(vha, DID_RESET << 16); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index fcdbf7a0be55..86d352ab9c58 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -903,24 +903,17 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return ret; } -enum nexus_wait_type { - WAIT_HOST = 0, - WAIT_TARGET, - WAIT_LUN, -}; - -static int +int qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, - unsigned int l, srb_t *sp, enum nexus_wait_type type) + unsigned int l, enum nexus_wait_type type) { int cnt, match, status; unsigned long flags; struct qla_hw_data *ha = vha->hw; struct req_que *req; + srb_t *sp; status = QLA_SUCCESS; - if (!sp) - return status; spin_lock_irqsave(&ha->hardware_lock, flags); req = vha->req; @@ -958,24 +951,6 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, return status; } -void qla82xx_wait_for_pending_commands(scsi_qla_host_t *vha) -{ - int cnt; - srb_t *sp; - struct req_que *req = vha->req; - - DEBUG2(qla_printk(KERN_INFO, vha->hw, - "Waiting for pending commands\n")); - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { - sp = req->outstanding_cmds[cnt]; - if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, - sp, WAIT_HOST) == QLA_SUCCESS) { - DEBUG2(qla_printk(KERN_INFO, vha->hw, - "Done wait for pending commands\n")); - } - } -} - static char *reset_errors[] = { "HBA not online", "HBA not ready", @@ -1011,7 +986,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, goto eh_reset_failed; err = 3; if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id, - cmd->device->lun, (srb_t *) CMD_SP(cmd), type) != QLA_SUCCESS) + cmd->device->lun, type) != QLA_SUCCESS) goto eh_reset_failed; qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n", @@ -1019,7 +994,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, return SUCCESS; - eh_reset_failed: +eh_reset_failed: qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n" , vha->host_no, cmd->device->id, cmd->device->lun, name, reset_errors[err]); @@ -1069,7 +1044,6 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) int ret = FAILED; unsigned int id, lun; unsigned long serial; - srb_t *sp = (srb_t *) CMD_SP(cmd); fc_block_scsi_eh(cmd); @@ -1096,7 +1070,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) goto eh_bus_reset_done; /* Flush outstanding commands. */ - if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) != + if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) != QLA_SUCCESS) ret = FAILED; @@ -1131,7 +1105,6 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) int ret = FAILED; unsigned int id, lun; unsigned long serial; - srb_t *sp = (srb_t *) CMD_SP(cmd); scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); fc_block_scsi_eh(cmd); @@ -1186,7 +1159,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) } /* Waiting for command to be returned to OS.*/ - if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, sp, WAIT_HOST) == + if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) == QLA_SUCCESS) ret = SUCCESS; -- cgit v1.2.3 From de7c5d059dbd245ad80011725f9c86f560e61fff Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 23 Jul 2010 15:28:36 +0500 Subject: [SCSI] qla2xxx: Update copyright banner. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 2 +- drivers/scsi/qla2xxx/qla_bsg.c | 2 +- drivers/scsi/qla2xxx/qla_bsg.h | 2 +- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_dbg.h | 2 +- drivers/scsi/qla2xxx/qla_def.h | 2 +- drivers/scsi/qla2xxx/qla_dfs.c | 2 +- drivers/scsi/qla2xxx/qla_fw.h | 2 +- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_gs.c | 2 +- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_inline.h | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 2 +- drivers/scsi/qla2xxx/qla_mbx.c | 2 +- drivers/scsi/qla2xxx/qla_mid.c | 2 +- drivers/scsi/qla2xxx/qla_nx.c | 2 +- drivers/scsi/qla2xxx/qla_nx.h | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- drivers/scsi/qla2xxx/qla_settings.h | 2 +- drivers/scsi/qla2xxx/qla_sup.c | 2 +- drivers/scsi/qla2xxx/qla_version.h | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 93a4c20e2113..d9b431d061b2 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 6b863f789c4d..9067629817ea 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index 1f096dabc015..cc7c52f87a11 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 2afc8a362f2c..096141148257 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 916c81f3f55d..6cfc28a25eb3 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 84e9c6b48ca3..3a432ea0c7a3 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index 3a9a6ca42266..6271353e8c51 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 93f833960147..631fefc8482d 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 4688ad2a559e..b7d940fcbc1b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 2fabae8daec4..4c083928c2fb 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 9b58a79c4ae5..1b7d80b20986 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 84c2fea154d2..48f97a92e33d 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index e27d94713bdf..c9c709e0f1a2 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 518003328226..6982ba70e12a 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 02a4d355db3c..6009b0c69488 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index d1618b4a5e50..642cd79bd030 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 4299df2e082c..915b77a6e193 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index 420e0773e743..569232b45502 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 86d352ab9c58..50f685415fb2 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h index 2801c2664b40..f0b2b9986a55 100644 --- a/drivers/scsi/qla2xxx/qla_settings.h +++ b/drivers/scsi/qla2xxx/qla_settings.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index df288dc829e0..76de9574b385 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 9b49b0862747..e75ccb91317d 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -1,6 +1,6 @@ /* * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */ -- cgit v1.2.3 From 3dbe756a66afbec6487068d4213ecccc3a18807f Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 23 Jul 2010 15:28:37 +0500 Subject: [SCSI] qla2xxx: Cleanup some dead-code and make some functions static. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 6 ----- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 2 +- drivers/scsi/qla2xxx/qla_mid.c | 51 +---------------------------------------- drivers/scsi/qla2xxx/qla_os.c | 4 ++-- 5 files changed, 5 insertions(+), 60 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index b7d940fcbc1b..1a1b281cea33 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -175,10 +175,7 @@ extern int qla2x00_start_scsi(srb_t *sp); extern int qla24xx_start_scsi(srb_t *sp); int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, uint16_t, uint16_t, uint8_t); -int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, - uint16_t, uint16_t, uint8_t); extern int qla2x00_start_sp(srb_t *); -extern void qla2x00_ctx_sp_free(srb_t *); extern uint16_t qla24xx_calc_iocbs(uint16_t); extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t); extern int qla24xx_dif_start_scsi(srb_t *); @@ -489,11 +486,8 @@ extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t, uint16_t, int, uint8_t); extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t, uint16_t, int); -extern int qla25xx_update_req_que(struct scsi_qla_host *, uint8_t, uint8_t); extern void qla2x00_init_response_q_entries(struct rsp_que *); extern int qla25xx_delete_req_que(struct scsi_qla_host *, struct req_que *); -extern int qla25xx_delete_rsp_que(struct scsi_qla_host *, struct rsp_que *); -extern int qla25xx_create_queues(struct scsi_qla_host *, uint8_t); extern int qla25xx_delete_queues(struct scsi_qla_host *); extern uint16_t qla24xx_rd_req_reg(struct qla_hw_data *, uint16_t); extern uint16_t qla25xx_rd_req_reg(struct qla_hw_data *, uint16_t); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1b7d80b20986..d863ed2619b5 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -64,7 +64,7 @@ qla2x00_ctx_sp_timeout(unsigned long __data) spin_unlock_irqrestore(&ha->hardware_lock, flags); } -void +static void qla2x00_ctx_sp_free(srb_t *sp) { struct srb_ctx *ctx = sp->ctx; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index c9c709e0f1a2..d2b299f2c503 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -461,7 +461,7 @@ queuing_error: * * Returns non-zero if a failure occurred, else zero. */ -int +static int __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, struct rsp_que *rsp, uint16_t loop_id, uint16_t lun, uint8_t type) diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 642cd79bd030..9a82c34f6206 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -482,7 +482,7 @@ qla25xx_delete_req_que(struct scsi_qla_host *vha, struct req_que *req) return ret; } -int +static int qla25xx_delete_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) { int ret = -1; @@ -497,23 +497,6 @@ qla25xx_delete_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) return ret; } -int qla25xx_update_req_que(struct scsi_qla_host *vha, uint8_t que, uint8_t qos) -{ - int ret = 0; - struct qla_hw_data *ha = vha->hw; - struct req_que *req = ha->req_q_map[que]; - - req->options |= BIT_3; - req->qos = qos; - ret = qla25xx_init_req_que(vha, req); - if (ret != QLA_SUCCESS) - DEBUG2_17(printk(KERN_WARNING "%s failed\n", __func__)); - /* restore options bit */ - req->options &= ~BIT_3; - return ret; -} - - /* Delete all queues for a given vhost */ int qla25xx_delete_queues(struct scsi_qla_host *vha) @@ -740,35 +723,3 @@ que_failed: failed: return 0; } - -int -qla25xx_create_queues(struct scsi_qla_host *vha, uint8_t qos) -{ - uint16_t options = 0; - uint8_t ret = 0; - struct qla_hw_data *ha = vha->hw; - struct rsp_que *rsp; - - options |= BIT_1; - ret = qla25xx_create_rsp_que(ha, options, vha->vp_idx, 0, -1); - if (!ret) { - qla_printk(KERN_WARNING, ha, "Response Que create failed\n"); - return ret; - } else - qla_printk(KERN_INFO, ha, "Response Que:%d created.\n", ret); - rsp = ha->rsp_q_map[ret]; - - options = 0; - if (qos & BIT_7) - options |= BIT_8; - ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, ret, - qos & ~BIT_7); - if (ret) { - vha->req = ha->req_q_map[ret]; - qla_printk(KERN_INFO, ha, "Request Que:%d created.\n", ret); - } else - qla_printk(KERN_WARNING, ha, "Request Que create failed\n"); - rsp->req = ha->req_q_map[ret]; - - return ret; -} diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 50f685415fb2..aeb2f1b504c4 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -701,7 +701,7 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha) * Success (Adapter is online/no flash ops) : 0 * Failed (Adapter is offline/disabled/flash ops in progress) : 1 */ -int +static int qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha) { int return_status; @@ -3469,7 +3469,7 @@ qla2x00_sp_free_dma(srb_t *sp) CMD_SP(cmd) = NULL; } -void +static void qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp) { struct scsi_cmnd *cmd = sp->cmd; -- cgit v1.2.3 From 0c470874858e0075f420dcfb3c3570b2057de275 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Fri, 23 Jul 2010 15:28:38 +0500 Subject: [SCSI] qla2xxx: T10 DIF Type 2 support Signed-off-by: Andrew Vasquez Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 2 ++ drivers/scsi/qla2xxx/qla_iocb.c | 35 +++++++++++++++++++++++++++++++---- drivers/scsi/qla2xxx/qla_mid.c | 5 ++++- drivers/scsi/qla2xxx/qla_os.c | 7 ++++++- 4 files changed, 43 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index d9b431d061b2..420238cc794e 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1758,8 +1758,10 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) " protection.\n")); scsi_host_set_prot(vha->host, SHOST_DIF_TYPE1_PROTECTION + | SHOST_DIF_TYPE2_PROTECTION | SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION + | SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION); scsi_host_set_guard(vha->host, SHOST_DIX_GUARD_CRC); } else diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d2b299f2c503..4e4c21fafe3a 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -712,6 +712,25 @@ qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, * match LBA in CDB + N */ case SCSI_PROT_DIF_TYPE2: + if (!ql2xenablehba_err_chk) + break; + + if (scsi_prot_sg_count(cmd)) { + spt = page_address(sg_page(scsi_prot_sglist(cmd))) + + scsi_prot_sglist(cmd)[0].offset; + pkt->app_tag = swab32(spt->app_tag); + pkt->app_tag_mask[0] = 0xff; + pkt->app_tag_mask[1] = 0xff; + } + + pkt->ref_tag = cpu_to_le32((uint32_t) + (0xffffffff & scsi_get_lba(cmd))); + + /* enable ALL bytes of the ref tag */ + pkt->ref_tag_mask[0] = 0xff; + pkt->ref_tag_mask[1] = 0xff; + pkt->ref_tag_mask[2] = 0xff; + pkt->ref_tag_mask[3] = 0xff; break; /* For Type 3 protection: 16 bit GUARD only */ @@ -1062,7 +1081,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, total_bytes = data_bytes; dif_bytes = 0; blk_size = cmd->device->sector_size; - if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE1) { + if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) { dif_bytes = (data_bytes / blk_size) * 8; total_bytes += dif_bytes; } @@ -1100,6 +1119,12 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, vha->host_no, dif_bytes, dif_bytes, total_bytes, total_bytes, crc_ctx_pkt->blk_size, crc_ctx_pkt->blk_size)); + if (!data_bytes || cmd->sc_data_direction == DMA_NONE) { + DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n", + __func__, data_bytes)); + cmd_pkt->byte_count = __constant_cpu_to_le32(0); + return QLA_SUCCESS; + } /* Walks data segments */ cmd_pkt->control_flags |= @@ -1310,9 +1335,11 @@ qla24xx_dif_start_scsi(srb_t *sp) #define QDSS_GOT_Q_SPACE BIT_0 - /* Only process protection in this routine */ - if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) - return qla24xx_start_scsi(sp); + /* Only process protection or >16 cdb in this routine */ + if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) { + if (cmd->cmd_len <= 16) + return qla24xx_start_scsi(sp); + } /* Setup device pointers. */ diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 9a82c34f6206..987c5b0ca78e 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -399,7 +399,10 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) host->can_queue = base_vha->req->length + 128; host->this_id = 255; host->cmd_per_lun = 3; - host->max_cmd_len = MAX_CMDSZ; + if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) + host->max_cmd_len = 32; + else + host->max_cmd_len = MAX_CMDSZ; host->max_channel = MAX_BUSES - 1; host->max_lun = MAX_LUNS; host->unique_id = host->host_no; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index aeb2f1b504c4..ff2172da7c19 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2147,7 +2147,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->this_id = 255; host->cmd_per_lun = 3; host->unique_id = host->host_no; - host->max_cmd_len = MAX_CMDSZ; + if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && ql2xenabledif) + host->max_cmd_len = 32; + else + host->max_cmd_len = MAX_CMDSZ; host->max_channel = MAX_BUSES - 1; host->max_lun = MAX_LUNS; host->transportt = qla2xxx_transport_template; @@ -2255,8 +2258,10 @@ skip_dpc: " protection.\n")); scsi_host_set_prot(host, SHOST_DIF_TYPE1_PROTECTION + | SHOST_DIF_TYPE2_PROTECTION | SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION + | SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION); scsi_host_set_guard(host, SHOST_DIX_GUARD_CRC); } else -- cgit v1.2.3 From 0dcae66fd9cb47f4db64aba20a59d26e09e78fe4 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Wed, 1 Jul 2009 22:43:39 +0200 Subject: [SCSI] aacraid: Do not set DMA mask to 32 bit first if adapter only supports 31 Signed-off-by: Rolf Eike Beer Acked-by: Achim Leubner Signed-off-by: James Bottomley --- drivers/scsi/aacraid/linit.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 33898b61fdb5..cad6f9abaeb9 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1091,6 +1091,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, struct list_head *insert = &aac_devices; int error = -ENODEV; int unique_id = 0; + u64 dmamask; list_for_each_entry(aac, &aac_devices, entry) { if (aac->id > unique_id) @@ -1104,17 +1105,18 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, goto out; error = -ENODEV; - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) || - pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) - goto out_disable_pdev; /* * If the quirk31 bit is set, the adapter needs adapter * to driver communication memory to be allocated below 2gig */ if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(31)) || - pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(31))) - goto out_disable_pdev; + dmamask = DMA_BIT_MASK(31); + else + dmamask = DMA_BIT_MASK(32); + + if (pci_set_dma_mask(pdev, dmamask) || + pci_set_consistent_dma_mask(pdev, dmamask)) + goto out_disable_pdev; pci_set_master(pdev); -- cgit v1.2.3 From b5833cbbd7c2bc3462e684feadd8e6a0ca8e5387 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 20 Jul 2010 15:28:41 -0700 Subject: [SCSI] ibmvstgt: add __init/__exit macros Add the __init and __exit macros to the module_init / module_exit functions from drivers/scsi/ibmvscsi/ibmvstgt.c Signed-off-by: Peter Huewe Signed-off-by: Andrew Morton Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvstgt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index e2056d517e99..2256babe0474 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -956,7 +956,7 @@ static struct srp_function_template ibmvstgt_transport_functions = { .it_nexus_response = ibmvstgt_it_nexus_response, }; -static int ibmvstgt_init(void) +static int __init ibmvstgt_init(void) { int err = -ENOMEM; @@ -987,7 +987,7 @@ release_transport: return err; } -static void ibmvstgt_exit(void) +static void __exit ibmvstgt_exit(void) { printk("Unregister IBM virtual SCSI driver\n"); -- cgit v1.2.3 From df64d3caab8db6ae17dacd229a03d7689a10c432 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 27 Jul 2010 15:51:13 -0500 Subject: [SCSI] Unify SAM_ and SAM_STAT_ macros We have two separate definitions for identical constants with nearly the same name. One comes from the generic headers in scsi.h; the other is an enum in libsas.h ... it's causing confusion about which one is correct (fortunately they both are). Fix this by eliminating the libsas.h duplicate Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_task.c | 2 +- drivers/scsi/libsas/sas_ata.c | 12 ++++++------ drivers/scsi/libsas/sas_expander.c | 2 +- drivers/scsi/libsas/sas_scsi_host.c | 4 ++-- drivers/scsi/libsas/sas_task.c | 6 +++--- drivers/scsi/mvsas/mv_sas.c | 16 ++++++++-------- drivers/scsi/pm8001/pm8001_hwi.c | 14 +++++++------- drivers/scsi/pm8001/pm8001_sas.c | 4 ++-- include/scsi/libsas.h | 11 +---------- 9 files changed, 31 insertions(+), 40 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index 75d20f72501f..532d212b6b2c 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -223,7 +223,7 @@ Again: switch (opcode) { case TC_NO_ERROR: ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAM_GOOD; + ts->stat = SAM_STAT_GOOD; break; case TC_UNDERRUN: ts->resp = SAS_TASK_COMPLETE; diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 8c496b56556c..042153cbbde1 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -71,7 +71,7 @@ static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts) case SAS_SG_ERR: return AC_ERR_INVALID; - case SAM_CHECK_COND: + case SAM_STAT_CHECK_CONDITION: case SAS_OPEN_TO: case SAS_OPEN_REJECT: SAS_DPRINTK("%s: Saw error %d. What to do?\n", @@ -107,7 +107,7 @@ static void sas_ata_task_done(struct sas_task *task) sas_ha = dev->port->ha; spin_lock_irqsave(dev->sata_dev.ap->lock, flags); - if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_GOOD) { + if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD) { ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); dev->sata_dev.sstatus = resp->sstatus; @@ -511,12 +511,12 @@ static int sas_execute_task(struct sas_task *task, void *buffer, int size, goto ex_err; } } - if (task->task_status.stat == SAM_BUSY || - task->task_status.stat == SAM_TASK_SET_FULL || + if (task->task_status.stat == SAM_STAT_BUSY || + task->task_status.stat == SAM_STAT_TASK_SET_FULL || task->task_status.stat == SAS_QUEUE_FULL) { SAS_DPRINTK("task: q busy, sleeping...\n"); schedule_timeout_interruptible(HZ); - } else if (task->task_status.stat == SAM_CHECK_COND) { + } else if (task->task_status.stat == SAM_STAT_CHECK_CONDITION) { struct scsi_sense_hdr shdr; if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, @@ -549,7 +549,7 @@ static int sas_execute_task(struct sas_task *task, void *buffer, int size, shdr.asc, shdr.ascq); } } else if (task->task_status.resp != SAS_TASK_COMPLETE || - task->task_status.stat != SAM_GOOD) { + task->task_status.stat != SAM_STAT_GOOD) { SAS_DPRINTK("task finished with resp:0x%x, " "stat:0x%x\n", task->task_status.resp, diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index c65af02dcfe8..83dd5070a15c 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -107,7 +107,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, } } if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAM_GOOD) { + task->task_status.stat == SAM_STAT_GOOD) { res = 0; break; } if (task->task_status.resp == SAS_TASK_COMPLETE && diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index a7890c6d878e..f0cfba9a1fc8 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -113,10 +113,10 @@ static void sas_scsi_task_done(struct sas_task *task) case SAS_ABORTED_TASK: hs = DID_ABORT; break; - case SAM_CHECK_COND: + case SAM_STAT_CHECK_CONDITION: memcpy(sc->sense_buffer, ts->buf, min(SCSI_SENSE_BUFFERSIZE, ts->buf_valid_size)); - stat = SAM_CHECK_COND; + stat = SAM_STAT_CHECK_CONDITION; break; default: stat = ts->stat; diff --git a/drivers/scsi/libsas/sas_task.c b/drivers/scsi/libsas/sas_task.c index 594524d5bfa1..b13a3346894c 100644 --- a/drivers/scsi/libsas/sas_task.c +++ b/drivers/scsi/libsas/sas_task.c @@ -15,13 +15,13 @@ void sas_ssp_task_response(struct device *dev, struct sas_task *task, else if (iu->datapres == 1) tstat->stat = iu->resp_data[3]; else if (iu->datapres == 2) { - tstat->stat = SAM_CHECK_COND; + tstat->stat = SAM_STAT_CHECK_CONDITION; tstat->buf_valid_size = min_t(int, SAS_STATUS_BUF_SIZE, be32_to_cpu(iu->sense_data_len)); memcpy(tstat->buf, iu->sense_data, tstat->buf_valid_size); - if (iu->status != SAM_CHECK_COND) + if (iu->status != SAM_STAT_CHECK_CONDITION) dev_printk(KERN_WARNING, dev, "dev %llx sent sense data, but " "stat(%x) is not CHECK CONDITION\n", @@ -30,7 +30,7 @@ void sas_ssp_task_response(struct device *dev, struct sas_task *task, } else /* when datapres contains corrupt/unknown value... */ - tstat->stat = SAM_CHECK_COND; + tstat->stat = SAM_STAT_CHECK_CONDITION; } EXPORT_SYMBOL_GPL(sas_ssp_task_response); diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index cab924239862..adedaa916ecb 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1483,7 +1483,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev, } if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAM_GOOD) { + task->task_status.stat == SAM_STAT_GOOD) { res = TMF_RESP_FUNC_COMPLETE; break; } @@ -1758,7 +1758,7 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task, struct mvs_device *mvi_dev = task->dev->lldd_dev; struct task_status_struct *tstat = &task->task_status; struct ata_task_resp *resp = (struct ata_task_resp *)tstat->buf; - int stat = SAM_GOOD; + int stat = SAM_STAT_GOOD; resp->frame_len = sizeof(struct dev_to_host_fis); @@ -1790,13 +1790,13 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, MVS_CHIP_DISP->command_active(mvi, slot_idx); - stat = SAM_CHECK_COND; + stat = SAM_STAT_CHECK_CONDITION; switch (task->task_proto) { case SAS_PROTOCOL_SSP: stat = SAS_ABORTED_TASK; break; case SAS_PROTOCOL_SMP: - stat = SAM_CHECK_COND; + stat = SAM_STAT_CHECK_CONDITION; break; case SAS_PROTOCOL_SATA: @@ -1881,7 +1881,7 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) case SAS_PROTOCOL_SSP: /* hw says status == 0, datapres == 0 */ if (rx_desc & RXQ_GOOD) { - tstat->stat = SAM_GOOD; + tstat->stat = SAM_STAT_GOOD; tstat->resp = SAS_TASK_COMPLETE; } /* response frame present */ @@ -1890,12 +1890,12 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) sizeof(struct mvs_err_info); sas_ssp_task_response(mvi->dev, task, iu); } else - tstat->stat = SAM_CHECK_COND; + tstat->stat = SAM_STAT_CHECK_CONDITION; break; case SAS_PROTOCOL_SMP: { struct scatterlist *sg_resp = &task->smp_task.smp_resp; - tstat->stat = SAM_GOOD; + tstat->stat = SAM_STAT_GOOD; to = kmap_atomic(sg_page(sg_resp), KM_IRQ0); memcpy(to + sg_resp->offset, slot->response + sizeof(struct mvs_err_info), @@ -1912,7 +1912,7 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) } default: - tstat->stat = SAM_CHECK_COND; + tstat->stat = SAM_STAT_CHECK_CONDITION; break; } if (!slot->port->port_attached) { diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 5ff8261c5d67..356ad268de6d 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1480,7 +1480,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ",param = %d \n", param)); if (param == 0) { ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAM_GOOD; + ts->stat = SAM_STAT_GOOD; } else { ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_PROTO_RESPONSE; @@ -1909,7 +1909,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); if (param == 0) { ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAM_GOOD; + ts->stat = SAM_STAT_GOOD; } else { u8 len; ts->resp = SAS_TASK_COMPLETE; @@ -2450,7 +2450,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) case IO_SUCCESS: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAM_GOOD; + ts->stat = SAM_STAT_GOOD; if (pm8001_dev) pm8001_dev->running_req--; break; @@ -2479,19 +2479,19 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_ERROR_HW_TIMEOUT\n")); ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAM_BUSY; + ts->stat = SAM_STAT_BUSY; break; case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_BREAK\n")); ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAM_BUSY; + ts->stat = SAM_STAT_BUSY; break; case IO_XFER_ERROR_PHY_NOT_READY: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAM_BUSY; + ts->stat = SAM_STAT_BUSY; break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: PM8001_IO_DBG(pm8001_ha, @@ -3260,7 +3260,7 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) case IO_SUCCESS: PM8001_EH_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAM_GOOD; + ts->stat = SAM_STAT_GOOD; break; case IO_NOT_VALID: PM8001_EH_DBG(pm8001_ha, pm8001_printk("IO_NOT_VALID\n")); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index cd02ceaf67ff..6ae059ebb4bb 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -763,7 +763,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, } if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAM_GOOD) { + task->task_status.stat == SAM_STAT_GOOD) { res = TMF_RESP_FUNC_COMPLETE; break; } @@ -853,7 +853,7 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha, } if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAM_GOOD) { + task->task_status.stat == SAM_STAT_GOOD) { res = TMF_RESP_FUNC_COMPLETE; break; diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 3b586859669c..d06e13be717b 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -422,16 +422,7 @@ enum service_response { }; enum exec_status { - SAM_GOOD = 0, - SAM_CHECK_COND = 2, - SAM_COND_MET = 4, - SAM_BUSY = 8, - SAM_INTERMEDIATE = 0x10, - SAM_IM_COND_MET = 0x12, - SAM_RESV_CONFLICT= 0x14, - SAM_TASK_SET_FULL= 0x28, - SAM_ACA_ACTIVE = 0x30, - SAM_TASK_ABORTED = 0x40, + /* The SAM_STAT_.. codes fit in the lower 6 bits */ SAS_DEV_NO_RESPONSE = 0x80, SAS_DATA_UNDERRUN, -- cgit v1.2.3 From db5bd1e0b505c54ff492172ce4abc245cf6cd639 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 17 Jun 2010 10:36:49 -0400 Subject: [SCSI] convert to the new PM framework This patch (as1397b) converts the SCSI midlayer to use the new PM callbacks (struct dev_pm_ops). A new source file, scsi_pm.c, is created to hold the new callback routines, and the existing suspend/resume code is moved there. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/Makefile | 1 + drivers/scsi/scsi_pm.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/scsi_priv.h | 7 ++++ drivers/scsi/scsi_sysfs.c | 48 +----------------------- 4 files changed, 105 insertions(+), 47 deletions(-) create mode 100644 drivers/scsi/scsi_pm.c (limited to 'drivers/scsi') diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 1c7ac49be649..2a3fca2eca6a 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -163,6 +163,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o scsi_mod-y += scsi_trace.o +scsi_mod-$(CONFIG_PM_OPS) += scsi_pm.o scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c new file mode 100644 index 000000000000..cd83758ce0a2 --- /dev/null +++ b/drivers/scsi/scsi_pm.c @@ -0,0 +1,96 @@ +/* + * scsi_pm.c Copyright (C) 2010 Alan Stern + * + * SCSI dynamic Power Management + * Initial version: Alan Stern + */ + +#include + +#include +#include +#include +#include + +#include "scsi_priv.h" + +static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg) +{ + struct device_driver *drv; + int err; + + err = scsi_device_quiesce(to_scsi_device(dev)); + if (err == 0) { + drv = dev->driver; + if (drv && drv->suspend) + err = drv->suspend(dev, msg); + } + dev_dbg(dev, "scsi suspend: %d\n", err); + return err; +} + +static int scsi_dev_type_resume(struct device *dev) +{ + struct device_driver *drv; + int err = 0; + + drv = dev->driver; + if (drv && drv->resume) + err = drv->resume(dev); + scsi_device_resume(to_scsi_device(dev)); + dev_dbg(dev, "scsi resume: %d\n", err); + return err; +} + +#ifdef CONFIG_PM_SLEEP + +static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg) +{ + int err = 0; + + if (scsi_is_sdev_device(dev)) + err = scsi_dev_type_suspend(dev, msg); + return err; +} + +static int scsi_bus_resume_common(struct device *dev) +{ + int err = 0; + + if (scsi_is_sdev_device(dev)) + err = scsi_dev_type_resume(dev); + return err; +} + +static int scsi_bus_suspend(struct device *dev) +{ + return scsi_bus_suspend_common(dev, PMSG_SUSPEND); +} + +static int scsi_bus_freeze(struct device *dev) +{ + return scsi_bus_suspend_common(dev, PMSG_FREEZE); +} + +static int scsi_bus_poweroff(struct device *dev) +{ + return scsi_bus_suspend_common(dev, PMSG_HIBERNATE); +} + +#else /* CONFIG_PM_SLEEP */ + +#define scsi_bus_resume_common NULL +#define scsi_bus_suspend NULL +#define scsi_bus_freeze NULL +#define scsi_bus_poweroff NULL + +#endif /* CONFIG_PM_SLEEP */ + +const struct dev_pm_ops scsi_bus_pm_ops = { + .suspend = scsi_bus_suspend, + .resume = scsi_bus_resume_common, + .freeze = scsi_bus_freeze, + .thaw = scsi_bus_resume_common, + .poweroff = scsi_bus_poweroff, + .restore = scsi_bus_resume_common, +}; diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 1fbf7c78bba0..dddacc732550 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -144,6 +144,13 @@ static inline void scsi_netlink_init(void) {} static inline void scsi_netlink_exit(void) {} #endif +/* scsi_pm.c */ +#ifdef CONFIG_PM_OPS +extern const struct dev_pm_ops scsi_bus_pm_ops; +#else +#define scsi_bus_pm_ops (*NULL) +#endif + /* * internal scsi timeout functions: for use by mid-layer and transport * classes. diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index c23ab978c3ba..5f85f8e831f3 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -376,57 +376,11 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -static int scsi_bus_suspend(struct device * dev, pm_message_t state) -{ - struct device_driver *drv; - struct scsi_device *sdev; - int err; - - if (dev->type != &scsi_dev_type) - return 0; - - drv = dev->driver; - sdev = to_scsi_device(dev); - - err = scsi_device_quiesce(sdev); - if (err) - return err; - - if (drv && drv->suspend) { - err = drv->suspend(dev, state); - if (err) - return err; - } - - return 0; -} - -static int scsi_bus_resume(struct device * dev) -{ - struct device_driver *drv; - struct scsi_device *sdev; - int err = 0; - - if (dev->type != &scsi_dev_type) - return 0; - - drv = dev->driver; - sdev = to_scsi_device(dev); - - if (drv && drv->resume) - err = drv->resume(dev); - - scsi_device_resume(sdev); - - return err; -} - struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, .uevent = scsi_bus_uevent, - .suspend = scsi_bus_suspend, - .resume = scsi_bus_resume, + .pm = &scsi_bus_pm_ops, }; EXPORT_SYMBOL_GPL(scsi_bus_type); -- cgit v1.2.3 From bc4f24014de58f045f169742701a6598884d93db Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 17 Jun 2010 10:41:42 -0400 Subject: [SCSI] implement runtime Power Management This patch (as1398b) adds runtime PM support to the SCSI layer. Only the machanism is provided; use of it is up to the various high-level drivers, and the patch doesn't change any of them. Except for sg -- the patch expicitly prevents a device from being runtime-suspended while its sg device file is open. The implementation is simplistic. In general, hosts and targets are automatically suspended when all their children are asleep, but for them the runtime-suspend code doesn't actually do anything. (A host's runtime PM status is propagated up the device tree, though, so a runtime-PM-aware lower-level driver could power down the host adapter hardware at the appropriate times.) There are comments indicating where a transport class might be notified or some other hooks added. LUNs are runtime-suspended by calling the drivers' existing suspend handlers (and likewise for runtime-resume). Somewhat arbitrarily, the implementation delays for 100 ms before suspending an eligible LUN. This is because there typically are occasions during bootup when the same device file is opened and closed several times in quick succession. The way this all works is that the SCSI core increments a device's PM-usage count when it is registered. If a high-level driver does nothing then the device will not be eligible for runtime-suspend because of the elevated usage count. If a high-level driver wants to use runtime PM then it can call scsi_autopm_put_device() in its probe routine to decrement the usage count and scsi_autopm_get_device() in its remove routine to restore the original count. Hosts, targets, and LUNs are not suspended while they are being probed or removed, or while the error handler is running. In fact, a fairly large part of the patch consists of code to make sure that things aren't suspended at such times. [jejb: fix up compile issues in PM config variations] Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/hosts.c | 10 ++++- drivers/scsi/scsi_error.c | 16 ++++++- drivers/scsi/scsi_pm.c | 110 +++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/scsi_priv.h | 14 +++++- drivers/scsi/scsi_scan.c | 24 ++++++++-- drivers/scsi/scsi_sysfs.c | 20 ++++++++- drivers/scsi/sg.c | 10 ++++- include/scsi/scsi_device.h | 8 ++++ 8 files changed, 201 insertions(+), 11 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index a2b1414da288..8a8f803439e1 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -156,6 +157,7 @@ EXPORT_SYMBOL(scsi_host_set_state); void scsi_remove_host(struct Scsi_Host *shost) { unsigned long flags; + mutex_lock(&shost->scan_mutex); spin_lock_irqsave(shost->host_lock, flags); if (scsi_host_set_state(shost, SHOST_CANCEL)) @@ -165,6 +167,8 @@ void scsi_remove_host(struct Scsi_Host *shost) return; } spin_unlock_irqrestore(shost->host_lock, flags); + + scsi_autopm_get_host(shost); scsi_forget_host(shost); mutex_unlock(&shost->scan_mutex); scsi_proc_host_rm(shost); @@ -216,12 +220,14 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, shost->shost_gendev.parent = dev ? dev : &platform_bus; shost->dma_dev = dma_dev; - device_enable_async_suspend(&shost->shost_gendev); - error = device_add(&shost->shost_gendev); if (error) goto out; + pm_runtime_set_active(&shost->shost_gendev); + pm_runtime_enable(&shost->shost_gendev); + device_enable_async_suspend(&shost->shost_gendev); + scsi_host_set_state(shost, SHOST_RUNNING); get_device(shost->shost_gendev.parent); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c60cffbefa3c..2bf98469dc4c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1775,6 +1775,14 @@ int scsi_error_handler(void *data) * what we need to do to get it up and online again (if we can). * If we fail, we end up taking the thing offline. */ + if (scsi_autopm_get_host(shost) != 0) { + SCSI_LOG_ERROR_RECOVERY(1, + printk(KERN_ERR "Error handler scsi_eh_%d " + "unable to autoresume\n", + shost->host_no)); + continue; + } + if (shost->transportt->eh_strategy_handler) shost->transportt->eh_strategy_handler(shost); else @@ -1788,6 +1796,7 @@ int scsi_error_handler(void *data) * which are still online. */ scsi_restart_operations(shost); + scsi_autopm_put_host(shost); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); @@ -1885,12 +1894,16 @@ scsi_reset_provider_done_command(struct scsi_cmnd *scmd) int scsi_reset_provider(struct scsi_device *dev, int flag) { - struct scsi_cmnd *scmd = scsi_get_command(dev, GFP_KERNEL); + struct scsi_cmnd *scmd; struct Scsi_Host *shost = dev->host; struct request req; unsigned long flags; int rtn; + if (scsi_autopm_get_host(shost) < 0) + return FAILED; + + scmd = scsi_get_command(dev, GFP_KERNEL); blk_rq_init(NULL, &req); scmd->request = &req; @@ -1947,6 +1960,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scsi_run_host_queues(shost); scsi_next_command(scmd); + scsi_autopm_put_host(shost); return rtn; } EXPORT_SYMBOL(scsi_reset_provider); diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index cd83758ce0a2..d70e91ae60af 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -59,6 +59,12 @@ static int scsi_bus_resume_common(struct device *dev) if (scsi_is_sdev_device(dev)) err = scsi_dev_type_resume(dev); + + if (err == 0) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } return err; } @@ -86,6 +92,107 @@ static int scsi_bus_poweroff(struct device *dev) #endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_PM_RUNTIME + +static int scsi_runtime_suspend(struct device *dev) +{ + int err = 0; + + dev_dbg(dev, "scsi_runtime_suspend\n"); + if (scsi_is_sdev_device(dev)) { + err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND); + if (err == -EAGAIN) + pm_schedule_suspend(dev, jiffies_to_msecs( + round_jiffies_up_relative(HZ/10))); + } + + /* Insert hooks here for targets, hosts, and transport classes */ + + return err; +} + +static int scsi_runtime_resume(struct device *dev) +{ + int err = 0; + + dev_dbg(dev, "scsi_runtime_resume\n"); + if (scsi_is_sdev_device(dev)) + err = scsi_dev_type_resume(dev); + + /* Insert hooks here for targets, hosts, and transport classes */ + + return err; +} + +static int scsi_runtime_idle(struct device *dev) +{ + int err; + + dev_dbg(dev, "scsi_runtime_idle\n"); + + /* Insert hooks here for targets, hosts, and transport classes */ + + if (scsi_is_sdev_device(dev)) + err = pm_schedule_suspend(dev, 100); + else + err = pm_runtime_suspend(dev); + return err; +} + +int scsi_autopm_get_device(struct scsi_device *sdev) +{ + int err; + + err = pm_runtime_get_sync(&sdev->sdev_gendev); + if (err < 0) + pm_runtime_put_sync(&sdev->sdev_gendev); + else if (err > 0) + err = 0; + return err; +} +EXPORT_SYMBOL_GPL(scsi_autopm_get_device); + +void scsi_autopm_put_device(struct scsi_device *sdev) +{ + pm_runtime_put_sync(&sdev->sdev_gendev); +} +EXPORT_SYMBOL_GPL(scsi_autopm_put_device); + +void scsi_autopm_get_target(struct scsi_target *starget) +{ + pm_runtime_get_sync(&starget->dev); +} + +void scsi_autopm_put_target(struct scsi_target *starget) +{ + pm_runtime_put_sync(&starget->dev); +} + +int scsi_autopm_get_host(struct Scsi_Host *shost) +{ + int err; + + err = pm_runtime_get_sync(&shost->shost_gendev); + if (err < 0) + pm_runtime_put_sync(&shost->shost_gendev); + else if (err > 0) + err = 0; + return err; +} + +void scsi_autopm_put_host(struct Scsi_Host *shost) +{ + pm_runtime_put_sync(&shost->shost_gendev); +} + +#else + +#define scsi_runtime_suspend NULL +#define scsi_runtime_resume NULL +#define scsi_runtime_idle NULL + +#endif /* CONFIG_PM_RUNTIME */ + const struct dev_pm_ops scsi_bus_pm_ops = { .suspend = scsi_bus_suspend, .resume = scsi_bus_resume_common, @@ -93,4 +200,7 @@ const struct dev_pm_ops scsi_bus_pm_ops = { .thaw = scsi_bus_resume_common, .poweroff = scsi_bus_poweroff, .restore = scsi_bus_resume_common, + .runtime_suspend = scsi_runtime_suspend, + .runtime_resume = scsi_runtime_resume, + .runtime_idle = scsi_runtime_idle, }; diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index dddacc732550..026295e2c539 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -7,6 +7,7 @@ struct request_queue; struct request; struct scsi_cmnd; struct scsi_device; +struct scsi_target; struct scsi_host_template; struct Scsi_Host; struct scsi_nl_hdr; @@ -147,9 +148,20 @@ static inline void scsi_netlink_exit(void) {} /* scsi_pm.c */ #ifdef CONFIG_PM_OPS extern const struct dev_pm_ops scsi_bus_pm_ops; -#else +#else /* CONFIG_PM_OPS */ #define scsi_bus_pm_ops (*NULL) #endif +#ifdef CONFIG_PM_RUNTIME +extern void scsi_autopm_get_target(struct scsi_target *); +extern void scsi_autopm_put_target(struct scsi_target *); +extern int scsi_autopm_get_host(struct Scsi_Host *); +extern void scsi_autopm_put_host(struct Scsi_Host *); +#else +static inline void scsi_autopm_get_target(struct scsi_target *t) {} +static inline void scsi_autopm_put_target(struct scsi_target *t) {} +static inline int scsi_autopm_get_host(struct Scsi_Host *h) { return 0; } +static inline void scsi_autopm_put_host(struct Scsi_Host *h) {} +#endif /* CONFIG_PM_RUNTIME */ /* * internal scsi timeout functions: for use by mid-layer and transport diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 1c027a97d8b9..3d0a1e6e9c48 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1513,14 +1513,18 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, starget = scsi_alloc_target(parent, channel, id); if (!starget) return ERR_PTR(-ENOMEM); + scsi_autopm_get_target(starget); mutex_lock(&shost->scan_mutex); if (!shost->async_scan) scsi_complete_async_scans(); - if (scsi_host_scan_allowed(shost)) + if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); + scsi_autopm_put_host(shost); + } mutex_unlock(&shost->scan_mutex); + scsi_autopm_put_target(starget); scsi_target_reap(starget); put_device(&starget->dev); @@ -1574,6 +1578,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, starget = scsi_alloc_target(parent, channel, id); if (!starget) return; + scsi_autopm_get_target(starget); if (lun != SCAN_WILD_CARD) { /* @@ -1599,6 +1604,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, } out_reap: + scsi_autopm_put_target(starget); /* now determine if the target has any children at all * and if not, nuke it */ scsi_target_reap(starget); @@ -1633,8 +1639,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel, if (!shost->async_scan) scsi_complete_async_scans(); - if (scsi_host_scan_allowed(shost)) + if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { __scsi_scan_target(parent, channel, id, lun, rescan); + scsi_autopm_put_host(shost); + } mutex_unlock(&shost->scan_mutex); } EXPORT_SYMBOL(scsi_scan_target); @@ -1686,7 +1694,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, if (!shost->async_scan) scsi_complete_async_scans(); - if (scsi_host_scan_allowed(shost)) { + if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { if (channel == SCAN_WILD_CARD) for (channel = 0; channel <= shost->max_channel; channel++) @@ -1694,6 +1702,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, rescan); else scsi_scan_channel(shost, channel, id, lun, rescan); + scsi_autopm_put_host(shost); } mutex_unlock(&shost->scan_mutex); @@ -1831,8 +1840,11 @@ static void do_scsi_scan_host(struct Scsi_Host *shost) static int do_scan_async(void *_data) { struct async_scan_data *data = _data; - do_scsi_scan_host(data->shost); + struct Scsi_Host *shost = data->shost; + + do_scsi_scan_host(shost); scsi_finish_async_scan(data); + scsi_autopm_put_host(shost); return 0; } @@ -1847,16 +1859,20 @@ void scsi_scan_host(struct Scsi_Host *shost) if (strncmp(scsi_scan_type, "none", 4) == 0) return; + if (scsi_autopm_get_host(shost) < 0) + return; data = scsi_prep_async_scan(shost); if (!data) { do_scsi_scan_host(shost); + scsi_autopm_put_host(shost); return; } p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); if (IS_ERR(p)) do_scan_async(data); + /* scsi_autopm_put_host(shost) is called in do_scan_async() */ } EXPORT_SYMBOL(scsi_scan_host); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 5f85f8e831f3..562fb3bce261 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -802,8 +803,6 @@ static int scsi_target_add(struct scsi_target *starget) if (starget->state != STARGET_CREATED) return 0; - device_enable_async_suspend(&starget->dev); - error = device_add(&starget->dev); if (error) { dev_err(&starget->dev, "target device_add failed, error %d\n", error); @@ -812,6 +811,10 @@ static int scsi_target_add(struct scsi_target *starget) transport_add_device(&starget->dev); starget->state = STARGET_RUNNING; + pm_runtime_set_active(&starget->dev); + pm_runtime_enable(&starget->dev); + device_enable_async_suspend(&starget->dev); + return 0; } @@ -841,7 +844,20 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) return error; transport_configure_device(&starget->dev); + device_enable_async_suspend(&sdev->sdev_gendev); + scsi_autopm_get_target(starget); + pm_runtime_set_active(&sdev->sdev_gendev); + pm_runtime_forbid(&sdev->sdev_gendev); + pm_runtime_enable(&sdev->sdev_gendev); + scsi_autopm_put_target(starget); + + /* The following call will keep sdev active indefinitely, until + * its driver does a corresponding scsi_autopm_pm_device(). Only + * drivers supporting autosuspend will do this. + */ + scsi_autopm_get_device(sdev); + error = device_add(&sdev->sdev_gendev); if (error) { printk(KERN_INFO "error 1\n"); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index d4549092400c..2968c6b83ddb 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -245,6 +245,10 @@ sg_open(struct inode *inode, struct file *filp) if (retval) goto sg_put; + retval = scsi_autopm_get_device(sdp->device); + if (retval) + goto sdp_put; + if (!((flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) { retval = -ENXIO; @@ -302,8 +306,11 @@ sg_open(struct inode *inode, struct file *filp) } retval = 0; error_out: - if (retval) + if (retval) { + scsi_autopm_put_device(sdp->device); +sdp_put: scsi_device_put(sdp->device); + } sg_put: if (sdp) sg_put_dev(sdp); @@ -327,6 +334,7 @@ sg_release(struct inode *inode, struct file *filp) sdp->exclude = 0; wake_up_interruptible(&sdp->o_excl_wait); + scsi_autopm_put_device(sdp->device); kref_put(&sfp->f_ref, sg_remove_sfp); return 0; } diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index d80b6dbed1ca..50cb34ffef11 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -381,6 +381,14 @@ extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, struct scsi_sense_hdr *, int timeout, int retries, int *resid); +#ifdef CONFIG_PM_RUNTIME +extern int scsi_autopm_get_device(struct scsi_device *); +extern void scsi_autopm_put_device(struct scsi_device *); +#else +static inline int scsi_autopm_get_device(struct scsi_device *d) { return 0; } +static inline void scsi_autopm_put_device(struct scsi_device *d) {} +#endif /* CONFIG_PM_RUNTIME */ + static inline int __must_check scsi_device_reprobe(struct scsi_device *sdev) { return device_reprobe(&sdev->sdev_gendev); -- cgit v1.2.3 From 478a8a0543021172220feeb0b39bb1b3e43c988f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 16 Jun 2010 14:52:17 -0400 Subject: [SCSI] sd: add support for runtime PM This patch (as1399) adds runtime-PM support to the sd driver. The support is unsophisticated: If a SCSI disk device is mounted, or if its device file is held open, then the device will not be runtime-suspended; otherwise it will (provided userspace gives permission by writing "auto" to the sysfs power/control attribute). In order to make this work, a dev_set_drvdata() call had to be moved from sd_probe_async() to sd_probe(). Also, a few lines of code were changed to use a local variable instead of recalculating the address of an embedded struct device. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8802e48bc063..cc8a1d1d915a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -759,6 +759,10 @@ static int sd_open(struct block_device *bdev, fmode_t mode) sdev = sdkp->device; + retval = scsi_autopm_get_device(sdev); + if (retval) + goto error_autopm; + /* * If the device is in error recovery, wait until it is done. * If the device is offline, then disallow any access to it. @@ -803,6 +807,8 @@ static int sd_open(struct block_device *bdev, fmode_t mode) return 0; error_out: + scsi_autopm_put_device(sdev); +error_autopm: scsi_disk_put(sdkp); return retval; } @@ -834,6 +840,8 @@ static int sd_release(struct gendisk *disk, fmode_t mode) * XXX and what if there are packets in flight and this close() * XXX is followed by a "rmmod sd_mod"? */ + + scsi_autopm_put_device(sdev); scsi_disk_put(sdkp); return 0; } @@ -2232,7 +2240,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) if (sdp->removable) gd->flags |= GENHD_FL_REMOVABLE; - dev_set_drvdata(dev, sdkp); add_disk(gd); sd_dif_config_host(sdkp); @@ -2240,6 +2247,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", sdp->removable ? "removable " : ""); + scsi_autopm_put_device(sdp); put_device(&sdkp->dev); } @@ -2317,14 +2325,15 @@ static int sd_probe(struct device *dev) } device_initialize(&sdkp->dev); - sdkp->dev.parent = &sdp->sdev_gendev; + sdkp->dev.parent = dev; sdkp->dev.class = &sd_disk_class; - dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev)); + dev_set_name(&sdkp->dev, dev_name(dev)); if (device_add(&sdkp->dev)) goto out_free_index; - get_device(&sdp->sdev_gendev); + get_device(dev); + dev_set_drvdata(dev, sdkp); get_device(&sdkp->dev); /* prevent release before async_schedule */ async_schedule(sd_probe_async, sdkp); @@ -2358,8 +2367,10 @@ static int sd_remove(struct device *dev) { struct scsi_disk *sdkp; - async_synchronize_full(); sdkp = dev_get_drvdata(dev); + scsi_autopm_get_device(sdkp->device); + + async_synchronize_full(); blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); device_del(&sdkp->dev); del_gendisk(sdkp->disk); -- cgit v1.2.3 From ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4 Mon Sep 17 00:00:00 2001 From: Felix Beck Date: Fri, 16 Jul 2010 15:37:42 +0200 Subject: [SCSI] zfcp: Introduce experimental support for DIF/DIX Introduce support for DIF/DIX in zfcp: Report the capabilities for the Scsi_host, map the protection data when issuing I/O requests and handle the new error codes. Also add the fsf data_direction field to the hba trace, it is useful information for debugging in that area. This is an EXPERIMENTAL feature for now. Signed-off-by: Felix Beck Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 3 ++ drivers/s390/scsi/zfcp_dbf.h | 1 + drivers/s390/scsi/zfcp_ext.h | 2 + drivers/s390/scsi/zfcp_fc.h | 3 ++ drivers/s390/scsi/zfcp_fsf.c | 109 +++++++++++++++++++++++++++++++++--------- drivers/s390/scsi/zfcp_fsf.h | 24 ++++++++-- drivers/s390/scsi/zfcp_qdio.c | 4 -- drivers/s390/scsi/zfcp_qdio.h | 16 +++++++ drivers/s390/scsi/zfcp_scsi.c | 53 ++++++++++++++++++++ drivers/scsi/Kconfig | 4 ++ 10 files changed, 189 insertions(+), 30 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a08d33a96ec9..a86117b0d6e1 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -155,6 +155,8 @@ void _zfcp_dbf_hba_fsf_response(const char *tag2, int level, if (scsi_cmnd) { response->u.fcp.cmnd = (unsigned long)scsi_cmnd; response->u.fcp.serial = scsi_cmnd->serial_number; + response->u.fcp.data_dir = + qtcb->bottom.io.data_direction; } break; @@ -326,6 +328,7 @@ static void zfcp_dbf_hba_view_response(char **p, case FSF_QTCB_FCP_CMND: if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) break; + zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir); zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial); *p += sprintf(*p, "\n"); diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 457e046f2d28..2bcc3403126a 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -111,6 +111,7 @@ struct zfcp_dbf_hba_record_response { struct { u64 cmnd; u64 serial; + u32 data_dir; } fcp; struct { u64 wwpn; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index a8bb7488dc98..de0925f25dcc 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -164,6 +164,8 @@ extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); extern void zfcp_scsi_scan(struct zfcp_unit *); extern void zfcp_scsi_scan_work(struct work_struct *); +extern void zfcp_scsi_set_prot(struct zfcp_adapter *); +extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int); /* zfcp_sysfs.c */ extern struct attribute_group zfcp_sysfs_unit_attrs; diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h index 85c37d2b82c2..938d50360166 100644 --- a/drivers/s390/scsi/zfcp_fc.h +++ b/drivers/s390/scsi/zfcp_fc.h @@ -220,6 +220,9 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi) memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len); fcp->fc_dl = scsi_bufflen(scsi); + + if (scsi_get_prot_type(scsi) == SCSI_PROT_DIF_TYPE1) + fcp->fc_dl += fcp->fc_dl / scsi->device->sector_size * 8; } /** diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 63402fd5f9ae..f9be5d60d92a 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -526,6 +526,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) return -EIO; } + zfcp_scsi_set_prot(adapter); + return 0; } @@ -988,6 +990,7 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, sg_req); if (bytes <= 0) return -EIO; + zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req); req->qtcb->bottom.support.req_buf_length = bytes; zfcp_qdio_skip_to_last_sbale(&req->qdio_req); @@ -996,6 +999,7 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, req->qtcb->bottom.support.resp_buf_length = bytes; if (bytes <= 0) return -EIO; + zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req); return 0; } @@ -2038,9 +2042,13 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) blktrc.fabric_lat = lat_in->fabric_lat * ticks; switch (req->qtcb->bottom.io.data_direction) { + case FSF_DATADIR_DIF_READ_STRIP: + case FSF_DATADIR_DIF_READ_CONVERT: case FSF_DATADIR_READ: lat = &unit->latencies.read; break; + case FSF_DATADIR_DIF_WRITE_INSERT: + case FSF_DATADIR_DIF_WRITE_CONVERT: case FSF_DATADIR_WRITE: lat = &unit->latencies.write; break; @@ -2081,6 +2089,21 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) goto skip_fsfstatus; } + switch (req->qtcb->header.fsf_status) { + case FSF_INCONSISTENT_PROT_DATA: + case FSF_INVALID_PROT_PARM: + set_host_byte(scpnt, DID_ERROR); + goto skip_fsfstatus; + case FSF_BLOCK_GUARD_CHECK_FAILURE: + zfcp_scsi_dif_sense_error(scpnt, 0x1); + goto skip_fsfstatus; + case FSF_APP_TAG_CHECK_FAILURE: + zfcp_scsi_dif_sense_error(scpnt, 0x2); + goto skip_fsfstatus; + case FSF_REF_TAG_CHECK_FAILURE: + zfcp_scsi_dif_sense_error(scpnt, 0x3); + goto skip_fsfstatus; + } fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp; zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt); @@ -2190,6 +2213,44 @@ skip_fsfstatus: } } +static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir) +{ + switch (scsi_get_prot_op(scsi_cmnd)) { + case SCSI_PROT_NORMAL: + switch (scsi_cmnd->sc_data_direction) { + case DMA_NONE: + *data_dir = FSF_DATADIR_CMND; + break; + case DMA_FROM_DEVICE: + *data_dir = FSF_DATADIR_READ; + break; + case DMA_TO_DEVICE: + *data_dir = FSF_DATADIR_WRITE; + break; + case DMA_BIDIRECTIONAL: + return -EINVAL; + } + break; + + case SCSI_PROT_READ_STRIP: + *data_dir = FSF_DATADIR_DIF_READ_STRIP; + break; + case SCSI_PROT_WRITE_INSERT: + *data_dir = FSF_DATADIR_DIF_WRITE_INSERT; + break; + case SCSI_PROT_READ_PASS: + *data_dir = FSF_DATADIR_DIF_READ_CONVERT; + break; + case SCSI_PROT_WRITE_PASS: + *data_dir = FSF_DATADIR_DIF_WRITE_CONVERT; + break; + default: + return -EINVAL; + } + + return 0; +} + /** * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) * @unit: unit where command is sent to @@ -2201,9 +2262,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, struct zfcp_fsf_req *req; struct fcp_cmnd *fcp_cmnd; unsigned int sbtype = SBAL_FLAGS0_TYPE_READ; - int real_bytes, retval = -EIO; + int real_bytes, retval = -EIO, dix_bytes = 0; struct zfcp_adapter *adapter = unit->port->adapter; struct zfcp_qdio *qdio = adapter->qdio; + struct fsf_qtcb_bottom_io *io; if (unlikely(!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_UNBLOCKED))) @@ -2226,46 +2288,46 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, goto out; } + scsi_cmnd->host_scribble = (unsigned char *) req->req_id; + + io = &req->qtcb->bottom.io; req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; req->unit = unit; req->data = scsi_cmnd; req->handler = zfcp_fsf_send_fcp_command_handler; req->qtcb->header.lun_handle = unit->handle; req->qtcb->header.port_handle = unit->port->handle; - req->qtcb->bottom.io.service_class = FSF_CLASS_3; - req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN; + io->service_class = FSF_CLASS_3; + io->fcp_cmnd_length = FCP_CMND_LEN; - scsi_cmnd->host_scribble = (unsigned char *) req->req_id; - - /* - * set depending on data direction: - * data direction bits in SBALE (SB Type) - * data direction bits in QTCB - */ - switch (scsi_cmnd->sc_data_direction) { - case DMA_NONE: - req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; - break; - case DMA_FROM_DEVICE: - req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ; - break; - case DMA_TO_DEVICE: - req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE; - break; - case DMA_BIDIRECTIONAL: - goto failed_scsi_cmnd; + if (scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) { + io->data_block_length = scsi_cmnd->device->sector_size; + io->ref_tag_value = scsi_get_lba(scsi_cmnd) & 0xFFFFFFFF; } + zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction); + get_device(&unit->dev); fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd); + if (scsi_prot_sg_count(scsi_cmnd)) { + zfcp_qdio_set_data_div(qdio, &req->qdio_req, + scsi_prot_sg_count(scsi_cmnd)); + dix_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, + scsi_prot_sglist(scsi_cmnd)); + io->prot_data_length = dix_bytes; + } + real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, scsi_sglist(scsi_cmnd)); - if (unlikely(real_bytes < 0)) + + if (unlikely(real_bytes < 0) || unlikely(dix_bytes < 0)) goto failed_scsi_cmnd; + zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req); + retval = zfcp_fsf_req_send(req); if (unlikely(retval)) goto failed_scsi_cmnd; @@ -2389,6 +2451,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, zfcp_fsf_req_free(req); goto out; } + zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req); zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index ca110e386761..db8c85382dca 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -80,11 +80,15 @@ #define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 #define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 #define FSF_SBAL_MISMATCH 0x00000063 +#define FSF_INCONSISTENT_PROT_DATA 0x00000070 +#define FSF_INVALID_PROT_PARM 0x00000071 +#define FSF_BLOCK_GUARD_CHECK_FAILURE 0x00000081 +#define FSF_APP_TAG_CHECK_FAILURE 0x00000082 +#define FSF_REF_TAG_CHECK_FAILURE 0x00000083 #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD #define FSF_UNKNOWN_COMMAND 0x000000E2 #define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3 #define FSF_INVALID_COMMAND_OPTION 0x000000E5 -/* #define FSF_ERROR 0x000000FF */ #define FSF_PROT_STATUS_QUAL_SIZE 16 #define FSF_STATUS_QUALIFIER_SIZE 16 @@ -147,6 +151,13 @@ #define FSF_DATADIR_WRITE 0x00000001 #define FSF_DATADIR_READ 0x00000002 #define FSF_DATADIR_CMND 0x00000004 +#define FSF_DATADIR_DIF_WRITE_INSERT 0x00000009 +#define FSF_DATADIR_DIF_READ_STRIP 0x0000000a +#define FSF_DATADIR_DIF_WRITE_CONVERT 0x0000000b +#define FSF_DATADIR_DIF_READ_CONVERT 0X0000000c + +/* data protection control flags */ +#define FSF_APP_TAG_CHECK_ENABLE 0x10 /* fc service class */ #define FSF_CLASS_3 0x00000003 @@ -162,6 +173,8 @@ #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 #define FSF_FEATURE_UPDATE_ALERT 0x00000100 #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 +#define FSF_FEATURE_DIF_PROT_TYPE1 0x00010000 +#define FSF_FEATURE_DIX_PROT_TCPIP 0x00020000 /* host connection features */ #define FSF_FEATURE_NPIV_MODE 0x00000001 @@ -316,9 +329,14 @@ struct fsf_qtcb_header { struct fsf_qtcb_bottom_io { u32 data_direction; u32 service_class; - u8 res1[8]; + u8 res1; + u8 data_prot_flags; + u16 app_tag_value; + u32 ref_tag_value; u32 fcp_cmnd_length; - u8 res2[12]; + u32 data_block_length; + u32 prot_data_length; + u8 res2[4]; u8 fcp_cmnd[FSF_FCP_CMND_SIZE]; u8 fcp_rsp[FSF_FCP_RSP_SIZE]; u8 res3[64]; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index c4559b29bebc..aceced8ec7e4 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -193,10 +193,6 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, bytes += sg->length; } - /* assume that no other SBALEs are to follow in the same SBAL */ - sbale = zfcp_qdio_sbale_curr(qdio, q_req); - sbale->flags |= SBAL_FLAGS_LAST_ENTRY; - return bytes; } diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h index 10d0df99dbf4..2297d8d3e947 100644 --- a/drivers/s390/scsi/zfcp_qdio.h +++ b/drivers/s390/scsi/zfcp_qdio.h @@ -215,4 +215,20 @@ void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio, QDIO_MAX_BUFFERS_PER_Q; } +/** + * zfcp_qdio_set_data_div - set data division count + * @qdio: pointer to struct zfcp_qdio + * @q_req: The current zfcp_qdio_req + * @count: The data division count + */ +static inline +void zfcp_qdio_set_data_div(struct zfcp_qdio *qdio, + struct zfcp_qdio_req *q_req, u32 count) +{ + struct qdio_buffer_element *sbale; + + sbale = &qdio->req_q[q_req->sbal_first]->element[0]; + sbale->length = count; +} + #endif /* ZFCP_QDIO_H */ diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index eb471a1723cd..cb000c9833bb 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "zfcp_ext.h" #include "zfcp_dbf.h" @@ -22,6 +23,13 @@ static unsigned int default_depth = 32; module_param_named(queue_depth, default_depth, uint, 0600); MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices"); +static bool enable_dif; + +#ifdef CONFIG_ZFCP_DIF +module_param_named(dif, enable_dif, bool, 0600); +MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support"); +#endif + static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) { @@ -652,6 +660,51 @@ void zfcp_scsi_scan_work(struct work_struct *work) put_device(&unit->dev); } +/** + * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host + * @adapter: The adapter where to configure DIF/DIX for the SCSI host + */ +void zfcp_scsi_set_prot(struct zfcp_adapter *adapter) +{ + unsigned int mask = 0; + unsigned int data_div; + struct Scsi_Host *shost = adapter->scsi_host; + + data_div = atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED; + + if (enable_dif && + adapter->adapter_features & FSF_FEATURE_DIF_PROT_TYPE1) + mask |= SHOST_DIF_TYPE1_PROTECTION; + + if (enable_dif && data_div && + adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) { + mask |= SHOST_DIX_TYPE1_PROTECTION; + scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP); + shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2; + shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2; + } + + scsi_host_set_prot(shost, mask); +} + +/** + * zfcp_scsi_dif_sense_error - Report DIF/DIX error as driver sense error + * @scmd: The SCSI command to report the error for + * @ascq: The ASCQ to put in the sense buffer + * + * See the error handling in sd_done for the sense codes used here. + * Set DID_SOFT_ERROR to retry the request, if possible. + */ +void zfcp_scsi_dif_sense_error(struct scsi_cmnd *scmd, int ascq) +{ + scsi_build_sense_buffer(1, scmd->sense_buffer, + ILLEGAL_REQUEST, 0x10, ascq); + set_driver_byte(scmd, DRIVER_SENSE); + scmd->result |= SAM_STAT_CHECK_CONDITION; + set_host_byte(scmd, DID_SOFT_ERROR); +} + struct fc_function_template zfcp_transport_functions = { .show_starget_port_id = 1, .show_starget_port_name = 1, diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 75f2336807cb..158284f05732 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1847,6 +1847,10 @@ config ZFCP called zfcp. If you want to compile it as a module, say M here and read . +config ZFCP_DIF + tristate "T10 DIF/DIX support for the zfcp driver (EXPERIMENTAL)" + depends on ZFCP && EXPERIMENTAL + config SCSI_PMCRAID tristate "PMC SIERRA Linux MaxRAID adapter support" depends on PCI && SCSI -- cgit v1.2.3 From ac8b422838046ffc26be4874a3cbae0d313f4209 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 21 Jul 2010 22:38:13 +0200 Subject: pcmcia: remove cs_types.h Remove cs_types.h which is no longer needed: Most definitions aren't used at all, a few can be made away with, and two remaining definitions (typedefs, unfortunatley) may be moved to more specific places. CC: linux-ide@vger.kernel.org CC: linux-usb@vger.kernel.org CC: laforge@gnumonks.org CC: linux-mtd@lists.infradead.org CC: alsa-devel@alsa-project.org CC: linux-serial@vger.kernel.org Acked-by: Marcel Holtmann (for drivers/bluetooth/) Acked-by: David S. Miller Signed-off-by: Dominik Brodowski --- Documentation/pcmcia/driver-changes.txt | 5 +++ drivers/ata/pata_pcmcia.c | 1 - drivers/bluetooth/bluecard_cs.c | 1 - drivers/bluetooth/bt3c_cs.c | 1 - drivers/bluetooth/btuart_cs.c | 1 - drivers/bluetooth/dtl1_cs.c | 1 - drivers/char/pcmcia/cm4000_cs.c | 1 - drivers/char/pcmcia/cm4040_cs.c | 1 - drivers/char/pcmcia/ipwireless/main.h | 1 - drivers/char/pcmcia/ipwireless/tty.h | 1 - drivers/char/pcmcia/synclink_cs.c | 1 - drivers/ide/ide-cs.c | 1 - drivers/isdn/hardware/avm/avm_cs.c | 1 - drivers/isdn/hisax/avma1_cs.c | 1 - drivers/isdn/hisax/elsa_cs.c | 1 - drivers/isdn/hisax/sedlbauer_cs.c | 1 - drivers/isdn/hisax/teles_cs.c | 1 - drivers/mmc/host/sdricoh_cs.c | 1 - drivers/mtd/maps/pcmciamtd.c | 1 - drivers/net/pcmcia/3c574_cs.c | 1 - drivers/net/pcmcia/3c589_cs.c | 1 - drivers/net/pcmcia/axnet_cs.c | 1 - drivers/net/pcmcia/com20020_cs.c | 1 - drivers/net/pcmcia/fmvj18x_cs.c | 1 - drivers/net/pcmcia/ibmtr_cs.c | 1 - drivers/net/pcmcia/nmclan_cs.c | 1 - drivers/net/pcmcia/pcnet_cs.c | 5 +-- drivers/net/pcmcia/smc91c92_cs.c | 1 - drivers/net/pcmcia/xirc2ps_cs.c | 1 - drivers/net/wireless/airo_cs.c | 1 - drivers/net/wireless/atmel_cs.c | 1 - drivers/net/wireless/b43/pcmcia.c | 1 - drivers/net/wireless/hostap/hostap_cs.c | 3 +- drivers/net/wireless/libertas/if_cs.c | 1 - drivers/net/wireless/orinoco/orinoco_cs.c | 1 - drivers/net/wireless/orinoco/spectrum_cs.c | 1 - drivers/net/wireless/ray_cs.c | 1 - drivers/net/wireless/wl3501_cs.c | 10 +----- drivers/parport/parport_cs.c | 1 - drivers/pcmcia/au1000_generic.h | 1 - drivers/pcmcia/au1000_pb1x00.c | 2 -- drivers/pcmcia/cistpl.c | 1 - drivers/pcmcia/cs.c | 1 - drivers/pcmcia/db1xxx_ss.c | 1 - drivers/pcmcia/ds.c | 1 - drivers/pcmcia/i82092.c | 1 - drivers/pcmcia/i82365.c | 1 - drivers/pcmcia/m32r_cfc.c | 1 - drivers/pcmcia/m32r_pcc.c | 1 - drivers/pcmcia/m8xx_pcmcia.c | 1 - drivers/pcmcia/pcmcia_cis.c | 1 - drivers/pcmcia/pcmcia_resource.c | 1 - drivers/pcmcia/pd6729.c | 1 - drivers/pcmcia/pxa2xx_base.c | 1 - drivers/pcmcia/rsrc_iodyn.c | 1 - drivers/pcmcia/rsrc_mgr.c | 1 - drivers/pcmcia/rsrc_nonstatic.c | 1 - drivers/pcmcia/sa1100_generic.c | 1 - drivers/pcmcia/soc_common.h | 1 - drivers/pcmcia/socket_sysfs.c | 1 - drivers/pcmcia/tcic.c | 1 - drivers/pcmcia/xxs1500_ss.c | 1 - drivers/pcmcia/yenta_socket.c | 1 - drivers/scsi/pcmcia/aha152x_stub.c | 1 - drivers/scsi/pcmcia/fdomain_stub.c | 1 - drivers/scsi/pcmcia/nsp_cs.c | 1 - drivers/scsi/pcmcia/qlogic_stub.c | 1 - drivers/scsi/pcmcia/sym53c500_cs.c | 1 - drivers/serial/serial_cs.c | 1 - drivers/ssb/main.c | 1 - drivers/ssb/pcmcia.c | 1 - drivers/ssb/scan.c | 1 - drivers/staging/comedi/drivers/cb_das16_cs.c | 1 - drivers/staging/comedi/drivers/das08_cs.c | 1 - drivers/staging/comedi/drivers/ni_daq_700.c | 1 - drivers/staging/comedi/drivers/ni_daq_dio24.c | 1 - drivers/staging/comedi/drivers/ni_labpc_cs.c | 1 - drivers/staging/comedi/drivers/ni_mio_cs.c | 1 - drivers/staging/comedi/drivers/quatech_daqp_cs.c | 1 - drivers/staging/wlags49_h2/wl_cs.c | 1 - drivers/staging/wlags49_h2/wl_internal.h | 1 - drivers/telephony/ixj_pcmcia.c | 1 - drivers/usb/host/sl811_cs.c | 5 +-- include/pcmcia/cistpl.h | 2 ++ include/pcmcia/cs.h | 10 +----- include/pcmcia/cs_types.h | 40 ------------------------ include/pcmcia/ds.h | 3 +- include/pcmcia/ss.h | 1 - sound/pcmcia/pdaudiocf/pdaudiocf.h | 1 - sound/pcmcia/vx/vxpocket.h | 1 - 90 files changed, 14 insertions(+), 151 deletions(-) delete mode 100644 include/pcmcia/cs_types.h (limited to 'drivers/scsi') diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt index 61bc4e943116..ff5f0be2470a 100644 --- a/Documentation/pcmcia/driver-changes.txt +++ b/Documentation/pcmcia/driver-changes.txt @@ -1,4 +1,9 @@ This file details changes in 2.6 which affect PCMCIA card driver authors: +* No dev_info_t, no cs_types.h (as of 2.6.36) + dev_info_t and a few other typedefs are removed. No longer use them + in PCMCIA device drivers. Also, do not include pcmcia/cs_types.h, as + this file is gone. + * No dev_node_t (as of 2.6.35) There is no more need to fill out a "dev_node_t" structure. diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 118c28e8abaf..3dcb2b1b60e9 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 6d34f405a2f3..eb085de16713 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -39,7 +39,6 @@ #include #include -#include #include #include #include diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 21e05fdc9121..457b603f8678 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -45,7 +45,6 @@ #include #include -#include #include #include #include diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 4ed7288f99db..e7e0a17aecc2 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index ef044d55cb25..7c94aad0b791 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index e7956acf2ad6..a8be2a7906e0 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index c0775c844e08..44adae98c576 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h index 96d0ef31b172..c207be87b597 100644 --- a/drivers/char/pcmcia/ipwireless/main.h +++ b/drivers/char/pcmcia/ipwireless/main.h @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h index 4da6c201f727..3e163d4cab15 100644 --- a/drivers/char/pcmcia/ipwireless/tty.h +++ b/drivers/char/pcmcia/ipwireless/tty.h @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 308903ec8bf8..522992ed6e49 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -70,7 +70,6 @@ #include #include -#include #include #include #include diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index 0b7815d2581c..27dbab84142c 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c @@ -43,7 +43,6 @@ #include #include -#include #include #include #include diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index f410d0eb2fef..e804a01ecdfb 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index a80a7617f16f..49e141e49aaf 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 218927e3a4ea..425deea1dd69 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 1f4feaab21af..5dbad966a29e 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 5771955cc532..d3fb1b716800 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c index e7507af3856e..7aa65bb2af4a 100644 --- a/drivers/mmc/host/sdricoh_cs.c +++ b/drivers/mmc/host/sdricoh_cs.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index e699e6ac23df..79488164e432 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 10ee106a1617..e249b898075c 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -87,7 +87,6 @@ earlier 3Com products. #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index ce63c3773b4c..b0772df31057 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 33525bf2a3d3..467fd4bfb2bd 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -39,7 +39,6 @@ #include #include "../8390.h" -#include #include #include #include diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 5643f94541bc..99957af40329 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -43,7 +43,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 7c27c50211a5..95a991beaa30 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -49,7 +49,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 67ee9851a8ed..c36dcd14ec45 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -57,7 +57,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 9b63dec549cb..c0eacfae1512 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -146,7 +146,6 @@ Include Files #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index bfdef72c5d5e..db6dbdabb702 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -42,7 +42,6 @@ #include #include "../8390.h" -#include #include #include #include @@ -113,8 +112,6 @@ static int setup_dma_config(struct pcmcia_device *link, int start_pg, static void pcnet_detach(struct pcmcia_device *p_dev); -static dev_info_t dev_info = "pcnet_cs"; - /*====================================================================*/ typedef struct hw_info_t { @@ -956,7 +953,7 @@ static int pcnet_open(struct net_device *dev) set_misc_reg(dev); outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */ - ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev); + ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev->name, dev); if (ret) return ret; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 307cd1721e91..88f503a80a8e 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -44,7 +44,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index b6c3644888cd..a7662f0832eb 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -82,7 +82,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 33bdc6a84e81..9389ba004fb9 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index c2746fc7f2be..91ee74a8801e 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -42,7 +42,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 0e99b634267c..f71bc7821378 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 29b31a694b59..2f4b6d4350ab 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -23,7 +22,7 @@ #include "hostap_wlan.h" -static dev_info_t dev_info = "hostap_cs"; +static char *dev_info = "hostap_cs"; MODULE_AUTHOR("Jouni Malinen"); MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 08e4e3908003..1d3a7e0e5f10 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index b16d5db52a4d..41ca4f1b395f 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index b51a9adc80f6..cad30e499dba 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index abff8934db13..165beb6af849 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 376c6b964a9c..35f431bf97d6 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -48,7 +48,6 @@ #include -#include #include #include #include @@ -89,13 +88,6 @@ static int wl3501_config(struct pcmcia_device *link); static void wl3501_release(struct pcmcia_device *link); -/* - * The dev_info variable is the "key" that is used to match up this - * device driver with appropriate cards, through the card configuration - * database. - */ -static dev_info_t wl3501_dev_info = "wl3501_cs"; - static const struct { int reg_domain; int min, max, deflt; @@ -1421,7 +1413,7 @@ static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev) static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strlcpy(info->driver, wl3501_dev_info, sizeof(info->driver)); + strlcpy(info->driver, "wl3501_cs", sizeof(info->driver)); } static const struct ethtool_ops ops = { diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index fd8cfe95f0a3..ee56fd66d5dc 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -48,7 +48,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h index a324d329dea6..67530cefcf3c 100644 --- a/drivers/pcmcia/au1000_generic.h +++ b/drivers/pcmcia/au1000_generic.h @@ -23,7 +23,6 @@ /* include the world */ -#include #include #include #include diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index 5a979cb8f3e6..807f2d75dad3 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c @@ -31,11 +31,9 @@ #include #include -#include #include #include #include -#include #include #include diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 8844bc3e3118..ba4a5acc2e9a 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index efa30b84a75a..2ec8ac97445c 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c index 0f4cc3f00028..27575e6378a1 100644 --- a/drivers/pcmcia/db1xxx_ss.c +++ b/drivers/pcmcia/db1xxx_ss.c @@ -29,7 +29,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 08617719d3a1..bacfc55f2026 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 3003bb3dfcc0..05d0879ce935 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -15,7 +15,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 9e2a15628de5..61746bd598b3 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -50,7 +50,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 7e16ed8eb0a4..24de49925863 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c @@ -26,7 +26,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index 6c5c3f910d71..8e4723844ad3 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c @@ -27,7 +27,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 25e5e30a18af..f2f90a7d3e12 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c @@ -59,7 +59,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c index 4a65eaf96b0a..0ac54da15885 100644 --- a/drivers/pcmcia/pcmcia_cis.c +++ b/drivers/pcmcia/pcmcia_cis.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index a4cd9adfcbc0..2394de468602 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -25,7 +25,6 @@ #include -#include #include #include #include diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index b61a13663a0a..b8a869af0f44 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -17,7 +17,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index df4532e91b1a..66c022579d9b 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -32,7 +32,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c index 6ed7bf171ca3..3b1dce2df26a 100644 --- a/drivers/pcmcia/rsrc_iodyn.c +++ b/drivers/pcmcia/rsrc_iodyn.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index b12ecf7c32bf..b433a7995651 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 13245a2986f3..0cca08ff65a8 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -28,7 +28,6 @@ #include -#include #include #include #include diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index edbd8c472628..e09851480295 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -35,7 +35,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h index e40824ce6b0b..3fba3a679128 100644 --- a/drivers/pcmcia/soc_common.h +++ b/drivers/pcmcia/soc_common.h @@ -11,7 +11,6 @@ /* include the world */ #include -#include #include #include #include diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 80e36bc407da..cb0d3ace18bd 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 56004a1b5bba..be0d841c7ebd 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -49,7 +49,6 @@ #include #include -#include #include #include #include "tcic.h" diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c index 201ccfa1e97b..fa88c360c37a 100644 --- a/drivers/pcmcia/xxs1500_ss.c +++ b/drivers/pcmcia/xxs1500_ss.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index f1d41374eea7..414d9a6f9a32 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -19,7 +19,6 @@ #include #include -#include #include #include diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 9d70aef99227..b07b53ef3c00 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -49,7 +49,6 @@ #include #include "aha152x.h" -#include #include #include #include diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 21b141151dfc..ee0489762539 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -46,7 +46,6 @@ #include #include "fdomain.h" -#include #include #include #include diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 0f0e112c3f8e..d4142075be21 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -47,7 +47,6 @@ #include #include -#include #include #include #include diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index f0fc6baed9fc..c1cf7f43313b 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -48,7 +48,6 @@ #include #include "../qlogicfas408.h" -#include #include #include #include diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index a51164171179..bd79e45ab856 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -71,7 +71,6 @@ #include #include -#include #include #include #include diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index ab17c08ddc03..2b99c7baf35b 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -45,7 +45,6 @@ #include #include -#include #include #include #include diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 51275aac5b34..06f04b42cb23 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index e72f4046a5e0..21520308178b 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 0d6c0280eb34..9738cad4ba13 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index cfeb11f443e3..acef29ca212b 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -37,7 +37,6 @@ Status: experimental #include #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 8761a6d285dc..3eddb7c4b1b0 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -48,7 +48,6 @@ Command support does not exist, but could be added for this board. #include "das08.h" /* pcmcia includes */ -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 6ec77bf88c63..f3c4d2f929f8 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -47,7 +47,6 @@ IRQ is assigned but not used. #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index e4865b1c2310..f0c4367dc10b 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -48,7 +48,6 @@ the PCMCIA interface. #include "8255.h" -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 163245ebb311..1ee78f806ed2 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -71,7 +71,6 @@ NI manuals: #include "comedi_fc.h" #include "ni_labpc.h" -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 3a46f0c0bff9..0bce220c47b5 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -48,7 +48,6 @@ See the notes in the ni_atmio.o driver. #include "ni_stc.h" #include "8255.h" -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index a91db6c42028..67c0fa6a2b06 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -50,7 +50,6 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308 #include "../comedidev.h" #include -#include #include #include #include diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c index 10abd406b09b..afe457541172 100644 --- a/drivers/staging/wlags49_h2/wl_cs.c +++ b/drivers/staging/wlags49_h2/wl_cs.c @@ -83,7 +83,6 @@ #include #include -#include #include #include #include diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h index d9a0ad039c19..02f0a20e178a 100644 --- a/drivers/staging/wlags49_h2/wl_internal.h +++ b/drivers/staging/wlags49_h2/wl_internal.h @@ -69,7 +69,6 @@ ******************************************************************************/ #include #ifdef BUS_PCMCIA -#include #include #include #include diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 99cb2246ac72..f6c7e6fd7ee1 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -8,7 +8,6 @@ #include /* error codes */ #include -#include #include #include #include diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 58cb73c8420a..acb7e255a837 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -43,8 +42,6 @@ MODULE_LICENSE("GPL"); /* VARIABLES */ /*====================================================================*/ -static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; - typedef struct local_info_t { struct pcmcia_device *p_dev; } local_info_t; @@ -246,7 +243,7 @@ MODULE_DEVICE_TABLE(pcmcia, sl811_ids); static struct pcmcia_driver sl811_cs_driver = { .owner = THIS_MODULE, .drv = { - .name = (char *)driver_name, + .name = "sl811_cs", }, .probe = sl811_cs_probe, .remove = sl811_cs_detach, diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h index cfdd5af77dcc..1c5088c9f7bf 100644 --- a/include/pcmcia/cistpl.h +++ b/include/pcmcia/cistpl.h @@ -15,6 +15,8 @@ #ifndef _LINUX_CISTPL_H #define _LINUX_CISTPL_H +typedef unsigned char cisdata_t; + #define CISTPL_NULL 0x00 #define CISTPL_DEVICE 0x01 #define CISTPL_LONGLINK_CB 0x02 diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index c943c967ac7a..c78d9b112080 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -43,14 +43,6 @@ typedef struct conf_reg_t { #define CV_COPY_VALUE 0x08 #define CV_EXT_STATUS 0x10 -/* For GetFirst/NextClient */ -typedef struct client_req_t { - socket_t Socket; - u_int Attributes; -} client_req_t; - -#define CLIENT_THIS_SOCKET 0x01 - /* ModifyConfiguration */ typedef struct modconf_t { u_int Attributes; @@ -133,7 +125,7 @@ typedef struct io_req_t { /* For GetMemPage, MapMemPage */ typedef struct memreq_t { u_int CardOffset; - page_t Page; + u_short Page; } memreq_t; /* For ModifyWindow */ diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h deleted file mode 100644 index f5e3b8386c8f..000000000000 --- a/include/pcmcia/cs_types.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * cs_types.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * (C) 1999 David A. Hinds - */ - -#ifndef _LINUX_CS_TYPES_H -#define _LINUX_CS_TYPES_H - -#ifdef __KERNEL__ -#include -#else -#include -#endif - -typedef u_short socket_t; -typedef u_int event_t; -typedef u_char cisdata_t; -typedef u_short page_t; - -typedef unsigned long window_handle_t; - -struct region_t; -typedef struct region_t *memory_handle_t; - -#ifndef DEV_NAME_LEN -#define DEV_NAME_LEN 32 -#endif - -typedef char dev_info_t[DEV_NAME_LEN]; - -#endif /* _LINUX_CS_TYPES_H */ diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 7d7721e86032..e614aa0ca2a2 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -20,7 +20,6 @@ #include #endif -#include #include #ifdef __KERNEL__ @@ -37,6 +36,8 @@ struct pcmcia_device; struct config_t; struct net_device; +typedef unsigned long window_handle_t; + /* dynamic device IDs for PCMCIA device drivers. See * Documentation/pcmcia/driver.txt for details. */ diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index aeac27109839..626b63c33d9e 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -19,7 +19,6 @@ #include /* task_struct, completion */ #include -#include #include #ifdef CONFIG_CARDBUS #include diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h index a0a7ec64222a..5cc3e4573074 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.h +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h index ea4df16a28ef..d9110669d042 100644 --- a/sound/pcmcia/vx/vxpocket.h +++ b/sound/pcmcia/vx/vxpocket.h @@ -23,7 +23,6 @@ #include -#include #include #include #include -- cgit v1.2.3 From 9a017a910346afd88ec2e065989903bf211a7d37 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 24 Jul 2010 15:58:54 +0200 Subject: pcmcia: do not use io_req_t after call to pcmcia_request_io() After pcmcia_request_io(), do not make use of the values stored in io_req_t, but instead use those found in struct pcmcia_device->resource[]. CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-ide@vger.kernel.org CC: linux-usb@vger.kernel.org CC: laforge@gnumonks.org CC: linux-mtd@lists.infradead.org CC: alsa-devel@alsa-project.org CC: linux-serial@vger.kernel.org Acked-by: Marcel Holtmann (for drivers/bluetooth/) Signed-off-by: Dominik Brodowski --- drivers/ata/pata_pcmcia.c | 8 ++++---- drivers/bluetooth/bluecard_cs.c | 18 ++++++++--------- drivers/bluetooth/bt3c_cs.c | 8 ++++---- drivers/bluetooth/btuart_cs.c | 12 ++++++------ drivers/bluetooth/dtl1_cs.c | 13 ++++++------ drivers/char/pcmcia/cm4000_cs.c | 12 ++++++------ drivers/char/pcmcia/cm4040_cs.c | 16 +++++++-------- drivers/char/pcmcia/ipwireless/main.c | 10 ++++------ drivers/char/pcmcia/synclink_cs.c | 7 +++---- drivers/ide/ide-cs.c | 8 ++++---- drivers/isdn/hardware/avm/avm_cs.c | 9 +++++---- drivers/isdn/hisax/avma1_cs.c | 8 +++++--- drivers/isdn/hisax/elsa_cs.c | 16 +++++++-------- drivers/isdn/hisax/sedlbauer_cs.c | 16 +++++++-------- drivers/isdn/hisax/teles_cs.c | 14 ++++++------- drivers/net/pcmcia/3c574_cs.c | 2 +- drivers/net/pcmcia/3c589_cs.c | 2 +- drivers/net/pcmcia/axnet_cs.c | 4 ++-- drivers/net/pcmcia/com20020_cs.c | 2 +- drivers/net/pcmcia/fmvj18x_cs.c | 6 +++--- drivers/net/pcmcia/ibmtr_cs.c | 2 +- drivers/net/pcmcia/nmclan_cs.c | 2 +- drivers/net/pcmcia/pcnet_cs.c | 4 ++-- drivers/net/pcmcia/smc91c92_cs.c | 18 ++++++++--------- drivers/net/pcmcia/xirc2ps_cs.c | 10 +++++----- drivers/net/wireless/airo_cs.c | 12 +++++------- drivers/net/wireless/atmel_cs.c | 2 +- drivers/net/wireless/hostap/hostap_cs.c | 18 ++++++++--------- drivers/net/wireless/libertas/if_cs.c | 7 +++---- drivers/net/wireless/orinoco/orinoco_cs.c | 5 +++-- drivers/net/wireless/orinoco/spectrum_cs.c | 5 +++-- drivers/net/wireless/wl3501_cs.c | 2 +- drivers/parport/parport_cs.c | 6 ++++-- drivers/scsi/pcmcia/aha152x_stub.c | 2 +- drivers/scsi/pcmcia/fdomain_stub.c | 4 ++-- drivers/scsi/pcmcia/nsp_cs.c | 25 ++++++++++++------------ drivers/scsi/pcmcia/qlogic_stub.c | 18 ++++++++--------- drivers/scsi/pcmcia/sym53c500_cs.c | 16 +++++++-------- drivers/serial/serial_cs.c | 22 ++++++++++----------- drivers/staging/comedi/drivers/cb_das16_cs.c | 12 +++++------- drivers/staging/comedi/drivers/das08_cs.c | 12 +++++------- drivers/staging/comedi/drivers/ni_daq_700.c | 12 +++++------- drivers/staging/comedi/drivers/ni_daq_dio24.c | 12 +++++------- drivers/staging/comedi/drivers/ni_labpc_cs.c | 12 +++++------- drivers/staging/comedi/drivers/ni_mio_cs.c | 2 +- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 12 +++++------- drivers/staging/wlags49_h2/wl_cs.c | 2 +- drivers/telephony/ixj_pcmcia.c | 3 ++- drivers/usb/host/sl811_cs.c | 7 +++---- sound/pcmcia/pdaudiocf/pdaudiocf.c | 3 ++- sound/pcmcia/vx/vxpocket.c | 3 ++- 51 files changed, 223 insertions(+), 240 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 3dcb2b1b60e9..1fcd0659b3f2 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -210,13 +210,13 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev, pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1; if (pcmcia_request_io(pdev, &pdev->io) != 0) return -ENODEV; - stk->ctl_base = pdev->io.BasePort2; + stk->ctl_base = pdev->resource[1]->start; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { pdev->io.NumPorts1 = io->win[0].len; pdev->io.NumPorts2 = 0; if (pcmcia_request_io(pdev, &pdev->io) != 0) return -ENODEV; - stk->ctl_base = pdev->io.BasePort1 + 0x0e; + stk->ctl_base = pdev->resource[0]->start + 0x0e; } else return -ENODEV; /* If we've got this far, we're done */ @@ -270,7 +270,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) goto failed; /* No suitable config found */ } - io_base = pdev->io.BasePort1; + io_base = pdev->resource[0]->start; ctl_base = stk->ctl_base; if (!pdev->irq) goto failed; @@ -293,7 +293,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) /* FIXME: Could be more ports at base + 0x10 but we only deal with one right now */ - if (pdev->io.NumPorts1 >= 0x20) + if (resource_size(pdev->resource[0]) >= 0x20) n_ports = 2; if (pdev->manf_id == 0x0097 && pdev->card_id == 0x1620) diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index eb085de16713..24d2007139e8 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -159,7 +159,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev); static void bluecard_activity_led_timeout(u_long arg) { bluecard_info_t *info = (bluecard_info_t *)arg; - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) return; @@ -176,7 +176,7 @@ static void bluecard_activity_led_timeout(u_long arg) static void bluecard_enable_activity_led(bluecard_info_t *info) { - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) return; @@ -232,7 +232,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info) } do { - register unsigned int iobase = info->p_dev->io.BasePort1; + register unsigned int iobase = info->p_dev->resource[0]->start; register unsigned int offset; register unsigned char command; register unsigned long ready_bit; @@ -379,7 +379,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset) return; } - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; if (test_bit(XMIT_SENDING_READY, &(info->tx_state))) bluecard_enable_activity_led(info); @@ -508,7 +508,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst) if (!test_bit(CARD_READY, &(info->hw_state))) return IRQ_HANDLED; - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; spin_lock(&(info->lock)); @@ -622,7 +622,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev) static int bluecard_hci_open(struct hci_dev *hdev) { bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); @@ -642,7 +642,7 @@ static int bluecard_hci_open(struct hci_dev *hdev) static int bluecard_hci_close(struct hci_dev *hdev) { bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) return 0; @@ -709,7 +709,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned l static int bluecard_open(bluecard_info_t *info) { - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; struct hci_dev *hdev; unsigned char id; @@ -828,7 +828,7 @@ static int bluecard_open(bluecard_info_t *info) static int bluecard_close(bluecard_info_t *info) { - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; struct hci_dev *hdev = info->hdev; if (!hdev) diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 457b603f8678..8ab494c0c17f 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -188,7 +188,7 @@ static void bt3c_write_wakeup(bt3c_info_t *info) return; do { - register unsigned int iobase = info->p_dev->io.BasePort1; + register unsigned int iobase = info->p_dev->resource[0]->start; register struct sk_buff *skb; register int len; @@ -226,7 +226,7 @@ static void bt3c_receive(bt3c_info_t *info) return; } - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; avail = bt3c_read(iobase, 0x7006); //printk("bt3c_cs: receiving %d bytes\n", avail); @@ -347,7 +347,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst) /* our irq handler is shared */ return IRQ_NONE; - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; spin_lock(&(info->lock)); @@ -480,7 +480,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, const unsigned char *firmware, unsigned int iobase, size, addr, fcs, tmp; int i, err = 0; - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; /* Reset */ bt3c_io_write(iobase, 0x8040, 0x0404); diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index e7e0a17aecc2..7e770d40368d 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -142,7 +142,7 @@ static void btuart_write_wakeup(btuart_info_t *info) } do { - register unsigned int iobase = info->p_dev->io.BasePort1; + register unsigned int iobase = info->p_dev->resource[0]->start; register struct sk_buff *skb; register int len; @@ -183,7 +183,7 @@ static void btuart_receive(btuart_info_t *info) return; } - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; do { info->hdev->stat.byte_rx++; @@ -297,7 +297,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst) /* our irq handler is shared */ return IRQ_NONE; - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; spin_lock(&(info->lock)); @@ -354,7 +354,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed) return; } - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; spin_lock_irqsave(&(info->lock), flags); @@ -478,7 +478,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon static int btuart_open(btuart_info_t *info) { unsigned long flags; - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; struct hci_dev *hdev; spin_lock_init(&(info->lock)); @@ -548,7 +548,7 @@ static int btuart_open(btuart_info_t *info) static int btuart_close(btuart_info_t *info) { unsigned long flags; - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; struct hci_dev *hdev = info->hdev; if (!hdev) diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 7c94aad0b791..bfe9313516fb 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -149,7 +149,7 @@ static void dtl1_write_wakeup(dtl1_info_t *info) } do { - register unsigned int iobase = info->p_dev->io.BasePort1; + register unsigned int iobase = info->p_dev->resource[0]->start; register struct sk_buff *skb; register int len; @@ -214,7 +214,7 @@ static void dtl1_receive(dtl1_info_t *info) return; } - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; do { info->hdev->stat.byte_rx++; @@ -301,7 +301,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst) /* our irq handler is shared */ return IRQ_NONE; - iobase = info->p_dev->io.BasePort1; + iobase = info->p_dev->resource[0]->start; spin_lock(&(info->lock)); @@ -461,7 +461,7 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long static int dtl1_open(dtl1_info_t *info) { unsigned long flags; - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; struct hci_dev *hdev; spin_lock_init(&(info->lock)); @@ -508,7 +508,8 @@ static int dtl1_open(dtl1_info_t *info) outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); - info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI; + info->ri_latch = inb(info->p_dev->resource[0]->start + UART_MSR) + & UART_MSR_RI; /* Turn on interrupts */ outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); @@ -533,7 +534,7 @@ static int dtl1_open(dtl1_info_t *info) static int dtl1_close(dtl1_info_t *info) { unsigned long flags; - unsigned int iobase = info->p_dev->io.BasePort1; + unsigned int iobase = info->p_dev->resource[0]->start; struct hci_dev *hdev = info->hdev; if (!hdev) diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index a8be2a7906e0..18484edc1259 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -421,7 +421,7 @@ static struct card_fixup card_fixups[] = { static void set_cardparameter(struct cm4000_dev *dev) { int i; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; u_int8_t stopbits = 0x02; /* ISO default */ DEBUGP(3, dev, "-> set_cardparameter\n"); @@ -454,7 +454,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) unsigned short num_bytes_read; unsigned char pts_reply[4]; ssize_t rc; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; rc = 0; @@ -663,7 +663,7 @@ static void terminate_monitor(struct cm4000_dev *dev) static void monitor_card(unsigned long p) { struct cm4000_dev *dev = (struct cm4000_dev *) p; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; unsigned short s; struct ptsreq ptsreq; int i, atrc; @@ -924,7 +924,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, loff_t *ppos) { struct cm4000_dev *dev = filp->private_data; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; ssize_t rc; int i, j, k; @@ -1047,7 +1047,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { struct cm4000_dev *dev = filp->private_data; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; unsigned short s; unsigned char tmp; unsigned char infolen; @@ -1400,7 +1400,7 @@ static void stop_monitor(struct cm4000_dev *dev) static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct cm4000_dev *dev = filp->private_data; - unsigned int iobase = dev->p_dev->io.BasePort1; + unsigned int iobase = dev->p_dev->resource[0]->start; struct inode *inode = filp->f_path.dentry->d_inode; struct pcmcia_device *link; int size; diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 44adae98c576..a6bbf199dde9 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -109,7 +109,7 @@ static inline unsigned char xinb(unsigned short port) static void cm4040_do_poll(unsigned long dummy) { struct reader_dev *dev = (struct reader_dev *) dummy; - unsigned int obs = xinb(dev->p_dev->io.BasePort1 + unsigned int obs = xinb(dev->p_dev->resource[0]->start + REG_OFFSET_BUFFER_STATUS); if ((obs & BSR_BULK_IN_FULL)) { @@ -140,7 +140,7 @@ static void cm4040_stop_poll(struct reader_dev *dev) static int wait_for_bulk_out_ready(struct reader_dev *dev) { int i, rc; - int iobase = dev->p_dev->io.BasePort1; + int iobase = dev->p_dev->resource[0]->start; for (i = 0; i < POLL_LOOP_COUNT; i++) { if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) @@ -170,7 +170,7 @@ static int wait_for_bulk_out_ready(struct reader_dev *dev) /* Write to Sync Control Register */ static int write_sync_reg(unsigned char val, struct reader_dev *dev) { - int iobase = dev->p_dev->io.BasePort1; + int iobase = dev->p_dev->resource[0]->start; int rc; rc = wait_for_bulk_out_ready(dev); @@ -188,7 +188,7 @@ static int write_sync_reg(unsigned char val, struct reader_dev *dev) static int wait_for_bulk_in_ready(struct reader_dev *dev) { int i, rc; - int iobase = dev->p_dev->io.BasePort1; + int iobase = dev->p_dev->resource[0]->start; for (i = 0; i < POLL_LOOP_COUNT; i++) { if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) @@ -218,7 +218,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { struct reader_dev *dev = filp->private_data; - int iobase = dev->p_dev->io.BasePort1; + int iobase = dev->p_dev->resource[0]->start; size_t bytes_to_read; unsigned long i; size_t min_bytes_to_read; @@ -320,7 +320,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { struct reader_dev *dev = filp->private_data; - int iobase = dev->p_dev->io.BasePort1; + int iobase = dev->p_dev->resource[0]->start; ssize_t rc; int i; unsigned int bytes_to_write; @@ -567,8 +567,8 @@ static int reader_config(struct pcmcia_device *link, int devno) dev = link->priv; - DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, - link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); + DEBUGP(2, dev, "device " DEVICE_NAME "%d at %pR\n", devno, + link->resource[0]); DEBUGP(2, dev, "<- reader_config (succ)\n"); return 0; diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 63c32e3f23ba..9467994d556f 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -100,7 +100,8 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, if (ret) return ret; - io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1, + io_resource = request_region(p_dev->resource[0]->start, + resource_size(p_dev->resource[0]), IPWIRELESS_PCCARD_NAME); if (cfg->mem.nwin == 0) @@ -197,7 +198,7 @@ static int config_ipwireless(struct ipw_dev *ipw) INIT_WORK(&ipw->work_reboot, signalled_reboot_work); - ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1, + ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start, ipw->attr_memory, ipw->common_memory, ipw->is_v2_card, signalled_reboot_callback, ipw); @@ -209,10 +210,7 @@ static int config_ipwireless(struct ipw_dev *ipw) printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", ipw->is_v2_card ? "V2/V3" : "V1"); printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": I/O ports 0x%04x-0x%04x, irq %d\n", - (unsigned int) link->io.BasePort1, - (unsigned int) (link->io.BasePort1 + - link->io.NumPorts1 - 1), + ": I/O ports %pR, irq %d\n", link->resource[0], (unsigned int) link->irq); if (ipw->attr_memory && ipw->common_memory) printk(KERN_INFO IPWIRELESS_PCCARD_NAME diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 522992ed6e49..8ded9b02b9b9 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -609,16 +609,15 @@ static int mgslpc_config(struct pcmcia_device *link) if (ret) goto failed; - info->io_base = link->io.BasePort1; + info->io_base = link->resource[0]->start; info->irq_level = link->irq; dev_info(&link->dev, "index 0x%02x:", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); + if (link->resource[0]) + printk(", io %pR", link->resource[0]); printk("\n"); return 0; diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index 27dbab84142c..6be0e5f108b5 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c @@ -239,13 +239,13 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev, pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1; if (pcmcia_request_io(pdev, &pdev->io) != 0) return -ENODEV; - stk->ctl_base = pdev->io.BasePort2; + stk->ctl_base = pdev->resource[1]->start; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { pdev->io.NumPorts1 = io->win[0].len; pdev->io.NumPorts2 = 0; if (pcmcia_request_io(pdev, &pdev->io) != 0) return -ENODEV; - stk->ctl_base = pdev->io.BasePort1 + 0x0e; + stk->ctl_base = pdev->resource[0]->start + 0x0e; } else return -ENODEV; /* If we've got this far, we're done */ @@ -279,7 +279,7 @@ static int ide_config(struct pcmcia_device *link) if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) goto failed; /* No suitable config found */ } - io_base = link->io.BasePort1; + io_base = link->resource[0]->start; ctl_base = stk->ctl_base; if (!link->irq) @@ -296,7 +296,7 @@ static int ide_config(struct pcmcia_device *link) outb(0x81, ctl_base+1); host = idecs_register(io_base, ctl_base, link->irq, link); - if (host == NULL && link->io.NumPorts1 == 0x20) { + if (host == NULL && resource_size(link->resource[0]) == 0x20) { outb(0x02, ctl_base + 0x10); host = idecs_register(io_base + 0x10, ctl_base + 0x10, link->irq, link); diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index e804a01ecdfb..7c8c51f22003 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -191,9 +191,10 @@ static int avmcs_config(struct pcmcia_device *link) default: case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; } - if ((i = (*addcard)(link->io.BasePort1, link->irq)) < 0) { - dev_err(&link->dev, "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n", - link->io.BasePort1, link->irq); + if ((i = (*addcard)(link->resource[0]->start, link->irq)) < 0) { + dev_err(&link->dev, + "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n", + (unsigned int) link->resource[0]->start, link->irq); avmcs_release(link); return -ENODEV; } @@ -211,7 +212,7 @@ static int avmcs_config(struct pcmcia_device *link) static void avmcs_release(struct pcmcia_device *link) { - b1pcmcia_delcard(link->io.BasePort1, link->irq); + b1pcmcia_delcard(link->resource[0]->start, link->irq); pcmcia_disable_device(link); } /* avmcs_release */ diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 49e141e49aaf..88899638f835 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -180,16 +180,18 @@ static int __devinit avma1cs_config(struct pcmcia_device *link) } printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", - link->io.BasePort1, link->irq); + (unsigned int) link->resource[0]->start, link->irq); icard.para[0] = link->irq; - icard.para[1] = link->io.BasePort1; + icard.para[1] = link->resource[0]->start; icard.protocol = isdnprot; icard.typ = ISDN_CTYPE_A1_PCMCIA; i = hisax_init_pcmcia(link, &busy, &icard); if (i < 0) { - printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); + printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 " + "PCMCIA %d at i/o %#x\n", i, + (unsigned int) link->resource[0]->start); avma1cs_release(link); return -ENODEV; } diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 425deea1dd69..c10bfd3f4588 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -214,23 +214,21 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link) link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); + if (link->resource[0]) + printk(" & %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); printk("\n"); icard.para[0] = link->irq; - icard.para[1] = link->io.BasePort1; + icard.para[1] = link->resource[0]->start; icard.protocol = protocol; icard.typ = ISDN_CTYPE_ELSA_PCMCIA; i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard); if (i < 0) { - printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n", - i, link->io.BasePort1); + printk(KERN_ERR "elsa_cs: failed to initialize Elsa " + "PCMCIA %d with %pR\n", i, link->resource[0]); elsa_cs_release(link); } else ((local_info_t*)link->priv)->cardnr = i; diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 5dbad966a29e..cecb35ab9d3d 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -296,27 +296,25 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link) printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); + if (link->resource[0]) + printk(" & %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); if (link->win) printk(", mem 0x%06lx-0x%06lx", req->Base, req->Base+req->Size-1); printk("\n"); icard.para[0] = link->irq; - icard.para[1] = link->io.BasePort1; + icard.para[1] = link->resource[0]->start; icard.protocol = protocol; icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; ret = hisax_init_pcmcia(link, &(((local_info_t *)link->priv)->stop), &icard); if (ret < 0) { - printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", - ret, link->io.BasePort1); + printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d with %pR\n", + ret, link->resource[0]); sedlbauer_release(link); return -ENODEV; } else diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index d3fb1b716800..3787fc70cf8f 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -194,23 +194,21 @@ static int __devinit teles_cs_config(struct pcmcia_device *link) link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); + if (link->resource[0]) + printk(" & %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); printk("\n"); icard.para[0] = link->irq; - icard.para[1] = link->io.BasePort1; + icard.para[1] = link->resource[0]->start; icard.protocol = protocol; icard.typ = ISDN_CTYPE_TELESPCMCIA; i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard); if (i < 0) { printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n", - i, link->io.BasePort1); + i, (unsigned int) link->resource[0]->start); teles_cs_release(link); return -ENODEV; } diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index e249b898075c..b5ea9b8cfd76 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -356,7 +356,7 @@ static int tc574_config(struct pcmcia_device *link) goto failed; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; ioaddr = dev->base_addr; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index b0772df31057..122ef4a9488c 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -298,7 +298,7 @@ static int tc589_config(struct pcmcia_device *link) goto failed; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; ioaddr = dev->base_addr; EL3WINDOW(0); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index ee0a6d036f94..c52fdf31cbfe 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -332,7 +332,7 @@ static int axnet_config(struct pcmcia_device *link) if (!link->irq) goto failed; - if (link->io.NumPorts2 == 8) { + if (resource_size(link->resource[1]) == 8) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; } @@ -342,7 +342,7 @@ static int axnet_config(struct pcmcia_device *link) goto failed; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; if (!get_prom(link)) { printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n"); diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 99957af40329..3b53818e3eef 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -266,7 +266,7 @@ static int com20020_config(struct pcmcia_device *link) goto failed; } - ioaddr = dev->base_addr = link->io.BasePort1; + ioaddr = dev->base_addr = link->resource[0]->start; dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr); dev_dbg(&link->dev, "request IRQ %d\n", diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 95a991beaa30..bba6369a028e 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -315,7 +315,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link) if (ret == 0) { /* calculate ConfigIndex value */ link->conf.ConfigIndex = - ((link->io.BasePort1 & 0x0f0) >> 3) | 0x22; + ((link->resource[0]->start & 0x0f0) >> 3) | 0x22; return ret; } } @@ -436,9 +436,9 @@ static int fmvj18x_config(struct pcmcia_device *link) goto failed; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; - if (link->io.BasePort2 != 0) { + if (resource_size(link->resource[1]) != 0) { ret = fmvj18x_setup_mfc(link); if (ret != 0) goto failed; } diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index c36dcd14ec45..e99abaa92be5 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -231,7 +231,7 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) if (ret) goto failed; } - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; ret = pcmcia_request_exclusive_irq(link, ibmtr_interrupt); if (ret) diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index c0d85af3e942..9980cbb81d34 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -655,7 +655,7 @@ static int nmclan_config(struct pcmcia_device *link) goto failed; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; ioaddr = dev->base_addr; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index db6dbdabb702..c9cd2377ef91 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -554,7 +554,7 @@ static int pcnet_config(struct pcmcia_device *link) if (!link->irq) goto failed; - if (link->io.NumPorts2 == 8) { + if (resource_size(link->resource[1]) == 8) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; } @@ -566,7 +566,7 @@ static int pcnet_config(struct pcmcia_device *link) if (ret) goto failed; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; if (info->flags & HAS_MISC_REG) { if ((if_port == 1) || (if_port == 2)) dev->if_port = if_port; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 88f503a80a8e..1b0b3230dd71 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -457,7 +457,7 @@ static int mhz_mfc_config(struct pcmcia_device *link) if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL)) return -ENODEV; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; /* Allocate a memory window, for accessing the ISR */ req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; @@ -545,7 +545,7 @@ static void mot_config(struct pcmcia_device *link) struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); unsigned int ioaddr = dev->base_addr; - unsigned int iouart = link->io.BasePort2; + unsigned int iouart = link->resource[1]->start; /* Set UART base address and force map with COR bit 1 */ writeb(iouart & 0xff, smc->base + MOT_UART + CISREG_IOBASE_0); @@ -614,7 +614,7 @@ static int smc_config(struct pcmcia_device *link) link->io.NumPorts1 = 16; i = pcmcia_loop_config(link, smc_configcheck, NULL); if (!i) - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; return i; } @@ -666,7 +666,7 @@ static int osi_config(struct pcmcia_device *link) link->io.NumPorts2 = 0; i = pcmcia_request_io(link, &link->io); } - dev->base_addr = link->io.BasePort1 + 0x10; + dev->base_addr = link->resource[0]->start + 0x10; return i; } @@ -683,7 +683,7 @@ static int osi_load_firmware(struct pcmcia_device *link) /* Download the Seven of Diamonds firmware */ for (i = 0; i < fw->size; i++) { - outb(fw->data[i], link->io.BasePort1 + 2); + outb(fw->data[i], link->resource[0]->start + 2); udelay(50); } release_firmware(fw); @@ -725,12 +725,12 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) return rc; } else if (manfid == MANFID_OSITECH) { /* Make sure both functions are powered up */ - set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR); + set_bits(0x300, link->resource[0]->start + OSITECH_AUI_PWR); /* Now, turn on the interrupt for both card functions */ - set_bits(0x300, link->io.BasePort1 + OSITECH_RESET_ISR); + set_bits(0x300, link->resource[0]->start + OSITECH_RESET_ISR); dev_dbg(&link->dev, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n", - inw(link->io.BasePort1 + OSITECH_AUI_PWR), - inw(link->io.BasePort1 + OSITECH_RESET_ISR)); + inw(link->resource[0]->start + OSITECH_AUI_PWR), + inw(link->resource[0]->start + OSITECH_RESET_ISR)); } return 0; } diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index e3a85ce89880..034920b459d1 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -877,13 +877,13 @@ xirc2ps_config(struct pcmcia_device * link) * the base address of the ethernet port (BasePort1) is written * to the BAR registers of the modem. */ - err = pcmcia_write_config_byte(link, CISREG_IOBASE_0, - link->io.BasePort2 & 0xff); + err = pcmcia_write_config_byte(link, CISREG_IOBASE_0, (u8) + link->resource[1]->start & 0xff); if (err) goto config_error; err = pcmcia_write_config_byte(link, CISREG_IOBASE_1, - (link->io.BasePort2 >> 8) & 0xff); + (link->resource[1]->start >> 8) & 0xff); if (err) goto config_error; @@ -907,7 +907,7 @@ xirc2ps_config(struct pcmcia_device * link) * part. */ writeb(0x47, local->dingo_ccr + CISREG_COR); - ioaddr = link->io.BasePort1; + ioaddr = link->resource[0]->start; writeb(ioaddr & 0xff , local->dingo_ccr + CISREG_IOBASE_0); writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1); @@ -954,7 +954,7 @@ xirc2ps_config(struct pcmcia_device * link) /* we can now register the device with the net subsystem */ dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; if (local->dingo) do_reset(dev, 1); /* a kludge to make the cem56 work */ diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 9389ba004fb9..b7e7f5054e44 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -271,7 +271,7 @@ static int airo_config(struct pcmcia_device *link) goto failed; ((local_info_t *)link->priv)->eth_dev = init_airo_card(link->irq, - link->io.BasePort1, 1, &link->dev); + link->resource[0]->start, 1, &link->dev); if (!((local_info_t *)link->priv)->eth_dev) goto failed; @@ -281,12 +281,10 @@ static int airo_config(struct pcmcia_device *link) if (link->conf.Vpp) printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); + if (link->resource[0]) + printk(" & %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); if (link->win) printk(", mem 0x%06lx-0x%06lx", req->Base, req->Base+req->Size-1); diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 91ee74a8801e..65b3aed49e58 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -253,7 +253,7 @@ static int atmel_config(struct pcmcia_device *link) ((local_info_t*)link->priv)->eth_dev = init_atmel_card(link->irq, - link->io.BasePort1, + link->resource[0]->start, did ? did->driver_info : ATMEL_FW_TYPE_NONE, &link->dev, card_present, diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 691293675a93..4e13cedb8235 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -227,7 +227,7 @@ static void sandisk_set_iobase(local_info_t *local) struct hostap_cs_priv *hw_priv = local->hw_priv; res = pcmcia_write_config_byte(hw_priv->link, 0x10, - hw_priv->link->io.BasePort1 & 0x00ff); + hw_priv->link->resource[0]->start & 0x00ff); if (res != 0) { printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" " res=%d\n", res); @@ -235,7 +235,7 @@ static void sandisk_set_iobase(local_info_t *local) udelay(10); res = pcmcia_write_config_byte(hw_priv->link, 0x12, - (hw_priv->link->io.BasePort1 >> 8) & 0x00ff); + (hw_priv->link->resource[0]->start >> 8) & 0x00ff); if (res != 0) { printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" " res=%d\n", res); @@ -265,7 +265,7 @@ static int sandisk_enable_wireless(struct net_device *dev) local_info_t *local = iface->local; struct hostap_cs_priv *hw_priv = local->hw_priv; - if (hw_priv->link->io.NumPorts1 < 0x42) { + if (resource_size(hw_priv->link->resource[0]) < 0x42) { /* Not enough ports to be SanDisk multi-function card */ ret = -ENODEV; goto done; @@ -604,7 +604,7 @@ static int prism2_config(struct pcmcia_device *link) goto failed_unlock; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; spin_unlock_irqrestore(&local->irq_init_lock, flags); @@ -616,12 +616,10 @@ static int prism2_config(struct pcmcia_device *link) link->conf.Vpp % 10); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); + if (link->resource[0]) + printk(" & %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); printk("\n"); local->shutdown = 0; diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 1d3a7e0e5f10..be4c47594b59 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -853,7 +853,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out1; /* Initialize io access */ - card->iobase = ioport_map(p_dev->io.BasePort1, p_dev->io.NumPorts1); + card->iobase = ioport_map(p_dev->resource[0]->start, + resource_size(p_dev->resource[0])); if (!card->iobase) { lbs_pr_err("error in ioport_map\n"); ret = -EIO; @@ -872,9 +873,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) } /* Finally, report what we've done */ - lbs_deb_cs("irq %d, io 0x%04x-0x%04x\n", - p_dev->irq, p_dev->io.BasePort1, - p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1); + lbs_deb_cs("irq %d, io %pR", p_dev->irq, p_dev->resource[0]); /* * Most of the libertas cards can do unaligned register access, but some diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 41ca4f1b395f..6d514b5462fd 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -257,7 +257,8 @@ orinoco_cs_config(struct pcmcia_device *link) /* We initialize the hermes structure before completing PCMCIA * configuration just in case the interrupt handler gets * called. */ - mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); + mem = ioport_map(link->resource[0]->start, + resource_size(link->resource[0])); if (!mem) goto failed; @@ -279,7 +280,7 @@ orinoco_cs_config(struct pcmcia_device *link) } /* Register an interface with the stack */ - if (orinoco_if_add(priv, link->io.BasePort1, + if (orinoco_if_add(priv, link->resource[0]->start, link->irq, NULL) != 0) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto failed; diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 39399cd2e683..4f8f55eab955 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -319,7 +319,8 @@ spectrum_cs_config(struct pcmcia_device *link) /* We initialize the hermes structure before completing PCMCIA * configuration just in case the interrupt handler gets * called. */ - mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); + mem = ioport_map(link->resource[0]->start, + resource_size(link->resource[0])); if (!mem) goto failed; @@ -346,7 +347,7 @@ spectrum_cs_config(struct pcmcia_device *link) } /* Register an interface with the stack */ - if (orinoco_if_add(priv, link->io.BasePort1, + if (orinoco_if_add(priv, link->resource[0]->start, link->irq, NULL) != 0) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto failed; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 35f431bf97d6..a32f220648c0 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1960,7 +1960,7 @@ static int wl3501_config(struct pcmcia_device *link) goto failed; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev)) { printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n"); diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index ee56fd66d5dc..fc1639c5ada6 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -177,12 +177,14 @@ static int parport_config(struct pcmcia_device *link) if (ret) goto failed; - p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, + p = parport_pc_probe_port(link->resource[0]->start, + link->resource[1]->start, link->irq, PARPORT_DMA_NONE, &link->dev, IRQF_SHARED); if (p == NULL) { printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at " - "0x%3x, irq %u failed\n", link->io.BasePort1, + "0x%3x, irq %u failed\n", + (unsigned int) link->resource[0]->start, link->irq); goto failed; } diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index b07b53ef3c00..3e040f503afa 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -167,7 +167,7 @@ static int aha152x_config_cs(struct pcmcia_device *link) /* Set configuration options for the aha152x driver */ memset(&s, 0, sizeof(s)); s.conf = "PCMCIA setup"; - s.io_port = link->io.BasePort1; + s.io_port = link->resource[0]->start; s.irq = link->irq; s.scsiid = host_id; s.reconnect = reconnect; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index ee0489762539..49a9a0a60c82 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -137,10 +137,10 @@ static int fdomain_config(struct pcmcia_device *link) goto failed; /* A bad hack... */ - release_region(link->io.BasePort1, link->io.NumPorts1); + release_region(link->resource[0]->start, resource_size(link->resource[0])); /* Set configuration options for the fdomain driver */ - sprintf(str, "%d,%d", link->io.BasePort1, link->irq); + sprintf(str, "%d,%d", (unsigned int) link->resource[0]->start, link->irq); fdomain_setup(str); host = __fdomain_16x0_detect(&fdomain_driver_template); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index d4142075be21..d929891809ab 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1719,17 +1719,19 @@ static int nsp_cs_config(struct pcmcia_device *link) goto cs_failed; if (free_ports) { - if (link->io.BasePort1) { - release_region(link->io.BasePort1, link->io.NumPorts1); + if (link->resource[0]) { + release_region(link->resource[0]->start, + resource_size(link->resource[0])); } - if (link->io.BasePort2) { - release_region(link->io.BasePort2, link->io.NumPorts2); + if (link->resource[1]) { + release_region(link->resource[1]->start, + resource_size(link->resource[1])); } } /* Set port and IRQ */ - data->BaseAddress = link->io.BasePort1; - data->NumAddress = link->io.NumPorts1; + data->BaseAddress = link->resource[0]->start; + data->NumAddress = resource_size(link->resource[0]); data->IrqNumber = link->irq; nsp_dbg(NSP_DEBUG_INIT, "I/O[0x%x+0x%x] IRQ %d", @@ -1764,13 +1766,10 @@ static int nsp_cs_config(struct pcmcia_device *link) if (link->conf.Attributes & CONF_ENABLE_IRQ) { printk(", irq %d", link->irq); } - if (link->io.NumPorts1) { - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - } - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); + if (link->resource[0]) + printk(", io %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); if (link->win) printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base, cfg_mem->req.Base+cfg_mem->req.Size-1); diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index c1cf7f43313b..4e2b83f26232 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -215,18 +215,18 @@ static int qlogic_config(struct pcmcia_device * link) if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { /* set ATAcmd */ - outb(0xb4, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); + outb(0xb4, link->resource[0]->start + 0xd); + outb(0x24, link->resource[0]->start + 0x9); + outb(0x04, link->resource[0]->start + 0xd); } /* The KXL-810AN has a bigger IO port window */ - if (link->io.NumPorts1 == 32) + if (resource_size(link->resource[0]) == 32) host = qlogic_detect(&qlogicfas_driver_template, link, - link->io.BasePort1 + 16, link->irq); + link->resource[0]->start + 16, link->irq); else host = qlogic_detect(&qlogicfas_driver_template, link, - link->io.BasePort1, link->irq); + link->resource[0]->start, link->irq); if (!host) { printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name); @@ -268,9 +268,9 @@ static int qlogic_resume(struct pcmcia_device *link) if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { - outb(0x80, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); + outb(0x80, link->resource[0]->start + 0xd); + outb(0x24, link->resource[0]->start + 0x9); + outb(0x04, link->resource[0]->start + 0xd); } /* Ugggglllyyyy!!! */ qlogicfas408_bus_reset(NULL); diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index bd79e45ab856..d99c0cbad2de 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -733,9 +733,9 @@ SYM53C500_config(struct pcmcia_device *link) (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { /* set ATAcmd */ - outb(0xb4, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); + outb(0xb4, link->resource[0]->start + 0xd); + outb(0x24, link->resource[0]->start + 0x9); + outb(0x04, link->resource[0]->start + 0xd); } /* @@ -748,7 +748,7 @@ SYM53C500_config(struct pcmcia_device *link) * 0x130, 0x230, 0x280, 0x290, * 0x320, 0x330, 0x340, 0x350 */ - port_base = link->io.BasePort1; + port_base = link->resource[0]->start; irq_level = link->irq; DEB(printk("SYM53C500: port_base=0x%x, irq=%d, fast_pio=%d\n", @@ -821,15 +821,15 @@ static int sym53c500_resume(struct pcmcia_device *link) if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { - outb(0x80, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); + outb(0x80, link->resource[0]->start + 0xd); + outb(0x24, link->resource[0]->start + 0x9); + outb(0x04, link->resource[0]->start + 0xd); } /* * If things don't work after a "resume", * this is a good place to start looking. */ - SYM53C500_int_host_reset(link->io.BasePort1); + SYM53C500_int_host_reset(link->resource[0]->start); return 0; } diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 2be8b107ed51..fe7adcdfde9e 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -463,13 +463,13 @@ static int simple_config(struct pcmcia_device *link) /* If the card is already configured, look up the port and irq */ if (link->function_config) { unsigned int port = 0; - if ((link->io.BasePort2 != 0) && - (link->io.NumPorts2 == 8)) { - port = link->io.BasePort2; + if ((link->resource[1]->end != 0) && + (resource_size(link->resource[1]) == 8)) { + port = link->resource[1]->end; info->slave = 1; } else if ((info->manfid == MANFID_OSITECH) && - (link->io.NumPorts1 == 0x40)) { - port = link->io.BasePort1 + 0x28; + (resource_size(link->resource[0]) == 0x40)) { + port = link->resource[0]->start + 0x28; info->slave = 1; } if (info->slave) { @@ -507,7 +507,7 @@ found_port: i = pcmcia_request_configuration(link, &link->conf); if (i != 0) return -1; - return setup_serial(link, info, link->io.BasePort1, link->irq); + return setup_serial(link, info, link->resource[0]->start, link->irq); } static int multi_config_check(struct pcmcia_device *p_dev, @@ -524,7 +524,7 @@ static int multi_config_check(struct pcmcia_device *p_dev, p_dev->io.BasePort1 = cf->io.win[0].base; p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; if (!pcmcia_request_io(p_dev, &p_dev->io)) { - *base2 = p_dev->io.BasePort1 + 8; + *base2 = p_dev->resource[0]->start + 8; return 0; } } @@ -544,7 +544,7 @@ static int multi_config_check_notpicky(struct pcmcia_device *p_dev, p_dev->io.BasePort2 = cf->io.win[1].base; p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; if (!pcmcia_request_io(p_dev, &p_dev->io)) { - *base2 = p_dev->io.BasePort2; + *base2 = p_dev->resource[1]->start; return 0; } } @@ -596,9 +596,9 @@ static int multi_config(struct pcmcia_device *link) link->conf.ConfigIndex == 3) { err = setup_serial(link, info, base2, link->irq); - base2 = link->io.BasePort1; + base2 = link->resource[0]->start;; } else { - err = setup_serial(link, info, link->io.BasePort1, + err = setup_serial(link, info, link->resource[0]->start, link->irq); } info->c950ctrl = base2; @@ -613,7 +613,7 @@ static int multi_config(struct pcmcia_device *link) return 0; } - setup_serial(link, info, link->io.BasePort1, link->irq); + setup_serial(link, info, link->resource[0]->start, link->irq); for (i = 0; i < info->multi - 1; i++) setup_serial(link, info, base2 + (8 * i), link->irq); diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index acef29ca212b..208f1b7a1312 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -170,7 +170,7 @@ static int das16cs_attach(struct comedi_device *dev, if (!link) return -EIO; - dev->iobase = link->io.BasePort1; + dev->iobase = link->resource[0]->start;; printk("I/O base=0x%04lx ", dev->iobase); printk("fingerprint:\n"); @@ -787,12 +787,10 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link) dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %u", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1 + link->io.NumPorts1 - 1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->resource[0]) + printk(", io %pR", link->resource[0]); + if (link->resource[1]) + printk(", io %pR", link->resource[1]); printk("\n"); return; diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 3eddb7c4b1b0..c4cfcffc633e 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -88,7 +88,7 @@ static int das08_cs_attach(struct comedi_device *dev, printk(" no pcmcia cards found\n"); return -EIO; } - iobase = link->io.BasePort1; + iobase = link->resource[0]->start; } else { printk(" bug! board does not have PCMCIA bustype\n"); return -EINVAL; @@ -283,12 +283,10 @@ static void das08_pcmcia_config(struct pcmcia_device *link) dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %u", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1 + link->io.NumPorts1 - 1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->resource[0]) + printk(", io %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); printk("\n"); return; diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index f3c4d2f929f8..6d569579d677 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -376,7 +376,7 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it) link = pcmcia_cur_dev; /* XXX hack */ if (!link) return -EIO; - iobase = link->io.BasePort1; + iobase = link->resource[0]->start; #ifdef incomplete irq = link->irq; #endif @@ -644,12 +644,10 @@ static void dio700_config(struct pcmcia_device *link) dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1 + link->io.NumPorts1 - 1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->resource[0]) + printk(", io %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); if (link->win) printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base + req.Size - 1); diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index f0c4367dc10b..29e1daf6a9e6 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -128,7 +128,7 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it) link = pcmcia_cur_dev; /* XXX hack */ if (!link) return -EIO; - iobase = link->io.BasePort1; + iobase = link->resource[0]->start; #ifdef incomplete irq = link->irq; #endif @@ -396,12 +396,10 @@ static void dio24_config(struct pcmcia_device *link) dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1 + link->io.NumPorts1 - 1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->resource[0]) + printk(" & %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); if (link->win) printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base + req.Size - 1); diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 1ee78f806ed2..fb10987a97b2 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -142,7 +142,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) link = pcmcia_cur_dev; /* XXX hack */ if (!link) return -EIO; - iobase = link->io.BasePort1; + iobase = link->resource[0]->start; irq = link->irq; break; default: @@ -373,12 +373,10 @@ static void labpc_config(struct pcmcia_device *link) dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1 + link->io.NumPorts1 - 1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->resource[0]) + printk(" & %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); if (link->win) printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base + req.Size - 1); diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 0bce220c47b5..f37dc22b4dbc 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -355,7 +355,7 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -EIO; dev->driver = &driver_ni_mio_cs; - dev->iobase = link->io.BasePort1; + dev->iobase = link->resource[0]->start; irq = link->irq; diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 67c0fa6a2b06..80b8d57c6842 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -871,7 +871,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } - dev->iobase = local->link->io.BasePort1; + dev->iobase = local->link->resource[0]->start; ret = alloc_subdevices(dev, 4); if (ret < 0) @@ -1153,12 +1153,10 @@ static void daqp_cs_config(struct pcmcia_device *link) dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %u", link->irq); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1 + link->io.NumPorts1 - 1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->resource[0]) + printk(" & %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); printk("\n"); return; diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c index afe457541172..23615378acf1 100644 --- a/drivers/staging/wlags49_h2/wl_cs.c +++ b/drivers/staging/wlags49_h2/wl_cs.c @@ -319,7 +319,7 @@ void wl_adapter_insert( struct pcmcia_device *link ) goto failed; dev->irq = link->irq; - dev->base_addr = link->io.BasePort1; + dev->base_addr = link->resource[0]->start; SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index f6c7e6fd7ee1..a801036392cd 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -150,7 +150,8 @@ static int ixj_config(struct pcmcia_device * link) /* * Register the card with the core. */ - j = ixj_pcmcia_probe(link->io.BasePort1, link->io.BasePort1 + 0x10); + j = ixj_pcmcia_probe(link->resource[0]->start, + link->resource[0]->start + 0x10); info->ndev = 1; ixj_get_serial(link, j); diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index acb7e255a837..22e04f206304 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -189,7 +189,7 @@ static int sl811_cs_config(struct pcmcia_device *link) goto failed; /* require an IRQ and two registers */ - if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) + if (resource_size(link->resource[0]) < 2) goto failed; if (!link->irq) @@ -204,11 +204,10 @@ static int sl811_cs_config(struct pcmcia_device *link) if (link->conf.Vpp) printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); printk(", irq %d", link->irq); - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); + printk(", io %pR", link->resource[0]); printk("\n"); - if (sl811_hc_init(parent, link->io.BasePort1, link->irq) + if (sl811_hc_init(parent, link->resource[0]->start, link->irq) < 0) { failed: printk(KERN_WARNING "sl811_cs_config failed\n"); diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index df110df52a8b..9f897bca0615 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -231,7 +231,8 @@ static int pdacf_config(struct pcmcia_device *link) if (ret) goto failed; - if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq) < 0) + if (snd_pdacf_assign_resources(pdacf, link->resource[0]->start, + link->irq) < 0) goto failed; return 0; diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 624b47a85f0a..f23c235013a4 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -241,7 +241,8 @@ static int vxpocket_config(struct pcmcia_device *link) chip->dev = &link->dev; snd_card_set_dev(chip->card, chip->dev); - if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq) < 0) + if (snd_vxpocket_assign_resources(chip, link->resource[0]->start, + link->irq) < 0) goto failed; return 0; -- cgit v1.2.3 From 90abdc3b973229bae98dd96649d9f7106cc177a4 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 24 Jul 2010 17:23:51 +0200 Subject: pcmcia: do not use io_req_t when calling pcmcia_request_io() Instead of io_req_t, drivers are now requested to fill out struct pcmcia_device *p_dev->resource[0,1] for up to two ioport ranges. After a call to pcmcia_request_io(), the ports found there are reserved, after calling pcmcia_request_configuration(), they may be used. CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-ide@vger.kernel.org CC: linux-usb@vger.kernel.org CC: laforge@gnumonks.org CC: linux-mtd@lists.infradead.org CC: alsa-devel@alsa-project.org CC: linux-serial@vger.kernel.org CC: Michael Buesch Acked-by: Marcel Holtmann (for drivers/bluetooth/) Signed-off-by: Dominik Brodowski --- Documentation/pcmcia/driver-changes.txt | 7 ++++ drivers/ata/pata_pcmcia.c | 29 ++++++++-------- drivers/bluetooth/bluecard_cs.c | 13 ++++--- drivers/bluetooth/bt3c_cs.c | 18 +++++----- drivers/bluetooth/btuart_cs.c | 18 +++++----- drivers/bluetooth/dtl1_cs.c | 21 ++++++------ drivers/char/pcmcia/cm4000_cs.c | 17 ++++------ drivers/char/pcmcia/cm4040_cs.c | 20 ++++------- drivers/char/pcmcia/ipwireless/main.c | 10 +++--- drivers/char/pcmcia/synclink_cs.c | 21 +++++------- drivers/ide/ide-cs.c | 30 +++++++++-------- drivers/isdn/hardware/avm/avm_cs.c | 15 +++------ drivers/isdn/hisax/avma1_cs.c | 20 +++++------ drivers/isdn/hisax/elsa_cs.c | 15 +++++---- drivers/isdn/hisax/sedlbauer_cs.c | 28 +++++++-------- drivers/isdn/hisax/teles_cs.c | 15 +++++---- drivers/net/pcmcia/3c574_cs.c | 11 +++--- drivers/net/pcmcia/3c589_cs.c | 11 +++--- drivers/net/pcmcia/axnet_cs.c | 40 +++++++++++----------- drivers/net/pcmcia/com20020_cs.c | 19 ++++++----- drivers/net/pcmcia/fmvj18x_cs.c | 31 ++++++++--------- drivers/net/pcmcia/ibmtr_cs.c | 14 ++++---- drivers/net/pcmcia/nmclan_cs.c | 8 ++--- drivers/net/pcmcia/pcnet_cs.c | 40 +++++++++++----------- drivers/net/pcmcia/smc91c92_cs.c | 43 ++++++++++++------------ drivers/net/pcmcia/xirc2ps_cs.c | 34 +++++++++---------- drivers/net/wireless/airo_cs.c | 22 ++++++------ drivers/net/wireless/atmel_cs.c | 22 ++++++------ drivers/net/wireless/b43/pcmcia.c | 4 --- drivers/net/wireless/hostap/hostap_cs.c | 28 ++++++--------- drivers/net/wireless/libertas/if_cs.c | 8 ++--- drivers/net/wireless/orinoco/orinoco_cs.c | 24 ++++++------- drivers/net/wireless/orinoco/spectrum_cs.c | 24 ++++++------- drivers/net/wireless/ray_cs.c | 5 ++- drivers/net/wireless/wl3501_cs.c | 12 +++---- drivers/parport/parport_cs.c | 16 ++++----- drivers/pcmcia/pcmcia_resource.c | 37 ++++++-------------- drivers/scsi/pcmcia/aha152x_stub.c | 14 ++++---- drivers/scsi/pcmcia/fdomain_stub.c | 10 +++--- drivers/scsi/pcmcia/nsp_cs.c | 30 ++++++++--------- drivers/scsi/pcmcia/qlogic_stub.c | 14 ++++---- drivers/scsi/pcmcia/sym53c500_cs.c | 14 ++++---- drivers/serial/serial_cs.c | 37 ++++++++++---------- drivers/staging/comedi/drivers/cb_das16_cs.c | 24 ++++++------- drivers/staging/comedi/drivers/das08_cs.c | 23 ++++++------- drivers/staging/comedi/drivers/ni_daq_700.c | 24 ++++++------- drivers/staging/comedi/drivers/ni_daq_dio24.c | 24 ++++++------- drivers/staging/comedi/drivers/ni_labpc_cs.c | 24 ++++++------- drivers/staging/comedi/drivers/ni_mio_cs.c | 13 ++++--- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 24 ++++++------- drivers/staging/wlags49_h2/wl_cs.c | 8 ++--- drivers/telephony/ixj_pcmcia.c | 16 ++++----- drivers/usb/host/sl811_cs.c | 12 +++---- include/pcmcia/cs.h | 17 ---------- include/pcmcia/ds.h | 21 ++++++++++-- sound/pcmcia/pdaudiocf/pdaudiocf.c | 6 ++-- sound/pcmcia/vx/vxpocket.c | 6 ++-- 57 files changed, 527 insertions(+), 584 deletions(-) (limited to 'drivers/scsi') diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt index ff5f0be2470a..26c0f9c00545 100644 --- a/Documentation/pcmcia/driver-changes.txt +++ b/Documentation/pcmcia/driver-changes.txt @@ -1,4 +1,11 @@ This file details changes in 2.6 which affect PCMCIA card driver authors: +* pcmcia_request_io changes (as of 2.6.36) + Instead of io_req_t, drivers are now requested to fill out + struct pcmcia_device *p_dev->resource[0,1] for up to two ioport + ranges. After a call to pcmcia_request_io(), the ports found there + are reserved, after calling pcmcia_request_configuration(), they may + be used. + * No dev_info_t, no cs_types.h (as of 2.6.36) dev_info_t and a few other typedefs are removed. No longer use them in PCMCIA device drivers. Also, do not include pcmcia/cs_types.h, as diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 1fcd0659b3f2..e944aa0c5517 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -200,21 +200,23 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev, if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - pdev->io.BasePort1 = io->win[0].base; - pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - if (!(io->flags & CISTPL_IO_16BIT)) - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + pdev->resource[0]->start = io->win[0].base; + if (!(io->flags & CISTPL_IO_16BIT)) { + pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + } if (io->nwin == 2) { - pdev->io.NumPorts1 = 8; - pdev->io.BasePort2 = io->win[1].base; - pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1; - if (pcmcia_request_io(pdev, &pdev->io) != 0) + pdev->resource[0]->end = 8; + pdev->resource[1]->start = io->win[1].base; + pdev->resource[1]->end = (stk->is_kme) ? 2 : 1; + if (pcmcia_request_io(pdev) != 0) return -ENODEV; stk->ctl_base = pdev->resource[1]->start; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { - pdev->io.NumPorts1 = io->win[0].len; - pdev->io.NumPorts2 = 0; - if (pcmcia_request_io(pdev, &pdev->io) != 0) + pdev->resource[0]->end = io->win[0].len; + pdev->resource[1]->end = 0; + if (pcmcia_request_io(pdev) != 0) return -ENODEV; stk->ctl_base = pdev->resource[0]->start + 0x0e; } else @@ -245,9 +247,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) struct ata_port_operations *ops = &pcmcia_port_ops; /* Set up attributes in order to probe card and get resources */ - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - pdev->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - pdev->io.IOAddrLines = 3; + pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; pdev->conf.Attributes = CONF_ENABLE_IRQ; pdev->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 24d2007139e8..d52e90a5a617 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -865,9 +865,6 @@ static int bluecard_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; - link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -890,12 +887,14 @@ static int bluecard_config(struct pcmcia_device *link) int i, n; link->conf.ConfigIndex = 0x20; - link->io.NumPorts1 = 64; - link->io.IOAddrLines = 6; + + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 64; + link->io_lines = 6; for (n = 0; n < 0x400; n += 0x40) { - link->io.BasePort1 = n ^ 0x300; - i = pcmcia_request_io(link, &link->io); + link->resource[0]->start = n ^ 0x300; + i = pcmcia_request_io(link); if (i == 0) break; } diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 8ab494c0c17f..7ab8f29d5e0d 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -657,8 +657,8 @@ static int bt3c_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 8; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -683,14 +683,14 @@ static int bt3c_check_config(struct pcmcia_device *p_dev, { unsigned long try = (unsigned long) priv_data; + p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.IOAddrLines = (try == 0) ? 16 : - cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = cf->io.win[0].base; + if (!pcmcia_request_io(p_dev)) return 0; } return -ENODEV; @@ -707,9 +707,9 @@ static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev, if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { for (j = 0; j < 5; j++) { - p_dev->io.BasePort1 = base[j]; - p_dev->io.IOAddrLines = base[j] ? 16 : 3; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = base[j]; + p_dev->io_lines = base[j] ? 16 : 3; + if (!pcmcia_request_io(p_dev)) return 0; } } diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 7e770d40368d..1c4f5e863b03 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -586,8 +586,8 @@ static int btuart_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 8; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -612,14 +612,14 @@ static int btuart_check_config(struct pcmcia_device *p_dev, { int *try = priv_data; + p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.IOAddrLines = (*try == 0) ? 16 : - cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = cf->io.win[0].base; + if (!pcmcia_request_io(p_dev)) return 0; } return -ENODEV; @@ -636,9 +636,9 @@ static int btuart_check_config_notpicky(struct pcmcia_device *p_dev, if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { for (j = 0; j < 5; j++) { - p_dev->io.BasePort1 = base[j]; - p_dev->io.IOAddrLines = base[j] ? 16 : 3; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = base[j]; + p_dev->io_lines = base[j] ? 16 : 3; + if (!pcmcia_request_io(p_dev)) return 0; } } diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index bfe9313516fb..18ecc5734e9f 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -572,8 +572,8 @@ static int dtl1_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 8; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -597,14 +597,13 @@ static int dtl1_confcheck(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.NumPorts1 = cf->io.win[0].len; /*yo */ - p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) - return 0; - } - return -ENODEV; + if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8)) + return -ENODEV; + + p_dev->resource[0]->start = cf->io.win[0].base; + p_dev->resource[0]->end = cf->io.win[0].len; /*yo */ + p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; + return pcmcia_request_io(p_dev); } static int dtl1_config(struct pcmcia_device *link) @@ -613,7 +612,7 @@ static int dtl1_config(struct pcmcia_device *link) int i; /* Look for a generic full-sized window */ - link->io.NumPorts1 = 8; + link->resource[0]->end = 8; if (pcmcia_loop_config(link, dtl1_confcheck, NULL) < 0) goto failed; diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 18484edc1259..ec73d9f6d9ed 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1751,17 +1751,12 @@ static int cm4000_config_check(struct pcmcia_device *p_dev, if (!cfg->io.nwin) return -ENODEV; - /* Get the IOaddr */ - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(cfg->io.flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(cfg->io.flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; - - return pcmcia_request_io(p_dev, &p_dev->io); + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; + p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags); + p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK; + + return pcmcia_request_io(p_dev); } static int cm4000_config(struct pcmcia_device * link, int devno) diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index a6bbf199dde9..815cde1d0570 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -527,16 +527,12 @@ static int cm4040_config_check(struct pcmcia_device *p_dev, return -ENODEV; /* Get the IOaddr */ - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(cfg->io.flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(cfg->io.flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; - - rc = pcmcia_request_io(p_dev, &p_dev->io); + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; + p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags); + p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK; + rc = pcmcia_request_io(p_dev); + dev_printk(KERN_INFO, &p_dev->dev, "pcmcia_request_io returned 0x%x\n", rc); return rc; @@ -548,10 +544,6 @@ static int reader_config(struct pcmcia_device *link, int devno) struct reader_dev *dev; int fail_rc; - link->io.BasePort2 = 0; - link->io.NumPorts2 = 0; - link->io.Attributes2 = 0; - if (pcmcia_loop_config(link, cm4040_config_check, NULL)) goto cs_release; diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 9467994d556f..5f87b9f7b6d2 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -88,15 +88,15 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, memreq_t memreq_common_memory; int ret; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; - p_dev->io.IOAddrLines = 16; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; /* 0x40 causes it to generate level mode interrupts. */ /* 0x04 enables IREQ pin. */ p_dev->conf.ConfigIndex = cfg->index | 0x44; - ret = pcmcia_request_io(p_dev, &p_dev->io); + p_dev->io_lines = 16; + ret = pcmcia_request_io(p_dev); if (ret) return ret; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 8ded9b02b9b9..9ecd6bef5d3b 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -571,18 +571,15 @@ static int mgslpc_ioprobe(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - if (cfg->io.nwin > 0) { - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(cfg->io.flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(cfg->io.flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; - return pcmcia_request_io(p_dev, &p_dev->io); - } - return -ENODEV; + if (!cfg->io.nwin) + return -ENODEV; + + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; + p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags); + p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK; + + return pcmcia_request_io(p_dev); } static int mgslpc_config(struct pcmcia_device *link) diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index 6be0e5f108b5..2a4cb9c18f01 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c @@ -97,9 +97,8 @@ static int ide_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -228,22 +227,25 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev, if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; + pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + pdev->conf.ConfigIndex = cfg->index; - pdev->io.BasePort1 = io->win[0].base; - pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - if (!(io->flags & CISTPL_IO_16BIT)) - pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + pdev->resource[0]->start = io->win[0].base; + if (!(io->flags & CISTPL_IO_16BIT)) { + pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + } if (io->nwin == 2) { - pdev->io.NumPorts1 = 8; - pdev->io.BasePort2 = io->win[1].base; - pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1; - if (pcmcia_request_io(pdev, &pdev->io) != 0) + pdev->resource[0]->end = 8; + pdev->resource[1]->start = io->win[1].base; + pdev->resource[1]->end = (stk->is_kme) ? 2 : 1; + if (pcmcia_request_io(pdev) != 0) return -ENODEV; stk->ctl_base = pdev->resource[1]->start; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { - pdev->io.NumPorts1 = io->win[0].len; - pdev->io.NumPorts2 = 0; - if (pcmcia_request_io(pdev, &pdev->io) != 0) + pdev->resource[0]->end = io->win[0].len; + pdev->resource[1]->end = 0; + if (pcmcia_request_io(pdev) != 0) return -ENODEV; stk->ctl_base = pdev->resource[0]->start + 0x0e; } else diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 7c8c51f22003..09b1795516f4 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -75,9 +75,8 @@ static int avmcs_probe(struct pcmcia_device *p_dev) { /* The io structure describes IO port mapping */ - p_dev->io.NumPorts1 = 16; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = 16; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; @@ -119,13 +118,9 @@ static int avmcs_configcheck(struct pcmcia_device *p_dev, if (cf->io.nwin <= 0) return -ENODEV; - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.NumPorts1 = cf->io.win[0].len; - p_dev->io.NumPorts2 = 0; - printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", - p_dev->io.BasePort1, - p_dev->io.BasePort1+p_dev->io.NumPorts1-1); - return pcmcia_request_io(p_dev, &p_dev->io); + p_dev->resource[0]->start = cf->io.win[0].base; + p_dev->resource[0]->end = cf->io.win[0].len; + return pcmcia_request_io(p_dev); } static int avmcs_config(struct pcmcia_device *link) diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 88899638f835..94263c22b874 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -78,11 +78,10 @@ static int __devinit avma1cs_probe(struct pcmcia_device *p_dev) dev_dbg(&p_dev->dev, "avma1cs_attach()\n"); /* The io structure describes IO port mapping */ - p_dev->io.NumPorts1 = 16; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.NumPorts2 = 16; - p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16; - p_dev->io.IOAddrLines = 5; + p_dev->resource[0]->end = 16; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + p_dev->resource[1]->end = 16; + p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; @@ -126,13 +125,10 @@ static int avma1cs_configcheck(struct pcmcia_device *p_dev, if (cf->io.nwin <= 0) return -ENODEV; - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.NumPorts1 = cf->io.win[0].len; - p_dev->io.NumPorts2 = 0; - printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", - p_dev->io.BasePort1, - p_dev->io.BasePort1+p_dev->io.NumPorts1-1); - return pcmcia_request_io(p_dev, &p_dev->io); + p_dev->resource[0]->start = cf->io.win[0].base; + p_dev->resource[0]->end = cf->io.win[0].len; + p_dev->io_lines = 5; + return pcmcia_request_io(p_dev); } diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index c10bfd3f4588..b3c08aaf41c4 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -126,9 +126,8 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link) and attributes of IO windows) are fixed by the nature of the device, and can be hard-wired here. */ - link->io.NumPorts1 = 8; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 3; + link->resource[0]->end = 8; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -173,16 +172,18 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev, { int j; + p_dev->io_lines = 3; + if ((cf->io.nwin > 0) && cf->io.win[0].base) { printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n"); - p_dev->io.BasePort1 = cf->io.win[0].base; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = cf->io.win[0].base; + if (!pcmcia_request_io(p_dev)) return 0; } else { printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n"); for (j = 0x2f0; j > 0x100; j -= 0x10) { - p_dev->io.BasePort1 = j; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = j; + if (!pcmcia_request_io(p_dev)) return 0; } } diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index cecb35ab9d3d..4755eb440f7e 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -129,9 +129,8 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link) /* from old sedl_cs */ /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 8; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; + link->resource[0]->end = 8; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; @@ -201,23 +200,22 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + p_dev->io_lines = 3; + if (pcmcia_request_io(p_dev) != 0) return -ENODEV; } diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 3787fc70cf8f..7296102ca255 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -106,9 +106,8 @@ static int __devinit teles_probe(struct pcmcia_device *link) and attributes of IO windows) are fixed by the nature of the device, and can be hard-wired here. */ - link->io.NumPorts1 = 96; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 5; + link->resource[0]->end = 96; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -153,16 +152,18 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev, { int j; + p_dev->io_lines = 5; + if ((cf->io.nwin > 0) && cf->io.win[0].base) { printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); - p_dev->io.BasePort1 = cf->io.win[0].base; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = cf->io.win[0].base; + if (!pcmcia_request_io(p_dev)) return 0; } else { printk(KERN_INFO "(teles_cs: looks like the 97 model)\n"); for (j = 0x2f0; j > 0x100; j -= 0x10) { - p_dev->io.BasePort1 = j; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = j; + if (!pcmcia_request_io(p_dev)) return 0; } } diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index b5ea9b8cfd76..c683f77c6f42 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -278,8 +278,8 @@ static int tc574_probe(struct pcmcia_device *link) lp->p_dev = link; spin_lock_init(&lp->window_lock); - link->io.NumPorts1 = 32; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + link->resource[0]->end = 32; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; @@ -337,10 +337,11 @@ static int tc574_config(struct pcmcia_device *link) dev_dbg(&link->dev, "3c574_config()\n"); - link->io.IOAddrLines = 16; + link->io_lines = 16; + for (i = j = 0; j < 0x400; j += 0x20) { - link->io.BasePort1 = j ^ 0x300; - i = pcmcia_request_io(link, &link->io); + link->resource[0]->start = j ^ 0x300; + i = pcmcia_request_io(link); if (i == 0) break; } diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 122ef4a9488c..61f9cf2100ff 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -213,8 +213,8 @@ static int tc589_probe(struct pcmcia_device *link) lp->p_dev = link; spin_lock_init(&lp->lock); - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + link->resource[0]->end = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -277,12 +277,13 @@ static int tc589_config(struct pcmcia_device *link) "3Com card??\n"); multi = (link->card_id == PRODID_3COM_3C562); + link->io_lines = 16; + /* For the 3c562, the base address must be xx00-xx7f */ - link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x10) { if (multi && (j & 0x80)) continue; - link->io.BasePort1 = j ^ 0x300; - i = pcmcia_request_io(link, &link->io); + link->resource[0]->start = j ^ 0x300; + i = pcmcia_request_io(link); if (i == 0) break; } diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index c52fdf31cbfe..5f05ffb240cc 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -259,28 +259,30 @@ static int get_prom(struct pcmcia_device *link) static int try_io_port(struct pcmcia_device *link) { int j, ret; - if (link->io.NumPorts1 == 32) { - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; + if (link->resource[0]->end == 32) { + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; /* for master/slave multifunction cards */ - if (link->io.NumPorts2 > 0) - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + if (link->resource[1]->end > 0) + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; } else { /* This should be two 16-port windows */ - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; } - if (link->io.BasePort1 == 0) { - link->io.IOAddrLines = 16; + if (link->resource[0]->start == 0) { for (j = 0; j < 0x400; j += 0x20) { - link->io.BasePort1 = j ^ 0x300; - link->io.BasePort2 = (j ^ 0x300) + 0x10; - ret = pcmcia_request_io(link, &link->io); + link->resource[0]->start = j ^ 0x300; + link->resource[1]->start = (j ^ 0x300) + 0x10; + link->io_lines = 16; + ret = pcmcia_request_io(link); if (ret == 0) return ret; } return ret; } else { - return pcmcia_request_io(link, &link->io); + return pcmcia_request_io(link); } } @@ -301,15 +303,15 @@ static int axnet_configcheck(struct pcmcia_device *p_dev, network function with window 0, and serial with window 1 */ if (io->nwin > 1) { i = (io->win[1].len > io->win[0].len); - p_dev->io.BasePort2 = io->win[1-i].base; - p_dev->io.NumPorts2 = io->win[1-i].len; + p_dev->resource[1]->start = io->win[1-i].base; + p_dev->resource[1]->end = io->win[1-i].len; } else { - i = p_dev->io.NumPorts2 = 0; + i = p_dev->resource[1]->end = 0; } - p_dev->io.BasePort1 = io->win[i].base; - p_dev->io.NumPorts1 = io->win[i].len; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32) + p_dev->resource[0]->start = io->win[i].base; + p_dev->resource[0]->end = io->win[i].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) return try_io_port(p_dev); return -ENODEV; diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 3b53818e3eef..3c400cfa82ae 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -158,9 +158,8 @@ static int com20020_probe(struct pcmcia_device *p_dev) /* fill in our module parameters as defaults */ dev->dev_addr[0] = node; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.NumPorts1 = 16; - p_dev->io.IOAddrLines = 16; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + p_dev->resource[0]->end = 16; p_dev->conf.Attributes = CONF_ENABLE_IRQ; p_dev->conf.IntType = INT_MEMORY_AND_IO; @@ -245,20 +244,24 @@ static int com20020_config(struct pcmcia_device *link) dev_dbg(&link->dev, "com20020_config\n"); - dev_dbg(&link->dev, "baseport1 is %Xh\n", link->io.BasePort1); + dev_dbg(&link->dev, "baseport1 is %Xh\n", + (unsigned int) link->resource[0]->start); + i = -ENODEV; - if (!link->io.BasePort1) + link->io_lines = 16; + + if (!link->resource[0]->start) { for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) { - link->io.BasePort1 = ioaddr; - i = pcmcia_request_io(link, &link->io); + link->resource[0]->start = ioaddr; + i = pcmcia_request_io(link); if (i == 0) break; } } else - i = pcmcia_request_io(link, &link->io); + i = pcmcia_request_io(link); if (i != 0) { diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index bba6369a028e..699304480aed 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -248,9 +248,8 @@ static int fmvj18x_probe(struct pcmcia_device *link) lp->base = NULL; /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 32; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 5; + link->resource[0]->end = 32; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; @@ -288,13 +287,13 @@ static int mfc_try_io_port(struct pcmcia_device *link) { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; for (i = 0; i < 5; i++) { - link->io.BasePort2 = serial_base[i]; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - if (link->io.BasePort2 == 0) { - link->io.NumPorts2 = 0; + link->resource[1]->start = serial_base[i]; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; + if (link->resource[1]->start == 0) { + link->resource[1]->end = 0; printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n"); } - ret = pcmcia_request_io(link, &link->io); + ret = pcmcia_request_io(link); if (ret == 0) return ret; } @@ -310,8 +309,8 @@ static int ungermann_try_io_port(struct pcmcia_device *link) 0x380,0x3c0 only for ioport. */ for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) { - link->io.BasePort1 = ioaddr; - ret = pcmcia_request_io(link, &link->io); + link->resource[0]->start = ioaddr; + ret = pcmcia_request_io(link); if (ret == 0) { /* calculate ConfigIndex value */ link->conf.ConfigIndex = @@ -345,6 +344,8 @@ static int fmvj18x_config(struct pcmcia_device *link) dev_dbg(&link->dev, "fmvj18x_config\n"); + link->io_lines = 5; + len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); kfree(buf); @@ -363,20 +364,20 @@ static int fmvj18x_config(struct pcmcia_device *link) /* MultiFunction Card */ link->conf.ConfigBase = 0x800; link->conf.ConfigIndex = 0x47; - link->io.NumPorts2 = 8; + link->resource[1]->end = 8; } break; case MANFID_NEC: cardtype = NEC; /* MultiFunction Card */ link->conf.ConfigBase = 0x800; link->conf.ConfigIndex = 0x47; - link->io.NumPorts2 = 8; + link->resource[1]->end = 8; break; case MANFID_KME: cardtype = KME; /* MultiFunction Card */ link->conf.ConfigBase = 0x800; link->conf.ConfigIndex = 0x47; - link->io.NumPorts2 = 8; + link->resource[1]->end = 8; break; case MANFID_CONTEC: cardtype = CONTEC; @@ -417,14 +418,14 @@ static int fmvj18x_config(struct pcmcia_device *link) } } - if (link->io.NumPorts2 != 0) { + if (link->resource[1]->end != 0) { ret = mfc_try_io_port(link); if (ret != 0) goto failed; } else if (cardtype == UNGERMANN) { ret = ungermann_try_io_port(link); if (ret != 0) goto failed; } else { - ret = pcmcia_request_io(link, &link->io); + ret = pcmcia_request_io(link); if (ret) goto failed; } diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index e99abaa92be5..3fd859570db3 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -151,9 +151,8 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link) link->priv = info; info->ti = netdev_priv(dev); - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 4; - link->io.IOAddrLines = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 4; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; @@ -218,16 +217,17 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) dev_dbg(&link->dev, "ibmtr_config\n"); link->conf.ConfigIndex = 0x61; + link->io_lines = 16; /* Determine if this is PRIMARY or ALTERNATE. */ /* Try PRIMARY card at 0xA20-0xA23 */ - link->io.BasePort1 = 0xA20; - i = pcmcia_request_io(link, &link->io); + link->resource[0]->start = 0xA20; + i = pcmcia_request_io(link); if (i != 0) { /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ - link->io.BasePort1 = 0xA24; - ret = pcmcia_request_io(link, &link->io); + link->resource[0]->start = 0xA24; + ret = pcmcia_request_io(link); if (ret) goto failed; } diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 9980cbb81d34..68f2deeb3ade 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -458,9 +458,8 @@ static int nmclan_probe(struct pcmcia_device *link) link->priv = dev; spin_lock_init(&lp->bank_lock); - link->io.NumPorts1 = 32; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 5; + link->resource[0]->end = 32; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; @@ -644,7 +643,8 @@ static int nmclan_config(struct pcmcia_device *link) dev_dbg(&link->dev, "nmclan_config\n"); - ret = pcmcia_request_io(link, &link->io); + link->io_lines = 5; + ret = pcmcia_request_io(link); if (ret) goto failed; ret = pcmcia_request_exclusive_irq(link, mace_interrupt); diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index c9cd2377ef91..9c5fc9dfc55d 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -477,29 +477,31 @@ static hw_info_t *get_hwired(struct pcmcia_device *link) static int try_io_port(struct pcmcia_device *link) { int j, ret; - if (link->io.NumPorts1 == 32) { - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (link->io.NumPorts2 > 0) { + link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; + if (link->resource[0]->end == 32) { + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + if (link->resource[1]->end > 0) { /* for master/slave multifunction cards */ - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; } } else { /* This should be two 16-port windows */ - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; } - if (link->io.BasePort1 == 0) { - link->io.IOAddrLines = 16; + if (link->resource[0]->start == 0) { for (j = 0; j < 0x400; j += 0x20) { - link->io.BasePort1 = j ^ 0x300; - link->io.BasePort2 = (j ^ 0x300) + 0x10; - ret = pcmcia_request_io(link, &link->io); + link->resource[0]->start = j ^ 0x300; + link->resource[1]->start = (j ^ 0x300) + 0x10; + link->io_lines = 16; + ret = pcmcia_request_io(link); if (ret == 0) return ret; } return ret; } else { - return pcmcia_request_io(link, &link->io); + return pcmcia_request_io(link); } } @@ -520,18 +522,18 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, network function with window 0, and serial with window 1 */ if (io->nwin > 1) { i = (io->win[1].len > io->win[0].len); - p_dev->io.BasePort2 = io->win[1-i].base; - p_dev->io.NumPorts2 = io->win[1-i].len; + p_dev->resource[1]->start = io->win[1-i].base; + p_dev->resource[1]->end = io->win[1-i].len; } else { - i = p_dev->io.NumPorts2 = 0; + i = p_dev->resource[1]->end = 0; } *has_shmem = ((cfg->mem.nwin == 1) && (cfg->mem.win[0].len >= 0x4000)); - p_dev->io.BasePort1 = io->win[i].base; - p_dev->io.NumPorts1 = io->win[i].len; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32) + p_dev->resource[0]->start = io->win[i].base; + p_dev->resource[0]->end = io->win[i].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) return try_io_port(p_dev); return 0; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 1b0b3230dd71..a5e47796f6ae 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -324,9 +324,8 @@ static int smc91c92_probe(struct pcmcia_device *link) link->priv = dev; spin_lock_init(&smc->lock); - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 4; + link->resource[0]->end = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -427,12 +426,13 @@ static int mhz_mfc_config_check(struct pcmcia_device *p_dev, void *priv_data) { int k; - p_dev->io.BasePort2 = cf->io.win[0].base; + p_dev->resource[1]->start = cf->io.win[0].base; for (k = 0; k < 0x400; k += 0x10) { if (k & 0x80) continue; - p_dev->io.BasePort1 = k ^ 0x300; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = k ^ 0x300; + p_dev->io_lines = 16; + if (!pcmcia_request_io(p_dev)) return 0; } return -ENODEV; @@ -448,9 +448,8 @@ static int mhz_mfc_config(struct pcmcia_device *link) link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; - link->io.IOAddrLines = 16; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts2 = 8; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[1]->end = 8; /* The Megahertz combo cards have modem-like CIS entries, so we have to explicitly try a bunch of port combinations. */ @@ -601,9 +600,9 @@ static int smc_configcheck(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - return pcmcia_request_io(p_dev, &p_dev->io); + p_dev->resource[0]->start = cf->io.win[0].base; + p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; + return pcmcia_request_io(p_dev); } static int smc_config(struct pcmcia_device *link) @@ -611,7 +610,7 @@ static int smc_config(struct pcmcia_device *link) struct net_device *dev = link->priv; int i; - link->io.NumPorts1 = 16; + link->resource[0]->end = 16; i = pcmcia_loop_config(link, smc_configcheck, NULL); if (!i) dev->base_addr = link->resource[0]->start; @@ -646,25 +645,25 @@ static int osi_config(struct pcmcia_device *link) link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; - link->io.NumPorts1 = 64; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts2 = 8; - link->io.IOAddrLines = 16; + link->resource[0]->end = 64; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[1]->end = 8; /* Enable Hard Decode, LAN, Modem */ link->conf.ConfigIndex = 0x23; + link->io_lines = 16; for (i = j = 0; j < 4; j++) { - link->io.BasePort2 = com[j]; - i = pcmcia_request_io(link, &link->io); + link->resource[1]->start = com[j]; + i = pcmcia_request_io(link); if (i == 0) break; } if (i != 0) { /* Fallback: turn off hard decode */ link->conf.ConfigIndex = 0x03; - link->io.NumPorts2 = 0; - i = pcmcia_request_io(link, &link->io); + link->resource[1]->end = 0; + i = pcmcia_request_io(link); } dev->base_addr = link->resource[0]->start + 0x10; return i; @@ -803,7 +802,7 @@ static int check_sig(struct pcmcia_device *link) } /* Try setting bus width */ - width = (link->io.Attributes1 == IO_DATA_PATH_WIDTH_AUTO); + width = (link->resource[0]->flags == IO_DATA_PATH_WIDTH_AUTO); s = inb(ioaddr + CONFIG); if (width) s |= CFG_16BIT; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 034920b459d1..8fb0eb1dc341 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -677,9 +677,9 @@ xirc2ps_config_modem(struct pcmcia_device *p_dev, if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { - p_dev->io.BasePort2 = cf->io.win[0].base; - p_dev->io.BasePort1 = ioaddr; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[1]->start = cf->io.win[0].base; + p_dev->resource[0]->start = ioaddr; + if (!pcmcia_request_io(p_dev)) return 0; } } @@ -696,11 +696,11 @@ xirc2ps_config_check(struct pcmcia_device *p_dev, int *pass = priv_data; if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { - p_dev->io.BasePort2 = cf->io.win[0].base; - p_dev->io.BasePort1 = p_dev->io.BasePort2 + p_dev->resource[1]->start = cf->io.win[0].base; + p_dev->resource[0]->start = p_dev->resource[1]->start + (*pass ? (cf->index & 0x20 ? -24:8) : (cf->index & 0x20 ? 8:-24)); - if (!pcmcia_request_io(p_dev, &p_dev->io)) + if (!pcmcia_request_io(p_dev)) return 0; } return -ENODEV; @@ -807,8 +807,7 @@ xirc2ps_config(struct pcmcia_device * link) goto failure; } - link->io.IOAddrLines =10; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; if (local->modem) { int pass; @@ -816,16 +815,16 @@ xirc2ps_config(struct pcmcia_device * link) link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status |= CCSR_AUDIO_ENA; } - link->io.NumPorts2 = 8; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + link->resource[1]->end = 8; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; if (local->dingo) { /* Take the Modem IO port from the CIS and scan for a free * Ethernet port */ - link->io.NumPorts1 = 16; /* no Mako stuff anymore */ + link->resource[0]->end = 16; /* no Mako stuff anymore */ if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL)) goto port_found; } else { - link->io.NumPorts1 = 18; + link->resource[0]->end = 18; /* We do 2 passes here: The first one uses the regular mapping and * the second tries again, thereby considering that the 32 ports are * mirrored every 32 bytes. Actually we use a mirrored port for @@ -840,14 +839,15 @@ xirc2ps_config(struct pcmcia_device * link) } printk(KNOT_XIRC "no ports available\n"); } else { - link->io.NumPorts1 = 16; + link->io_lines = 10; + link->resource[0]->end = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { - link->io.BasePort1 = ioaddr; - if (!(err=pcmcia_request_io(link, &link->io))) + link->resource[0]->start = ioaddr; + if (!(err = pcmcia_request_io(link))) goto port_found; } - link->io.BasePort1 = 0; /* let CS decide */ - if ((err=pcmcia_request_io(link, &link->io))) + link->resource[0]->start = 0; /* let CS decide */ + if ((err = pcmcia_request_io(link))) goto config_error; } port_found: diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index b7e7f5054e44..d241b4aed71e 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -175,25 +175,23 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) return -ENODEV; /* diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 65b3aed49e58..3b632161c106 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -190,25 +190,23 @@ static int atmel_config_check(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } } /* This reserves IO space but doesn't actually enable it */ - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } static int atmel_config(struct pcmcia_device *link) diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index f71bc7821378..7c9af82fcf7e 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -77,10 +77,6 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) dev->conf.Attributes = CONF_ENABLE_IRQ; dev->conf.IntType = INT_MEMORY_AND_IO; - dev->io.BasePort2 = 0; - dev->io.NumPorts2 = 0; - dev->io.Attributes2 = 0; - win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_DATA_WIDTH_16 | WIN_USE_WAIT; diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 4e13cedb8235..ba54d1b04d22 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -519,30 +519,24 @@ static int prism2_config_check(struct pcmcia_device *p_dev, PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " "dflt->io.nwin=%d\n", cfg->io.nwin, dflt->io.nwin); - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " - "io.base=0x%04x, len=%d\n", io->flags, - io->win[0].base, io->win[0].len); - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & - CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } } /* This reserves IO space but doesn't actually enable it */ - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } static int prism2_config(struct pcmcia_device *link) diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index be4c47594b59..9c298396be50 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -801,9 +801,9 @@ static int if_cs_ioprobe(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; /* Do we need to allocate an interrupt? */ p_dev->conf.Attributes |= CONF_ENABLE_IRQ; @@ -815,7 +815,7 @@ static int if_cs_ioprobe(struct pcmcia_device *p_dev, } /* This reserves IO space but doesn't actually enable it */ - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } static int if_cs_probe(struct pcmcia_device *p_dev) diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 6d514b5462fd..ef46a2d88539 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -191,25 +191,23 @@ static int orinoco_cs_config_check(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) goto next_entry; } return 0; diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 4f8f55eab955..873877e17e1b 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -253,25 +253,23 @@ static int spectrum_cs_config_check(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) goto next_entry; } return 0; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 165beb6af849..b83d5ef1dffe 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -315,9 +315,8 @@ static int ray_probe(struct pcmcia_device *p_dev) local->finder = p_dev; /* The io structure describes IO port mapping. None used here */ - p_dev->io.NumPorts1 = 0; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = 5; + p_dev->resource[0]->end = 0; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index a32f220648c0..a1cc2d498a1c 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1884,9 +1884,8 @@ static int wl3501_probe(struct pcmcia_device *p_dev) struct wl3501_card *this; /* The io structure describes IO port mapping */ - p_dev->io.NumPorts1 = 16; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = 5; + p_dev->resource[0]->end = 16; + p_dev->resource[0]->flags = IO_DATA_PATH_WIDTH_8; /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; @@ -1932,13 +1931,14 @@ static int wl3501_config(struct pcmcia_device *link) /* Try allocating IO ports. This tries a few fixed addresses. If you * want, you can also read the card's config table to pick addresses -- * see the serial driver for an example. */ + link->io_lines = 5; for (j = 0x280; j < 0x400; j += 0x20) { /* The '^0x300' is so that we probe 0x300-0x3ff first, then * 0x200-0x2ff, and so on, because this seems safer */ - link->io.BasePort1 = j; - link->io.BasePort2 = link->io.BasePort1 + 0x10; - i = pcmcia_request_io(link, &link->io); + link->resource[0]->start = j; + link->resource[1]->start = link->resource[0]->start + 0x10; + i = pcmcia_request_io(link); if (i == 0) break; } diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index fc1639c5ada6..23e50f4a27c5 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -101,8 +101,8 @@ static int parport_probe(struct pcmcia_device *link) link->priv = info; info->p_dev = link; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -143,16 +143,16 @@ static int parport_config_check(struct pcmcia_device *p_dev, { if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; if (epp_mode) p_dev->conf.ConfigIndex |= FORCE_EPP_MODE; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin == 2) { - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) return -ENODEV; return 0; } diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index fcd48dae79bc..a48d4a91d440 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -70,7 +70,8 @@ static int alloc_io_space(struct pcmcia_socket *s, struct resource *res, res->flags |= IORESOURCE_IO; - dev_dbg(&s->dev, "alloc_io_space request for %pR\n", res); + dev_dbg(&s->dev, "alloc_io_space request for %pR, %d lines\n", + res, lines); align = base ? (lines ? 1<resource[0] and *p_dev->resource[1]. The + * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The * "start" value is the requested start of the IO port resource; "end" - * relfects the number of ports requested. - * - * If io_req_t is passed, those values are converted automatically. + * reflects the number of ports requested. The number of IO lines requested + * is specified in &struct pcmcia_device @p_dev->io_lines. */ -int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) +int pcmcia_request_io(struct pcmcia_device *p_dev) { struct pcmcia_socket *s = p_dev->socket; - config_t *c; + config_t *c = p_dev->function_config; int ret = -EINVAL; - unsigned int lines = req->IOAddrLines; mutex_lock(&s->ops_mutex); + dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]); if (!(s->state & SOCKET_PRESENT)) { dev_dbg(&s->dev, "pcmcia_request_io: No card present\n"); goto out; } - c = p_dev->function_config; - if (req) { - c->io[0].start = req->BasePort1; - c->io[0].end = req->NumPorts1; - c->io[0].flags |= req->Attributes1; - c->io[1].start = req->BasePort2; - c->io[1].end = req->NumPorts2; - c->io[1].flags |= req->Attributes2; - } - - dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]); - if (c->state & CONFIG_LOCKED) { dev_dbg(&s->dev, "Configuration is locked\n"); goto out; @@ -582,12 +570,12 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) goto out; } - ret = alloc_io_space(s, &c->io[0], lines); + ret = alloc_io_space(s, &c->io[0], p_dev->io_lines); if (ret) goto out; if (c->io[1].end) { - ret = alloc_io_space(s, &c->io[1], lines); + ret = alloc_io_space(s, &c->io[1], p_dev->io_lines); if (ret) { release_io_space(s, &c->io[0]); goto out; @@ -598,11 +586,6 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) c->state |= CONFIG_IO_REQ; p_dev->_io = 1; - if (!ret) { - req->BasePort1 = c->io[0].start; - req->BasePort2 = c->io[1].start; - } - dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR", &c->io[0], &c->io[1]); out: diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 3e040f503afa..61f49bdcc0c2 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -100,9 +100,8 @@ static int aha152x_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.NumPorts1 = 0x20; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; + link->resource[0]->end = 0x20; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; @@ -130,15 +129,16 @@ static int aha152x_config_check(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { + p_dev->io_lines = 10; /* For New Media T&J, look for a SCSI window */ if (cfg->io.win[0].len >= 0x20) - p_dev->io.BasePort1 = cfg->io.win[0].base; + p_dev->resource[0]->start = cfg->io.win[0].base; else if ((cfg->io.nwin > 1) && (cfg->io.win[1].len >= 0x20)) - p_dev->io.BasePort1 = cfg->io.win[1].base; + p_dev->resource[0]->start = cfg->io.win[1].base; if ((cfg->io.nwin > 0) && - (p_dev->io.BasePort1 < 0xffff)) { - if (!pcmcia_request_io(p_dev, &p_dev->io)) + (p_dev->resource[0]->start < 0xffff)) { + if (!pcmcia_request_io(p_dev)) return 0; } return -EINVAL; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 49a9a0a60c82..13dbe5c48492 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -83,9 +83,8 @@ static int fdomain_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.NumPorts1 = 0x10; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; + link->resource[0]->end = 0x10; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; @@ -112,8 +111,9 @@ static int fdomain_config_check(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - p_dev->io.BasePort1 = cfg->io.win[0].base; - return pcmcia_request_io(p_dev, &p_dev->io); + p_dev->io_lines = 10; + p_dev->resource[0]->start = cfg->io.win[0].base; + return pcmcia_request_io(p_dev); } diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index d929891809ab..8bb598bb440d 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1558,9 +1558,8 @@ static int nsp_cs_probe(struct pcmcia_device *link) nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info); /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 0x10; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; /* not used */ + link->resource[0]->end = 0x10; + link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO; /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; @@ -1641,24 +1640,23 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = + p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) goto next_entry; } diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 4e2b83f26232..eb775f1a523c 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -156,9 +156,8 @@ static int qlogic_probe(struct pcmcia_device *link) return -ENOMEM; info->p_dev = link; link->priv = info; - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; + link->resource[0]->end = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; @@ -185,13 +184,14 @@ static int qlogic_config_check(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; + p_dev->io_lines = 10; + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; - if (p_dev->io.BasePort1 == 0) + if (p_dev->resource[0]->start == 0) return -ENODEV; - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } static int qlogic_config(struct pcmcia_device * link) diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index d99c0cbad2de..321e390c9120 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -690,13 +690,14 @@ static int SYM53C500_config_check(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; + p_dev->io_lines = 10; + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; - if (p_dev->io.BasePort1 == 0) + if (p_dev->resource[0]->start == 0) return -ENODEV; - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } static int @@ -858,9 +859,8 @@ SYM53C500_probe(struct pcmcia_device *link) return -ENOMEM; info->p_dev = link; link->priv = info; - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; + link->resource[0]->end = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index fe7adcdfde9e..141c69554bd4 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -335,8 +335,8 @@ static int serial_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 8; link->conf.Attributes = CONF_ENABLE_IRQ; if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; @@ -424,12 +424,13 @@ static int simple_config_check(struct pcmcia_device *p_dev, p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + p_dev->io_lines = ((*try & 0x1) == 0) ? + 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)]) && (cf->io.win[0].base != 0)) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ? - 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = cf->io.win[0].base; + if (!pcmcia_request_io(p_dev)) return 0; } return -EINVAL; @@ -446,9 +447,9 @@ static int simple_config_check_notpicky(struct pcmcia_device *p_dev, if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { for (j = 0; j < 5; j++) { - p_dev->io.BasePort1 = base[j]; - p_dev->io.IOAddrLines = base[j] ? 16 : 3; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = base[j]; + p_dev->io_lines = base[j] ? 16 : 3; + if (!pcmcia_request_io(p_dev)) return 0; } } @@ -521,9 +522,9 @@ static int multi_config_check(struct pcmcia_device *p_dev, /* The quad port cards have bad CIS's, so just look for a window larger than 8 ports and assume it will be right */ if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) { + p_dev->resource[0]->start = cf->io.win[0].base; + p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; + if (!pcmcia_request_io(p_dev)) { *base2 = p_dev->resource[0]->start + 8; return 0; } @@ -540,10 +541,10 @@ static int multi_config_check_notpicky(struct pcmcia_device *p_dev, int *base2 = priv_data; if (cf->io.nwin == 2) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.BasePort2 = cf->io.win[1].base; - p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) { + p_dev->resource[0]->start = cf->io.win[0].base; + p_dev->resource[1]->start = cf->io.win[1].base; + p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; + if (!pcmcia_request_io(p_dev)) { *base2 = p_dev->resource[1]->start; return 0; } @@ -557,10 +558,10 @@ static int multi_config(struct pcmcia_device *link) int i, base2 = 0; /* First, look for a generic full-sized window */ - link->io.NumPorts1 = info->multi * 8; + link->resource[0]->end = info->multi * 8; if (pcmcia_loop_config(link, multi_config_check, &base2)) { /* If that didn't work, look for two windows */ - link->io.NumPorts1 = link->io.NumPorts2 = 8; + link->resource[0]->end = link->resource[1]->end = 8; info->multi = 2; if (pcmcia_loop_config(link, multi_config_check_notpicky, &base2)) { diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 208f1b7a1312..7cf0ccb5adef 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -736,24 +736,22 @@ static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } return 0; diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index c4cfcffc633e..9ee677f14b66 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -224,24 +224,23 @@ static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } return 0; } diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 6d569579d677..7e41ad93703d 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -571,24 +571,22 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) return -ENODEV; } diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 29e1daf6a9e6..b2483f86c242 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -323,24 +323,22 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) return -ENODEV; } diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index fb10987a97b2..c1444b4a5b4c 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -301,24 +301,22 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) return -ENODEV; } diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index f37dc22b4dbc..d50b6c409fe7 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -264,8 +264,8 @@ static const dev_info_t dev_info = "ni_mio_cs"; static int cs_attach(struct pcmcia_device *link) { - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->io.NumPorts1 = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; + link->resource[0]->end = 16; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -310,13 +310,12 @@ static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, { int base, ret; - p_dev->io.NumPorts1 = cfg->io.win[0].len; - p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; - p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = cfg->io.win[0].len; + p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK; for (base = 0x000; base < 0x400; base += 0x20) { - p_dev->io.BasePort1 = base; - ret = pcmcia_request_io(p_dev, &p_dev->io); + p_dev->resource[0]->start = base; + ret = pcmcia_request_io(p_dev); if (!ret) return 0; } diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 80b8d57c6842..25f4e67e3e89 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -1102,26 +1102,24 @@ static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } } /* This reserves IO space but doesn't actually enable it */ - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } static void daqp_cs_config(struct pcmcia_device *link) diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c index 23615378acf1..f15afd2050be 100644 --- a/drivers/staging/wlags49_h2/wl_cs.c +++ b/drivers/staging/wlags49_h2/wl_cs.c @@ -145,9 +145,8 @@ static int wl_adapter_attach(struct pcmcia_device *link) return -ENOMEM; } - link->io.NumPorts1 = HCF_NUM_IO_PORTS; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->io.IOAddrLines = 6; + link->resource[0]->end = HCF_NUM_IO_PORTS; + link->resource[0]->flags = IO_DATA_PATH_WIDTH_16; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 5; @@ -305,8 +304,9 @@ void wl_adapter_insert( struct pcmcia_device *link ) /* Do we need to allocate an interrupt? */ link->conf.Attributes |= CONF_ENABLE_IRQ; + link->io_lines = 6; - ret = pcmcia_request_io(link, &link->io); + ret = pcmcia_request_io(link); if (ret != 0) goto failed; diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index a801036392cd..a1900e502518 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -32,9 +32,8 @@ static int ixj_probe(struct pcmcia_device *p_dev) { dev_dbg(&p_dev->dev, "ixj_attach()\n"); /* Create new ixj device */ - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = 3; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; p_dev->conf.IntType = INT_MEMORY_AND_IO; p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL); if (!p_dev->priv) { @@ -120,13 +119,14 @@ static int ixj_config_check(struct pcmcia_device *p_dev, { if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; + p_dev->io_lines = 3; if (io->nwin == 2) { - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } - if (!pcmcia_request_io(p_dev, &p_dev->io)) + if (!pcmcia_request_io(p_dev)) return 0; } return -ENODEV; diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 22e04f206304..0e13a00eb2ed 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -162,16 +162,16 @@ static int sl811_cs_config_check(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } pcmcia_disable_device(p_dev); return -ENODEV; diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 0cd8c70d8aaa..ad71bb5a8658 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -56,23 +56,6 @@ typedef struct config_req_t { #define INT_CARDBUS 0x04 #define INT_ZOOMED_VIDEO 0x08 -/* For RequestIO and ReleaseIO */ -typedef struct io_req_t { - u_int BasePort1; - u_int NumPorts1; - u_int Attributes1; - u_int BasePort2; - u_int NumPorts2; - u_int Attributes2; - u_int IOAddrLines; -} io_req_t; - -/* Attributes for RequestIO and ReleaseIO */ -#define IO_DATA_PATH_WIDTH 0x18 -#define IO_DATA_PATH_WIDTH_8 0x00 -#define IO_DATA_PATH_WIDTH_16 0x08 -#define IO_DATA_PATH_WIDTH_AUTO 0x10 - /* Bits in IRQInfo1 field */ #define IRQ_NMI_ID 0x01 #define IRQ_IOCK_ID 0x02 diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 3dafd7db34df..0748bec0a87a 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -80,7 +80,6 @@ struct pcmcia_device { struct list_head socket_device_list; /* deprecated, will be cleaned up soon */ - io_req_t io; config_req_t conf; window_handle_t win; @@ -88,6 +87,8 @@ struct pcmcia_device { unsigned int irq; struct resource *resource[MAX_IO_WIN]; + unsigned int io_lines; /* number of I/O lines */ + /* Is the device suspended? */ u16 suspended:1; @@ -179,7 +180,7 @@ int pcmcia_read_config_byte(struct pcmcia_device *p_dev, off_t where, u8 *val); int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val); /* device configuration */ -int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req); +int pcmcia_request_io(struct pcmcia_device *p_dev); int __must_check __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, @@ -206,6 +207,22 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t win, int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod); void pcmcia_disable_device(struct pcmcia_device *p_dev); +/* IO ports */ +#define IO_DATA_PATH_WIDTH 0x18 +#define IO_DATA_PATH_WIDTH_8 0x00 +#define IO_DATA_PATH_WIDTH_16 0x08 +#define IO_DATA_PATH_WIDTH_AUTO 0x10 + +/* convert flag found in cfgtable to data path width parameter */ +static inline int pcmcia_io_cfg_data_width(unsigned int flags) +{ + if (!(flags & CISTPL_IO_8BIT)) + return IO_DATA_PATH_WIDTH_16; + if (!(flags & CISTPL_IO_16BIT)) + return IO_DATA_PATH_WIDTH_8; + return IO_DATA_PATH_WIDTH_AUTO; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_DS_H */ diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 9f897bca0615..7ab9174a8a84 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -139,8 +139,8 @@ static int snd_pdacf_probe(struct pcmcia_device *link) pdacf->p_dev = link; link->priv = pdacf; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.NumPorts1 = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + link->resource[0]->end = 16; link->conf.Attributes = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -219,7 +219,7 @@ static int pdacf_config(struct pcmcia_device *link) snd_printdd(KERN_DEBUG "pdacf_config called\n"); link->conf.ConfigIndex = 0x5; - ret = pcmcia_request_io(link, &link->io); + ret = pcmcia_request_io(link); if (ret) goto failed; diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index f23c235013a4..a6edfc3be29a 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -159,8 +159,8 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl, vxp->p_dev = link; link->priv = chip; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.NumPorts1 = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + link->resource[0]->end = 16; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; @@ -226,7 +226,7 @@ static int vxpocket_config(struct pcmcia_device *link) strcpy(chip->card->driver, vxp440_hw.name); } - ret = pcmcia_request_io(link, &link->io); + ret = pcmcia_request_io(link); if (ret) goto failed; -- cgit v1.2.3 From b5cb259e7fac5536c4ddf350af6a3d6cc950e47e Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 24 Jul 2010 18:46:42 +0200 Subject: pcmcia: remove memreq_t Page already had to be set to 0; Offset can easily be passed as parameter to pcmcia_map_mem_page. CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-ide@vger.kernel.org CC: linux-usb@vger.kernel.org CC: laforge@gnumonks.org CC: linux-mtd@lists.infradead.org CC: linux-bluetooth@vger.kernel.org CC: alsa-devel@alsa-project.org CC: linux-serial@vger.kernel.org CC: Michael Buesch Signed-off-by: Dominik Brodowski --- drivers/char/pcmcia/ipwireless/main.c | 14 ++------------ drivers/isdn/hisax/sedlbauer_cs.c | 7 +++---- drivers/mtd/maps/pcmciamtd.c | 13 ++++++------- drivers/net/pcmcia/fmvj18x_cs.c | 10 ++-------- drivers/net/pcmcia/ibmtr_cs.c | 11 +++-------- drivers/net/pcmcia/pcnet_cs.c | 14 ++++---------- drivers/net/pcmcia/smc91c92_cs.c | 9 +++------ drivers/net/pcmcia/xirc2ps_cs.c | 5 +---- drivers/net/wireless/airo_cs.c | 6 ++---- drivers/net/wireless/b43/pcmcia.c | 5 +---- drivers/net/wireless/ray_cs.c | 13 +++---------- drivers/pcmcia/pcmcia_resource.c | 9 +++------ drivers/scsi/pcmcia/nsp_cs.c | 5 ++--- drivers/staging/comedi/drivers/ni_daq_700.c | 6 ++---- drivers/staging/comedi/drivers/ni_daq_dio24.c | 6 ++---- drivers/staging/comedi/drivers/ni_labpc_cs.c | 6 ++---- include/pcmcia/cs.h | 6 ------ include/pcmcia/ds.h | 2 +- 18 files changed, 42 insertions(+), 105 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 5f87b9f7b6d2..6c4aa4b0be99 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -84,8 +84,6 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, { struct ipw_dev *ipw = priv_data; struct resource *io_resource; - memreq_t memreq_attr_memory; - memreq_t memreq_common_memory; int ret; p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; @@ -121,11 +119,8 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, if (ret != 0) goto exit1; - memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr; - memreq_common_memory.Page = 0; - ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory, - &memreq_common_memory); + cfg->mem.win[0].card_addr); if (ret != 0) goto exit2; @@ -150,12 +145,7 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, if (ret != 0) goto exit2; - memreq_attr_memory.CardOffset = 0; - memreq_attr_memory.Page = 0; - - ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, - &memreq_attr_memory); - + ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, 0); if (ret != 0) goto exit3; diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 4755eb440f7e..0b06dbb2d52d 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -232,7 +232,6 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, */ if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; - memreq_t map; req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; req->Attributes |= WIN_ENABLE; req->Base = mem->win[0].host_addr; @@ -240,9 +239,9 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, req->AccessSpeed = 0; if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0) return -ENODEV; - map.Page = 0; - map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0) + + if (pcmcia_map_mem_page(p_dev, p_dev->win, + mem->win[0].card_addr) != 0) return -ENODEV; } return 0; diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 79488164e432..f97463ecfc5e 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -102,7 +102,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) { struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; window_handle_t win = (window_handle_t)map->map_priv_2; - memreq_t mrq; + unsigned int offset; int ret; if (!pcmcia_dev_present(dev->p_dev)) { @@ -110,15 +110,14 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) return 0; } - mrq.CardOffset = to & ~(dev->win_size-1); - if(mrq.CardOffset != dev->offset) { + offset = to & ~(dev->win_size-1); + if (offset != dev->offset) { DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x", - dev->offset, mrq.CardOffset); - mrq.Page = 0; - ret = pcmcia_map_mem_page(dev->p_dev, win, &mrq); + dev->offset, offset); + ret = pcmcia_map_mem_page(dev->p_dev, win, offset); if (ret != 0) return NULL; - dev->offset = mrq.CardOffset; + dev->offset = offset; } return dev->win_base + (to & (dev->win_size-1)); } diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 699304480aed..98fffb03ecd7 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -545,7 +545,6 @@ failed: static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) { win_req_t req; - memreq_t mem; u_char __iomem *base; int i, j; @@ -558,9 +557,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) return -1; base = ioremap(req.Base, req.Size); - mem.Page = 0; - mem.CardOffset = 0; - pcmcia_map_mem_page(link, link->win, &mem); + pcmcia_map_mem_page(link, link->win, 0); /* * MBH10304 CISTPL_FUNCE_LAN_NODE_ID format @@ -594,7 +591,6 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) static int fmvj18x_setup_mfc(struct pcmcia_device *link) { win_req_t req; - memreq_t mem; int i; struct net_device *dev = link->priv; unsigned int ioaddr; @@ -614,9 +610,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link) return -1; } - mem.Page = 0; - mem.CardOffset = 0; - i = pcmcia_map_mem_page(link, link->win, &mem); + i = pcmcia_map_mem_page(link, link->win, 0); if (i != 0) { iounmap(lp->base); lp->base = NULL; diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 3fd859570db3..c0b3cdd49c6a 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -211,7 +211,6 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) struct net_device *dev = info->dev; struct tok_info *ti = netdev_priv(dev); win_req_t req; - memreq_t mem; int i, ret; dev_dbg(&link->dev, "ibmtr_config\n"); @@ -250,9 +249,7 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) if (ret) goto failed; - mem.CardOffset = mmiobase; - mem.Page = 0; - ret = pcmcia_map_mem_page(link, link->win, &mem); + ret = pcmcia_map_mem_page(link, link->win, mmiobase); if (ret) goto failed; ti->mmio = ioremap(req.Base, req.Size); @@ -267,13 +264,11 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) if (ret) goto failed; - mem.CardOffset = srambase; - mem.Page = 0; - ret = pcmcia_map_mem_page(link, info->sram_win_handle, &mem); + ret = pcmcia_map_mem_page(link, info->sram_win_handle, srambase); if (ret) goto failed; - ti->sram_base = mem.CardOffset >> 12; + ti->sram_base = srambase >> 12; ti->sram_virt = ioremap(req.Base, req.Size); ti->sram_phys = req.Base; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 9c5fc9dfc55d..c3edfe4c2651 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -301,7 +301,6 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link) { struct net_device *dev = link->priv; win_req_t req; - memreq_t mem; u_char __iomem *base, *virt; int i, j; @@ -314,10 +313,8 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link) return NULL; virt = ioremap(req.Base, req.Size); - mem.Page = 0; for (i = 0; i < NR_INFO; i++) { - mem.CardOffset = hw_info[i].offset & ~(req.Size-1); - pcmcia_map_mem_page(link, link->win, &mem); + pcmcia_map_mem_page(link, link->win, hw_info[i].offset & ~(req.Size-1)); base = &virt[hw_info[i].offset & (req.Size-1)]; if ((readb(base+0) == hw_info[i].a0) && (readb(base+2) == hw_info[i].a1) && @@ -1463,7 +1460,6 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg, struct net_device *dev = link->priv; pcnet_dev_t *info = PRIV(dev); win_req_t req; - memreq_t mem; int i, window_size, offset, ret; window_size = (stop_pg - start_pg) << 8; @@ -1482,11 +1478,9 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg, if (ret) goto failed; - mem.CardOffset = (start_pg << 8) + cm_offset; - offset = mem.CardOffset % window_size; - mem.CardOffset -= offset; - mem.Page = 0; - ret = pcmcia_map_mem_page(link, link->win, &mem); + offset = (start_pg << 8) + cm_offset; + offset -= offset % window_size; + ret = pcmcia_map_mem_page(link, link->win, offset); if (ret) goto failed; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index a5e47796f6ae..377367d03b41 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -443,7 +443,7 @@ static int mhz_mfc_config(struct pcmcia_device *link) struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); win_req_t req; - memreq_t mem; + unsigned int offset; int i; link->conf.Attributes |= CONF_ENABLE_SPKR; @@ -467,11 +467,8 @@ static int mhz_mfc_config(struct pcmcia_device *link) return -ENODEV; smc->base = ioremap(req.Base, req.Size); - mem.CardOffset = mem.Page = 0; - if (smc->manfid == MANFID_MOTOROLA) - mem.CardOffset = link->conf.ConfigBase; - i = pcmcia_map_mem_page(link, link->win, &mem); - + offset = (smc->manfid == MANFID_MOTOROLA) ? link->conf.ConfigBase : 0; + i = pcmcia_map_mem_page(link, link->win, offset); if ((i == 0) && (smc->manfid == MANFID_MEGAHERTZ) && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 8fb0eb1dc341..4eb6f986703b 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -870,7 +870,6 @@ xirc2ps_config(struct pcmcia_device * link) if (local->dingo) { win_req_t req; - memreq_t mem; /* Reset the modem's BAR to the correct value * This is necessary because in the RequestConfiguration call, @@ -898,9 +897,7 @@ xirc2ps_config(struct pcmcia_device * link) goto config_error; local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; - mem.CardOffset = 0x0; - mem.Page = 0; - if ((err = pcmcia_map_mem_page(link, link->win, &mem))) + if ((err = pcmcia_map_mem_page(link, link->win, 0))) goto config_error; /* Setup the CCRs; there are no infos in the CIS about the Ethernet diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index d241b4aed71e..d47672cb4196 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -207,16 +207,14 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev, */ if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; - memreq_t map; req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; req->Base = mem->win[0].host_addr; req->Size = mem->win[0].len; req->AccessSpeed = 0; if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0) return -ENODEV; - map.Page = 0; - map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0) + if (pcmcia_map_mem_page(p_dev, p_dev->win, + mem->win[0].card_addr) != 0) return -ENODEV; } /* If we got this far, we're cool! */ diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 7c9af82fcf7e..ffe1f89d5f72 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -64,7 +64,6 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) { struct ssb_bus *ssb; win_req_t win; - memreq_t mem; int err = -ENOMEM; int res = 0; @@ -87,9 +86,7 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) if (res != 0) goto err_kfree_ssb; - mem.CardOffset = 0; - mem.Page = 0; - res = pcmcia_map_mem_page(dev, dev->win, &mem); + res = pcmcia_map_mem_page(dev, dev->win, 0); if (res != 0) goto err_disable; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index b83d5ef1dffe..7eb339af351b 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -393,7 +393,6 @@ static int ray_config(struct pcmcia_device *link) int ret = 0; int i; win_req_t req; - memreq_t mem; struct net_device *dev = (struct net_device *)link->priv; ray_dev_t *local = netdev_priv(dev); @@ -430,9 +429,7 @@ static int ray_config(struct pcmcia_device *link) ret = pcmcia_request_window(link, &req, &link->win); if (ret) goto failed; - mem.CardOffset = 0x0000; - mem.Page = 0; - ret = pcmcia_map_mem_page(link, link->win, &mem); + ret = pcmcia_map_mem_page(link, link->win, 0); if (ret) goto failed; local->sram = ioremap(req.Base, req.Size); @@ -446,9 +443,7 @@ static int ray_config(struct pcmcia_device *link) ret = pcmcia_request_window(link, &req, &local->rmem_handle); if (ret) goto failed; - mem.CardOffset = 0x8000; - mem.Page = 0; - ret = pcmcia_map_mem_page(link, local->rmem_handle, &mem); + ret = pcmcia_map_mem_page(link, local->rmem_handle, 0x8000); if (ret) goto failed; local->rmem = ioremap(req.Base, req.Size); @@ -462,9 +457,7 @@ static int ray_config(struct pcmcia_device *link) ret = pcmcia_request_window(link, &req, &local->amem_handle); if (ret) goto failed; - mem.CardOffset = 0x0000; - mem.Page = 0; - ret = pcmcia_map_mem_page(link, local->amem_handle, &mem); + ret = pcmcia_map_mem_page(link, local->amem_handle, 0); if (ret) goto failed; local->amem = ioremap(req.Base, req.Size); diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index a48d4a91d440..975baaa8168b 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -193,7 +193,7 @@ EXPORT_SYMBOL(pcmcia_write_config_byte); int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, - memreq_t *req) + unsigned int offset) { struct pcmcia_socket *s = p_dev->socket; int ret; @@ -201,12 +201,9 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, wh--; if (wh >= MAX_WIN) return -EINVAL; - if (req->Page != 0) { - dev_dbg(&s->dev, "failure: requested page is zero\n"); - return -EINVAL; - } + mutex_lock(&s->ops_mutex); - s->win[wh].card_start = req->CardOffset; + s->win[wh].card_start = offset; ret = s->ops->set_mem_map(s, &s->win[wh]); if (ret) dev_warn(&s->dev, "failed to set_mem_map\n"); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 8bb598bb440d..dd9b40306f3d 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1661,7 +1661,6 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev, } if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { - memreq_t map; cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; @@ -1673,8 +1672,8 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev, cfg_mem->req.AccessSpeed = 0; if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0) goto next_entry; - map.Page = 0; map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0) + if (pcmcia_map_mem_page(p_dev, p_dev->win, + mem->win[0].card_addr) != 0) goto next_entry; cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size); diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 7e41ad93703d..abaa40b8be7e 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -556,7 +556,6 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) { win_req_t *req = priv_data; - memreq_t map; if (cfg->index == 0) return -ENODEV; @@ -602,9 +601,8 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev, req->AccessSpeed = 0; if (pcmcia_request_window(p_dev, req, &p_dev->win)) return -ENODEV; - map.Page = 0; - map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev, p_dev->win, &map)) + if (pcmcia_map_mem_page(p_dev, p_dev->win, + mem->win[0].card_addr)) return -ENODEV; } /* If we got this far, we're cool! */ diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index b2483f86c242..caccece20855 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -308,7 +308,6 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) { win_req_t *req = priv_data; - memreq_t map; if (cfg->index == 0) return -ENODEV; @@ -354,9 +353,8 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev, req->AccessSpeed = 0; if (pcmcia_request_window(p_dev, req, &p_dev->win)) return -ENODEV; - map.Page = 0; - map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev, p_dev->win, &map)) + if (pcmcia_map_mem_page(p_dev, p_dev->win, + mem->win[0].card_addr)) return -ENODEV; } /* If we got this far, we're cool! */ diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index c1444b4a5b4c..94d9f7fe6f2c 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -286,7 +286,6 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) { win_req_t *req = priv_data; - memreq_t map; if (cfg->index == 0) return -ENODEV; @@ -332,9 +331,8 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev, req->AccessSpeed = 0; if (pcmcia_request_window(p_dev, req, &p_dev->win)) return -ENODEV; - map.Page = 0; - map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev, p_dev->win, &map)) + if (pcmcia_map_mem_page(p_dev, p_dev->win, + mem->win[0].card_addr)) return -ENODEV; } /* If we got this far, we're cool! */ diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 583a4e33039a..e4faf4420f2a 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -68,12 +68,6 @@ typedef struct config_req_t { #define PRESENT_IOBASE_3 0x100 #define PRESENT_IOSIZE 0x200 -/* For GetMemPage, MapMemPage */ -typedef struct memreq_t { - u_int CardOffset; - u_short Page; -} memreq_t; - /* For RequestWindow */ typedef struct win_req_t { u_int Attributes; diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 0748bec0a87a..a2bf3a702c08 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -202,7 +202,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh); int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t win); int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t win, - memreq_t *req); + unsigned int offset); int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod); void pcmcia_disable_device(struct pcmcia_device *p_dev); -- cgit v1.2.3 From 3577dc76fc92c45ff61f8fa85b90e872755796d1 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 28 Jul 2010 22:09:21 -0700 Subject: scsi: Remove owner field from attribute initialization in LPFC driver Signed-off-by: Guenter Roeck Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/lpfc/lpfc_attr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 868874c28f99..162704cf6a96 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2778,7 +2778,6 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = { .attr = { .name = "lpfc_drvr_stat_data", .mode = S_IRUSR, - .owner = THIS_MODULE, }, .size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET, .read = sysfs_drvr_stat_data_read, -- cgit v1.2.3 From cf9e82a8a03cee3c4ffe0a23ca0f17bd57b3cc60 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 28 Jul 2010 22:09:22 -0700 Subject: scsi: Remove owner field from attribute initialization in ARCMSR driver Signed-off-by: Guenter Roeck Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/arcmsr/arcmsr_attr.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 07fdfe57e38e..a4e04c50c436 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -192,7 +192,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { .attr = { .name = "mu_read", .mode = S_IRUSR , - .owner = THIS_MODULE, }, .size = 1032, .read = arcmsr_sysfs_iop_message_read, @@ -202,7 +201,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { .attr = { .name = "mu_write", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 1032, .write = arcmsr_sysfs_iop_message_write, @@ -212,7 +210,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { .attr = { .name = "mu_clear", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 1, .write = arcmsr_sysfs_iop_message_clear, -- cgit v1.2.3 From f3506b755f730f199aea3289712f9604ae562319 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 22 Jul 2010 20:40:10 +0900 Subject: [SCSI] 53c700: remove dma_is_consistent usage This driver is the only user of dma_is_consistent(). We plan to remove this API. The driver uses the API in the following way: BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); The above code tries to see if L1_CACHE_BYTES is greater than dma_get_cache_alignment() on sysmtes that can not allocate coherent memory (some old systems can't). James Bottomley exmplained that this is necesary because the driver packs the set of mailboxes into a single coherent area and separates the different usages by a L1 cache stride. So it's fatal if the dma coherence stride is greater than the L1 cache size. He also pointed out that we can kill this checking because we don't hit this BUG_ON on all architectures that actually use the driver. Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/53c700.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 80dc3ac12cde..89fc1c8af86b 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -309,9 +309,6 @@ NCR_700_detect(struct scsi_host_template *tpnt, hostdata->msgin = memory + MSGIN_OFFSET; hostdata->msgout = memory + MSGOUT_OFFSET; hostdata->status = memory + STATUS_OFFSET; - /* all of these offsets are L1_CACHE_BYTES separated. It is fatal - * if this isn't sufficient separation to avoid dma flushing issues */ - BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); hostdata->dev = dev; -- cgit v1.2.3 From c7acc5b8f9a0e6cb17d313ebfbc5d392aa837ac7 Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:29:18 +0530 Subject: [SCSI] be2iscsi: Add support for iscsi boot This patch contains changes for adding support for iscsi_boot. Have modified to make read of mac address from chip as a function. The mac_address is being cached after teh first call as it is not expected to change Signed-off-by: Mike Christie Signed-off-by: Jayamohan Kallickal Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_cmds.h | 147 +++++++++++++++--- drivers/scsi/be2iscsi/be_iscsi.c | 76 ++++++---- drivers/scsi/be2iscsi/be_iscsi.h | 2 + drivers/scsi/be2iscsi/be_main.c | 311 +++++++++++++++++++++++++++++++++++++++ drivers/scsi/be2iscsi/be_main.h | 3 + drivers/scsi/be2iscsi/be_mgmt.c | 71 +++++++++ 6 files changed, 564 insertions(+), 46 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 40641d0845f4..5218de4ab35a 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -162,6 +162,13 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2 #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3 #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7 +#define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN 14 +#define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR 17 +#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR 21 +#define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY 22 +#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23 +#define OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID 24 +#define OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO 25 #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61 #define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64 #define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 @@ -237,11 +244,109 @@ struct be_cmd_resp_eq_create { u16 rsvd0; /* sword */ } __packed; +struct mgmt_chap_format { + u32 flags; + u8 intr_chap_name[256]; + u8 intr_secret[16]; + u8 target_chap_name[256]; + u8 target_secret[16]; + u16 intr_chap_name_length; + u16 intr_secret_length; + u16 target_chap_name_length; + u16 target_secret_length; +} __packed; + +struct mgmt_auth_method_format { + u8 auth_method_type; + u8 padding[3]; + struct mgmt_chap_format chap; +} __packed; + +struct mgmt_conn_login_options { + u8 flags; + u8 header_digest; + u8 data_digest; + u8 rsvd0; + u32 max_recv_datasegment_len_ini; + u32 max_recv_datasegment_len_tgt; + u32 tcp_mss; + u32 tcp_window_size; + struct mgmt_auth_method_format auth_data; +} __packed; + +struct ip_address_format { + u16 size_of_structure; + u8 reserved; + u8 ip_type; + u8 ip_address[16]; + u32 rsvd0; +} __packed; + +struct mgmt_conn_info { + u32 connection_handle; + u32 connection_status; + u16 src_port; + u16 dest_port; + u16 dest_port_redirected; + u16 cid; + u32 estimated_throughput; + struct ip_address_format src_ipaddr; + struct ip_address_format dest_ipaddr; + struct ip_address_format dest_ipaddr_redirected; + struct mgmt_conn_login_options negotiated_login_options; +} __packed; + +struct mgmt_session_login_options { + u8 flags; + u8 error_recovery_level; + u16 rsvd0; + u32 first_burst_length; + u32 max_burst_length; + u16 max_connections; + u16 max_outstanding_r2t; + u16 default_time2wait; + u16 default_time2retain; +} __packed; + +struct mgmt_session_info { + u32 session_handle; + u32 status; + u8 isid[6]; + u16 tsih; + u32 session_flags; + u16 conn_count; + u16 pad; + u8 target_name[224]; + u8 initiator_iscsiname[224]; + struct mgmt_session_login_options negotiated_login_options; + struct mgmt_conn_info conn_list[1]; +} __packed; + +struct be_cmd_req_get_session { + struct be_cmd_req_hdr hdr; + u32 session_handle; +} __packed; + +struct be_cmd_resp_get_session { + struct be_cmd_resp_hdr hdr; + struct mgmt_session_info session_info; +} __packed; + struct mac_addr { u16 size_of_struct; u8 addr[ETH_ALEN]; } __packed; +struct be_cmd_req_get_boot_target { + struct be_cmd_req_hdr hdr; +} __packed; + +struct be_cmd_resp_get_boot_target { + struct be_cmd_resp_hdr hdr; + u32 boot_session_count; + int boot_session_handle; +}; + struct be_cmd_req_mac_query { struct be_cmd_req_hdr hdr; u8 type; @@ -426,6 +531,11 @@ int be_poll_mcc(struct be_ctrl_info *ctrl); int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba); +unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba); +unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, + u32 boot_session_handle, + struct be_dma_mem *nonemb_cmd); + void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); /*ISCSI Functuions */ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); @@ -601,14 +711,6 @@ struct be_eq_delay_params_in { struct eq_delay delay[8]; } __packed; -struct ip_address_format { - u16 size_of_structure; - u8 reserved; - u8 ip_type; - u8 ip_address[16]; - u32 rsvd0; -} __packed; - struct tcp_connect_and_offload_in { struct be_cmd_req_hdr hdr; struct ip_address_format ip_address; @@ -688,18 +790,29 @@ struct be_fw_cfg { u32 function_caps; } __packed; -#define CMD_ISCSI_COMMAND_INVALIDATE 1 -#define ISCSI_OPCODE_SCSI_DATA_OUT 5 +struct be_all_if_id { + struct be_cmd_req_hdr hdr; + u32 if_count; + u32 if_hndl_list[1]; +} __packed; + +#define ISCSI_OPCODE_SCSI_DATA_OUT 5 +#define OPCODE_COMMON_MODIFY_EQ_DELAY 41 +#define OPCODE_COMMON_ISCSI_CLEANUP 59 +#define OPCODE_COMMON_TCP_UPLOAD 56 #define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70 -#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 -#define OPCODE_COMMON_MODIFY_EQ_DELAY 41 -#define OPCODE_COMMON_ISCSI_CLEANUP 59 -#define OPCODE_COMMON_TCP_UPLOAD 56 #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 -/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ -#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 -#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 +#define OPCODE_ISCSI_INI_CFG_GET_HBA_NAME 6 +#define OPCODE_ISCSI_INI_CFG_SET_HBA_NAME 7 +#define OPCODE_ISCSI_INI_SESSION_GET_A_SESSION 14 +#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 +#define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52 + +/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ +#define CMD_ISCSI_COMMAND_INVALIDATE 1 +#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 +#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 #define INI_WR_CMD 1 /* Initiator write command */ #define INI_TMF_CMD 2 /* Initiator TMF command */ diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 6d63e7b312cf..7d4d2275573c 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -300,40 +300,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf) { struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); - struct be_cmd_resp_get_mac_addr *resp; - struct be_mcc_wrb *wrb; - unsigned int tag, wrb_num; int len = 0; - unsigned short status, extd_status; - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + int status; SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); switch (param) { case ISCSI_HOST_PARAM_HWADDRESS: - tag = be_cmd_get_mac_addr(phba); - if (!tag) { - SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); - return -EAGAIN; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - if (status || extd_status) { - SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" - " status = %d extd_status = %d\n", - status, extd_status); - free_mcc_tag(&phba->ctrl, tag); - return -EAGAIN; - } else { - wrb = queue_get_wrb(mccq, wrb_num); - free_mcc_tag(&phba->ctrl, tag); - resp = embedded_payload(wrb); - memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); - len = sysfs_format_mac(buf, phba->mac_address, - ETH_ALEN); + status = beiscsi_get_macaddr(buf, phba); + if (status < 0) { + SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); + return status; } break; default: @@ -342,6 +318,48 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, return len; } +int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) +{ + struct be_cmd_resp_get_mac_addr *resp; + struct be_mcc_wrb *wrb; + unsigned int tag, wrb_num; + unsigned short status, extd_status; + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + int rc; + + if (phba->read_mac_address) + return sysfs_format_mac(buf, phba->mac_address, + ETH_ALEN); + + tag = be_cmd_get_mac_addr(phba); + if (!tag) { + SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); + return -EBUSY; + } else + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + + wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; + extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; + status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + if (status || extd_status) { + SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr" + " status = %d extd_status = %d\n", + status, extd_status); + free_mcc_tag(&phba->ctrl, tag); + return -EAGAIN; + } + wrb = queue_get_wrb(mccq, wrb_num); + free_mcc_tag(&phba->ctrl, tag); + resp = embedded_payload(wrb); + memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); + rc = sysfs_format_mac(buf, phba->mac_address, + ETH_ALEN); + phba->read_mac_address = 1; + return rc; +} + + /** * beiscsi_conn_get_stats - get the iscsi stats * @cls_conn: pointer to iscsi cls conn diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index 870cdb2a73e4..8950a702b9f4 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h @@ -54,6 +54,8 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, int beiscsi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf); +int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba); + int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf, int buflen); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 7436c5ad5697..8220bde6c04c 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -211,6 +212,218 @@ unlock: return rc; } +static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) +{ + struct beiscsi_hba *phba = data; + char *str = buf; + int rc; + + switch (type) { + case ISCSI_BOOT_TGT_NAME: + rc = sprintf(buf, "%.*s\n", + (int)strlen(phba->boot_sess.target_name), + (char *)&phba->boot_sess.target_name); + break; + case ISCSI_BOOT_TGT_IP_ADDR: + if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1) + rc = sprintf(buf, "%pI4\n", + (char *)&phba->boot_sess.conn_list[0]. + dest_ipaddr.ip_address); + else + rc = sprintf(str, "%pI6\n", + (char *)&phba->boot_sess.conn_list[0]. + dest_ipaddr.ip_address); + break; + case ISCSI_BOOT_TGT_PORT: + rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0]. + dest_port); + break; + + case ISCSI_BOOT_TGT_CHAP_NAME: + rc = sprintf(str, "%.*s\n", + phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + target_chap_name_length, + (char *)&phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + target_chap_name); + break; + case ISCSI_BOOT_TGT_CHAP_SECRET: + rc = sprintf(str, "%.*s\n", + phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + target_secret_length, + (char *)&phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + target_secret); + + break; + case ISCSI_BOOT_TGT_REV_CHAP_NAME: + rc = sprintf(str, "%.*s\n", + phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + intr_chap_name_length, + (char *)&phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + intr_chap_name); + + break; + case ISCSI_BOOT_TGT_REV_CHAP_SECRET: + rc = sprintf(str, "%.*s\n", + phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + intr_secret_length, + (char *)&phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + intr_secret); + break; + case ISCSI_BOOT_TGT_FLAGS: + rc = sprintf(str, "2\n"); + break; + case ISCSI_BOOT_TGT_NIC_ASSOC: + rc = sprintf(str, "0\n"); + break; + default: + rc = -ENOSYS; + break; + } + return rc; +} + +static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) +{ + struct beiscsi_hba *phba = data; + char *str = buf; + int rc; + + switch (type) { + case ISCSI_BOOT_INI_INITIATOR_NAME: + rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname); + break; + default: + rc = -ENOSYS; + break; + } + return rc; +} + +static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) +{ + struct beiscsi_hba *phba = data; + char *str = buf; + int rc; + + switch (type) { + case ISCSI_BOOT_ETH_FLAGS: + rc = sprintf(str, "2\n"); + break; + case ISCSI_BOOT_ETH_INDEX: + rc = sprintf(str, "0\n"); + break; + case ISCSI_BOOT_ETH_MAC: + rc = beiscsi_get_macaddr(buf, phba); + if (rc < 0) { + SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); + return rc; + } + break; + default: + rc = -ENOSYS; + break; + } + return rc; +} + + +static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type) +{ + int rc; + + switch (type) { + case ISCSI_BOOT_TGT_NAME: + case ISCSI_BOOT_TGT_IP_ADDR: + case ISCSI_BOOT_TGT_PORT: + case ISCSI_BOOT_TGT_CHAP_NAME: + case ISCSI_BOOT_TGT_CHAP_SECRET: + case ISCSI_BOOT_TGT_REV_CHAP_NAME: + case ISCSI_BOOT_TGT_REV_CHAP_SECRET: + case ISCSI_BOOT_TGT_NIC_ASSOC: + case ISCSI_BOOT_TGT_FLAGS: + rc = S_IRUGO; + break; + default: + rc = 0; + break; + } + return rc; +} + +static mode_t beiscsi_ini_get_attr_visibility(void *data, int type) +{ + int rc; + + switch (type) { + case ISCSI_BOOT_INI_INITIATOR_NAME: + rc = S_IRUGO; + break; + default: + rc = 0; + break; + } + return rc; +} + + +static mode_t beiscsi_eth_get_attr_visibility(void *data, int type) +{ + int rc; + + switch (type) { + case ISCSI_BOOT_ETH_FLAGS: + case ISCSI_BOOT_ETH_MAC: + case ISCSI_BOOT_ETH_INDEX: + rc = S_IRUGO; + break; + default: + rc = 0; + break; + } + return rc; +} + +static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) +{ + struct iscsi_boot_kobj *boot_kobj; + + phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); + if (!phba->boot_kset) + return -ENOMEM; + + /* get boot info using mgmt cmd */ + boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, + beiscsi_show_boot_tgt_info, + beiscsi_tgt_get_attr_visibility); + if (!boot_kobj) + goto free_kset; + + boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, + beiscsi_show_boot_ini_info, + beiscsi_ini_get_attr_visibility); + if (!boot_kobj) + goto free_kset; + + boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, + beiscsi_show_boot_eth_info, + beiscsi_eth_get_attr_visibility); + if (!boot_kobj) + goto free_kset; + return 0; + +free_kset: + iscsi_boot_destroy_kset(phba->boot_kset); + return -ENOMEM; +} + /*------------------- PCI Driver operations and data ----------------- */ static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, @@ -268,6 +481,15 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) if (iscsi_host_add(shost, &phba->pcidev->dev)) goto free_devices; + + if (beiscsi_setup_boot_info(phba)) + /* + * log error but continue, because we may not be using + * iscsi boot. + */ + shost_printk(KERN_ERR, phba->shost, "Could not set up " + "iSCSI boot info."); + return phba; free_devices: @@ -3279,6 +3501,89 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) "In hwi_disable_intr, Already Disabled\n"); } +static int beiscsi_get_boot_info(struct beiscsi_hba *phba) +{ + struct be_cmd_resp_get_boot_target *boot_resp; + struct be_cmd_resp_get_session *session_resp; + struct be_mcc_wrb *wrb; + struct be_dma_mem nonemb_cmd; + unsigned int tag, wrb_num; + unsigned short status, extd_status; + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + + tag = beiscsi_get_boot_target(phba); + if (!tag) { + SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); + return -EAGAIN; + } else + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + + wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; + extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; + status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + if (status || extd_status) { + SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" + " status = %d extd_status = %d\n", + status, extd_status); + free_mcc_tag(&phba->ctrl, tag); + return -EBUSY; + } + wrb = queue_get_wrb(mccq, wrb_num); + free_mcc_tag(&phba->ctrl, tag); + boot_resp = embedded_payload(wrb); + + if (boot_resp->boot_session_handle < 0) { + printk(KERN_ERR "No Boot Session for this pci_func," + "session Hndl = %d\n", boot_resp->boot_session_handle); + return -ENXIO; + } + + nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, + sizeof(*session_resp), + &nonemb_cmd.dma); + if (nonemb_cmd.va == NULL) { + SE_DEBUG(DBG_LVL_1, + "Failed to allocate memory for" + "beiscsi_get_session_info\n"); + return -ENOMEM; + } + + memset(nonemb_cmd.va, 0, sizeof(*session_resp)); + tag = beiscsi_get_session_info(phba, + boot_resp->boot_session_handle, &nonemb_cmd); + if (!tag) { + SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info" + " Failed\n"); + goto boot_freemem; + } else + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + + wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; + extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; + status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + if (status || extd_status) { + SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed" + " status = %d extd_status = %d\n", + status, extd_status); + free_mcc_tag(&phba->ctrl, tag); + goto boot_freemem; + } + wrb = queue_get_wrb(mccq, wrb_num); + free_mcc_tag(&phba->ctrl, tag); + session_resp = nonemb_cmd.va ; + memcpy(&phba->boot_sess, &session_resp->session_info, + sizeof(struct mgmt_session_info)); + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); + return 0; +boot_freemem: + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); + return -ENOMEM; +} + static int beiscsi_init_port(struct beiscsi_hba *phba) { int ret; @@ -3841,6 +4146,7 @@ static void beiscsi_remove(struct pci_dev *pcidev) iscsi_host_remove(phba->shost); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); + iscsi_boot_destroy_kset(phba->boot_kset); } static void beiscsi_msix_enable(struct beiscsi_hba *phba) @@ -3996,6 +4302,11 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, goto free_blkenbld; } hwi_enable_intr(phba); + ret = beiscsi_get_boot_info(phba); + if (ret < 0) { + shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" + "No Boot Devices !!!!!\n"); + } SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); return 0; diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c643bb3736fc..48b7d4d28d9d 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -312,6 +312,7 @@ struct beiscsi_hba { struct list_head hba_queue; unsigned short *cid_array; struct iscsi_endpoint **ep_array; + struct iscsi_boot_kset *boot_kset; struct Scsi_Host *shost; struct { /** @@ -342,6 +343,8 @@ struct beiscsi_hba { struct work_struct work_cqs; /* The work being queued */ struct be_ctrl_info ctrl; unsigned int generation; + unsigned int read_mac_address; + struct mgmt_session_info boot_sess; struct invalidate_command_table inv_tbl[128]; }; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 3f3fab91a7d1..26350e470bcc 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -20,6 +20,77 @@ #include "be_mgmt.h" #include "be_iscsi.h" +#include + +unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) +{ + struct be_ctrl_info *ctrl = &phba->ctrl; + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_mac_addr *req; + unsigned int tag = 0; + + SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n"); + spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); + return tag; + } + + wrb = wrb_from_mccq(phba); + req = embedded_payload(wrb); + wrb->tag0 |= tag; + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, + OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, + sizeof(*req)); + + be_mcc_notify(phba); + spin_unlock(&ctrl->mbox_lock); + return tag; +} + +unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, + u32 boot_session_handle, + struct be_dma_mem *nonemb_cmd) +{ + struct be_ctrl_info *ctrl = &phba->ctrl; + struct be_mcc_wrb *wrb; + unsigned int tag = 0; + struct be_cmd_req_get_session *req; + struct be_cmd_resp_get_session *resp; + struct be_sge *sge; + + SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n"); + spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); + return tag; + } + + nonemb_cmd->size = sizeof(*resp); + req = nonemb_cmd->va; + memset(req, 0, sizeof(*req)); + wrb = wrb_from_mccq(phba); + sge = nonembedded_sgl(wrb); + wrb->tag0 |= tag; + + + wrb->tag0 |= tag; + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, + OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, + sizeof(*resp)); + req->session_handle = boot_session_handle; + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); + + be_mcc_notify(phba); + spin_unlock(&ctrl->mbox_lock); + return tag; +} int mgmt_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) -- cgit v1.2.3 From e919dee8a398fea1db184ce1418e70170a01c8fa Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:30:32 +0530 Subject: [SCSI] be2iscsi: Increase max sector This patch increases the max_sectors to 2048 Signed-off-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 48b7d4d28d9d..6cfa55d019da 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -63,7 +63,7 @@ #define BEISCSI_SGLIST_ELEMENTS 30 #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ -#define BEISCSI_MAX_SECTORS 256 /* scsi_host->max_sectors */ +#define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ -- cgit v1.2.3 From dd81beaee9a8bf000f7fbfe609b5a0fc9607e233 Mon Sep 17 00:00:00 2001 From: Jayamohan Kallickal Date: Thu, 22 Jul 2010 04:31:07 +0530 Subject: [SCSI] be2iscsi: Driver Version change to 2.0.549.0 Signed-off-by: Jayamohan Kallickal Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 6cfa55d019da..90eb74f6bcab 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -35,7 +35,7 @@ #include "be.h" #define DRV_NAME "be2iscsi" -#define BUILD_STR "2.0.527.0" +#define BUILD_STR "2.0.549.0" #define BE_NAME "ServerEngines BladeEngine2" \ "Linux iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" -- cgit v1.2.3 From 787f0bd3376aedb3f9ba9bbf862d85e4b176f9b0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 29 Jul 2010 10:16:09 -0700 Subject: [SCSI] be2iscsi: select ISCSI_BOOT_SYSFS be2iscsi uses iscsi_boot_*() interfaces, so it should ensure that ISCSI_BOOT_SYSFS is enabled. ERROR: "iscsi_boot_create_target" [drivers/scsi/be2iscsi/be2iscsi.ko] undefined! ERROR: "iscsi_boot_create_ethernet" [drivers/scsi/be2iscsi/be2iscsi.ko] undefined! ERROR: "iscsi_boot_create_host_kset" [drivers/scsi/be2iscsi/be2iscsi.ko] undefined! ERROR: "iscsi_boot_create_initiator" [drivers/scsi/be2iscsi/be2iscsi.ko] undefined! ERROR: "iscsi_boot_destroy_kset" [drivers/scsi/be2iscsi/be2iscsi.ko] undefined! Signed-off-by: Randy Dunlap Acked-by: Jayamohan Kallickal Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig index 84c275fb9f6b..ceaca32e788d 100644 --- a/drivers/scsi/be2iscsi/Kconfig +++ b/drivers/scsi/be2iscsi/Kconfig @@ -2,6 +2,7 @@ config BE2ISCSI tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2" depends on PCI && SCSI && NET select SCSI_ISCSI_ATTRS + select ISCSI_BOOT_SYSFS help This driver implements the iSCSI functionality for ServerEngines' -- cgit v1.2.3 From 2dc11581376829303b98eadb2de253bee065a56a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 6 Aug 2010 09:25:50 -0600 Subject: of/device: Replace struct of_device with struct platform_device of_device is just an alias for platform_device, so remove it entirely. Also replace to_of_device() with to_platform_device() and update comment blocks. This patch was initially generated from the following semantic patch, and then edited by hand to pick up the bits that coccinelle didn't catch. @@ @@ -struct of_device +struct platform_device Signed-off-by: Grant Likely Reviewed-by: David S. Miller --- arch/powerpc/platforms/83xx/mpc837x_mds.c | 2 +- arch/powerpc/platforms/83xx/mpc837x_rdb.c | 2 +- arch/powerpc/sysdev/fsl_rio.c | 2 +- drivers/ata/pata_mpc52xx.c | 8 ++--- drivers/ata/pata_of_platform.c | 4 +-- drivers/ata/sata_fsl.c | 8 ++--- drivers/atm/fore200e.c | 26 ++++++++-------- drivers/block/xsysace.c | 4 +-- drivers/char/hw_random/n2-drv.c | 4 +-- drivers/char/hw_random/n2rng.h | 2 +- drivers/char/hw_random/pasemi-rng.c | 4 +-- drivers/char/ipmi/ipmi_si_intf.c | 4 +-- drivers/char/rtc.c | 2 +- drivers/char/xilinx_hwicap/xilinx_hwicap.c | 4 +-- drivers/crypto/amcc/crypto4xx_core.c | 4 +-- drivers/crypto/amcc/crypto4xx_core.h | 2 +- drivers/crypto/n2_core.c | 22 +++++++------- drivers/crypto/talitos.c | 6 ++-- drivers/dma/fsldma.c | 4 +-- drivers/dma/mpc512x_dma.c | 4 +-- drivers/dma/ppc4xx/adma.c | 8 ++--- drivers/edac/mpc85xx_edac.c | 12 ++++---- drivers/edac/ppc4xx_edac.c | 12 ++++---- drivers/hwmon/ams/ams.h | 2 +- drivers/hwmon/ultra45_env.c | 4 +-- drivers/i2c/busses/i2c-cpm.c | 8 ++--- drivers/i2c/busses/i2c-ibm_iic.c | 6 ++-- drivers/i2c/busses/i2c-mpc.c | 4 +-- drivers/infiniband/hw/ehca/ehca_classes.h | 2 +- drivers/infiniband/hw/ehca/ehca_main.c | 4 +-- drivers/input/misc/sparcspkr.c | 10 +++--- drivers/input/serio/i8042-sparcio.h | 8 ++--- drivers/input/serio/xilinx_ps2.c | 4 +-- drivers/leds/leds-gpio.c | 4 +-- drivers/macintosh/macio_sysfs.c | 6 ++-- drivers/macintosh/smu.c | 6 ++-- drivers/macintosh/therm_adt746x.c | 2 +- drivers/macintosh/therm_pm72.c | 6 ++-- drivers/macintosh/therm_windtunnel.c | 6 ++-- drivers/media/video/fsl-viu.c | 8 ++--- drivers/mmc/host/sdhci-of-core.c | 8 ++--- drivers/mtd/maps/physmap_of.c | 8 ++--- drivers/mtd/maps/sun_uflash.c | 6 ++-- drivers/mtd/nand/fsl_elbc_nand.c | 4 +-- drivers/mtd/nand/fsl_upm.c | 4 +-- drivers/mtd/nand/mpc5121_nfc.c | 4 +-- drivers/mtd/nand/ndfc.c | 6 ++-- drivers/mtd/nand/pasemi_nand.c | 4 +-- drivers/mtd/nand/socrates_nand.c | 4 +-- drivers/net/can/mscan/mpc5xxx_can.c | 18 +++++------ drivers/net/can/sja1000/sja1000_of_platform.c | 4 +-- drivers/net/ehea/ehea.h | 4 +-- drivers/net/ehea/ehea_main.c | 12 ++++---- drivers/net/fec_mpc52xx.c | 8 ++--- drivers/net/fec_mpc52xx_phy.c | 4 +-- drivers/net/fs_enet/fs_enet-main.c | 4 +-- drivers/net/fs_enet/mac-fcc.c | 2 +- drivers/net/fs_enet/mac-fec.c | 2 +- drivers/net/fs_enet/mac-scc.c | 2 +- drivers/net/fs_enet/mii-bitbang.c | 4 +-- drivers/net/fs_enet/mii-fec.c | 4 +-- drivers/net/fsl_pq_mdio.c | 4 +-- drivers/net/gianfar.c | 10 +++--- drivers/net/gianfar.h | 2 +- drivers/net/greth.c | 4 +-- drivers/net/greth.h | 2 +- drivers/net/ibm_newemac/core.c | 6 ++-- drivers/net/ibm_newemac/core.h | 12 ++++---- drivers/net/ibm_newemac/mal.c | 4 +-- drivers/net/ibm_newemac/mal.h | 2 +- drivers/net/ibm_newemac/rgmii.c | 18 +++++------ drivers/net/ibm_newemac/rgmii.h | 16 +++++----- drivers/net/ibm_newemac/tah.c | 14 ++++----- drivers/net/ibm_newemac/tah.h | 12 ++++---- drivers/net/ibm_newemac/zmii.c | 18 +++++------ drivers/net/ibm_newemac/zmii.h | 16 +++++----- drivers/net/ll_temac_main.c | 8 ++--- drivers/net/myri_sbus.c | 4 +-- drivers/net/myri_sbus.h | 2 +- drivers/net/niu.c | 8 ++--- drivers/net/phy/mdio-gpio.c | 4 +-- drivers/net/sunbmac.c | 18 +++++------ drivers/net/sunbmac.h | 4 +-- drivers/net/sunhme.c | 22 +++++++------- drivers/net/sunhme.h | 2 +- drivers/net/sunlance.c | 20 ++++++------ drivers/net/sunqe.c | 16 +++++----- drivers/net/sunqe.h | 4 +-- drivers/net/ucc_geth.c | 8 ++--- drivers/net/xilinx_emaclite.c | 6 ++-- drivers/of/device.c | 2 +- drivers/parport/parport_sunbpp.c | 4 +-- drivers/pcmcia/electra_cf.c | 6 ++-- drivers/pcmcia/m8xx_pcmcia.c | 4 +-- drivers/rtc/rtc-mpc5121.c | 4 +-- drivers/sbus/char/bbc_envctrl.c | 6 ++-- drivers/sbus/char/bbc_i2c.c | 18 +++++------ drivers/sbus/char/bbc_i2c.h | 10 +++--- drivers/sbus/char/display7seg.c | 4 +-- drivers/sbus/char/envctrl.c | 4 +-- drivers/sbus/char/flash.c | 4 +-- drivers/sbus/char/uctrl.c | 4 +-- drivers/scsi/qlogicpti.c | 14 ++++----- drivers/scsi/qlogicpti.h | 2 +- drivers/scsi/sun_esp.c | 44 +++++++++++++-------------- drivers/serial/apbuart.c | 2 +- drivers/serial/cpm_uart/cpm_uart_core.c | 4 +-- drivers/serial/mpc52xx_uart.c | 8 ++--- drivers/serial/nwpserial.c | 2 +- drivers/serial/of_serial.c | 6 ++-- drivers/serial/sunhv.c | 4 +-- drivers/serial/sunsab.c | 8 ++--- drivers/serial/sunsu.c | 8 ++--- drivers/serial/sunzilog.c | 6 ++-- drivers/serial/uartlite.c | 4 +-- drivers/serial/ucc_uart.c | 4 +-- drivers/spi/mpc512x_psc_spi.c | 4 +-- drivers/spi/mpc52xx_psc_spi.c | 4 +-- drivers/spi/mpc52xx_spi.c | 4 +-- drivers/spi/spi_mpc8xxx.c | 4 +-- drivers/spi/spi_ppc4xx.c | 6 ++-- drivers/spi/xilinx_spi_of.c | 6 ++-- drivers/usb/gadget/fsl_qe_udc.c | 10 +++--- drivers/usb/host/ehci-ppc-of.c | 6 ++-- drivers/usb/host/ehci-xilinx-of.c | 12 ++++---- drivers/usb/host/fhci-hcd.c | 4 +-- drivers/usb/host/isp1760-if.c | 4 +-- drivers/usb/host/ohci-ppc-of.c | 6 ++-- drivers/video/bw2.c | 4 +-- drivers/video/cg14.c | 6 ++-- drivers/video/cg3.c | 4 +-- drivers/video/cg6.c | 6 ++-- drivers/video/ffb.c | 4 +-- drivers/video/fsl-diu-fb.c | 8 ++--- drivers/video/leo.c | 6 ++-- drivers/video/mb862xx/mb862xxfb.c | 4 +-- drivers/video/p9100.c | 4 +-- drivers/video/platinumfb.c | 4 +-- drivers/video/sunxvr1000.c | 4 +-- drivers/video/tcx.c | 6 ++-- drivers/video/xilinxfb.c | 4 +-- drivers/watchdog/cpwd.c | 4 +-- drivers/watchdog/gef_wdt.c | 2 +- drivers/watchdog/mpc8xxx_wdt.c | 4 +-- drivers/watchdog/riowd.c | 4 +-- include/linux/of_device.h | 16 ---------- include/linux/of_platform.h | 14 +++++++-- sound/aoa/soundbus/core.c | 2 +- sound/aoa/soundbus/soundbus.h | 2 +- sound/aoa/soundbus/sysfs.c | 2 +- sound/soc/fsl/mpc5200_dma.c | 4 +-- sound/soc/fsl/mpc5200_dma.h | 4 +-- sound/soc/fsl/mpc5200_psc_ac97.c | 4 +-- sound/soc/fsl/mpc5200_psc_i2s.c | 4 +-- sound/soc/fsl/mpc8610_hpcd.c | 4 +-- sound/sparc/amd7930.c | 8 ++--- sound/sparc/cs4231.c | 18 +++++------ sound/sparc/dbri.c | 8 ++--- 158 files changed, 519 insertions(+), 527 deletions(-) (limited to 'drivers/scsi') diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index 51df7e754698..f9751c8905be 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c @@ -102,7 +102,7 @@ static struct of_device_id mpc837x_ids[] = { static int __init mpc837x_declare_of_platform_devices(void) { - /* Publish of_device */ + /* Publish platform_device */ of_platform_bus_probe(NULL, mpc837x_ids, NULL); return 0; diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c index e00801c42540..910caa6b5810 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c @@ -78,7 +78,7 @@ static struct of_device_id mpc837x_ids[] = { static int __init mpc837x_declare_of_platform_devices(void) { - /* Publish of_device */ + /* Publish platform_device */ of_platform_bus_probe(NULL, mpc837x_ids, NULL); return 0; diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 8bd86530ee25..6425abe5b7db 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -1332,7 +1332,7 @@ static inline void fsl_rio_info(struct device *dev, u32 ccsr) /** * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface - * @dev: of_device pointer + * @dev: platform_device pointer * * Initializes MPC85xx RapidIO hardware interface, configures * master port with system-specific info, and registers the diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index f087ab55b1df..8cc536e49a0a 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -680,7 +680,7 @@ mpc52xx_ata_remove_one(struct device *dev) /* ======================================================================== */ static int __devinit -mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) +mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match) { unsigned int ipb_freq; struct resource res_mem; @@ -821,7 +821,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) } static int -mpc52xx_ata_remove(struct of_device *op) +mpc52xx_ata_remove(struct platform_device *op) { struct mpc52xx_ata_priv *priv; int task_irq; @@ -848,7 +848,7 @@ mpc52xx_ata_remove(struct of_device *op) #ifdef CONFIG_PM static int -mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) +mpc52xx_ata_suspend(struct platform_device *op, pm_message_t state) { struct ata_host *host = dev_get_drvdata(&op->dev); @@ -856,7 +856,7 @@ mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) } static int -mpc52xx_ata_resume(struct of_device *op) +mpc52xx_ata_resume(struct platform_device *op) { struct ata_host *host = dev_get_drvdata(&op->dev); struct mpc52xx_ata_priv *priv = host->private_data; diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 5a1b82c08be9..480e043ce6b8 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c @@ -14,7 +14,7 @@ #include #include -static int __devinit pata_of_platform_probe(struct of_device *ofdev, +static int __devinit pata_of_platform_probe(struct platform_device *ofdev, const struct of_device_id *match) { int ret; @@ -78,7 +78,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev, reg_shift, pio_mask); } -static int __devexit pata_of_platform_remove(struct of_device *ofdev) +static int __devexit pata_of_platform_remove(struct platform_device *ofdev) { return __pata_platform_remove(&ofdev->dev); } diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 61c89b54ea23..4e4d42f1186a 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -1296,7 +1296,7 @@ static const struct ata_port_info sata_fsl_port_info[] = { }, }; -static int sata_fsl_probe(struct of_device *ofdev, +static int sata_fsl_probe(struct platform_device *ofdev, const struct of_device_id *match) { int retval = -ENXIO; @@ -1370,7 +1370,7 @@ error_exit_with_cleanup: return retval; } -static int sata_fsl_remove(struct of_device *ofdev) +static int sata_fsl_remove(struct platform_device *ofdev) { struct ata_host *host = dev_get_drvdata(&ofdev->dev); struct sata_fsl_host_priv *host_priv = host->private_data; @@ -1387,13 +1387,13 @@ static int sata_fsl_remove(struct of_device *ofdev) } #ifdef CONFIG_PM -static int sata_fsl_suspend(struct of_device *op, pm_message_t state) +static int sata_fsl_suspend(struct platform_device *op, pm_message_t state) { struct ata_host *host = dev_get_drvdata(&op->dev); return ata_host_suspend(host, state); } -static int sata_fsl_resume(struct of_device *op) +static int sata_fsl_resume(struct platform_device *op) { struct ata_host *host = dev_get_drvdata(&op->dev); struct sata_fsl_host_priv *host_priv = host->private_data; diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index b7385e077717..c8fc69c85a06 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -674,7 +674,7 @@ static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; u32 dma_addr; dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); @@ -687,7 +687,7 @@ static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", dma_addr, size, direction); @@ -697,7 +697,7 @@ static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); @@ -706,7 +706,7 @@ static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_add static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); @@ -719,7 +719,7 @@ static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, int size, int nbr, int alignment) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; chunk->alloc_size = chunk->align_size = size * nbr; @@ -738,7 +738,7 @@ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk /* free a DVMA consistent chunk of memory */ static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; dma_free_coherent(&op->dev, chunk->alloc_size, chunk->alloc_addr, chunk->dma_addr); @@ -770,7 +770,7 @@ static void fore200e_sba_reset(struct fore200e *fore200e) static int __init fore200e_sba_map(struct fore200e *fore200e) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; unsigned int bursts; /* gain access to the SBA specific registers */ @@ -800,7 +800,7 @@ static int __init fore200e_sba_map(struct fore200e *fore200e) static void fore200e_sba_unmap(struct fore200e *fore200e) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); @@ -816,7 +816,7 @@ static int __init fore200e_sba_configure(struct fore200e *fore200e) static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; const u8 *prop; int len; @@ -840,7 +840,7 @@ static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_ static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; const struct linux_prom_registers *regs; regs = of_get_property(op->dev.of_node, "reg", NULL); @@ -2513,7 +2513,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e) device = &((struct pci_dev *) fore200e->bus_dev)->dev; #ifdef CONFIG_SBUS else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) - device = &((struct of_device *) fore200e->bus_dev)->dev; + device = &((struct platform_device *) fore200e->bus_dev)->dev; #endif else return err; @@ -2643,7 +2643,7 @@ fore200e_init(struct fore200e* fore200e) } #ifdef CONFIG_SBUS -static int __devinit fore200e_sba_probe(struct of_device *op, +static int __devinit fore200e_sba_probe(struct platform_device *op, const struct of_device_id *match) { const struct fore200e_bus *bus = match->data; @@ -2675,7 +2675,7 @@ static int __devinit fore200e_sba_probe(struct of_device *op, return 0; } -static int __devexit fore200e_sba_remove(struct of_device *op) +static int __devexit fore200e_sba_remove(struct platform_device *op) { struct fore200e *fore200e = dev_get_drvdata(&op->dev); diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index a7b83c0a7eb5..d7cb69db3067 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1188,7 +1188,7 @@ static struct platform_driver ace_platform_driver = { #if defined(CONFIG_OF) static int __devinit -ace_of_probe(struct of_device *op, const struct of_device_id *match) +ace_of_probe(struct platform_device *op, const struct of_device_id *match) { struct resource res; resource_size_t physaddr; @@ -1220,7 +1220,7 @@ ace_of_probe(struct of_device *op, const struct of_device_id *match) return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width); } -static int __devexit ace_of_remove(struct of_device *op) +static int __devexit ace_of_remove(struct platform_device *op) { ace_free(&op->dev); return 0; diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 7a4f080f8356..1acdb2509511 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -619,7 +619,7 @@ static void __devinit n2rng_driver_version(void) pr_info("%s", version); } -static int __devinit n2rng_probe(struct of_device *op, +static int __devinit n2rng_probe(struct platform_device *op, const struct of_device_id *match) { int victoria_falls = (match->data != NULL); @@ -714,7 +714,7 @@ out: return err; } -static int __devexit n2rng_remove(struct of_device *op) +static int __devexit n2rng_remove(struct platform_device *op) { struct n2rng *np = dev_get_drvdata(&op->dev); diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h index a2b81e7bfc18..4bea07f30978 100644 --- a/drivers/char/hw_random/n2rng.h +++ b/drivers/char/hw_random/n2rng.h @@ -65,7 +65,7 @@ struct n2rng_unit { }; struct n2rng { - struct of_device *op; + struct platform_device *op; unsigned long flags; #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 261ba8f22b8b..a31c830ca8cd 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c @@ -94,7 +94,7 @@ static struct hwrng pasemi_rng = { .data_read = pasemi_rng_data_read, }; -static int __devinit rng_probe(struct of_device *ofdev, +static int __devinit rng_probe(struct platform_device *ofdev, const struct of_device_id *match) { void __iomem *rng_regs; @@ -123,7 +123,7 @@ static int __devinit rng_probe(struct of_device *ofdev, return err; } -static int __devexit rng_remove(struct of_device *dev) +static int __devexit rng_remove(struct platform_device *dev) { void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 094bdc355b1f..b532d613fb5b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2502,7 +2502,7 @@ static struct pci_driver ipmi_pci_driver = { #ifdef CONFIG_PPC_OF -static int __devinit ipmi_of_probe(struct of_device *dev, +static int __devinit ipmi_of_probe(struct platform_device *dev, const struct of_device_id *match) { struct smi_info *info; @@ -2576,7 +2576,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev, return add_smi(info); } -static int __devexit ipmi_of_remove(struct of_device *dev) +static int __devexit ipmi_of_remove(struct platform_device *dev) { cleanup_one_si(dev_get_drvdata(&dev->dev)); return 0; diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 95acb8c880f4..dfa8b3062fda 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -961,7 +961,7 @@ static int __init rtc_init(void) #endif #ifdef CONFIG_SPARC32 struct device_node *ebus_dp; - struct of_device *op; + struct platform_device *op; #else void *r; #ifdef RTC_IRQ diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index ed8a9cec2a05..0ed763cd2e77 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -761,7 +761,7 @@ static struct platform_driver hwicap_platform_driver = { #if defined(CONFIG_OF) static int __devinit -hwicap_of_probe(struct of_device *op, const struct of_device_id *match) +hwicap_of_probe(struct platform_device *op, const struct of_device_id *match) { struct resource res; const unsigned int *id; @@ -798,7 +798,7 @@ hwicap_of_probe(struct of_device *op, const struct of_device_id *match) regs); } -static int __devexit hwicap_of_remove(struct of_device *op) +static int __devexit hwicap_of_remove(struct platform_device *op) { return hwicap_remove(&op->dev); } diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 983530ba04a7..2b1baee525bc 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1150,7 +1150,7 @@ struct crypto4xx_alg_common crypto4xx_alg[] = { /** * Module Initialization Routine */ -static int __init crypto4xx_probe(struct of_device *ofdev, +static int __init crypto4xx_probe(struct platform_device *ofdev, const struct of_device_id *match) { int rc; @@ -1258,7 +1258,7 @@ err_alloc_dev: return rc; } -static int __exit crypto4xx_remove(struct of_device *ofdev) +static int __exit crypto4xx_remove(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h index da9cbe3b9fc3..bac0bdeb4b5f 100644 --- a/drivers/crypto/amcc/crypto4xx_core.h +++ b/drivers/crypto/amcc/crypto4xx_core.h @@ -104,7 +104,7 @@ struct crypto4xx_device { struct crypto4xx_core_device { struct device *device; - struct of_device *ofdev; + struct platform_device *ofdev; struct crypto4xx_device *dev; u32 int_status; u32 irq; diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 26af2dd5d831..931fdd471d6d 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -1552,7 +1552,7 @@ static void __exit n2_unregister_algs(void) /* To map CWQ queues to interrupt sources, the hypervisor API provides * a devino. This isn't very useful to us because all of the - * interrupts listed in the of_device node have been translated to + * interrupts listed in the device_node have been translated to * Linux virtual IRQ cookie numbers. * * So we have to back-translate, going through the 'intr' and 'ino' @@ -1560,7 +1560,7 @@ static void __exit n2_unregister_algs(void) * 'interrupts' property entries, in order to to figure out which * devino goes to which already-translated IRQ. */ -static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, +static int find_devino_index(struct platform_device *dev, struct spu_mdesc_info *ip, unsigned long dev_ino) { const unsigned int *dev_intrs; @@ -1588,7 +1588,7 @@ static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, return -ENODEV; } -static int spu_map_ino(struct of_device *dev, struct spu_mdesc_info *ip, +static int spu_map_ino(struct platform_device *dev, struct spu_mdesc_info *ip, const char *irq_name, struct spu_queue *p, irq_handler_t handler) { @@ -1736,7 +1736,7 @@ static void spu_list_destroy(struct list_head *list) * gathering cpu membership information. */ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, - struct of_device *dev, + struct platform_device *dev, u64 node, struct spu_queue *p, struct spu_queue **table) { @@ -1763,7 +1763,7 @@ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, /* Process an 'exec-unit' MDESC node of type 'cwq'. */ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, - struct of_device *dev, struct mdesc_handle *mdesc, + struct platform_device *dev, struct mdesc_handle *mdesc, u64 node, const char *iname, unsigned long q_type, irq_handler_t handler, struct spu_queue **table) { @@ -1794,7 +1794,7 @@ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, return spu_map_ino(dev, ip, iname, p, handler); } -static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct of_device *dev, +static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct platform_device *dev, struct spu_mdesc_info *ip, struct list_head *list, const char *exec_name, unsigned long q_type, irq_handler_t handler, struct spu_queue **table) @@ -1855,7 +1855,7 @@ static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node, } static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc, - struct of_device *dev, + struct platform_device *dev, struct spu_mdesc_info *ip, const char *node_name) { @@ -2004,7 +2004,7 @@ static void __devinit n2_spu_driver_version(void) pr_info("%s", version); } -static int __devinit n2_crypto_probe(struct of_device *dev, +static int __devinit n2_crypto_probe(struct platform_device *dev, const struct of_device_id *match) { struct mdesc_handle *mdesc; @@ -2081,7 +2081,7 @@ out_free_n2cp: return err; } -static int __devexit n2_crypto_remove(struct of_device *dev) +static int __devexit n2_crypto_remove(struct platform_device *dev) { struct n2_crypto *np = dev_get_drvdata(&dev->dev); @@ -2116,7 +2116,7 @@ static void free_ncp(struct n2_mau *mp) kfree(mp); } -static int __devinit n2_mau_probe(struct of_device *dev, +static int __devinit n2_mau_probe(struct platform_device *dev, const struct of_device_id *match) { struct mdesc_handle *mdesc; @@ -2184,7 +2184,7 @@ out_free_ncp: return err; } -static int __devexit n2_mau_remove(struct of_device *dev) +static int __devexit n2_mau_remove(struct platform_device *dev) { struct n2_mau *mp = dev_get_drvdata(&dev->dev); diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 97f4af1d8a64..4bcd825b5739 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -118,7 +118,7 @@ struct talitos_channel { struct talitos_private { struct device *dev; - struct of_device *ofdev; + struct platform_device *ofdev; void __iomem *reg; int irq; @@ -2308,7 +2308,7 @@ static int hw_supports(struct device *dev, __be32 desc_hdr_template) return ret; } -static int talitos_remove(struct of_device *ofdev) +static int talitos_remove(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct talitos_private *priv = dev_get_drvdata(dev); @@ -2401,7 +2401,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, return t_alg; } -static int talitos_probe(struct of_device *ofdev, +static int talitos_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device *dev = &ofdev->dev; diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index f0fd6db6063c..cea08bed9cf9 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1297,7 +1297,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan) kfree(chan); } -static int __devinit fsldma_of_probe(struct of_device *op, +static int __devinit fsldma_of_probe(struct platform_device *op, const struct of_device_id *match) { struct fsldma_device *fdev; @@ -1382,7 +1382,7 @@ out_return: return err; } -static int fsldma_of_remove(struct of_device *op) +static int fsldma_of_remove(struct platform_device *op) { struct fsldma_device *fdev; unsigned int i; diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 14a8c0f1698e..4e9cbf300594 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -627,7 +627,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, return &mdesc->desc; } -static int __devinit mpc_dma_probe(struct of_device *op, +static int __devinit mpc_dma_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dn = op->dev.of_node; @@ -753,7 +753,7 @@ static int __devinit mpc_dma_probe(struct of_device *op, return retval; } -static int __devexit mpc_dma_remove(struct of_device *op) +static int __devexit mpc_dma_remove(struct platform_device *op) { struct device *dev = &op->dev; struct mpc_dma *mdma = dev_get_drvdata(dev); diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 7c3747902a37..0d58a4a4487f 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c @@ -4257,11 +4257,11 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev, struct ppc440spe_adma_chan *chan, int *initcode) { - struct of_device *ofdev; + struct platform_device *ofdev; struct device_node *np; int ret; - ofdev = container_of(adev->dev, struct of_device, dev); + ofdev = container_of(adev->dev, struct platform_device, dev); np = ofdev->dev.of_node; if (adev->id != PPC440SPE_XOR_ID) { adev->err_irq = irq_of_parse_and_map(np, 1); @@ -4393,7 +4393,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev, /** * ppc440spe_adma_probe - probe the asynch device */ -static int __devinit ppc440spe_adma_probe(struct of_device *ofdev, +static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -4625,7 +4625,7 @@ out: /** * ppc440spe_adma_remove - remove the asynch device */ -static int __devexit ppc440spe_adma_remove(struct of_device *ofdev) +static int __devexit ppc440spe_adma_remove(struct platform_device *ofdev) { struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev); struct device_node *np = ofdev->dev.of_node; diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 1052340e6802..8ea07b019543 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -200,7 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mpc85xx_pci_err_probe(struct of_device *op, +static int __devinit mpc85xx_pci_err_probe(struct platform_device *op, const struct of_device_id *match) { struct edac_pci_ctl_info *pci; @@ -305,7 +305,7 @@ err: return res; } -static int mpc85xx_pci_err_remove(struct of_device *op) +static int mpc85xx_pci_err_remove(struct platform_device *op) { struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); struct mpc85xx_pci_pdata *pdata = pci->pvt_info; @@ -503,7 +503,7 @@ static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mpc85xx_l2_err_probe(struct of_device *op, +static int __devinit mpc85xx_l2_err_probe(struct platform_device *op, const struct of_device_id *match) { struct edac_device_ctl_info *edac_dev; @@ -613,7 +613,7 @@ err: return res; } -static int mpc85xx_l2_err_remove(struct of_device *op) +static int mpc85xx_l2_err_remove(struct platform_device *op) { struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; @@ -953,7 +953,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) } } -static int __devinit mpc85xx_mc_err_probe(struct of_device *op, +static int __devinit mpc85xx_mc_err_probe(struct platform_device *op, const struct of_device_id *match) { struct mem_ctl_info *mci; @@ -1085,7 +1085,7 @@ err: return res; } -static int mpc85xx_mc_err_remove(struct of_device *op) +static int mpc85xx_mc_err_remove(struct platform_device *op) { struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index e78839e89a06..070cea41b661 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -184,9 +184,9 @@ struct ppc4xx_ecc_status { /* Function Prototypes */ -static int ppc4xx_edac_probe(struct of_device *device, +static int ppc4xx_edac_probe(struct platform_device *device, const struct of_device_id *device_id); -static int ppc4xx_edac_remove(struct of_device *device); +static int ppc4xx_edac_remove(struct platform_device *device); /* Global Variables */ @@ -1014,7 +1014,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) */ static int __devinit ppc4xx_edac_mc_init(struct mem_ctl_info *mci, - struct of_device *op, + struct platform_device *op, const struct of_device_id *match, const dcr_host_t *dcr_host, u32 mcopt1) @@ -1108,7 +1108,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci, * mapped and assigned. */ static int __devinit -ppc4xx_edac_register_irq(struct of_device *op, struct mem_ctl_info *mci) +ppc4xx_edac_register_irq(struct platform_device *op, struct mem_ctl_info *mci) { int status = 0; int ded_irq, sec_irq; @@ -1238,7 +1238,7 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host) * driver; otherwise, < 0 on error. */ static int __devinit -ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match) +ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match) { int status = 0; u32 mcopt1, memcheck; @@ -1359,7 +1359,7 @@ ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match) * Unconditionally returns 0. */ static int -ppc4xx_edac_remove(struct of_device *op) +ppc4xx_edac_remove(struct platform_device *op) { struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); struct ppc4xx_edac_pdata *pdata = mci->pvt_info; diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h index b28d7e27a031..90f094d45450 100644 --- a/drivers/hwmon/ams/ams.h +++ b/drivers/hwmon/ams/ams.h @@ -23,7 +23,7 @@ struct ams { /* General properties */ struct device_node *of_node; - struct of_device *of_dev; + struct platform_device *of_dev; char has_device; char vflag; u32 orient1; diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index 89643261ccdb..d863e13a50b8 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c @@ -234,7 +234,7 @@ static const struct attribute_group env_group = { .attrs = env_attributes, }; -static int __devinit env_probe(struct of_device *op, +static int __devinit env_probe(struct platform_device *op, const struct of_device_id *match) { struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); @@ -276,7 +276,7 @@ out_free: goto out; } -static int __devexit env_remove(struct of_device *op) +static int __devexit env_remove(struct platform_device *op) { struct env *p = dev_get_drvdata(&op->dev); diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index e591de1bc704..f7bd2613cecc 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -105,7 +105,7 @@ struct i2c_reg { struct cpm_i2c { char *base; - struct of_device *ofdev; + struct platform_device *ofdev; struct i2c_adapter adap; uint dp_addr; int version; /* CPM1=1, CPM2=2 */ @@ -428,7 +428,7 @@ static const struct i2c_adapter cpm_ops = { static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) { - struct of_device *ofdev = cpm->ofdev; + struct platform_device *ofdev = cpm->ofdev; const u32 *data; int len, ret, i; void __iomem *i2c_base; @@ -634,7 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm) cpm_muram_free(cpm->i2c_addr); } -static int __devinit cpm_i2c_probe(struct of_device *ofdev, +static int __devinit cpm_i2c_probe(struct platform_device *ofdev, const struct of_device_id *match) { int result, len; @@ -687,7 +687,7 @@ out_free: return result; } -static int __devexit cpm_i2c_remove(struct of_device *ofdev) +static int __devexit cpm_i2c_remove(struct platform_device *ofdev) { struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 1168d61418c9..43ca32fddde2 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -661,7 +661,7 @@ static inline u8 iic_clckdiv(unsigned int opb) return (u8)((opb + 9) / 10 - 1); } -static int __devinit iic_request_irq(struct of_device *ofdev, +static int __devinit iic_request_irq(struct platform_device *ofdev, struct ibm_iic_private *dev) { struct device_node *np = ofdev->dev.of_node; @@ -692,7 +692,7 @@ static int __devinit iic_request_irq(struct of_device *ofdev, /* * Register single IIC interface */ -static int __devinit iic_probe(struct of_device *ofdev, +static int __devinit iic_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -780,7 +780,7 @@ error_cleanup: /* * Cleanup initialized IIC interface */ -static int __devexit iic_remove(struct of_device *ofdev) +static int __devexit iic_remove(struct platform_device *ofdev) { struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 6545d1c99b61..a1c419a716af 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -560,7 +560,7 @@ static struct i2c_adapter mpc_ops = { .timeout = HZ, }; -static int __devinit fsl_i2c_probe(struct of_device *op, +static int __devinit fsl_i2c_probe(struct platform_device *op, const struct of_device_id *match) { struct mpc_i2c *i2c; @@ -646,7 +646,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op, return result; }; -static int __devexit fsl_i2c_remove(struct of_device *op) +static int __devexit fsl_i2c_remove(struct platform_device *op) { struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 0136abd50dd4..aaf6023a4835 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -112,7 +112,7 @@ struct ehca_sport { struct ehca_shca { struct ib_device ib_device; - struct of_device *ofdev; + struct platform_device *ofdev; u8 num_ports; int hw_level; struct list_head shca_list; diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index ecb51b396c42..67c4534fb941 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -712,7 +712,7 @@ static struct attribute_group ehca_dev_attr_grp = { .attrs = ehca_dev_attrs }; -static int __devinit ehca_probe(struct of_device *dev, +static int __devinit ehca_probe(struct platform_device *dev, const struct of_device_id *id) { struct ehca_shca *shca; @@ -878,7 +878,7 @@ probe1: return -EINVAL; } -static int __devexit ehca_remove(struct of_device *dev) +static int __devexit ehca_remove(struct platform_device *dev) { struct ehca_shca *shca = dev_get_drvdata(&dev->dev); unsigned long flags; diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index f3bb92e9755f..8e130bf7d32b 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -173,7 +173,7 @@ static int __devinit sparcspkr_probe(struct device *dev) return 0; } -static int sparcspkr_shutdown(struct of_device *dev) +static int sparcspkr_shutdown(struct platform_device *dev) { struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); struct input_dev *input_dev = state->input_dev; @@ -184,7 +184,7 @@ static int sparcspkr_shutdown(struct of_device *dev) return 0; } -static int __devinit bbc_beep_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit bbc_beep_probe(struct platform_device *op, const struct of_device_id *match) { struct sparcspkr_state *state; struct bbc_beep_info *info; @@ -231,7 +231,7 @@ out_err: return err; } -static int __devexit bbc_remove(struct of_device *op) +static int __devexit bbc_remove(struct platform_device *op) { struct sparcspkr_state *state = dev_get_drvdata(&op->dev); struct input_dev *input_dev = state->input_dev; @@ -269,7 +269,7 @@ static struct of_platform_driver bbc_beep_driver = { .shutdown = sparcspkr_shutdown, }; -static int __devinit grover_beep_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit grover_beep_probe(struct platform_device *op, const struct of_device_id *match) { struct sparcspkr_state *state; struct grover_beep_info *info; @@ -312,7 +312,7 @@ out_err: return err; } -static int __devexit grover_remove(struct of_device *op) +static int __devexit grover_remove(struct platform_device *op) { struct sparcspkr_state *state = dev_get_drvdata(&op->dev); struct grover_beep_info *info = &state->u.grover; diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index cb2a24b94746..c5cc4508d6df 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -49,7 +49,7 @@ static inline void i8042_write_command(int val) #define OBP_PS2MS_NAME1 "kdmouse" #define OBP_PS2MS_NAME2 "mouse" -static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -57,7 +57,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev while (dp) { if (!strcmp(dp->name, OBP_PS2KBD_NAME1) || !strcmp(dp->name, OBP_PS2KBD_NAME2)) { - struct of_device *kbd = of_find_device_by_node(dp); + struct platform_device *kbd = of_find_device_by_node(dp); unsigned int irq = kbd->archdata.irqs[0]; if (irq == 0xffffffff) irq = op->archdata.irqs[0]; @@ -67,7 +67,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev kbd_res = &kbd->resource[0]; } else if (!strcmp(dp->name, OBP_PS2MS_NAME1) || !strcmp(dp->name, OBP_PS2MS_NAME2)) { - struct of_device *ms = of_find_device_by_node(dp); + struct platform_device *ms = of_find_device_by_node(dp); unsigned int irq = ms->archdata.irqs[0]; if (irq == 0xffffffff) irq = op->archdata.irqs[0]; @@ -80,7 +80,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev return 0; } -static int __devexit sparc_i8042_remove(struct of_device *op) +static int __devexit sparc_i8042_remove(struct platform_device *op) { of_iounmap(kbd_res, kbd_iobase, 8); diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index e2c028d2638f..bb14449fb022 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -232,7 +232,7 @@ static void sxps2_close(struct serio *pserio) * It returns 0, if the driver is bound to the PS/2 device, or a negative * value if there is an error. */ -static int __devinit xps2_of_probe(struct of_device *ofdev, +static int __devinit xps2_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct resource r_irq; /* Interrupt resources */ @@ -332,7 +332,7 @@ failed1: * if the driver module is being unloaded. It frees any resources allocated to * the device. */ -static int __devexit xps2_of_remove(struct of_device *of_dev) +static int __devexit xps2_of_remove(struct platform_device *of_dev) { struct device *dev = &of_dev->dev; struct xps2data *drvdata = dev_get_drvdata(dev); diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index cc22eeefa10b..ea57e05d08f3 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -224,7 +224,7 @@ struct gpio_led_of_platform_data { struct gpio_led_data led_data[]; }; -static int __devinit of_gpio_leds_probe(struct of_device *ofdev, +static int __devinit of_gpio_leds_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node, *child; @@ -283,7 +283,7 @@ err: return ret; } -static int __devexit of_gpio_leds_remove(struct of_device *ofdev) +static int __devexit of_gpio_leds_remove(struct platform_device *ofdev) { struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev); int i; diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 6024038a5b9d..8eb40afbd0f5 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c @@ -15,7 +15,7 @@ field##_show (struct device *dev, struct device_attribute *attr, \ static ssize_t compatible_show (struct device *dev, struct device_attribute *attr, char *buf) { - struct of_device *of; + struct platform_device *of; const char *compat; int cplen; int length = 0; @@ -52,9 +52,9 @@ static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, static ssize_t devspec_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct of_device *ofdev; + struct platform_device *ofdev; - ofdev = to_of_device(dev); + ofdev = to_platform_device(dev); return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); } diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 2506c957712e..e58c3d33e035 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -75,7 +75,7 @@ struct smu_cmd_buf { struct smu_device { spinlock_t lock; struct device_node *of_node; - struct of_device *of_dev; + struct platform_device *of_dev; int doorbell; /* doorbell gpio */ u32 __iomem *db_buf; /* doorbell buffer */ struct device_node *db_node; @@ -645,7 +645,7 @@ static void smu_expose_childs(struct work_struct *unused) static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); -static int smu_platform_probe(struct of_device* dev, +static int smu_platform_probe(struct platform_device* dev, const struct of_device_id *match) { if (!smu) @@ -695,7 +695,7 @@ static int __init smu_init_sysfs(void) device_initcall(smu_init_sysfs); -struct of_device *smu_get_ofdev(void) +struct platform_device *smu_get_ofdev(void) { if (!smu) return NULL; diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index c42eeb43042d..d0d221332db0 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -84,7 +84,7 @@ struct thermostat { static enum {ADT7460, ADT7467} therm_type; static int therm_bus, therm_address; -static struct of_device * of_dev; +static struct platform_device * of_dev; static struct thermostat* thermostat; static struct task_struct *thread_therm = NULL; diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index e60605bd0ea9..44549272333c 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -148,7 +148,7 @@ * Driver statics */ -static struct of_device * of_dev; +static struct platform_device * of_dev; static struct i2c_adapter * u3_0; static struct i2c_adapter * u3_1; static struct i2c_adapter * k2; @@ -2210,7 +2210,7 @@ static void fcu_lookup_fans(struct device_node *fcu_node) } } -static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) +static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match) { state = state_detached; @@ -2221,7 +2221,7 @@ static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) return i2c_add_driver(&therm_pm72_driver); } -static int fcu_of_remove(struct of_device* dev) +static int fcu_of_remove(struct platform_device* dev) { i2c_del_driver(&therm_pm72_driver); diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 5c9367acf0cf..133f195de1fd 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -52,7 +52,7 @@ static struct { struct task_struct *poll_task; struct mutex lock; - struct of_device *of_dev; + struct platform_device *of_dev; struct i2c_client *thermostat; struct i2c_client *fan; @@ -444,13 +444,13 @@ static struct i2c_driver g4fan_driver = { /************************************************************************/ static int -therm_of_probe( struct of_device *dev, const struct of_device_id *match ) +therm_of_probe( struct platform_device *dev, const struct of_device_id *match ) { return i2c_add_driver( &g4fan_driver ); } static int -therm_of_remove( struct of_device *dev ) +therm_of_remove( struct platform_device *dev ) { i2c_del_driver( &g4fan_driver ); return 0; diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index 8f1c94f7e00c..43d208f1f586 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c @@ -1418,7 +1418,7 @@ static struct video_device viu_template = { .current_norm = V4L2_STD_NTSC_M, }; -static int __devinit viu_of_probe(struct of_device *op, +static int __devinit viu_of_probe(struct platform_device *op, const struct of_device_id *match) { struct viu_dev *viu_dev; @@ -1549,7 +1549,7 @@ err: return ret; } -static int __devexit viu_of_remove(struct of_device *op) +static int __devexit viu_of_remove(struct platform_device *op) { struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); @@ -1570,7 +1570,7 @@ static int __devexit viu_of_remove(struct of_device *op) } #ifdef CONFIG_PM -static int viu_suspend(struct of_device *op, pm_message_t state) +static int viu_suspend(struct platform_device *op, pm_message_t state) { struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); @@ -1579,7 +1579,7 @@ static int viu_suspend(struct of_device *op, pm_message_t state) return 0; } -static int viu_resume(struct of_device *op) +static int viu_resume(struct platform_device *op) { struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c index a2e9820cd42f..a6bd448a3b46 100644 --- a/drivers/mmc/host/sdhci-of-core.c +++ b/drivers/mmc/host/sdhci-of-core.c @@ -85,14 +85,14 @@ void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) #ifdef CONFIG_PM -static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state) +static int sdhci_of_suspend(struct platform_device *ofdev, pm_message_t state) { struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); return mmc_suspend_host(host->mmc); } -static int sdhci_of_resume(struct of_device *ofdev) +static int sdhci_of_resume(struct platform_device *ofdev) { struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); @@ -115,7 +115,7 @@ static bool __devinit sdhci_of_wp_inverted(struct device_node *np) return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds); } -static int __devinit sdhci_of_probe(struct of_device *ofdev, +static int __devinit sdhci_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -179,7 +179,7 @@ err_addr_map: return ret; } -static int __devexit sdhci_of_remove(struct of_device *ofdev) +static int __devexit sdhci_of_remove(struct platform_device *ofdev) { struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index ba124baa646d..8f9bab8dc8da 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -43,7 +43,7 @@ struct of_flash { #ifdef CONFIG_MTD_PARTITIONS #define OF_FLASH_PARTS(info) ((info)->parts) -static int parse_obsolete_partitions(struct of_device *dev, +static int parse_obsolete_partitions(struct platform_device *dev, struct of_flash *info, struct device_node *dp) { @@ -93,7 +93,7 @@ static int parse_obsolete_partitions(struct of_device *dev, #define parse_partitions(info, dev) (0) #endif /* MTD_PARTITIONS */ -static int of_flash_remove(struct of_device *dev) +static int of_flash_remove(struct platform_device *dev) { struct of_flash *info; int i; @@ -140,7 +140,7 @@ static int of_flash_remove(struct of_device *dev) /* Helper function to handle probing of the obsolete "direct-mapped" * compatible binding, which has an extra "probe-type" property * describing the type of flash probe necessary. */ -static struct mtd_info * __devinit obsolete_probe(struct of_device *dev, +static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, struct map_info *map) { struct device_node *dp = dev->dev.of_node; @@ -215,7 +215,7 @@ static void __devinit of_free_probes(const char **probes) } #endif -static int __devinit of_flash_probe(struct of_device *dev, +static int __devinit of_flash_probe(struct platform_device *dev, const struct of_device_id *match) { #ifdef CONFIG_MTD_PARTITIONS diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 8984236a8d0a..3582ba1f9b09 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -48,7 +48,7 @@ struct map_info uflash_map_templ = { .bankwidth = UFLASH_BUSWIDTH, }; -int uflash_devinit(struct of_device *op, struct device_node *dp) +int uflash_devinit(struct platform_device *op, struct device_node *dp) { struct uflash_dev *up; @@ -108,7 +108,7 @@ int uflash_devinit(struct of_device *op, struct device_node *dp) return 0; } -static int __devinit uflash_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit uflash_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -121,7 +121,7 @@ static int __devinit uflash_probe(struct of_device *op, const struct of_device_i return uflash_devinit(op, dp); } -static int __devexit uflash_remove(struct of_device *op) +static int __devexit uflash_remove(struct platform_device *op) { struct uflash_dev *up = dev_get_drvdata(&op->dev); diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 5084cc517944..80de0bff6c3a 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -958,7 +958,7 @@ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) return 0; } -static int fsl_elbc_ctrl_remove(struct of_device *ofdev) +static int fsl_elbc_ctrl_remove(struct platform_device *ofdev) { struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); int i; @@ -1013,7 +1013,7 @@ static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) * in the chip probe function. */ -static int __devinit fsl_elbc_ctrl_probe(struct of_device *ofdev, +static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *child; diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 1312eda57ba6..4eff8b25e5af 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -217,7 +217,7 @@ err: return ret; } -static int __devinit fun_probe(struct of_device *ofdev, +static int __devinit fun_probe(struct platform_device *ofdev, const struct of_device_id *ofid) { struct fsl_upm_nand *fun; @@ -335,7 +335,7 @@ err1: return ret; } -static int __devexit fun_remove(struct of_device *ofdev) +static int __devexit fun_remove(struct platform_device *ofdev) { struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); int i; diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 0a130dcaa129..df0c1da4ff49 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -647,7 +647,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) iounmap(prv->csreg); } -static int __devinit mpc5121_nfc_probe(struct of_device *op, +static int __devinit mpc5121_nfc_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *rootnode, *dn = op->dev.of_node; @@ -869,7 +869,7 @@ error: return retval; } -static int __devexit mpc5121_nfc_remove(struct of_device *op) +static int __devexit mpc5121_nfc_remove(struct platform_device *op) { struct device *dev = &op->dev; struct mtd_info *mtd = dev_get_drvdata(dev); diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 98fd2bdf8be1..510554e6c115 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -35,7 +35,7 @@ struct ndfc_controller { - struct of_device *ofdev; + struct platform_device *ofdev; void __iomem *ndfcbase; struct mtd_info mtd; struct nand_chip chip; @@ -225,7 +225,7 @@ err: return ret; } -static int __devinit ndfc_probe(struct of_device *ofdev, +static int __devinit ndfc_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct ndfc_controller *ndfc = &ndfc_ctrl; @@ -277,7 +277,7 @@ static int __devinit ndfc_probe(struct of_device *ofdev, return 0; } -static int __devexit ndfc_remove(struct of_device *ofdev) +static int __devexit ndfc_remove(struct platform_device *ofdev) { struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index f02af24d033a..6ddb2461d740 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -89,7 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd) return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); } -static int __devinit pasemi_nand_probe(struct of_device *ofdev, +static int __devinit pasemi_nand_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct pci_dev *pdev; @@ -185,7 +185,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev, return err; } -static int __devexit pasemi_nand_remove(struct of_device *ofdev) +static int __devexit pasemi_nand_remove(struct platform_device *ofdev) { struct nand_chip *chip; diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index cc728b12de82..a8e403eebedb 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -162,7 +162,7 @@ static const char *part_probes[] = { "cmdlinepart", NULL }; /* * Probe for the NAND device. */ -static int __devinit socrates_nand_probe(struct of_device *ofdev, +static int __devinit socrates_nand_probe(struct platform_device *ofdev, const struct of_device_id *ofid) { struct socrates_nand_host *host; @@ -276,7 +276,7 @@ out: /* * Remove a NAND device. */ -static int __devexit socrates_nand_remove(struct of_device *ofdev) +static int __devexit socrates_nand_remove(struct platform_device *ofdev) { struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); struct mtd_info *mtd = &host->mtd; diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index af753936e835..b1bdc909090f 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -38,7 +38,7 @@ struct mpc5xxx_can_data { unsigned int type; - u32 (*get_clock)(struct of_device *ofdev, const char *clock_name, + u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc); }; @@ -48,7 +48,7 @@ static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = { {} }; -static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, +static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc) { @@ -101,7 +101,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, return freq; } #else /* !CONFIG_PPC_MPC52xx */ -static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, +static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc) { @@ -129,7 +129,7 @@ static struct of_device_id __devinitdata mpc512x_clock_ids[] = { {} }; -static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, +static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc) { @@ -239,7 +239,7 @@ exit_unmap: return freq; } #else /* !CONFIG_PPC_MPC512x */ -static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, +static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc) { @@ -247,7 +247,7 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, } #endif /* CONFIG_PPC_MPC512x */ -static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, +static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev, const struct of_device_id *id) { struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; @@ -317,7 +317,7 @@ exit_unmap_mem: return err; } -static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) +static int __devexit mpc5xxx_can_remove(struct platform_device *ofdev) { struct net_device *dev = dev_get_drvdata(&ofdev->dev); struct mscan_priv *priv = netdev_priv(dev); @@ -334,7 +334,7 @@ static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) #ifdef CONFIG_PM static struct mscan_regs saved_regs; -static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) +static int mpc5xxx_can_suspend(struct platform_device *ofdev, pm_message_t state) { struct net_device *dev = dev_get_drvdata(&ofdev->dev); struct mscan_priv *priv = netdev_priv(dev); @@ -345,7 +345,7 @@ static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) return 0; } -static int mpc5xxx_can_resume(struct of_device *ofdev) +static int mpc5xxx_can_resume(struct platform_device *ofdev) { struct net_device *dev = dev_get_drvdata(&ofdev->dev); struct mscan_priv *priv = netdev_priv(dev); diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index ac1a83d7c204..5bfccfdf3bbb 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -67,7 +67,7 @@ static void sja1000_ofp_write_reg(const struct sja1000_priv *priv, out_8(priv->reg_base + reg, val); } -static int __devexit sja1000_ofp_remove(struct of_device *ofdev) +static int __devexit sja1000_ofp_remove(struct platform_device *ofdev) { struct net_device *dev = dev_get_drvdata(&ofdev->dev); struct sja1000_priv *priv = netdev_priv(dev); @@ -87,7 +87,7 @@ static int __devexit sja1000_ofp_remove(struct of_device *ofdev) return 0; } -static int __devinit sja1000_ofp_probe(struct of_device *ofdev, +static int __devinit sja1000_ofp_probe(struct platform_device *ofdev, const struct of_device_id *id) { struct device_node *np = ofdev->dev.of_node; diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0060e422f171..99a929964e3c 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -413,7 +413,7 @@ struct ehea_port_res { struct ehea_adapter { u64 handle; - struct of_device *ofdev; + struct platform_device *ofdev; struct ehea_port *port[EHEA_MAX_PORTS]; struct ehea_eq *neq; /* notification event queue */ struct tasklet_struct neq_tasklet; @@ -465,7 +465,7 @@ struct ehea_port { struct net_device *netdev; struct net_device_stats stats; struct ehea_port_res port_res[EHEA_MAX_PORT_RES]; - struct of_device ofdev; /* Open Firmware Device */ + struct platform_device ofdev; /* Open Firmware Device */ struct ehea_mc_list *mc_list; /* Multicast MAC addresses */ struct vlan_group *vgrp; struct ehea_eq *qp_eq; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 3beba70b7dea..897719b49f96 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -107,10 +107,10 @@ struct ehea_fw_handle_array ehea_fw_handles; struct ehea_bcmc_reg_array ehea_bcmc_regs; -static int __devinit ehea_probe_adapter(struct of_device *dev, +static int __devinit ehea_probe_adapter(struct platform_device *dev, const struct of_device_id *id); -static int __devexit ehea_remove(struct of_device *dev); +static int __devexit ehea_remove(struct platform_device *dev); static struct of_device_id ehea_device_table[] = { { @@ -3376,7 +3376,7 @@ static ssize_t ehea_remove_port(struct device *dev, static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); -int ehea_create_device_sysfs(struct of_device *dev) +int ehea_create_device_sysfs(struct platform_device *dev) { int ret = device_create_file(&dev->dev, &dev_attr_probe_port); if (ret) @@ -3387,13 +3387,13 @@ out: return ret; } -void ehea_remove_device_sysfs(struct of_device *dev) +void ehea_remove_device_sysfs(struct platform_device *dev) { device_remove_file(&dev->dev, &dev_attr_probe_port); device_remove_file(&dev->dev, &dev_attr_remove_port); } -static int __devinit ehea_probe_adapter(struct of_device *dev, +static int __devinit ehea_probe_adapter(struct platform_device *dev, const struct of_device_id *id) { struct ehea_adapter *adapter; @@ -3492,7 +3492,7 @@ out: return ret; } -static int __devexit ehea_remove(struct of_device *dev) +static int __devexit ehea_remove(struct platform_device *dev) { struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); int i; diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index d1a5b17b2a95..e3e10b4add9c 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -850,7 +850,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = { /* ======================================================================== */ static int __devinit -mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) +mpc52xx_fec_probe(struct platform_device *op, const struct of_device_id *match) { int rv; struct net_device *ndev; @@ -995,7 +995,7 @@ err_netdev: } static int -mpc52xx_fec_remove(struct of_device *op) +mpc52xx_fec_remove(struct platform_device *op) { struct net_device *ndev; struct mpc52xx_fec_priv *priv; @@ -1025,7 +1025,7 @@ mpc52xx_fec_remove(struct of_device *op) } #ifdef CONFIG_PM -static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) +static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state) { struct net_device *dev = dev_get_drvdata(&op->dev); @@ -1035,7 +1035,7 @@ static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) return 0; } -static int mpc52xx_fec_of_resume(struct of_device *op) +static int mpc52xx_fec_of_resume(struct platform_device *op) { struct net_device *dev = dev_get_drvdata(&op->dev); diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index dbaf72cbb233..0b4cb6f15984 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c @@ -61,7 +61,7 @@ static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, data | FEC_MII_WRITE_FRAME); } -static int mpc52xx_fec_mdio_probe(struct of_device *of, +static int mpc52xx_fec_mdio_probe(struct platform_device *of, const struct of_device_id *match) { struct device *dev = &of->dev; @@ -122,7 +122,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, return err; } -static int mpc52xx_fec_mdio_remove(struct of_device *of) +static int mpc52xx_fec_mdio_remove(struct platform_device *of) { struct device *dev = &of->dev; struct mii_bus *bus = dev_get_drvdata(dev); diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index f08cff9020bd..d6e3111959ab 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -997,7 +997,7 @@ static const struct net_device_ops fs_enet_netdev_ops = { #endif }; -static int __devinit fs_enet_probe(struct of_device *ofdev, +static int __devinit fs_enet_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct net_device *ndev; @@ -1105,7 +1105,7 @@ out_free_fpi: return ret; } -static int fs_enet_remove(struct of_device *ofdev) +static int fs_enet_remove(struct platform_device *ofdev) { struct net_device *ndev = dev_get_drvdata(&ofdev->dev); struct fs_enet_private *fep = netdev_priv(ndev); diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 48e91b6242ce..7a84e45487e8 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -84,7 +84,7 @@ static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op) static int do_pd_setup(struct fs_enet_private *fep) { - struct of_device *ofdev = to_of_device(fep->dev); + struct platform_device *ofdev = to_platform_device(fep->dev); struct fs_platform_info *fpi = fep->fpi; int ret = -EINVAL; diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 7ca1642276d0..61035fc5599b 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -96,7 +96,7 @@ static int whack_reset(struct fec __iomem *fecp) static int do_pd_setup(struct fs_enet_private *fep) { - struct of_device *ofdev = to_of_device(fep->dev); + struct platform_device *ofdev = to_platform_device(fep->dev); fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); if (fep->interrupt == NO_IRQ) diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index a3c44544846d..22a02a767069 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -96,7 +96,7 @@ static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op) static int do_pd_setup(struct fs_enet_private *fep) { - struct of_device *ofdev = to_of_device(fep->dev); + struct platform_device *ofdev = to_platform_device(fep->dev); fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); if (fep->interrupt == NO_IRQ) diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index 3607340f3da7..3cda2b515471 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c @@ -150,7 +150,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, return 0; } -static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, +static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct mii_bus *new_bus; @@ -200,7 +200,7 @@ out: return ret; } -static int fs_enet_mdio_remove(struct of_device *ofdev) +static int fs_enet_mdio_remove(struct platform_device *ofdev) { struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); struct bb_info *bitbang = bus->priv; diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index bddffd169b93..dbb9c48623df 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c @@ -101,7 +101,7 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus) return 0; } -static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, +static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct resource res; @@ -192,7 +192,7 @@ out: return ret; } -static int fs_enet_mdio_remove(struct of_device *ofdev) +static int fs_enet_mdio_remove(struct platform_device *ofdev) { struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); struct fec_info *fec = bus->priv; diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index f53f850b6418..d4bf91aac25f 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -265,7 +265,7 @@ static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) #endif -static int fsl_pq_mdio_probe(struct of_device *ofdev, +static int fsl_pq_mdio_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -425,7 +425,7 @@ err_free_priv: } -static int fsl_pq_mdio_remove(struct of_device *ofdev) +static int fsl_pq_mdio_remove(struct platform_device *ofdev) { struct device *device = &ofdev->dev; struct mii_bus *bus = dev_get_drvdata(device); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index a1b6301bc674..4f7c3f3ca234 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -122,9 +122,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id); static void adjust_link(struct net_device *dev); static void init_registers(struct net_device *dev); static int init_phy(struct net_device *dev); -static int gfar_probe(struct of_device *ofdev, +static int gfar_probe(struct platform_device *ofdev, const struct of_device_id *match); -static int gfar_remove(struct of_device *ofdev); +static int gfar_remove(struct platform_device *ofdev); static void free_skb_resources(struct gfar_private *priv); static void gfar_set_multi(struct net_device *dev); static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); @@ -605,7 +605,7 @@ static int gfar_parse_group(struct device_node *np, return 0; } -static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev) +static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) { const char *model; const char *ctype; @@ -959,7 +959,7 @@ static void gfar_detect_errata(struct gfar_private *priv) /* Set up the ethernet device structure, private data, * and anything else we need before we start */ -static int gfar_probe(struct of_device *ofdev, +static int gfar_probe(struct platform_device *ofdev, const struct of_device_id *match) { u32 tempval; @@ -1238,7 +1238,7 @@ register_fail: return err; } -static int gfar_remove(struct of_device *ofdev) +static int gfar_remove(struct platform_device *ofdev) { struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 710810e2adb4..68984eb88ae0 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -1054,7 +1054,7 @@ struct gfar_private { struct device_node *node; struct net_device *ndev; - struct of_device *ofdev; + struct platform_device *ofdev; enum gfar_errata errata; struct gfar_priv_grp gfargrp[MAXGROUPS]; diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 4d09eab3548e..9ec4b7f28ca4 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -1373,7 +1373,7 @@ error: } /* Initialize the GRETH MAC */ -static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_device_id *match) +static int __devinit greth_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct net_device *dev; struct greth_private *greth; @@ -1572,7 +1572,7 @@ error1: return err; } -static int __devexit greth_of_remove(struct of_device *of_dev) +static int __devexit greth_of_remove(struct platform_device *of_dev) { struct net_device *ndev = dev_get_drvdata(&of_dev->dev); struct greth_private *greth = netdev_priv(ndev); diff --git a/drivers/net/greth.h b/drivers/net/greth.h index 973388d6abca..03ad903cd676 100644 --- a/drivers/net/greth.h +++ b/drivers/net/greth.h @@ -118,7 +118,7 @@ struct greth_private { int irq; - struct device *dev; /* Pointer to of_device->dev */ + struct device *dev; /* Pointer to platform_device->dev */ struct net_device *netdev; struct napi_struct napi; spinlock_t devlock; diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index eeec7bc2ce74..3506fd6ad726 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2245,7 +2245,7 @@ static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) struct emac_depentry { u32 phandle; struct device_node *node; - struct of_device *ofdev; + struct platform_device *ofdev; void *drvdata; }; @@ -2719,7 +2719,7 @@ static const struct net_device_ops emac_gige_netdev_ops = { .ndo_change_mtu = emac_change_mtu, }; -static int __devinit emac_probe(struct of_device *ofdev, +static int __devinit emac_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct net_device *ndev; @@ -2941,7 +2941,7 @@ static int __devinit emac_probe(struct of_device *ofdev, return err; } -static int __devexit emac_remove(struct of_device *ofdev) +static int __devexit emac_remove(struct platform_device *ofdev) { struct emac_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h index b1cbe6fdfc7a..9e37e3d9c51d 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h @@ -170,12 +170,12 @@ struct emac_instance { struct net_device *ndev; struct resource rsrc_regs; struct emac_regs __iomem *emacp; - struct of_device *ofdev; + struct platform_device *ofdev; struct device_node **blist; /* bootlist entry */ /* MAL linkage */ u32 mal_ph; - struct of_device *mal_dev; + struct platform_device *mal_dev; u32 mal_rx_chan; u32 mal_tx_chan; struct mal_instance *mal; @@ -196,24 +196,24 @@ struct emac_instance { /* Shared MDIO if any */ u32 mdio_ph; - struct of_device *mdio_dev; + struct platform_device *mdio_dev; struct emac_instance *mdio_instance; struct mutex mdio_lock; /* ZMII infos if any */ u32 zmii_ph; u32 zmii_port; - struct of_device *zmii_dev; + struct platform_device *zmii_dev; /* RGMII infos if any */ u32 rgmii_ph; u32 rgmii_port; - struct of_device *rgmii_dev; + struct platform_device *rgmii_dev; /* TAH infos if any */ u32 tah_ph; u32 tah_port; - struct of_device *tah_dev; + struct platform_device *tah_dev; /* IRQs */ int wol_irq; diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index fcff9e0bd382..d5717e2123e1 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c @@ -517,7 +517,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf) return regs + 1; } -static int __devinit mal_probe(struct of_device *ofdev, +static int __devinit mal_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct mal_instance *mal; @@ -730,7 +730,7 @@ static int __devinit mal_probe(struct of_device *ofdev, return err; } -static int __devexit mal_remove(struct of_device *ofdev) +static int __devexit mal_remove(struct platform_device *ofdev) { struct mal_instance *mal = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 9ededfbf0726..66084214bf45 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h @@ -210,7 +210,7 @@ struct mal_instance { dma_addr_t bd_dma; struct mal_descriptor *bd_virt; - struct of_device *ofdev; + struct platform_device *ofdev; int index; spinlock_t lock; diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index 108919bcdf13..dd61798897ac 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c @@ -93,7 +93,7 @@ static inline u32 rgmii_mode_mask(int mode, int input) } } -int __devinit rgmii_attach(struct of_device *ofdev, int input, int mode) +int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -122,7 +122,7 @@ int __devinit rgmii_attach(struct of_device *ofdev, int input, int mode) return 0; } -void rgmii_set_speed(struct of_device *ofdev, int input, int speed) +void rgmii_set_speed(struct platform_device *ofdev, int input, int speed) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -144,7 +144,7 @@ void rgmii_set_speed(struct of_device *ofdev, int input, int speed) mutex_unlock(&dev->lock); } -void rgmii_get_mdio(struct of_device *ofdev, int input) +void rgmii_get_mdio(struct platform_device *ofdev, int input) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -165,7 +165,7 @@ void rgmii_get_mdio(struct of_device *ofdev, int input) DBG2(dev, " fer = 0x%08x\n", fer); } -void rgmii_put_mdio(struct of_device *ofdev, int input) +void rgmii_put_mdio(struct platform_device *ofdev, int input) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -186,7 +186,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input) mutex_unlock(&dev->lock); } -void rgmii_detach(struct of_device *ofdev, int input) +void rgmii_detach(struct platform_device *ofdev, int input) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p; @@ -206,13 +206,13 @@ void rgmii_detach(struct of_device *ofdev, int input) mutex_unlock(&dev->lock); } -int rgmii_get_regs_len(struct of_device *ofdev) +int rgmii_get_regs_len(struct platform_device *ofdev) { return sizeof(struct emac_ethtool_regs_subhdr) + sizeof(struct rgmii_regs); } -void *rgmii_dump_regs(struct of_device *ofdev, void *buf) +void *rgmii_dump_regs(struct platform_device *ofdev, void *buf) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct emac_ethtool_regs_subhdr *hdr = buf; @@ -228,7 +228,7 @@ void *rgmii_dump_regs(struct of_device *ofdev, void *buf) } -static int __devinit rgmii_probe(struct of_device *ofdev, +static int __devinit rgmii_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -293,7 +293,7 @@ static int __devinit rgmii_probe(struct of_device *ofdev, return rc; } -static int __devexit rgmii_remove(struct of_device *ofdev) +static int __devexit rgmii_remove(struct platform_device *ofdev) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/rgmii.h b/drivers/net/ibm_newemac/rgmii.h index c4a4b358a270..d69799049865 100644 --- a/drivers/net/ibm_newemac/rgmii.h +++ b/drivers/net/ibm_newemac/rgmii.h @@ -51,20 +51,20 @@ struct rgmii_instance { int users; /* OF device instance */ - struct of_device *ofdev; + struct platform_device *ofdev; }; #ifdef CONFIG_IBM_NEW_EMAC_RGMII extern int rgmii_init(void); extern void rgmii_exit(void); -extern int rgmii_attach(struct of_device *ofdev, int input, int mode); -extern void rgmii_detach(struct of_device *ofdev, int input); -extern void rgmii_get_mdio(struct of_device *ofdev, int input); -extern void rgmii_put_mdio(struct of_device *ofdev, int input); -extern void rgmii_set_speed(struct of_device *ofdev, int input, int speed); -extern int rgmii_get_regs_len(struct of_device *ofdev); -extern void *rgmii_dump_regs(struct of_device *ofdev, void *buf); +extern int rgmii_attach(struct platform_device *ofdev, int input, int mode); +extern void rgmii_detach(struct platform_device *ofdev, int input); +extern void rgmii_get_mdio(struct platform_device *ofdev, int input); +extern void rgmii_put_mdio(struct platform_device *ofdev, int input); +extern void rgmii_set_speed(struct platform_device *ofdev, int input, int speed); +extern int rgmii_get_regs_len(struct platform_device *ofdev); +extern void *rgmii_dump_regs(struct platform_device *ofdev, void *buf); #else diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c index 044637144c43..299aa49490c0 100644 --- a/drivers/net/ibm_newemac/tah.c +++ b/drivers/net/ibm_newemac/tah.c @@ -23,7 +23,7 @@ #include "emac.h" #include "core.h" -int __devinit tah_attach(struct of_device *ofdev, int channel) +int __devinit tah_attach(struct platform_device *ofdev, int channel) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel) return 0; } -void tah_detach(struct of_device *ofdev, int channel) +void tah_detach(struct platform_device *ofdev, int channel) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -44,7 +44,7 @@ void tah_detach(struct of_device *ofdev, int channel) mutex_unlock(&dev->lock); } -void tah_reset(struct of_device *ofdev) +void tah_reset(struct platform_device *ofdev) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); struct tah_regs __iomem *p = dev->base; @@ -66,13 +66,13 @@ void tah_reset(struct of_device *ofdev) TAH_MR_DIG); } -int tah_get_regs_len(struct of_device *ofdev) +int tah_get_regs_len(struct platform_device *ofdev) { return sizeof(struct emac_ethtool_regs_subhdr) + sizeof(struct tah_regs); } -void *tah_dump_regs(struct of_device *ofdev, void *buf) +void *tah_dump_regs(struct platform_device *ofdev, void *buf) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); struct emac_ethtool_regs_subhdr *hdr = buf; @@ -87,7 +87,7 @@ void *tah_dump_regs(struct of_device *ofdev, void *buf) return regs + 1; } -static int __devinit tah_probe(struct of_device *ofdev, +static int __devinit tah_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -139,7 +139,7 @@ static int __devinit tah_probe(struct of_device *ofdev, return rc; } -static int __devexit tah_remove(struct of_device *ofdev) +static int __devexit tah_remove(struct platform_device *ofdev) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/tah.h b/drivers/net/ibm_newemac/tah.h index a068b5658dad..61dbeca006d1 100644 --- a/drivers/net/ibm_newemac/tah.h +++ b/drivers/net/ibm_newemac/tah.h @@ -48,7 +48,7 @@ struct tah_instance { int users; /* OF device instance */ - struct of_device *ofdev; + struct platform_device *ofdev; }; @@ -74,11 +74,11 @@ struct tah_instance { extern int tah_init(void); extern void tah_exit(void); -extern int tah_attach(struct of_device *ofdev, int channel); -extern void tah_detach(struct of_device *ofdev, int channel); -extern void tah_reset(struct of_device *ofdev); -extern int tah_get_regs_len(struct of_device *ofdev); -extern void *tah_dump_regs(struct of_device *ofdev, void *buf); +extern int tah_attach(struct platform_device *ofdev, int channel); +extern void tah_detach(struct platform_device *ofdev, int channel); +extern void tah_reset(struct platform_device *ofdev); +extern int tah_get_regs_len(struct platform_device *ofdev); +extern void *tah_dump_regs(struct platform_device *ofdev, void *buf); #else diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c index 046dcd069c45..34ed6ee8ca8a 100644 --- a/drivers/net/ibm_newemac/zmii.c +++ b/drivers/net/ibm_newemac/zmii.c @@ -82,7 +82,7 @@ static inline u32 zmii_mode_mask(int mode, int input) } } -int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) +int __devinit zmii_attach(struct platform_device *ofdev, int input, int *mode) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct zmii_regs __iomem *p = dev->base; @@ -148,7 +148,7 @@ int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) return 0; } -void zmii_get_mdio(struct of_device *ofdev, int input) +void zmii_get_mdio(struct platform_device *ofdev, int input) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); u32 fer; @@ -161,7 +161,7 @@ void zmii_get_mdio(struct of_device *ofdev, int input) out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input)); } -void zmii_put_mdio(struct of_device *ofdev, int input) +void zmii_put_mdio(struct platform_device *ofdev, int input) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -170,7 +170,7 @@ void zmii_put_mdio(struct of_device *ofdev, int input) } -void zmii_set_speed(struct of_device *ofdev, int input, int speed) +void zmii_set_speed(struct platform_device *ofdev, int input, int speed) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); u32 ssr; @@ -191,7 +191,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed) mutex_unlock(&dev->lock); } -void zmii_detach(struct of_device *ofdev, int input) +void zmii_detach(struct platform_device *ofdev, int input) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -210,13 +210,13 @@ void zmii_detach(struct of_device *ofdev, int input) mutex_unlock(&dev->lock); } -int zmii_get_regs_len(struct of_device *ofdev) +int zmii_get_regs_len(struct platform_device *ofdev) { return sizeof(struct emac_ethtool_regs_subhdr) + sizeof(struct zmii_regs); } -void *zmii_dump_regs(struct of_device *ofdev, void *buf) +void *zmii_dump_regs(struct platform_device *ofdev, void *buf) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct emac_ethtool_regs_subhdr *hdr = buf; @@ -231,7 +231,7 @@ void *zmii_dump_regs(struct of_device *ofdev, void *buf) return regs + 1; } -static int __devinit zmii_probe(struct of_device *ofdev, +static int __devinit zmii_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -286,7 +286,7 @@ static int __devinit zmii_probe(struct of_device *ofdev, return rc; } -static int __devexit zmii_remove(struct of_device *ofdev) +static int __devexit zmii_remove(struct platform_device *ofdev) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/zmii.h b/drivers/net/ibm_newemac/zmii.h index 6c9beba0c4b6..1333fa2b2781 100644 --- a/drivers/net/ibm_newemac/zmii.h +++ b/drivers/net/ibm_newemac/zmii.h @@ -48,20 +48,20 @@ struct zmii_instance { u32 fer_save; /* OF device instance */ - struct of_device *ofdev; + struct platform_device *ofdev; }; #ifdef CONFIG_IBM_NEW_EMAC_ZMII extern int zmii_init(void); extern void zmii_exit(void); -extern int zmii_attach(struct of_device *ofdev, int input, int *mode); -extern void zmii_detach(struct of_device *ofdev, int input); -extern void zmii_get_mdio(struct of_device *ofdev, int input); -extern void zmii_put_mdio(struct of_device *ofdev, int input); -extern void zmii_set_speed(struct of_device *ofdev, int input, int speed); -extern int zmii_get_regs_len(struct of_device *ocpdev); -extern void *zmii_dump_regs(struct of_device *ofdev, void *buf); +extern int zmii_attach(struct platform_device *ofdev, int input, int *mode); +extern void zmii_detach(struct platform_device *ofdev, int input); +extern void zmii_get_mdio(struct platform_device *ofdev, int input); +extern void zmii_put_mdio(struct platform_device *ofdev, int input); +extern void zmii_set_speed(struct platform_device *ofdev, int input, int speed); +extern int zmii_get_regs_len(struct platform_device *ocpdev); +extern void *zmii_dump_regs(struct platform_device *ofdev, void *buf); #else # define zmii_init() 0 diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 4eea3f70c5cf..c7b624711f5e 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -159,7 +159,7 @@ static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value) * temac_dcr_setup - If the DMA is DCR based, then setup the address and * I/O functions */ -static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, +static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, struct device_node *np) { unsigned int dcrs; @@ -184,7 +184,7 @@ static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, * temac_dcr_setup - This is a stub for when DCR is not supported, * such as with MicroBlaze */ -static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, +static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, struct device_node *np) { return -1; @@ -952,7 +952,7 @@ static const struct attribute_group temac_attr_group = { }; static int __init -temac_of_probe(struct of_device *op, const struct of_device_id *match) +temac_of_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *np; struct temac_local *lp; @@ -1094,7 +1094,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) return rc; } -static int __devexit temac_of_remove(struct of_device *op) +static int __devexit temac_of_remove(struct platform_device *op) { struct net_device *ndev = dev_get_drvdata(&op->dev); struct temac_local *lp = netdev_priv(ndev); diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 04e552aa14ec..617f898ba5f0 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -926,7 +926,7 @@ static const struct net_device_ops myri_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit myri_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; static unsigned version_printed; @@ -1124,7 +1124,7 @@ err: return -ENODEV; } -static int __devexit myri_sbus_remove(struct of_device *op) +static int __devexit myri_sbus_remove(struct platform_device *op) { struct myri_eth *mp = dev_get_drvdata(&op->dev); struct net_device *net_dev = mp->dev; diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h index ff363e95d9cf..80a2fa5cf757 100644 --- a/drivers/net/myri_sbus.h +++ b/drivers/net/myri_sbus.h @@ -288,7 +288,7 @@ struct myri_eth { struct myri_eeprom eeprom; /* Local copy of EEPROM. */ unsigned int reg_size; /* Size of register space. */ unsigned int shmem_base; /* Offset to shared ram. */ - struct of_device *myri_op; /* Our OF device struct. */ + struct platform_device *myri_op; /* Our OF device struct. */ }; /* We use this to acquire receive skb's that we can DMA directly into. */ diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 404f2d552888..bc695d53cdcc 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -9103,7 +9103,7 @@ retry: static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) { #ifdef CONFIG_SPARC64 - struct of_device *op = np->op; + struct platform_device *op = np->op; const u32 *int_prop; int i; @@ -9688,7 +9688,7 @@ static void __devinit niu_driver_version(void) static struct net_device * __devinit niu_alloc_and_init( struct device *gen_dev, struct pci_dev *pdev, - struct of_device *op, const struct niu_ops *ops, + struct platform_device *op, const struct niu_ops *ops, u8 port) { struct net_device *dev; @@ -10064,7 +10064,7 @@ static const struct niu_ops niu_phys_ops = { .unmap_single = niu_phys_unmap_single, }; -static int __devinit niu_of_probe(struct of_device *op, +static int __devinit niu_of_probe(struct platform_device *op, const struct of_device_id *match) { union niu_parent_id parent_id; @@ -10179,7 +10179,7 @@ err_out: return err; } -static int __devexit niu_of_remove(struct of_device *op) +static int __devexit niu_of_remove(struct platform_device *op) { struct net_device *dev = dev_get_drvdata(&op->dev); diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index fc5fef2a8175..f62c7b717bc8 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -188,7 +188,7 @@ static int __devexit mdio_gpio_remove(struct platform_device *pdev) #ifdef CONFIG_OF_GPIO -static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, +static int __devinit mdio_ofgpio_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct mdio_gpio_platform_data *pdata; @@ -224,7 +224,7 @@ out_free: return -ENODEV; } -static int __devexit mdio_ofgpio_remove(struct of_device *ofdev) +static int __devexit mdio_ofgpio_remove(struct platform_device *ofdev) { mdio_gpio_bus_destroy(&ofdev->dev); kfree(ofdev->dev.platform_data); diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 09c071bd6ad4..618643e3ca3e 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -97,7 +97,7 @@ static int qec_global_reset(void __iomem *gregs) static void qec_init(struct bigmac *bp) { - struct of_device *qec_op = bp->qec_op; + struct platform_device *qec_op = bp->qec_op; void __iomem *gregs = bp->gregs; u8 bsizes = bp->bigmac_bursts; u32 regval; @@ -1083,8 +1083,8 @@ static const struct net_device_ops bigmac_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit bigmac_ether_init(struct of_device *op, - struct of_device *qec_op) +static int __devinit bigmac_ether_init(struct platform_device *op, + struct platform_device *qec_op) { static int version_printed; struct net_device *dev; @@ -1242,25 +1242,25 @@ fail_and_cleanup: /* QEC can be the parent of either QuadEthernet or a BigMAC. We want * the latter. */ -static int __devinit bigmac_sbus_probe(struct of_device *op, +static int __devinit bigmac_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device *parent = op->dev.parent; - struct of_device *qec_op; + struct platform_device *qec_op; - qec_op = to_of_device(parent); + qec_op = to_platform_device(parent); return bigmac_ether_init(op, qec_op); } -static int __devexit bigmac_sbus_remove(struct of_device *op) +static int __devexit bigmac_sbus_remove(struct platform_device *op) { struct bigmac *bp = dev_get_drvdata(&op->dev); struct device *parent = op->dev.parent; struct net_device *net_dev = bp->dev; - struct of_device *qec_op; + struct platform_device *qec_op; - qec_op = to_of_device(parent); + qec_op = to_platform_device(parent); unregister_netdev(net_dev); diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index 8840bc0b840b..8db88945b889 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h @@ -329,8 +329,8 @@ struct bigmac { unsigned int timer_ticks; struct net_device_stats enet_stats; - struct of_device *qec_op; - struct of_device *bigmac_op; + struct platform_device *qec_op; + struct platform_device *bigmac_op; struct net_device *dev; }; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index eec443f64079..bd0df1c14955 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1591,7 +1591,7 @@ static int happy_meal_init(struct happy_meal *hp) */ #ifdef CONFIG_SBUS if ((hp->happy_flags & HFLAG_PCI) == 0) { - struct of_device *op = hp->happy_dev; + struct platform_device *op = hp->happy_dev; if (sbus_can_dma_64bit()) { sbus_set_sbus64(&op->dev, hp->happy_bursts); @@ -2480,7 +2480,7 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info #ifdef CONFIG_SBUS else { const struct linux_prom_registers *regs; - struct of_device *op = hp->happy_dev; + struct platform_device *op = hp->happy_dev; regs = of_get_property(op->dev.of_node, "regs", NULL); if (regs) sprintf(info->bus_info, "SBUS:%d", @@ -2515,13 +2515,13 @@ static int hme_version_printed; * * Return NULL on failure. */ -static struct quattro * __devinit quattro_sbus_find(struct of_device *child) +static struct quattro * __devinit quattro_sbus_find(struct platform_device *child) { struct device *parent = child->dev.parent; - struct of_device *op; + struct platform_device *op; struct quattro *qp; - op = to_of_device(parent); + op = to_platform_device(parent); qp = dev_get_drvdata(&op->dev); if (qp) return qp; @@ -2551,7 +2551,7 @@ static int __init quattro_sbus_register_irqs(void) struct quattro *qp; for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { - struct of_device *op = qp->quattro_dev; + struct platform_device *op = qp->quattro_dev; int err, qfe_slot, skip = 0; for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { @@ -2580,7 +2580,7 @@ static void quattro_sbus_free_irqs(void) struct quattro *qp; for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { - struct of_device *op = qp->quattro_dev; + struct platform_device *op = qp->quattro_dev; int qfe_slot, skip = 0; for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { @@ -2639,7 +2639,7 @@ static const struct net_device_ops hme_netdev_ops = { }; #ifdef CONFIG_SBUS -static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) +static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe) { struct device_node *dp = op->dev.of_node, *sbus_dp; struct quattro *qp = NULL; @@ -2648,7 +2648,7 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) int i, qfe_slot = -1; int err = -ENODEV; - sbus_dp = to_of_device(op->dev.parent)->dev.of_node; + sbus_dp = op->dev.parent->of_node; /* We can match PCI devices too, do not accept those here. */ if (strcmp(sbus_dp->name, "sbus")) @@ -3235,7 +3235,7 @@ static void happy_meal_pci_exit(void) #endif #ifdef CONFIG_SBUS -static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit hme_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; const char *model = of_get_property(dp, "model", NULL); @@ -3247,7 +3247,7 @@ static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device return happy_meal_sbus_probe_one(op, is_qfe); } -static int __devexit hme_sbus_remove(struct of_device *op) +static int __devexit hme_sbus_remove(struct platform_device *op) { struct happy_meal *hp = dev_get_drvdata(&op->dev); struct net_device *net_dev = hp->dev; diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index efd2ca0fcad3..756b5bf3aa89 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h @@ -407,7 +407,7 @@ struct happy_meal { void (*write_rxd)(struct happy_meal_rxd *, u32, u32); #endif - /* This is either an of_device or a pci_dev. */ + /* This is either an platform_device or a pci_dev. */ void *happy_dev; struct device *dma_dev; diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index ee364fa75634..8dcb858f2168 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -250,7 +250,7 @@ struct lance_private { int rx_new, tx_new; int rx_old, tx_old; - struct of_device *ledma; /* If set this points to ledma */ + struct platform_device *ledma; /* If set this points to ledma */ char tpe; /* cable-selection is TPE */ char auto_select; /* cable-selection by carrier */ char burst_sizes; /* ledma SBus burst sizes */ @@ -265,8 +265,8 @@ struct lance_private { char *name; dma_addr_t init_block_dvma; struct net_device *dev; /* Backpointer */ - struct of_device *op; - struct of_device *lebuffer; + struct platform_device *op; + struct platform_device *lebuffer; struct timer_list multicast_timer; }; @@ -1272,7 +1272,7 @@ static void lance_free_hwresources(struct lance_private *lp) if (lp->lregs) of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE); if (lp->dregs) { - struct of_device *ledma = lp->ledma; + struct platform_device *ledma = lp->ledma; of_iounmap(&ledma->resource[0], lp->dregs, resource_size(&ledma->resource[0])); @@ -1319,9 +1319,9 @@ static const struct net_device_ops sparc_lance_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit sparc_lance_probe_one(struct of_device *op, - struct of_device *ledma, - struct of_device *lebuffer) +static int __devinit sparc_lance_probe_one(struct platform_device *op, + struct platform_device *ledma, + struct platform_device *lebuffer) { struct device_node *dp = op->dev.of_node; static unsigned version_printed; @@ -1503,9 +1503,9 @@ fail: return -ENODEV; } -static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit sunlance_sbus_probe(struct platform_device *op, const struct of_device_id *match) { - struct of_device *parent = to_of_device(op->dev.parent); + struct platform_device *parent = to_platform_device(op->dev.parent); struct device_node *parent_dp = parent->dev.of_node; int err; @@ -1519,7 +1519,7 @@ static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_d return err; } -static int __devexit sunlance_sbus_remove(struct of_device *op) +static int __devexit sunlance_sbus_remove(struct platform_device *op) { struct lance_private *lp = dev_get_drvdata(&op->dev); struct net_device *net_dev = lp->dev; diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 5f84a5dadedd..72e65d4666ef 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -689,7 +689,7 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { const struct linux_prom_registers *regs; struct sunqe *qep = netdev_priv(dev); - struct of_device *op; + struct platform_device *op; strcpy(info->driver, "sunqe"); strcpy(info->version, "3.0"); @@ -720,7 +720,7 @@ static const struct ethtool_ops qe_ethtool_ops = { }; /* This is only called once at boot time for each card probed. */ -static void qec_init_once(struct sunqec *qecp, struct of_device *op) +static void qec_init_once(struct sunqec *qecp, struct platform_device *op) { u8 bsizes = qecp->qec_bursts; @@ -770,9 +770,9 @@ static u8 __devinit qec_get_burst(struct device_node *dp) return bsizes; } -static struct sunqec * __devinit get_qec(struct of_device *child) +static struct sunqec * __devinit get_qec(struct platform_device *child) { - struct of_device *op = to_of_device(child->dev.parent); + struct platform_device *op = to_platform_device(child->dev.parent); struct sunqec *qecp; qecp = dev_get_drvdata(&op->dev); @@ -836,7 +836,7 @@ static const struct net_device_ops qec_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit qec_ether_init(struct of_device *op) +static int __devinit qec_ether_init(struct platform_device *op) { static unsigned version_printed; struct net_device *dev; @@ -941,12 +941,12 @@ fail: return res; } -static int __devinit qec_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit qec_sbus_probe(struct platform_device *op, const struct of_device_id *match) { return qec_ether_init(op); } -static int __devexit qec_sbus_remove(struct of_device *op) +static int __devexit qec_sbus_remove(struct platform_device *op) { struct sunqe *qp = dev_get_drvdata(&op->dev); struct net_device *net_dev = qp->dev; @@ -997,7 +997,7 @@ static void __exit qec_exit(void) while (root_qec_dev) { struct sunqec *next = root_qec_dev->next_module; - struct of_device *op = root_qec_dev->op; + struct platform_device *op = root_qec_dev->op; free_irq(op->archdata.irqs[0], (void *) root_qec_dev); of_iounmap(&op->resource[0], root_qec_dev->gregs, diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h index 5813a7b2faa5..581781b6b2fa 100644 --- a/drivers/net/sunqe.h +++ b/drivers/net/sunqe.h @@ -314,7 +314,7 @@ struct sunqec { void __iomem *gregs; /* QEC Global Registers */ struct sunqe *qes[4]; /* Each child MACE */ unsigned int qec_bursts; /* Support burst sizes */ - struct of_device *op; /* QEC's OF device */ + struct platform_device *op; /* QEC's OF device */ struct sunqec *next_module; /* List of all QECs in system */ }; @@ -342,7 +342,7 @@ struct sunqe { __u32 buffers_dvma; /* DVMA visible address. */ struct sunqec *parent; u8 mconfig; /* Base MACE mconfig value */ - struct of_device *op; /* QE's OF device struct */ + struct platform_device *op; /* QE's OF device struct */ struct net_device *dev; /* QE's netdevice struct */ int channel; /* Who am I? */ }; diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8d532f9b50d0..a4c3f5708246 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3601,7 +3601,7 @@ static void ucc_geth_timeout(struct net_device *dev) #ifdef CONFIG_PM -static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) +static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state) { struct net_device *ndev = dev_get_drvdata(&ofdev->dev); struct ucc_geth_private *ugeth = netdev_priv(ndev); @@ -3629,7 +3629,7 @@ static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) return 0; } -static int ucc_geth_resume(struct of_device *ofdev) +static int ucc_geth_resume(struct platform_device *ofdev) { struct net_device *ndev = dev_get_drvdata(&ofdev->dev); struct ucc_geth_private *ugeth = netdev_priv(ndev); @@ -3732,7 +3732,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = { #endif }; -static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) +static int ucc_geth_probe(struct platform_device* ofdev, const struct of_device_id *match) { struct device *device = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; @@ -3954,7 +3954,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma return 0; } -static int ucc_geth_remove(struct of_device* ofdev) +static int ucc_geth_remove(struct platform_device* ofdev) { struct device *device = &ofdev->dev; struct net_device *dev = dev_get_drvdata(device); diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index b2c2f391b29d..ecbbb688eba0 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -1086,7 +1086,7 @@ static void xemaclite_remove_ndev(struct net_device *ndev) * * Return: Value of the parameter if the parameter is found, or 0 otherwise */ -static bool get_bool(struct of_device *ofdev, const char *s) +static bool get_bool(struct platform_device *ofdev, const char *s) { u32 *p = (u32 *)of_get_property(ofdev->dev.of_node, s, NULL); @@ -1115,7 +1115,7 @@ static struct net_device_ops xemaclite_netdev_ops; * Return: 0, if the driver is bound to the Emaclite device, or * a negative error if there is failure. */ -static int __devinit xemaclite_of_probe(struct of_device *ofdev, +static int __devinit xemaclite_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct resource r_irq; /* Interrupt resources */ @@ -1240,7 +1240,7 @@ error2: * * Return: 0, always. */ -static int __devexit xemaclite_of_remove(struct of_device *of_dev) +static int __devexit xemaclite_of_remove(struct platform_device *of_dev) { struct device *dev = &of_dev->dev; struct net_device *ndev = dev_get_drvdata(dev); diff --git a/drivers/of/device.c b/drivers/of/device.c index 0d8a0644f540..92de0eb74aea 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -14,7 +14,7 @@ * @ids: array of of device match structures to search in * @dev: the of device structure to match against * - * Used by a driver to check whether an of_device present in the + * Used by a driver to check whether an platform_device present in the * system is in its list of supported devices. */ const struct of_device_id *of_match_device(const struct of_device_id *matches, diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 210a6441a066..55ba118f1cf1 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -286,7 +286,7 @@ static struct parport_operations parport_sunbpp_ops = .owner = THIS_MODULE, }; -static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit bpp_probe(struct platform_device *op, const struct of_device_id *match) { struct parport_operations *ops; struct bpp_regs __iomem *regs; @@ -351,7 +351,7 @@ out_unmap: return err; } -static int __devexit bpp_remove(struct of_device *op) +static int __devexit bpp_remove(struct platform_device *op) { struct parport *p = dev_get_drvdata(&op->dev); struct parport_operations *ops = p->ops; diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c index f94d8281cfb0..546d3024b6f0 100644 --- a/drivers/pcmcia/electra_cf.c +++ b/drivers/pcmcia/electra_cf.c @@ -44,7 +44,7 @@ struct electra_cf_socket { unsigned present:1; unsigned active:1; - struct of_device *ofdev; + struct platform_device *ofdev; unsigned long mem_phys; void __iomem * mem_base; unsigned long mem_size; @@ -181,7 +181,7 @@ static struct pccard_operations electra_cf_ops = { .set_mem_map = electra_cf_set_mem_map, }; -static int __devinit electra_cf_probe(struct of_device *ofdev, +static int __devinit electra_cf_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device *device = &ofdev->dev; @@ -325,7 +325,7 @@ fail1: } -static int __devexit electra_cf_remove(struct of_device *ofdev) +static int __devexit electra_cf_remove(struct platform_device *ofdev) { struct device *device = &ofdev->dev; struct electra_cf_socket *cf; diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 25e5e30a18af..84a70a59ef95 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c @@ -1150,7 +1150,7 @@ static struct pccard_operations m8xx_services = { .set_mem_map = m8xx_set_mem_map, }; -static int __init m8xx_probe(struct of_device *ofdev, +static int __init m8xx_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct pcmcia_win *w; @@ -1250,7 +1250,7 @@ static int __init m8xx_probe(struct of_device *ofdev, return 0; } -static int m8xx_remove(struct of_device *ofdev) +static int m8xx_remove(struct platform_device *ofdev) { u32 m, i; struct pcmcia_win *w; diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index db5d8c416d26..dfcdf0901d21 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -268,7 +268,7 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { .update_irq_enable = mpc5121_rtc_update_irq_enable, }; -static int __devinit mpc5121_rtc_probe(struct of_device *op, +static int __devinit mpc5121_rtc_probe(struct platform_device *op, const struct of_device_id *match) { struct mpc5121_rtc_data *rtc; @@ -338,7 +338,7 @@ out_free: return err; } -static int __devexit mpc5121_rtc_remove(struct of_device *op) +static int __devexit mpc5121_rtc_remove(struct platform_device *op) { struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); struct mpc5121_rtc_regs __iomem *regs = rtc->regs; diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 103fdf6b0b89..160e7510aca6 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -443,7 +443,7 @@ static int kenvctrld(void *__unused) return 0; } -static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, +static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op, int temp_idx) { struct bbc_cpu_temperature *tp; @@ -488,7 +488,7 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, tp->fan_todo[FAN_CPU] = FAN_SAME; } -static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op, +static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op, int fan_idx) { struct bbc_fan_control *fp; @@ -559,7 +559,7 @@ static void destroy_all_fans(struct bbc_i2c_bus *bp) int bbc_envctrl_init(struct bbc_i2c_bus *bp) { - struct of_device *op; + struct platform_device *op; int temp_index = 0; int fan_index = 0; int devidx = 0; diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 3e89c313e98d..614a5e114a19 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -51,7 +51,7 @@ * The second controller also connects to the smartcard reader, if present. */ -static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val) +static void set_device_claimage(struct bbc_i2c_bus *bp, struct platform_device *op, int val) { int i; @@ -66,9 +66,9 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, in #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) -struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) +struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) { - struct of_device *op = NULL; + struct platform_device *op = NULL; int curidx = 0, i; for (i = 0; i < NUM_CHILDREN; i++) { @@ -86,7 +86,7 @@ out: return NULL; } -struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op) +struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *op) { struct bbc_i2c_client *client; const u32 *reg; @@ -114,7 +114,7 @@ struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device * void bbc_i2c_detach(struct bbc_i2c_client *client) { struct bbc_i2c_bus *bp = client->bp; - struct of_device *op = client->op; + struct platform_device *op = client->op; release_device(bp, op); kfree(client); @@ -297,7 +297,7 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp) writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); } -static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index) +static struct bbc_i2c_bus * __init attach_one_i2c(struct platform_device *op, int index) { struct bbc_i2c_bus *bp; struct device_node *dp; @@ -330,7 +330,7 @@ static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int inde for (dp = op->dev.of_node->child; dp && entry < 8; dp = dp->sibling, entry++) { - struct of_device *child_op; + struct platform_device *child_op; child_op = of_find_device_by_node(dp); bp->devs[entry].device = child_op; @@ -361,7 +361,7 @@ fail: extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); -static int __devinit bbc_i2c_probe(struct of_device *op, +static int __devinit bbc_i2c_probe(struct platform_device *op, const struct of_device_id *match) { struct bbc_i2c_bus *bp; @@ -386,7 +386,7 @@ static int __devinit bbc_i2c_probe(struct of_device *op, return err; } -static int __devexit bbc_i2c_remove(struct of_device *op) +static int __devexit bbc_i2c_remove(struct platform_device *op) { struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h index 83c4811b7b5e..4b4531066e75 100644 --- a/drivers/sbus/char/bbc_i2c.h +++ b/drivers/sbus/char/bbc_i2c.h @@ -7,7 +7,7 @@ struct bbc_i2c_client { struct bbc_i2c_bus *bp; - struct of_device *op; + struct platform_device *op; int bus; int address; }; @@ -64,16 +64,16 @@ struct bbc_i2c_bus { struct list_head temps; struct list_head fans; - struct of_device *op; + struct platform_device *op; struct { - struct of_device *device; + struct platform_device *device; int client_claimed; } devs[NUM_CHILDREN]; }; /* Probing and attachment. */ -extern struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); -extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *); +extern struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); +extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *); extern void bbc_i2c_detach(struct bbc_i2c_client *); /* Register read/write. NOTE: Blocking! */ diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 47db97583ea7..1690e53fb84a 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -170,7 +170,7 @@ static struct miscdevice d7s_miscdev = { .fops = &d7s_fops }; -static int __devinit d7s_probe(struct of_device *op, +static int __devinit d7s_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *opts; @@ -236,7 +236,7 @@ out_free: goto out; } -static int __devexit d7s_remove(struct of_device *op) +static int __devexit d7s_remove(struct platform_device *op) { struct d7s *p = dev_get_drvdata(&op->dev); u8 regs = readb(p->regs); diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 3c27f45e2b6d..078e5f4520ef 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1027,7 +1027,7 @@ static int kenvctrld(void *__unused) return 0; } -static int __devinit envctrl_probe(struct of_device *op, +static int __devinit envctrl_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp; @@ -1104,7 +1104,7 @@ out_iounmap: return err; } -static int __devexit envctrl_remove(struct of_device *op) +static int __devexit envctrl_remove(struct platform_device *op) { int index; diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 8bb31c584b64..2b4b4b613c48 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -160,7 +160,7 @@ static const struct file_operations flash_fops = { static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; -static int __devinit flash_probe(struct of_device *op, +static int __devinit flash_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -192,7 +192,7 @@ static int __devinit flash_probe(struct of_device *op, return misc_register(&flash_dev); } -static int __devexit flash_remove(struct of_device *op) +static int __devexit flash_remove(struct platform_device *op) { misc_deregister(&flash_dev); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 41eb6725ff5f..1b345be5cc02 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -348,7 +348,7 @@ static void uctrl_get_external_status(struct uctrl_driver *driver) } -static int __devinit uctrl_probe(struct of_device *op, +static int __devinit uctrl_probe(struct platform_device *op, const struct of_device_id *match) { struct uctrl_driver *p; @@ -404,7 +404,7 @@ out_free: goto out; } -static int __devexit uctrl_remove(struct of_device *op) +static int __devexit uctrl_remove(struct platform_device *op) { struct uctrl_driver *p = dev_get_drvdata(&op->dev); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 53d7ed0dc169..f8c561cf751e 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -704,7 +704,7 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti) static int __devinit qpti_map_regs(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; qpti->qregs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), @@ -727,7 +727,7 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti) static int __devinit qpti_register_irq(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; @@ -752,7 +752,7 @@ fail: static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; struct device_node *dp; dp = op->dev.of_node; @@ -773,7 +773,7 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) static void qpti_get_bursts(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; u8 bursts, bmask; bursts = of_getintprop_default(op->dev.of_node, "burst-sizes", 0xff); @@ -806,7 +806,7 @@ static void qpti_get_clock(struct qlogicpti *qpti) */ static int __devinit qpti_map_queues(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) qpti->res_cpu = dma_alloc_coherent(&op->dev, @@ -1290,7 +1290,7 @@ static struct scsi_host_template qpti_template = { .use_clustering = ENABLE_CLUSTERING, }; -static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit qpti_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct scsi_host_template *tpnt = match->data; struct device_node *dp = op->dev.of_node; @@ -1401,7 +1401,7 @@ fail_unlink: return -ENODEV; } -static int __devexit qpti_sbus_remove(struct of_device *op) +static int __devexit qpti_sbus_remove(struct platform_device *op) { struct qlogicpti *qpti = dev_get_drvdata(&op->dev); diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index e3c74d1ee2db..4377e87ee79c 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h @@ -342,7 +342,7 @@ struct qlogicpti { u_int req_in_ptr; /* index of next request slot */ u_int res_out_ptr; /* index of next result slot */ long send_marker; /* must we send a marker? */ - struct of_device *op; + struct platform_device *op; unsigned long __pad; int cmd_count[MAX_TARGETS]; diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index 89ba6fe02f80..193b37ba1834 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c @@ -44,7 +44,7 @@ enum dvma_rev { }; static int __devinit esp_sbus_setup_dma(struct esp *esp, - struct of_device *dma_of) + struct platform_device *dma_of) { esp->dma = dma_of; @@ -81,7 +81,7 @@ static int __devinit esp_sbus_setup_dma(struct esp *esp, static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct resource *res; /* On HME, two reg sets exist, first is DVMA, @@ -101,7 +101,7 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) static int __devinit esp_sbus_map_command_block(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; esp->command_block = dma_alloc_coherent(&op->dev, 16, &esp->command_block_dma, @@ -114,15 +114,15 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp) static int __devinit esp_sbus_register_irq(struct esp *esp) { struct Scsi_Host *host = esp->host; - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; host->irq = op->archdata.irqs[0]; return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); } -static void __devinit esp_get_scsi_id(struct esp *esp, struct of_device *espdma) +static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; dp = op->dev.of_node; @@ -144,7 +144,7 @@ done: static void __devinit esp_get_differential(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; dp = op->dev.of_node; @@ -156,7 +156,7 @@ static void __devinit esp_get_differential(struct esp *esp) static void __devinit esp_get_clock_params(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *bus_dp, *dp; int fmhz; @@ -170,10 +170,10 @@ static void __devinit esp_get_clock_params(struct esp *esp) esp->cfreq = fmhz; } -static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) +static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of) { struct device_node *dma_dp = dma_of->dev.of_node; - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; u8 bursts, val; @@ -195,7 +195,7 @@ static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) esp->bursts = bursts; } -static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma) +static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma) { esp_get_scsi_id(esp, espdma); esp_get_differential(esp); @@ -216,7 +216,7 @@ static u8 sbus_esp_read8(struct esp *esp, unsigned long reg) static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, size_t sz, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; return dma_map_single(&op->dev, buf, sz, dir); } @@ -224,7 +224,7 @@ static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; return dma_map_sg(&op->dev, sg, num_sg, dir); } @@ -232,7 +232,7 @@ static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, size_t sz, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; dma_unmap_single(&op->dev, addr, sz, dir); } @@ -240,7 +240,7 @@ static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; dma_unmap_sg(&op->dev, sg, num_sg, dir); } @@ -256,7 +256,7 @@ static void sbus_esp_reset_dma(struct esp *esp) { int can_do_burst16, can_do_burst32, can_do_burst64; int can_do_sbus64, lim; - struct of_device *op; + struct platform_device *op; u32 val; can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; @@ -487,8 +487,8 @@ static const struct esp_driver_ops sbus_esp_ops = { .dma_error = sbus_esp_dma_error, }; -static int __devinit esp_sbus_probe_one(struct of_device *op, - struct of_device *espdma, +static int __devinit esp_sbus_probe_one(struct platform_device *op, + struct platform_device *espdma, int hme) { struct scsi_host_template *tpnt = &scsi_esp_template; @@ -562,11 +562,11 @@ fail: return err; } -static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit esp_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dma_node = NULL; struct device_node *dp = op->dev.of_node; - struct of_device *dma_of = NULL; + struct platform_device *dma_of = NULL; int hme = 0; if (dp->parent && @@ -585,10 +585,10 @@ static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device return esp_sbus_probe_one(op, dma_of, hme); } -static int __devexit esp_sbus_remove(struct of_device *op) +static int __devexit esp_sbus_remove(struct platform_device *op) { struct esp *esp = dev_get_drvdata(&op->dev); - struct of_device *dma_of = esp->dma; + struct platform_device *dma_of = esp->dma; unsigned int irq = esp->host->irq; bool is_hme; u32 val; diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c index 0099b8692b60..cc01c650a144 100644 --- a/drivers/serial/apbuart.c +++ b/drivers/serial/apbuart.c @@ -551,7 +551,7 @@ static struct uart_driver grlib_apbuart_driver = { /* OF Platform Driver */ /* ======================================================================== */ -static int __devinit apbuart_probe(struct of_device *op, +static int __devinit apbuart_probe(struct platform_device *op, const struct of_device_id *match) { int i = -1; diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 6016179db533..f2b8adcc6c92 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -1340,7 +1340,7 @@ static struct uart_driver cpm_reg = { static int probe_index; -static int __devinit cpm_uart_probe(struct of_device *ofdev, +static int __devinit cpm_uart_probe(struct platform_device *ofdev, const struct of_device_id *match) { int index = probe_index++; @@ -1364,7 +1364,7 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev, return uart_add_one_port(&cpm_reg, &pinfo->port); } -static int __devexit cpm_uart_remove(struct of_device *ofdev) +static int __devexit cpm_uart_remove(struct platform_device *ofdev) { struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); return uart_remove_one_port(&cpm_reg, &pinfo->port); diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 1a88b363005c..8dedb266f143 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -1298,7 +1298,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { }; static int __devinit -mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) +mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *match) { int idx = -1; unsigned int uartclk; @@ -1369,7 +1369,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) } static int -mpc52xx_uart_of_remove(struct of_device *op) +mpc52xx_uart_of_remove(struct platform_device *op) { struct uart_port *port = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); @@ -1382,7 +1382,7 @@ mpc52xx_uart_of_remove(struct of_device *op) #ifdef CONFIG_PM static int -mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) +mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) { struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); @@ -1393,7 +1393,7 @@ mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) } static int -mpc52xx_uart_of_resume(struct of_device *op) +mpc52xx_uart_of_resume(struct platform_device *op) { struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c index e65b0d9202a5..de173671e3d0 100644 --- a/drivers/serial/nwpserial.c +++ b/drivers/serial/nwpserial.c @@ -344,7 +344,7 @@ int nwpserial_register_port(struct uart_port *port) mutex_lock(&nwpserial_mutex); - dn = to_of_device(port->dev)->dev.of_node; + dn = port->dev->of_node; if (dn == NULL) goto out; diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c index a48d9080f552..659a695bdad6 100644 --- a/drivers/serial/of_serial.c +++ b/drivers/serial/of_serial.c @@ -27,7 +27,7 @@ struct of_serial_info { /* * Fill a struct uart_port for a given device node */ -static int __devinit of_platform_serial_setup(struct of_device *ofdev, +static int __devinit of_platform_serial_setup(struct platform_device *ofdev, int type, struct uart_port *port) { struct resource resource; @@ -80,7 +80,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, /* * Try to register a serial port */ -static int __devinit of_platform_serial_probe(struct of_device *ofdev, +static int __devinit of_platform_serial_probe(struct platform_device *ofdev, const struct of_device_id *id) { struct of_serial_info *info; @@ -134,7 +134,7 @@ out: /* * Release a line */ -static int of_platform_serial_remove(struct of_device *ofdev) +static int of_platform_serial_remove(struct platform_device *ofdev) { struct of_serial_info *info = dev_get_drvdata(&ofdev->dev); switch (info->type) { diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index a779e22d213e..c9014868297d 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -519,7 +519,7 @@ static struct console sunhv_console = { .data = &sunhv_reg, }; -static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit hv_probe(struct platform_device *op, const struct of_device_id *match) { struct uart_port *port; unsigned long minor; @@ -598,7 +598,7 @@ out_free_port: return err; } -static int __devexit hv_remove(struct of_device *dev) +static int __devexit hv_remove(struct platform_device *dev) { struct uart_port *port = dev_get_drvdata(&dev->dev); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 9845fb1cfb1f..5b246b18f42f 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -883,7 +883,7 @@ static int sunsab_console_setup(struct console *con, char *options) printk("Console: ttyS%d (SAB82532)\n", (sunsab_reg.minor - 64) + con->index); - sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node); + sunserial_console_termios(con, up->port.dev->of_node); switch (con->cflag & CBAUD) { case B150: baud = 150; break; @@ -954,7 +954,7 @@ static inline struct console *SUNSAB_CONSOLE(void) #endif static int __devinit sunsab_init_one(struct uart_sunsab_port *up, - struct of_device *op, + struct platform_device *op, unsigned long offset, int line) { @@ -1006,7 +1006,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up, return 0; } -static int __devinit sab_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit sab_probe(struct platform_device *op, const struct of_device_id *match) { static int inst; struct uart_sunsab_port *up; @@ -1062,7 +1062,7 @@ out: return err; } -static int __devexit sab_remove(struct of_device *op) +static int __devexit sab_remove(struct platform_device *op) { struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 3cdf74822db5..551ebfe3ccbb 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1200,7 +1200,7 @@ static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up) return -ENODEV; printk("%s: %s port at %llx, irq %u\n", - to_of_device(up->port.dev)->dev.of_node->full_name, + up->port.dev->of_node->full_name, (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", (unsigned long long) up->port.mapbase, up->port.irq); @@ -1352,7 +1352,7 @@ static int __init sunsu_console_setup(struct console *co, char *options) spin_lock_init(&port->lock); /* Get firmware console settings. */ - sunserial_console_termios(co, to_of_device(port->dev)->dev.of_node); + sunserial_console_termios(co, port->dev->of_node); memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = co->cflag; @@ -1406,7 +1406,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp) return SU_PORT_PORT; } -static int __devinit su_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit su_probe(struct platform_device *op, const struct of_device_id *match) { static int inst; struct device_node *dp = op->dev.of_node; @@ -1497,7 +1497,7 @@ out_unmap: return err; } -static int __devexit su_remove(struct of_device *op) +static int __devexit su_remove(struct platform_device *op) { struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); bool kbdms = false; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index d1e6bcb59546..c1967ac1c07f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1230,7 +1230,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) (sunzilog_reg.minor - 64) + con->index, con->index); /* Get firmware console settings. */ - sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node); + sunserial_console_termios(con, up->port.dev->of_node); /* Firmware console speed is limited to 150-->38400 baud so * this hackish cflag thing is OK. @@ -1399,7 +1399,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) static int zilog_irq = -1; -static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit zs_probe(struct platform_device *op, const struct of_device_id *match) { static int kbm_inst, uart_inst; int inst; @@ -1516,7 +1516,7 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up) uart_remove_one_port(&sunzilog_reg, &up->port); } -static int __devexit zs_remove(struct of_device *op) +static int __devexit zs_remove(struct platform_device *op) { struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); struct zilog_layout __iomem *regs; diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index caf085d3a76a..9b03d7b3e456 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -584,7 +584,7 @@ static struct platform_driver ulite_platform_driver = { */ #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) static int __devinit -ulite_of_probe(struct of_device *op, const struct of_device_id *match) +ulite_of_probe(struct platform_device *op, const struct of_device_id *match) { struct resource res; const unsigned int *id; @@ -605,7 +605,7 @@ ulite_of_probe(struct of_device *op, const struct of_device_id *match) return ulite_assign(&op->dev, id ? *id : -1, res.start, irq); } -static int __devexit ulite_of_remove(struct of_device *op) +static int __devexit ulite_of_remove(struct platform_device *op) { return ulite_release(&op->dev); } diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 907b06f5c447..3f4848e2174a 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c @@ -1194,7 +1194,7 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) release_firmware(fw); } -static int ucc_uart_probe(struct of_device *ofdev, +static int ucc_uart_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -1462,7 +1462,7 @@ static int ucc_uart_probe(struct of_device *ofdev, return 0; } -static int ucc_uart_remove(struct of_device *ofdev) +static int ucc_uart_remove(struct platform_device *ofdev) { struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c index 10baac3f8ea5..cddbfceb324f 100644 --- a/drivers/spi/mpc512x_psc_spi.c +++ b/drivers/spi/mpc512x_psc_spi.c @@ -507,7 +507,7 @@ static int __exit mpc512x_psc_spi_do_remove(struct device *dev) return 0; } -static int __init mpc512x_psc_spi_of_probe(struct of_device *op, +static int __init mpc512x_psc_spi_of_probe(struct platform_device *op, const struct of_device_id *match) { const u32 *regaddr_p; @@ -539,7 +539,7 @@ static int __init mpc512x_psc_spi_of_probe(struct of_device *op, irq_of_parse_and_map(op->dev.of_node, 0), id); } -static int __exit mpc512x_psc_spi_of_remove(struct of_device *op) +static int __exit mpc512x_psc_spi_of_remove(struct platform_device *op) { return mpc512x_psc_spi_do_remove(&op->dev); } diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 66d170147dcc..983fbbfce76e 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -465,7 +465,7 @@ static int __exit mpc52xx_psc_spi_do_remove(struct device *dev) return 0; } -static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, +static int __init mpc52xx_psc_spi_of_probe(struct platform_device *op, const struct of_device_id *match) { const u32 *regaddr_p; @@ -495,7 +495,7 @@ static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, irq_of_parse_and_map(op->dev.of_node, 0), id); } -static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) +static int __exit mpc52xx_psc_spi_of_remove(struct platform_device *op) { return mpc52xx_psc_spi_do_remove(&op->dev); } diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c index 56136ff00e01..ec9f0b1bf864 100644 --- a/drivers/spi/mpc52xx_spi.c +++ b/drivers/spi/mpc52xx_spi.c @@ -390,7 +390,7 @@ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m) /* * OF Platform Bus Binding */ -static int __devinit mpc52xx_spi_probe(struct of_device *op, +static int __devinit mpc52xx_spi_probe(struct platform_device *op, const struct of_device_id *match) { struct spi_master *master; @@ -530,7 +530,7 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, return rc; } -static int __devexit mpc52xx_spi_remove(struct of_device *op) +static int __devexit mpc52xx_spi_remove(struct platform_device *op) { struct spi_master *master = dev_get_drvdata(&op->dev); struct mpc52xx_spi *ms = spi_master_get_devdata(master); diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index aad9ae1b9c69..d31b57f7baaf 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -1236,7 +1236,7 @@ static int of_mpc8xxx_spi_free_chipselects(struct device *dev) return 0; } -static int __devinit of_mpc8xxx_spi_probe(struct of_device *ofdev, +static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev, const struct of_device_id *ofid) { struct device *dev = &ofdev->dev; @@ -1308,7 +1308,7 @@ err_clk: return ret; } -static int __devexit of_mpc8xxx_spi_remove(struct of_device *ofdev) +static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev) { int ret; diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c index 0f5fa7e2a550..80e172d3e72a 100644 --- a/drivers/spi/spi_ppc4xx.c +++ b/drivers/spi/spi_ppc4xx.c @@ -388,9 +388,9 @@ static void free_gpios(struct ppc4xx_spi *hw) } /* - * of_device layer stuff... + * platform_device layer stuff... */ -static int __init spi_ppc4xx_of_probe(struct of_device *op, +static int __init spi_ppc4xx_of_probe(struct platform_device *op, const struct of_device_id *match) { struct ppc4xx_spi *hw; @@ -565,7 +565,7 @@ free_master: return ret; } -static int __exit spi_ppc4xx_of_remove(struct of_device *op) +static int __exit spi_ppc4xx_of_remove(struct platform_device *op) { struct spi_master *master = dev_get_drvdata(&op->dev); struct ppc4xx_spi *hw = spi_master_get_devdata(master); diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c index f53d3f6b9f61..b66c2dbf20a5 100644 --- a/drivers/spi/xilinx_spi_of.c +++ b/drivers/spi/xilinx_spi_of.c @@ -38,7 +38,7 @@ #include "xilinx_spi.h" -static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, +static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct spi_master *master; @@ -84,7 +84,7 @@ static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, return 0; } -static int __devexit xilinx_spi_remove(struct of_device *ofdev) +static int __devexit xilinx_spi_remove(struct platform_device *ofdev) { xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); dev_set_drvdata(&ofdev->dev, 0); @@ -93,7 +93,7 @@ static int __devexit xilinx_spi_remove(struct of_device *ofdev) return 0; } -static int __exit xilinx_spi_of_remove(struct of_device *op) +static int __exit xilinx_spi_of_remove(struct platform_device *op) { return xilinx_spi_remove(op); } diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 9648b75f0283..a5ea2c1d8c93 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2398,7 +2398,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) EXPORT_SYMBOL(usb_gadget_unregister_driver); /* udc structure's alloc and setup, include ep-param alloc */ -static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev) +static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev) { struct qe_udc *udc; struct device_node *np = ofdev->dev.of_node; @@ -2523,7 +2523,7 @@ static void qe_udc_release(struct device *dev) } /* Driver probe functions */ -static int __devinit qe_udc_probe(struct of_device *ofdev, +static int __devinit qe_udc_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -2679,18 +2679,18 @@ err1: } #ifdef CONFIG_PM -static int qe_udc_suspend(struct of_device *dev, pm_message_t state) +static int qe_udc_suspend(struct platform_device *dev, pm_message_t state) { return -ENOTSUPP; } -static int qe_udc_resume(struct of_device *dev) +static int qe_udc_resume(struct platform_device *dev) { return -ENOTSUPP; } #endif -static int __devexit qe_udc_remove(struct of_device *ofdev) +static int __devexit qe_udc_remove(struct platform_device *ofdev) { struct qe_ep *ep; unsigned int size; diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 5aec92866ab3..335ee699fd85 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -106,7 +106,7 @@ ppc44x_enable_bmt(struct device_node *dn) static int __devinit -ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) +ehci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -210,7 +210,7 @@ err_rmr: } -static int ehci_hcd_ppc_of_remove(struct of_device *op) +static int ehci_hcd_ppc_of_remove(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -253,7 +253,7 @@ static int ehci_hcd_ppc_of_remove(struct of_device *op) } -static int ehci_hcd_ppc_of_shutdown(struct of_device *op) +static int ehci_hcd_ppc_of_shutdown(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 4899f451add9..6c8076ad821d 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -140,7 +140,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { /** * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller - * @op: pointer to the of_device to which the host controller bound + * @op: pointer to the platform_device bound to the host controller * @match: pointer to of_device_id structure, not used * * This function requests resources and sets up appropriate properties for the @@ -149,7 +149,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { * entry, and sets an appropriate value for hcd->has_tt. */ static int __devinit -ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match) +ehci_hcd_xilinx_of_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -242,12 +242,12 @@ err_rmr: /** * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources - * @op: pointer to of_device structure that is to be removed + * @op: pointer to platform_device structure that is to be removed * * Remove the hcd structure, and release resources that has been requested * during probe. */ -static int ehci_hcd_xilinx_of_remove(struct of_device *op) +static int ehci_hcd_xilinx_of_remove(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); @@ -266,11 +266,11 @@ static int ehci_hcd_xilinx_of_remove(struct of_device *op) /** * ehci_hcd_xilinx_of_shutdown - shutdown the hcd - * @op: pointer to of_device structure that is to be removed + * @op: pointer to platform_device structure that is to be removed * * Properly shutdown the hcd, call driver's shutdown routine. */ -static int ehci_hcd_xilinx_of_shutdown(struct of_device *op) +static int ehci_hcd_xilinx_of_shutdown(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index c7c8392a88b9..20092a27a1e8 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = { .hub_control = fhci_hub_control, }; -static int __devinit of_fhci_probe(struct of_device *ofdev, +static int __devinit of_fhci_probe(struct platform_device *ofdev, const struct of_device_id *ofid) { struct device *dev = &ofdev->dev; @@ -801,7 +801,7 @@ static int __devexit fhci_remove(struct device *dev) return 0; } -static int __devexit of_fhci_remove(struct of_device *ofdev) +static int __devexit of_fhci_remove(struct platform_device *ofdev) { return fhci_remove(&ofdev->dev); } diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index ec85d0c3cc3e..3b28dbfca058 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -27,7 +27,7 @@ #endif #ifdef CONFIG_PPC_OF -static int of_isp1760_probe(struct of_device *dev, +static int of_isp1760_probe(struct platform_device *dev, const struct of_device_id *match) { struct usb_hcd *hcd; @@ -95,7 +95,7 @@ release_reg: return ret; } -static int of_isp1760_remove(struct of_device *dev) +static int of_isp1760_remove(struct platform_device *dev) { struct usb_hcd *hcd = dev_get_drvdata(&dev->dev); diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index df165917412a..b2c2dbf08766 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { static int __devinit -ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) +ohci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -183,7 +183,7 @@ err_rmr: return rv; } -static int ohci_hcd_ppc_of_remove(struct of_device *op) +static int ohci_hcd_ppc_of_remove(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); @@ -201,7 +201,7 @@ static int ohci_hcd_ppc_of_remove(struct of_device *op) return 0; } -static int ohci_hcd_ppc_of_shutdown(struct of_device *op) +static int ohci_hcd_ppc_of_shutdown(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index c7796637bafd..4dc13467281d 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par, return 0; } -static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; struct fb_info *info; @@ -350,7 +350,7 @@ out_err: return err; } -static int __devexit bw2_remove(struct of_device *op) +static int __devexit bw2_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct bw2_par *par = info->par; diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index d09fde8beb69..24249535ac86 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -446,7 +446,7 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = { { .size = 0 } }; -static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, +static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info, struct cg14_par *par) { if (par->regs) @@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, info->screen_base, info->fix.smem_len); } -static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; struct fb_info *info; @@ -570,7 +570,7 @@ out_err: return err; } -static int __devexit cg14_remove(struct of_device *op) +static int __devexit cg14_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct cg14_par *par = info->par; diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 64aa29809fb9..09c0c3c42482 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -346,7 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par) return 0; } -static int __devinit cg3_probe(struct of_device *op, +static int __devinit cg3_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -433,7 +433,7 @@ out_err: return err; } -static int __devexit cg3_remove(struct of_device *op) +static int __devexit cg3_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct cg3_par *par = info->par; diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 2389a719dcc7..2b5a97058b08 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -718,7 +718,7 @@ static void __devinit cg6_chip_init(struct fb_info *info) sbus_writel(info->var.yres - 1, &fbc->clipmaxy); } -static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, +static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info, struct cg6_par *par) { if (par->fbc) @@ -737,7 +737,7 @@ static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, info->fix.smem_len); } -static int __devinit cg6_probe(struct of_device *op, +static int __devinit cg6_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -827,7 +827,7 @@ out_err: return err; } -static int __devexit cg6_remove(struct of_device *op) +static int __devexit cg6_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct cg6_par *par = info->par; diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index f6ecfab296d3..6739b2af3bc0 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -893,7 +893,7 @@ static void ffb_init_fix(struct fb_info *info) info->fix.accel = FB_ACCEL_SUN_CREATOR; } -static int __devinit ffb_probe(struct of_device *op, +static int __devinit ffb_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -1023,7 +1023,7 @@ out_err: return err; } -static int __devexit ffb_remove(struct of_device *op) +static int __devexit ffb_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct ffb_par *par = info->par; diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index e38ad2224540..8bbbf08fa3ce 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1393,7 +1393,7 @@ static void free_irq_local(int irq) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) +static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state) { struct fsl_diu_data *machine_data; @@ -1403,7 +1403,7 @@ static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) return 0; } -static int fsl_diu_resume(struct of_device *ofdev) +static int fsl_diu_resume(struct platform_device *ofdev) { struct fsl_diu_data *machine_data; @@ -1487,7 +1487,7 @@ static ssize_t show_monitor(struct device *device, return diu_ops.show_monitor_port(machine_data->monitor_port, buf); } -static int __devinit fsl_diu_probe(struct of_device *ofdev, +static int __devinit fsl_diu_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -1667,7 +1667,7 @@ error2: } -static int fsl_diu_remove(struct of_device *ofdev) +static int fsl_diu_remove(struct platform_device *ofdev) { struct fsl_diu_data *machine_data; int i; diff --git a/drivers/video/leo.c b/drivers/video/leo.c index ad677637ffbb..b599e5e36ced 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -529,7 +529,7 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) var->transp.length = 0; } -static void leo_unmap_regs(struct of_device *op, struct fb_info *info, +static void leo_unmap_regs(struct platform_device *op, struct fb_info *info, struct leo_par *par) { if (par->lc_ss0_usr) @@ -547,7 +547,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info, of_iounmap(&op->resource[0], info->screen_base, 0x800000); } -static int __devinit leo_probe(struct of_device *op, +static int __devinit leo_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -637,7 +637,7 @@ out_err: return err; } -static int __devexit leo_remove(struct of_device *op) +static int __devexit leo_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct leo_par *par = info->par; diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c index 4e2b8cc3d460..b1c4374cf940 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfb.c @@ -550,7 +550,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par) return 0; } -static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, +static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev, const struct of_device_id *id) { struct device_node *np = ofdev->dev.of_node; @@ -669,7 +669,7 @@ fbrel: return ret; } -static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) +static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev) { struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); struct mb862xxfb_par *par = fbi->par; diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 688b055abab2..b6c3fc2db632 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no info->fix.accel = FB_ACCEL_SUN_CGTHREE; } -static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; struct fb_info *info; @@ -326,7 +326,7 @@ out_err: return err; } -static int __devexit p9100_remove(struct of_device *op) +static int __devexit p9100_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct p9100_par *par = info->par; diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 72a1f4c04732..a50e1977b316 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -533,7 +533,7 @@ static int __init platinumfb_setup(char *options) #define invalidate_cache(addr) #endif -static int __devinit platinumfb_probe(struct of_device* odev, +static int __devinit platinumfb_probe(struct platform_device* odev, const struct of_device_id *match) { struct device_node *dp = odev->dev.of_node; @@ -646,7 +646,7 @@ static int __devinit platinumfb_probe(struct of_device* odev, return rc; } -static int __devexit platinumfb_remove(struct of_device* odev) +static int __devexit platinumfb_remove(struct platform_device* odev) { struct fb_info *info = dev_get_drvdata(&odev->dev); struct fb_info_platinum *pinfo = info->par; diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c index 7288934c0d49..5dbe06af2226 100644 --- a/drivers/video/sunxvr1000.c +++ b/drivers/video/sunxvr1000.c @@ -111,7 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp) return 0; } -static int __devinit gfb_probe(struct of_device *op, +static int __devinit gfb_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -172,7 +172,7 @@ err_out: return err; } -static int __devexit gfb_remove(struct of_device *op) +static int __devexit gfb_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct gfb_info *gp = info->par; diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index f375e0db6776..77ad27955cf0 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -342,7 +342,7 @@ tcx_init_fix(struct fb_info *info, int linebytes) info->fix.accel = FB_ACCEL_SUN_TCX; } -static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, +static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info, struct tcx_par *par) { if (par->tec) @@ -362,7 +362,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, info->screen_base, info->fix.smem_len); } -static int __devinit tcx_probe(struct of_device *op, +static int __devinit tcx_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -486,7 +486,7 @@ out_err: return err; } -static int __devexit tcx_remove(struct of_device *op) +static int __devexit tcx_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct tcx_par *par = info->par; diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 29b5daacc217..0c9ce88e95e8 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -397,7 +397,7 @@ static int xilinxfb_release(struct device *dev) */ static int __devinit -xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) +xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match) { const u32 *prop; u32 *p; @@ -477,7 +477,7 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) return -ENODEV; } -static int __devexit xilinxfb_of_remove(struct of_device *op) +static int __devexit xilinxfb_of_remove(struct platform_device *op) { return xilinxfb_release(&op->dev); } diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 30a2512fd52e..566343b3c131 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -526,7 +526,7 @@ static const struct file_operations cpwd_fops = { .release = cpwd_release, }; -static int __devinit cpwd_probe(struct of_device *op, +static int __devinit cpwd_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *options; @@ -639,7 +639,7 @@ out_free: goto out; } -static int __devexit cpwd_remove(struct of_device *op) +static int __devexit cpwd_remove(struct platform_device *op) { struct cpwd *p = dev_get_drvdata(&op->dev); int i; diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 1df284f9c2a1..9c21d19043a6 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -260,7 +260,7 @@ static struct miscdevice gef_wdt_miscdev = { }; -static int __devinit gef_wdt_probe(struct of_device *dev, +static int __devinit gef_wdt_probe(struct platform_device *dev, const struct of_device_id *match) { int timeout = 10; diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 4cda64dd309c..8fa213cdb499 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -185,7 +185,7 @@ static struct miscdevice mpc8xxx_wdt_miscdev = { .fops = &mpc8xxx_wdt_fops, }; -static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, +static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev, const struct of_device_id *match) { int ret; @@ -238,7 +238,7 @@ err_unmap: return ret; } -static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev) +static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev) { mpc8xxx_wdt_pr_warn("watchdog removed"); del_timer_sync(&wdt_timer); diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 4082b4ace1fc..3faee1ae64bd 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -172,7 +172,7 @@ static struct miscdevice riowd_miscdev = { .fops = &riowd_fops }; -static int __devinit riowd_probe(struct of_device *op, +static int __devinit riowd_probe(struct platform_device *op, const struct of_device_id *match) { struct riowd *p; @@ -219,7 +219,7 @@ out: return err; } -static int __devexit riowd_remove(struct of_device *op) +static int __devexit riowd_remove(struct platform_device *op) { struct riowd *p = dev_get_drvdata(&op->dev); diff --git a/include/linux/of_device.h b/include/linux/of_device.h index 35aa44ad9f2c..835f85ecd2de 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -1,20 +1,6 @@ #ifndef _LINUX_OF_DEVICE_H #define _LINUX_OF_DEVICE_H -/* - * The of_device *was* a kind of "base class" that was a superset of - * struct device for use by devices attached to an OF node and probed - * using OF properties. However, the important bit of OF-style - * probing, namely the device node pointer, has been moved into the - * common struct device when CONFIG_OF is set to make OF-style probing - * available to all bus types. So now, just make of_device and - * platform_device equivalent so that current of_platform bus users - * can be transparently migrated over to using the platform bus. - * - * This line will go away once all references to of_device are removed - * from the kernel. - */ -#define of_device platform_device #include #include /* temporary until merge */ @@ -23,8 +9,6 @@ #include #include -#define to_of_device(d) container_of(d, struct of_device, dev) - extern const struct of_device_id *of_match_device( const struct of_device_id *matches, const struct device *dev); extern void of_device_make_bus_id(struct device *dev); diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 4e6d989c06df..a68716ad38ce 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -19,9 +19,17 @@ #include #include -/* - * An of_platform_driver driver is attached to a basic of_device on - * the "platform bus" (platform_bus_type). +/** + * of_platform_driver - Legacy of-aware driver for platform devices. + * + * An of_platform_driver driver is attached to a basic platform_device on + * ether the "platform bus" (platform_bus_type), or the ibm ebus + * (ibmebus_bus_type). + * + * of_platform_driver is being phased out when used with the platform_bus_type, + * and regular platform_drivers should be used instead. When the transition + * is complete, only ibmebus will be using this structure, and the + * platform_driver member of this structure will be removed. */ struct of_platform_driver { diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 99ca7120e269..7487eb76e034 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c @@ -59,7 +59,7 @@ static int soundbus_probe(struct device *dev) static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct soundbus_dev * soundbus_dev; - struct of_device * of; + struct platform_device * of; const char *compat; int retval = 0; int cplen, seen = 0; diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h index a0f223c13f66..adecbf36f4f6 100644 --- a/sound/aoa/soundbus/soundbus.h +++ b/sound/aoa/soundbus/soundbus.h @@ -141,7 +141,7 @@ struct soundbus_dev { struct list_head onbuslist; /* the of device it represents */ - struct of_device ofdev; + struct platform_device ofdev; /* what modules go by */ char modalias[32]; diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c index 6496e754f00a..e0980b5c2cd8 100644 --- a/sound/aoa/soundbus/sysfs.c +++ b/sound/aoa/soundbus/sysfs.c @@ -16,7 +16,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { struct soundbus_dev *sdev = to_soundbus_device(dev); - struct of_device *of = &sdev->ofdev; + struct platform_device *of = &sdev->ofdev; int length; if (*sdev->modalias) { diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 1d4e7164e80a..3dcd1469f283 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -369,7 +369,7 @@ struct snd_soc_platform mpc5200_audio_dma_platform = { }; EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform); -int mpc5200_audio_dma_create(struct of_device *op) +int mpc5200_audio_dma_create(struct platform_device *op) { phys_addr_t fifo; struct psc_dma *psc_dma; @@ -488,7 +488,7 @@ out_unmap: } EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); -int mpc5200_audio_dma_destroy(struct of_device *op) +int mpc5200_audio_dma_destroy(struct platform_device *op) { struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index e1ec6d91ea38..ca99586f2ad9 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -81,8 +81,8 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) return &psc_dma->playback; } -int mpc5200_audio_dma_create(struct of_device *op); -int mpc5200_audio_dma_destroy(struct of_device *op); +int mpc5200_audio_dma_create(struct platform_device *op); +int mpc5200_audio_dma_destroy(struct platform_device *op); extern struct snd_soc_platform mpc5200_audio_dma_platform; diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index e2ee220bfb7e..a0310170a170 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -263,7 +263,7 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai); * - Probe/remove operations * - OF device match table */ -static int __devinit psc_ac97_of_probe(struct of_device *op, +static int __devinit psc_ac97_of_probe(struct platform_device *op, const struct of_device_id *match) { int rc, i; @@ -303,7 +303,7 @@ static int __devinit psc_ac97_of_probe(struct of_device *op, return 0; } -static int __devexit psc_ac97_of_remove(struct of_device *op) +static int __devexit psc_ac97_of_remove(struct platform_device *op) { return mpc5200_audio_dma_destroy(op); } diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 4f455bd6851f..9aee748eca7d 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -153,7 +153,7 @@ EXPORT_SYMBOL_GPL(psc_i2s_dai); * - Probe/remove operations * - OF device match table */ -static int __devinit psc_i2s_of_probe(struct of_device *op, +static int __devinit psc_i2s_of_probe(struct platform_device *op, const struct of_device_id *match) { int rc; @@ -206,7 +206,7 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, } -static int __devexit psc_i2s_of_remove(struct of_device *op) +static int __devexit psc_i2s_of_remove(struct platform_device *op) { return mpc5200_audio_dma_destroy(op); } diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 3a501062c244..3b13b8d65262 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -200,7 +200,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = { * SSI devices. We also probably aren't compatible with the generic Elo DMA * device driver. */ -static int mpc8610_hpcd_probe(struct of_device *ofdev, +static int mpc8610_hpcd_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -534,7 +534,7 @@ error: * * This function is called when the OF device is removed. */ -static int mpc8610_hpcd_remove(struct of_device *ofdev) +static int mpc8610_hpcd_remove(struct platform_device *ofdev) { struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); struct mpc8610_hpcd_data *machine_data = diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 9eb1a4e0363b..f8bcfc30f800 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -336,7 +336,7 @@ struct snd_amd7930 { int pgain; int mgain; - struct of_device *op; + struct platform_device *op; unsigned int irq; struct snd_amd7930 *next; }; @@ -906,7 +906,7 @@ static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd) static int snd_amd7930_free(struct snd_amd7930 *amd) { - struct of_device *op = amd->op; + struct platform_device *op = amd->op; amd7930_idle(amd); @@ -934,7 +934,7 @@ static struct snd_device_ops snd_amd7930_dev_ops = { }; static int __devinit snd_amd7930_create(struct snd_card *card, - struct of_device *op, + struct platform_device *op, int irq, int dev, struct snd_amd7930 **ramd) { @@ -1002,7 +1002,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card, return 0; } -static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit amd7930_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct resource *rp = &op->resource[0]; static int dev_num; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 68570ee2c9bb..c276086c3b57 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -111,7 +111,7 @@ struct snd_cs4231 { struct mutex mce_mutex; /* mutex for mce register */ struct mutex open_mutex; /* mutex for ALSA open/close */ - struct of_device *op; + struct platform_device *op; unsigned int irq[2]; unsigned int regs_size; struct snd_cs4231 *next; @@ -1771,7 +1771,7 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) { - struct of_device *op = chip->op; + struct platform_device *op = chip->op; if (chip->irq[0]) free_irq(chip->irq[0], chip); @@ -1794,7 +1794,7 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { }; static int __devinit snd_cs4231_sbus_create(struct snd_card *card, - struct of_device *op, + struct platform_device *op, int dev) { struct snd_cs4231 *chip = card->private_data; @@ -1856,7 +1856,7 @@ static int __devinit snd_cs4231_sbus_create(struct snd_card *card, return 0; } -static int __devinit cs4231_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit cs4231_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct resource *rp = &op->resource[0]; struct snd_card *card; @@ -1931,7 +1931,7 @@ static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) { - struct of_device *op = chip->op; + struct platform_device *op = chip->op; if (chip->c_dma.ebus_info.regs) { ebus_dma_unregister(&chip->c_dma.ebus_info); @@ -1960,7 +1960,7 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { }; static int __devinit snd_cs4231_ebus_create(struct snd_card *card, - struct of_device *op, + struct platform_device *op, int dev) { struct snd_cs4231 *chip = card->private_data; @@ -2048,7 +2048,7 @@ static int __devinit snd_cs4231_ebus_create(struct snd_card *card, return 0; } -static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit cs4231_ebus_probe(struct platform_device *op, const struct of_device_id *match) { struct snd_card *card; int err; @@ -2072,7 +2072,7 @@ static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_dev } #endif -static int __devinit cs4231_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit cs4231_probe(struct platform_device *op, const struct of_device_id *match) { #ifdef EBUS_SUPPORT if (!strcmp(op->dev.of_node->parent->name, "ebus")) @@ -2086,7 +2086,7 @@ static int __devinit cs4231_probe(struct of_device *op, const struct of_device_i return -ENODEV; } -static int __devexit cs4231_remove(struct of_device *op) +static int __devexit cs4231_remove(struct platform_device *op) { struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index c421901c48d0..39cd5d69d051 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -299,7 +299,7 @@ struct dbri_streaminfo { /* This structure holds the information for both chips (DBRI & CS4215) */ struct snd_dbri { int regs_size, irq; /* Needed for unload */ - struct of_device *op; /* OF device info */ + struct platform_device *op; /* OF device info */ spinlock_t lock; struct dbri_dma *dma; /* Pointer to our DMA block */ @@ -2523,7 +2523,7 @@ static void __devinit snd_dbri_proc(struct snd_card *card) static void snd_dbri_free(struct snd_dbri *dbri); static int __devinit snd_dbri_create(struct snd_card *card, - struct of_device *op, + struct platform_device *op, int irq, int dev) { struct snd_dbri *dbri = card->private_data; @@ -2592,7 +2592,7 @@ static void snd_dbri_free(struct snd_dbri *dbri) (void *)dbri->dma, dbri->dma_dvma); } -static int __devinit dbri_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit dbri_probe(struct platform_device *op, const struct of_device_id *match) { struct snd_dbri *dbri; struct resource *rp; @@ -2662,7 +2662,7 @@ _err: return err; } -static int __devexit dbri_remove(struct of_device *op) +static int __devexit dbri_remove(struct platform_device *op) { struct snd_card *card = dev_get_drvdata(&op->dev); -- cgit v1.2.3 From aab7a8fd19d0c2f7fcac4d07616899655e326dfe Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 2 Aug 2010 12:46:12 -0500 Subject: [SCSI] iscsi boot: mv iscsi_boot_sysfs to drivers/scsi iscsi_boot_sysfs does not depend on firmware. Any iscsi driver can use it. This patch moves iscsi_boot_sysfs to the scsi dir, so that it can be used on any arch with any driver. Signed-off-by: Mike Christie Acked-by: Konrad Rzeszutek Wilk Signed-off-by: James Bottomley --- drivers/firmware/Kconfig | 8 - drivers/firmware/Makefile | 1 - drivers/firmware/iscsi_boot_sysfs.c | 481 ------------------------------------ drivers/scsi/Kconfig | 8 + drivers/scsi/Makefile | 1 + drivers/scsi/iscsi_boot_sysfs.c | 481 ++++++++++++++++++++++++++++++++++++ 6 files changed, 490 insertions(+), 490 deletions(-) delete mode 100644 drivers/firmware/iscsi_boot_sysfs.c create mode 100644 drivers/scsi/iscsi_boot_sysfs.c (limited to 'drivers/scsi') diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index a6c670b8ce52..f7cff381a4b8 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -122,14 +122,6 @@ config ISCSI_IBFT_FIND is necessary for iSCSI Boot Firmware Table Attributes module to work properly. -config ISCSI_BOOT_SYSFS - tristate "iSCSI Boot Sysfs Interface" - default n - help - This option enables support for exposing iSCSI boot information - via sysfs to userspace. If you wish to export this information, - say Y. Otherwise, say N. - config ISCSI_IBFT tristate "iSCSI Boot Firmware Table Attributes module" select ISCSI_BOOT_SYSFS diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 5fe7e1662922..1c3c17343dbe 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -10,5 +10,4 @@ obj-$(CONFIG_DCDBAS) += dcdbas.o obj-$(CONFIG_DMIID) += dmi-id.o obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o -obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o diff --git a/drivers/firmware/iscsi_boot_sysfs.c b/drivers/firmware/iscsi_boot_sysfs.c deleted file mode 100644 index df6bff7366cf..000000000000 --- a/drivers/firmware/iscsi_boot_sysfs.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Export the iSCSI boot info to userland via sysfs. - * - * Copyright (C) 2010 Red Hat, Inc. All rights reserved. - * Copyright (C) 2010 Mike Christie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License v2.0 as published by - * the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include - - -MODULE_AUTHOR("Mike Christie "); -MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information"); -MODULE_LICENSE("GPL"); -/* - * The kobject and attribute structures. - */ -struct iscsi_boot_attr { - struct attribute attr; - int type; - ssize_t (*show) (void *data, int type, char *buf); -}; - -/* - * The routine called for all sysfs attributes. - */ -static ssize_t iscsi_boot_show_attribute(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct iscsi_boot_kobj *boot_kobj = - container_of(kobj, struct iscsi_boot_kobj, kobj); - struct iscsi_boot_attr *boot_attr = - container_of(attr, struct iscsi_boot_attr, attr); - ssize_t ret = -EIO; - char *str = buf; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (boot_kobj->show) - ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str); - return ret; -} - -static const struct sysfs_ops iscsi_boot_attr_ops = { - .show = iscsi_boot_show_attribute, -}; - -static void iscsi_boot_kobj_release(struct kobject *kobj) -{ - struct iscsi_boot_kobj *boot_kobj = - container_of(kobj, struct iscsi_boot_kobj, kobj); - - kfree(boot_kobj->data); - kfree(boot_kobj); -} - -static struct kobj_type iscsi_boot_ktype = { - .release = iscsi_boot_kobj_release, - .sysfs_ops = &iscsi_boot_attr_ops, -}; - -#define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type) \ -static struct iscsi_boot_attr iscsi_boot_attr_##fnname = { \ - .attr = { .name = __stringify(sysfs_name), .mode = 0444 }, \ - .type = attr_type, \ -} - -/* Target attrs */ -iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX); -iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS); -iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR); -iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT); -iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN); -iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE); -iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC); -iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME); -iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME); -iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET); -iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name, - ISCSI_BOOT_TGT_REV_CHAP_NAME); -iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret, - ISCSI_BOOT_TGT_REV_CHAP_SECRET); - -static struct attribute *target_attrs[] = { - &iscsi_boot_attr_tgt_index.attr, - &iscsi_boot_attr_tgt_flags.attr, - &iscsi_boot_attr_tgt_ip.attr, - &iscsi_boot_attr_tgt_port.attr, - &iscsi_boot_attr_tgt_lun.attr, - &iscsi_boot_attr_tgt_chap.attr, - &iscsi_boot_attr_tgt_nic.attr, - &iscsi_boot_attr_tgt_name.attr, - &iscsi_boot_attr_tgt_chap_name.attr, - &iscsi_boot_attr_tgt_chap_secret.attr, - &iscsi_boot_attr_tgt_chap_rev_name.attr, - &iscsi_boot_attr_tgt_chap_rev_secret.attr, - NULL -}; - -static mode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int i) -{ - struct iscsi_boot_kobj *boot_kobj = - container_of(kobj, struct iscsi_boot_kobj, kobj); - - if (attr == &iscsi_boot_attr_tgt_index.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_INDEX); - else if (attr == &iscsi_boot_attr_tgt_flags.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_FLAGS); - else if (attr == &iscsi_boot_attr_tgt_ip.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_IP_ADDR); - else if (attr == &iscsi_boot_attr_tgt_port.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_PORT); - else if (attr == &iscsi_boot_attr_tgt_lun.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_LUN); - else if (attr == &iscsi_boot_attr_tgt_chap.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_CHAP_TYPE); - else if (attr == &iscsi_boot_attr_tgt_nic.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_NIC_ASSOC); - else if (attr == &iscsi_boot_attr_tgt_name.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_NAME); - else if (attr == &iscsi_boot_attr_tgt_chap_name.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_CHAP_NAME); - else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_CHAP_SECRET); - else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_REV_CHAP_NAME); - else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_TGT_REV_CHAP_SECRET); - return 0; -} - -static struct attribute_group iscsi_boot_target_attr_group = { - .attrs = target_attrs, - .is_visible = iscsi_boot_tgt_attr_is_visible, -}; - -/* Ethernet attrs */ -iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX); -iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS); -iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR); -iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK); -iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN); -iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY); -iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS); -iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns, - ISCSI_BOOT_ETH_SECONDARY_DNS); -iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP); -iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN); -iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC); -iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME); - -static struct attribute *ethernet_attrs[] = { - &iscsi_boot_attr_eth_index.attr, - &iscsi_boot_attr_eth_flags.attr, - &iscsi_boot_attr_eth_ip.attr, - &iscsi_boot_attr_eth_subnet.attr, - &iscsi_boot_attr_eth_origin.attr, - &iscsi_boot_attr_eth_gateway.attr, - &iscsi_boot_attr_eth_primary_dns.attr, - &iscsi_boot_attr_eth_secondary_dns.attr, - &iscsi_boot_attr_eth_dhcp.attr, - &iscsi_boot_attr_eth_vlan.attr, - &iscsi_boot_attr_eth_mac.attr, - &iscsi_boot_attr_eth_hostname.attr, - NULL -}; - -static mode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int i) -{ - struct iscsi_boot_kobj *boot_kobj = - container_of(kobj, struct iscsi_boot_kobj, kobj); - - if (attr == &iscsi_boot_attr_eth_index.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_INDEX); - else if (attr == &iscsi_boot_attr_eth_flags.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_FLAGS); - else if (attr == &iscsi_boot_attr_eth_ip.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_IP_ADDR); - else if (attr == &iscsi_boot_attr_eth_subnet.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_SUBNET_MASK); - else if (attr == &iscsi_boot_attr_eth_origin.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_ORIGIN); - else if (attr == &iscsi_boot_attr_eth_gateway.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_GATEWAY); - else if (attr == &iscsi_boot_attr_eth_primary_dns.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_PRIMARY_DNS); - else if (attr == &iscsi_boot_attr_eth_secondary_dns.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_SECONDARY_DNS); - else if (attr == &iscsi_boot_attr_eth_dhcp.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_DHCP); - else if (attr == &iscsi_boot_attr_eth_vlan.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_VLAN); - else if (attr == &iscsi_boot_attr_eth_mac.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_MAC); - else if (attr == &iscsi_boot_attr_eth_hostname.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_ETH_HOSTNAME); - return 0; -} - -static struct attribute_group iscsi_boot_ethernet_attr_group = { - .attrs = ethernet_attrs, - .is_visible = iscsi_boot_eth_attr_is_visible, -}; - -/* Initiator attrs */ -iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX); -iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS); -iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER); -iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER); -iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server, - ISCSI_BOOT_INI_PRI_RADIUS_SERVER); -iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server, - ISCSI_BOOT_INI_SEC_RADIUS_SERVER); -iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME); - -static struct attribute *initiator_attrs[] = { - &iscsi_boot_attr_ini_index.attr, - &iscsi_boot_attr_ini_flags.attr, - &iscsi_boot_attr_ini_isns.attr, - &iscsi_boot_attr_ini_slp.attr, - &iscsi_boot_attr_ini_primary_radius.attr, - &iscsi_boot_attr_ini_secondary_radius.attr, - &iscsi_boot_attr_ini_name.attr, - NULL -}; - -static mode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int i) -{ - struct iscsi_boot_kobj *boot_kobj = - container_of(kobj, struct iscsi_boot_kobj, kobj); - - if (attr == &iscsi_boot_attr_ini_index.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_INI_INDEX); - if (attr == &iscsi_boot_attr_ini_flags.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_INI_FLAGS); - if (attr == &iscsi_boot_attr_ini_isns.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_INI_ISNS_SERVER); - if (attr == &iscsi_boot_attr_ini_slp.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_INI_SLP_SERVER); - if (attr == &iscsi_boot_attr_ini_primary_radius.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_INI_PRI_RADIUS_SERVER); - if (attr == &iscsi_boot_attr_ini_secondary_radius.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_INI_SEC_RADIUS_SERVER); - if (attr == &iscsi_boot_attr_ini_name.attr) - return boot_kobj->is_visible(boot_kobj->data, - ISCSI_BOOT_INI_INITIATOR_NAME); - - return 0; -} - -static struct attribute_group iscsi_boot_initiator_attr_group = { - .attrs = initiator_attrs, - .is_visible = iscsi_boot_ini_attr_is_visible, -}; - -static struct iscsi_boot_kobj * -iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, - struct attribute_group *attr_group, - const char *name, int index, void *data, - ssize_t (*show) (void *data, int type, char *buf), - mode_t (*is_visible) (void *data, int type)) -{ - struct iscsi_boot_kobj *boot_kobj; - - boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL); - if (!boot_kobj) - return NULL; - INIT_LIST_HEAD(&boot_kobj->list); - - boot_kobj->kobj.kset = boot_kset->kset; - if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype, - NULL, name, index)) { - kfree(boot_kobj); - return NULL; - } - boot_kobj->data = data; - boot_kobj->show = show; - boot_kobj->is_visible = is_visible; - - if (sysfs_create_group(&boot_kobj->kobj, attr_group)) { - /* - * We do not want to free this because the caller - * will assume that since the creation call failed - * the boot kobj was not setup and the normal release - * path is not being run. - */ - boot_kobj->data = NULL; - kobject_put(&boot_kobj->kobj); - return NULL; - } - boot_kobj->attr_group = attr_group; - - kobject_uevent(&boot_kobj->kobj, KOBJ_ADD); - /* Nothing broke so lets add it to the list. */ - list_add_tail(&boot_kobj->list, &boot_kset->kobj_list); - return boot_kobj; -} - -static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj) -{ - list_del(&boot_kobj->list); - sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group); - kobject_put(&boot_kobj->kobj); -} - -/** - * iscsi_boot_create_target() - create boot target sysfs dir - * @boot_kset: boot kset - * @index: the target id - * @data: driver specific data for target - * @show: attr show function - * @is_visible: attr visibility function - * - * Note: The boot sysfs lib will free the data passed in for the caller - * when all refs to the target kobject have been released. - */ -struct iscsi_boot_kobj * -iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, - void *data, - ssize_t (*show) (void *data, int type, char *buf), - mode_t (*is_visible) (void *data, int type)) -{ - return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group, - "target%d", index, data, show, is_visible); -} -EXPORT_SYMBOL_GPL(iscsi_boot_create_target); - -/** - * iscsi_boot_create_initiator() - create boot initiator sysfs dir - * @boot_kset: boot kset - * @index: the initiator id - * @data: driver specific data - * @show: attr show function - * @is_visible: attr visibility function - * - * Note: The boot sysfs lib will free the data passed in for the caller - * when all refs to the initiator kobject have been released. - */ -struct iscsi_boot_kobj * -iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, - void *data, - ssize_t (*show) (void *data, int type, char *buf), - mode_t (*is_visible) (void *data, int type)) -{ - return iscsi_boot_create_kobj(boot_kset, - &iscsi_boot_initiator_attr_group, - "initiator", index, data, show, - is_visible); -} -EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); - -/** - * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir - * @boot_kset: boot kset - * @index: the ethernet device id - * @data: driver specific data - * @show: attr show function - * @is_visible: attr visibility function - * - * Note: The boot sysfs lib will free the data passed in for the caller - * when all refs to the ethernet kobject have been released. - */ -struct iscsi_boot_kobj * -iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, - void *data, - ssize_t (*show) (void *data, int type, char *buf), - mode_t (*is_visible) (void *data, int type)) -{ - return iscsi_boot_create_kobj(boot_kset, - &iscsi_boot_ethernet_attr_group, - "ethernet%d", index, data, show, - is_visible); -} -EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet); - -/** - * iscsi_boot_create_kset() - creates root sysfs tree - * @set_name: name of root dir - */ -struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name) -{ - struct iscsi_boot_kset *boot_kset; - - boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL); - if (!boot_kset) - return NULL; - - boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj); - if (!boot_kset->kset) { - kfree(boot_kset); - return NULL; - } - - INIT_LIST_HEAD(&boot_kset->kobj_list); - return boot_kset; -} -EXPORT_SYMBOL_GPL(iscsi_boot_create_kset); - -/** - * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host - * @hostno: host number of scsi host - */ -struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno) -{ - struct iscsi_boot_kset *boot_kset; - char *set_name; - - set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno); - if (!set_name) - return NULL; - - boot_kset = iscsi_boot_create_kset(set_name); - kfree(set_name); - return boot_kset; -} -EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset); - -/** - * iscsi_boot_destroy_kset() - destroy kset and kobjects under it - * @boot_kset: boot kset - * - * This will remove the kset and kobjects and attrs under it. - */ -void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset) -{ - struct iscsi_boot_kobj *boot_kobj, *tmp_kobj; - - list_for_each_entry_safe(boot_kobj, tmp_kobj, - &boot_kset->kobj_list, list) - iscsi_boot_remove_kobj(boot_kobj); - - kset_unregister(boot_kset->kset); -} -EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset); diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 158284f05732..a479b3b7ea90 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -370,6 +370,14 @@ config ISCSI_TCP http://open-iscsi.org +config ISCSI_BOOT_SYSFS + tristate "iSCSI Boot Sysfs Interface" + default n + help + This option enables support for exposing iSCSI boot information + via sysfs to userspace. If you wish to export this information, + say Y. Otherwise, say N. + source "drivers/scsi/cxgb3i/Kconfig" source "drivers/scsi/bnx2i/Kconfig" source "drivers/scsi/be2iscsi/Kconfig" diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 2a3fca2eca6a..2703c6ec5e36 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_FCOE) += fcoe/ obj-$(CONFIG_FCOE_FNIC) += fnic/ obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o +obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o obj-$(CONFIG_SCSI_ZORRO7XX) += 53c700.o zorro7xx.o obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c new file mode 100644 index 000000000000..df6bff7366cf --- /dev/null +++ b/drivers/scsi/iscsi_boot_sysfs.c @@ -0,0 +1,481 @@ +/* + * Export the iSCSI boot info to userland via sysfs. + * + * Copyright (C) 2010 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010 Mike Christie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2.0 as published by + * the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + + +MODULE_AUTHOR("Mike Christie "); +MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information"); +MODULE_LICENSE("GPL"); +/* + * The kobject and attribute structures. + */ +struct iscsi_boot_attr { + struct attribute attr; + int type; + ssize_t (*show) (void *data, int type, char *buf); +}; + +/* + * The routine called for all sysfs attributes. + */ +static ssize_t iscsi_boot_show_attribute(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + struct iscsi_boot_attr *boot_attr = + container_of(attr, struct iscsi_boot_attr, attr); + ssize_t ret = -EIO; + char *str = buf; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (boot_kobj->show) + ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str); + return ret; +} + +static const struct sysfs_ops iscsi_boot_attr_ops = { + .show = iscsi_boot_show_attribute, +}; + +static void iscsi_boot_kobj_release(struct kobject *kobj) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + + kfree(boot_kobj->data); + kfree(boot_kobj); +} + +static struct kobj_type iscsi_boot_ktype = { + .release = iscsi_boot_kobj_release, + .sysfs_ops = &iscsi_boot_attr_ops, +}; + +#define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type) \ +static struct iscsi_boot_attr iscsi_boot_attr_##fnname = { \ + .attr = { .name = __stringify(sysfs_name), .mode = 0444 }, \ + .type = attr_type, \ +} + +/* Target attrs */ +iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX); +iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS); +iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR); +iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT); +iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN); +iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE); +iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC); +iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME); +iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME); +iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET); +iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name, + ISCSI_BOOT_TGT_REV_CHAP_NAME); +iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret, + ISCSI_BOOT_TGT_REV_CHAP_SECRET); + +static struct attribute *target_attrs[] = { + &iscsi_boot_attr_tgt_index.attr, + &iscsi_boot_attr_tgt_flags.attr, + &iscsi_boot_attr_tgt_ip.attr, + &iscsi_boot_attr_tgt_port.attr, + &iscsi_boot_attr_tgt_lun.attr, + &iscsi_boot_attr_tgt_chap.attr, + &iscsi_boot_attr_tgt_nic.attr, + &iscsi_boot_attr_tgt_name.attr, + &iscsi_boot_attr_tgt_chap_name.attr, + &iscsi_boot_attr_tgt_chap_secret.attr, + &iscsi_boot_attr_tgt_chap_rev_name.attr, + &iscsi_boot_attr_tgt_chap_rev_secret.attr, + NULL +}; + +static mode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + + if (attr == &iscsi_boot_attr_tgt_index.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_INDEX); + else if (attr == &iscsi_boot_attr_tgt_flags.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_FLAGS); + else if (attr == &iscsi_boot_attr_tgt_ip.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_IP_ADDR); + else if (attr == &iscsi_boot_attr_tgt_port.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_PORT); + else if (attr == &iscsi_boot_attr_tgt_lun.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_LUN); + else if (attr == &iscsi_boot_attr_tgt_chap.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_CHAP_TYPE); + else if (attr == &iscsi_boot_attr_tgt_nic.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_NIC_ASSOC); + else if (attr == &iscsi_boot_attr_tgt_name.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_NAME); + else if (attr == &iscsi_boot_attr_tgt_chap_name.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_CHAP_NAME); + else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_CHAP_SECRET); + else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_REV_CHAP_NAME); + else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_REV_CHAP_SECRET); + return 0; +} + +static struct attribute_group iscsi_boot_target_attr_group = { + .attrs = target_attrs, + .is_visible = iscsi_boot_tgt_attr_is_visible, +}; + +/* Ethernet attrs */ +iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX); +iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS); +iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR); +iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK); +iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN); +iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY); +iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS); +iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns, + ISCSI_BOOT_ETH_SECONDARY_DNS); +iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP); +iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN); +iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC); +iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME); + +static struct attribute *ethernet_attrs[] = { + &iscsi_boot_attr_eth_index.attr, + &iscsi_boot_attr_eth_flags.attr, + &iscsi_boot_attr_eth_ip.attr, + &iscsi_boot_attr_eth_subnet.attr, + &iscsi_boot_attr_eth_origin.attr, + &iscsi_boot_attr_eth_gateway.attr, + &iscsi_boot_attr_eth_primary_dns.attr, + &iscsi_boot_attr_eth_secondary_dns.attr, + &iscsi_boot_attr_eth_dhcp.attr, + &iscsi_boot_attr_eth_vlan.attr, + &iscsi_boot_attr_eth_mac.attr, + &iscsi_boot_attr_eth_hostname.attr, + NULL +}; + +static mode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + + if (attr == &iscsi_boot_attr_eth_index.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_INDEX); + else if (attr == &iscsi_boot_attr_eth_flags.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_FLAGS); + else if (attr == &iscsi_boot_attr_eth_ip.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_IP_ADDR); + else if (attr == &iscsi_boot_attr_eth_subnet.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_SUBNET_MASK); + else if (attr == &iscsi_boot_attr_eth_origin.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_ORIGIN); + else if (attr == &iscsi_boot_attr_eth_gateway.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_GATEWAY); + else if (attr == &iscsi_boot_attr_eth_primary_dns.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_PRIMARY_DNS); + else if (attr == &iscsi_boot_attr_eth_secondary_dns.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_SECONDARY_DNS); + else if (attr == &iscsi_boot_attr_eth_dhcp.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_DHCP); + else if (attr == &iscsi_boot_attr_eth_vlan.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_VLAN); + else if (attr == &iscsi_boot_attr_eth_mac.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_MAC); + else if (attr == &iscsi_boot_attr_eth_hostname.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_HOSTNAME); + return 0; +} + +static struct attribute_group iscsi_boot_ethernet_attr_group = { + .attrs = ethernet_attrs, + .is_visible = iscsi_boot_eth_attr_is_visible, +}; + +/* Initiator attrs */ +iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX); +iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS); +iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER); +iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER); +iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server, + ISCSI_BOOT_INI_PRI_RADIUS_SERVER); +iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server, + ISCSI_BOOT_INI_SEC_RADIUS_SERVER); +iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME); + +static struct attribute *initiator_attrs[] = { + &iscsi_boot_attr_ini_index.attr, + &iscsi_boot_attr_ini_flags.attr, + &iscsi_boot_attr_ini_isns.attr, + &iscsi_boot_attr_ini_slp.attr, + &iscsi_boot_attr_ini_primary_radius.attr, + &iscsi_boot_attr_ini_secondary_radius.attr, + &iscsi_boot_attr_ini_name.attr, + NULL +}; + +static mode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + + if (attr == &iscsi_boot_attr_ini_index.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_INDEX); + if (attr == &iscsi_boot_attr_ini_flags.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_FLAGS); + if (attr == &iscsi_boot_attr_ini_isns.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_ISNS_SERVER); + if (attr == &iscsi_boot_attr_ini_slp.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_SLP_SERVER); + if (attr == &iscsi_boot_attr_ini_primary_radius.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_PRI_RADIUS_SERVER); + if (attr == &iscsi_boot_attr_ini_secondary_radius.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_SEC_RADIUS_SERVER); + if (attr == &iscsi_boot_attr_ini_name.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_INITIATOR_NAME); + + return 0; +} + +static struct attribute_group iscsi_boot_initiator_attr_group = { + .attrs = initiator_attrs, + .is_visible = iscsi_boot_ini_attr_is_visible, +}; + +static struct iscsi_boot_kobj * +iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, + struct attribute_group *attr_group, + const char *name, int index, void *data, + ssize_t (*show) (void *data, int type, char *buf), + mode_t (*is_visible) (void *data, int type)) +{ + struct iscsi_boot_kobj *boot_kobj; + + boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL); + if (!boot_kobj) + return NULL; + INIT_LIST_HEAD(&boot_kobj->list); + + boot_kobj->kobj.kset = boot_kset->kset; + if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype, + NULL, name, index)) { + kfree(boot_kobj); + return NULL; + } + boot_kobj->data = data; + boot_kobj->show = show; + boot_kobj->is_visible = is_visible; + + if (sysfs_create_group(&boot_kobj->kobj, attr_group)) { + /* + * We do not want to free this because the caller + * will assume that since the creation call failed + * the boot kobj was not setup and the normal release + * path is not being run. + */ + boot_kobj->data = NULL; + kobject_put(&boot_kobj->kobj); + return NULL; + } + boot_kobj->attr_group = attr_group; + + kobject_uevent(&boot_kobj->kobj, KOBJ_ADD); + /* Nothing broke so lets add it to the list. */ + list_add_tail(&boot_kobj->list, &boot_kset->kobj_list); + return boot_kobj; +} + +static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj) +{ + list_del(&boot_kobj->list); + sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group); + kobject_put(&boot_kobj->kobj); +} + +/** + * iscsi_boot_create_target() - create boot target sysfs dir + * @boot_kset: boot kset + * @index: the target id + * @data: driver specific data for target + * @show: attr show function + * @is_visible: attr visibility function + * + * Note: The boot sysfs lib will free the data passed in for the caller + * when all refs to the target kobject have been released. + */ +struct iscsi_boot_kobj * +iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, + void *data, + ssize_t (*show) (void *data, int type, char *buf), + mode_t (*is_visible) (void *data, int type)) +{ + return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group, + "target%d", index, data, show, is_visible); +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_target); + +/** + * iscsi_boot_create_initiator() - create boot initiator sysfs dir + * @boot_kset: boot kset + * @index: the initiator id + * @data: driver specific data + * @show: attr show function + * @is_visible: attr visibility function + * + * Note: The boot sysfs lib will free the data passed in for the caller + * when all refs to the initiator kobject have been released. + */ +struct iscsi_boot_kobj * +iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, + void *data, + ssize_t (*show) (void *data, int type, char *buf), + mode_t (*is_visible) (void *data, int type)) +{ + return iscsi_boot_create_kobj(boot_kset, + &iscsi_boot_initiator_attr_group, + "initiator", index, data, show, + is_visible); +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); + +/** + * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir + * @boot_kset: boot kset + * @index: the ethernet device id + * @data: driver specific data + * @show: attr show function + * @is_visible: attr visibility function + * + * Note: The boot sysfs lib will free the data passed in for the caller + * when all refs to the ethernet kobject have been released. + */ +struct iscsi_boot_kobj * +iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, + void *data, + ssize_t (*show) (void *data, int type, char *buf), + mode_t (*is_visible) (void *data, int type)) +{ + return iscsi_boot_create_kobj(boot_kset, + &iscsi_boot_ethernet_attr_group, + "ethernet%d", index, data, show, + is_visible); +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet); + +/** + * iscsi_boot_create_kset() - creates root sysfs tree + * @set_name: name of root dir + */ +struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name) +{ + struct iscsi_boot_kset *boot_kset; + + boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL); + if (!boot_kset) + return NULL; + + boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj); + if (!boot_kset->kset) { + kfree(boot_kset); + return NULL; + } + + INIT_LIST_HEAD(&boot_kset->kobj_list); + return boot_kset; +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_kset); + +/** + * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host + * @hostno: host number of scsi host + */ +struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno) +{ + struct iscsi_boot_kset *boot_kset; + char *set_name; + + set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno); + if (!set_name) + return NULL; + + boot_kset = iscsi_boot_create_kset(set_name); + kfree(set_name); + return boot_kset; +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset); + +/** + * iscsi_boot_destroy_kset() - destroy kset and kobjects under it + * @boot_kset: boot kset + * + * This will remove the kset and kobjects and attrs under it. + */ +void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset) +{ + struct iscsi_boot_kobj *boot_kobj, *tmp_kobj; + + list_for_each_entry_safe(boot_kobj, tmp_kobj, + &boot_kset->kobj_list, list) + iscsi_boot_remove_kobj(boot_kobj); + + kset_unregister(boot_kset->kset); +} +EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset); -- cgit v1.2.3 From 26845f585fad66dc23d87dad89d403cd64b48780 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 5 Aug 2010 13:17:10 -0400 Subject: [SCSI] remove fake "address-of" expression Fake "address-of" expressions that evaluate to NULL generally confuse readers and can provoke compiler warnings. This patch (as1411) removes one such fake expression introduced by: commit db5bd1e0b505c54ff492172ce4abc245cf6cd639 Author: Alan Stern Date: Thu Jun 17 10:36:49 2010 -0400 [SCSI] convert to the new PM framework using an "#ifdef" in its place. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/scsi_priv.h | 2 -- drivers/scsi/scsi_sysfs.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 026295e2c539..b4056d14f812 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -148,8 +148,6 @@ static inline void scsi_netlink_exit(void) {} /* scsi_pm.c */ #ifdef CONFIG_PM_OPS extern const struct dev_pm_ops scsi_bus_pm_ops; -#else /* CONFIG_PM_OPS */ -#define scsi_bus_pm_ops (*NULL) #endif #ifdef CONFIG_PM_RUNTIME extern void scsi_autopm_get_target(struct scsi_target *); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 562fb3bce261..c3f67373a4f8 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -381,7 +381,9 @@ struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, .uevent = scsi_bus_uevent, +#ifdef CONFIG_PM_OPS .pm = &scsi_bus_pm_ops, +#endif }; EXPORT_SYMBOL_GPL(scsi_bus_type); -- cgit v1.2.3 From be948fc30dabc347e4fba4daf4da9fd83d2abf49 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 2 Aug 2010 16:02:24 -0500 Subject: [SCSI] libfc: call fc_remote_port_chkready under the host lock. The rport port state and flags are set under the host lock, so this patch calls fc_remote_port_chkready with the host lock held like is also done in the other fc drivers. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index eac4d09314eb..c797f6b48f05 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1765,14 +1765,14 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) struct fcoe_dev_stats *stats; lport = shost_priv(sc_cmd->device->host); - spin_unlock_irq(lport->host->host_lock); rval = fc_remote_port_chkready(rport); if (rval) { sc_cmd->result = rval; done(sc_cmd); - goto out; + return 0; } + spin_unlock_irq(lport->host->host_lock); if (!*(struct fc_remote_port **)rport->dd_data) { /* -- cgit v1.2.3 From e6da54d84f9286edbe4c92ff5023ff481ce2a5c9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 5 Aug 2010 13:17:10 -0400 Subject: SCSI: remove fake "address-of" expression Fake "address-of" expressions that evaluate to NULL generally confuse readers and can provoke compiler warnings. This patch (as1411) removes one such fake expression, using an "#ifdef" in its place. Signed-off-by: Alan Stern Signed-off-by: Linus Torvalds --- drivers/scsi/scsi_priv.h | 2 -- drivers/scsi/scsi_sysfs.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 026295e2c539..b4056d14f812 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -148,8 +148,6 @@ static inline void scsi_netlink_exit(void) {} /* scsi_pm.c */ #ifdef CONFIG_PM_OPS extern const struct dev_pm_ops scsi_bus_pm_ops; -#else /* CONFIG_PM_OPS */ -#define scsi_bus_pm_ops (*NULL) #endif #ifdef CONFIG_PM_RUNTIME extern void scsi_autopm_get_target(struct scsi_target *); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 562fb3bce261..c3f67373a4f8 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -381,7 +381,9 @@ struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, .uevent = scsi_bus_uevent, +#ifdef CONFIG_PM_OPS .pm = &scsi_bus_pm_ops, +#endif }; EXPORT_SYMBOL_GPL(scsi_bus_type); -- cgit v1.2.3 From 3013cea83ef3532e49b973a0bc9b3562f56871c6 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Fri, 30 Jul 2010 14:25:46 +0530 Subject: [SCSI] qla4xxx: set correct value in sess->recovery_tmo Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 5 +++-- drivers/scsi/qla4xxx/ql4_init.c | 3 --- drivers/scsi/qla4xxx/ql4_mbx.c | 1 - drivers/scsi/qla4xxx/ql4_os.c | 7 ++++--- 4 files changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index a79da8dd2064..6af5d04c5290 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -137,6 +137,9 @@ #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ +#define QL4_SESS_RECOVERY_TMO 30 /* iSCSI session */ + /* recovery timeout */ + #define LSDW(x) ((u32)((u64)(x))) #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) @@ -249,7 +252,6 @@ struct ddb_entry { uint32_t default_time2wait; /* Default Min time between * relogins (+aens) */ - atomic_t port_down_timer; /* Device connection timer */ atomic_t retry_relogin_timer; /* Min Time between relogins * (4000 only) */ atomic_t relogin_timer; /* Max Time to wait for relogin to complete */ @@ -474,7 +476,6 @@ struct scsi_qla_host { uint32_t timer_active; /* Recovery Timers */ - uint32_t port_down_retry_count; uint32_t discovery_wait; atomic_t check_relogin_timeouts; uint32_t retry_reset_ha_cnt; diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 30073577c3a4..b69c5736cb43 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -669,7 +669,6 @@ static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, } ddb_entry->fw_ddb_index = fw_ddb_index; - atomic_set(&ddb_entry->port_down_timer, ha->port_down_retry_count); atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); atomic_set(&ddb_entry->relogin_timer, 0); atomic_set(&ddb_entry->relogin_retry_count, 0); @@ -1556,8 +1555,6 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, /* Device is back online. */ if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); - atomic_set(&ddb_entry->port_down_timer, - ha->port_down_retry_count); atomic_set(&ddb_entry->relogin_retry_count, 0); atomic_set(&ddb_entry->relogin_timer, 0); clear_bit(DF_RELOGIN, &ddb_entry->flags); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 940ee561ee0a..c4e036b449c2 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -361,7 +361,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ /* Save Command Line Paramater info */ - ha->port_down_retry_count = le16_to_cpu(init_fw_cb->conn_ka_timeout); ha->discovery_wait = ql4xdiscoverywait; if (ha->acb_version == ACB_SUPPORTED) { diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 5529b2a39741..fd1af23e6801 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -163,10 +163,10 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { atomic_set(&ddb_entry->state, DDB_STATE_DEAD); - DEBUG2(printk("scsi%ld: %s: ddb [%d] port down retry count " + DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout " "of (%d) secs exhausted, marking device DEAD.\n", ha->host_no, __func__, ddb_entry->fw_ddb_index, - ha->port_down_retry_count)); + QL4_SESS_RECOVERY_TMO)); qla4xxx_wake_dpc(ha); } @@ -298,7 +298,8 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry) { int err; - ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count; + ddb_entry->sess->recovery_tmo = QL4_SESS_RECOVERY_TMO; + err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index); if (err) { DEBUG2(printk(KERN_ERR "Could not add session.\n")); -- cgit v1.2.3 From b173a132cbf0a4a48b2f341716e20a6d8b24957e Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Fri, 30 Jul 2010 14:26:08 +0530 Subject: [SCSI] qla4xxx: Use the correct request queue. Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_iocb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index f89973deac5b..4ef9ba112ee8 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -19,7 +19,7 @@ qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt) /* Calculate number of free request entries. */ if ((req_cnt + 2) >= ha->req_q_count) { - cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); + cnt = (uint16_t) ha->isp_ops->rd_shdw_req_q_out(ha); if (ha->request_in < cnt) ha->req_q_count = cnt - ha->request_in; else -- cgit v1.2.3 From 9d4946f89fc050cadf66d08c47379ab62848a5b7 Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Fri, 30 Jul 2010 14:26:31 +0530 Subject: [SCSI] qla4xxx: Stop firmware before doing init firmware. If BIOS is enabled then drivers init firmware fails since BIOS has done the init once. Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index b69c5736cb43..39048d9339ac 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -445,6 +445,12 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) { int status = QLA_ERROR; + /* For 82xx, stop firmware before initializing because if BIOS + * has previously initialized firmware, then driver's initialize + * firmware will fail. */ + if (is_qla8022(ha)) + qla4_8xxx_stop_firmware(ha); + ql4_printk(KERN_INFO, ha, "Initializing firmware..\n"); if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) { DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware " -- cgit v1.2.3 From 0753b4871d5b09687cee652b380a6ca15aee330e Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Fri, 30 Jul 2010 14:27:19 +0530 Subject: [SCSI] qla4xxx: clear AF_DPC_SCHEDULED flage when exit from do_dpc Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index fd1af23e6801..e575d765ba26 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1208,7 +1208,7 @@ static void qla4xxx_do_dpc(struct work_struct *work) /* Initialization not yet finished. Don't do anything yet. */ if (!test_bit(AF_INIT_DONE, &ha->flags)) - return; + goto do_dpc_exit; /* HBA is in the process of being permanently disabled. * Don't process anything */ @@ -1347,6 +1347,8 @@ dpc_post_reset_ha: } } } + +do_dpc_exit: clear_bit(AF_DPC_SCHEDULED, &ha->flags); } -- cgit v1.2.3 From 2ccdf0dce41a39db3721fe801dac5c5effa8e4be Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Fri, 30 Jul 2010 14:27:45 +0530 Subject: [SCSI] qla4xxx: updated mbx_sys_info struct to sync with FW 4.6.x Also, changed boundary checking from size of total structure to verification that we received the amount of data needed to cache inernally. This change will provide compatibility with mbx_sys_info structure sizes in both older and newer firmware versions. Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_fw.h | 20 ++++++++++---------- drivers/scsi/qla4xxx/ql4_nx.c | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index c94c9ddfb3a6..0336c6db8cb3 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -673,17 +673,17 @@ struct flash_sys_info { }; /* 200 */ struct mbx_sys_info { - uint8_t board_id_str[16]; /* Keep board ID string first */ - /* in this structure for GUI. */ - uint16_t board_id; /* board ID code */ - uint16_t phys_port_cnt; /* number of physical network ports */ - uint16_t port_num; /* network port for this PCI function */ + uint8_t board_id_str[16]; /* 0-f Keep board ID string first */ + /* in this structure for GUI. */ + uint16_t board_id; /* 10-11 board ID code */ + uint16_t phys_port_cnt; /* 12-13 number of physical network ports */ + uint16_t port_num; /* 14-15 network port for this PCI function */ /* (port 0 is first port) */ - uint8_t mac_addr[6]; /* MAC address for this PCI function */ - uint32_t iscsi_pci_func_cnt; /* number of iSCSI PCI functions */ - uint32_t pci_func; /* this PCI function */ - unsigned char serial_number[16]; /* serial number string */ - uint8_t reserved[16]; + uint8_t mac_addr[6]; /* 16-1b MAC address for this PCI function */ + uint32_t iscsi_pci_func_cnt; /* 1c-1f number of iSCSI PCI functions */ + uint32_t pci_func; /* 20-23 this PCI function */ + unsigned char serial_number[16]; /* 24-33 serial number string */ + uint8_t reserved[12]; /* 34-3f */ }; struct crash_record { diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 3e119ae78397..ec46651100cb 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -2145,7 +2145,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) goto exit_validate_mac82; } - if (mbox_sts[4] < sizeof(*sys_info)) { + /* Make sure we receive the minimum required data to cache internally */ + if (mbox_sts[4] < offsetof(struct mbx_sys_info, reserved)) { DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); goto exit_validate_mac82; -- cgit v1.2.3 From 21033639699d883668f6937b03e7b710771ad37e Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Fri, 30 Jul 2010 14:28:07 +0530 Subject: [SCSI] qla4xxx: Handle outstanding mbx cmds on hung f/w scenarios Outstanding mailbox commands, have no way to recover on f/w hung, and we timeout on waiting for mbx response. This in turn affects the recovery process as follows: - We might already be in dpc while waiting for mbx to complete, so recovery for that pci function will never get invoked. Reset Timeout (10 sec) is far less than mbx timeout (30 sec). - Other mbx cmds will get stuck due to serial mbx access. Solution is to identify fw-hung scenario and handle outstanding mbx commands to have an early-exit instead of waiting for response. Other mbx commands waiting for access will also do an early-exit if fw-hung is still applicable. Signed-off-by: Nilesh Javali Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 1 + drivers/scsi/qla4xxx/ql4_glbl.h | 1 + drivers/scsi/qla4xxx/ql4_mbx.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla4xxx/ql4_nx.c | 3 +++ drivers/scsi/qla4xxx/ql4_os.c | 3 +++ 5 files changed, 47 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 6af5d04c5290..6c9262753243 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -380,6 +380,7 @@ struct scsi_qla_host { #define AF_MSI_ENABLED 16 /* 0x00010000 */ #define AF_MSIX_ENABLED 17 /* 0x00020000 */ #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ +#define AF_FW_RECOVERY 19 /* 0x00080000 */ unsigned long dpc_flags; diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index c9cd5d6db982..ea3db23602e6 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -93,6 +93,7 @@ void qla4xxx_free_irqs(struct scsi_qla_host *ha); void qla4xxx_process_response_queue(struct scsi_qla_host *ha); void qla4xxx_wake_dpc(struct scsi_qla_host *ha); void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha); +void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha); void qla4_8xxx_pci_config(struct scsi_qla_host *); int qla4_8xxx_iospace_config(struct scsi_qla_host *ha); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index c4e036b449c2..1003e48d2200 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -39,6 +39,15 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, "pointer\n", ha->host_no, __func__)); return status; } + + if (is_qla8022(ha) && + test_bit(AF_FW_RECOVERY, &ha->flags)) { + DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: prematurely " + "completing mbx cmd as firmware recovery detected\n", + ha->host_no, __func__)); + return status; + } + /* Mailbox code active */ wait_count = MBOX_TOV * 100; @@ -196,6 +205,14 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, /* Check for mailbox timeout. */ if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { + if (is_qla8022(ha) && + test_bit(AF_FW_RECOVERY, &ha->flags)) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "scsi%ld: %s: prematurely completing mbx cmd as " + "firmware recovery detected\n", + ha->host_no, __func__)); + goto mbox_exit; + } DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...," " Scheduling Adapter Reset\n", ha->host_no, mbx_cmd[0])); @@ -246,6 +263,28 @@ mbox_exit: return status; } +void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) +{ + set_bit(AF_FW_RECOVERY, &ha->flags); + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n", + ha->host_no, __func__); + + if (test_bit(AF_MBOX_COMMAND, &ha->flags)) { + if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) { + complete(&ha->mbx_intr_comp); + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " + "recovery, doing premature completion of " + "mbx cmd\n", ha->host_no, __func__); + + } else { + set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " + "recovery, doing premature completion of " + "polling mbx cmd\n", ha->host_no, __func__); + } + } +} + static uint8_t qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index ec46651100cb..0830ea9d708c 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -2105,6 +2105,9 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) qla4_8xxx_clear_rst_ready(ha); qla4_8xxx_idc_unlock(ha); + if (rval == QLA_SUCCESS) + clear_bit(AF_FW_RECOVERY, &ha->flags); + return rval; } diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index e575d765ba26..2bb362c6e634 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -663,6 +663,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) ha->seconds_since_last_heartbeat = 0; halt_status = qla4_8xxx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); + /* Since we cannot change dev_state in interrupt * context, set appropriate DPC flag then wakeup * DPC */ @@ -674,6 +675,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) set_bit(DPC_RESET_HA, &ha->dpc_flags); } qla4xxx_wake_dpc(ha); + qla4xxx_mailbox_premature_completion(ha); } } ha->fw_heartbeat_counter = fw_heartbeat_counter; @@ -699,6 +701,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) ha->host_no, __func__); set_bit(DPC_RESET_HA, &ha->dpc_flags); qla4xxx_wake_dpc(ha); + qla4xxx_mailbox_premature_completion(ha); } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { printk("scsi%ld: %s: HW State: NEED QUIES!\n", -- cgit v1.2.3 From 2232be0d5707cd331b92027c0fd7ea5e843c2121 Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Fri, 30 Jul 2010 14:38:47 +0530 Subject: [SCSI] qla4xxx: Added AER support for ISP82xx Added support for PCI error handling Signed-off-by: Lalit Chandivade Signed-off-by: Vikas Chaudhary Signed-off-by: Poornima Vonti Signed-off-by: Ravi Anand Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 30 +++- drivers/scsi/qla4xxx/ql4_glbl.h | 1 + drivers/scsi/qla4xxx/ql4_init.c | 5 +- drivers/scsi/qla4xxx/ql4_isr.c | 3 + drivers/scsi/qla4xxx/ql4_mbx.c | 8 ++ drivers/scsi/qla4xxx/ql4_nx.c | 8 +- drivers/scsi/qla4xxx/ql4_os.c | 301 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 352 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 6c9262753243..9dc0a6616edd 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -36,6 +36,24 @@ #include "ql4_dbg.h" #include "ql4_nx.h" +#if defined(CONFIG_PCIEAER) +#include +#else +/* AER releated */ +static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) +{ + return -EINVAL; +} +static inline int pci_disable_pcie_error_reporting(struct pci_dev *dev) +{ + return -EINVAL; +} +static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) +{ + return -EINVAL; +} +#endif + #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 #endif @@ -381,7 +399,8 @@ struct scsi_qla_host { #define AF_MSIX_ENABLED 17 /* 0x00020000 */ #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ #define AF_FW_RECOVERY 19 /* 0x00080000 */ - +#define AF_EEH_BUSY 20 /* 0x00100000 */ +#define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ unsigned long dpc_flags; @@ -617,6 +636,15 @@ static inline int is_qla8022(struct scsi_qla_host *ha) return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; } +/* Note: Currently AER/EEH is now supported only for 8022 cards + * This function needs to be updated when AER/EEH is enabled + * for other cards. + */ +static inline int is_aer_supported(struct scsi_qla_host *ha) +{ + return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; +} + static inline int adapter_up(struct scsi_qla_host *ha) { return (test_bit(AF_ONLINE, &ha->flags) != 0) && diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index ea3db23602e6..f065204e401b 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -132,6 +132,7 @@ void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha); int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha); void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha); void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha); +inline void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha); extern int ql4xextended_error_logging; extern int ql4xdiscoverywait; diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 39048d9339ac..4c9be77ee70b 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -308,7 +308,6 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) DEBUG2(printk("scsi%ld: %s: unable to get firmware " "state\n", ha->host_no, __func__)); break; - } if (ha->firmware_state & FW_STATE_ERROR) { @@ -445,6 +444,10 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) { int status = QLA_ERROR; + if (is_aer_supported(ha) && + test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) + return status; + /* For 82xx, stop firmware before initializing because if BIOS * has previously initialized firmware, then driver's initialize * firmware will fail. */ diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index aa65697a86b4..2a1ab63f3eb0 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -816,6 +816,9 @@ irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id) unsigned long flags = 0; uint8_t reqs_count = 0; + if (unlikely(pci_channel_offline(ha->pdev))) + return IRQ_HANDLED; + ha->isr_count++; status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); if (!(status & ha->nx_legacy_intr.int_vec_bit)) diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 1003e48d2200..90021704d8ca 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -48,6 +48,13 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, return status; } + if ((is_aer_supported(ha)) && + (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { + DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " + "timeout MBX Exiting.\n", ha->host_no, __func__)); + return status; + } + /* Mailbox code active */ wait_count = MBOX_TOV * 100; @@ -159,6 +166,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { if (time_after_eq(jiffies, wait_count)) break; + /* * Service the interrupt. * The ISR will save the mailbox status registers diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 0830ea9d708c..1b85235efd8c 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1418,7 +1418,7 @@ static int qla4_8xxx_rcvpeg_ready(struct scsi_qla_host *ha) return QLA_SUCCESS; } -static inline void +inline void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) { uint32_t drv_active; @@ -1441,11 +1441,15 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) static inline int qla4_8xxx_need_reset(struct scsi_qla_host *ha) { - uint32_t drv_state; + uint32_t drv_state, drv_active; int rval; + drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); rval = drv_state & (1 << (ha->func_num * 4)); + if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active) + rval = 1; + return rval; } diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 2bb362c6e634..370d40ff1529 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -475,6 +475,14 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, struct srb *srb; int rval; + if (test_bit(AF_EEH_BUSY, &ha->flags)) { + if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) + cmd->result = DID_NO_CONNECT << 16; + else + cmd->result = DID_REQUEUE << 16; + goto qc_fail_command; + } + if (!sess) { cmd->result = DID_IMM_RETRY << 16; goto qc_fail_command; @@ -655,6 +663,13 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) uint32_t fw_heartbeat_counter, halt_status; fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); + /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */ + if (fw_heartbeat_counter == 0xffffffff) { + DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen " + "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n", + ha->host_no, __func__)); + return; + } if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { ha->seconds_since_last_heartbeat++; @@ -723,6 +738,19 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) { struct ddb_entry *ddb_entry, *dtemp; int start_dpc = 0; + uint16_t w; + + /* If we are in the middle of AER/EEH processing + * skip any processing and reschedule the timer + */ + if (test_bit(AF_EEH_BUSY, &ha->flags)) { + mod_timer(&ha->timer, jiffies + HZ); + return; + } + + /* Hardware read to trigger an EEH error during mailbox waits. */ + if (!pci_channel_offline(ha->pdev)) + pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", @@ -1213,6 +1241,12 @@ static void qla4xxx_do_dpc(struct work_struct *work) if (!test_bit(AF_INIT_DONE, &ha->flags)) goto do_dpc_exit; + if (test_bit(AF_EEH_BUSY, &ha->flags)) { + DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", + ha->host_no, __func__, ha->flags)); + goto do_dpc_exit; + } + /* HBA is in the process of being permanently disabled. * Don't process anything */ if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) @@ -1618,6 +1652,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ha->host = host; ha->host_no = host->host_no; + pci_enable_pcie_error_reporting(pdev); + /* Setup Runtime configurable options */ if (is_qla8022(ha)) { ha->isp_ops = &qla4_8xxx_isp_ops; @@ -1636,6 +1672,10 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ha->isp_ops = &qla4xxx_isp_ops; } + /* Set EEH reset type to fundamental if required by hba */ + if (is_qla8022(ha)) + pdev->needs_freset = 1; + /* Configure PCI I/O space. */ ret = ha->isp_ops->iospace_config(ha); if (ret) @@ -1732,6 +1772,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, } } + pci_save_state(ha->pdev); ha->isp_ops->enable_intrs(ha); /* Start timer thread. */ @@ -1758,6 +1799,7 @@ probe_failed: qla4xxx_free_adapter(ha); probe_failed_ioconfig: + pci_disable_pcie_error_reporting(pdev); scsi_host_put(ha->host); probe_disable_device: @@ -1787,6 +1829,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) scsi_host_put(ha->host); + pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } @@ -1883,6 +1926,17 @@ static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha, int done = 0; struct srb *rp; uint32_t max_wait_time = EH_WAIT_CMD_TOV; + int ret = SUCCESS; + + /* Dont wait on command if PCI error is being handled + * by PCI AER driver + */ + if (unlikely(pci_channel_offline(ha->pdev)) || + (test_bit(AF_EEH_BUSY, &ha->flags))) { + ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n", + ha->host_no, __func__); + return ret; + } do { /* Checking to see if its returned to OS */ @@ -2178,6 +2232,252 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) return return_status; } +/* PCI AER driver recovers from all correctable errors w/o + * driver intervention. For uncorrectable errors PCI AER + * driver calls the following device driver's callbacks + * + * - Fatal Errors - link_reset + * - Non-Fatal Errors - driver's pci_error_detected() which + * returns CAN_RECOVER, NEED_RESET or DISCONNECT. + * + * PCI AER driver calls + * CAN_RECOVER - driver's pci_mmio_enabled(), mmio_enabled + * returns RECOVERED or NEED_RESET if fw_hung + * NEED_RESET - driver's slot_reset() + * DISCONNECT - device is dead & cannot recover + * RECOVERED - driver's pci_resume() + */ +static pci_ers_result_t +qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) +{ + struct scsi_qla_host *ha = pci_get_drvdata(pdev); + + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n", + ha->host_no, __func__, state); + + if (!is_aer_supported(ha)) + return PCI_ERS_RESULT_NONE; + + switch (state) { + case pci_channel_io_normal: + clear_bit(AF_EEH_BUSY, &ha->flags); + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: + set_bit(AF_EEH_BUSY, &ha->flags); + qla4xxx_mailbox_premature_completion(ha); + qla4xxx_free_irqs(ha); + pci_disable_device(pdev); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + set_bit(AF_EEH_BUSY, &ha->flags); + set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags); + qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); + return PCI_ERS_RESULT_DISCONNECT; + } + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * qla4xxx_pci_mmio_enabled() gets called if + * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER + * and read/write to the device still works. + **/ +static pci_ers_result_t +qla4xxx_pci_mmio_enabled(struct pci_dev *pdev) +{ + struct scsi_qla_host *ha = pci_get_drvdata(pdev); + + if (!is_aer_supported(ha)) + return PCI_ERS_RESULT_NONE; + + if (test_bit(AF_FW_RECOVERY, &ha->flags)) { + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: firmware hang -- " + "mmio_enabled\n", ha->host_no, __func__); + return PCI_ERS_RESULT_NEED_RESET; + } else + return PCI_ERS_RESULT_RECOVERED; +} + +uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) +{ + uint32_t rval = QLA_ERROR; + int fn; + struct pci_dev *other_pdev = NULL; + + ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__); + + set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); + + if (test_bit(AF_ONLINE, &ha->flags)) { + clear_bit(AF_ONLINE, &ha->flags); + qla4xxx_mark_all_devices_missing(ha); + qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); + qla4xxx_abort_active_cmds(ha, DID_RESET << 16); + } + + fn = PCI_FUNC(ha->pdev->devfn); + while (fn > 0) { + fn--; + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at " + "func %x\n", ha->host_no, __func__, fn); + /* Get the pci device given the domain, bus, + * slot/function number */ + other_pdev = + pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus), + ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn), + fn)); + + if (!other_pdev) + continue; + + if (atomic_read(&other_pdev->enable_cnt)) { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI " + "func in enabled state%x\n", ha->host_no, + __func__, fn); + pci_dev_put(other_pdev); + break; + } + pci_dev_put(other_pdev); + } + + /* The first function on the card, the reset owner will + * start & initialize the firmware. The other functions + * on the card will reset the firmware context + */ + if (!fn) { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset " + "0x%x is the owner\n", ha->host_no, __func__, + ha->pdev->devfn); + + qla4_8xxx_idc_lock(ha); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_COLD); + + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, + QLA82XX_IDC_VERSION); + + qla4_8xxx_idc_unlock(ha); + clear_bit(AF_FW_RECOVERY, &ha->flags); + rval = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); + qla4_8xxx_idc_lock(ha); + + if (rval != QLA_SUCCESS) { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " + "FAILED\n", ha->host_no, __func__); + qla4_8xxx_clear_drv_active(ha); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_FAILED); + } else { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " + "READY\n", ha->host_no, __func__); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_READY); + /* Clear driver state register */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0); + qla4_8xxx_set_drv_active(ha); + ha->isp_ops->enable_intrs(ha); + } + qla4_8xxx_idc_unlock(ha); + } else { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not " + "the reset owner\n", ha->host_no, __func__, + ha->pdev->devfn); + if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == + QLA82XX_DEV_READY)) { + clear_bit(AF_FW_RECOVERY, &ha->flags); + rval = qla4xxx_initialize_adapter(ha, + PRESERVE_DDB_LIST); + if (rval == QLA_SUCCESS) + ha->isp_ops->enable_intrs(ha); + qla4_8xxx_idc_lock(ha); + qla4_8xxx_set_drv_active(ha); + qla4_8xxx_idc_unlock(ha); + } + } + clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); + return rval; +} + +static pci_ers_result_t +qla4xxx_pci_slot_reset(struct pci_dev *pdev) +{ + pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; + struct scsi_qla_host *ha = pci_get_drvdata(pdev); + int rc; + + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n", + ha->host_no, __func__); + + if (!is_aer_supported(ha)) + return PCI_ERS_RESULT_NONE; + + /* Restore the saved state of PCIe device - + * BAR registers, PCI Config space, PCIX, MSI, + * IOV states + */ + pci_restore_state(pdev); + + /* pci_restore_state() clears the saved_state flag of the device + * save restored state which resets saved_state flag + */ + pci_save_state(pdev); + + /* Initialize device or resume if in suspended state */ + rc = pci_enable_device(pdev); + if (rc) { + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cant re-enable " + "device after reset\n", ha->host_no, __func__); + goto exit_slot_reset; + } + + ret = qla4xxx_request_irqs(ha); + if (ret) { + ql4_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d" + " already in use.\n", pdev->irq); + goto exit_slot_reset; + } + + if (is_qla8022(ha)) { + if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) { + ret = PCI_ERS_RESULT_RECOVERED; + goto exit_slot_reset; + } else + goto exit_slot_reset; + } + +exit_slot_reset: + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n" + "device after reset\n", ha->host_no, __func__, ret); + return ret; +} + +static void +qla4xxx_pci_resume(struct pci_dev *pdev) +{ + struct scsi_qla_host *ha = pci_get_drvdata(pdev); + int ret; + + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n", + ha->host_no, __func__); + + ret = qla4xxx_wait_for_hba_online(ha); + if (ret != QLA_SUCCESS) { + ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to " + "resume I/O from slot/link_reset\n", ha->host_no, + __func__); + } + + pci_cleanup_aer_uncorrect_error_status(pdev); + clear_bit(AF_EEH_BUSY, &ha->flags); +} + +static struct pci_error_handlers qla4xxx_err_handler = { + .error_detected = qla4xxx_pci_error_detected, + .mmio_enabled = qla4xxx_pci_mmio_enabled, + .slot_reset = qla4xxx_pci_slot_reset, + .resume = qla4xxx_pci_resume, +}; + static struct pci_device_id qla4xxx_pci_tbl[] = { { .vendor = PCI_VENDOR_ID_QLOGIC, @@ -2212,6 +2512,7 @@ static struct pci_driver qla4xxx_pci_driver = { .id_table = qla4xxx_pci_tbl, .probe = qla4xxx_probe_adapter, .remove = qla4xxx_remove_adapter, + .err_handler = &qla4xxx_err_handler, }; static int __init qla4xxx_module_init(void) -- cgit v1.2.3 From e8ed741fcd521a25f1d983ec81f72ac823d8429a Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Fri, 30 Jul 2010 14:28:52 +0530 Subject: [SCSI] qla4xxx: Update driver version to 5.02.00-k3 Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index c905dbd75331..a77b973f2cbc 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k2" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k3" -- cgit v1.2.3 From 823d219f23b958292279cfdc8583dc4f1f91c2d5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 1 Aug 2010 19:23:35 +0200 Subject: [SCSI] pm8001: introduce missing kfree Error handling code following a kmalloc should free the allocated data. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; expression E; identifier f,f1; position p1,p2; @@ x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); <... when != x when != if (...) { <+...x...+> } when != (x) == NULL when != (x) != NULL when != (x) == 0 when != (x) != 0 ( x->f1 = E | (x->f1 == NULL || ...) | f(...,x->f1,...) ) ...> ( return <+...x...+>; | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Acked-by: jack wang Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm8001_hwi.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 58d1134935ef..9793aa6afb10 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -4199,8 +4199,10 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, circularQ = &pm8001_ha->inbnd_q_tbl[0]; memset(&nvmd_req, 0, sizeof(nvmd_req)); rc = pm8001_tag_alloc(pm8001_ha, &tag); - if (rc) + if (rc) { + kfree(fw_control_context); return rc; + } ccb = &pm8001_ha->ccb_info[tag]; ccb->ccb_tag = tag; ccb->fw_control_context = fw_control_context; @@ -4276,8 +4278,10 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, ioctl_payload->length); memset(&nvmd_req, 0, sizeof(nvmd_req)); rc = pm8001_tag_alloc(pm8001_ha, &tag); - if (rc) + if (rc) { + kfree(fw_control_context); return rc; + } ccb = &pm8001_ha->ccb_info[tag]; ccb->fw_control_context = fw_control_context; ccb->ccb_tag = tag; @@ -4387,6 +4391,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, fw_control->len, 0) != 0) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Mem alloc failure\n")); + kfree(fw_control_context); return -ENOMEM; } } @@ -4401,8 +4406,10 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, fw_control_context->virtAddr = buffer; fw_control_context->len = fw_control->len; rc = pm8001_tag_alloc(pm8001_ha, &tag); - if (rc) + if (rc) { + kfree(fw_control_context); return rc; + } ccb = &pm8001_ha->ccb_info[tag]; ccb->fw_control_context = fw_control_context; ccb->ccb_tag = tag; -- cgit v1.2.3 From bc73905abf7701920fe687564ecd3c6b316b9a2e Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 4 Aug 2010 16:11:18 -0400 Subject: [SCSI] lpfc 8.3.16: SLI Additions, updates, and code cleanup - Remove unneeded Endian swap for Block Guard IOCB response - Add a check for mailbox active before issuing the heartbeat command - Correct heartbeat last_completion updates to avoid unneeded heartbeats - Add Security crypto support to CONFIG_PORT mailbox command - Add fips level and fips spec revision sysfs parameters - Remove duplicate setting of ext_byte_len fields in lpfc_bsg_issue_mbox - Switch call to memcpy_toio to __write32_copy to prevent unaligned 64 bit copy - Change log message 0318 from an error to a warning as it is not an error - Patch an incorrect call to lpfc_drain_txq on SLI-3 functions Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 3 +++ drivers/scsi/lpfc/lpfc_attr.c | 46 +++++++++++++++++++++++++++++++++- drivers/scsi/lpfc/lpfc_bsg.c | 9 ------- drivers/scsi/lpfc/lpfc_compat.h | 3 +-- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/lpfc/lpfc_hw.h | 26 +++++++++++--------- drivers/scsi/lpfc/lpfc_init.c | 53 +++++++++++++++++++++++++++------------- drivers/scsi/lpfc/lpfc_scsi.c | 8 +++--- drivers/scsi/lpfc/lpfc_sli.c | 29 +++++++++++++++++----- 9 files changed, 128 insertions(+), 51 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3482d5a5aed2..a50aa03b8ac1 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -775,6 +775,7 @@ struct lpfc_hba { uint8_t temp_sensor_support; /* Fields used for heart beat. */ unsigned long last_completion_time; + unsigned long skipped_hb; struct timer_list hb_tmofunc; uint8_t hb_outstanding; enum hba_temp_state over_temp_state; @@ -817,6 +818,8 @@ struct lpfc_hba { uint32_t iocb_cnt; uint32_t iocb_max; atomic_t sdev_cnt; + uint8_t fips_spec_rev; + uint8_t fips_level; }; static inline struct Scsi_Host * diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 868874c28f99..fac26e4445f9 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1238,6 +1238,44 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr, return strlen(buf); } +/** + * lpfc_fips_level_show - Return the current FIPS level for the HBA + * @dev: class unused variable. + * @attr: device attribute, not used. + * @buf: on return contains the module description text. + * + * Returns: size of formatted string. + **/ +static ssize_t +lpfc_fips_level_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + + return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level); +} + +/** + * lpfc_fips_rev_show - Return the FIPS Spec revision for the HBA + * @dev: class unused variable. + * @attr: device attribute, not used. + * @buf: on return contains the module description text. + * + * Returns: size of formatted string. + **/ +static ssize_t +lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + + return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev); +} + /** * lpfc_param_show - Return a cfg attribute value in decimal * @@ -1676,6 +1714,8 @@ static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); +static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); +static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); static char *lpfc_soft_wwn_key = "C99G71SL8032A"; @@ -3280,7 +3320,7 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); # - Default will result in registering capabilities for all profiles. # */ -unsigned int lpfc_prot_mask = SHOST_DIX_TYPE0_PROTECTION; +unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION; module_param(lpfc_prot_mask, uint, 0); MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); @@ -3385,6 +3425,8 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_iocb_hw, &dev_attr_txq_hw, &dev_attr_txcmplq_hw, + &dev_attr_lpfc_fips_level, + &dev_attr_lpfc_fips_rev, NULL, }; @@ -3411,6 +3453,8 @@ struct device_attribute *lpfc_vport_attrs[] = { &dev_attr_lpfc_max_scsicmpl_time, &dev_attr_lpfc_stat_data_ctrl, &dev_attr_lpfc_static_vport, + &dev_attr_lpfc_fips_level, + &dev_attr_lpfc_fips_rev, NULL, }; diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index d521569e6620..49d0cf99c24c 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -2722,15 +2722,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, mbox_req->inExtWLen * sizeof(uint32_t)); } - pmboxq->context2 = ext; - pmboxq->in_ext_byte_len = - mbox_req->inExtWLen * - sizeof(uint32_t); - pmboxq->out_ext_byte_len = - mbox_req->outExtWLen * - sizeof(uint32_t); - pmboxq->mbox_offset_word = - mbox_req->mbOffset; pmboxq->context2 = ext; pmboxq->in_ext_byte_len = mbox_req->inExtWLen * sizeof(uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h index a11f1ae7b98e..75e2e569dede 100644 --- a/drivers/scsi/lpfc/lpfc_compat.h +++ b/drivers/scsi/lpfc/lpfc_compat.h @@ -82,8 +82,7 @@ lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes) static inline void lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes) { - /* actually returns 1 byte past dest */ - memcpy_toio( dest, src, bytes); + __iowrite32_copy(dest, src, bytes); } static inline void diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 0639c994349c..efba65b368a8 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -588,7 +588,7 @@ lpfc_work_done(struct lpfc_hba *phba) (status & HA_RXMASK)); } - if (pring->txq_cnt) + if ((phba->sli_rev == LPFC_SLI_REV4) && pring->txq_cnt) lpfc_drain_txq(phba); /* * Turn on Ring interrupts diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index f5dbf2be3eab..897caa05e94d 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -2806,11 +2806,15 @@ typedef struct { uint32_t rsvd6; /* Reserved */ #ifdef __BIG_ENDIAN_BITFIELD - uint32_t rsvd7 : 16; /* Reserved */ + uint32_t fips_rev : 3; /* FIPS Spec Revision */ + uint32_t fips_level : 4; /* FIPS Level */ + uint32_t sec_err : 9; /* security crypto error */ uint32_t max_vpi : 16; /* Max number of virt N-Ports */ #else /* __LITTLE_ENDIAN */ uint32_t max_vpi : 16; /* Max number of virt N-Ports */ - uint32_t rsvd7 : 16; /* Reserved */ + uint32_t sec_err : 9; /* security crypto error */ + uint32_t fips_level : 4; /* FIPS Level */ + uint32_t fips_rev : 3; /* FIPS Spec Revision */ #endif } CONFIG_PORT_VAR; @@ -3441,63 +3445,63 @@ struct sli3_bg_fields { static inline uint32_t lpfc_bgs_get_bidir_bg_prof(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_BIDIR_BG_PROF_MASK) >> + return (bgstat & BGS_BIDIR_BG_PROF_MASK) >> BGS_BIDIR_BG_PROF_SHIFT; } static inline uint32_t lpfc_bgs_get_bidir_err_cond(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_BIDIR_ERR_COND_FLAGS_MASK) >> + return (bgstat & BGS_BIDIR_ERR_COND_FLAGS_MASK) >> BGS_BIDIR_ERR_COND_SHIFT; } static inline uint32_t lpfc_bgs_get_bg_prof(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_BG_PROFILE_MASK) >> + return (bgstat & BGS_BG_PROFILE_MASK) >> BGS_BG_PROFILE_SHIFT; } static inline uint32_t lpfc_bgs_get_invalid_prof(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_INVALID_PROF_MASK) >> + return (bgstat & BGS_INVALID_PROF_MASK) >> BGS_INVALID_PROF_SHIFT; } static inline uint32_t lpfc_bgs_get_uninit_dif_block(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_UNINIT_DIF_BLOCK_MASK) >> + return (bgstat & BGS_UNINIT_DIF_BLOCK_MASK) >> BGS_UNINIT_DIF_BLOCK_SHIFT; } static inline uint32_t lpfc_bgs_get_hi_water_mark_present(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_HI_WATER_MARK_PRESENT_MASK) >> + return (bgstat & BGS_HI_WATER_MARK_PRESENT_MASK) >> BGS_HI_WATER_MARK_PRESENT_SHIFT; } static inline uint32_t lpfc_bgs_get_reftag_err(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_REFTAG_ERR_MASK) >> + return (bgstat & BGS_REFTAG_ERR_MASK) >> BGS_REFTAG_ERR_SHIFT; } static inline uint32_t lpfc_bgs_get_apptag_err(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_APPTAG_ERR_MASK) >> + return (bgstat & BGS_APPTAG_ERR_MASK) >> BGS_APPTAG_ERR_SHIFT; } static inline uint32_t lpfc_bgs_get_guard_err(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_GUARD_ERR_MASK) >> + return (bgstat & BGS_GUARD_ERR_MASK) >> BGS_GUARD_ERR_SHIFT; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 2786ee3b605d..9244aa64b3be 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1032,27 +1032,46 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) /* If there is no heart beat outstanding, issue a heartbeat command */ if (phba->cfg_enable_hba_heartbeat) { if (!phba->hb_outstanding) { - pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); - if (!pmboxq) { - mod_timer(&phba->hb_tmofunc, - jiffies + HZ * LPFC_HB_MBOX_INTERVAL); - return; - } + if ((!(psli->sli_flag & LPFC_SLI_MBOX_ACTIVE)) && + (list_empty(&psli->mboxq))) { + pmboxq = mempool_alloc(phba->mbox_mem_pool, + GFP_KERNEL); + if (!pmboxq) { + mod_timer(&phba->hb_tmofunc, + jiffies + + HZ * LPFC_HB_MBOX_INTERVAL); + return; + } - lpfc_heart_beat(phba, pmboxq); - pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; - pmboxq->vport = phba->pport; - retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); + lpfc_heart_beat(phba, pmboxq); + pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; + pmboxq->vport = phba->pport; + retval = lpfc_sli_issue_mbox(phba, pmboxq, + MBX_NOWAIT); + + if (retval != MBX_BUSY && + retval != MBX_SUCCESS) { + mempool_free(pmboxq, + phba->mbox_mem_pool); + mod_timer(&phba->hb_tmofunc, + jiffies + + HZ * LPFC_HB_MBOX_INTERVAL); + return; + } + phba->skipped_hb = 0; + phba->hb_outstanding = 1; + } else if (time_before_eq(phba->last_completion_time, + phba->skipped_hb)) { + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "2857 Last completion time not " + " updated in %d ms\n", + jiffies_to_msecs(jiffies + - phba->last_completion_time)); + } else + phba->skipped_hb = jiffies; - if (retval != MBX_BUSY && retval != MBX_SUCCESS) { - mempool_free(pmboxq, phba->mbox_mem_pool); - mod_timer(&phba->hb_tmofunc, - jiffies + HZ * LPFC_HB_MBOX_INTERVAL); - return; - } mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); - phba->hb_outstanding = 1; return; } else { /* diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c818a7255962..2e51aa6b45b3 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1325,7 +1325,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); pde5->reftag = reftag; - /* Endian convertion if necessary for PDE5 */ + /* Endianness conversion if necessary for PDE5 */ pde5->word0 = cpu_to_le32(pde5->word0); pde5->reftag = cpu_to_le32(pde5->reftag); @@ -1347,7 +1347,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde6_ai, pde6, 1); bf_set(pde6_apptagval, pde6, apptagval); - /* Endian convertion if necessary for PDE6 */ + /* Endianness conversion if necessary for PDE6 */ pde6->word0 = cpu_to_le32(pde6->word0); pde6->word1 = cpu_to_le32(pde6->word1); pde6->word2 = cpu_to_le32(pde6->word2); @@ -1459,7 +1459,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); pde5->reftag = reftag; - /* Endian convertion if necessary for PDE5 */ + /* Endianness conversion if necessary for PDE5 */ pde5->word0 = cpu_to_le32(pde5->word0); pde5->reftag = cpu_to_le32(pde5->reftag); @@ -1479,7 +1479,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde6_ai, pde6, 1); bf_set(pde6_apptagval, pde6, apptagval); - /* Endian convertion if necessary for PDE6 */ + /* Endianness conversion if necessary for PDE6 */ pde6->word0 = cpu_to_le32(pde6->word0); pde6->word1 = cpu_to_le32(pde6->word1); pde6->word2 = cpu_to_le32(pde6->word2); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e758eae0d0fd..0ce9eb7ca4ee 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1046,7 +1046,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) } else spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_ERR,LOG_SLI, + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0318 Failed to allocate IOTAG.last IOTAG is %d\n", psli->last_iotag); @@ -3914,7 +3914,8 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED | LPFC_SLI3_CRP_ENABLED | - LPFC_SLI3_BG_ENABLED); + LPFC_SLI3_BG_ENABLED | + LPFC_SLI3_DSS_ENABLED); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0442 Adapter failed to init, mbxCmd x%x " @@ -3949,8 +3950,23 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) } else phba->max_vpi = 0; - if (pmb->u.mb.un.varCfgPort.gdss) + phba->fips_level = 0; + phba->fips_spec_rev = 0; + if (pmb->u.mb.un.varCfgPort.gdss) { phba->sli3_options |= LPFC_SLI3_DSS_ENABLED; + phba->fips_level = pmb->u.mb.un.varCfgPort.fips_level; + phba->fips_spec_rev = pmb->u.mb.un.varCfgPort.fips_rev; + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "2850 Security Crypto Active. FIPS x%d " + "(Spec Rev: x%d)", + phba->fips_level, phba->fips_spec_rev); + } + if (pmb->u.mb.un.varCfgPort.sec_err) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2856 Config Port Security Crypto " + "Error: x%x ", + pmb->u.mb.un.varCfgPort.sec_err); + } if (pmb->u.mb.un.varCfgPort.gerbm) phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED; if (pmb->u.mb.un.varCfgPort.gcrp) @@ -9040,6 +9056,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, switch (bf_get(lpfc_cqe_code, &cqevt)) { case CQE_CODE_COMPL_WQE: /* Process the WQ/RQ complete event */ + phba->last_completion_time = jiffies; workposted = lpfc_sli4_sp_handle_els_wcqe(phba, (struct lpfc_wcqe_complete *)&cqevt); break; @@ -9050,11 +9067,13 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, break; case CQE_CODE_XRI_ABORTED: /* Process the WQ XRI abort event */ + phba->last_completion_time = jiffies; workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, (struct sli4_wcqe_xri_aborted *)&cqevt); break; case CQE_CODE_RECEIVE: /* Process the RQ event */ + phba->last_completion_time = jiffies; workposted = lpfc_sli4_sp_handle_rcqe(phba, (struct lpfc_rcqe *)&cqevt); break; @@ -9276,7 +9295,6 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, { struct lpfc_wcqe_release wcqe; bool workposted = false; - unsigned long iflag; /* Copy the work queue CQE and convert endian order if needed */ lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe)); @@ -9285,9 +9303,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, switch (bf_get(lpfc_wcqe_c_code, &wcqe)) { case CQE_CODE_COMPL_WQE: /* Process the WQ complete event */ - spin_lock_irqsave(&phba->hbalock, iflag); phba->last_completion_time = jiffies; - spin_unlock_irqrestore(&phba->hbalock, iflag); lpfc_sli4_fp_handle_fcp_wcqe(phba, (struct lpfc_wcqe_complete *)&wcqe); break; @@ -9298,6 +9314,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, break; case CQE_CODE_XRI_ABORTED: /* Process the WQ XRI abort event */ + phba->last_completion_time = jiffies; workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, (struct sli4_wcqe_xri_aborted *)&wcqe); break; -- cgit v1.2.3 From 38b92ef89b0d5a255f2f812c623fcdec4e63a21c Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 4 Aug 2010 16:11:39 -0400 Subject: [SCSI] lpfc 8.3.16: FCoE Discovery and Failover Fixes - Add support for re-reg'ing changed VPI w/o unregister VPI - Copy WWN and state from old nodelist when target DID change. - Clean up old nodelist rport and put the nodelist when target DID change. - Clear the VFI_REGISTERED flag when UNREG_VFI completes. - Made both checks of port_state against LPFC_FLOGI and LPFC_FDISC non-inclusive for ignoring CVL events. - Added logic to stop retrying of the ongoing PLOGI and FDISC if transitioned back to the FCF rediscovery state in reaction to CVL. - Removed the dependency of scanning of all the available FCF table entries for bulding round-robin bitmap. - Use the lpfc_sli4_fcf_rr_read_fcf_rec() in responding to individual New FCF found event. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 76 +++++++++++++++++++++++++++++++++++--- drivers/scsi/lpfc/lpfc_hbadisc.c | 15 ++++++-- drivers/scsi/lpfc/lpfc_hw.h | 6 ++- drivers/scsi/lpfc/lpfc_init.c | 79 +++++++++++++++++++++++++--------------- drivers/scsi/lpfc/lpfc_mbox.c | 8 +++- drivers/scsi/lpfc/lpfc_sli.c | 7 +--- 6 files changed, 144 insertions(+), 47 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index afbed6bc31f0..8d09191c327e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -600,6 +600,14 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; spin_unlock_irq(shost->host_lock); } + } else if ((phba->sli_rev == LPFC_SLI_REV4) && + !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { + /* + * Driver needs to re-reg VPI in order for f/w + * to update the MAC address. + */ + lpfc_register_new_vport(phba, vport, ndlp); + return 0; } if (phba->sli_rev < LPFC_SLI_REV4) { @@ -801,9 +809,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, "2611 FLOGI failed on registered " - "FCF record fcf_index:%d, trying " - "to perform round robin failover\n", - phba->fcf.current_rec.fcf_indx); + "FCF record fcf_index(%d), status: " + "x%x/x%x, tmo:x%x, trying to perform " + "round robin failover\n", + phba->fcf.current_rec.fcf_indx, + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout); fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) { /* @@ -841,6 +852,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } } + /* FLOGI failure */ + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "2858 FLOGI failure Status:x%x/x%x TMO:x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout); + /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) goto out; @@ -1291,6 +1308,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, struct serv_parm *sp; uint8_t name[sizeof(struct lpfc_name)]; uint32_t rc, keepDID = 0; + int put_node; + int put_rport; /* Fabric nodes can have the same WWPN so we don't bother searching * by WWPN. Just return the ndlp that was given to us. @@ -1379,6 +1398,28 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, /* Two ndlps cannot have the same did */ ndlp->nlp_DID = keepDID; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); + /* Since we are swapping the ndlp passed in with the new one + * and the did has already been swapped, copy over the + * state and names. + */ + memcpy(&new_ndlp->nlp_portname, &ndlp->nlp_portname, + sizeof(struct lpfc_name)); + memcpy(&new_ndlp->nlp_nodename, &ndlp->nlp_nodename, + sizeof(struct lpfc_name)); + new_ndlp->nlp_state = ndlp->nlp_state; + /* Fix up the rport accordingly */ + rport = ndlp->rport; + if (rport) { + rdata = rport->dd_data; + put_node = rdata->pnode != NULL; + put_rport = ndlp->rport != NULL; + rdata->pnode = NULL; + ndlp->rport = NULL; + if (put_node) + lpfc_nlp_put(ndlp); + if (put_rport) + put_device(&rport->dev); + } } return new_ndlp; } @@ -2880,6 +2921,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, retry = 0; if (retry) { + if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_FDISC)) { + /* Stop retrying PLOGI and FDISC if in FCF discovery */ + if (phba->fcf.fcf_flag & FCF_DISCOVERY) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "2849 Stop retry ELS command " + "x%x to remote NPORT x%x, " + "Data: x%x x%x\n", cmd, did, + cmdiocb->retry, delay); + return 0; + } + } /* Retry ELS command to remote NPORT */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, @@ -6076,8 +6128,12 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if (mb->mbxStatus) { lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, - "0915 Register VPI failed: 0x%x\n", - mb->mbxStatus); + "0915 Register VPI failed : Status: x%x" + " upd bit: x%x \n", mb->mbxStatus, + mb->un.varRegVpi.upd); + if (phba->sli_rev == LPFC_SLI_REV4 && + mb->un.varRegVpi.upd) + goto mbox_err_exit ; switch (mb->mbxStatus) { case 0x11: /* unsupported feature */ @@ -6142,7 +6198,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } else lpfc_do_scr_ns_plogi(phba, vport); } - +mbox_err_exit: /* Now, we decrement the ndlp reference count held for this * callback function */ @@ -6387,6 +6443,14 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, else vport->fc_flag |= FC_LOGO_RCVD_DID_CHNG; spin_unlock_irq(shost->host_lock); + } else if ((phba->sli_rev == LPFC_SLI_REV4) && + !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { + /* + * Driver needs to re-reg VPI in order for f/w + * to update the MAC address. + */ + lpfc_register_new_vport(phba, vport, ndlp); + return ; } if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index efba65b368a8..1f62ea8c165d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1852,8 +1852,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) /* If in fast failover, mark it's completed */ - phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | - FCF_DISCOVERY); + phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; spin_unlock_irq(&phba->hbalock); lpfc_printf_log(phba, KERN_INFO, LOG_FIP, "2836 The new FCF record (x%x) " @@ -2651,7 +2650,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) spin_unlock_irq(&phba->hbalock); lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2778 Start FCF table scan at linkup\n"); - rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); if (rc) { @@ -2660,6 +2658,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) spin_unlock_irq(&phba->hbalock); goto out; } + /* Reset FCF roundrobin bmask for new discovery */ + memset(phba->fcf.fcf_rr_bmask, 0, + sizeof(*phba->fcf.fcf_rr_bmask)); } return; @@ -5097,6 +5098,7 @@ static void lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { struct lpfc_vport *vport = mboxq->vport; + struct Scsi_Host *shost = lpfc_shost_from_vport(vport); if (mboxq->u.mb.mbxStatus) { lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, @@ -5104,6 +5106,9 @@ lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) "HBA state x%x\n", mboxq->u.mb.mbxStatus, vport->port_state); } + spin_lock_irq(shost->host_lock); + phba->pport->fc_flag &= ~FC_VFI_REGISTERED; + spin_unlock_irq(shost->host_lock); mempool_free(mboxq, phba->mbox_mem_pool); return; } @@ -5285,6 +5290,10 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag |= FCF_INIT_DISC; spin_unlock_irq(&phba->hbalock); + + /* Reset FCF roundrobin bmask for new discovery */ + memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask)); + rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); if (rc) { diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 897caa05e94d..1676f61291e7 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -2291,7 +2291,8 @@ typedef struct { typedef struct { #ifdef __BIG_ENDIAN_BITFIELD uint32_t rsvd1; - uint32_t rsvd2:8; + uint32_t rsvd2:7; + uint32_t upd:1; uint32_t sid:24; uint32_t wwn[2]; uint32_t rsvd5; @@ -2300,7 +2301,8 @@ typedef struct { #else /* __LITTLE_ENDIAN */ uint32_t rsvd1; uint32_t sid:24; - uint32_t rsvd2:8; + uint32_t upd:1; + uint32_t rsvd2:7; uint32_t wwn[2]; uint32_t rsvd5; uint16_t vpi; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 9244aa64b3be..da9ba06ad583 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -3300,10 +3300,10 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport) if (!ndlp) return 0; } - if (phba->pport->port_state <= LPFC_FLOGI) + if (phba->pport->port_state < LPFC_FLOGI) return NULL; /* If virtual link is not yet instantiated ignore CVL */ - if (vport->port_state <= LPFC_FDISC) + if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)) return NULL; shost = lpfc_shost_from_vport(vport); if (!shost) @@ -3376,21 +3376,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, "evt_tag:x%x, fcf_index:x%x\n", acqe_fcoe->event_tag, acqe_fcoe->index); - /* If the FCF discovery is in progress, do nothing. */ - spin_lock_irq(&phba->hbalock); - if (phba->hba_flag & FCF_DISC_INPROGRESS) { - spin_unlock_irq(&phba->hbalock); - break; - } - /* If fast FCF failover rescan event is pending, do nothing */ - if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { - spin_unlock_irq(&phba->hbalock); - break; - } - spin_unlock_irq(&phba->hbalock); - - if ((phba->fcf.fcf_flag & FCF_DISCOVERY) && - !(phba->fcf.fcf_flag & FCF_REDISC_FOV)) { + if (phba->fcf.fcf_flag & FCF_DISCOVERY) { /* * During period of FCF discovery, read the FCF * table record indexed by the event to update @@ -3404,13 +3390,26 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, acqe_fcoe->index); rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index); } - /* If the FCF has been in discovered state, do nothing. */ + + /* If the FCF discovery is in progress, do nothing. */ spin_lock_irq(&phba->hbalock); + if (phba->hba_flag & FCF_DISC_INPROGRESS) { + spin_unlock_irq(&phba->hbalock); + break; + } + /* If fast FCF failover rescan event is pending, do nothing */ + if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { + spin_unlock_irq(&phba->hbalock); + break; + } + + /* If the FCF has been in discovered state, do nothing. */ if (phba->fcf.fcf_flag & FCF_SCAN_DONE) { spin_unlock_irq(&phba->hbalock); break; } spin_unlock_irq(&phba->hbalock); + /* Otherwise, scan the entire FCF table and re-discover SAN */ lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2770 Start FCF table scan due to new FCF " @@ -3436,13 +3435,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, "2549 FCF disconnected from network index 0x%x" " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag); - /* If the event is not for currently used fcf do nothing */ - if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) - break; - /* We request port to rediscover the entire FCF table for - * a fast recovery from case that the current FCF record - * is no longer valid if we are not in the middle of FCF - * failover process already. + /* + * If we are in the middle of FCF failover process, clear + * the corresponding FCF bit in the roundrobin bitmap. */ spin_lock_irq(&phba->hbalock); if (phba->fcf.fcf_flag & FCF_DISCOVERY) { @@ -3451,9 +3446,23 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index); break; } + spin_unlock_irq(&phba->hbalock); + + /* If the event is not for currently used fcf do nothing */ + if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) + break; + + /* + * Otherwise, request the port to rediscover the entire FCF + * table for a fast recovery from case that the current FCF + * is no longer valid as we are not in the middle of FCF + * failover process already. + */ + spin_lock_irq(&phba->hbalock); /* Mark the fast failover process in progress */ phba->fcf.fcf_flag |= FCF_DEAD_DISC; spin_unlock_irq(&phba->hbalock); + lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2771 Start FCF fast failover process due to " "FCF DEAD event: evt_tag:x%x, fcf_index:x%x " @@ -3473,12 +3482,16 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, * as a link down to FCF registration. */ lpfc_sli4_fcf_dead_failthrough(phba); - } else - /* Handling fast FCF failover to a DEAD FCF event - * is considered equalivant to receiving CVL to all - * vports. + } else { + /* Reset FCF roundrobin bmask for new discovery */ + memset(phba->fcf.fcf_rr_bmask, 0, + sizeof(*phba->fcf.fcf_rr_bmask)); + /* + * Handling fast FCF failover to a DEAD FCF event is + * considered equalivant to receiving CVL to all vports. */ lpfc_sli4_perform_all_vport_cvl(phba); + } break; case LPFC_FCOE_EVENT_TYPE_CVL: lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, @@ -3553,7 +3566,13 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, * the current registered FCF entry. */ lpfc_retry_pport_discovery(phba); - } + } else + /* + * Reset FCF roundrobin bmask for new + * discovery. + */ + memset(phba->fcf.fcf_rr_bmask, 0, + sizeof(*phba->fcf.fcf_rr_bmask)); } break; default: diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 9c2c7c7140c7..0dfa310cd609 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -815,9 +815,15 @@ void lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) { MAILBOX_t *mb = &pmb->u.mb; + struct lpfc_hba *phba = vport->phba; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); - + /* + * Set the re-reg VPI bit for f/w to update the MAC address. + */ + if ((phba->sli_rev == LPFC_SLI_REV4) && + !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) + mb->un.varRegVpi.upd = 1; mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; mb->un.varRegVpi.sid = vport->fc_myDID; mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 0ce9eb7ca4ee..fb8905f893f5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -12295,12 +12295,9 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) spin_lock_irq(&phba->hbalock); phba->hba_flag |= FCF_DISC_INPROGRESS; spin_unlock_irq(&phba->hbalock); - /* Reset FCF round robin index bmask for new scan */ - if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) { - memset(phba->fcf.fcf_rr_bmask, 0, - sizeof(*phba->fcf.fcf_rr_bmask)); + /* Reset eligible FCF count for new scan */ + if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) phba->fcf.eligible_fcf_cnt = 0; - } error = 0; } fail_fcf_scan: -- cgit v1.2.3 From 161155519c27773b8f35ee3d7a1b49acfc9eee73 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 4 Aug 2010 16:12:12 -0400 Subject: [SCSI] lpfc 8.3.16: Change LPFC driver version to 8.3.16 Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index d28830af71d8..61afb3420a96 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.15" +#define LPFC_DRIVER_VERSION "8.3.16" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" -- cgit v1.2.3 From d5da3040d798df4bbb62579b97f8b6b83749da22 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 5 Aug 2010 16:38:31 -0500 Subject: [SCSI] ibmvfc: Fix rport add/delete race resulting in oops Commit 43c8da907ccc656935d1085701f4db83385d8a59 introduced a race condition which can occur when adding/deleting rports. There are two possible threads now that can be deleting rports in the ibmvfc driver, which can result in list_del being called twice, resulting in an oops. This patch adds a new state to the ibmvfc_target struct to indicate the target has been removed from the list and is in the process of being deleted. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 8 ++++++++ drivers/scsi/ibmvscsi/ibmvfc.h | 1 + 2 files changed, 9 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index bd96cecaa619..a13db5908426 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -433,6 +433,9 @@ static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, { switch (tgt->action) { case IBMVFC_TGT_ACTION_DEL_RPORT: + if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) + tgt->action = action; + case IBMVFC_TGT_ACTION_DELETED_RPORT: break; default: if (action == IBMVFC_TGT_ACTION_DEL_RPORT) @@ -4193,11 +4196,15 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { tgt_dbg(tgt, "Deleting rport\n"); list_del(&tgt->queue); + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); spin_unlock_irqrestore(vhost->host->host_lock, flags); fc_remote_port_delete(rport); del_timer_sync(&tgt->timer); kref_put(&tgt->kref, ibmvfc_release_tgt); return; + } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + return; } if (rport) { @@ -4297,6 +4304,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) rport = tgt->rport; tgt->rport = NULL; list_del(&tgt->queue); + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); spin_unlock_irqrestore(vhost->host->host_lock, flags); if (rport) fc_remote_port_delete(rport); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index d7e8dcd90650..af48172112fa 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -597,6 +597,7 @@ enum ibmvfc_target_action { IBMVFC_TGT_ACTION_INIT, IBMVFC_TGT_ACTION_INIT_WAIT, IBMVFC_TGT_ACTION_DEL_RPORT, + IBMVFC_TGT_ACTION_DELETED_RPORT, }; struct ibmvfc_target { -- cgit v1.2.3 From d2fab5cf3979c55f802c96616daf96e9e8de1c80 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 5 Aug 2010 16:38:34 -0500 Subject: [SCSI] ibmvfc: Fix terminate_rport_io The ibmvfc driver was incorrectly obtaining a scsi_target pointer from an fc_rport. The way it is coded ensures that ibmvfc's terminate_rport_io handler does absolutely nothing. Fix this up to iterate through affected devices differently, sending cancel and abort task set as appropriate. Without this patch, fast_io_fail_tmo is broken for ibmvfc. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 372 ++++++++++++++++++++++------------------- drivers/scsi/ibmvscsi/ibmvfc.h | 1 + 2 files changed, 204 insertions(+), 169 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index a13db5908426..9f75a6d519a2 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2039,95 +2039,108 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) } /** - * ibmvfc_abort_task_set - Abort outstanding commands to the device - * @sdev: scsi device to abort commands - * - * This sends an Abort Task Set to the VIOS for the specified device. This does - * NOT send any cancel to the VIOS. That must be done separately. + * ibmvfc_match_rport - Match function for specified remote port + * @evt: ibmvfc event struct + * @device: device to match (rport) * * Returns: - * 0 on success / other on failure + * 1 if event matches rport / 0 if event does not match rport **/ -static int ibmvfc_abort_task_set(struct scsi_device *sdev) +static int ibmvfc_match_rport(struct ibmvfc_event *evt, void *rport) { - struct ibmvfc_host *vhost = shost_priv(sdev->host); - struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); - struct ibmvfc_cmd *tmf; - struct ibmvfc_event *evt, *found_evt; - union ibmvfc_iu rsp_iu; - struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; - int rsp_rc = -EBUSY; - unsigned long flags; - int rsp_code = 0; + struct fc_rport *cmd_rport; - spin_lock_irqsave(vhost->host->host_lock, flags); - found_evt = NULL; - list_for_each_entry(evt, &vhost->sent, queue) { - if (evt->cmnd && evt->cmnd->device == sdev) { - found_evt = evt; - break; - } - } - - if (!found_evt) { - if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) - sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); - spin_unlock_irqrestore(vhost->host->host_lock, flags); - return 0; - } - - if (vhost->state == IBMVFC_ACTIVE) { - evt = ibmvfc_get_event(vhost); - ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); - - tmf = &evt->iu.cmd; - memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); - tmf->resp.len = sizeof(tmf->rsp); - tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; - tmf->payload_len = sizeof(tmf->iu); - tmf->resp_len = sizeof(tmf->rsp); - tmf->cancel_key = (unsigned long)sdev->hostdata; - tmf->tgt_scsi_id = rport->port_id; - int_to_scsilun(sdev->lun, &tmf->iu.lun); - tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); - tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; - evt->sync_iu = &rsp_iu; - - init_completion(&evt->comp); - rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); + if (evt->cmnd) { + cmd_rport = starget_to_rport(scsi_target(evt->cmnd->device)); + if (cmd_rport == rport) + return 1; } + return 0; +} - spin_unlock_irqrestore(vhost->host->host_lock, flags); +/** + * ibmvfc_match_target - Match function for specified target + * @evt: ibmvfc event struct + * @device: device to match (starget) + * + * Returns: + * 1 if event matches starget / 0 if event does not match starget + **/ +static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) +{ + if (evt->cmnd && scsi_target(evt->cmnd->device) == device) + return 1; + return 0; +} - if (rsp_rc != 0) { - sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); - return -EIO; - } +/** + * ibmvfc_match_lun - Match function for specified LUN + * @evt: ibmvfc event struct + * @device: device to match (sdev) + * + * Returns: + * 1 if event matches sdev / 0 if event does not match sdev + **/ +static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) +{ + if (evt->cmnd && evt->cmnd->device == device) + return 1; + return 0; +} - sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); - wait_for_completion(&evt->comp); +/** + * ibmvfc_wait_for_ops - Wait for ops to complete + * @vhost: ibmvfc host struct + * @device: device to match (starget or sdev) + * @match: match function + * + * Returns: + * SUCCESS / FAILED + **/ +static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, + int (*match) (struct ibmvfc_event *, void *)) +{ + struct ibmvfc_event *evt; + DECLARE_COMPLETION_ONSTACK(comp); + int wait; + unsigned long flags; + signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; - if (rsp_iu.cmd.status) - rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); + ENTER; + do { + wait = 0; + spin_lock_irqsave(vhost->host->host_lock, flags); + list_for_each_entry(evt, &vhost->sent, queue) { + if (match(evt, device)) { + evt->eh_comp = ∁ + wait++; + } + } + spin_unlock_irqrestore(vhost->host->host_lock, flags); - if (rsp_code) { - if (fc_rsp->flags & FCP_RSP_LEN_VALID) - rsp_code = fc_rsp->data.info.rsp_code; + if (wait) { + timeout = wait_for_completion_timeout(&comp, timeout); - sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " - "flags: %x fcp_rsp: %x, scsi_status: %x\n", - ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), - rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, - fc_rsp->scsi_status); - rsp_rc = -EIO; - } else - sdev_printk(KERN_INFO, sdev, "Abort successful\n"); + if (!timeout) { + wait = 0; + spin_lock_irqsave(vhost->host->host_lock, flags); + list_for_each_entry(evt, &vhost->sent, queue) { + if (match(evt, device)) { + evt->eh_comp = NULL; + wait++; + } + } + spin_unlock_irqrestore(vhost->host->host_lock, flags); + if (wait) + dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); + LEAVE; + return wait ? FAILED : SUCCESS; + } + } + } while (wait); - spin_lock_irqsave(vhost->host->host_lock, flags); - ibmvfc_free_event(evt); - spin_unlock_irqrestore(vhost->host->host_lock, flags); - return rsp_rc; + LEAVE; + return SUCCESS; } /** @@ -2215,88 +2228,130 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) } /** - * ibmvfc_match_target - Match function for specified target + * ibmvfc_match_key - Match function for specified cancel key * @evt: ibmvfc event struct - * @device: device to match (starget) + * @key: cancel key to match * * Returns: - * 1 if event matches starget / 0 if event does not match starget + * 1 if event matches key / 0 if event does not match key **/ -static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) +static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) { - if (evt->cmnd && scsi_target(evt->cmnd->device) == device) - return 1; - return 0; -} + unsigned long cancel_key = (unsigned long)key; -/** - * ibmvfc_match_lun - Match function for specified LUN - * @evt: ibmvfc event struct - * @device: device to match (sdev) - * - * Returns: - * 1 if event matches sdev / 0 if event does not match sdev - **/ -static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) -{ - if (evt->cmnd && evt->cmnd->device == device) + if (evt->crq.format == IBMVFC_CMD_FORMAT && + evt->iu.cmd.cancel_key == cancel_key) return 1; return 0; } /** - * ibmvfc_wait_for_ops - Wait for ops to complete - * @vhost: ibmvfc host struct - * @device: device to match (starget or sdev) - * @match: match function + * ibmvfc_abort_task_set - Abort outstanding commands to the device + * @sdev: scsi device to abort commands + * + * This sends an Abort Task Set to the VIOS for the specified device. This does + * NOT send any cancel to the VIOS. That must be done separately. * * Returns: - * SUCCESS / FAILED + * 0 on success / other on failure **/ -static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, - int (*match) (struct ibmvfc_event *, void *)) +static int ibmvfc_abort_task_set(struct scsi_device *sdev) { - struct ibmvfc_event *evt; - DECLARE_COMPLETION_ONSTACK(comp); - int wait; - unsigned long flags; - signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; + struct ibmvfc_host *vhost = shost_priv(sdev->host); + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); + struct ibmvfc_cmd *tmf; + struct ibmvfc_event *evt, *found_evt; + union ibmvfc_iu rsp_iu; + struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; + int rc, rsp_rc = -EBUSY; + unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT; + int rsp_code = 0; - ENTER; - do { - wait = 0; - spin_lock_irqsave(vhost->host->host_lock, flags); - list_for_each_entry(evt, &vhost->sent, queue) { - if (match(evt, device)) { - evt->eh_comp = ∁ - wait++; - } + spin_lock_irqsave(vhost->host->host_lock, flags); + found_evt = NULL; + list_for_each_entry(evt, &vhost->sent, queue) { + if (evt->cmnd && evt->cmnd->device == sdev) { + found_evt = evt; + break; } + } + + if (!found_evt) { + if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) + sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); spin_unlock_irqrestore(vhost->host->host_lock, flags); + return 0; + } - if (wait) { - timeout = wait_for_completion_timeout(&comp, timeout); + if (vhost->state == IBMVFC_ACTIVE) { + evt = ibmvfc_get_event(vhost); + ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); - if (!timeout) { - wait = 0; - spin_lock_irqsave(vhost->host->host_lock, flags); - list_for_each_entry(evt, &vhost->sent, queue) { - if (match(evt, device)) { - evt->eh_comp = NULL; - wait++; - } - } - spin_unlock_irqrestore(vhost->host->host_lock, flags); - if (wait) - dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); - LEAVE; - return wait ? FAILED : SUCCESS; - } + tmf = &evt->iu.cmd; + memset(tmf, 0, sizeof(*tmf)); + tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); + tmf->resp.len = sizeof(tmf->rsp); + tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; + tmf->payload_len = sizeof(tmf->iu); + tmf->resp_len = sizeof(tmf->rsp); + tmf->cancel_key = (unsigned long)sdev->hostdata; + tmf->tgt_scsi_id = rport->port_id; + int_to_scsilun(sdev->lun, &tmf->iu.lun); + tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); + tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; + evt->sync_iu = &rsp_iu; + + init_completion(&evt->comp); + rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); + } + + spin_unlock_irqrestore(vhost->host->host_lock, flags); + + if (rsp_rc != 0) { + sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); + return -EIO; + } + + sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); + timeout = wait_for_completion_timeout(&evt->comp, timeout); + + if (!timeout) { + rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); + if (!rc) { + rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); + if (rc == SUCCESS) + rc = 0; } - } while (wait); - LEAVE; - return SUCCESS; + if (rc) { + sdev_printk(KERN_INFO, sdev, "Cancel failed, resetting host\n"); + ibmvfc_reset_host(vhost); + rsp_rc = 0; + goto out; + } + } + + if (rsp_iu.cmd.status) + rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); + + if (rsp_code) { + if (fc_rsp->flags & FCP_RSP_LEN_VALID) + rsp_code = fc_rsp->data.info.rsp_code; + + sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " + "flags: %x fcp_rsp: %x, scsi_status: %x\n", + ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), + rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, + fc_rsp->scsi_status); + rsp_rc = -EIO; + } else + sdev_printk(KERN_INFO, sdev, "Abort successful\n"); + +out: + spin_lock_irqsave(vhost->host->host_lock, flags); + ibmvfc_free_event(evt); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + return rsp_rc; } /** @@ -2353,18 +2408,6 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) return rc; } -/** - * ibmvfc_dev_cancel_all_abts - Device iterated cancel all function - * @sdev: scsi device struct - * @data: return code - * - **/ -static void ibmvfc_dev_cancel_all_abts(struct scsi_device *sdev, void *data) -{ - unsigned long *rc = data; - *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); -} - /** * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function * @sdev: scsi device struct @@ -2377,18 +2420,6 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_TGT_RESET); } -/** - * ibmvfc_dev_abort_all - Device iterated abort task set function - * @sdev: scsi device struct - * @data: return code - * - **/ -static void ibmvfc_dev_abort_all(struct scsi_device *sdev, void *data) -{ - unsigned long *rc = data; - *rc |= ibmvfc_abort_task_set(sdev); -} - /** * ibmvfc_eh_target_reset_handler - Reset the target * @cmd: scsi command struct @@ -2443,19 +2474,22 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) **/ static void ibmvfc_terminate_rport_io(struct fc_rport *rport) { - struct scsi_target *starget = to_scsi_target(&rport->dev); - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct Scsi_Host *shost = rport_to_shost(rport); struct ibmvfc_host *vhost = shost_priv(shost); - unsigned long cancel_rc = 0; - unsigned long abort_rc = 0; - int rc = FAILED; + struct fc_rport *dev_rport; + struct scsi_device *sdev; + unsigned long rc; ENTER; - starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_abts); - starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all); + shost_for_each_device(sdev, shost) { + dev_rport = starget_to_rport(scsi_target(sdev)); + if (dev_rport != rport) + continue; + ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); + ibmvfc_abort_task_set(sdev); + } - if (!cancel_rc && !abort_rc) - rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); + rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport); if (rc == FAILED) ibmvfc_issue_fc_host_lip(shost); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index af48172112fa..d47cefc22ed3 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -38,6 +38,7 @@ #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \ (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT) #define IBMVFC_INIT_TIMEOUT 120 +#define IBMVFC_ABORT_TIMEOUT 8 #define IBMVFC_ABORT_WAIT_TIMEOUT 40 #define IBMVFC_MAX_REQUESTS_DEFAULT 100 -- cgit v1.2.3 From 7e41dfdaf11a45ab4f4dfc444a7d42bf79dd9356 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 5 Aug 2010 16:38:36 -0500 Subject: [SCSI] ibmvfc: Driver version 1.0.9 Bump driver version. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index d47cefc22ed3..608af394c8cf 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -29,8 +29,8 @@ #include "viosrp.h" #define IBMVFC_NAME "ibmvfc" -#define IBMVFC_DRIVER_VERSION "1.0.8" -#define IBMVFC_DRIVER_DATE "(June 17, 2010)" +#define IBMVFC_DRIVER_VERSION "1.0.9" +#define IBMVFC_DRIVER_DATE "(August 5, 2010)" #define IBMVFC_DEFAULT_TIMEOUT 60 #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 -- cgit v1.2.3 From b375a612ad931264b71cf162d692b4420f2578a9 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 17 Jun 2010 14:58:21 +0200 Subject: aha1532: remove ISA_DMA_THRESHOLD usage We can safely remove ISA_DMA_THRESHOLD usage in aha1542. aha1542 uses ISA_DMA_THRESHOLD to see if: - the buffers in scatter/list are below 16MB. - scsi_host is below 16MB. Both checkings were added in the ancient times but aren't necessary nowadays since we properly bounce the buffers and allocate scsi_host below 16MB with non-zero unchecked_isa_dma. Signed-off-by: FUJITA Tomonori Acked-by: James Bottomley Signed-off-by: Jens Axboe --- drivers/scsi/aha1542.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 2a8cf137f609..4f785f254c1f 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -52,22 +52,6 @@ #define SCSI_BUF_PA(address) isa_virt_to_bus(address) #define SCSI_SG_PA(sgent) (isa_page_to_bus(sg_page((sgent))) + (sgent)->offset) -static void BAD_SG_DMA(Scsi_Cmnd * SCpnt, - struct scatterlist *sgp, - int nseg, - int badseg) -{ - printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%llx length %u\n", - badseg, nseg, sg_virt(sgp), - (unsigned long long)SCSI_SG_PA(sgp), - sgp->length); - - /* - * Not safe to continue. - */ - panic("Buffer at physical address > 16Mb used for aha1542"); -} - #include #ifdef DEBUG @@ -691,8 +675,6 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) } scsi_for_each_sg(SCpnt, sg, sg_count, i) { any2scsi(cptr[i].dataptr, SCSI_SG_PA(sg)); - if (SCSI_SG_PA(sg) + sg->length - 1 > ISA_DMA_THRESHOLD) - BAD_SG_DMA(SCpnt, scsi_sglist(SCpnt), sg_count, i); any2scsi(cptr[i].datalen, sg->length); }; any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain)); @@ -1133,16 +1115,9 @@ static int __init aha1542_detect(struct scsi_host_template * tpnt) release_region(bases[indx], 4); continue; } - /* For now we do this - until kmalloc is more intelligent - we are resigned to stupid hacks like this */ - if (SCSI_BUF_PA(shpnt) >= ISA_DMA_THRESHOLD) { - printk(KERN_ERR "Invalid address for shpnt with 1542.\n"); - goto unregister; - } if (!aha1542_test_port(bases[indx], shpnt)) goto unregister; - base_io = bases[indx]; /* Set the Bus on/off-times as not to ruin floppy performance */ -- cgit v1.2.3 From 33659ebbae262228eef4e0fe990f393d1f0ed941 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 7 Aug 2010 18:17:56 +0200 Subject: block: remove wrappers for request type/flags Remove all the trivial wrappers for the cmd_type and cmd_flags fields in struct requests. This allows much easier grepping for different request types instead of unwinding through macros. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-barrier.c | 7 ++-- block/blk-core.c | 13 ++++---- block/blk-exec.c | 2 +- block/blk-merge.c | 4 +-- block/blk.h | 6 ++-- block/cfq-iosched.c | 19 ++++++----- block/elevator.c | 16 +++++---- drivers/ata/libata-scsi.c | 2 +- drivers/block/cciss.c | 49 ++++++++++++++++----------- drivers/block/hd.c | 2 +- drivers/block/mg_disk.c | 4 +-- drivers/block/nbd.c | 2 +- drivers/block/osdblk.c | 3 +- drivers/block/paride/pd.c | 2 +- drivers/block/ps3disk.c | 2 +- drivers/block/ub.c | 8 ++--- drivers/block/viodasd.c | 2 +- drivers/block/virtio_blk.c | 15 +++++---- drivers/block/xd.c | 2 +- drivers/block/xen-blkfront.c | 4 +-- drivers/block/xsysace.c | 2 +- drivers/cdrom/gdrom.c | 2 +- drivers/cdrom/viocd.c | 2 +- drivers/ide/ide-atapi.c | 17 ++++++---- drivers/ide/ide-cd.c | 66 ++++++++++++++++++++----------------- drivers/ide/ide-disk.c | 2 +- drivers/ide/ide-eh.c | 5 +-- drivers/ide/ide-floppy.c | 25 +++++++++----- drivers/ide/ide-io.c | 8 ++--- drivers/ide/ide-pm.c | 8 ++--- drivers/ide/ide-tape.c | 3 +- drivers/md/dm.c | 10 +++--- drivers/memstick/core/mspro_block.c | 3 +- drivers/message/i2o/i2o_block.c | 2 +- drivers/mmc/card/queue.c | 2 +- drivers/mtd/mtd_blkdevs.c | 4 +-- drivers/scsi/scsi_error.c | 10 +++--- drivers/scsi/scsi_lib.c | 5 +-- drivers/scsi/sd.c | 12 +++---- drivers/scsi/sun3_NCR5380.c | 2 +- drivers/scsi/sun3_scsi.c | 2 +- drivers/scsi/sun3_scsi_vme.c | 2 +- drivers/staging/hv/blkvsc_drv.c | 8 +++-- include/linux/blkdev.h | 41 ++++++++--------------- include/linux/blktrace_api.h | 2 +- include/trace/events/block.h | 15 ++++++--- kernel/trace/blktrace.c | 10 +++--- 47 files changed, 236 insertions(+), 198 deletions(-) (limited to 'drivers/scsi') diff --git a/block/blk-barrier.c b/block/blk-barrier.c index 0d710c9d403b..74e404393172 100644 --- a/block/blk-barrier.c +++ b/block/blk-barrier.c @@ -79,7 +79,7 @@ unsigned blk_ordered_req_seq(struct request *rq) * * http://thread.gmane.org/gmane.linux.kernel/537473 */ - if (!blk_fs_request(rq)) + if (rq->cmd_type != REQ_TYPE_FS) return QUEUE_ORDSEQ_DRAIN; if ((rq->cmd_flags & REQ_ORDERED_COLOR) == @@ -236,7 +236,8 @@ static inline bool start_ordered(struct request_queue *q, struct request **rqp) bool blk_do_ordered(struct request_queue *q, struct request **rqp) { struct request *rq = *rqp; - const int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq); + const int is_barrier = rq->cmd_type == REQ_TYPE_FS && + (rq->cmd_flags & REQ_HARDBARRIER); if (!q->ordseq) { if (!is_barrier) @@ -261,7 +262,7 @@ bool blk_do_ordered(struct request_queue *q, struct request **rqp) */ /* Special requests are not subject to ordering rules. */ - if (!blk_fs_request(rq) && + if (rq->cmd_type != REQ_TYPE_FS && rq != &q->pre_flush_rq && rq != &q->post_flush_rq) return true; diff --git a/block/blk-core.c b/block/blk-core.c index b4131d29148c..dca43a31e725 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -184,7 +184,7 @@ void blk_dump_rq_flags(struct request *rq, char *msg) printk(KERN_INFO " bio %p, biotail %p, buffer %p, len %u\n", rq->bio, rq->biotail, rq->buffer, blk_rq_bytes(rq)); - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { printk(KERN_INFO " cdb: "); for (bit = 0; bit < BLK_MAX_CDB; bit++) printk("%02x ", rq->cmd[bit]); @@ -1796,7 +1796,7 @@ struct request *blk_peek_request(struct request_queue *q) * sees this request (possibly after * requeueing). Notify IO scheduler. */ - if (blk_sorted_rq(rq)) + if (rq->cmd_flags & REQ_SORTED) elv_activate_rq(q, rq); /* @@ -1984,10 +1984,11 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) * TODO: tj: This is too subtle. It would be better to let * low level drivers do what they see fit. */ - if (blk_fs_request(req)) + if (req->cmd_type == REQ_TYPE_FS) req->errors = 0; - if (error && (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))) { + if (error && req->cmd_type == REQ_TYPE_FS && + !(req->cmd_flags & REQ_QUIET)) { printk(KERN_ERR "end_request: I/O error, dev %s, sector %llu\n", req->rq_disk ? req->rq_disk->disk_name : "?", (unsigned long long)blk_rq_pos(req)); @@ -2074,7 +2075,7 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) req->buffer = bio_data(req->bio); /* update sector only for requests with clear definition of sector */ - if (blk_fs_request(req) || blk_discard_rq(req)) + if (req->cmd_type == REQ_TYPE_FS || (req->cmd_flags & REQ_DISCARD)) req->__sector += total_bytes >> 9; /* mixed attributes always follow the first bio */ @@ -2127,7 +2128,7 @@ static void blk_finish_request(struct request *req, int error) BUG_ON(blk_queued_rq(req)); - if (unlikely(laptop_mode) && blk_fs_request(req)) + if (unlikely(laptop_mode) && req->cmd_type == REQ_TYPE_FS) laptop_io_completion(&req->q->backing_dev_info); blk_delete_timer(req); diff --git a/block/blk-exec.c b/block/blk-exec.c index 49557e91f0da..e1672f14840e 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -57,7 +57,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, __elv_add_request(q, rq, where, 1); __generic_unplug_device(q); /* the queue is stopped so it won't be plugged+unplugged */ - if (blk_pm_resume_request(rq)) + if (rq->cmd_type == REQ_TYPE_PM_RESUME) q->request_fn(q); spin_unlock_irq(q->queue_lock); } diff --git a/block/blk-merge.c b/block/blk-merge.c index 5e7dc9973458..87e4fb7d0e98 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -226,7 +226,7 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, { unsigned short max_sectors; - if (unlikely(blk_pc_request(req))) + if (unlikely(req->cmd_type == REQ_TYPE_BLOCK_PC)) max_sectors = queue_max_hw_sectors(q); else max_sectors = queue_max_sectors(q); @@ -250,7 +250,7 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req, { unsigned short max_sectors; - if (unlikely(blk_pc_request(req))) + if (unlikely(req->cmd_type == REQ_TYPE_BLOCK_PC)) max_sectors = queue_max_hw_sectors(q); else max_sectors = queue_max_sectors(q); diff --git a/block/blk.h b/block/blk.h index 5ee3d7e72feb..6e7dc87141e4 100644 --- a/block/blk.h +++ b/block/blk.h @@ -161,8 +161,10 @@ static inline int blk_cpu_to_group(int cpu) */ static inline int blk_do_io_stat(struct request *rq) { - return rq->rq_disk && blk_rq_io_stat(rq) && - (blk_fs_request(rq) || blk_discard_rq(rq)); + return rq->rq_disk && + (rq->cmd_flags & REQ_IO_STAT) && + (rq->cmd_type == REQ_TYPE_FS || + (rq->cmd_flags & REQ_DISCARD)); } #endif diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 7982b830db58..d4edeb8fceb8 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -646,9 +646,10 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2, return rq1; else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) return rq2; - if (rq_is_meta(rq1) && !rq_is_meta(rq2)) + if ((rq1->cmd_flags & REQ_RW_META) && !(rq2->cmd_flags & REQ_RW_META)) return rq1; - else if (rq_is_meta(rq2) && !rq_is_meta(rq1)) + else if ((rq2->cmd_flags & REQ_RW_META) && + !(rq1->cmd_flags & REQ_RW_META)) return rq2; s1 = blk_rq_pos(rq1); @@ -1484,7 +1485,7 @@ static void cfq_remove_request(struct request *rq) cfqq->cfqd->rq_queued--; cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq), rq_is_sync(rq)); - if (rq_is_meta(rq)) { + if (rq->cmd_flags & REQ_RW_META) { WARN_ON(!cfqq->meta_pending); cfqq->meta_pending--; } @@ -3176,7 +3177,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, * So both queues are sync. Let the new request get disk time if * it's a metadata request and the current queue is doing regular IO. */ - if (rq_is_meta(rq) && !cfqq->meta_pending) + if ((rq->cmd_flags & REQ_RW_META) && !cfqq->meta_pending) return true; /* @@ -3230,7 +3231,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct cfq_io_context *cic = RQ_CIC(rq); cfqd->rq_queued++; - if (rq_is_meta(rq)) + if (rq->cmd_flags & REQ_RW_META) cfqq->meta_pending++; cfq_update_io_thinktime(cfqd, cic); @@ -3365,7 +3366,8 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) unsigned long now; now = jiffies; - cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d", !!rq_noidle(rq)); + cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d", + !!(rq->cmd_flags & REQ_NOIDLE)); cfq_update_hw_tag(cfqd); @@ -3419,11 +3421,12 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) cfq_slice_expired(cfqd, 1); else if (sync && cfqq_empty && !cfq_close_cooperator(cfqd, cfqq)) { - cfqd->noidle_tree_requires_idle |= !rq_noidle(rq); + cfqd->noidle_tree_requires_idle |= + !(rq->cmd_flags & REQ_NOIDLE); /* * Idling is enabled for SYNC_WORKLOAD. * SYNC_NOIDLE_WORKLOAD idles at the end of the tree - * only if we processed at least one !rq_noidle request + * only if we processed at least one !REQ_NOIDLE request */ if (cfqd->serving_type == SYNC_WORKLOAD || cfqd->noidle_tree_requires_idle diff --git a/block/elevator.c b/block/elevator.c index 923a9139106c..aa99b59c03d6 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -428,7 +428,8 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) list_for_each_prev(entry, &q->queue_head) { struct request *pos = list_entry_rq(entry); - if (blk_discard_rq(rq) != blk_discard_rq(pos)) + if ((rq->cmd_flags & REQ_DISCARD) != + (pos->cmd_flags & REQ_DISCARD)) break; if (rq_data_dir(rq) != rq_data_dir(pos)) break; @@ -558,7 +559,7 @@ void elv_requeue_request(struct request_queue *q, struct request *rq) */ if (blk_account_rq(rq)) { q->in_flight[rq_is_sync(rq)]--; - if (blk_sorted_rq(rq)) + if (rq->cmd_flags & REQ_SORTED) elv_deactivate_rq(q, rq); } @@ -644,7 +645,8 @@ void elv_insert(struct request_queue *q, struct request *rq, int where) break; case ELEVATOR_INSERT_SORT: - BUG_ON(!blk_fs_request(rq) && !blk_discard_rq(rq)); + BUG_ON(rq->cmd_type != REQ_TYPE_FS && + !(rq->cmd_flags & REQ_DISCARD)); rq->cmd_flags |= REQ_SORTED; q->nr_sorted++; if (rq_mergeable(rq)) { @@ -716,7 +718,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where, /* * toggle ordered color */ - if (blk_barrier_rq(rq)) + if (rq->cmd_flags & REQ_HARDBARRIER) q->ordcolor ^= 1; /* @@ -729,7 +731,8 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where, * this request is scheduling boundary, update * end_sector */ - if (blk_fs_request(rq) || blk_discard_rq(rq)) { + if (rq->cmd_type == REQ_TYPE_FS || + (rq->cmd_flags & REQ_DISCARD)) { q->end_sector = rq_end_sector(rq); q->boundary_rq = rq; } @@ -843,7 +846,8 @@ void elv_completed_request(struct request_queue *q, struct request *rq) */ if (blk_account_rq(rq)) { q->in_flight[rq_is_sync(rq)]--; - if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn) + if ((rq->cmd_flags & REQ_SORTED) && + e->ops->elevator_completed_req_fn) e->ops->elevator_completed_req_fn(q, rq); } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index a54273d2c3c6..a5c08b082edb 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1111,7 +1111,7 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) */ static int atapi_drain_needed(struct request *rq) { - if (likely(!blk_pc_request(rq))) + if (likely(rq->cmd_type != REQ_TYPE_BLOCK_PC)) return 0; if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_RW)) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 10a0268a1f92..11b377762b8e 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1783,7 +1783,7 @@ static void cciss_softirq_done(struct request *rq) #endif /* CCISS_DEBUG */ /* set the residual count for pc requests */ - if (blk_pc_request(rq)) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) rq->resid_len = cmd->err_info->ResidualCnt; blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO); @@ -2983,7 +2983,7 @@ static inline int evaluate_target_status(ctlr_info_t *h, driver_byte = DRIVER_OK; msg_byte = cmd->err_info->CommandStatus; /* correct? seems too device specific */ - if (blk_pc_request(cmd->rq)) + if (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) host_byte = DID_PASSTHROUGH; else host_byte = DID_OK; @@ -2992,7 +2992,7 @@ static inline int evaluate_target_status(ctlr_info_t *h, host_byte, driver_byte); if (cmd->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) { - if (!blk_pc_request(cmd->rq)) + if (cmd->rq->cmd_type != REQ_TYPE_BLOCK_PC) printk(KERN_WARNING "cciss: cmd %p " "has SCSI Status 0x%x\n", cmd, cmd->err_info->ScsiStatus); @@ -3002,15 +3002,17 @@ static inline int evaluate_target_status(ctlr_info_t *h, /* check the sense key */ sense_key = 0xf & cmd->err_info->SenseInfo[2]; /* no status or recovered error */ - if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq)) + if (((sense_key == 0x0) || (sense_key == 0x1)) && + (cmd->rq->cmd_type != REQ_TYPE_BLOCK_PC)) error_value = 0; if (check_for_unit_attention(h, cmd)) { - *retry_cmd = !blk_pc_request(cmd->rq); + *retry_cmd = !(cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC); return 0; } - if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */ + /* Not SG_IO or similar? */ + if (cmd->rq->cmd_type != REQ_TYPE_BLOCK_PC) { if (error_value != 0) printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION" " sense key = 0x%x\n", cmd, sense_key); @@ -3052,7 +3054,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, rq->errors = evaluate_target_status(h, cmd, &retry_cmd); break; case CMD_DATA_UNDERRUN: - if (blk_fs_request(cmd->rq)) { + if (cmd->rq->cmd_type == REQ_TYPE_FS) { printk(KERN_WARNING "cciss: cmd %p has" " completed with data underrun " "reported\n", cmd); @@ -3060,7 +3062,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, } break; case CMD_DATA_OVERRUN: - if (blk_fs_request(cmd->rq)) + if (cmd->rq->cmd_type == REQ_TYPE_FS) printk(KERN_WARNING "cciss: cmd %p has" " completed with data overrun " "reported\n", cmd); @@ -3070,42 +3072,48 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, "reported invalid\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_PROTOCOL_ERR: printk(KERN_WARNING "cciss: cmd %p has " "protocol error \n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_HARDWARE_ERR: printk(KERN_WARNING "cciss: cmd %p had " " hardware error\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_CONNECTION_LOST: printk(KERN_WARNING "cciss: cmd %p had " "connection lost\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_ABORTED: printk(KERN_WARNING "cciss: cmd %p was " "aborted\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ABORT); break; case CMD_ABORT_FAILED: printk(KERN_WARNING "cciss: cmd %p reports " "abort failed\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_UNSOLICITED_ABORT: printk(KERN_WARNING "cciss%d: unsolicited " @@ -3121,13 +3129,15 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, "many times\n", h->ctlr, cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ABORT); break; case CMD_TIMEOUT: printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; default: printk(KERN_WARNING "cciss: cmd %p returned " @@ -3135,7 +3145,8 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, cmd->err_info->CommandStatus); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); } after_error_processing: @@ -3294,7 +3305,7 @@ static void do_cciss_request(struct request_queue *q) c->Header.SGList = h->max_cmd_sgentries; set_performant_mode(h, c); - if (likely(blk_fs_request(creq))) { + if (likely(creq->cmd_type == REQ_TYPE_FS)) { if(h->cciss_read == CCISS_READ_10) { c->Request.CDB[1] = 0; c->Request.CDB[2] = (start_blk >> 24) & 0xff; /* MSB */ @@ -3324,7 +3335,7 @@ static void do_cciss_request(struct request_queue *q) c->Request.CDB[13]= blk_rq_sectors(creq) & 0xff; c->Request.CDB[14] = c->Request.CDB[15] = 0; } - } else if (blk_pc_request(creq)) { + } else if (creq->cmd_type == REQ_TYPE_BLOCK_PC) { c->Request.CDBLen = creq->cmd_len; memcpy(c->Request.CDB, creq->cmd, BLK_MAX_CDB); } else { diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 81c78b3ce2df..30ec6b37424e 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -627,7 +627,7 @@ repeat: req_data_dir(req) == READ ? "read" : "writ", cyl, head, sec, nsect, req->buffer); #endif - if (blk_fs_request(req)) { + if (req->cmd_type == REQ_TYPE_FS) { switch (rq_data_dir(req)) { case READ: hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_READ, diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index 28db925dbdad..b82c5ce5e9df 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c @@ -670,7 +670,7 @@ static void mg_request_poll(struct request_queue *q) break; } - if (unlikely(!blk_fs_request(host->req))) { + if (unlikely(host->req->cmd_type != REQ_TYPE_FS)) { mg_end_request_cur(host, -EIO); continue; } @@ -756,7 +756,7 @@ static void mg_request(struct request_queue *q) continue; } - if (unlikely(!blk_fs_request(req))) { + if (unlikely(req->cmd_type != REQ_TYPE_FS)) { mg_end_request_cur(host, -EIO); continue; } diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 218d091f3c52..2e74e7d475ca 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -448,7 +448,7 @@ static void nbd_clear_que(struct nbd_device *lo) static void nbd_handle_req(struct nbd_device *lo, struct request *req) { - if (!blk_fs_request(req)) + if (req->cmd_type != REQ_TYPE_FS) goto error_out; nbd_cmd(req) = NBD_CMD_READ; diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c index 6cd8b705b11b..819002ba3433 100644 --- a/drivers/block/osdblk.c +++ b/drivers/block/osdblk.c @@ -310,7 +310,8 @@ static void osdblk_rq_fn(struct request_queue *q) break; /* filter out block requests we don't understand */ - if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) { + if (rq->cmd_type != REQ_TYPE_FS && + !(rq->cmd_flags & REQ_HARDBARRIER)) { blk_end_request_all(rq, 0); continue; } diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index c1e5cd029b23..4e8b9bff3abe 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -439,7 +439,7 @@ static char *pd_buf; /* buffer for request in progress */ static enum action do_pd_io_start(void) { - if (blk_special_request(pd_req)) { + if (pd_req->cmd_type == REQ_TYPE_SPECIAL) { phase = pd_special; return pd_special(); } diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 3b419e3fffa1..5f208c0bf156 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -196,7 +196,7 @@ static void ps3disk_do_request(struct ps3_storage_device *dev, dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); while ((req = blk_fetch_request(q))) { - if (blk_fs_request(req)) { + if (req->cmd_type == REQ_TYPE_FS) { if (ps3disk_submit_request_sg(dev, req)) break; } else if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 0536b5b29adc..034b34440ffa 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -648,7 +648,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) return 0; } - if (lun->changed && !blk_pc_request(rq)) { + if (lun->changed && rq->cmd_type != REQ_TYPE_BLOCK_PC) blk_start_request(rq); ub_end_rq(rq, SAM_STAT_CHECK_CONDITION); return 0; @@ -684,7 +684,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) } urq->nsg = n_elem; - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { ub_cmd_build_packet(sc, lun, cmd, urq); } else { ub_cmd_build_block(sc, lun, cmd, urq); @@ -781,7 +781,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) rq = urq->rq; if (cmd->error == 0) { - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { if (cmd->act_len >= rq->resid_len) rq->resid_len = 0; else @@ -795,7 +795,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) } } } else { - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); rq->sense_len = UB_SENSE_SIZE; diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 788d93882ab9..5663d3c284c8 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -361,7 +361,7 @@ static void do_viodasd_request(struct request_queue *q) if (req == NULL) return; /* check that request contains a valid command */ - if (!blk_fs_request(req)) { + if (req->cmd_type != REQ_TYPE_FS) { viodasd_end_request(req, -EIO, blk_rq_sectors(req)); continue; } diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 258bc2ae2885..774144334ece 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -65,13 +65,16 @@ static void blk_done(struct virtqueue *vq) break; } - if (blk_pc_request(vbr->req)) { + switch (vbr->req->cmd_type) { + case REQ_TYPE_BLOCK_PC: vbr->req->resid_len = vbr->in_hdr.residual; vbr->req->sense_len = vbr->in_hdr.sense_len; vbr->req->errors = vbr->in_hdr.errors; - } - if (blk_special_request(vbr->req)) + break; + case REQ_TYPE_SPECIAL: vbr->req->errors = (error != 0); + break; + } __blk_end_request_all(vbr->req, error); list_del(&vbr->list); @@ -123,7 +126,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, BUG(); } - if (blk_barrier_rq(vbr->req)) + if (vbr->req->cmd_flags & REQ_HARDBARRIER) vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; sg_set_buf(&vblk->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr)); @@ -134,12 +137,12 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, * block, and before the normal inhdr we put the sense data and the * inhdr with additional status information before the normal inhdr. */ - if (blk_pc_request(vbr->req)) + if (vbr->req->cmd_type == REQ_TYPE_BLOCK_PC) sg_set_buf(&vblk->sg[out++], vbr->req->cmd, vbr->req->cmd_len); num = blk_rq_map_sg(q, vbr->req, vblk->sg + out); - if (blk_pc_request(vbr->req)) { + if (vbr->req->cmd_type == REQ_TYPE_BLOCK_PC) { sg_set_buf(&vblk->sg[num + out + in++], vbr->req->sense, 96); sg_set_buf(&vblk->sg[num + out + in++], &vbr->in_hdr, sizeof(vbr->in_hdr)); diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 18a80ff57ce8..4dc298376098 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -322,7 +322,7 @@ static void do_xd_request (struct request_queue * q) int res = -EIO; int retry; - if (!blk_fs_request(req)) + if (req->cmd_type != REQ_TYPE_FS) { goto done; if (block + count > get_capacity(req->rq_disk)) goto done; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 82ed403147c0..495533e66542 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -238,7 +238,7 @@ static int blkif_queue_request(struct request *req) ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; - if (blk_barrier_rq(req)) + if (req->cmd_flags & REQ_HARDBARRIER) ring_req->operation = BLKIF_OP_WRITE_BARRIER; ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); @@ -309,7 +309,7 @@ static void do_blkif_request(struct request_queue *rq) blk_start_request(req); - if (!blk_fs_request(req)) { + if (req->cmd_type != REQ_TYPE_FS) { __blk_end_request_all(req, -EIO); continue; } diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index a7b83c0a7eb5..ac278ac908d5 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -465,7 +465,7 @@ struct request *ace_get_next_request(struct request_queue * q) struct request *req; while ((req = blk_peek_request(q)) != NULL) { - if (blk_fs_request(req)) + if (req->cmd_type == REQ_TYPE_FS) break; blk_start_request(req); __blk_end_request_all(req, -EIO); diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 03c71f7698cb..7c05ddc63ae8 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -643,7 +643,7 @@ static void gdrom_request(struct request_queue *rq) struct request *req; while ((req = blk_fetch_request(rq)) != NULL) { - if (!blk_fs_request(req)) { + if (req->cmd_type != REQ_TYPE_FS) { printk(KERN_DEBUG "GDROM: Non-fs request ignored\n"); __blk_end_request_all(req, -EIO); continue; diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 451cd7071b1d..14e420168764 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -298,7 +298,7 @@ static void do_viocd_request(struct request_queue *q) struct request *req; while ((rwreq == 0) && ((req = blk_fetch_request(q)) != NULL)) { - if (!blk_fs_request(req)) + if (req->cmd_type != REQ_TYPE_FS) __blk_end_request_all(req, -EIO); else if (send_request(req) < 0) { printk(VIOCD_KERN_WARNING diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index f9daffd7d0e3..3117a894d20e 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -190,7 +190,7 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) BUG_ON(sense_len > sizeof(*sense)); - if (blk_sense_request(rq) || drive->sense_rq_armed) + if (rq->cmd_type == REQ_TYPE_SENSE || drive->sense_rq_armed) return; memset(sense, 0, sizeof(*sense)); @@ -307,13 +307,16 @@ EXPORT_SYMBOL_GPL(ide_cd_expiry); int ide_cd_get_xferlen(struct request *rq) { - if (blk_fs_request(rq)) + switch (rq->cmd_type) + case REQ_TYPE_FS: return 32768; - else if (blk_sense_request(rq) || blk_pc_request(rq) || - rq->cmd_type == REQ_TYPE_ATA_PC) + case REQ_TYPE_SENSE: + case REQ_TYPE_BLOCK_PC: + case REQ_TYPE_ATA_PC: return blk_rq_bytes(rq); - else + default: return 0; + } } EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); @@ -474,12 +477,12 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) if (uptodate == 0) drive->failed_pc = NULL; - if (blk_special_request(rq)) { + if (rq->cmd_type == REQ_TYPE_SPECIAL) rq->errors = 0; error = 0; } else { - if (blk_fs_request(rq) == 0 && uptodate <= 0) { + if (req->cmd_type != REQ_TYPE_FS && uptodate <= 0) { if (rq->errors == 0) rq->errors = -EIO; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 64207df8da82..26a3688de467 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -176,7 +176,7 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, if (!sense->valid) break; if (failed_command == NULL || - !blk_fs_request(failed_command)) + failed_command->cmd_type != REQ_TYPE_FS) break; sector = (sense->information[0] << 24) | (sense->information[1] << 16) | @@ -292,7 +292,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) "stat 0x%x", rq->cmd[0], rq->cmd_type, err, stat); - if (blk_sense_request(rq)) { + if (rq->cmd_type == REQ_TYPE_SENSE) { /* * We got an error trying to get sense info from the drive * (probably while trying to recover from a former error). @@ -303,7 +303,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) } /* if we have an error, pass CHECK_CONDITION as the SCSI status byte */ - if (blk_pc_request(rq) && !rq->errors) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !rq->errors) rq->errors = SAM_STAT_CHECK_CONDITION; if (blk_noretry_request(rq)) @@ -311,13 +311,14 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) switch (sense_key) { case NOT_READY: - if (blk_fs_request(rq) && rq_data_dir(rq) == WRITE) { + if (rq->cmd_type == REQ_TYPE_FS && rq_data_dir(rq) == WRITE) { if (ide_cd_breathe(drive, rq)) return 1; } else { cdrom_saw_media_change(drive); - if (blk_fs_request(rq) && !blk_rq_quiet(rq)) + if (rq->cmd_type == REQ_TYPE_FS && + !(rq->cmd_flags & REQ_QUIET)) { printk(KERN_ERR PFX "%s: tray open\n", drive->name); } @@ -326,7 +327,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) case UNIT_ATTENTION: cdrom_saw_media_change(drive); - if (blk_fs_request(rq) == 0) + if (rq->cmd_type != REQ_TYPE_FS) return 0; /* @@ -352,7 +353,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in retrying after an illegal request or data * protect error. */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "command error", stat); do_end_request = 1; break; @@ -361,20 +362,20 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in re-trying a zillion times on a bad sector. * If we got here the error is not correctable. */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "media error " "(bad sector)", stat); do_end_request = 1; break; case BLANK_CHECK: /* disk appears blank? */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "media error (blank)", stat); do_end_request = 1; break; default: - if (blk_fs_request(rq) == 0) + if (req->cmd_type != REQ_TYPE_FS) break; if (err & ~ATA_ABORTED) { /* go to the default handler for other errors */ @@ -385,7 +386,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) do_end_request = 1; } - if (blk_fs_request(rq) == 0) { + if (rq->cmd_type != REQ_TYPE_FS) { rq->cmd_flags |= REQ_FAILED; do_end_request = 1; } @@ -525,7 +526,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) ide_expiry_t *expiry = NULL; int dma_error = 0, dma, thislen, uptodate = 0; int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0; - int sense = blk_sense_request(rq); + int sense = (rq->cmd_type == REQ_TYPE_SENSE); unsigned int timeout; u16 len; u8 ireason, stat; @@ -568,7 +569,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) ide_read_bcount_and_ireason(drive, &len, &ireason); - thislen = blk_fs_request(rq) ? len : cmd->nleft; + thislen = (rq->cmd_type == REQ_TYPE_FS) ? len : cmd->nleft; if (thislen > len) thislen = len; @@ -577,7 +578,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) /* If DRQ is clear, the command has completed. */ if ((stat & ATA_DRQ) == 0) { - if (blk_fs_request(rq)) { + if (rq->cmd_type == REQ_TYPE_FS) { /* * If we're not done reading/writing, complain. * Otherwise, complete the command normally. @@ -591,7 +592,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) rq->cmd_flags |= REQ_FAILED; uptodate = 0; } - } else if (!blk_pc_request(rq)) { + } else if (rq->cmd_type != REQ_TYPE_BLOCK_PC) { ide_cd_request_sense_fixup(drive, cmd); uptodate = cmd->nleft ? 0 : 1; @@ -640,7 +641,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) /* pad, if necessary */ if (len > 0) { - if (blk_fs_request(rq) == 0 || write == 0) + if (rq->cmd_type != REQ_TYPE_FS || write == 0) ide_pad_transfer(drive, write, len); else { printk(KERN_ERR PFX "%s: confused, missing data\n", @@ -649,11 +650,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } } - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { timeout = rq->timeout; } else { timeout = ATAPI_WAIT_PC; - if (!blk_fs_request(rq)) + if (rq->cmd_type != REQ_TYPE_FS) expiry = ide_cd_expiry; } @@ -662,7 +663,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) return ide_started; out_end: - if (blk_pc_request(rq) && rc == 0) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC && rc == 0) { rq->resid_len = 0; blk_end_request_all(rq, 0); hwif->rq = NULL; @@ -670,7 +671,7 @@ out_end: if (sense && uptodate) ide_cd_complete_failed_rq(drive, rq); - if (blk_fs_request(rq)) { + if (rq->cmd_type == REQ_TYPE_FS) { if (cmd->nleft == 0) uptodate = 1; } else { @@ -682,7 +683,7 @@ out_end: ide_cd_error_cmd(drive, cmd); /* make sure it's fully ended */ - if (blk_fs_request(rq) == 0) { + if (rq->cmd_type != REQ_TYPE_FS) { rq->resid_len -= cmd->nbytes - cmd->nleft; if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE)) rq->resid_len += cmd->last_xfer_len; @@ -742,7 +743,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) ide_debug_log(IDE_DBG_PC, "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x", rq->cmd[0], rq->cmd_type); - if (blk_pc_request(rq)) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) rq->cmd_flags |= REQ_QUIET; else rq->cmd_flags &= ~REQ_FAILED; @@ -783,21 +784,26 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, if (drive->debug_mask & IDE_DBG_RQ) blk_dump_rq_flags(rq, "ide_cd_do_request"); - if (blk_fs_request(rq)) { + switch (rq->cmd_type) { + case REQ_TYPE_FS: if (cdrom_start_rw(drive, rq) == ide_stopped) goto out_end; - } else if (blk_sense_request(rq) || blk_pc_request(rq) || - rq->cmd_type == REQ_TYPE_ATA_PC) { + break; + case REQ_TYPE_SENSE: + case REQ_TYPE_BLOCK_PC: + case REQ_TYPE_ATA_PC: if (!rq->timeout) rq->timeout = ATAPI_WAIT_PC; cdrom_do_block_pc(drive, rq); - } else if (blk_special_request(rq)) { + break; + case REQ_TYPE_SPECIAL: /* right now this can only be a reset... */ uptodate = 1; goto out_end; - } else + default: BUG(); + } /* prepare sense request for this command */ ide_prep_sense(drive, rq); @@ -809,7 +815,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, cmd.rq = rq; - if (blk_fs_request(rq) || blk_rq_bytes(rq)) { + if (rq->cmd_type == REQ_TYPE_FS || blk_rq_bytes(rq)) { ide_init_sg_cmd(&cmd, blk_rq_bytes(rq)); ide_map_sg(drive, &cmd); } @@ -1365,9 +1371,9 @@ static int ide_cdrom_prep_pc(struct request *rq) static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq) { - if (blk_fs_request(rq)) + if (rq->cmd_type == REQ_TYPE_FS) return ide_cdrom_prep_fs(q, rq); - else if (blk_pc_request(rq)) + else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) return ide_cdrom_prep_pc(rq); return 0; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 33d65039cce9..df3d91ba1c96 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -184,7 +184,7 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, ide_hwif_t *hwif = drive->hwif; BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED); - BUG_ON(!blk_fs_request(rq)); + BUG_ON(rq->cmd_type != REQ_TYPE_FS); ledtrig_ide_activity(); diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c index e9abf2c3c335..c0aa93fb7a60 100644 --- a/drivers/ide/ide-eh.c +++ b/drivers/ide/ide-eh.c @@ -122,7 +122,7 @@ ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat) return ide_stopped; /* retry only "normal" I/O: */ - if (!blk_fs_request(rq)) { + if (rq->cmd_type != REQ_TYPE_FS) { if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { struct ide_cmd *cmd = rq->special; @@ -146,7 +146,8 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) { struct request *rq = drive->hwif->rq; - if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) { + if (rq && rq->cmd_type == REQ_TYPE_SPECIAL && + rq->cmd[0] == REQ_DRIVE_RESET) { if (err <= 0 && rq->errors == 0) rq->errors = -EIO; ide_complete_rq(drive, err ? err : 0, blk_rq_bytes(rq)); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 4713bdca20b6..c7d0737bb18a 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -73,7 +73,7 @@ static int ide_floppy_callback(ide_drive_t *drive, int dsc) drive->failed_pc = NULL; if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 || - (rq && blk_pc_request(rq))) + (rq && rq->cmd_type == REQ_TYPE_BLOCK_PC)) uptodate = 1; /* FIXME */ else if (pc->c[0] == GPCMD_REQUEST_SENSE) { @@ -98,7 +98,7 @@ static int ide_floppy_callback(ide_drive_t *drive, int dsc) "Aborting request!\n"); } - if (blk_special_request(rq)) + if (rq->cmd_type == REQ_TYPE_SPECIAL) rq->errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL; return uptodate; @@ -247,14 +247,16 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, } else printk(KERN_ERR PFX "%s: I/O error\n", drive->name); - if (blk_special_request(rq)) { + if (rq->cmd_type == REQ_TYPE_SPECIAL) { rq->errors = 0; ide_complete_rq(drive, 0, blk_rq_bytes(rq)); return ide_stopped; } else goto out_end; } - if (blk_fs_request(rq)) { + + switch (rq->cmd_type) { + case REQ_TYPE_FS: if (((long)blk_rq_pos(rq) % floppy->bs_factor) || (blk_rq_sectors(rq) % floppy->bs_factor)) { printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", @@ -263,13 +265,18 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, } pc = &floppy->queued_pc; idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); - } else if (blk_special_request(rq) || blk_sense_request(rq)) { + break; + case REQ_TYPE_SPECIAL: + case REQ_TYPE_SENSE: pc = (struct ide_atapi_pc *)rq->special; - } else if (blk_pc_request(rq)) { + break; + case REQ_TYPE_BLOCK_PC: pc = &floppy->queued_pc; idefloppy_blockpc_cmd(floppy, pc, rq); - } else + break; + default: BUG(); + } ide_prep_sense(drive, rq); @@ -280,7 +287,7 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, cmd.rq = rq; - if (blk_fs_request(rq) || blk_rq_bytes(rq)) { + if (rq->cmd_type == REQ_TYPE_FS || blk_rq_bytes(rq)) { ide_init_sg_cmd(&cmd, blk_rq_bytes(rq)); ide_map_sg(drive, &cmd); } @@ -290,7 +297,7 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, return ide_floppy_issue_pc(drive, &cmd, pc); out_end: drive->failed_pc = NULL; - if (blk_fs_request(rq) == 0 && rq->errors == 0) + if (rq->cmd_type != REQ_TYPE_FS && rq->errors == 0) rq->errors = -EIO; ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); return ide_stopped; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 172ac9218154..9304a7e54d9e 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -135,7 +135,7 @@ EXPORT_SYMBOL(ide_complete_rq); void ide_kill_rq(ide_drive_t *drive, struct request *rq) { - u8 drv_req = blk_special_request(rq) && rq->rq_disk; + u8 drv_req = (rq->cmd_type == REQ_TYPE_SPECIAL) && rq->rq_disk; u8 media = drive->media; drive->failed_pc = NULL; @@ -145,7 +145,7 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq) } else { if (media == ide_tape) rq->errors = IDE_DRV_ERROR_GENERAL; - else if (blk_fs_request(rq) == 0 && rq->errors == 0) + else if (rq->cmd_type != REQ_TYPE_FS && rq->errors == 0) rq->errors = -EIO; } @@ -307,7 +307,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; - BUG_ON(!blk_rq_started(rq)); + BUG_ON(!(rq->cmd_flags & REQ_STARTED)); #ifdef DEBUG printk("%s: start_request: current=0x%08lx\n", @@ -353,7 +353,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) pm->pm_step == IDE_PM_COMPLETED) ide_complete_pm_rq(drive, rq); return startstop; - } else if (!rq->rq_disk && blk_special_request(rq)) + } else if (!rq->rq_disk && rq->cmd_type == REQ_TYPE_SPECIAL) { /* * TODO: Once all ULDs have been modified to * check for specific op codes rather than diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index 1c08311b0a0e..92406097efeb 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c @@ -191,10 +191,10 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) #ifdef DEBUG_PM printk("%s: completing PM request, %s\n", drive->name, - blk_pm_suspend_request(rq) ? "suspend" : "resume"); + (rq->cmd_type == REQ_TYPE_PM_SUSPEND) ? "suspend" : "resume"); #endif spin_lock_irqsave(q->queue_lock, flags); - if (blk_pm_suspend_request(rq)) + if (rq->cmd_type == REQ_TYPE_PM_SUSPEND) blk_stop_queue(q); else drive->dev_flags &= ~IDE_DFLAG_BLOCKED; @@ -210,11 +210,11 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) { struct request_pm_state *pm = rq->special; - if (blk_pm_suspend_request(rq) && + if (rq->cmd_type == REQ_TYPE_PM_SUSPEND && pm->pm_step == IDE_PM_START_SUSPEND) /* Mark drive blocked when starting the suspend sequence. */ drive->dev_flags |= IDE_DFLAG_BLOCKED; - else if (blk_pm_resume_request(rq) && + else if (rq->cmd_type == REQ_TYPE_PM_RESUME && pm->pm_step == IDE_PM_START_RESUME) { /* * The first thing we do on wakeup is to wait for BSY bit to diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index b07232880ec9..635fd72d4728 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -577,7 +577,8 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, rq->cmd[0], (unsigned long long)blk_rq_pos(rq), blk_rq_sectors(rq)); - BUG_ON(!(blk_special_request(rq) || blk_sense_request(rq))); + BUG_ON(!(rq->cmd_type == REQ_TYPE_SPECIAL || + rq->cmd_type == REQ_TYPE_SENSE)); /* Retry a failed packet command */ if (drive->failed_pc && drive->pc->c[0] == REQUEST_SENSE) { diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d21e1284604f..1e0e6dd51501 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -792,12 +792,12 @@ static void dm_end_request(struct request *clone, int error) { int rw = rq_data_dir(clone); int run_queue = 1; - bool is_barrier = blk_barrier_rq(clone); + bool is_barrier = clone->cmd_flags & REQ_HARDBARRIER; struct dm_rq_target_io *tio = clone->end_io_data; struct mapped_device *md = tio->md; struct request *rq = tio->orig; - if (blk_pc_request(rq) && !is_barrier) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !is_barrier) { rq->errors = clone->errors; rq->resid_len = clone->resid_len; @@ -844,7 +844,7 @@ void dm_requeue_unmapped_request(struct request *clone) struct request_queue *q = rq->q; unsigned long flags; - if (unlikely(blk_barrier_rq(clone))) { + if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) { /* * Barrier clones share an original request. * Leave it to dm_end_request(), which handles this special @@ -943,7 +943,7 @@ static void dm_complete_request(struct request *clone, int error) struct dm_rq_target_io *tio = clone->end_io_data; struct request *rq = tio->orig; - if (unlikely(blk_barrier_rq(clone))) { + if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) { /* * Barrier clones share an original request. So can't use * softirq_done with the original. @@ -972,7 +972,7 @@ void dm_kill_unmapped_request(struct request *clone, int error) struct dm_rq_target_io *tio = clone->end_io_data; struct request *rq = tio->orig; - if (unlikely(blk_barrier_rq(clone))) { + if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) { /* * Barrier clones share an original request. * Leave it to dm_end_request(), which handles this special diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 8327e248520a..56645408d225 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -805,7 +805,8 @@ static void mspro_block_start(struct memstick_dev *card) static int mspro_block_prepare_req(struct request_queue *q, struct request *req) { - if (!blk_fs_request(req) && !blk_pc_request(req)) { + if (req->cmd_type != REQ_TYPE_FS && + req->cmd_type != REQ_TYPE_BLOCK_PC) { blk_dump_rq_flags(req, "MSPro unsupported request"); return BLKPREP_KILL; } diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index fc593fbab696..108f0c2b2bfd 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -883,7 +883,7 @@ static void i2o_block_request_fn(struct request_queue *q) if (!req) break; - if (blk_fs_request(req)) { + if (req->cmd_type == REQ_TYPE_FS) { struct i2o_block_delayed_request *dreq; struct i2o_block_request *ireq = req->special; unsigned int queue_depth; diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index d6ded247d941..ec92bcbdeddb 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -32,7 +32,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) /* * We only like normal block requests. */ - if (!blk_fs_request(req)) { + if (req->cmd_type != REQ_TYPE_FS) { blk_dump_rq_flags(req, "MMC bad request"); return BLKPREP_KILL; } diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 03e19c1965cc..475af42745cb 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -73,14 +73,14 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, buf = req->buffer; - if (!blk_fs_request(req)) + if (req->cmd_type != REQ_TYPE_FS) return -EIO; if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(req->rq_disk)) return -EIO; - if (blk_discard_rq(req)) + if (req->cmd_flags & REQ_DISCARD) return tr->discard(dev, block, nsect); switch(rq_data_dir(req)) { diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a5d630f5f519..1b88af89d0c7 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -307,7 +307,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) (sshdr.asc == 0x04) && (sshdr.ascq == 0x02)) return FAILED; - if (blk_barrier_rq(scmd->request)) + if (scmd->request->cmd_flags & REQ_HARDBARRIER) /* * barrier requests should always retry on UA * otherwise block will get a spurious error @@ -1318,16 +1318,16 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd) case DID_OK: break; case DID_BUS_BUSY: - return blk_failfast_transport(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT); case DID_PARITY: - return blk_failfast_dev(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_DEV); case DID_ERROR: if (msg_byte(scmd->result) == COMMAND_COMPLETE && status_byte(scmd->result) == RESERVATION_CONFLICT) return 0; /* fall through */ case DID_SOFT_ERROR: - return blk_failfast_driver(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER); } switch (status_byte(scmd->result)) { @@ -1336,7 +1336,7 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd) * assume caller has checked sense and determinted * the check condition was retryable. */ - return blk_failfast_dev(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_DEV); } return 0; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1646fe7cbd4b..5f1160841b0e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -722,7 +722,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) sense_deferred = scsi_sense_is_deferred(&sshdr); } - if (blk_pc_request(req)) { /* SG_IO ioctl from block level */ + if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ req->errors = result; if (result) { if (sense_valid && req->sense) { @@ -757,7 +757,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } } - BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */ + /* no bidi support for !REQ_TYPE_BLOCK_PC yet */ + BUG_ON(blk_bidi_rq(req)); /* * Next deal with any sectors which we were able to correctly diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8802e48bc063..a3fdf4dc59da 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -485,7 +485,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * Discard request come in as REQ_TYPE_FS but we turn them into * block PC requests to make life easier. */ - if (blk_discard_rq(rq)) + if (rq->cmd_flags & REQ_DISCARD) ret = sd_prepare_discard(rq); if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { @@ -636,7 +636,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD; SCpnt->cmnd[7] = 0x18; SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32; - SCpnt->cmnd[10] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[10] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); /* LBA */ SCpnt->cmnd[12] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; @@ -661,7 +661,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[31] = (unsigned char) this_count & 0xff; } else if (block > 0xffffffff) { SCpnt->cmnd[0] += READ_16 - READ_6; - SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; @@ -682,7 +682,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) this_count = 0xffff; SCpnt->cmnd[0] += READ_10 - READ_6; - SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; @@ -691,7 +691,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; } else { - if (unlikely(blk_fua_rq(rq))) { + if (unlikely(rq->cmd_flags & REQ_FUA)) { /* * This happens only if this drive failed * 10byte rw command with ILLEGAL_REQUEST @@ -1112,7 +1112,7 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) u64 bad_lba; int info_valid; - if (!blk_fs_request(scmd->request)) + if (scmd->request->cmd_type != REQ_TYPE_FS) return 0; info_valid = scsi_get_sense_info_fld(scmd->sense_buffer, diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index b5838d547c68..713620ed70d9 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -2022,7 +2022,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) if((count > SUN3_DMA_MINSIZE) && (sun3_dma_setup_done != cmd)) { - if(blk_fs_request(cmd->request)) { + if (cmd->request->cmd_type == REQ_TYPE_FS) { sun3scsi_dma_setup(d, count, rq_data_dir(cmd->request)); sun3_dma_setup_done = cmd; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index e606cf0a2eb7..613f5880d135 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -524,7 +524,7 @@ static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, struct scsi_cmnd *cmd, int write_flag) { - if(blk_fs_request(cmd->request)) + if (cmd->request->cmd_type == REQ_TYPE_FS) return wanted; else return 0; diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index aaa4fd0dd1b9..7c526b8e30ac 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c @@ -458,7 +458,7 @@ static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, struct scsi_cmnd *cmd, int write_flag) { - if(blk_fs_request(cmd->request)) + if (cmd->request->cmd_type == REQ_TYPE_FS) return wanted; else return 0; diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 61bd0be5fb18..a9aff90e58e0 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -823,7 +823,8 @@ static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req) blkvsc_req->cmnd[0] = READ_16; } - blkvsc_req->cmnd[1] |= blk_fua_rq(blkvsc_req->req) ? 0x8 : 0; + blkvsc_req->cmnd[1] |= + (blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0; *(unsigned long long *)&blkvsc_req->cmnd[2] = cpu_to_be64(blkvsc_req->sector_start); @@ -839,7 +840,8 @@ static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req) blkvsc_req->cmnd[0] = READ_10; } - blkvsc_req->cmnd[1] |= blk_fua_rq(blkvsc_req->req) ? 0x8 : 0; + blkvsc_req->cmnd[1] |= + (blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0; *(unsigned int *)&blkvsc_req->cmnd[2] = cpu_to_be32(blkvsc_req->sector_start); @@ -1286,7 +1288,7 @@ static void blkvsc_request(struct request_queue *queue) DPRINT_DBG(BLKVSC_DRV, "- req %p\n", req); blkdev = req->rq_disk->private_data; - if (blkdev->shutting_down || !blk_fs_request(req) || + if (blkdev->shutting_down || req->cmd_type != REQ_TYPE_FS || blkdev->media_not_present) { __blk_end_request_cur(req, 0); continue; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d7ae241a9e55..3ecd28ef9ba4 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -604,33 +604,20 @@ enum { test_bit(QUEUE_FLAG_STACKABLE, &(q)->queue_flags) #define blk_queue_discard(q) test_bit(QUEUE_FLAG_DISCARD, &(q)->queue_flags) -#define blk_fs_request(rq) ((rq)->cmd_type == REQ_TYPE_FS) -#define blk_pc_request(rq) ((rq)->cmd_type == REQ_TYPE_BLOCK_PC) -#define blk_special_request(rq) ((rq)->cmd_type == REQ_TYPE_SPECIAL) -#define blk_sense_request(rq) ((rq)->cmd_type == REQ_TYPE_SENSE) - -#define blk_failfast_dev(rq) ((rq)->cmd_flags & REQ_FAILFAST_DEV) -#define blk_failfast_transport(rq) ((rq)->cmd_flags & REQ_FAILFAST_TRANSPORT) -#define blk_failfast_driver(rq) ((rq)->cmd_flags & REQ_FAILFAST_DRIVER) -#define blk_noretry_request(rq) (blk_failfast_dev(rq) || \ - blk_failfast_transport(rq) || \ - blk_failfast_driver(rq)) -#define blk_rq_started(rq) ((rq)->cmd_flags & REQ_STARTED) -#define blk_rq_io_stat(rq) ((rq)->cmd_flags & REQ_IO_STAT) -#define blk_rq_quiet(rq) ((rq)->cmd_flags & REQ_QUIET) - -#define blk_account_rq(rq) (blk_rq_started(rq) && (blk_fs_request(rq) || blk_discard_rq(rq))) - -#define blk_pm_suspend_request(rq) ((rq)->cmd_type == REQ_TYPE_PM_SUSPEND) -#define blk_pm_resume_request(rq) ((rq)->cmd_type == REQ_TYPE_PM_RESUME) +#define blk_noretry_request(rq) \ + ((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \ + REQ_FAILFAST_DRIVER)) + +#define blk_account_rq(rq) \ + (((rq)->cmd_flags & REQ_STARTED) && \ + ((rq)->cmd_type == REQ_TYPE_FS || \ + ((rq)->cmd_flags & REQ_DISCARD))) + #define blk_pm_request(rq) \ - (blk_pm_suspend_request(rq) || blk_pm_resume_request(rq)) + ((rq)->cmd_type == REQ_TYPE_PM_SUSPEND || \ + (rq)->cmd_type == REQ_TYPE_PM_RESUME) #define blk_rq_cpu_valid(rq) ((rq)->cpu != -1) -#define blk_sorted_rq(rq) ((rq)->cmd_flags & REQ_SORTED) -#define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER) -#define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) -#define blk_discard_rq(rq) ((rq)->cmd_flags & REQ_DISCARD) #define blk_bidi_rq(rq) ((rq)->next_rq != NULL) /* rq->queuelist of dequeued request must be list_empty() */ #define blk_queued_rq(rq) (!list_empty(&(rq)->queuelist)) @@ -652,9 +639,6 @@ static inline bool rq_is_sync(struct request *rq) return rw_is_sync(rq->cmd_flags); } -#define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) -#define rq_noidle(rq) ((rq)->cmd_flags & REQ_NOIDLE) - static inline int blk_queue_full(struct request_queue *q, int sync) { if (sync) @@ -687,7 +671,8 @@ static inline void blk_clear_queue_full(struct request_queue *q, int sync) (REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER) #define rq_mergeable(rq) \ (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \ - (blk_discard_rq(rq) || blk_fs_request((rq)))) + (((rq)->cmd_flags & REQ_DISCARD) || \ + (rq)->cmd_type == REQ_TYPE_FS)) /* * q->prep_rq_fn return values diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 416bf62d6d46..23faa67e8022 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -224,7 +224,7 @@ static inline int blk_trace_init_sysfs(struct device *dev) static inline int blk_cmd_buf_len(struct request *rq) { - return blk_pc_request(rq) ? rq->cmd_len * 3 : 1; + return (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? rq->cmd_len * 3 : 1; } extern void blk_dump_cmd(char *buf, struct request *rq); diff --git a/include/trace/events/block.h b/include/trace/events/block.h index d870a918559c..d8ce278515c3 100644 --- a/include/trace/events/block.h +++ b/include/trace/events/block.h @@ -25,8 +25,10 @@ DECLARE_EVENT_CLASS(block_rq_with_error, TP_fast_assign( __entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0; - __entry->sector = blk_pc_request(rq) ? 0 : blk_rq_pos(rq); - __entry->nr_sector = blk_pc_request(rq) ? 0 : blk_rq_sectors(rq); + __entry->sector = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + 0 : blk_rq_pos(rq); + __entry->nr_sector = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + 0 : blk_rq_sectors(rq); __entry->errors = rq->errors; blk_fill_rwbs_rq(__entry->rwbs, rq); @@ -109,9 +111,12 @@ DECLARE_EVENT_CLASS(block_rq, TP_fast_assign( __entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0; - __entry->sector = blk_pc_request(rq) ? 0 : blk_rq_pos(rq); - __entry->nr_sector = blk_pc_request(rq) ? 0 : blk_rq_sectors(rq); - __entry->bytes = blk_pc_request(rq) ? blk_rq_bytes(rq) : 0; + __entry->sector = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + 0 : blk_rq_pos(rq); + __entry->nr_sector = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + 0 : blk_rq_sectors(rq); + __entry->bytes = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + blk_rq_bytes(rq) : 0; blk_fill_rwbs_rq(__entry->rwbs, rq); blk_dump_cmd(__get_str(cmd), rq); diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 638711c17504..4f149944cb89 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -661,10 +661,10 @@ static void blk_add_trace_rq(struct request_queue *q, struct request *rq, if (likely(!bt)) return; - if (blk_discard_rq(rq)) + if (rq->cmd_flags & REQ_DISCARD) rw |= (1 << BIO_RW_DISCARD); - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { what |= BLK_TC_ACT(BLK_TC_PC); __blk_add_trace(bt, 0, blk_rq_bytes(rq), rw, what, rq->errors, rq->cmd_len, rq->cmd); @@ -925,7 +925,7 @@ void blk_add_driver_data(struct request_queue *q, if (likely(!bt)) return; - if (blk_pc_request(rq)) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) __blk_add_trace(bt, 0, blk_rq_bytes(rq), 0, BLK_TA_DRV_DATA, rq->errors, len, data); else @@ -1730,7 +1730,7 @@ void blk_dump_cmd(char *buf, struct request *rq) int len = rq->cmd_len; unsigned char *cmd = rq->cmd; - if (!blk_pc_request(rq)) { + if (rq->cmd_type != REQ_TYPE_BLOCK_PC) { buf[0] = '\0'; return; } @@ -1779,7 +1779,7 @@ void blk_fill_rwbs_rq(char *rwbs, struct request *rq) int rw = rq->cmd_flags & 0x03; int bytes; - if (blk_discard_rq(rq)) + if (rq->cmd_flags & REQ_DISCARD) rw |= (1 << BIO_RW_DISCARD); bytes = blk_rq_bytes(rq); -- cgit v1.2.3 From 7b6d91daee5cac6402186ff224c3af39d79f4a0e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 7 Aug 2010 18:20:39 +0200 Subject: block: unify flags for struct bio and struct request Remove the current bio flags and reuse the request flags for the bio, too. This allows to more easily trace the type of I/O from the filesystem down to the block driver. There were two flags in the bio that were missing in the requests: BIO_RW_UNPLUG and BIO_RW_AHEAD. Also I've renamed two request flags that had a superflous RW in them. Note that the flags are in bio.h despite having the REQ_ name - as blkdev.h includes bio.h that is the only way to go for now. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-barrier.c | 2 +- block/blk-core.c | 37 +++-------- block/blk-map.c | 2 +- block/blk-merge.c | 2 +- block/cfq-iosched.c | 14 ++--- block/elevator.c | 3 +- drivers/ata/libata-scsi.c | 2 +- drivers/block/aoe/aoeblk.c | 2 +- drivers/block/brd.c | 2 +- drivers/block/drbd/drbd_actlog.c | 8 +-- drivers/block/drbd/drbd_main.c | 6 +- drivers/block/drbd/drbd_receiver.c | 22 +++---- drivers/block/drbd/drbd_req.c | 2 +- drivers/block/loop.c | 2 +- drivers/block/pktcdvd.c | 2 +- drivers/block/umem.c | 2 +- drivers/ide/ide-cd_ioctl.c | 2 +- drivers/ide/ide-floppy.c | 2 +- drivers/md/dm-io.c | 12 ++-- drivers/md/dm-kcopyd.c | 2 +- drivers/md/dm-raid1.c | 2 +- drivers/md/dm-stripe.c | 2 +- drivers/md/dm.c | 14 ++--- drivers/md/linear.c | 2 +- drivers/md/md.c | 10 +-- drivers/md/md.h | 4 +- drivers/md/multipath.c | 8 +-- drivers/md/raid0.c | 2 +- drivers/md/raid1.c | 22 +++---- drivers/md/raid10.c | 12 ++-- drivers/md/raid5.c | 2 +- drivers/scsi/osd/osd_initiator.c | 8 +-- fs/bio.c | 5 +- fs/btrfs/disk-io.c | 8 +-- fs/btrfs/inode.c | 6 +- fs/btrfs/volumes.c | 18 +++--- fs/exofs/ios.c | 2 +- fs/gfs2/log.c | 4 +- fs/gfs2/meta_io.c | 8 +-- fs/gfs2/ops_fstype.c | 2 +- fs/nilfs2/segbuf.c | 2 +- include/linux/bio.h | 125 +++++++++++++++++++++++-------------- include/linux/blkdev.h | 66 +------------------- include/linux/fs.h | 38 +++++------ kernel/power/block_io.c | 2 +- kernel/trace/blktrace.c | 27 ++++---- mm/page_io.c | 2 +- 47 files changed, 242 insertions(+), 289 deletions(-) (limited to 'drivers/scsi') diff --git a/block/blk-barrier.c b/block/blk-barrier.c index 74e404393172..7c6f4a714687 100644 --- a/block/blk-barrier.c +++ b/block/blk-barrier.c @@ -203,7 +203,7 @@ static inline bool start_ordered(struct request_queue *q, struct request **rqp) /* initialize proxy request and queue it */ blk_rq_init(q, rq); if (bio_data_dir(q->orig_bar_rq->bio) == WRITE) - rq->cmd_flags |= REQ_RW; + rq->cmd_flags |= REQ_WRITE; if (q->ordered & QUEUE_ORDERED_DO_FUA) rq->cmd_flags |= REQ_FUA; init_request_from_bio(rq, q->orig_bar_rq->bio); diff --git a/block/blk-core.c b/block/blk-core.c index dca43a31e725..66c3cfe94d0a 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1140,25 +1140,9 @@ void init_request_from_bio(struct request *req, struct bio *bio) req->cpu = bio->bi_comp_cpu; req->cmd_type = REQ_TYPE_FS; - /* - * Inherit FAILFAST from bio (for read-ahead, and explicit - * FAILFAST). FAILFAST flags are identical for req and bio. - */ - if (bio_rw_flagged(bio, BIO_RW_AHEAD)) + req->cmd_flags |= bio->bi_rw & REQ_COMMON_MASK; + if (bio->bi_rw & REQ_RAHEAD) req->cmd_flags |= REQ_FAILFAST_MASK; - else - req->cmd_flags |= bio->bi_rw & REQ_FAILFAST_MASK; - - if (bio_rw_flagged(bio, BIO_RW_DISCARD)) - req->cmd_flags |= REQ_DISCARD; - if (bio_rw_flagged(bio, BIO_RW_BARRIER)) - req->cmd_flags |= REQ_HARDBARRIER; - if (bio_rw_flagged(bio, BIO_RW_SYNCIO)) - req->cmd_flags |= REQ_RW_SYNC; - if (bio_rw_flagged(bio, BIO_RW_META)) - req->cmd_flags |= REQ_RW_META; - if (bio_rw_flagged(bio, BIO_RW_NOIDLE)) - req->cmd_flags |= REQ_NOIDLE; req->errors = 0; req->__sector = bio->bi_sector; @@ -1181,12 +1165,12 @@ static int __make_request(struct request_queue *q, struct bio *bio) int el_ret; unsigned int bytes = bio->bi_size; const unsigned short prio = bio_prio(bio); - const bool sync = bio_rw_flagged(bio, BIO_RW_SYNCIO); - const bool unplug = bio_rw_flagged(bio, BIO_RW_UNPLUG); + const bool sync = (bio->bi_rw & REQ_SYNC); + const bool unplug = (bio->bi_rw & REQ_UNPLUG); const unsigned int ff = bio->bi_rw & REQ_FAILFAST_MASK; int rw_flags; - if (bio_rw_flagged(bio, BIO_RW_BARRIER) && + if ((bio->bi_rw & REQ_HARDBARRIER) && (q->next_ordered == QUEUE_ORDERED_NONE)) { bio_endio(bio, -EOPNOTSUPP); return 0; @@ -1200,7 +1184,7 @@ static int __make_request(struct request_queue *q, struct bio *bio) spin_lock_irq(q->queue_lock); - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER)) || elv_queue_empty(q)) + if (unlikely((bio->bi_rw & REQ_HARDBARRIER)) || elv_queue_empty(q)) goto get_rq; el_ret = elv_merge(q, &req, bio); @@ -1275,7 +1259,7 @@ get_rq: */ rw_flags = bio_data_dir(bio); if (sync) - rw_flags |= REQ_RW_SYNC; + rw_flags |= REQ_SYNC; /* * Grab a free request. This is might sleep but can not fail. @@ -1464,7 +1448,7 @@ static inline void __generic_make_request(struct bio *bio) goto end_io; } - if (unlikely(!bio_rw_flagged(bio, BIO_RW_DISCARD) && + if (unlikely(!(bio->bi_rw & REQ_DISCARD) && nr_sectors > queue_max_hw_sectors(q))) { printk(KERN_ERR "bio too big device %s (%u > %u)\n", bdevname(bio->bi_bdev, b), @@ -1497,8 +1481,7 @@ static inline void __generic_make_request(struct bio *bio) if (bio_check_eod(bio, nr_sectors)) goto end_io; - if (bio_rw_flagged(bio, BIO_RW_DISCARD) && - !blk_queue_discard(q)) { + if ((bio->bi_rw & REQ_DISCARD) && !blk_queue_discard(q)) { err = -EOPNOTSUPP; goto end_io; } @@ -2365,7 +2348,7 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, struct bio *bio) { /* Bit 0 (R/W) is identical in rq->cmd_flags and bio->bi_rw */ - rq->cmd_flags |= bio->bi_rw & REQ_RW; + rq->cmd_flags |= bio->bi_rw & REQ_WRITE; if (bio_has_data(bio)) { rq->nr_phys_segments = bio_phys_segments(q, bio); diff --git a/block/blk-map.c b/block/blk-map.c index 9083cf0180cc..c65d7593f7f1 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -307,7 +307,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, return PTR_ERR(bio); if (rq_data_dir(rq) == WRITE) - bio->bi_rw |= (1 << BIO_RW); + bio->bi_rw |= (1 << REQ_WRITE); if (do_copy) rq->cmd_flags |= REQ_COPY_USER; diff --git a/block/blk-merge.c b/block/blk-merge.c index 87e4fb7d0e98..4852475521ea 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -180,7 +180,7 @@ new_segment: } if (q->dma_drain_size && q->dma_drain_needed(rq)) { - if (rq->cmd_flags & REQ_RW) + if (rq->cmd_flags & REQ_WRITE) memset(q->dma_drain_buffer, 0, q->dma_drain_size); sg->page_link &= ~0x02; diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index d4edeb8fceb8..eb4086f7dfef 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -458,7 +458,7 @@ static inline struct cfq_data *cic_to_cfqd(struct cfq_io_context *cic) */ static inline bool cfq_bio_sync(struct bio *bio) { - return bio_data_dir(bio) == READ || bio_rw_flagged(bio, BIO_RW_SYNCIO); + return bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC); } /* @@ -646,10 +646,10 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2, return rq1; else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) return rq2; - if ((rq1->cmd_flags & REQ_RW_META) && !(rq2->cmd_flags & REQ_RW_META)) + if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) return rq1; - else if ((rq2->cmd_flags & REQ_RW_META) && - !(rq1->cmd_flags & REQ_RW_META)) + else if ((rq2->cmd_flags & REQ_META) && + !(rq1->cmd_flags & REQ_META)) return rq2; s1 = blk_rq_pos(rq1); @@ -1485,7 +1485,7 @@ static void cfq_remove_request(struct request *rq) cfqq->cfqd->rq_queued--; cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq), rq_is_sync(rq)); - if (rq->cmd_flags & REQ_RW_META) { + if (rq->cmd_flags & REQ_META) { WARN_ON(!cfqq->meta_pending); cfqq->meta_pending--; } @@ -3177,7 +3177,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, * So both queues are sync. Let the new request get disk time if * it's a metadata request and the current queue is doing regular IO. */ - if ((rq->cmd_flags & REQ_RW_META) && !cfqq->meta_pending) + if ((rq->cmd_flags & REQ_META) && !cfqq->meta_pending) return true; /* @@ -3231,7 +3231,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct cfq_io_context *cic = RQ_CIC(rq); cfqd->rq_queued++; - if (rq->cmd_flags & REQ_RW_META) + if (rq->cmd_flags & REQ_META) cfqq->meta_pending++; cfq_update_io_thinktime(cfqd, cic); diff --git a/block/elevator.c b/block/elevator.c index aa99b59c03d6..816a7c8d6394 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -79,8 +79,7 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio) /* * Don't merge file system requests and discard requests */ - if (bio_rw_flagged(bio, BIO_RW_DISCARD) != - bio_rw_flagged(rq->bio, BIO_RW_DISCARD)) + if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD)) return 0; /* diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index a5c08b082edb..0a8cd3484791 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1114,7 +1114,7 @@ static int atapi_drain_needed(struct request *rq) if (likely(rq->cmd_type != REQ_TYPE_BLOCK_PC)) return 0; - if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_RW)) + if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_WRITE)) return 0; return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC; diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 035cefe4045a..65deffde60ac 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -173,7 +173,7 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) BUG(); bio_endio(bio, -ENXIO); return 0; - } else if (bio_rw_flagged(bio, BIO_RW_BARRIER)) { + } else if (bio->bi_rw & REQ_HARDBARRIER) { bio_endio(bio, -EOPNOTSUPP); return 0; } else if (bio->bi_io_vec == NULL) { diff --git a/drivers/block/brd.c b/drivers/block/brd.c index f1bf79d9bc0a..1b218c6b6820 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -340,7 +340,7 @@ static int brd_make_request(struct request_queue *q, struct bio *bio) get_capacity(bdev->bd_disk)) goto out; - if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) { + if (unlikely(bio->bi_rw & REQ_DISCARD)) { err = 0; discard_from_brd(brd, sector, bio->bi_size); goto out; diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index df018990c422..9400845d602e 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -79,8 +79,8 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev, md_io.error = 0; if ((rw & WRITE) && !test_bit(MD_NO_BARRIER, &mdev->flags)) - rw |= (1 << BIO_RW_BARRIER); - rw |= ((1<bi_rw & REQ_HARDBARRIER) && !ok)) { /* Try again with no barrier */ dev_warn(DEV, "Barriers not supported on meta data device - disabling\n"); set_bit(MD_NO_BARRIER, &mdev->flags); - rw &= ~(1 << BIO_RW_BARRIER); + rw &= ~REQ_HARDBARRIER; bio_put(bio); goto retry; } diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 7258c95e895e..e2ab13d99d69 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2425,15 +2425,15 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) /* NOTE: no need to check if barriers supported here as we would * not pass the test in make_request_common in that case */ - if (bio_rw_flagged(req->master_bio, BIO_RW_BARRIER)) { + if (req->master_bio->bi_rw & REQ_HARDBARRIER) { dev_err(DEV, "ASSERT FAILED would have set DP_HARDBARRIER\n"); /* dp_flags |= DP_HARDBARRIER; */ } - if (bio_rw_flagged(req->master_bio, BIO_RW_SYNCIO)) + if (req->master_bio->bi_rw & REQ_SYNC) dp_flags |= DP_RW_SYNC; /* for now handle SYNCIO and UNPLUG * as if they still were one and the same flag */ - if (bio_rw_flagged(req->master_bio, BIO_RW_UNPLUG)) + if (req->master_bio->bi_rw & REQ_UNPLUG) dp_flags |= DP_RW_SYNC; if (mdev->state.conn >= C_SYNC_SOURCE && mdev->state.conn <= C_PAUSED_SYNC_T) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index dff48701b84d..cba1deb7b271 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1180,7 +1180,7 @@ next_bio: bio->bi_sector = sector; bio->bi_bdev = mdev->ldev->backing_bdev; /* we special case some flags in the multi-bio case, see below - * (BIO_RW_UNPLUG, BIO_RW_BARRIER) */ + * (REQ_UNPLUG, REQ_HARDBARRIER) */ bio->bi_rw = rw; bio->bi_private = e; bio->bi_end_io = drbd_endio_sec; @@ -1209,16 +1209,16 @@ next_bio: bios = bios->bi_next; bio->bi_next = NULL; - /* strip off BIO_RW_UNPLUG unless it is the last bio */ + /* strip off REQ_UNPLUG unless it is the last bio */ if (bios) - bio->bi_rw &= ~(1<bi_rw &= ~REQ_UNPLUG; drbd_generic_make_request(mdev, fault_type, bio); - /* strip off BIO_RW_BARRIER, + /* strip off REQ_HARDBARRIER, * unless it is the first or last bio */ if (bios && bios->bi_next) - bios->bi_rw &= ~(1<bi_rw &= ~REQ_HARDBARRIER; } while (bios); maybe_kick_lo(mdev); return 0; @@ -1233,7 +1233,7 @@ fail: } /** - * w_e_reissue() - Worker callback; Resubmit a bio, without BIO_RW_BARRIER set + * w_e_reissue() - Worker callback; Resubmit a bio, without REQ_HARDBARRIER set * @mdev: DRBD device. * @w: work object. * @cancel: The connection will be closed anyways (unused in this callback) @@ -1245,7 +1245,7 @@ int w_e_reissue(struct drbd_conf *mdev, struct drbd_work *w, int cancel) __relea (and DE_BARRIER_IN_NEXT_EPOCH_ISSUED in the previous Epoch) so that we can finish that epoch in drbd_may_finish_epoch(). That is necessary if we already have a long chain of Epochs, before - we realize that BIO_RW_BARRIER is actually not supported */ + we realize that REQ_HARDBARRIER is actually not supported */ /* As long as the -ENOTSUPP on the barrier is reported immediately that will never trigger. If it is reported late, we will just @@ -1824,14 +1824,14 @@ static int receive_Data(struct drbd_conf *mdev, struct p_header *h) epoch = list_entry(e->epoch->list.prev, struct drbd_epoch, list); if (epoch == e->epoch) { set_bit(DE_CONTAINS_A_BARRIER, &e->epoch->flags); - rw |= (1<flags |= EE_IS_BARRIER; } else { if (atomic_read(&epoch->epoch_size) > 1 || !test_bit(DE_CONTAINS_A_BARRIER, &epoch->flags)) { set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &epoch->flags); set_bit(DE_CONTAINS_A_BARRIER, &e->epoch->flags); - rw |= (1<flags |= EE_IS_BARRIER; } } @@ -1841,10 +1841,10 @@ static int receive_Data(struct drbd_conf *mdev, struct p_header *h) dp_flags = be32_to_cpu(p->dp_flags); if (dp_flags & DP_HARDBARRIER) { dev_err(DEV, "ASSERT FAILED would have submitted barrier request\n"); - /* rw |= (1<flags |= EE_MAY_SET_IN_SYNC; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 654f1ef5cbb0..f761d98a4e90 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -997,7 +997,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) * because of those XXX, this is not yet enabled, * i.e. in drbd_init_set_defaults we set the NO_BARRIER_SUPP bit. */ - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER) && test_bit(NO_BARRIER_SUPP, &mdev->flags))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER) && test_bit(NO_BARRIER_SUPP, &mdev->flags)) { /* dev_warn(DEV, "Rejecting barrier request as underlying device does not support\n"); */ bio_endio(bio, -EOPNOTSUPP); return 0; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6120922f459f..fedfdb7d3cdf 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -476,7 +476,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; if (bio_rw(bio) == WRITE) { - bool barrier = bio_rw_flagged(bio, BIO_RW_BARRIER); + bool barrier = (bio->bi_rw & REQ_HARDBARRIER); struct file *file = lo->lo_backing_file; if (barrier) { diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 8a549db2aa78..9f3e4454274b 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1221,7 +1221,7 @@ static int pkt_start_recovery(struct packet_data *pkt) pkt->bio->bi_flags = 1 << BIO_UPTODATE; pkt->bio->bi_idx = 0; - BUG_ON(pkt->bio->bi_rw != (1 << BIO_RW)); + BUG_ON(pkt->bio->bi_rw != REQ_WRITE); BUG_ON(pkt->bio->bi_vcnt != pkt->frames); BUG_ON(pkt->bio->bi_size != pkt->frames * CD_FRAMESIZE); BUG_ON(pkt->bio->bi_end_io != pkt_end_io_packet_write); diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 2f9470ff8f7c..8be57151f5d6 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -478,7 +478,7 @@ static void process_page(unsigned long data) le32_to_cpu(desc->local_addr)>>9, le32_to_cpu(desc->transfer_size)); dump_dmastat(card, control); - } else if (test_bit(BIO_RW, &bio->bi_rw) && + } else if ((bio->bi_rw & REQ_WRITE) && le32_to_cpu(desc->local_addr) >> 9 == card->init_size) { card->init_size += le32_to_cpu(desc->transfer_size) >> 9; diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c index 02712bf045c1..766b3deeb23c 100644 --- a/drivers/ide/ide-cd_ioctl.c +++ b/drivers/ide/ide-cd_ioctl.c @@ -454,7 +454,7 @@ int ide_cdrom_packet(struct cdrom_device_info *cdi, touch it at all. */ if (cgc->data_direction == CGC_DATA_WRITE) - flags |= REQ_RW; + flags |= REQ_WRITE; if (cgc->sense) memset(cgc->sense, 0, sizeof(struct request_sense)); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index c7d0737bb18a..5406b6ea3ad1 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -207,7 +207,7 @@ static void idefloppy_create_rw_cmd(ide_drive_t *drive, memcpy(rq->cmd, pc->c, 12); pc->rq = rq; - if (rq->cmd_flags & REQ_RW) + if (rq->cmd_flags & REQ_WRITE) pc->flags |= PC_FLAG_WRITING; pc->flags |= PC_FLAG_DMA_OK; diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 10f457ca6af2..0590c75b0ab6 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -356,7 +356,7 @@ static void dispatch_io(int rw, unsigned int num_regions, BUG_ON(num_regions > DM_IO_MAX_REGIONS); if (sync) - rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); + rw |= REQ_SYNC | REQ_UNPLUG; /* * For multiple regions we need to be careful to rewind @@ -364,7 +364,7 @@ static void dispatch_io(int rw, unsigned int num_regions, */ for (i = 0; i < num_regions; i++) { *dp = old_pages; - if (where[i].count || (rw & (1 << BIO_RW_BARRIER))) + if (where[i].count || (rw & REQ_HARDBARRIER)) do_region(rw, i, where + i, dp, io); } @@ -412,8 +412,8 @@ retry: } set_current_state(TASK_RUNNING); - if (io->eopnotsupp_bits && (rw & (1 << BIO_RW_BARRIER))) { - rw &= ~(1 << BIO_RW_BARRIER); + if (io->eopnotsupp_bits && (rw & REQ_HARDBARRIER)) { + rw &= ~REQ_HARDBARRIER; goto retry; } @@ -479,8 +479,8 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp) * New collapsed (a)synchronous interface. * * If the IO is asynchronous (i.e. it has notify.fn), you must either unplug - * the queue with blk_unplug() some time later or set the BIO_RW_SYNC bit in - * io_req->bi_rw. If you fail to do one of these, the IO will be submitted to + * the queue with blk_unplug() some time later or set REQ_SYNC in +io_req->bi_rw. If you fail to do one of these, the IO will be submitted to * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c. */ int dm_io(struct dm_io_request *io_req, unsigned num_regions, diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index addf83475040..d8587bac5682 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c @@ -345,7 +345,7 @@ static int run_io_job(struct kcopyd_job *job) { int r; struct dm_io_request io_req = { - .bi_rw = job->rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG), + .bi_rw = job->rw | REQ_SYNC | REQ_UNPLUG, .mem.type = DM_IO_PAGE_LIST, .mem.ptr.pl = job->pages, .mem.offset = job->offset, diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index ddda531723dc..74136262d654 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1211,7 +1211,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, if (error == -EOPNOTSUPP) goto out; - if ((error == -EWOULDBLOCK) && bio_rw_flagged(bio, BIO_RW_AHEAD)) + if ((error == -EWOULDBLOCK) && (bio->bi_rw & REQ_RAHEAD)) goto out; if (unlikely(error)) { diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index e610725db766..d6e28d732b4d 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -284,7 +284,7 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, if (!error) return 0; /* I/O complete */ - if ((error == -EWOULDBLOCK) && bio_rw_flagged(bio, BIO_RW_AHEAD)) + if ((error == -EWOULDBLOCK) && (bio->bi_rw & REQ_RAHEAD)) return error; if (error == -EOPNOTSUPP) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 1e0e6dd51501..d6f77baeafd6 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -614,7 +614,7 @@ static void dec_pending(struct dm_io *io, int error) */ spin_lock_irqsave(&md->deferred_lock, flags); if (__noflush_suspending(md)) { - if (!bio_rw_flagged(io->bio, BIO_RW_BARRIER)) + if (!(io->bio->bi_rw & REQ_HARDBARRIER)) bio_list_add_head(&md->deferred, io->bio); } else @@ -626,7 +626,7 @@ static void dec_pending(struct dm_io *io, int error) io_error = io->error; bio = io->bio; - if (bio_rw_flagged(bio, BIO_RW_BARRIER)) { + if (bio->bi_rw & REQ_HARDBARRIER) { /* * There can be just one barrier request so we use * a per-device variable for error reporting. @@ -1106,7 +1106,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector, clone->bi_sector = sector; clone->bi_bdev = bio->bi_bdev; - clone->bi_rw = bio->bi_rw & ~(1 << BIO_RW_BARRIER); + clone->bi_rw = bio->bi_rw & ~REQ_HARDBARRIER; clone->bi_vcnt = 1; clone->bi_size = to_bytes(len); clone->bi_io_vec->bv_offset = offset; @@ -1133,7 +1133,7 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs); __bio_clone(clone, bio); - clone->bi_rw &= ~(1 << BIO_RW_BARRIER); + clone->bi_rw &= ~REQ_HARDBARRIER; clone->bi_destructor = dm_bio_destructor; clone->bi_sector = sector; clone->bi_idx = idx; @@ -1301,7 +1301,7 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) ci.map = dm_get_live_table(md); if (unlikely(!ci.map)) { - if (!bio_rw_flagged(bio, BIO_RW_BARRIER)) + if (!(bio->bi_rw & REQ_HARDBARRIER)) bio_io_error(bio); else if (!md->barrier_error) @@ -1414,7 +1414,7 @@ static int _dm_request(struct request_queue *q, struct bio *bio) * we have to queue this io for later. */ if (unlikely(test_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags)) || - unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + unlikely(bio->bi_rw & REQ_HARDBARRIER)) { up_read(&md->io_lock); if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) && @@ -2296,7 +2296,7 @@ static void dm_wq_work(struct work_struct *work) if (dm_request_based(md)) generic_make_request(c); else { - if (bio_rw_flagged(c, BIO_RW_BARRIER)) + if (c->bi_rw & REQ_HARDBARRIER) process_barrier(md, c); else __split_and_process_bio(md, c); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 7e0e057db9a7..ba19060bcf3f 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -294,7 +294,7 @@ static int linear_make_request (mddev_t *mddev, struct bio *bio) dev_info_t *tmp_dev; sector_t start_sector; - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { md_barrier_request(mddev, bio); return 0; } diff --git a/drivers/md/md.c b/drivers/md/md.c index cb20d0b0555a..1893af678779 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -353,7 +353,7 @@ static void md_submit_barrier(struct work_struct *ws) /* an empty barrier - all done */ bio_endio(bio, 0); else { - bio->bi_rw &= ~(1<bi_rw &= ~REQ_HARDBARRIER; if (mddev->pers->make_request(mddev, bio)) generic_make_request(bio); mddev->barrier = POST_REQUEST_BARRIER; @@ -675,11 +675,11 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, * if zero is reached. * If an error occurred, call md_error * - * As we might need to resubmit the request if BIO_RW_BARRIER + * As we might need to resubmit the request if REQ_HARDBARRIER * causes ENOTSUPP, we allocate a spare bio... */ struct bio *bio = bio_alloc(GFP_NOIO, 1); - int rw = (1<bi_bdev = rdev->bdev; bio->bi_sector = sector; @@ -691,7 +691,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, atomic_inc(&mddev->pending_writes); if (!test_bit(BarriersNotsupp, &rdev->flags)) { struct bio *rbio; - rw |= (1<bi_private = bio; rbio->bi_end_io = super_written_barrier; @@ -736,7 +736,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size, struct completion event; int ret; - rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); + rw |= REQ_SYNC | REQ_UNPLUG; bio->bi_bdev = bdev; bio->bi_sector = sector; diff --git a/drivers/md/md.h b/drivers/md/md.h index 10597bfec000..fc56e0f21c80 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -67,7 +67,7 @@ struct mdk_rdev_s #define Faulty 1 /* device is known to have a fault */ #define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ -#define BarriersNotsupp 5 /* BIO_RW_BARRIER is not supported */ +#define BarriersNotsupp 5 /* REQ_HARDBARRIER is not supported */ #define AllReserved 6 /* If whole device is reserved for * one array */ #define AutoDetected 7 /* added by auto-detect */ @@ -254,7 +254,7 @@ struct mddev_s * fails. Only supported */ struct bio *biolist; /* bios that need to be retried - * because BIO_RW_BARRIER is not supported + * because REQ_HARDBARRIER is not supported */ atomic_t recovery_active; /* blocks scheduled, but not written */ diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 410fb60699ac..0307d217e7a4 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -91,7 +91,7 @@ static void multipath_end_request(struct bio *bio, int error) if (uptodate) multipath_end_bh_io(mp_bh, 0); - else if (!bio_rw_flagged(bio, BIO_RW_AHEAD)) { + else if (!(bio->bi_rw & REQ_RAHEAD)) { /* * oops, IO error: */ @@ -142,7 +142,7 @@ static int multipath_make_request(mddev_t *mddev, struct bio * bio) struct multipath_bh * mp_bh; struct multipath_info *multipath; - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { md_barrier_request(mddev, bio); return 0; } @@ -163,7 +163,7 @@ static int multipath_make_request(mddev_t *mddev, struct bio * bio) mp_bh->bio = *bio; mp_bh->bio.bi_sector += multipath->rdev->data_offset; mp_bh->bio.bi_bdev = multipath->rdev->bdev; - mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT); + mp_bh->bio.bi_rw |= REQ_FAILFAST_TRANSPORT; mp_bh->bio.bi_end_io = multipath_end_request; mp_bh->bio.bi_private = mp_bh; generic_make_request(&mp_bh->bio); @@ -398,7 +398,7 @@ static void multipathd (mddev_t *mddev) *bio = *(mp_bh->master_bio); bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset; bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev; - bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT); + bio->bi_rw |= REQ_FAILFAST_TRANSPORT; bio->bi_end_io = multipath_end_request; bio->bi_private = mp_bh; generic_make_request(bio); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 563abed5a2cb..6f7af46d623c 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -483,7 +483,7 @@ static int raid0_make_request(mddev_t *mddev, struct bio *bio) struct strip_zone *zone; mdk_rdev_t *tmp_dev; - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { md_barrier_request(mddev, bio); return 0; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a948da8012de..73cc74ffc26b 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -787,7 +787,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) struct bio_list bl; struct page **behind_pages = NULL; const int rw = bio_data_dir(bio); - const bool do_sync = bio_rw_flagged(bio, BIO_RW_SYNCIO); + const bool do_sync = (bio->bi_rw & REQ_SYNC); bool do_barriers; mdk_rdev_t *blocked_rdev; @@ -822,7 +822,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) finish_wait(&conf->wait_barrier, &w); } if (unlikely(!mddev->barriers_work && - bio_rw_flagged(bio, BIO_RW_BARRIER))) { + (bio->bi_rw & REQ_HARDBARRIER))) { if (rw == WRITE) md_write_end(mddev); bio_endio(bio, -EOPNOTSUPP); @@ -877,7 +877,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = raid1_end_read_request; - read_bio->bi_rw = READ | (do_sync << BIO_RW_SYNCIO); + read_bio->bi_rw = READ | do_sync; read_bio->bi_private = r1_bio; generic_make_request(read_bio); @@ -959,7 +959,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) atomic_set(&r1_bio->remaining, 0); atomic_set(&r1_bio->behind_remaining, 0); - do_barriers = bio_rw_flagged(bio, BIO_RW_BARRIER); + do_barriers = bio->bi_rw & REQ_HARDBARRIER; if (do_barriers) set_bit(R1BIO_Barrier, &r1_bio->state); @@ -975,8 +975,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = raid1_end_write_request; - mbio->bi_rw = WRITE | (do_barriers << BIO_RW_BARRIER) | - (do_sync << BIO_RW_SYNCIO); + mbio->bi_rw = WRITE | do_barriers | do_sync; mbio->bi_private = r1_bio; if (behind_pages) { @@ -1633,7 +1632,7 @@ static void raid1d(mddev_t *mddev) sync_request_write(mddev, r1_bio); unplug = 1; } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { - /* some requests in the r1bio were BIO_RW_BARRIER + /* some requests in the r1bio were REQ_HARDBARRIER * requests which failed with -EOPNOTSUPP. Hohumm.. * Better resubmit without the barrier. * We know which devices to resubmit for, because @@ -1641,7 +1640,7 @@ static void raid1d(mddev_t *mddev) * We already have a nr_pending reference on these rdevs. */ int i; - const bool do_sync = bio_rw_flagged(r1_bio->master_bio, BIO_RW_SYNCIO); + const bool do_sync = (r1_bio->master_bio->bi_rw & REQ_SYNC); clear_bit(R1BIO_BarrierRetry, &r1_bio->state); clear_bit(R1BIO_Barrier, &r1_bio->state); for (i=0; i < conf->raid_disks; i++) @@ -1662,8 +1661,7 @@ static void raid1d(mddev_t *mddev) conf->mirrors[i].rdev->data_offset; bio->bi_bdev = conf->mirrors[i].rdev->bdev; bio->bi_end_io = raid1_end_write_request; - bio->bi_rw = WRITE | - (do_sync << BIO_RW_SYNCIO); + bio->bi_rw = WRITE | do_sync; bio->bi_private = r1_bio; r1_bio->bios[i] = bio; generic_make_request(bio); @@ -1698,7 +1696,7 @@ static void raid1d(mddev_t *mddev) (unsigned long long)r1_bio->sector); raid_end_bio_io(r1_bio); } else { - const bool do_sync = bio_rw_flagged(r1_bio->master_bio, BIO_RW_SYNCIO); + const bool do_sync = r1_bio->master_bio->bi_rw & REQ_SYNC; r1_bio->bios[r1_bio->read_disk] = mddev->ro ? IO_BLOCKED : NULL; r1_bio->read_disk = disk; @@ -1715,7 +1713,7 @@ static void raid1d(mddev_t *mddev) bio->bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_bdev = rdev->bdev; bio->bi_end_io = raid1_end_read_request; - bio->bi_rw = READ | (do_sync << BIO_RW_SYNCIO); + bio->bi_rw = READ | do_sync; bio->bi_private = r1_bio; unplug = 1; generic_make_request(bio); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 42e64e4e5e25..62ecb6650fd0 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -799,12 +799,12 @@ static int make_request(mddev_t *mddev, struct bio * bio) int i; int chunk_sects = conf->chunk_mask + 1; const int rw = bio_data_dir(bio); - const bool do_sync = bio_rw_flagged(bio, BIO_RW_SYNCIO); + const bool do_sync = (bio->bi_rw & REQ_SYNC); struct bio_list bl; unsigned long flags; mdk_rdev_t *blocked_rdev; - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { md_barrier_request(mddev, bio); return 0; } @@ -879,7 +879,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = raid10_end_read_request; - read_bio->bi_rw = READ | (do_sync << BIO_RW_SYNCIO); + read_bio->bi_rw = READ | do_sync; read_bio->bi_private = r10_bio; generic_make_request(read_bio); @@ -947,7 +947,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) conf->mirrors[d].rdev->data_offset; mbio->bi_bdev = conf->mirrors[d].rdev->bdev; mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | (do_sync << BIO_RW_SYNCIO); + mbio->bi_rw = WRITE | do_sync; mbio->bi_private = r10_bio; atomic_inc(&r10_bio->remaining); @@ -1716,7 +1716,7 @@ static void raid10d(mddev_t *mddev) raid_end_bio_io(r10_bio); bio_put(bio); } else { - const bool do_sync = bio_rw_flagged(r10_bio->master_bio, BIO_RW_SYNCIO); + const bool do_sync = (r10_bio->master_bio->bi_rw & REQ_SYNC); bio_put(bio); rdev = conf->mirrors[mirror].rdev; if (printk_ratelimit()) @@ -1730,7 +1730,7 @@ static void raid10d(mddev_t *mddev) bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr + rdev->data_offset; bio->bi_bdev = rdev->bdev; - bio->bi_rw = READ | (do_sync << BIO_RW_SYNCIO); + bio->bi_rw = READ | do_sync; bio->bi_private = r10_bio; bio->bi_end_io = raid10_end_read_request; unplug = 1; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 96c690279fc6..20ac2f14376a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3958,7 +3958,7 @@ static int make_request(mddev_t *mddev, struct bio * bi) const int rw = bio_data_dir(bi); int remaining; - if (unlikely(bio_rw_flagged(bi, BIO_RW_BARRIER))) { + if (unlikely(bi->bi_rw & REQ_HARDBARRIER)) { /* Drain all pending writes. We only really need * to ensure they have been submitted, but this is * easier. diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index ee4b6914667f..fda4de3440c4 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -716,7 +716,7 @@ static int _osd_req_list_objects(struct osd_request *or, return PTR_ERR(bio); } - bio->bi_rw &= ~(1 << BIO_RW); + bio->bi_rw &= ~REQ_WRITE; or->in.bio = bio; or->in.total_bytes = bio->bi_size; return 0; @@ -814,7 +814,7 @@ void osd_req_write(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, len); WARN_ON(or->out.bio || or->out.total_bytes); - WARN_ON(0 == bio_rw_flagged(bio, BIO_RW)); + WARN_ON(0 == (bio->bi_rw & REQ_WRITE)); or->out.bio = bio; or->out.total_bytes = len; } @@ -829,7 +829,7 @@ int osd_req_write_kern(struct osd_request *or, if (IS_ERR(bio)) return PTR_ERR(bio); - bio->bi_rw |= (1 << BIO_RW); /* FIXME: bio_set_dir() */ + bio->bi_rw |= REQ_WRITE; /* FIXME: bio_set_dir() */ osd_req_write(or, obj, offset, bio, len); return 0; } @@ -865,7 +865,7 @@ void osd_req_read(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len); WARN_ON(or->in.bio || or->in.total_bytes); - WARN_ON(1 == bio_rw_flagged(bio, BIO_RW)); + WARN_ON(1 == (bio->bi_rw & REQ_WRITE)); or->in.bio = bio; or->in.total_bytes = len; } diff --git a/fs/bio.c b/fs/bio.c index e7bf6ca64dcf..8abb2dfb2e7c 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -843,7 +843,8 @@ struct bio *bio_copy_user_iov(struct request_queue *q, if (!bio) goto out_bmd; - bio->bi_rw |= (!write_to_vm << BIO_RW); + if (!write_to_vm) + bio->bi_rw |= REQ_WRITE; ret = 0; @@ -1024,7 +1025,7 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, * set data direction, and check if mapped pages need bouncing */ if (!write_to_vm) - bio->bi_rw |= (1 << BIO_RW); + bio->bi_rw |= REQ_WRITE; bio->bi_bdev = bdev; bio->bi_flags |= (1 << BIO_USER_MAPPED); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 34f7c375567e..64f10082f048 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -480,7 +480,7 @@ static void end_workqueue_bio(struct bio *bio, int err) end_io_wq->work.func = end_workqueue_fn; end_io_wq->work.flags = 0; - if (bio->bi_rw & (1 << BIO_RW)) { + if (bio->bi_rw & REQ_WRITE) { if (end_io_wq->metadata) btrfs_queue_worker(&fs_info->endio_meta_write_workers, &end_io_wq->work); @@ -604,7 +604,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, atomic_inc(&fs_info->nr_async_submits); - if (rw & (1 << BIO_RW_SYNCIO)) + if (rw & REQ_SYNC) btrfs_set_work_high_prio(&async->work); btrfs_queue_worker(&fs_info->workers, &async->work); @@ -668,7 +668,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, bio, 1); BUG_ON(ret); - if (!(rw & (1 << BIO_RW))) { + if (!(rw & REQ_WRITE)) { /* * called for a read, do the setup so that checksum validation * can happen in the async kernel threads @@ -1427,7 +1427,7 @@ static void end_workqueue_fn(struct btrfs_work *work) * ram and up to date before trying to verify things. For * blocksize <= pagesize, it is basically a noop */ - if (!(bio->bi_rw & (1 << BIO_RW)) && end_io_wq->metadata && + if (!(bio->bi_rw & REQ_WRITE) && end_io_wq->metadata && !bio_ready_for_csum(bio)) { btrfs_queue_worker(&fs_info->endio_meta_workers, &end_io_wq->work); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1bff92ad4744..e975d7180a88 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1429,7 +1429,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); BUG_ON(ret); - if (!(rw & (1 << BIO_RW))) { + if (!(rw & REQ_WRITE)) { if (bio_flags & EXTENT_BIO_COMPRESSED) { return btrfs_submit_compressed_read(inode, bio, mirror_num, bio_flags); @@ -1841,7 +1841,7 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, bio->bi_size = 0; bio_add_page(bio, page, failrec->len, start - page_offset(page)); - if (failed_bio->bi_rw & (1 << BIO_RW)) + if (failed_bio->bi_rw & REQ_WRITE) rw = WRITE; else rw = READ; @@ -5642,7 +5642,7 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, struct bio_vec *bvec = bio->bi_io_vec; u64 start; int skip_sum; - int write = rw & (1 << BIO_RW); + int write = rw & REQ_WRITE; int ret = 0; skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index d6e3af8be95b..dd318ff280b2 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -258,7 +258,7 @@ loop_lock: BUG_ON(atomic_read(&cur->bi_cnt) == 0); - if (bio_rw_flagged(cur, BIO_RW_SYNCIO)) + if (cur->bi_rw & REQ_SYNC) num_sync_run++; submit_bio(cur->bi_rw, cur); @@ -2651,7 +2651,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int max_errors = 0; struct btrfs_multi_bio *multi = NULL; - if (multi_ret && !(rw & (1 << BIO_RW))) + if (multi_ret && !(rw & REQ_WRITE)) stripes_allocated = 1; again: if (multi_ret) { @@ -2687,7 +2687,7 @@ again: mirror_num = 0; /* if our multi bio struct is too small, back off and try again */ - if (rw & (1 << BIO_RW)) { + if (rw & REQ_WRITE) { if (map->type & (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP)) { stripes_required = map->num_stripes; @@ -2697,7 +2697,7 @@ again: max_errors = 1; } } - if (multi_ret && (rw & (1 << BIO_RW)) && + if (multi_ret && (rw & REQ_WRITE) && stripes_allocated < stripes_required) { stripes_allocated = map->num_stripes; free_extent_map(em); @@ -2733,7 +2733,7 @@ again: num_stripes = 1; stripe_index = 0; if (map->type & BTRFS_BLOCK_GROUP_RAID1) { - if (unplug_page || (rw & (1 << BIO_RW))) + if (unplug_page || (rw & REQ_WRITE)) num_stripes = map->num_stripes; else if (mirror_num) stripe_index = mirror_num - 1; @@ -2744,7 +2744,7 @@ again: } } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { - if (rw & (1 << BIO_RW)) + if (rw & REQ_WRITE) num_stripes = map->num_stripes; else if (mirror_num) stripe_index = mirror_num - 1; @@ -2755,7 +2755,7 @@ again: stripe_index = do_div(stripe_nr, factor); stripe_index *= map->sub_stripes; - if (unplug_page || (rw & (1 << BIO_RW))) + if (unplug_page || (rw & REQ_WRITE)) num_stripes = map->sub_stripes; else if (mirror_num) stripe_index += mirror_num - 1; @@ -2945,7 +2945,7 @@ static noinline int schedule_bio(struct btrfs_root *root, struct btrfs_pending_bios *pending_bios; /* don't bother with additional async steps for reads, right now */ - if (!(rw & (1 << BIO_RW))) { + if (!(rw & REQ_WRITE)) { bio_get(bio); submit_bio(rw, bio); bio_put(bio); @@ -2964,7 +2964,7 @@ static noinline int schedule_bio(struct btrfs_root *root, bio->bi_rw |= rw; spin_lock(&device->io_lock); - if (bio_rw_flagged(bio, BIO_RW_SYNCIO)) + if (bio->bi_rw & REQ_SYNC) pending_bios = &device->pending_sync_bios; else pending_bios = &device->pending_bios; diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c index 4337cad7777b..e2732203fa93 100644 --- a/fs/exofs/ios.c +++ b/fs/exofs/ios.c @@ -599,7 +599,7 @@ static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp) } else { bio = master_dev->bio; /* FIXME: bio_set_dir() */ - bio->bi_rw |= (1 << BIO_RW); + bio->bi_rw |= REQ_WRITE; } osd_req_write(or, &ios->obj, per_dev->offset, bio, diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index efc3539ac5a1..cde1248a6225 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -595,7 +595,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) goto skip_barrier; get_bh(bh); - submit_bh(WRITE_BARRIER | (1 << BIO_RW_META), bh); + submit_bh(WRITE_BARRIER | REQ_META, bh); wait_on_buffer(bh); if (buffer_eopnotsupp(bh)) { clear_buffer_eopnotsupp(bh); @@ -605,7 +605,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) lock_buffer(bh); skip_barrier: get_bh(bh); - submit_bh(WRITE_SYNC | (1 << BIO_RW_META), bh); + submit_bh(WRITE_SYNC | REQ_META, bh); wait_on_buffer(bh); } if (!buffer_uptodate(bh)) diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 18176d0b75d7..f3b071f921aa 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -36,8 +36,8 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb { struct buffer_head *bh, *head; int nr_underway = 0; - int write_op = (1 << BIO_RW_META) | ((wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC_PLUG : WRITE)); + int write_op = REQ_META | + (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC_PLUG : WRITE); BUG_ON(!PageLocked(page)); BUG_ON(!page_has_buffers(page)); @@ -225,7 +225,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, } bh->b_end_io = end_buffer_read_sync; get_bh(bh); - submit_bh(READ_SYNC | (1 << BIO_RW_META), bh); + submit_bh(READ_SYNC | REQ_META, bh); if (!(flags & DIO_WAIT)) return 0; @@ -432,7 +432,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) if (buffer_uptodate(first_bh)) goto out; if (!buffer_locked(first_bh)) - ll_rw_block(READ_SYNC | (1 << BIO_RW_META), 1, &first_bh); + ll_rw_block(READ_SYNC | REQ_META, 1, &first_bh); dblock++; extlen--; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 3593b3a7290e..fd4f8946abf5 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -275,7 +275,7 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) bio->bi_end_io = end_bio_io_page; bio->bi_private = page; - submit_bio(READ_SYNC | (1 << BIO_RW_META), bio); + submit_bio(READ_SYNC | REQ_META, bio); wait_on_page_locked(page); bio_put(bio); if (!PageUptodate(page)) { diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 2e6a2723b8fa..4588fb9e93df 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -508,7 +508,7 @@ static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, * Last BIO is always sent through the following * submission. */ - rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); + rw |= REQ_SYNC | REQ_UNPLUG; res = nilfs_segbuf_submit_bio(segbuf, &wi, rw); } diff --git a/include/linux/bio.h b/include/linux/bio.h index 7fc5606e6ea5..4d379c8250ae 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -138,55 +138,83 @@ struct bio { #define BIO_POOL_IDX(bio) ((bio)->bi_flags >> BIO_POOL_OFFSET) /* - * bio bi_rw flags - * - * bit 0 -- data direction - * If not set, bio is a read from device. If set, it's a write to device. - * bit 1 -- fail fast device errors - * bit 2 -- fail fast transport errors - * bit 3 -- fail fast driver errors - * bit 4 -- rw-ahead when set - * bit 5 -- barrier - * Insert a serialization point in the IO queue, forcing previously - * submitted IO to be completed before this one is issued. - * bit 6 -- synchronous I/O hint. - * bit 7 -- Unplug the device immediately after submitting this bio. - * bit 8 -- metadata request - * Used for tracing to differentiate metadata and data IO. May also - * get some preferential treatment in the IO scheduler - * bit 9 -- discard sectors - * Informs the lower level device that this range of sectors is no longer - * used by the file system and may thus be freed by the device. Used - * for flash based storage. - * Don't want driver retries for any fast fail whatever the reason. - * bit 10 -- Tell the IO scheduler not to wait for more requests after this - one has been submitted, even if it is a SYNC request. + * Request flags. For use in the cmd_flags field of struct request, and in + * bi_rw of struct bio. Note that some flags are only valid in either one. */ -enum bio_rw_flags { - BIO_RW, - BIO_RW_FAILFAST_DEV, - BIO_RW_FAILFAST_TRANSPORT, - BIO_RW_FAILFAST_DRIVER, - /* above flags must match REQ_* */ - BIO_RW_AHEAD, - BIO_RW_BARRIER, - BIO_RW_SYNCIO, - BIO_RW_UNPLUG, - BIO_RW_META, - BIO_RW_DISCARD, - BIO_RW_NOIDLE, +enum rq_flag_bits { + /* common flags */ + __REQ_WRITE, /* not set, read. set, write */ + __REQ_FAILFAST_DEV, /* no driver retries of device errors */ + __REQ_FAILFAST_TRANSPORT, /* no driver retries of transport errors */ + __REQ_FAILFAST_DRIVER, /* no driver retries of driver errors */ + + __REQ_HARDBARRIER, /* may not be passed by drive either */ + __REQ_SYNC, /* request is sync (sync write or read) */ + __REQ_META, /* metadata io request */ + __REQ_DISCARD, /* request to discard sectors */ + __REQ_NOIDLE, /* don't anticipate more IO after this one */ + + /* bio only flags */ + __REQ_UNPLUG, /* unplug the immediately after submission */ + __REQ_RAHEAD, /* read ahead, can fail anytime */ + + /* request only flags */ + __REQ_SORTED, /* elevator knows about this request */ + __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ + __REQ_FUA, /* forced unit access */ + __REQ_NOMERGE, /* don't touch this for merging */ + __REQ_STARTED, /* drive already may have started this one */ + __REQ_DONTPREP, /* don't call prep for this one */ + __REQ_QUEUED, /* uses queueing */ + __REQ_ELVPRIV, /* elevator private data attached */ + __REQ_FAILED, /* set if the request failed */ + __REQ_QUIET, /* don't worry about errors */ + __REQ_PREEMPT, /* set for "ide_preempt" requests */ + __REQ_ORDERED_COLOR, /* is before or after barrier */ + __REQ_ALLOCED, /* request came from our alloc pool */ + __REQ_COPY_USER, /* contains copies of user pages */ + __REQ_INTEGRITY, /* integrity metadata has been remapped */ + __REQ_IO_STAT, /* account I/O stat */ + __REQ_MIXED_MERGE, /* merge of different types, fail separately */ + __REQ_NR_BITS, /* stops here */ }; -/* - * First four bits must match between bio->bi_rw and rq->cmd_flags, make - * that explicit here. - */ -#define BIO_RW_RQ_MASK 0xf - -static inline bool bio_rw_flagged(struct bio *bio, enum bio_rw_flags flag) -{ - return (bio->bi_rw & (1 << flag)) != 0; -} +#define REQ_WRITE (1 << __REQ_WRITE) +#define REQ_FAILFAST_DEV (1 << __REQ_FAILFAST_DEV) +#define REQ_FAILFAST_TRANSPORT (1 << __REQ_FAILFAST_TRANSPORT) +#define REQ_FAILFAST_DRIVER (1 << __REQ_FAILFAST_DRIVER) +#define REQ_HARDBARRIER (1 << __REQ_HARDBARRIER) +#define REQ_SYNC (1 << __REQ_SYNC) +#define REQ_META (1 << __REQ_META) +#define REQ_DISCARD (1 << __REQ_DISCARD) +#define REQ_NOIDLE (1 << __REQ_NOIDLE) + +#define REQ_FAILFAST_MASK \ + (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) +#define REQ_COMMON_MASK \ + (REQ_WRITE | REQ_FAILFAST_MASK | REQ_HARDBARRIER | REQ_SYNC | \ + REQ_META| REQ_DISCARD | REQ_NOIDLE) + +#define REQ_UNPLUG (1 << __REQ_UNPLUG) +#define REQ_RAHEAD (1 << __REQ_RAHEAD) + +#define REQ_SORTED (1 << __REQ_SORTED) +#define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER) +#define REQ_FUA (1 << __REQ_FUA) +#define REQ_NOMERGE (1 << __REQ_NOMERGE) +#define REQ_STARTED (1 << __REQ_STARTED) +#define REQ_DONTPREP (1 << __REQ_DONTPREP) +#define REQ_QUEUED (1 << __REQ_QUEUED) +#define REQ_ELVPRIV (1 << __REQ_ELVPRIV) +#define REQ_FAILED (1 << __REQ_FAILED) +#define REQ_QUIET (1 << __REQ_QUIET) +#define REQ_PREEMPT (1 << __REQ_PREEMPT) +#define REQ_ORDERED_COLOR (1 << __REQ_ORDERED_COLOR) +#define REQ_ALLOCED (1 << __REQ_ALLOCED) +#define REQ_COPY_USER (1 << __REQ_COPY_USER) +#define REQ_INTEGRITY (1 << __REQ_INTEGRITY) +#define REQ_IO_STAT (1 << __REQ_IO_STAT) +#define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE) /* * upper 16 bits of bi_rw define the io priority of this bio @@ -211,7 +239,10 @@ static inline bool bio_rw_flagged(struct bio *bio, enum bio_rw_flags flag) #define bio_offset(bio) bio_iovec((bio))->bv_offset #define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_idx) #define bio_sectors(bio) ((bio)->bi_size >> 9) -#define bio_empty_barrier(bio) (bio_rw_flagged(bio, BIO_RW_BARRIER) && !bio_has_data(bio) && !bio_rw_flagged(bio, BIO_RW_DISCARD)) +#define bio_empty_barrier(bio) \ + ((bio->bi_rw & REQ_HARDBARRIER) && \ + !bio_has_data(bio) && \ + !(bio->bi_rw & REQ_DISCARD)) static inline unsigned int bio_cur_bytes(struct bio *bio) { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3ecd28ef9ba4..3fc0f5908619 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -84,70 +84,6 @@ enum { REQ_LB_OP_FLUSH = 0x41, /* flush request */ }; -/* - * request type modified bits. first four bits match BIO_RW* bits, important - */ -enum rq_flag_bits { - __REQ_RW, /* not set, read. set, write */ - __REQ_FAILFAST_DEV, /* no driver retries of device errors */ - __REQ_FAILFAST_TRANSPORT, /* no driver retries of transport errors */ - __REQ_FAILFAST_DRIVER, /* no driver retries of driver errors */ - /* above flags must match BIO_RW_* */ - __REQ_DISCARD, /* request to discard sectors */ - __REQ_SORTED, /* elevator knows about this request */ - __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ - __REQ_HARDBARRIER, /* may not be passed by drive either */ - __REQ_FUA, /* forced unit access */ - __REQ_NOMERGE, /* don't touch this for merging */ - __REQ_STARTED, /* drive already may have started this one */ - __REQ_DONTPREP, /* don't call prep for this one */ - __REQ_QUEUED, /* uses queueing */ - __REQ_ELVPRIV, /* elevator private data attached */ - __REQ_FAILED, /* set if the request failed */ - __REQ_QUIET, /* don't worry about errors */ - __REQ_PREEMPT, /* set for "ide_preempt" requests */ - __REQ_ORDERED_COLOR, /* is before or after barrier */ - __REQ_RW_SYNC, /* request is sync (sync write or read) */ - __REQ_ALLOCED, /* request came from our alloc pool */ - __REQ_RW_META, /* metadata io request */ - __REQ_COPY_USER, /* contains copies of user pages */ - __REQ_INTEGRITY, /* integrity metadata has been remapped */ - __REQ_NOIDLE, /* Don't anticipate more IO after this one */ - __REQ_IO_STAT, /* account I/O stat */ - __REQ_MIXED_MERGE, /* merge of different types, fail separately */ - __REQ_NR_BITS, /* stops here */ -}; - -#define REQ_RW (1 << __REQ_RW) -#define REQ_FAILFAST_DEV (1 << __REQ_FAILFAST_DEV) -#define REQ_FAILFAST_TRANSPORT (1 << __REQ_FAILFAST_TRANSPORT) -#define REQ_FAILFAST_DRIVER (1 << __REQ_FAILFAST_DRIVER) -#define REQ_DISCARD (1 << __REQ_DISCARD) -#define REQ_SORTED (1 << __REQ_SORTED) -#define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER) -#define REQ_HARDBARRIER (1 << __REQ_HARDBARRIER) -#define REQ_FUA (1 << __REQ_FUA) -#define REQ_NOMERGE (1 << __REQ_NOMERGE) -#define REQ_STARTED (1 << __REQ_STARTED) -#define REQ_DONTPREP (1 << __REQ_DONTPREP) -#define REQ_QUEUED (1 << __REQ_QUEUED) -#define REQ_ELVPRIV (1 << __REQ_ELVPRIV) -#define REQ_FAILED (1 << __REQ_FAILED) -#define REQ_QUIET (1 << __REQ_QUIET) -#define REQ_PREEMPT (1 << __REQ_PREEMPT) -#define REQ_ORDERED_COLOR (1 << __REQ_ORDERED_COLOR) -#define REQ_RW_SYNC (1 << __REQ_RW_SYNC) -#define REQ_ALLOCED (1 << __REQ_ALLOCED) -#define REQ_RW_META (1 << __REQ_RW_META) -#define REQ_COPY_USER (1 << __REQ_COPY_USER) -#define REQ_INTEGRITY (1 << __REQ_INTEGRITY) -#define REQ_NOIDLE (1 << __REQ_NOIDLE) -#define REQ_IO_STAT (1 << __REQ_IO_STAT) -#define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE) - -#define REQ_FAILFAST_MASK (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | \ - REQ_FAILFAST_DRIVER) - #define BLK_MAX_CDB 16 /* @@ -631,7 +567,7 @@ enum { */ static inline bool rw_is_sync(unsigned int rw_flags) { - return !(rw_flags & REQ_RW) || (rw_flags & REQ_RW_SYNC); + return !(rw_flags & REQ_WRITE) || (rw_flags & REQ_SYNC); } static inline bool rq_is_sync(struct request *rq) diff --git a/include/linux/fs.h b/include/linux/fs.h index 598878831497..c5c92943c767 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -144,29 +144,31 @@ struct inodes_stat_t { * of this IO. * */ -#define RW_MASK 1 -#define RWA_MASK 2 -#define READ 0 -#define WRITE 1 -#define READA 2 /* read-ahead - don't block if no resources */ -#define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ -#define READ_SYNC (READ | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG)) -#define READ_META (READ | (1 << BIO_RW_META)) -#define WRITE_SYNC_PLUG (WRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_NOIDLE)) -#define WRITE_SYNC (WRITE_SYNC_PLUG | (1 << BIO_RW_UNPLUG)) -#define WRITE_ODIRECT_PLUG (WRITE | (1 << BIO_RW_SYNCIO)) -#define WRITE_META (WRITE | (1 << BIO_RW_META)) -#define SWRITE_SYNC_PLUG \ - (SWRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_NOIDLE)) -#define SWRITE_SYNC (SWRITE_SYNC_PLUG | (1 << BIO_RW_UNPLUG)) -#define WRITE_BARRIER (WRITE_SYNC | (1 << BIO_RW_BARRIER)) +#define RW_MASK 1 +#define RWA_MASK 2 + +#define READ 0 +#define WRITE 1 +#define READA 2 /* readahead - don't block if no resources */ +#define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ + +#define READ_SYNC (READ | REQ_SYNC | REQ_UNPLUG) +#define READ_META (READ | REQ_META) +#define WRITE_SYNC_PLUG (WRITE | REQ_SYNC | REQ_NOIDLE) +#define WRITE_SYNC (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG) +#define WRITE_ODIRECT_PLUG (WRITE | REQ_SYNC) +#define WRITE_META (WRITE | REQ_META) +#define WRITE_BARRIER (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \ + REQ_HARDBARRIER) +#define SWRITE_SYNC_PLUG (SWRITE | REQ_SYNC | REQ_NOIDLE) +#define SWRITE_SYNC (SWRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG) /* * These aren't really reads or writes, they pass down information about * parts of device that are now unused by the file system. */ -#define DISCARD_NOBARRIER (WRITE | (1 << BIO_RW_DISCARD)) -#define DISCARD_BARRIER (DISCARD_NOBARRIER | (1 << BIO_RW_BARRIER)) +#define DISCARD_NOBARRIER (WRITE | REQ_DISCARD) +#define DISCARD_BARRIER (WRITE | REQ_DISCARD | REQ_HARDBARRIER) #define SEL_IN 1 #define SEL_OUT 2 diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c index 97024fd40cd5..83bbc7c02df9 100644 --- a/kernel/power/block_io.c +++ b/kernel/power/block_io.c @@ -28,7 +28,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector, struct page *page, struct bio **bio_chain) { - const int bio_rw = rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); + const int bio_rw = rw | REQ_SYNC | REQ_UNPLUG; struct bio *bio; bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 4f149944cb89..3b4a695051b6 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -169,9 +169,12 @@ static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, static const u32 ddir_act[2] = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK_TC_WRITE) }; +#define BLK_TC_HARDBARRIER BLK_TC_BARRIER +#define BLK_TC_RAHEAD BLK_TC_AHEAD + /* The ilog2() calls fall out because they're constant */ -#define MASK_TC_BIT(rw, __name) ((rw & (1 << BIO_RW_ ## __name)) << \ - (ilog2(BLK_TC_ ## __name) + BLK_TC_SHIFT - BIO_RW_ ## __name)) +#define MASK_TC_BIT(rw, __name) ((rw & REQ_ ## __name) << \ + (ilog2(BLK_TC_ ## __name) + BLK_TC_SHIFT - __REQ_ ## __name)) /* * The worker for the various blk_add_trace*() types. Fills out a @@ -194,9 +197,9 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, return; what |= ddir_act[rw & WRITE]; - what |= MASK_TC_BIT(rw, BARRIER); - what |= MASK_TC_BIT(rw, SYNCIO); - what |= MASK_TC_BIT(rw, AHEAD); + what |= MASK_TC_BIT(rw, HARDBARRIER); + what |= MASK_TC_BIT(rw, SYNC); + what |= MASK_TC_BIT(rw, RAHEAD); what |= MASK_TC_BIT(rw, META); what |= MASK_TC_BIT(rw, DISCARD); @@ -662,7 +665,7 @@ static void blk_add_trace_rq(struct request_queue *q, struct request *rq, return; if (rq->cmd_flags & REQ_DISCARD) - rw |= (1 << BIO_RW_DISCARD); + rw |= REQ_DISCARD; if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { what |= BLK_TC_ACT(BLK_TC_PC); @@ -1755,20 +1758,20 @@ void blk_fill_rwbs(char *rwbs, u32 rw, int bytes) if (rw & WRITE) rwbs[i++] = 'W'; - else if (rw & 1 << BIO_RW_DISCARD) + else if (rw & REQ_DISCARD) rwbs[i++] = 'D'; else if (bytes) rwbs[i++] = 'R'; else rwbs[i++] = 'N'; - if (rw & 1 << BIO_RW_AHEAD) + if (rw & REQ_RAHEAD) rwbs[i++] = 'A'; - if (rw & 1 << BIO_RW_BARRIER) + if (rw & REQ_HARDBARRIER) rwbs[i++] = 'B'; - if (rw & 1 << BIO_RW_SYNCIO) + if (rw & REQ_SYNC) rwbs[i++] = 'S'; - if (rw & 1 << BIO_RW_META) + if (rw & REQ_META) rwbs[i++] = 'M'; rwbs[i] = '\0'; @@ -1780,7 +1783,7 @@ void blk_fill_rwbs_rq(char *rwbs, struct request *rq) int bytes; if (rq->cmd_flags & REQ_DISCARD) - rw |= (1 << BIO_RW_DISCARD); + rw |= REQ_DISCARD; bytes = blk_rq_bytes(rq); diff --git a/mm/page_io.c b/mm/page_io.c index 31a3b962230a..2dee975bf469 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -106,7 +106,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) goto out; } if (wbc->sync_mode == WB_SYNC_ALL) - rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); + rw |= REQ_SYNC | REQ_UNPLUG; count_vm_event(PSWPOUT); set_page_writeback(page); unlock_page(page); -- cgit v1.2.3 From 66ac0280197981f88774e74b60c8e5f9f07c1dba Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 18 Jun 2010 16:59:42 +0200 Subject: block: don't allocate a payload for discard request Allocating a fixed payload for discard requests always was a horrible hack, and it's not coming to byte us when adding support for discard in DM/MD. So change the code to leave the allocation of a payload to the lowlevel driver. Unfortunately that means we'll need another hack, which allows us to update the various block layer length fields indicating that we have a payload. Instead of hiding this in sd.c, which we already partially do for UNMAP support add a documented helper in the core block layer for it. Signed-off-by: Christoph Hellwig Acked-by: Mike Snitzer Signed-off-by: Jens Axboe --- block/blk-core.c | 32 +++++++++++++++++++++++++++++++ block/blk-lib.c | 33 ++++++-------------------------- drivers/scsi/sd.c | 52 +++++++++++++++++++++++++++++++++----------------- include/linux/blkdev.h | 2 ++ 4 files changed, 74 insertions(+), 45 deletions(-) (limited to 'drivers/scsi') diff --git a/block/blk-core.c b/block/blk-core.c index 66c3cfe94d0a..3531d8e1da04 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1135,6 +1135,38 @@ void blk_put_request(struct request *req) } EXPORT_SYMBOL(blk_put_request); +/** + * blk_add_request_payload - add a payload to a request + * @rq: request to update + * @page: page backing the payload + * @len: length of the payload. + * + * This allows to later add a payload to an already submitted request by + * a block driver. The driver needs to take care of freeing the payload + * itself. + * + * Note that this is a quite horrible hack and nothing but handling of + * discard requests should ever use it. + */ +void blk_add_request_payload(struct request *rq, struct page *page, + unsigned int len) +{ + struct bio *bio = rq->bio; + + bio->bi_io_vec->bv_page = page; + bio->bi_io_vec->bv_offset = 0; + bio->bi_io_vec->bv_len = len; + + bio->bi_size = len; + bio->bi_vcnt = 1; + bio->bi_phys_segments = 1; + + rq->__data_len = rq->resid_len = len; + rq->nr_phys_segments = 1; + rq->buffer = bio_data(bio); +} +EXPORT_SYMBOL_GPL(blk_add_request_payload); + void init_request_from_bio(struct request *req, struct bio *bio) { req->cpu = bio->bi_comp_cpu; diff --git a/block/blk-lib.c b/block/blk-lib.c index d0216b9f22d4..e16185b0d8e1 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -19,7 +19,6 @@ static void blkdev_discard_end_io(struct bio *bio, int err) if (bio->bi_private) complete(bio->bi_private); - __free_page(bio_page(bio)); bio_put(bio); } @@ -43,7 +42,6 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, int type = flags & BLKDEV_IFL_BARRIER ? DISCARD_BARRIER : DISCARD_NOBARRIER; struct bio *bio; - struct page *page; int ret = 0; if (!q) @@ -53,35 +51,21 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, return -EOPNOTSUPP; while (nr_sects && !ret) { - unsigned int sector_size = q->limits.logical_block_size; unsigned int max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9); bio = bio_alloc(gfp_mask, 1); - if (!bio) - goto out; + if (!bio) { + ret = -ENOMEM; + break; + } + bio->bi_sector = sector; bio->bi_end_io = blkdev_discard_end_io; bio->bi_bdev = bdev; if (flags & BLKDEV_IFL_WAIT) bio->bi_private = &wait; - /* - * Add a zeroed one-sector payload as that's what - * our current implementations need. If we'll ever need - * more the interface will need revisiting. - */ - page = alloc_page(gfp_mask | __GFP_ZERO); - if (!page) - goto out_free_bio; - if (bio_add_pc_page(q, bio, page, sector_size, 0) < sector_size) - goto out_free_page; - - /* - * And override the bio size - the way discard works we - * touch many more blocks on disk than the actual payload - * length. - */ if (nr_sects > max_discard_sectors) { bio->bi_size = max_discard_sectors << 9; nr_sects -= max_discard_sectors; @@ -103,13 +87,8 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, ret = -EIO; bio_put(bio); } + return ret; -out_free_page: - __free_page(page); -out_free_bio: - bio_put(bio); -out: - return -ENOMEM; } EXPORT_SYMBOL(blkdev_issue_discard); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a3fdf4dc59da..86da819c70eb 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -411,22 +411,25 @@ static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) } /** - * sd_prepare_discard - unmap blocks on thinly provisioned device + * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device + * @sdp: scsi device to operate one * @rq: Request to prepare * * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ -static int sd_prepare_discard(struct request *rq) +static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) { struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); struct bio *bio = rq->bio; sector_t sector = bio->bi_sector; - unsigned int num = bio_sectors(bio); + unsigned int nr_sectors = bio_sectors(bio); + unsigned int len; + struct page *page; if (sdkp->device->sector_size == 4096) { sector >>= 3; - num >>= 3; + nr_sectors >>= 3; } rq->cmd_type = REQ_TYPE_BLOCK_PC; @@ -434,31 +437,35 @@ static int sd_prepare_discard(struct request *rq) memset(rq->cmd, 0, rq->cmd_len); + page = alloc_page(GFP_ATOMIC | __GFP_ZERO); + if (!page) + return BLKPREP_DEFER; + if (sdkp->unmap) { - char *buf = kmap_atomic(bio_page(bio), KM_USER0); + char *buf = page_address(page); + rq->cmd_len = 10; rq->cmd[0] = UNMAP; rq->cmd[8] = 24; - rq->cmd_len = 10; - - /* Ensure that data length matches payload */ - rq->__data_len = bio->bi_size = bio->bi_io_vec->bv_len = 24; put_unaligned_be16(6 + 16, &buf[0]); put_unaligned_be16(16, &buf[2]); put_unaligned_be64(sector, &buf[8]); - put_unaligned_be32(num, &buf[16]); + put_unaligned_be32(nr_sectors, &buf[16]); - kunmap_atomic(buf, KM_USER0); + len = 24; } else { + rq->cmd_len = 16; rq->cmd[0] = WRITE_SAME_16; rq->cmd[1] = 0x8; /* UNMAP */ put_unaligned_be64(sector, &rq->cmd[2]); - put_unaligned_be32(num, &rq->cmd[10]); - rq->cmd_len = 16; + put_unaligned_be32(nr_sectors, &rq->cmd[10]); + + len = sdkp->device->sector_size; } - return BLKPREP_OK; + blk_add_request_payload(rq, page, len); + return scsi_setup_blk_pc_cmnd(sdp, rq); } /** @@ -485,10 +492,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * Discard request come in as REQ_TYPE_FS but we turn them into * block PC requests to make life easier. */ - if (rq->cmd_flags & REQ_DISCARD) - ret = sd_prepare_discard(rq); - - if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { + if (rq->cmd_flags & REQ_DISCARD) { + ret = scsi_setup_discard_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { ret = scsi_setup_blk_pc_cmnd(sdp, rq); goto out; } else if (rq->cmd_type != REQ_TYPE_FS) { @@ -1163,6 +1170,15 @@ static int sd_done(struct scsi_cmnd *SCpnt) int sense_valid = 0; int sense_deferred = 0; + /* + * If this is a discard request that originated from the kernel + * we need to free our payload here. Note that we need to check + * the request flag as the normal payload rules apply for + * pass-through UNMAP / WRITE SAME requests. + */ + if (SCpnt->request->cmd_flags & REQ_DISCARD) + __free_page(bio_page(SCpnt->request->bio)); + if (result) { sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); if (sense_valid) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3fc0f5908619..204fbe22354d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -705,6 +705,8 @@ extern struct request *blk_make_request(struct request_queue *, struct bio *, gfp_t); extern void blk_insert_request(struct request_queue *, struct request *, int, void *); extern void blk_requeue_request(struct request_queue *, struct request *); +extern void blk_add_request_payload(struct request *rq, struct page *page, + unsigned int len); extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); extern int blk_lld_busy(struct request_queue *q); extern int blk_rq_prep_clone(struct request *rq, struct request *rq_src, -- cgit v1.2.3 From 28018c242a4ec7017bbbf81d2d3952f820a27118 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 1 Jul 2010 19:49:17 +0900 Subject: block: implement an unprep function corresponding directly to prep Reviewed-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- block/blk-core.c | 25 +++++++++++++++++++++++++ block/blk-settings.c | 17 +++++++++++++++++ drivers/scsi/scsi_lib.c | 2 +- include/linux/blkdev.h | 4 ++++ 4 files changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/block/blk-core.c b/block/blk-core.c index 3c3789492c10..5ab3ac22930c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -608,6 +608,7 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, q->request_fn = rfn; q->prep_rq_fn = NULL; + q->unprep_rq_fn = NULL; q->unplug_fn = generic_unplug_device; q->queue_flags = QUEUE_FLAG_DEFAULT; q->queue_lock = lock; @@ -2133,6 +2134,26 @@ static bool blk_update_bidi_request(struct request *rq, int error, return false; } +/** + * blk_unprep_request - unprepare a request + * @req: the request + * + * This function makes a request ready for complete resubmission (or + * completion). It happens only after all error handling is complete, + * so represents the appropriate moment to deallocate any resources + * that were allocated to the request in the prep_rq_fn. The queue + * lock is held when calling this. + */ +void blk_unprep_request(struct request *req) +{ + struct request_queue *q = req->q; + + req->cmd_flags &= ~REQ_DONTPREP; + if (q->unprep_rq_fn) + q->unprep_rq_fn(q, req); +} +EXPORT_SYMBOL_GPL(blk_unprep_request); + /* * queue lock must be held */ @@ -2148,6 +2169,10 @@ static void blk_finish_request(struct request *req, int error) blk_delete_timer(req); + if (req->cmd_flags & REQ_DONTPREP) + blk_unprep_request(req); + + blk_account_io_done(req); if (req->end_io) diff --git a/block/blk-settings.c b/block/blk-settings.c index f5ed5a1187ba..a234f4bf1d6f 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -36,6 +36,23 @@ void blk_queue_prep_rq(struct request_queue *q, prep_rq_fn *pfn) } EXPORT_SYMBOL(blk_queue_prep_rq); +/** + * blk_queue_unprep_rq - set an unprepare_request function for queue + * @q: queue + * @ufn: unprepare_request function + * + * It's possible for a queue to register an unprepare_request callback + * which is invoked before the request is finally completed. The goal + * of the function is to deallocate any data that was allocated in the + * prepare_request callback. + * + */ +void blk_queue_unprep_rq(struct request_queue *q, unprep_rq_fn *ufn) +{ + q->unprep_rq_fn = ufn; +} +EXPORT_SYMBOL(blk_queue_unprep_rq); + /** * blk_queue_merge_bvec - set a merge_bvec function for queue * @q: queue diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5f1160841b0e..ee836193f531 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -85,7 +85,7 @@ static void scsi_unprep_request(struct request *req) { struct scsi_cmnd *cmd = req->special; - req->cmd_flags &= ~REQ_DONTPREP; + blk_unprep_request(req); req->special = NULL; scsi_put_command(cmd); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 204fbe22354d..6bba04c7ec48 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -200,6 +200,7 @@ struct request_pm_state typedef void (request_fn_proc) (struct request_queue *q); typedef int (make_request_fn) (struct request_queue *q, struct bio *bio); typedef int (prep_rq_fn) (struct request_queue *, struct request *); +typedef void (unprep_rq_fn) (struct request_queue *, struct request *); typedef void (unplug_fn) (struct request_queue *); struct bio_vec; @@ -282,6 +283,7 @@ struct request_queue request_fn_proc *request_fn; make_request_fn *make_request_fn; prep_rq_fn *prep_rq_fn; + unprep_rq_fn *unprep_rq_fn; unplug_fn *unplug_fn; merge_bvec_fn *merge_bvec_fn; prepare_flush_fn *prepare_flush_fn; @@ -841,6 +843,7 @@ extern void blk_complete_request(struct request *); extern void __blk_complete_request(struct request *); extern void blk_abort_request(struct request *); extern void blk_abort_queue(struct request_queue *); +extern void blk_unprep_request(struct request *); /* * Access functions for manipulating queue properties @@ -885,6 +888,7 @@ extern int blk_queue_dma_drain(struct request_queue *q, extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn); extern void blk_queue_segment_boundary(struct request_queue *, unsigned long); extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn); +extern void blk_queue_unprep_rq(struct request_queue *, unprep_rq_fn *ufn); extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *); extern void blk_queue_dma_alignment(struct request_queue *, int); extern void blk_queue_update_dma_alignment(struct request_queue *, int); -- cgit v1.2.3 From f1126e950d28ff875d96ed6a04a9ff96c7bfc357 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 1 Jul 2010 19:49:18 +0900 Subject: scsi: add sd_unprep_fn to free discard page This fixes discard page leak by using q->unprep_rq_fn facility. q->unprep_rq_fn is called when all the data buffer (req->bio and scsi_data_buffer) in the request is freed. sd_unprep() uses rq->buffer to free discard page allocated in sd_prepare_discard(). Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 86da819c70eb..2d4e3a865f39 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -425,6 +425,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) sector_t sector = bio->bi_sector; unsigned int nr_sectors = bio_sectors(bio); unsigned int len; + int ret; struct page *page; if (sdkp->device->sector_size == 4096) { @@ -465,7 +466,15 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) } blk_add_request_payload(rq, page, len); - return scsi_setup_blk_pc_cmnd(sdp, rq); + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + rq->buffer = page_address(page); + return ret; +} + +static void sd_unprep_fn(struct request_queue *q, struct request *rq) +{ + if (rq->cmd_flags & REQ_DISCARD) + __free_page(virt_to_page(rq->buffer)); } /** @@ -2242,6 +2251,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) sd_revalidate_disk(gd); blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); + blk_queue_unprep_rq(sdp->request_queue, sd_unprep_fn); gd->driverfs_dev = &sdp->sdev_gendev; gd->flags = GENHD_FL_EXT_DEVT; -- cgit v1.2.3 From 802447c1c0513a0ea0e29d6bda23b19ac0686654 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 1 Jul 2010 19:49:19 +0900 Subject: scsi: remove unused free discard page in sd_done - sd_done isn't called for pc request so we never call the code. - we use sd_unprep to free discard page now. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2d4e3a865f39..aa6b48ba78b1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1179,15 +1179,6 @@ static int sd_done(struct scsi_cmnd *SCpnt) int sense_valid = 0; int sense_deferred = 0; - /* - * If this is a discard request that originated from the kernel - * we need to free our payload here. Note that we need to check - * the request flag as the normal payload rules apply for - * pass-through UNMAP / WRITE SAME requests. - */ - if (SCpnt->request->cmd_flags & REQ_DISCARD) - __free_page(bio_page(SCpnt->request->bio)); - if (result) { sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); if (sense_valid) -- cgit v1.2.3 From 90467c294aba7f911bdae72ed86995cf1de4d364 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 3 Jul 2010 17:45:34 +0900 Subject: scsi: stop using q->prepare_flush_fn scsi-ml builds flush requests via q->prepare_flush_fn(), however, builds discard requests via q->prep_rq_fn. Using two different mechnisms for the similar requests (building commands in SCSI ULD) doesn't make sense. Handing both via q->prep_rq_fn makes the code design simpler. Signed-off-by: FUJITA Tomonori Cc: James Bottomley Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index aa6b48ba78b1..e8c295e01466 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -471,6 +471,18 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) return ret; } +static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) +{ + /* for now, we use REQ_TYPE_BLOCK_PC. */ + rq->cmd_type = REQ_TYPE_BLOCK_PC; + rq->timeout = SD_TIMEOUT; + rq->retries = SD_MAX_RETRIES; + rq->cmd[0] = SYNCHRONIZE_CACHE; + rq->cmd_len = 10; + + return scsi_setup_blk_pc_cmnd(sdp, rq); +} + static void sd_unprep_fn(struct request_queue *q, struct request *rq) { if (rq->cmd_flags & REQ_DISCARD) @@ -504,6 +516,9 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) if (rq->cmd_flags & REQ_DISCARD) { ret = scsi_setup_discard_cmnd(sdp, rq); goto out; + } else if (rq->cmd_flags & REQ_FLUSH) { + ret = scsi_setup_flush_cmnd(sdp, rq); + goto out; } else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { ret = scsi_setup_blk_pc_cmnd(sdp, rq); goto out; @@ -1053,15 +1068,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp) return 0; } -static void sd_prepare_flush(struct request_queue *q, struct request *rq) -{ - rq->cmd_type = REQ_TYPE_BLOCK_PC; - rq->timeout = SD_TIMEOUT; - rq->retries = SD_MAX_RETRIES; - rq->cmd[0] = SYNCHRONIZE_CACHE; - rq->cmd_len = 10; -} - static void sd_rescan(struct device *dev) { struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); @@ -2129,7 +2135,7 @@ static int sd_revalidate_disk(struct gendisk *disk) else ordered = QUEUE_ORDERED_DRAIN; - blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush); + blk_queue_ordered(sdkp->disk->queue, ordered, NULL); set_capacity(disk, sdkp->capacity); kfree(buffer); -- cgit v1.2.3 From 00fff26539bfe3fad21c164fc4002d9ede056fb0 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 3 Jul 2010 17:45:40 +0900 Subject: block: remove q->prepare_flush_fn completely This removes q->prepare_flush_fn completely (changes the blk_queue_ordered API). Signed-off-by: FUJITA Tomonori Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-barrier.c | 7 +------ drivers/block/brd.c | 2 +- drivers/block/loop.c | 2 +- drivers/block/osdblk.c | 2 +- drivers/block/ps3disk.c | 2 +- drivers/block/virtio_blk.c | 4 ++-- drivers/block/xen-blkfront.c | 3 +-- drivers/ide/ide-disk.c | 2 +- drivers/md/dm.c | 2 +- drivers/mmc/card/queue.c | 2 +- drivers/s390/block/dasd.c | 2 +- drivers/scsi/sd.c | 2 +- include/linux/blkdev.h | 4 +--- 13 files changed, 14 insertions(+), 22 deletions(-) (limited to 'drivers/scsi') diff --git a/block/blk-barrier.c b/block/blk-barrier.c index 7ce0a32a21fd..eefbde835308 100644 --- a/block/blk-barrier.c +++ b/block/blk-barrier.c @@ -13,7 +13,6 @@ * blk_queue_ordered - does this queue support ordered writes * @q: the request queue * @ordered: one of QUEUE_ORDERED_* - * @prepare_flush_fn: rq setup helper for cache flush ordered writes * * Description: * For journalled file systems, doing ordered writes on a commit @@ -22,8 +21,7 @@ * feature should call this function and indicate so. * **/ -int blk_queue_ordered(struct request_queue *q, unsigned ordered, - prepare_flush_fn *prepare_flush_fn) +int blk_queue_ordered(struct request_queue *q, unsigned ordered) { if (ordered != QUEUE_ORDERED_NONE && ordered != QUEUE_ORDERED_DRAIN && @@ -38,7 +36,6 @@ int blk_queue_ordered(struct request_queue *q, unsigned ordered, q->ordered = ordered; q->next_ordered = ordered; - q->prepare_flush_fn = prepare_flush_fn; return 0; } @@ -140,8 +137,6 @@ static void queue_flush(struct request_queue *q, unsigned which) rq->cmd_flags = REQ_HARDBARRIER | REQ_FLUSH; rq->rq_disk = q->bar_rq.rq_disk; rq->end_io = end_io; - if (q->prepare_flush_fn) - q->prepare_flush_fn(q, rq); elv_insert(q, rq, ELEVATOR_INSERT_FRONT); } diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 1b218c6b6820..1d2c18620f9a 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -479,7 +479,7 @@ static struct brd_device *brd_alloc(int i) if (!brd->brd_queue) goto out_free_dev; blk_queue_make_request(brd->brd_queue, brd_make_request); - blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG, NULL); + blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG); blk_queue_max_hw_sectors(brd->brd_queue, 1024); blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index fedfdb7d3cdf..d285a5481965 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -831,7 +831,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, lo->lo_queue->unplug_fn = loop_unplug; if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) - blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN, NULL); + blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN); set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c index 9639565a9a6a..2284b4f05c62 100644 --- a/drivers/block/osdblk.c +++ b/drivers/block/osdblk.c @@ -439,7 +439,7 @@ static int osdblk_init_disk(struct osdblk_device *osdev) blk_queue_stack_limits(q, osd_request_queue(osdev->osd)); blk_queue_prep_rq(q, blk_queue_start_tag); - blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, NULL); + blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH); disk->queue = q; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index ab528a480f98..e9da874d0419 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -468,7 +468,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev) blk_queue_dma_alignment(queue, dev->blk_size-1); blk_queue_logical_block_size(queue, dev->blk_size); - blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH, NULL); + blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH); blk_queue_max_segments(queue, -1); blk_queue_max_segment_size(queue, dev->bounce_size); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index b277f9e6abac..0a3222fd4442 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -366,9 +366,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) /* If barriers are supported, tell block layer that queue is ordered */ if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) - blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, NULL); + blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH); else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) - blk_queue_ordered(q, QUEUE_ORDERED_TAG, NULL); + blk_queue_ordered(q, QUEUE_ORDERED_TAG); /* If disk is read-only in the host, the guest should obey */ if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 495533e66542..76af65b654e3 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -373,8 +373,7 @@ static int xlvbd_barrier(struct blkfront_info *info) int err; err = blk_queue_ordered(info->rq, - info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE, - NULL); + info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE); if (err) return err; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index c22e6226e9e9..7433e07de30e 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -549,7 +549,7 @@ static void update_ordered(ide_drive_t *drive) } else ordered = QUEUE_ORDERED_DRAIN; - blk_queue_ordered(drive->queue, ordered, NULL); + blk_queue_ordered(drive->queue, ordered); } ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 00c810551814..d505a96845c1 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1901,7 +1901,7 @@ static struct mapped_device *alloc_dev(int minor) blk_queue_softirq_done(md->queue, dm_softirq_done); blk_queue_prep_rq(md->queue, dm_prep_fn); blk_queue_lld_busy(md->queue, dm_lld_busy); - blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH, NULL); + blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH); md->disk = alloc_disk(1); if (!md->disk) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index ec92bcbdeddb..c77eb49eda0e 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -128,7 +128,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock mq->req = NULL; blk_queue_prep_rq(mq->queue, mmc_prep_request); - blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL); + blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); #ifdef CONFIG_MMC_BLOCK_BOUNCE diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 33975e922d65..17b033d0e050 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2196,7 +2196,7 @@ static void dasd_setup_queue(struct dasd_block *block) */ blk_queue_max_segment_size(block->request_queue, PAGE_SIZE); blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1); - blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN, NULL); + blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN); } /* diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e8c295e01466..d9a4314a1948 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2135,7 +2135,7 @@ static int sd_revalidate_disk(struct gendisk *disk) else ordered = QUEUE_ORDERED_DRAIN; - blk_queue_ordered(sdkp->disk->queue, ordered, NULL); + blk_queue_ordered(sdkp->disk->queue, ordered); set_capacity(disk, sdkp->capacity); kfree(buffer); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6bba04c7ec48..3a2c5d9a9288 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -212,7 +212,6 @@ struct bvec_merge_data { }; typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *, struct bio_vec *); -typedef void (prepare_flush_fn) (struct request_queue *, struct request *); typedef void (softirq_done_fn)(struct request *); typedef int (dma_drain_needed_fn)(struct request *); typedef int (lld_busy_fn) (struct request_queue *q); @@ -286,7 +285,6 @@ struct request_queue unprep_rq_fn *unprep_rq_fn; unplug_fn *unplug_fn; merge_bvec_fn *merge_bvec_fn; - prepare_flush_fn *prepare_flush_fn; softirq_done_fn *softirq_done_fn; rq_timed_out_fn *rq_timed_out_fn; dma_drain_needed_fn *dma_drain_needed; @@ -896,7 +894,7 @@ extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *); extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); -extern int blk_queue_ordered(struct request_queue *, unsigned, prepare_flush_fn *); +extern int blk_queue_ordered(struct request_queue *, unsigned); extern bool blk_do_ordered(struct request_queue *, struct request **); extern unsigned blk_ordered_cur_seq(struct request_queue *); extern unsigned blk_ordered_req_seq(struct request *); -- cgit v1.2.3 From 82b6d57fb11644fe25c8a1346627ad0027673dae Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 3 Jul 2010 08:07:04 -0600 Subject: scsi: need to reset unprep_rq_fn in sd_remove This is for block's for-2.6.36. We need to reset q->unprep_rq_fn in sd_remove. Otherwise we hit kernel oops if we access to a scsi disk device via sg after removing scsi disk module. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d9a4314a1948..0994ab63b598 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2384,6 +2384,7 @@ static int sd_remove(struct device *dev) async_synchronize_full(); sdkp = dev_get_drvdata(dev); blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); + blk_queue_unprep_rq(sdkp->device->request_queue, NULL); device_del(&sdkp->dev); del_gendisk(sdkp->disk); sd_shutdown(dev); -- cgit v1.2.3 From 610a63498f7f366031a6327eaaa9963ffa110b2b Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 8 Jul 2010 10:16:17 +0200 Subject: scsi: fix discard page leak We leak a page allocated for discard on some error conditions (e.g. scsi_prep_state_check returns BLKPREP_DEFER in scsi_setup_blk_pc_cmnd). We unprep on requests that weren't prepped in the error path of scsi_init_io. It makes the error path to clean up scsi commands messy. Let's strictly apply the rule that we can't unprep on a request that wasn't prepped. Calling just scsi_put_command() in the error path of scsi_init_io() is enough. We don't set REQ_DONTPREP yet. scsi_setup_discard_cmnd can safely free a page on the error case with the above rule. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/scsi_lib.c | 7 ++----- drivers/scsi/sd.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ee836193f531..b8de389636f8 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1011,11 +1011,8 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) err_exit: scsi_release_buffers(cmd); - if (error == BLKPREP_KILL) - scsi_put_command(cmd); - else /* BLKPREP_DEFER */ - scsi_unprep_request(cmd->request); - + scsi_put_command(cmd); + cmd->request->special = NULL; return error; } EXPORT_SYMBOL(scsi_init_io); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 0994ab63b598..1d0c4b7c3b69 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -468,6 +468,10 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) blk_add_request_payload(rq, page, len); ret = scsi_setup_blk_pc_cmnd(sdp, rq); rq->buffer = page_address(page); + if (ret != BLKPREP_OK) { + __free_page(page); + rq->buffer = NULL; + } return ret; } @@ -485,8 +489,10 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) static void sd_unprep_fn(struct request_queue *q, struct request *rq) { - if (rq->cmd_flags & REQ_DISCARD) - __free_page(virt_to_page(rq->buffer)); + if (rq->cmd_flags & REQ_DISCARD) { + free_page((unsigned long)rq->buffer); + rq->buffer = NULL; + } } /** -- cgit v1.2.3 From 8a6cfeb6deca3a8fefd639d898b0d163c0b5d368 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 8 Jul 2010 10:18:46 +0200 Subject: block: push down BKL into .locked_ioctl As a preparation for the removal of the big kernel lock in the block layer, this removes the BKL from the common ioctl handling code, moving it into every single driver still using it. Signed-off-by: Arnd Bergmann Acked-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/ioctl.c | 11 +---------- drivers/block/amiflop.c | 17 +++++++++++++++-- drivers/block/ataflop.c | 18 +++++++++++++++--- drivers/block/brd.c | 5 ++++- drivers/block/cciss.c | 8 +++++--- drivers/block/cpqarray.c | 18 ++++++++++++++++-- drivers/block/floppy.c | 17 +++++++++++++++-- drivers/block/nbd.c | 5 ++++- drivers/block/paride/pcd.c | 11 +++++++++-- drivers/block/paride/pd.c | 5 ++++- drivers/block/paride/pf.c | 6 +++++- drivers/block/pktcdvd.c | 13 +++++++++---- drivers/block/swim.c | 5 ++++- drivers/block/swim3.c | 17 +++++++++++++++-- drivers/block/ub.c | 10 ++++++++-- drivers/block/virtio_blk.c | 17 +++++++++++++++-- drivers/block/xd.c | 17 +++++++++++++++-- drivers/block/xen-blkfront.c | 2 +- drivers/cdrom/gdrom.c | 11 +++++++++-- drivers/cdrom/viocd.c | 11 +++++++++-- drivers/ide/ide-cd.c | 18 ++++++++++++++++-- drivers/ide/ide-disk_ioctl.c | 9 +++++++-- drivers/ide/ide-floppy_ioctl.c | 12 +++++++++--- drivers/ide/ide-gd.c | 2 +- drivers/ide/ide-tape.c | 10 ++++++++-- drivers/message/i2o/i2o_block.c | 22 +++++----------------- drivers/mtd/mtd_blkdevs.c | 5 ++++- drivers/scsi/sd.c | 17 ++++++++++++----- drivers/scsi/sr.c | 18 +++++++++++++----- include/linux/blkdev.h | 1 - 30 files changed, 253 insertions(+), 85 deletions(-) (limited to 'drivers/scsi') diff --git a/block/ioctl.c b/block/ioctl.c index e8eb679f2f9b..1cfa8d449d90 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -163,18 +163,10 @@ int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { struct gendisk *disk = bdev->bd_disk; - int ret; if (disk->fops->ioctl) return disk->fops->ioctl(bdev, mode, cmd, arg); - if (disk->fops->locked_ioctl) { - lock_kernel(); - ret = disk->fops->locked_ioctl(bdev, mode, cmd, arg); - unlock_kernel(); - return ret; - } - return -ENOTTY; } /* @@ -185,8 +177,7 @@ int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl); /* - * always keep this in sync with compat_blkdev_ioctl() and - * compat_blkdev_locked_ioctl() + * always keep this in sync with compat_blkdev_ioctl() */ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 832798aa14f6..0fa26359304c 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -1423,7 +1424,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { struct amiga_floppy_struct *p = bdev->bd_disk->private_data; @@ -1500,6 +1501,18 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, return 0; } +static int fd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = fd_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + static void fd_probe(int dev) { unsigned long code; @@ -1638,7 +1651,7 @@ static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, .open = floppy_open, .release = floppy_release, - .locked_ioctl = fd_ioctl, + .ioctl = fd_ioctl, .getgeo = fd_getgeo, .media_changed = amiga_floppy_change, }; diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index e35cf59cbfde..1bb8bfcfdbd9 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -67,6 +67,7 @@ #include #include #include +#include #include #include @@ -359,7 +360,7 @@ static void finish_fdc( void ); static void finish_fdc_done( int dummy ); static void setup_req_params( int drive ); static void redo_fd_request( void); -static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int +static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param); static void fd_probe( int drive ); static int fd_test_drive_present( int drive ); @@ -1480,7 +1481,7 @@ void do_fd_request(struct request_queue * q) atari_enable_irq( IRQ_MFP_FDC ); } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { struct gendisk *disk = bdev->bd_disk; @@ -1665,6 +1666,17 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, } } +static int fd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + lock_kernel(); + ret = fd_locked_ioctl(bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; +} /* Initialize the 'unit' variable for drive 'drive' */ @@ -1855,7 +1867,7 @@ static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, .open = floppy_open, .release = floppy_release, - .locked_ioctl = fd_ioctl, + .ioctl = fd_ioctl, .media_changed = check_floppy_change, .revalidate_disk= floppy_revalidate, }; diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 1d2c18620f9a..1c7f63792ff8 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include /* invalidate_bh_lrus() */ #include @@ -401,6 +402,7 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode, * ram device BLKFLSBUF has special semantics, we want to actually * release and destroy the ramdisk data. */ + lock_kernel(); mutex_lock(&bdev->bd_mutex); error = -EBUSY; if (bdev->bd_openers <= 1) { @@ -417,13 +419,14 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode, error = 0; } mutex_unlock(&bdev->bd_mutex); + unlock_kernel(); return error; } static const struct block_device_operations brd_fops = { .owner = THIS_MODULE, - .locked_ioctl = brd_ioctl, + .ioctl = brd_ioctl, #ifdef CONFIG_BLK_DEV_XIP .direct_access = brd_direct_access, #endif diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 11b377762b8e..a6c0494dd054 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -179,6 +179,8 @@ static irqreturn_t do_cciss_intx(int irq, void *dev_id); static irqreturn_t do_cciss_msix_intr(int irq, void *dev_id); static int cciss_open(struct block_device *bdev, fmode_t mode); static int cciss_release(struct gendisk *disk, fmode_t mode); +static int do_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg); static int cciss_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -237,7 +239,7 @@ static const struct block_device_operations cciss_fops = { .owner = THIS_MODULE, .open = cciss_open, .release = cciss_release, - .locked_ioctl = cciss_ioctl, + .ioctl = do_ioctl, .getgeo = cciss_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = cciss_compat_ioctl, @@ -1057,8 +1059,6 @@ static int cciss_release(struct gendisk *disk, fmode_t mode) return 0; } -#ifdef CONFIG_COMPAT - static int do_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { @@ -1069,6 +1069,8 @@ static int do_ioctl(struct block_device *bdev, fmode_t mode, return ret; } +#ifdef CONFIG_COMPAT + static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg); static int cciss_ioctl32_big_passthru(struct block_device *bdev, fmode_t mode, diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index abb4ec6690fc..c459aeea3c0c 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -197,7 +198,7 @@ static const struct block_device_operations ida_fops = { .owner = THIS_MODULE, .open = ida_open, .release = ida_release, - .locked_ioctl = ida_ioctl, + .ioctl = ida_ioctl, .getgeo = ida_getgeo, .revalidate_disk= ida_revalidate, }; @@ -1128,7 +1129,7 @@ static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo) * ida_ioctl does some miscellaneous stuff like reporting drive geometry, * setting readahead and submitting commands from userspace to the controller. */ -static int ida_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) +static int ida_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { drv_info_t *drv = get_drv(bdev->bd_disk); ctlr_info_t *host = get_host(bdev->bd_disk); @@ -1192,6 +1193,19 @@ out_passthru: } } + +static int ida_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = ida_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + /* * ida_ctlr_ioctl is for passing commands to the controller from userspace. * The command block (io) has already been copied to kernel space for us, diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 82c30f9f81ca..40419b066aa9 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -178,6 +178,7 @@ static int print_unex = 1; #include #include #include +#include #include #include #include @@ -3371,7 +3372,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, +static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { int drive = (long)bdev->bd_disk->private_data; @@ -3547,6 +3548,18 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, return 0; } +static int fd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = fd_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + static void __init config_types(void) { bool has_drive = false; @@ -3848,7 +3861,7 @@ static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, .open = floppy_open, .release = floppy_release, - .locked_ioctl = fd_ioctl, + .ioctl = fd_ioctl, .getgeo = fd_getgeo, .media_changed = check_floppy_change, .revalidate_disk = floppy_revalidate, diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 2e74e7d475ca..6751789fb379 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -716,9 +717,11 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode, dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n", lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg); + lock_kernel(); mutex_lock(&lo->tx_lock); error = __nbd_ioctl(bdev, lo, cmd, arg); mutex_unlock(&lo->tx_lock); + unlock_kernel(); return error; } @@ -726,7 +729,7 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode, static const struct block_device_operations nbd_fops = { .owner = THIS_MODULE, - .locked_ioctl = nbd_ioctl, + .ioctl = nbd_ioctl, }; /* diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 71acf4e53356..daba7a62a663 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -138,6 +138,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; #include #include #include +#include #include static DEFINE_SPINLOCK(pcd_lock); @@ -238,7 +239,13 @@ static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { struct pcd_unit *cd = bdev->bd_disk->private_data; - return cdrom_ioctl(&cd->info, bdev, mode, cmd, arg); + int ret; + + lock_kernel(); + ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; } static int pcd_block_media_changed(struct gendisk *disk) @@ -251,7 +258,7 @@ static const struct block_device_operations pcd_bdops = { .owner = THIS_MODULE, .open = pcd_block_open, .release = pcd_block_release, - .locked_ioctl = pcd_block_ioctl, + .ioctl = pcd_block_ioctl, .media_changed = pcd_block_media_changed, }; diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 4e8b9bff3abe..c4d6ed9846ca 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -153,6 +153,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV}; #include #include #include +#include #include #include @@ -768,8 +769,10 @@ static int pd_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case CDROMEJECT: + lock_kernel(); if (disk->access == 1) pd_special_command(disk, pd_eject); + unlock_kernel(); return 0; default: return -EINVAL; @@ -812,7 +815,7 @@ static const struct block_device_operations pd_fops = { .owner = THIS_MODULE, .open = pd_open, .release = pd_release, - .locked_ioctl = pd_ioctl, + .ioctl = pd_ioctl, .getgeo = pd_getgeo, .media_changed = pd_check_media, .revalidate_disk= pd_revalidate diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index c059aab3006b..38b4d566b816 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -152,6 +152,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY}; #include #include #include +#include #include static DEFINE_SPINLOCK(pf_spin_lock); @@ -266,7 +267,7 @@ static const struct block_device_operations pf_fops = { .owner = THIS_MODULE, .open = pf_open, .release = pf_release, - .locked_ioctl = pf_ioctl, + .ioctl = pf_ioctl, .getgeo = pf_getgeo, .media_changed = pf_check_media, }; @@ -342,7 +343,10 @@ static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u if (pf->access != 1) return -EBUSY; + lock_kernel(); pf_eject(pf); + unlock_kernel(); + return 0; } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 9f3e4454274b..40f1e31f42c4 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -2762,10 +2763,12 @@ out_mem: static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct pktcdvd_device *pd = bdev->bd_disk->private_data; + int ret; VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); + lock_kernel(); switch (cmd) { case CDROMEJECT: /* @@ -2783,14 +2786,16 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, case CDROM_LAST_WRITTEN: case CDROM_SEND_PACKET: case SCSI_IOCTL_SEND_COMMAND: - return __blkdev_driver_ioctl(pd->bdev, mode, cmd, arg); + ret = __blkdev_driver_ioctl(pd->bdev, mode, cmd, arg); + break; default: VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd); - return -ENOTTY; + ret = -ENOTTY; } + unlock_kernel(); - return 0; + return ret; } static int pkt_media_changed(struct gendisk *disk) @@ -2812,7 +2817,7 @@ static const struct block_device_operations pktcdvd_ops = { .owner = THIS_MODULE, .open = pkt_open, .release = pkt_close, - .locked_ioctl = pkt_ioctl, + .ioctl = pkt_ioctl, .media_changed = pkt_media_changed, }; diff --git a/drivers/block/swim.c b/drivers/block/swim.c index e463657569ff..f04f74e3758f 100644 --- a/drivers/block/swim.c +++ b/drivers/block/swim.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -690,7 +691,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode, case FDEJECT: if (fs->ref_count != 1) return -EBUSY; + lock_kernel(); err = floppy_eject(fs); + unlock_kernel(); return err; case FDGETPRM: @@ -753,7 +756,7 @@ static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, .open = floppy_open, .release = floppy_release, - .locked_ioctl = floppy_ioctl, + .ioctl = floppy_ioctl, .getgeo = floppy_getgeo, .media_changed = floppy_check_change, .revalidate_disk = floppy_revalidate, diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index ed6fb91123ab..f3657b2a5386 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -839,7 +840,7 @@ static int fd_eject(struct floppy_state *fs) static struct floppy_struct floppy_type = { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */ -static int floppy_ioctl(struct block_device *bdev, fmode_t mode, +static int floppy_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { struct floppy_state *fs = bdev->bd_disk->private_data; @@ -867,6 +868,18 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode, return -ENOTTY; } +static int floppy_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = floppy_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + static int floppy_open(struct block_device *bdev, fmode_t mode) { struct floppy_state *fs = bdev->bd_disk->private_data; @@ -997,7 +1010,7 @@ static int floppy_revalidate(struct gendisk *disk) static const struct block_device_operations floppy_fops = { .open = floppy_open, .release = floppy_release, - .locked_ioctl = floppy_ioctl, + .ioctl = floppy_ioctl, .media_changed = floppy_check_change, .revalidate_disk= floppy_revalidate, }; diff --git a/drivers/block/ub.c b/drivers/block/ub.c index aaf27fb4efd6..102ed52d0e0f 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #define DRV_NAME "ub" @@ -1729,8 +1730,13 @@ static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode, { struct gendisk *disk = bdev->bd_disk; void __user *usermem = (void __user *) arg; + int ret; + + lock_kernel(); + ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem); + unlock_kernel(); - return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem); + return ret; } /* @@ -1794,7 +1800,7 @@ static const struct block_device_operations ub_bd_fops = { .owner = THIS_MODULE, .open = ub_bd_open, .release = ub_bd_release, - .locked_ioctl = ub_bd_ioctl, + .ioctl = ub_bd_ioctl, .media_changed = ub_bd_media_changed, .revalidate_disk = ub_bd_revalidate, }; diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 0a3222fd4442..7b0f7b624adf 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -217,7 +218,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); } -static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, +static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long data) { struct gendisk *disk = bdev->bd_disk; @@ -243,6 +244,18 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, (void __user *)data); } +static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = virtblk_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + /* We provide getgeo only to please some old bootloader/partitioning tools */ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) { @@ -269,7 +282,7 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) } static const struct block_device_operations virtblk_fops = { - .locked_ioctl = virtblk_ioctl, + .ioctl = virtblk_ioctl, .owner = THIS_MODULE, .getgeo = virtblk_getgeo, }; diff --git a/drivers/block/xd.c b/drivers/block/xd.c index b16a3a926cf2..d5a3cd750561 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -133,7 +134,7 @@ static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo); static const struct block_device_operations xd_fops = { .owner = THIS_MODULE, - .locked_ioctl = xd_ioctl, + .ioctl = xd_ioctl, .getgeo = xd_getgeo, }; static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int); @@ -347,7 +348,7 @@ static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo) } /* xd_ioctl: handle device ioctl's */ -static int xd_ioctl(struct block_device *bdev, fmode_t mode, u_int cmd, u_long arg) +static int xd_locked_ioctl(struct block_device *bdev, fmode_t mode, u_int cmd, u_long arg) { switch (cmd) { case HDIO_SET_DMA: @@ -375,6 +376,18 @@ static int xd_ioctl(struct block_device *bdev, fmode_t mode, u_int cmd, u_long a } } +static int xd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = xd_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + /* xd_readwrite: handle a read/write request */ static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_int count) { diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 76af65b654e3..9119cd3d56a4 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1045,7 +1045,7 @@ static const struct block_device_operations xlvbd_block_fops = .open = blkif_open, .release = blkif_release, .getgeo = blkif_getgeo, - .locked_ioctl = blkif_ioctl, + .ioctl = blkif_ioctl, }; diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 5219b57deb36..1772fd914fb9 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -509,7 +510,13 @@ static int gdrom_bdops_mediachanged(struct gendisk *disk) static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { - return cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg); + int ret; + + lock_kernel(); + ret = cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; } static const struct block_device_operations gdrom_bdops = { @@ -517,7 +524,7 @@ static const struct block_device_operations gdrom_bdops = { .open = gdrom_bdops_open, .release = gdrom_bdops_release, .media_changed = gdrom_bdops_mediachanged, - .locked_ioctl = gdrom_bdops_ioctl, + .ioctl = gdrom_bdops_ioctl, }; static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id) diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 1fa6628d150b..16dada0627ee 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -167,7 +168,13 @@ static int viocd_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { struct disk_info *di = bdev->bd_disk->private_data; - return cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg); + int ret; + + lock_kernel(); + ret = cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; } static int viocd_blk_media_changed(struct gendisk *disk) @@ -180,7 +187,7 @@ static const struct block_device_operations viocd_fops = { .owner = THIS_MODULE, .open = viocd_blk_open, .release = viocd_blk_release, - .locked_ioctl = viocd_blk_ioctl, + .ioctl = viocd_blk_ioctl, .media_changed = viocd_blk_media_changed, }; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index ef7e3a9bee51..bf9f61a5c2f8 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1654,7 +1655,7 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg) return 0; } -static int idecd_ioctl(struct block_device *bdev, fmode_t mode, +static int idecd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info); @@ -1676,6 +1677,19 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode, return err; } +static int idecd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + lock_kernel(); + ret = idecd_locked_ioctl(bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; +} + + static int idecd_media_changed(struct gendisk *disk) { struct cdrom_info *info = ide_drv_g(disk, cdrom_info); @@ -1696,7 +1710,7 @@ static const struct block_device_operations idecd_ops = { .owner = THIS_MODULE, .open = idecd_open, .release = idecd_release, - .locked_ioctl = idecd_ioctl, + .ioctl = idecd_ioctl, .media_changed = idecd_media_changed, .revalidate_disk = idecd_revalidate_disk }; diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c index 7b783dd7c0be..ec94c66918f6 100644 --- a/drivers/ide/ide-disk_ioctl.c +++ b/drivers/ide/ide-disk_ioctl.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "ide-disk.h" @@ -18,9 +19,13 @@ int ide_disk_ioctl(ide_drive_t *drive, struct block_device *bdev, fmode_t mode, { int err; + lock_kernel(); err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings); if (err != -EOPNOTSUPP) - return err; + goto out; - return generic_ide_ioctl(drive, bdev, cmd, arg); + err = generic_ide_ioctl(drive, bdev, cmd, arg); +out: + unlock_kernel(); + return err; } diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c index 9c2288234dea..fd3d05ab3417 100644 --- a/drivers/ide/ide-floppy_ioctl.c +++ b/drivers/ide/ide-floppy_ioctl.c @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -275,12 +276,15 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, void __user *argp = (void __user *)arg; int err; - if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) - return ide_floppy_lockdoor(drive, &pc, arg, cmd); + lock_kernel(); + if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) { + err = ide_floppy_lockdoor(drive, &pc, arg, cmd); + goto out; + } err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp); if (err != -ENOTTY) - return err; + goto out; /* * skip SCSI_IOCTL_SEND_COMMAND (deprecated) @@ -293,5 +297,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, if (err == -ENOTTY) err = generic_ide_ioctl(drive, bdev, cmd, arg); +out: + unlock_kernel(); return err; } diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index c102d23d9b38..883f0c979c9f 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c @@ -323,7 +323,7 @@ static const struct block_device_operations ide_gd_ops = { .owner = THIS_MODULE, .open = ide_gd_open, .release = ide_gd_release, - .locked_ioctl = ide_gd_ioctl, + .ioctl = ide_gd_ioctl, .getgeo = ide_gd_getgeo, .media_changed = ide_gd_media_changed, .unlock_native_capacity = ide_gd_unlock_native_capacity, diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 635fd72d4728..39b0a5c45f07 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -1927,9 +1928,14 @@ static int idetape_ioctl(struct block_device *bdev, fmode_t mode, { struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj); ide_drive_t *drive = tape->drive; - int err = generic_ide_ioctl(drive, bdev, cmd, arg); + int err; + + lock_kernel(); + err = generic_ide_ioctl(drive, bdev, cmd, arg); if (err == -EINVAL) err = idetape_blkdev_ioctl(drive, cmd, arg); + unlock_kernel(); + return err; } @@ -1937,7 +1943,7 @@ static const struct block_device_operations idetape_block_ops = { .owner = THIS_MODULE, .open = idetape_open, .release = idetape_release, - .locked_ioctl = idetape_ioctl, + .ioctl = idetape_ioctl, }; static int ide_tape_probe(ide_drive_t *drive) diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index b8233ff863e3..d1bdf8abe5db 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -53,7 +53,6 @@ #include #include #include -#include #include @@ -653,40 +652,30 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode, { struct gendisk *disk = bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; - int ret = -ENOTTY; /* Anyone capable of this syscall can do *real bad* things */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; - lock_kernel(); switch (cmd) { case BLKI2OGRSTRAT: - ret = put_user(dev->rcache, (int __user *)arg); - break; + return put_user(dev->rcache, (int __user *)arg); case BLKI2OGWSTRAT: - ret = put_user(dev->wcache, (int __user *)arg); - break; + return put_user(dev->wcache, (int __user *)arg); case BLKI2OSRSTRAT: - ret = -EINVAL; if (arg < 0 || arg > CACHE_SMARTFETCH) - break; + return -EINVAL; dev->rcache = arg; - ret = 0; break; case BLKI2OSWSTRAT: - ret = -EINVAL; if (arg != 0 && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) - break; + return -EINVAL; dev->wcache = arg; - ret = 0; break; } - unlock_kernel(); - - return ret; + return -ENOTTY; }; /** @@ -942,7 +931,6 @@ static const struct block_device_operations i2o_block_fops = { .open = i2o_block_open, .release = i2o_block_release, .ioctl = i2o_block_ioctl, - .compat_ioctl = i2o_block_ioctl, .getgeo = i2o_block_getgeo, .media_changed = i2o_block_media_changed }; diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 475af42745cb..8c83b11a77d5 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -237,6 +238,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, if (!dev) return ret; + lock_kernel(); mutex_lock(&dev->lock); if (!dev->mtd) @@ -250,6 +252,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, } unlock: mutex_unlock(&dev->lock); + unlock_kernel(); blktrans_dev_put(dev); return ret; } @@ -258,7 +261,7 @@ static const struct block_device_operations mtd_blktrans_ops = { .owner = THIS_MODULE, .open = blktrans_open, .release = blktrans_release, - .locked_ioctl = blktrans_ioctl, + .ioctl = blktrans_ioctl, .getgeo = blktrans_getgeo, }; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 1d0c4b7c3b69..633ac32b25c1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -924,6 +925,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n", disk->disk_name, cmd)); + lock_kernel(); /* * If we are in the middle of error recovery, don't let anyone * else try and use this device. Also, if error recovery fails, it @@ -933,7 +935,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, error = scsi_nonblockable_ioctl(sdp, cmd, p, (mode & FMODE_NDELAY) != 0); if (!scsi_block_when_processing_errors(sdp) || !error) - return error; + goto out; /* * Send SCSI addressing ioctls directly to mid level, send other @@ -943,13 +945,18 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdp, cmd, p); + error = scsi_ioctl(sdp, cmd, p); + break; default: error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); if (error != -ENOTTY) - return error; + break; + error = scsi_ioctl(sdp, cmd, p); + break; } - return scsi_ioctl(sdp, cmd, p); +out: + unlock_kernel(); + return error; } static void set_media_not_present(struct scsi_disk *sdkp) @@ -1123,7 +1130,7 @@ static const struct block_device_operations sd_fops = { .owner = THIS_MODULE, .open = sd_open, .release = sd_release, - .locked_ioctl = sd_ioctl, + .ioctl = sd_ioctl, .getgeo = sd_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = sd_compat_ioctl, diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 0a90abc7f140..d42fa6468f41 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -493,6 +494,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, void __user *argp = (void __user *)arg; int ret; + lock_kernel(); + /* * Send SCSI addressing ioctls directly to mid level, send other * ioctls to cdrom/block level. @@ -500,12 +503,13 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, switch (cmd) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdev, cmd, argp); + ret = scsi_ioctl(sdev, cmd, argp); + goto out; } ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); if (ret != -ENOSYS) - return ret; + goto out; /* * ENODEV means that we didn't recognise the ioctl, or that we @@ -516,8 +520,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, ret = scsi_nonblockable_ioctl(sdev, cmd, argp, (mode & FMODE_NDELAY) != 0); if (ret != -ENODEV) - return ret; - return scsi_ioctl(sdev, cmd, argp); + goto out; + ret = scsi_ioctl(sdev, cmd, argp); + +out: + unlock_kernel(); + return ret; } static int sr_block_media_changed(struct gendisk *disk) @@ -531,7 +539,7 @@ static const struct block_device_operations sr_bdops = .owner = THIS_MODULE, .open = sr_block_open, .release = sr_block_release, - .locked_ioctl = sr_block_ioctl, + .ioctl = sr_block_ioctl, .media_changed = sr_block_media_changed, /* * No compat_ioctl for now because sr_block_ioctl never diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index baf5258f5985..a8b05fc80c6d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1246,7 +1246,6 @@ static inline int blk_integrity_rq(struct request *rq) struct block_device_operations { int (*open) (struct block_device *, fmode_t); int (*release) (struct gendisk *, fmode_t); - int (*locked_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); int (*direct_access) (struct block_device *, sector_t, -- cgit v1.2.3 From 6e9624b8caec290d28b4c6d9ec75749df6372b87 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 7 Aug 2010 18:25:34 +0200 Subject: block: push down BKL into .open and .release The open and release block_device_operations are currently called with the BKL held. In order to change that, we must first make sure that all drivers that currently rely on this have no regressions. This blindly pushes the BKL into all .open and .release operations for all block drivers to prepare for the next step. The drivers can subsequently replace the BKL with their own locks or remove it completely when it can be shown that it is not needed. The functions blkdev_get and blkdev_put are the only remaining users of the big kernel lock in the block layer, besides a few uses in the ioctl code, none of which need to serialize with blkdev_{get,put}. Most of these two functions is also under the protection of bdev->bd_mutex, including the actual calls to ->open and ->release, and the common code does not access any global data structures that need the BKL. Signed-off-by: Arnd Bergmann Acked-by: Christoph Hellwig Signed-off-by: Jens Axboe --- arch/um/drivers/ubd_kern.c | 7 ++++++- drivers/block/DAC960.c | 13 +++++++++---- drivers/block/amiflop.c | 12 ++++++++++-- drivers/block/aoe/aoeblk.c | 4 ++++ drivers/block/ataflop.c | 14 +++++++++++++- drivers/block/cciss.c | 23 ++++++++++++++++++++--- drivers/block/cpqarray.c | 22 +++++++++++++++++++--- drivers/block/drbd/drbd_main.c | 4 ++++ drivers/block/floppy.c | 5 +++++ drivers/block/loop.c | 5 +++++ drivers/block/paride/pcd.c | 10 +++++++++- drivers/block/paride/pd.c | 4 ++++ drivers/block/paride/pf.c | 20 +++++++++++++++----- drivers/block/pktcdvd.c | 5 +++++ drivers/block/swim.c | 15 ++++++++++++++- drivers/block/swim3.c | 15 ++++++++++++++- drivers/block/ub.c | 17 ++++++++++++++++- drivers/block/viodasd.c | 19 ++++++++++++++++++- drivers/block/xen-blkfront.c | 7 +++++++ drivers/block/xsysace.c | 6 ++++++ drivers/block/z2ram.c | 13 ++++++++++--- drivers/cdrom/gdrom.c | 8 +++++++- drivers/cdrom/viocd.c | 10 +++++++++- drivers/ide/ide-cd.c | 14 +++++++++----- drivers/ide/ide-gd.c | 17 ++++++++++++++++- drivers/ide/ide-tape.c | 9 ++++++++- drivers/md/dm.c | 7 +++++++ drivers/md/md.c | 6 ++++++ drivers/memstick/core/mspro_block.c | 9 ++++++++- drivers/message/i2o/i2o_block.c | 5 +++++ drivers/mmc/card/block.c | 5 +++++ drivers/mtd/mtd_blkdevs.c | 6 +++++- drivers/s390/block/dasd.c | 6 ++++++ drivers/s390/block/dcssblk.c | 5 +++++ drivers/s390/char/tape_block.c | 8 +++++++- drivers/scsi/sd.c | 5 +++++ drivers/scsi/sr.c | 7 ++++++- drivers/staging/hv/blkvsc_drv.c | 5 +++++ fs/block_dev.c | 10 ++-------- 39 files changed, 334 insertions(+), 48 deletions(-) (limited to 'drivers/scsi') diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index da992a3ad6b7..1bcd208c459f 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -33,6 +33,7 @@ #include "linux/mm.h" #include "linux/slab.h" #include "linux/vmalloc.h" +#include "linux/smp_lock.h" #include "linux/blkpg.h" #include "linux/genhd.h" #include "linux/spinlock.h" @@ -1098,6 +1099,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode) struct ubd *ubd_dev = disk->private_data; int err = 0; + lock_kernel(); if(ubd_dev->count == 0){ err = ubd_open_dev(ubd_dev); if(err){ @@ -1115,7 +1117,8 @@ static int ubd_open(struct block_device *bdev, fmode_t mode) if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); err = -EROFS; }*/ - out: +out: + unlock_kernel(); return err; } @@ -1123,8 +1126,10 @@ static int ubd_release(struct gendisk *disk, fmode_t mode) { struct ubd *ubd_dev = disk->private_data; + lock_kernel(); if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); + unlock_kernel(); return 0; } diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index c5f22bb0a48e..4e2c367fec11 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -79,23 +79,28 @@ static int DAC960_open(struct block_device *bdev, fmode_t mode) struct gendisk *disk = bdev->bd_disk; DAC960_Controller_T *p = disk->queue->queuedata; int drive_nr = (long)disk->private_data; + int ret = -ENXIO; + lock_kernel(); if (p->FirmwareType == DAC960_V1_Controller) { if (p->V1.LogicalDriveInformation[drive_nr]. LogicalDriveState == DAC960_V1_LogicalDrive_Offline) - return -ENXIO; + goto out; } else { DAC960_V2_LogicalDeviceInfo_T *i = p->V2.LogicalDeviceInformation[drive_nr]; if (!i || i->LogicalDeviceState == DAC960_V2_LogicalDevice_Offline) - return -ENXIO; + goto out; } check_disk_change(bdev); if (!get_capacity(p->disks[drive_nr])) - return -ENXIO; - return 0; + goto out; + ret = 0; +out: + unlock_kernel(); + return ret; } static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo) diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 0fa26359304c..76f114f0bba3 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1555,10 +1555,13 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) int old_dev; unsigned long flags; + lock_kernel(); old_dev = fd_device[drive]; - if (fd_ref[drive] && old_dev != system) + if (fd_ref[drive] && old_dev != system) { + unlock_kernel(); return -EBUSY; + } if (mode & (FMODE_READ|FMODE_WRITE)) { check_disk_change(bdev); @@ -1571,8 +1574,10 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) fd_deselect (drive); rel_fdc(); - if (wrprot) + if (wrprot) { + unlock_kernel(); return -EROFS; + } } } @@ -1589,6 +1594,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, unit[drive].type->name, data_types[system].name); + unlock_kernel(); return 0; } @@ -1597,6 +1603,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) struct amiga_floppy_struct *p = disk->private_data; int drive = p - unit; + lock_kernel(); if (unit[drive].dirty == 1) { del_timer (flush_track_timer + drive); non_int_flush_track (drive); @@ -1610,6 +1617,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) /* the mod_use counter is handled this way */ floppy_off (drive | 0x40000000); #endif + unlock_kernel(); return 0; } diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 65deffde60ac..a946929735a5 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "aoe.h" static struct kmem_cache *buf_pool_cache; @@ -124,13 +125,16 @@ aoeblk_open(struct block_device *bdev, fmode_t mode) struct aoedev *d = bdev->bd_disk->private_data; ulong flags; + lock_kernel(); spin_lock_irqsave(&d->lock, flags); if (d->flags & DEVFL_UP) { d->nopen++; spin_unlock_irqrestore(&d->lock, flags); + unlock_kernel(); return 0; } spin_unlock_irqrestore(&d->lock, flags); + unlock_kernel(); return -ENODEV; } diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 1bb8bfcfdbd9..aceb96476524 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -1850,22 +1850,34 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return 0; } +static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = floppy_open(bdev, mode); + unlock_kernel(); + + return ret; +} static int floppy_release(struct gendisk *disk, fmode_t mode) { struct atari_floppy_struct *p = disk->private_data; + lock_kernel(); if (p->ref < 0) p->ref = 0; else if (!p->ref--) { printk(KERN_ERR "floppy_release with fd_ref == 0"); p->ref = 0; } + unlock_kernel(); return 0; } static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, - .open = floppy_open, + .open = floppy_unlocked_open, .release = floppy_release, .ioctl = fd_ioctl, .media_changed = check_floppy_change, diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index a6c0494dd054..665a470310a9 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -178,6 +178,7 @@ static void do_cciss_request(struct request_queue *q); static irqreturn_t do_cciss_intx(int irq, void *dev_id); static irqreturn_t do_cciss_msix_intr(int irq, void *dev_id); static int cciss_open(struct block_device *bdev, fmode_t mode); +static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode); static int cciss_release(struct gendisk *disk, fmode_t mode); static int do_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); @@ -237,7 +238,7 @@ static int cciss_compat_ioctl(struct block_device *, fmode_t, static const struct block_device_operations cciss_fops = { .owner = THIS_MODULE, - .open = cciss_open, + .open = cciss_unlocked_open, .release = cciss_release, .ioctl = do_ioctl, .getgeo = cciss_getgeo, @@ -1042,13 +1043,28 @@ static int cciss_open(struct block_device *bdev, fmode_t mode) return 0; } +static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = cciss_open(bdev, mode); + unlock_kernel(); + + return ret; +} + /* * Close. Sync first. */ static int cciss_release(struct gendisk *disk, fmode_t mode) { - ctlr_info_t *host = get_host(disk); - drive_info_struct *drv = get_drv(disk); + ctlr_info_t *host; + drive_info_struct *drv; + + lock_kernel(); + host = get_host(disk); + drv = get_drv(disk); #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss_release %s\n", disk->disk_name); @@ -1056,6 +1072,7 @@ static int cciss_release(struct gendisk *disk, fmode_t mode) drv->usage_count--; host->usage_count--; + unlock_kernel(); return 0; } diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index c459aeea3c0c..28937b661564 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -158,7 +158,7 @@ static int sendcmd( unsigned int blkcnt, unsigned int log_unit ); -static int ida_open(struct block_device *bdev, fmode_t mode); +static int ida_unlocked_open(struct block_device *bdev, fmode_t mode); static int ida_release(struct gendisk *disk, fmode_t mode); static int ida_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -196,7 +196,7 @@ static inline ctlr_info_t *get_host(struct gendisk *disk) static const struct block_device_operations ida_fops = { .owner = THIS_MODULE, - .open = ida_open, + .open = ida_unlocked_open, .release = ida_release, .ioctl = ida_ioctl, .getgeo = ida_getgeo, @@ -841,13 +841,29 @@ static int ida_open(struct block_device *bdev, fmode_t mode) return 0; } +static int ida_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = ida_open(bdev, mode); + unlock_kernel(); + + return ret; +} + /* * Close. Sync first. */ static int ida_release(struct gendisk *disk, fmode_t mode) { - ctlr_info_t *host = get_host(disk); + ctlr_info_t *host; + + lock_kernel(); + host = get_host(disk); host->usage_count--; + unlock_kernel(); + return 0; } diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index e2ab13d99d69..d2b6764a7b1f 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2604,6 +2604,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode) unsigned long flags; int rv = 0; + lock_kernel(); spin_lock_irqsave(&mdev->req_lock, flags); /* to have a stable mdev->state.role * and no race with updating open_cnt */ @@ -2618,6 +2619,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode) if (!rv) mdev->open_cnt++; spin_unlock_irqrestore(&mdev->req_lock, flags); + unlock_kernel(); return rv; } @@ -2625,7 +2627,9 @@ static int drbd_open(struct block_device *bdev, fmode_t mode) static int drbd_release(struct gendisk *gd, fmode_t mode) { struct drbd_conf *mdev = gd->private_data; + lock_kernel(); mdev->open_cnt--; + unlock_kernel(); return 0; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 40419b066aa9..3126d5122b2b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3616,6 +3616,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) { int drive = (long)disk->private_data; + lock_kernel(); mutex_lock(&open_lock); if (UDRS->fd_ref < 0) UDRS->fd_ref = 0; @@ -3626,6 +3627,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) if (!UDRS->fd_ref) opened_bdev[drive] = NULL; mutex_unlock(&open_lock); + unlock_kernel(); return 0; } @@ -3643,6 +3645,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) int res = -EBUSY; char *tmp; + lock_kernel(); mutex_lock(&open_lock); old_dev = UDRS->fd_device; if (opened_bdev[drive] && opened_bdev[drive] != bdev) @@ -3719,6 +3722,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) goto out; } mutex_unlock(&open_lock); + unlock_kernel(); return 0; out: if (UDRS->fd_ref < 0) @@ -3729,6 +3733,7 @@ out: opened_bdev[drive] = NULL; out2: mutex_unlock(&open_lock); + unlock_kernel(); return res; } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index d285a5481965..f3c636d23718 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -67,6 +67,7 @@ #include #include #include +#include #include #include /* for invalidate_bdev() */ #include @@ -1408,9 +1409,11 @@ static int lo_open(struct block_device *bdev, fmode_t mode) { struct loop_device *lo = bdev->bd_disk->private_data; + lock_kernel(); mutex_lock(&lo->lo_ctl_mutex); lo->lo_refcnt++; mutex_unlock(&lo->lo_ctl_mutex); + unlock_kernel(); return 0; } @@ -1420,6 +1423,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode) struct loop_device *lo = disk->private_data; int err; + lock_kernel(); mutex_lock(&lo->lo_ctl_mutex); if (--lo->lo_refcnt) @@ -1444,6 +1448,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode) out: mutex_unlock(&lo->lo_ctl_mutex); out_unlocked: + lock_kernel(); return 0; } diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index daba7a62a663..76f8565e1e8d 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -225,13 +225,21 @@ static char *pcd_buf; /* buffer for request in progress */ static int pcd_block_open(struct block_device *bdev, fmode_t mode) { struct pcd_unit *cd = bdev->bd_disk->private_data; - return cdrom_open(&cd->info, bdev, mode); + int ret; + + lock_kernel(); + ret = cdrom_open(&cd->info, bdev, mode); + unlock_kernel(); + + return ret; } static int pcd_block_release(struct gendisk *disk, fmode_t mode) { struct pcd_unit *cd = disk->private_data; + lock_kernel(); cdrom_release(&cd->info, mode); + unlock_kernel(); return 0; } diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index c4d6ed9846ca..985f0d4f1d1e 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -736,12 +736,14 @@ static int pd_open(struct block_device *bdev, fmode_t mode) { struct pd_unit *disk = bdev->bd_disk->private_data; + lock_kernel(); disk->access++; if (disk->removable) { pd_special_command(disk, pd_media_check); pd_special_command(disk, pd_door_lock); } + unlock_kernel(); return 0; } @@ -783,8 +785,10 @@ static int pd_release(struct gendisk *p, fmode_t mode) { struct pd_unit *disk = p->private_data; + lock_kernel(); if (!--disk->access && disk->removable) pd_special_command(disk, pd_door_unlock); + unlock_kernel(); return 0; } diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 38b4d566b816..4457b494882a 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -300,20 +300,26 @@ static void __init pf_init_units(void) static int pf_open(struct block_device *bdev, fmode_t mode) { struct pf_unit *pf = bdev->bd_disk->private_data; + int ret; + lock_kernel(); pf_identify(pf); + ret = -ENODEV; if (pf->media_status == PF_NM) - return -ENODEV; + goto out; + ret = -EROFS; if ((pf->media_status == PF_RO) && (mode & FMODE_WRITE)) - return -EROFS; + goto out; + ret = 0; pf->access++; if (pf->removable) pf_lock(pf, 1); - - return 0; +out: + unlock_kernel(); + return ret; } static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo) @@ -354,14 +360,18 @@ static int pf_release(struct gendisk *disk, fmode_t mode) { struct pf_unit *pf = disk->private_data; - if (pf->access <= 0) + lock_kernel(); + if (pf->access <= 0) { + unlock_kernel(); return -EINVAL; + } pf->access--; if (!pf->access && pf->removable) pf_lock(pf, 0); + unlock_kernel(); return 0; } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 40f1e31f42c4..b1cbeb59bb76 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2383,6 +2383,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode) VPRINTK(DRIVER_NAME": entering open\n"); + lock_kernel(); mutex_lock(&ctl_mutex); pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev)); if (!pd) { @@ -2410,6 +2411,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode) } mutex_unlock(&ctl_mutex); + unlock_kernel(); return 0; out_dec: @@ -2417,6 +2419,7 @@ out_dec: out: VPRINTK(DRIVER_NAME": failed open (%d)\n", ret); mutex_unlock(&ctl_mutex); + unlock_kernel(); return ret; } @@ -2425,6 +2428,7 @@ static int pkt_close(struct gendisk *disk, fmode_t mode) struct pktcdvd_device *pd = disk->private_data; int ret = 0; + lock_kernel(); mutex_lock(&ctl_mutex); pd->refcnt--; BUG_ON(pd->refcnt < 0); @@ -2433,6 +2437,7 @@ static int pkt_close(struct gendisk *disk, fmode_t mode) pkt_release_dev(pd, flush); } mutex_unlock(&ctl_mutex); + unlock_kernel(); return ret; } diff --git a/drivers/block/swim.c b/drivers/block/swim.c index f04f74e3758f..2e46815876df 100644 --- a/drivers/block/swim.c +++ b/drivers/block/swim.c @@ -662,11 +662,23 @@ out: return err; } +static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = floppy_open(bdev, mode); + unlock_kernel(); + + return ret; +} + static int floppy_release(struct gendisk *disk, fmode_t mode) { struct floppy_state *fs = disk->private_data; struct swim __iomem *base = fs->swd->base; + lock_kernel(); if (fs->ref_count < 0) fs->ref_count = 0; else if (fs->ref_count > 0) @@ -674,6 +686,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) if (fs->ref_count == 0) swim_motor(base, OFF); + unlock_kernel(); return 0; } @@ -754,7 +767,7 @@ static int floppy_revalidate(struct gendisk *disk) static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, - .open = floppy_open, + .open = floppy_unlocked_open, .release = floppy_release, .ioctl = floppy_ioctl, .getgeo = floppy_getgeo, diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index f3657b2a5386..cc6a3864822c 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -949,15 +949,28 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return 0; } +static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = floppy_open(bdev, mode); + unlock_kernel(); + + return ret; +} + static int floppy_release(struct gendisk *disk, fmode_t mode) { struct floppy_state *fs = disk->private_data; struct swim3 __iomem *sw = fs->swim3; + lock_kernel(); if (fs->ref_count > 0 && --fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); out_8(&sw->control_bic, 0xff); swim3_select(fs, RELAX); } + unlock_kernel(); return 0; } @@ -1008,7 +1021,7 @@ static int floppy_revalidate(struct gendisk *disk) } static const struct block_device_operations floppy_fops = { - .open = floppy_open, + .open = floppy_unlocked_open, .release = floppy_release, .ioctl = floppy_ioctl, .media_changed = floppy_check_change, diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 102ed52d0e0f..c48e14878582 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -1711,6 +1711,18 @@ err_open: return rc; } +static int ub_bd_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = ub_bd_open(bdev, mode); + unlock_kernel(); + + return ret; +} + + /* */ static int ub_bd_release(struct gendisk *disk, fmode_t mode) @@ -1718,7 +1730,10 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode) struct ub_lun *lun = disk->private_data; struct ub_dev *sc = lun->udev; + lock_kernel(); ub_put(sc); + unlock_kernel(); + return 0; } @@ -1798,7 +1813,7 @@ static int ub_bd_media_changed(struct gendisk *disk) static const struct block_device_operations ub_bd_fops = { .owner = THIS_MODULE, - .open = ub_bd_open, + .open = ub_bd_unlocked_open, .release = ub_bd_release, .ioctl = ub_bd_ioctl, .media_changed = ub_bd_media_changed, diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 5663d3c284c8..f651e51a3319 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -175,6 +176,18 @@ static int viodasd_open(struct block_device *bdev, fmode_t mode) return 0; } +static int viodasd_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = viodasd_open(bdev, mode); + unlock_kernel(); + + return ret; +} + + /* * External release entry point. */ @@ -183,6 +196,7 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode) struct viodasd_device *d = disk->private_data; HvLpEvent_Rc hvrc; + lock_kernel(); /* Send the event to OS/400. We DON'T expect a response */ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, HvLpEvent_Type_VirtualIo, @@ -195,6 +209,9 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode) 0, 0, 0); if (hvrc != 0) pr_warning("HV close call failed %d\n", (int)hvrc); + + unlock_kernel(); + return 0; } @@ -219,7 +236,7 @@ static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) */ static const struct block_device_operations viodasd_fops = { .owner = THIS_MODULE, - .open = viodasd_open, + .open = viodasd_unlocked_open, .release = viodasd_release, .getgeo = viodasd_getgeo, }; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 9119cd3d56a4..91374282755d 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -1018,13 +1019,18 @@ static int blkfront_is_ready(struct xenbus_device *dev) static int blkif_open(struct block_device *bdev, fmode_t mode) { struct blkfront_info *info = bdev->bd_disk->private_data; + + lock_kernel(); info->users++; + unlock_kernel(); + return 0; } static int blkif_release(struct gendisk *disk, fmode_t mode) { struct blkfront_info *info = disk->private_data; + lock_kernel(); info->users--; if (info->users == 0) { /* Check whether we have been instructed to close. We will @@ -1036,6 +1042,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode) if (state == XenbusStateClosing && info->is_ready) blkfront_closing(dev); } + unlock_kernel(); return 0; } diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index ac278ac908d5..b71888b909a0 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -89,6 +89,7 @@ #include #include #include +#include #include #include #include @@ -901,11 +902,14 @@ static int ace_open(struct block_device *bdev, fmode_t mode) dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1); + lock_kernel(); spin_lock_irqsave(&ace->lock, flags); ace->users++; spin_unlock_irqrestore(&ace->lock, flags); check_disk_change(bdev); + unlock_kernel(); + return 0; } @@ -917,6 +921,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode) dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1); + lock_kernel(); spin_lock_irqsave(&ace->lock, flags); ace->users--; if (ace->users == 0) { @@ -924,6 +929,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode) ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ); } spin_unlock_irqrestore(&ace->lock, flags); + unlock_kernel(); return 0; } diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 9114654b54d9..d75b2bb601ad 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -153,6 +154,7 @@ static int z2_open(struct block_device *bdev, fmode_t mode) device = MINOR(bdev->bd_dev); + lock_kernel(); if ( current_device != -1 && current_device != device ) { rc = -EBUSY; @@ -294,20 +296,25 @@ static int z2_open(struct block_device *bdev, fmode_t mode) set_capacity(z2ram_gendisk, z2ram_size >> 9); } + unlock_kernel(); return 0; err_out_kfree: kfree(z2ram_map); err_out: + unlock_kernel(); return rc; } static int z2_release(struct gendisk *disk, fmode_t mode) { - if ( current_device == -1 ) - return 0; - + lock_kernel(); + if ( current_device == -1 ) { + unlock_kernel(); + return 0; + } + unlock_kernel(); /* * FIXME: unmap memory */ diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 1772fd914fb9..261107d1457c 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -493,12 +493,18 @@ static struct cdrom_device_ops gdrom_ops = { static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode) { - return cdrom_open(gd.cd_info, bdev, mode); + int ret; + lock_kernel(); + ret = cdrom_open(gd.cd_info, bdev, mode); + unlock_kernel(); + return ret; } static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode) { + lock_kernel(); cdrom_release(gd.cd_info, mode); + unlock_kernel(); return 0; } diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 16dada0627ee..56bf9f44700c 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -154,13 +154,21 @@ static const struct file_operations proc_viocd_operations = { static int viocd_blk_open(struct block_device *bdev, fmode_t mode) { struct disk_info *di = bdev->bd_disk->private_data; - return cdrom_open(&di->viocd_info, bdev, mode); + int ret; + + lock_kernel(); + ret = cdrom_open(&di->viocd_info, bdev, mode); + unlock_kernel(); + + return ret; } static int viocd_blk_release(struct gendisk *disk, fmode_t mode) { struct disk_info *di = disk->private_data; + lock_kernel(); cdrom_release(&di->viocd_info, mode); + unlock_kernel(); return 0; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index bf9f61a5c2f8..5108e9739c96 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1591,17 +1591,19 @@ static struct ide_driver ide_cdrom_driver = { static int idecd_open(struct block_device *bdev, fmode_t mode) { - struct cdrom_info *info = ide_cd_get(bdev->bd_disk); - int rc = -ENOMEM; + struct cdrom_info *info; + int rc = -ENXIO; + lock_kernel(); + info = ide_cd_get(bdev->bd_disk); if (!info) - return -ENXIO; + goto out; rc = cdrom_open(&info->devinfo, bdev, mode); - if (rc < 0) ide_cd_put(info); - +out: + unlock_kernel(); return rc; } @@ -1609,9 +1611,11 @@ static int idecd_release(struct gendisk *disk, fmode_t mode) { struct cdrom_info *info = ide_drv_g(disk, cdrom_info); + lock_kernel(); cdrom_release(&info->devinfo, mode); ide_cd_put(info); + unlock_kernel(); return 0; } diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index 883f0c979c9f..137337a795a9 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -237,6 +238,18 @@ out_put_idkp: return ret; } +static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = ide_gd_open(bdev, mode); + unlock_kernel(); + + return ret; +} + + static int ide_gd_release(struct gendisk *disk, fmode_t mode) { struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); @@ -244,6 +257,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode) ide_debug_log(IDE_DBG_FUNC, "enter"); + lock_kernel(); if (idkp->openers == 1) drive->disk_ops->flush(drive); @@ -255,6 +269,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode) idkp->openers--; ide_disk_put(idkp); + unlock_kernel(); return 0; } @@ -321,7 +336,7 @@ static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode, static const struct block_device_operations ide_gd_ops = { .owner = THIS_MODULE, - .open = ide_gd_open, + .open = ide_gd_unlocked_open, .release = ide_gd_release, .ioctl = ide_gd_ioctl, .getgeo = ide_gd_getgeo, diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 39b0a5c45f07..6d622cb5ac81 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1907,7 +1907,11 @@ static const struct file_operations idetape_fops = { static int idetape_open(struct block_device *bdev, fmode_t mode) { - struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk, false, 0); + struct ide_tape_obj *tape; + + lock_kernel(); + tape = ide_tape_get(bdev->bd_disk, false, 0); + unlock_kernel(); if (!tape) return -ENXIO; @@ -1919,7 +1923,10 @@ static int idetape_release(struct gendisk *disk, fmode_t mode) { struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj); + lock_kernel(); ide_tape_put(tape); + unlock_kernel(); + return 0; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d505a96845c1..a3f21dc02bd8 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -338,6 +339,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode) { struct mapped_device *md; + lock_kernel(); spin_lock(&_minor_lock); md = bdev->bd_disk->private_data; @@ -355,6 +357,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode) out: spin_unlock(&_minor_lock); + unlock_kernel(); return md ? 0 : -ENXIO; } @@ -362,8 +365,12 @@ out: static int dm_blk_close(struct gendisk *disk, fmode_t mode) { struct mapped_device *md = disk->private_data; + + lock_kernel(); atomic_dec(&md->open_count); dm_put(md); + unlock_kernel(); + return 0; } diff --git a/drivers/md/md.c b/drivers/md/md.c index 1893af678779..700c96edf9b2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -36,6 +36,7 @@ #include #include #include +#include #include /* for invalidate_bdev */ #include #include @@ -5902,6 +5903,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) mddev_t *mddev = mddev_find(bdev->bd_dev); int err; + lock_kernel(); if (mddev->gendisk != bdev->bd_disk) { /* we are racing with mddev_put which is discarding this * bd_disk. @@ -5910,6 +5912,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) /* Wait until bdev->bd_disk is definitely gone */ flush_scheduled_work(); /* Then retry the open from the top */ + unlock_kernel(); return -ERESTARTSYS; } BUG_ON(mddev != bdev->bd_disk->private_data); @@ -5923,6 +5926,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) check_disk_size_change(mddev->gendisk, bdev); out: + unlock_kernel(); return err; } @@ -5931,8 +5935,10 @@ static int md_release(struct gendisk *disk, fmode_t mode) mddev_t *mddev = disk->private_data; BUG_ON(!mddev); + lock_kernel(); atomic_dec(&mddev->openers); mddev_put(mddev); + unlock_kernel(); return 0; } diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 56645408d225..eef78a068fd1 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #define DRIVER_NAME "mspro_block" @@ -179,6 +180,7 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode) struct mspro_block_data *msb = disk->private_data; int rc = -ENXIO; + lock_kernel(); mutex_lock(&mspro_block_disk_lock); if (msb && msb->card) { @@ -190,6 +192,7 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode) } mutex_unlock(&mspro_block_disk_lock); + unlock_kernel(); return rc; } @@ -221,7 +224,11 @@ static int mspro_block_disk_release(struct gendisk *disk) static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode) { - return mspro_block_disk_release(disk); + int ret; + lock_kernel(); + ret = mspro_block_disk_release(disk); + unlock_kernel(); + return ret; } static int mspro_block_bd_getgeo(struct block_device *bdev, diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index d1bdf8abe5db..a5bc3ee0d93e 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -53,6 +53,7 @@ #include #include #include +#include #include @@ -577,6 +578,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode) if (!dev->i2o_dev) return -ENODEV; + lock_kernel(); if (dev->power > 0x1f) i2o_block_device_power(dev, 0x02); @@ -585,6 +587,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode) i2o_block_device_lock(dev->i2o_dev, -1); osm_debug("Ready.\n"); + unlock_kernel(); return 0; }; @@ -615,6 +618,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode) if (!dev->i2o_dev) return 0; + lock_kernel(); i2o_block_device_flush(dev->i2o_dev); i2o_block_device_unlock(dev->i2o_dev, -1); @@ -625,6 +629,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode) operation = 0x24; i2o_block_device_power(dev, operation); + unlock_kernel(); return 0; } diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index cb9fbc83b090..8433cde29c8b 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); int ret = -ENXIO; + lock_kernel(); if (md) { if (md->usage == 2) check_disk_change(bdev); @@ -117,6 +119,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) ret = -EROFS; } } + unlock_kernel(); return ret; } @@ -125,7 +128,9 @@ static int mmc_blk_release(struct gendisk *disk, fmode_t mode) { struct mmc_blk_data *md = disk->private_data; + lock_kernel(); mmc_blk_put(md); + unlock_kernel(); return 0; } diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 8c83b11a77d5..5ca80aee2ed0 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -165,8 +165,9 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) int ret; if (!dev) - return -ERESTARTSYS; + return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ + lock_kernel(); mutex_lock(&dev->lock); if (!dev->mtd) { @@ -183,6 +184,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); + unlock_kernel(); return ret; } @@ -194,6 +196,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode) if (!dev) return ret; + lock_kernel(); mutex_lock(&dev->lock); /* Release one reference, we sure its not the last one here*/ @@ -206,6 +209,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode) unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); + unlock_kernel(); return ret; } diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 17b033d0e050..1a84fae155e1 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -2235,6 +2236,7 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) if (!block) return -ENODEV; + lock_kernel(); base = block->base; atomic_inc(&block->open_count); if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) { @@ -2269,12 +2271,14 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) goto out; } + unlock_kernel(); return 0; out: module_put(base->discipline->owner); unlock: atomic_dec(&block->open_count); + unlock_kernel(); return rc; } @@ -2282,8 +2286,10 @@ static int dasd_release(struct gendisk *disk, fmode_t mode) { struct dasd_block *block = disk->private_data; + lock_kernel(); atomic_dec(&block->open_count); module_put(block->base->discipline->owner); + unlock_kernel(); return 0; } diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 9b43ae94beba..2bd72aa34c59 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -775,6 +776,7 @@ dcssblk_open(struct block_device *bdev, fmode_t mode) struct dcssblk_dev_info *dev_info; int rc; + lock_kernel(); dev_info = bdev->bd_disk->private_data; if (NULL == dev_info) { rc = -ENODEV; @@ -784,6 +786,7 @@ dcssblk_open(struct block_device *bdev, fmode_t mode) bdev->bd_block_size = 4096; rc = 0; out: + unlock_kernel(); return rc; } @@ -794,6 +797,7 @@ dcssblk_release(struct gendisk *disk, fmode_t mode) struct segment_info *entry; int rc; + lock_kernel(); if (!dev_info) { rc = -ENODEV; goto out; @@ -811,6 +815,7 @@ dcssblk_release(struct gendisk *disk, fmode_t mode) up_write(&dcssblk_devices_sem); rc = 0; out: + unlock_kernel(); return rc; } diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 097da8ce6be6..b7de02525ec9 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -361,6 +362,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) struct tape_device * device; int rc; + lock_kernel(); device = tape_get_device(disk->private_data); if (device->required_tapemarks) { @@ -384,12 +386,14 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) * is called. */ tape_state_set(device, TS_BLKUSE); + unlock_kernel(); return 0; release: tape_release(device); put_device: tape_put_device(device); + unlock_kernel(); return rc; } @@ -403,10 +407,12 @@ static int tapeblock_release(struct gendisk *disk, fmode_t mode) { struct tape_device *device = disk->private_data; - + + lock_kernel(); tape_state_set(device, TS_IN_USE); tape_release(device); tape_put_device(device); + unlock_kernel(); return 0; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 633ac32b25c1..01680c7c8507 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -795,6 +795,7 @@ static int sd_open(struct block_device *bdev, fmode_t mode) SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n")); + lock_kernel(); sdev = sdkp->device; /* @@ -838,10 +839,12 @@ static int sd_open(struct block_device *bdev, fmode_t mode) scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); } + unlock_kernel(); return 0; error_out: scsi_disk_put(sdkp); + unlock_kernel(); return retval; } @@ -863,6 +866,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode) SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); + lock_kernel(); if (!--sdkp->openers && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); @@ -873,6 +877,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode) * XXX is followed by a "rmmod sd_mod"? */ scsi_disk_put(sdkp); + unlock_kernel(); return 0; } diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index d42fa6468f41..ba9c3e0387ce 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -467,22 +467,27 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) static int sr_block_open(struct block_device *bdev, fmode_t mode) { - struct scsi_cd *cd = scsi_cd_get(bdev->bd_disk); + struct scsi_cd *cd; int ret = -ENXIO; + lock_kernel(); + cd = scsi_cd_get(bdev->bd_disk); if (cd) { ret = cdrom_open(&cd->cdi, bdev, mode); if (ret) scsi_cd_put(cd); } + unlock_kernel(); return ret; } static int sr_block_release(struct gendisk *disk, fmode_t mode) { struct scsi_cd *cd = scsi_cd(disk); + lock_kernel(); cdrom_release(&cd->cdi, mode); scsi_cd_put(cd); + unlock_kernel(); return 0; } diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index a9aff90e58e0..87a11c9293e9 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1326,6 +1327,7 @@ static int blkvsc_open(struct block_device *bdev, fmode_t mode) DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users, blkdev->gd->disk_name); + lock_kernel(); spin_lock(&blkdev->lock); if (!blkdev->users && blkdev->device_type == DVD_TYPE) { @@ -1337,6 +1339,7 @@ static int blkvsc_open(struct block_device *bdev, fmode_t mode) blkdev->users++; spin_unlock(&blkdev->lock); + unlock_kernel(); return 0; } @@ -1347,6 +1350,7 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode) DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users, blkdev->gd->disk_name); + lock_kernel(); spin_lock(&blkdev->lock); if (blkdev->users == 1) { spin_unlock(&blkdev->lock); @@ -1357,6 +1361,7 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode) blkdev->users--; spin_unlock(&blkdev->lock); + unlock_kernel(); return 0; } diff --git a/fs/block_dev.c b/fs/block_dev.c index 99d6af811747..693c2bf5d65e 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1345,13 +1345,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) return ret; } - lock_kernel(); restart: ret = -ENXIO; disk = get_gendisk(bdev->bd_dev, &partno); if (!disk) - goto out_unlock_kernel; + goto out; mutex_lock_nested(&bdev->bd_mutex, for_part); if (!bdev->bd_openers) { @@ -1431,7 +1430,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (for_part) bdev->bd_part_count++; mutex_unlock(&bdev->bd_mutex); - unlock_kernel(); return 0; out_clear: @@ -1444,9 +1442,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) bdev->bd_contains = NULL; out_unlock_bdev: mutex_unlock(&bdev->bd_mutex); - out_unlock_kernel: - unlock_kernel(); - + out: if (disk) module_put(disk->fops->owner); put_disk(disk); @@ -1515,7 +1511,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part) struct block_device *victim = NULL; mutex_lock_nested(&bdev->bd_mutex, for_part); - lock_kernel(); if (for_part) bdev->bd_part_count--; @@ -1540,7 +1535,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part) victim = bdev->bd_contains; bdev->bd_contains = NULL; } - unlock_kernel(); mutex_unlock(&bdev->bd_mutex); bdput(bdev); if (victim) -- cgit v1.2.3 From 409f3499a2cfcd1e9c2857c53af7fcce069f027f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 7 Jul 2010 16:51:29 +0200 Subject: scsi/sd: remove big kernel lock Every user of the BKL in the sd driver is the result of the pushdown from the block layer into the open/close/ioctl functions. The only place that used to rely on the BKL is the sdkp->openers variable, which gets converted into an atomic_t. Nothing else seems to rely on the BKL, since the functions do not touch global data without holding another lock, and the open/close functions are still protected from concurrent execution using the bdev->bd_mutex. Signed-off-by: Arnd Bergmann Cc: linux-scsi@vger.kernel.org Cc: "James E.J. Bottomley" Acked-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 17 +++++++---------- drivers/scsi/sd.h | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 01680c7c8507..fc5d69a84af5 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -783,6 +783,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * or from within the kernel (e.g. as a result of a mount(1) ). * In the latter case @inode and @filp carry an abridged amount * of information as noted above. + * + * Locking: called with bdev->bd_mutex held. **/ static int sd_open(struct block_device *bdev, fmode_t mode) { @@ -795,7 +797,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode) SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n")); - lock_kernel(); sdev = sdkp->device; /* @@ -834,17 +835,15 @@ static int sd_open(struct block_device *bdev, fmode_t mode) if (!scsi_device_online(sdev)) goto error_out; - if (!sdkp->openers++ && sdev->removable) { + if ((atomic_inc_return(&sdkp->openers) == 1) && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); } - unlock_kernel(); return 0; error_out: scsi_disk_put(sdkp); - unlock_kernel(); return retval; } @@ -858,6 +857,8 @@ error_out: * * Note: may block (uninterruptible) if error recovery is underway * on this disk. + * + * Locking: called with bdev->bd_mutex held. **/ static int sd_release(struct gendisk *disk, fmode_t mode) { @@ -866,8 +867,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode) SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); - lock_kernel(); - if (!--sdkp->openers && sdev->removable) { + if (atomic_dec_return(&sdkp->openers) && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); } @@ -877,7 +877,6 @@ static int sd_release(struct gendisk *disk, fmode_t mode) * XXX is followed by a "rmmod sd_mod"? */ scsi_disk_put(sdkp); - unlock_kernel(); return 0; } @@ -930,7 +929,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n", disk->disk_name, cmd)); - lock_kernel(); /* * If we are in the middle of error recovery, don't let anyone * else try and use this device. Also, if error recovery fails, it @@ -960,7 +958,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, break; } out: - unlock_kernel(); return error; } @@ -2346,7 +2343,7 @@ static int sd_probe(struct device *dev) sdkp->driver = &sd_template; sdkp->disk = gd; sdkp->index = index; - sdkp->openers = 0; + atomic_set(&sdkp->openers, 0); sdkp->previous_state = 1; if (!sdp->request_queue->rq_timeout) { diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 43d3caf268ef..f81a9309e6de 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -47,7 +47,7 @@ struct scsi_disk { struct scsi_device *device; struct device dev; struct gendisk *disk; - unsigned int openers; /* protected by BKL for now, yuck */ + atomic_t openers; sector_t capacity; /* size in 512-byte sectors */ u32 index; unsigned short hw_sector_size; -- cgit v1.2.3 From 6a32a8aed509e71137043d464db4a7fcd88c903e Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 21 Jul 2010 10:29:37 +0900 Subject: scsi: convert discard to REQ_TYPE_FS from REQ_TYPE_BLOCK_PC Jens, any reason why this isn't included in your for-2.6.36 yet? = From: FUJITA Tomonori Subject: [PATCH resend] scsi: convert discard to REQ_TYPE_FS from REQ_TYPE_BLOCK_PC The block layer (file systems) sends discard requests as REQ_TYPE_FS (the role of REQ_TYPE_FS is that setting up commands and interpreting the results). But SCSI-ml treats discard requests as REQ_TYPE_BLOCK_PC. scsi-ml can handle discard requests as REQ_TYPE_FS easily. scsi_setup_discard_cmnd() sets up struct request and the bio nicely. Only remaining issue is that discard requests can't be completed partially so we need to modify sd_done. This conversion also fixes the problem that discard requests aren't retried when possible (e.g. UNIT ATTENTION). Signed-off-by: FUJITA Tomonori Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/scsi/sd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index fc5d69a84af5..e63b85ac8cd1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -434,7 +434,6 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) nr_sectors >>= 3; } - rq->cmd_type = REQ_TYPE_BLOCK_PC; rq->timeout = SD_TIMEOUT; memset(rq->cmd, 0, rq->cmd_len); @@ -1200,6 +1199,12 @@ static int sd_done(struct scsi_cmnd *SCpnt) int sense_valid = 0; int sense_deferred = 0; + if (SCpnt->request->cmd_flags & REQ_DISCARD) { + if (!result) + scsi_set_resid(SCpnt, 0); + return good_bytes; + } + if (result) { sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); if (sense_valid) -- cgit v1.2.3 From e96f6abe02fc3320d669985443e8c68ff8e83294 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 9 Jul 2010 09:38:26 +0900 Subject: scsi: use REQ_TYPE_FS for flush request scsi-ml uses REQ_TYPE_BLOCK_PC for flush requests from file systems. The definition of REQ_TYPE_BLOCK_PC is that we don't retry requests even when we can (e.g. UNIT ATTENTION) and we send the response to the callers (then the callers can decide what they want). We need a workaround such as the commit 77a4229719e511a0d38d9c355317ae1469adeb54 to retry BLOCK_PC flush requests. We will need the similar workaround for discard requests too since SCSI-ml handle them as BLOCK_PC internally. This uses REQ_TYPE_FS for flush requests from file systems instead of REQ_TYPE_BLOCK_PC. scsi-ml retries only REQ_TYPE_FS requests that have data to transfer when we can retry them (e.g. UNIT_ATTENTION). However, we also need to retry REQ_TYPE_FS requests without data because the callers don't. This also changes scsi_check_sense() to retry all the REQ_TYPE_FS requests when appropriate. Thanks to scsi_noretry_cmd(), REQ_TYPE_BLOCK_PC requests don't be retried as before. Note that basically, this reverts the commit 77a4229719e511a0d38d9c355317ae1469adeb54 since now we use REQ_TYPE_FS for flush requests. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/scsi_error.c | 19 ++++--------------- drivers/scsi/sd.c | 2 -- 2 files changed, 4 insertions(+), 17 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1b88af89d0c7..2768bf6ffe59 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -307,20 +307,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) (sshdr.asc == 0x04) && (sshdr.ascq == 0x02)) return FAILED; - if (scmd->request->cmd_flags & REQ_HARDBARRIER) - /* - * barrier requests should always retry on UA - * otherwise block will get a spurious error - */ - return NEEDS_RETRY; - else - /* - * for normal (non barrier) commands, pass the - * UA upwards for a determination in the - * completion functions - */ - return SUCCESS; - + return NEEDS_RETRY; /* these three are not supported */ case COPY_ABORTED: case VOLUME_OVERFLOW: @@ -1336,7 +1323,9 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd) * assume caller has checked sense and determinted * the check condition was retryable. */ - return (scmd->request->cmd_flags & REQ_FAILFAST_DEV); + if (scmd->request->cmd_flags & REQ_FAILFAST_DEV || + scmd->request->cmd_type == REQ_TYPE_BLOCK_PC) + return 1; } return 0; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e63b85ac8cd1..108daead7ae8 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -477,8 +477,6 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) { - /* for now, we use REQ_TYPE_BLOCK_PC. */ - rq->cmd_type = REQ_TYPE_BLOCK_PC; rq->timeout = SD_TIMEOUT; rq->retries = SD_MAX_RETRIES; rq->cmd[0] = SYNCHRONIZE_CACHE; -- cgit v1.2.3 From 3eb3a92851857e6de92ad0c57bf7046ac4f58671 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 29 Jul 2010 10:10:16 +0200 Subject: [SCSI] Return NEEDS_RETRY for eh commands with status BUSY When the transport is busy and we're sending an EH command drivers occasionally return 'BUSY'. As this in most cases is the TUR command sent as part of the error recovery this is a sure way to make the error recovery escalate. Returning 'NEEDS_RETRY' here will just retry the TUR command and eventually abort the original command, thus making error handling far smoother. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2bf98469dc4c..cfd01ef8a9d4 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -481,6 +481,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) scsi_handle_queue_full(scmd->device); /* fall through */ case BUSY: + return NEEDS_RETRY; default: return FAILED; } -- cgit v1.2.3 From 3deee42088ddcf5b23021aa089b53444797e565d Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Thu, 5 Aug 2010 17:50:37 -0700 Subject: [SCSI] tgt: fix warning Using scsi_tgt_lib in a new target module, we were getting the following warning and a stack traceback on every I/O completion: WARNING: at block/blk-core.c:1108 Which is claiming we may be leaking a bio. We don't leak bios (blk_rq_unmap_user should free them). Set rq->bio to NULL before calling scsi_host_put_command(). This was as advised by Fujita Tomonori. Signed-off-by: Joe Eykholt Acked-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/scsi_tgt_lib.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 66241dd525ae..c399be979921 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -185,6 +185,7 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work) dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction, rq_data_dir(cmd->request)); scsi_unmap_user_pages(tcmd); + tcmd->rq->bio = NULL; scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); } -- cgit v1.2.3 From 67110dfd45442e70753c575cf0509eaed237b749 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 6 Aug 2010 15:17:24 -0500 Subject: [SCSI] make error handling more robust in the face of reservations commit 5f91bb050ecc4ff1d8d3d07edbe550c8f431c5e1 Author: Michael Reed Date: Mon Aug 10 11:59:28 2009 -0500 [SCSI] reservation conflict after timeout causes device to be taken offline Flipped us from always returning failed to always returning success in the name of fixing the problem where reservation conflict returns from test unit ready cause the device always to be taken offline. Unfortuantely, it also introduced a problem whereby for commands other than test unit ready, the eh dispatcher thinks they succeeded when reservation conflict is returned, whereas in reality they failed. Fix this by only returning success for the test unit ready case. Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index cfd01ef8a9d4..0bd88381c1e1 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -473,10 +473,12 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) */ return SUCCESS; case RESERVATION_CONFLICT: - /* - * let issuer deal with this, it could be just fine - */ - return SUCCESS; + if (scmd->cmnd[0] == TEST_UNIT_READY) + /* it is a success, we probed the device and + * found it */ + return SUCCESS; + /* otherwise, we failed to send the command */ + return FAILED; case QUEUE_FULL: scsi_handle_queue_full(scmd->device); /* fall through */ -- cgit v1.2.3 From 3c3e210877e89aa3bfbda22551876986c035c433 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Mon, 9 Aug 2010 05:14:07 -0700 Subject: [SCSI] qla4xxx: fix compilation warning Fix following warning: drivers/scsi/qla4xxx/ql4_nx.c: In function 'qla4_8xxx_get_flash_info': drivers/scsi/qla4xxx/ql4_nx.c:1952: warning: 'mid' may be used uninitialized in this function drivers/scsi/qla4xxx/ql4_nx.c:1952: note: 'mid' was declared here drivers/scsi/qla4xxx/ql4_nx.c:1952: warning: 'fid' may be used uninitialized in this function drivers/scsi/qla4xxx/ql4_nx.c:1952: note: 'fid' was declared here Signed-off-by: Vikas Chaudhary Reported-by: Stephen Rothwell Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_nx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 1b85235efd8c..e031a734836e 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1953,7 +1953,8 @@ qla4_8xxx_get_fdt_info(struct scsi_qla_host *ha) uint16_t cnt, chksum; uint16_t *wptr; struct qla_fdt_layout *fdt; - uint16_t mid, fid; + uint16_t mid = 0; + uint16_t fid = 0; struct ql82xx_hw_data *hw = &ha->hw; hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; -- cgit v1.2.3 From d6d1b650ae6acce73d55dd0246de22180303ae73 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 11 Aug 2010 23:04:27 -0600 Subject: param: simple locking for sysfs-writable charp parameters Since the writing to sysfs can free the old one, we need to block that when we access the charp variables. Signed-off-by: Rusty Russell Reviewed-by: Takashi Iwai Tested-by: Phil Carmody Cc: Jeff Dike Cc: Dan Williams Cc: John W. Linville Cc: Jing Huang Cc: James E.J. Bottomley Cc: Greg Kroah-Hartman Cc: Johannes Berg Cc: David S. Miller Cc: user-mode-linux-devel@lists.sourceforge.net Cc: libertas-dev@lists.infradead.org Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Cc: linux-scsi@vger.kernel.org Cc: linux-usb@vger.kernel.org --- arch/um/drivers/hostaudio_kern.c | 10 ++++++++++ drivers/net/wireless/libertas/if_usb.c | 3 +++ drivers/net/wireless/libertas_tf/if_usb.c | 3 +++ drivers/scsi/bfa/bfad.c | 2 ++ drivers/usb/atm/ueagle-atm.c | 2 ++ drivers/video/vt8623fb.c | 2 ++ net/mac80211/rate.c | 2 ++ 7 files changed, 24 insertions(+) (limited to 'drivers/scsi') diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 68142df76608..0c46e398cd8f 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -187,7 +187,9 @@ static int hostaudio_open(struct inode *inode, struct file *file) int ret; #ifdef DEBUG + kparam_block_sysfs_write(dsp); printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp); + kparam_unblock_sysfs_write(dsp); #endif state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); @@ -199,9 +201,11 @@ static int hostaudio_open(struct inode *inode, struct file *file) if (file->f_mode & FMODE_WRITE) w = 1; + kparam_block_sysfs_write(dsp); lock_kernel(); ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); unlock_kernel(); + kparam_unblock_sysfs_write(dsp); if (ret < 0) { kfree(state); @@ -258,13 +262,17 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) if (file->f_mode & FMODE_WRITE) w = 1; + kparam_block_sysfs_write(mixer); lock_kernel(); ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); unlock_kernel(); + kparam_unblock_sysfs_write(mixer); if (ret < 0) { + kparam_block_sysfs_write(dsp); printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', " "err = %d\n", dsp, -ret); + kparam_unblock_sysfs_write(dsp); kfree(state); return ret; } @@ -320,8 +328,10 @@ MODULE_LICENSE("GPL"); static int __init hostaudio_init_module(void) { + __kernel_param_lock(); printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", dsp, mixer); + __kernel_param_unlock(); module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); if (module_data.dev_audio < 0) { diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 07ece9d26c63..3ff61063671a 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -289,10 +289,13 @@ static int if_usb_probe(struct usb_interface *intf, } /* Upload firmware */ + kparam_block_sysfs_write(fw_name); if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { + kparam_unblock_sysfs_write(fw_name); lbs_deb_usbd(&udev->dev, "FW upload failed\n"); goto err_prog_firmware; } + kparam_unblock_sysfs_write(fw_name); if (!(priv = lbs_add_card(cardp, &udev->dev))) goto err_prog_firmware; diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index b172f5d87a3b..41a4f214ade1 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -811,12 +811,15 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) lbtf_deb_enter(LBTF_DEB_USB); + kparam_block_sysfs_write(fw_name); ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); if (ret < 0) { pr_err("request_firmware() failed with %#x\n", ret); pr_err("firmware %s not found\n", lbtf_fw_name); + kparam_unblock_sysfs_write(fw_name); goto done; } + kparam_unblock_sysfs_write(fw_name); if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) goto release_fw; diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 915a29d6c7ad..ca04cc9d332f 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -788,6 +788,7 @@ bfad_drv_init(struct bfad_s *bfad) memset(&driver_info, 0, sizeof(driver_info)); strncpy(driver_info.version, BFAD_DRIVER_VERSION, sizeof(driver_info.version) - 1); + __kernel_param_lock(); if (host_name) strncpy(driver_info.host_machine_name, host_name, sizeof(driver_info.host_machine_name) - 1); @@ -797,6 +798,7 @@ bfad_drv_init(struct bfad_s *bfad) if (os_patch) strncpy(driver_info.host_os_patch, os_patch, sizeof(driver_info.host_os_patch) - 1); + __kernel_param_unlock(); strncpy(driver_info.os_device_name, bfad->pci_name, sizeof(driver_info.os_device_name - 1)); diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 5b3f555e01c9..ea071a5b6eee 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -1577,6 +1577,7 @@ static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) char file_arr[] = "CMVxy.bin"; char *file; + kparam_block_sysfs_write(cmv_file); /* set proper name corresponding modem version and line type */ if (cmv_file[sc->modem_index] == NULL) { if (UEA_CHIP_VERSION(sc) == ADI930) @@ -1595,6 +1596,7 @@ static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) strlcat(cmv_name, file, UEA_FW_NAME_MAX); if (ver == 2) strlcat(cmv_name, ".v2", UEA_FW_NAME_MAX); + kparam_unblock_sysfs_write(cmv_file); } static int request_cmvs_old(struct uea_softc *sc, diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index d31dc96f838a..85d76ec4c63e 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c @@ -726,7 +726,9 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi /* Prepare startup mode */ + kparam_block_sysfs_write(mode_option); rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); + kparam_unblock_sysfs_write(mode_option); if (! ((rc == 1) || (rc == 2))) { rc = -EINVAL; dev_err(info->device, "mode %s not found\n", mode_option); diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6d0bd198af19..be04d46110fe 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -103,6 +103,7 @@ ieee80211_rate_control_ops_get(const char *name) struct rate_control_ops *ops; const char *alg_name; + kparam_block_sysfs_write(ieee80211_default_rc_algo); if (!name) alg_name = ieee80211_default_rc_algo; else @@ -120,6 +121,7 @@ ieee80211_rate_control_ops_get(const char *name) /* try built-in one if specific alg requested but not found */ if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); + kparam_unblock_sysfs_write(ieee80211_default_rc_algo); return ops; } -- cgit v1.2.3 From ef3f7cc41280e9611a837df1fedf3f6d4d921a75 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 10 Aug 2010 18:01:10 -0700 Subject: osst: fix read buffer overflow Check whether index is within bounds before testing the element. Signed-off-by: Roel Kluin Cc: Willem Riede Cc: James E.J. Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/osst.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index d64b7178fa08..278b352ae78d 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5868,7 +5868,8 @@ static int osst_probe(struct device *dev) } /* find a free minor number */ - for (i=0; os_scsi_tapes[i] && i= osst_max_dev) panic ("Scsi_devices corrupt (osst)"); dev_num = i; -- cgit v1.2.3 From 2c076eea6d3005c54f6e7be5938477fdc7027686 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 10 Aug 2010 18:01:10 -0700 Subject: gdth: unmap ccb_phys when scsi_add_host() fails in gdth_eisa_probe_one() unmap ccb_phys as well when scsi_add_host() fails Signed-off-by: Roel Kluin Cc: Achim Leubner Cc: James E.J. Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/gdth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index f672d6213eea..b860d650a563 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4914,7 +4914,7 @@ static int __init gdth_eisa_probe_one(u16 eisa_slot) error = scsi_add_host(shp, NULL); if (error) - goto out_free_coal_stat; + goto out_free_ccb_phys; list_add_tail(&ha->list, &gdth_instances); gdth_timer_init(); -- cgit v1.2.3 From 085267acd0ca29623c8239a38639d43d6d21e972 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 10 Aug 2010 18:01:11 -0700 Subject: NCR5380: bit MR_DMA_MODE set twice in NCR5380_transfer_dma() Besides keeping the line short, the second setting of the MR_DMA_MODE bit was removed. Signed-off-by: Roel Kluin Cc: James Bottomley Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/NCR5380.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index f92da9fd5f20..5d2f148889ad 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1857,7 +1857,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase #endif /* KLL May need eop and parity in 53c400 */ if (hostdata->flags & FLAG_NCR53C400) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE | MR_MONITOR_BSY); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | + MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | + MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); else NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); #endif /* def REAL_DMA */ -- cgit v1.2.3 From 95cc7baa7f19e191b4790d144b7cbe47369cfe32 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 10 Aug 2010 18:01:13 -0700 Subject: drivers/scsi: remove unnecessary NULL test At the point where cmnd is initialized, it is tested for NULL, so it doesn't have to be tested again here. A simplified version of the semantic match that detects this problem is as follows (http://coccinelle.lip6.fr/): // @match exists@ expression x, E; identifier fld; @@ * x->fld ... when != \(x = E\|&x\) * x == NULL // Signed-off-by: Julia Lawall Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/initio.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index a7714160fbc3..108797761b95 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -2817,7 +2817,6 @@ static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem) } cmnd->result = cblk->tastat | (cblk->hastat << 16); - WARN_ON(cmnd == NULL); i91u_unmap_scb(host->pci_dev, cmnd); cmnd->scsi_done(cmnd); /* Notify system DONE */ initio_release_scb(host, cblk); /* Release SCB for current channel */ -- cgit v1.2.3 From c94babbaf85c3162bd53a722ceeea32a0982d436 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 10 Aug 2010 18:01:15 -0700 Subject: g_NCR5380: remove misleading pnp error message Remove misleading error message that appears after pnp card has been detected correctly. Signed-off-by: Ondrej Zary Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/g_NCR5380.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 75585a52c88b..6bc0015662e0 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -322,10 +322,8 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { if (count >= NO_OVERRIDES) break; - if (pnp_device_attach(dev) < 0) { - printk(KERN_ERR "dtc436e probe: attach failed\n"); + if (pnp_device_attach(dev) < 0) continue; - } if (pnp_activate_dev(dev) < 0) { printk(KERN_ERR "dtc436e probe: activate failed\n"); pnp_device_detach(dev); -- cgit v1.2.3 From 702a98c63355b74aec50897870eb1c89b5009cfb Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 10 Aug 2010 18:01:16 -0700 Subject: g_NCR5380: fix broken MMIO compilation The ifdefs are broken so the MMIO code is never compiled and so it's broken too. Fix them all. Untested as I don't have the hardware. Signed-off-by: Ondrej Zary Reviewed-by: Andy Walls Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/g_NCR5380.c | 43 +++++++++++++++++++++++-------------------- drivers/scsi/g_NCR5380.h | 6 +++--- 2 files changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 6bc0015662e0..427a56d3117e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -285,9 +285,12 @@ static int __init do_DTC3181E_setup(char *str) int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) { static int current_override = 0; - int count, i; + int count; unsigned int *ports; +#ifndef SCSI_G_NCR5380_MEM + int i; unsigned long region_size = 16; +#endif static unsigned int __initdata ncr_53c400a_ports[] = { 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 }; @@ -296,7 +299,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) }; int flags = 0; struct Scsi_Host *instance; -#ifdef CONFIG_SCSI_G_NCR5380_MEM +#ifdef SCSI_G_NCR5380_MEM unsigned long base; void __iomem *iomem; #endif @@ -315,7 +318,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) overrides[0].board = BOARD_NCR53C400A; else if (dtc_3181e != NCR_NOT_SET) overrides[0].board = BOARD_DTC3181E; - +#ifndef SCSI_G_NCR5380_MEM if (!current_override && isapnp_present()) { struct pnp_dev *dev = NULL; count = 0; @@ -347,7 +350,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) count++; } } - +#endif tpnt->proc_name = "g_NCR5380"; for (count = 0; current_override < NO_OVERRIDES; ++current_override) { @@ -372,7 +375,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) break; } -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM if (ports) { /* wakeup sequence for the NCR53C400A and DTC3181E */ @@ -434,7 +437,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) #endif instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); if (instance == NULL) { -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM release_region(overrides[current_override].NCR5380_map_name, region_size); #else iounmap(iomem); @@ -444,10 +447,10 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) } instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM instance->n_io_port = region_size; #else - ((struct NCR5380_hostdata *)instance->hostdata).iomem = iomem; + ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem; #endif NCR5380_init(instance, flags); @@ -515,10 +518,10 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) free_irq(instance->irq, instance); NCR5380_exit(instance); -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM release_region(instance->NCR5380_instance_name, instance->n_io_port); #else - iounmap(((struct NCR5380_hostdata *)instance->hostdata).iomem); + iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem); release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); #endif @@ -588,14 +591,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY); -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM { int i; for (i = 0; i < 128; i++) dst[start + i] = NCR5380_read(C400_HOST_BUFFER); } #else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ + /* implies SCSI_G_NCR5380_MEM */ memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); #endif start += 128; @@ -608,14 +611,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, // FIXME - no timeout } -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM { int i; for (i = 0; i < 128; i++) dst[start + i] = NCR5380_read(C400_HOST_BUFFER); } #else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ + /* implies SCSI_G_NCR5380_MEM */ memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); #endif start += 128; @@ -674,13 +677,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, } while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - timeout -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM { for (i = 0; i < 128; i++) NCR5380_write(C400_HOST_BUFFER, src[start + i]); } #else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ + /* implies SCSI_G_NCR5380_MEM */ memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); #endif start += 128; @@ -690,13 +693,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - no timeout -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM { for (i = 0; i < 128; i++) NCR5380_write(C400_HOST_BUFFER, src[start + i]); } #else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ + /* implies SCSI_G_NCR5380_MEM */ memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); #endif start += 128; @@ -936,7 +939,7 @@ module_param(ncr_53c400a, int, 0); module_param(dtc_3181e, int, 0); MODULE_LICENSE("GPL"); - +#ifndef SCSI_G_NCR5380_MEM static struct isapnp_device_id id_table[] __devinitdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, @@ -946,7 +949,7 @@ static struct isapnp_device_id id_table[] __devinitdata = { }; MODULE_DEVICE_TABLE(isapnp, id_table); - +#endif __setup("ncr5380=", do_NCR5380_setup); __setup("ncr53c400=", do_NCR53C400_setup); diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index df0b3f69ef63..921764c9ab24 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -63,7 +63,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); #define __STRVAL(x) #x #define STRVAL(x) __STRVAL(x) -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM #define NCR5380_map_config port #define NCR5380_map_type int @@ -91,7 +91,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) #else -/* therefore CONFIG_SCSI_G_NCR5380_MEM */ +/* therefore SCSI_G_NCR5380_MEM */ #define NCR5380_map_config memory #define NCR5380_map_type unsigned long @@ -114,7 +114,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); register void __iomem *iomem #define NCR5380_setup(instance) \ - iomem = (((struct NCR5380_hostdata *)(instance)->hostdata).iomem) + iomem = (((struct NCR5380_hostdata *)(instance)->hostdata)->iomem) #endif -- cgit v1.2.3 From d8187b945aa4ed9ea298518e3dac691ea09724e5 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 10 Aug 2010 18:01:17 -0700 Subject: dc395x: decrease iteration for tag_number of max_command in start_scsi() The tag_number reaches dcb->max_command + 1 after the loop, but when the tag_number equals dcb->max_command an error message is already issued. The last iteration therefore appears obsolete. Signed-off-by: Roel Kluin Cc: Oliver Neukum Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/dc395x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index bd977be7544e..54f50b07dac7 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -1597,7 +1597,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, u32 tag_mask = 1; u8 tag_number = 0; while (tag_mask & dcb->tag_mask - && tag_number <= dcb->max_command) { + && tag_number < dcb->max_command) { tag_mask = tag_mask << 1; tag_number++; } -- cgit v1.2.3 From 85bc081f44d53e3ac268c59275cc3b9b5afae04a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 10 Aug 2010 18:01:18 -0700 Subject: drivers/scsi/aic94xx/aic94xx_init.c: correct the size argument to kmalloc In each case, the destination of the allocation has type struct **, so the elements of the array should have pointer type, not structure type. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @disable sizeof_type_expr@ type T; T **x; @@ x = <+...sizeof( - T + *x )...+> // Signed-off-by: Julia Lawall Cc: Rolf Eike Beer Cc: Joe Perches Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/aic94xx/aic94xx_init.c | 4 ++-- drivers/scsi/ch.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 24ac2315c5c7..3b7e83d2dab4 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -688,9 +688,9 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha) { int i; struct asd_sas_phy **sas_phys = - kmalloc(ASD_MAX_PHYS * sizeof(struct asd_sas_phy), GFP_KERNEL); + kcalloc(ASD_MAX_PHYS, sizeof(*sas_phys), GFP_KERNEL); struct asd_sas_port **sas_ports = - kmalloc(ASD_MAX_PHYS * sizeof(struct asd_sas_port), GFP_KERNEL); + kcalloc(ASD_MAX_PHYS, sizeof(*sas_ports), GFP_KERNEL); if (!sas_phys || !sas_ports) { kfree(sas_phys); diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 4799d4391203..769b35f8b39f 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -352,7 +352,7 @@ ch_readconfig(scsi_changer *ch) } /* look up the devices of the data transfer elements */ - ch->dt = kmalloc(ch->counts[CHET_DT]*sizeof(struct scsi_device), + ch->dt = kcalloc(ch->counts[CHET_DT], sizeof(*ch->dt), GFP_KERNEL); if (!ch->dt) { -- cgit v1.2.3 From d6e9fb46cd9e60946dc3e89ad8e32dd251dcc05d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 10 Aug 2010 18:01:19 -0700 Subject: scsi: remove superfluous NULL pointer check from scsi_kill_request() Dan's list included: drivers/scsi/scsi_lib.c +1365 scsi_kill_request(9) warning: variable derefenced in initializer 'cmd' drivers/scsi/scsi_lib.c +1365 scsi_kill_request(9) warning: variable derefenced before check 'cmd' We dereference cmd (and possible OOPS if cmd == NULL) before starting the request so just remove the superfluous debugging code altogether. [ bart: the potential NULL pointer dereference was finally fixed in (much later than mine) commit 03b1470 but my patch is still valid ] Reported-by: Dan Carpenter Cc: Jonathan Corbet Cc: Eugene Teo Signed-off-by: Bartlomiej Zolnierkiewicz Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/scsi_lib.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b8de389636f8..9ade720422c6 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1370,12 +1370,6 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) blk_start_request(req); - if (unlikely(cmd == NULL)) { - printk(KERN_CRIT "impossible request in %s.\n", - __func__); - BUG(); - } - sdev = cmd->device; starget = scsi_target(sdev); shost = sdev->host; -- cgit v1.2.3 From 439d77f70f18ebe2b28757b141e67a25575fe363 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 10 Aug 2010 18:01:20 -0700 Subject: scsi/sd.c: quiet all sparse noise In sd_store_cache_type the symbol 'len' is declared twice. Remove the second declaration to quiet the following sparse warning. warning: symbol 'len' shadows an earlier one In sd_probe the variable 'index' is declared as a u32. This variable is used in a call to ida_get_new which is expecting an int *. Make the variable an int to quiet the following sparse warning. warning: incorrect type in argument 2 (different signedness) There are 4 symbols in the file that are not exported and produce the following sparse warnings. warning: symbol 'sd_cdb_cache' was not declared. Should it be static? warning: symbol 'sd_cdb_pool' was not declared. Should it be static? warning: symbol 'sd_read_protection_type' was not declared. Should it be static? warning: symbol 'sd_read_app_tag_own' was not declared. Should it be static? Make them static to quiet the warnings. Signed-off-by: H Hartley Sweeten Cc: James E.J. Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/sd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8e2e893db9e7..2714becc2eaf 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -119,8 +119,8 @@ static DEFINE_IDA(sd_index_ida); * object after last put) */ static DEFINE_MUTEX(sd_ref_mutex); -struct kmem_cache *sd_cdb_cache; -mempool_t *sd_cdb_pool; +static struct kmem_cache *sd_cdb_cache; +static mempool_t *sd_cdb_pool; static const char *sd_cache_types[] = { "write through", "none", "write back", @@ -147,7 +147,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, return -EINVAL; for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { - const int len = strlen(sd_cache_types[i]); + len = strlen(sd_cache_types[i]); if (strncmp(sd_cache_types[i], buf, len) == 0 && buf[len] == '\n') { ct = i; @@ -1423,7 +1423,7 @@ sd_spinup_disk(struct scsi_disk *sdkp) /* * Determine whether disk supports Data Integrity Field. */ -void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) +static void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) { struct scsi_device *sdp = sdkp->device; u8 type; @@ -1969,7 +1969,7 @@ defaults: * The ATO bit indicates whether the DIF application tag is available * for use by the operating system. */ -void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) +static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) { int res, offset; struct scsi_device *sdp = sdkp->device; @@ -2315,7 +2315,7 @@ static int sd_probe(struct device *dev) struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp; struct gendisk *gd; - u32 index; + int index; int error; error = -ENODEV; -- cgit v1.2.3 From ae68230c2da8e5be712acd50dd9115918fa28839 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 10 Aug 2010 18:01:21 -0700 Subject: drivers/scsi/qla2xxx/qla_os.c: fix continuation line formats String constants that are continued on subsequent lines with \ will cause spurious whitespace in the resulting output. Signed-off-by: Joe Perches Cc: James E.J. Bottomley Cc: Giridhar Malavali Cc: Anirban Chakraborty Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/qla2xxx/qla_os.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ff2172da7c19..8c80b49ac1c4 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -115,8 +115,8 @@ int ql2xmaxqueues = 1; module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR); MODULE_PARM_DESC(ql2xmaxqueues, "Enables MQ settings " - "Default is 1 for single queue. Set it to number \ - of queues in MQ mode."); + "Default is 1 for single queue. Set it to number " + "of queues in MQ mode."); int ql2xmultique_tag; module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR); -- cgit v1.2.3 From 6d154db6b3fc3c4dc3fbf7c32df0ad9d7aeaa18c Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 10 Aug 2010 18:01:22 -0700 Subject: scsi: bfa: correct onstack wait_queue_head declaration Use DECLARE_WAIT_QUEUE_HEAD_ONSTACK to make lockdep happy Signed-off-by: Yong Zhang Cc: Jing Huang Cc: James E.J. Bottomley Cc: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/bfa/bfad_im.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 678120b70460..6ef87f6fcdbb 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -291,7 +291,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd) struct bfa_tskim_s *tskim; struct bfad_itnim_s *itnim; struct bfa_itnim_s *bfa_itnim; - DECLARE_WAIT_QUEUE_HEAD(wq); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); int rc = SUCCESS; unsigned long flags; enum bfi_tskim_status task_status; @@ -353,7 +353,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd) struct bfad_itnim_s *itnim; unsigned long flags; u32 i, rc, err_cnt = 0; - DECLARE_WAIT_QUEUE_HEAD(wq); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); enum bfi_tskim_status task_status; spin_lock_irqsave(&bfad->bfad_lock, flags); -- cgit v1.2.3 From 87da32356bcee42569666bef1479d0e599a556f8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 10 Aug 2010 18:01:22 -0700 Subject: drivers/scsi/ch.c: don't use vprintk as macro It's an exported symbol of kernel/printk.c Rename vprintk and dprintk macros to more common VPRINTK and DPRINTK Add do { } while(0) around macros Add level to VPRINTK so KERN_CONT can be used a couple of times. Signed-off-by: Joe Perches Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/ch.c | 87 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 43 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 769b35f8b39f..d6532187f616 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -84,10 +84,16 @@ static const char * vendor_labels[CH_TYPES-4] = { }; // module_param_string_array(vendor_labels, NULL, 0444); -#define dprintk(fmt, arg...) if (debug) \ - printk(KERN_DEBUG "%s: " fmt, ch->name , ## arg) -#define vprintk(fmt, arg...) if (verbose) \ - printk(KERN_INFO "%s: " fmt, ch->name , ## arg) +#define DPRINTK(fmt, arg...) \ +do { \ + if (debug) \ + printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg); \ +} while (0) +#define VPRINTK(level, fmt, arg...) \ +do { \ + if (verbose) \ + printk(level "%s: " fmt, ch->name, ##arg); \ +} while (0) /* ------------------------------------------------------------------- */ @@ -186,7 +192,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, retry: errno = 0; if (debug) { - dprintk("command: "); + DPRINTK("command: "); __scsi_print_command(cmd); } @@ -194,7 +200,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, buflength, &sshdr, timeout * HZ, MAX_RETRIES, NULL); - dprintk("result: 0x%x\n",result); + DPRINTK("result: 0x%x\n",result); if (driver_byte(result) & DRIVER_SENSE) { if (debug) scsi_print_sense_hdr(ch->name, &sshdr); @@ -250,7 +256,7 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data) cmd[9] = 255; if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) { if (((buffer[16] << 8) | buffer[17]) != elem) { - dprintk("asked for element 0x%02x, got 0x%02x\n", + DPRINTK("asked for element 0x%02x, got 0x%02x\n", elem,(buffer[16] << 8) | buffer[17]); kfree(buffer); return -EIO; @@ -259,10 +265,10 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data) } else { if (ch->voltags) { ch->voltags = 0; - vprintk("device has no volume tag support\n"); + VPRINTK(KERN_INFO, "device has no volume tag support\n"); goto retry; } - dprintk("READ ELEMENT STATUS for element 0x%x failed\n",elem); + DPRINTK("READ ELEMENT STATUS for element 0x%x failed\n",elem); } kfree(buffer); return result; @@ -274,12 +280,12 @@ ch_init_elem(scsi_changer *ch) int err; u_char cmd[6]; - vprintk("INITIALIZE ELEMENT STATUS, may take some time ...\n"); + VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n"); memset(cmd,0,sizeof(cmd)); cmd[0] = INITIALIZE_ELEMENT_STATUS; cmd[1] = ch->device->lun << 5; err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE); - vprintk("... finished\n"); + VPRINTK(KERN_INFO, "... finished\n"); return err; } @@ -322,20 +328,20 @@ ch_readconfig(scsi_changer *ch) (buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19]; ch->counts[CHET_DT] = (buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21]; - vprintk("type #1 (mt): 0x%x+%d [medium transport]\n", + VPRINTK(KERN_INFO, "type #1 (mt): 0x%x+%d [medium transport]\n", ch->firsts[CHET_MT], ch->counts[CHET_MT]); - vprintk("type #2 (st): 0x%x+%d [storage]\n", + VPRINTK(KERN_INFO, "type #2 (st): 0x%x+%d [storage]\n", ch->firsts[CHET_ST], ch->counts[CHET_ST]); - vprintk("type #3 (ie): 0x%x+%d [import/export]\n", + VPRINTK(KERN_INFO, "type #3 (ie): 0x%x+%d [import/export]\n", ch->firsts[CHET_IE], ch->counts[CHET_IE]); - vprintk("type #4 (dt): 0x%x+%d [data transfer]\n", + VPRINTK(KERN_INFO, "type #4 (dt): 0x%x+%d [data transfer]\n", ch->firsts[CHET_DT], ch->counts[CHET_DT]); } else { - vprintk("reading element address assigment page failed!\n"); + VPRINTK(KERN_INFO, "reading element address assigment page failed!\n"); } /* vendor specific element types */ @@ -346,7 +352,7 @@ ch_readconfig(scsi_changer *ch) continue; ch->firsts[CHET_V1+i] = vendor_firsts[i]; ch->counts[CHET_V1+i] = vendor_counts[i]; - vprintk("type #%d (v%d): 0x%x+%d [%s, vendor specific]\n", + VPRINTK(KERN_INFO, "type #%d (v%d): 0x%x+%d [%s, vendor specific]\n", i+5,i+1,vendor_firsts[i],vendor_counts[i], vendor_labels[i]); } @@ -366,21 +372,19 @@ ch_readconfig(scsi_changer *ch) if (elem < CH_DT_MAX && -1 != dt_id[elem]) { id = dt_id[elem]; lun = dt_lun[elem]; - vprintk("dt 0x%x: [insmod option] ", + VPRINTK(KERN_INFO, "dt 0x%x: [insmod option] ", elem+ch->firsts[CHET_DT]); } else if (0 != ch_read_element_status (ch,elem+ch->firsts[CHET_DT],data)) { - vprintk("dt 0x%x: READ ELEMENT STATUS failed\n", + VPRINTK(KERN_INFO, "dt 0x%x: READ ELEMENT STATUS failed\n", elem+ch->firsts[CHET_DT]); } else { - vprintk("dt 0x%x: ",elem+ch->firsts[CHET_DT]); + VPRINTK(KERN_INFO, "dt 0x%x: ",elem+ch->firsts[CHET_DT]); if (data[6] & 0x80) { - if (verbose) - printk("not this SCSI bus\n"); + VPRINTK(KERN_CONT, "not this SCSI bus\n"); ch->dt[elem] = NULL; } else if (0 == (data[6] & 0x30)) { - if (verbose) - printk("ID/LUN unknown\n"); + VPRINTK(KERN_CONT, "ID/LUN unknown\n"); ch->dt[elem] = NULL; } else { id = ch->device->id; @@ -390,22 +394,19 @@ ch_readconfig(scsi_changer *ch) } } if (-1 != id) { - if (verbose) - printk("ID %i, LUN %i, ",id,lun); + VPRINTK(KERN_CONT, "ID %i, LUN %i, ",id,lun); ch->dt[elem] = scsi_device_lookup(ch->device->host, ch->device->channel, id,lun); if (!ch->dt[elem]) { /* should not happen */ - if (verbose) - printk("Huh? device not found!\n"); + VPRINTK(KERN_CONT, "Huh? device not found!\n"); } else { - if (verbose) - printk("name: %8.8s %16.16s %4.4s\n", - ch->dt[elem]->vendor, - ch->dt[elem]->model, - ch->dt[elem]->rev); + VPRINTK(KERN_CONT, "name: %8.8s %16.16s %4.4s\n", + ch->dt[elem]->vendor, + ch->dt[elem]->model, + ch->dt[elem]->rev); } } } @@ -422,7 +423,7 @@ ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate) { u_char cmd[10]; - dprintk("position: 0x%x\n",elem); + DPRINTK("position: 0x%x\n",elem); if (0 == trans) trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); @@ -441,7 +442,7 @@ ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate) { u_char cmd[12]; - dprintk("move: 0x%x => 0x%x\n",src,dest); + DPRINTK("move: 0x%x => 0x%x\n",src,dest); if (0 == trans) trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); @@ -463,7 +464,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src, { u_char cmd[12]; - dprintk("exchange: 0x%x => 0x%x => 0x%x\n", + DPRINTK("exchange: 0x%x => 0x%x => 0x%x\n", src,dest1,dest2); if (0 == trans) trans = ch->firsts[CHET_MT]; @@ -511,7 +512,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem, if (!buffer) return -ENOMEM; - dprintk("%s %s voltag: 0x%x => \"%s\"\n", + DPRINTK("%s %s voltag: 0x%x => \"%s\"\n", clear ? "clear" : "set", alternate ? "alternate" : "primary", elem, tag); @@ -550,7 +551,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest) } put_user(data[2], dest+i); if (data[2] & CESTATUS_EXCEPT) - vprintk("element 0x%x: asc=0x%x, ascq=0x%x\n", + VPRINTK(KERN_INFO, "element 0x%x: asc=0x%x, ascq=0x%x\n", ch->firsts[type]+i, (int)data[4],(int)data[5]); retval = ch_read_element_status @@ -660,7 +661,7 @@ static long ch_ioctl(struct file *file, return -EFAULT; if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) { - dprintk("CHIOPOSITION: invalid parameter\n"); + DPRINTK("CHIOPOSITION: invalid parameter\n"); return -EBADSLT; } mutex_lock(&ch->lock); @@ -680,7 +681,7 @@ static long ch_ioctl(struct file *file, if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) || 0 != ch_checkrange(ch, mv.cm_totype, mv.cm_tounit )) { - dprintk("CHIOMOVE: invalid parameter\n"); + DPRINTK("CHIOMOVE: invalid parameter\n"); return -EBADSLT; } @@ -703,7 +704,7 @@ static long ch_ioctl(struct file *file, if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) || 0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) || 0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) { - dprintk("CHIOEXCHANGE: invalid parameter\n"); + DPRINTK("CHIOEXCHANGE: invalid parameter\n"); return -EBADSLT; } @@ -796,7 +797,7 @@ static long ch_ioctl(struct file *file, } } else if (ch->voltags) { ch->voltags = 0; - vprintk("device has no volume tag support\n"); + VPRINTK(KERN_INFO, "device has no volume tag support\n"); goto voltag_retry; } kfree(buffer); @@ -824,7 +825,7 @@ static long ch_ioctl(struct file *file, return -EFAULT; if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) { - dprintk("CHIOSVOLTAG: invalid parameter\n"); + DPRINTK("CHIOSVOLTAG: invalid parameter\n"); return -EBADSLT; } elem = ch->firsts[csv.csv_type] + csv.csv_unit; -- cgit v1.2.3 From 6de61f9d2491970a204da9111e2d25e0d9f284d6 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 10 Aug 2010 18:01:23 -0700 Subject: bfa: wrong fcport H2I message tested in bfa_fcport_isr() It appears that the wrong fcport H2I message was tested Signed-off-by: Roel Kluin Acked-by: Jing Huang Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/bfa/bfa_fcport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index f0933d8d1eda..76867b5577fa 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -1310,7 +1310,7 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) break; case BFI_FCPORT_I2H_DISABLE_RSP: - if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) + if (fcport->msgtag == i2hmsg.pdisable_rsp->msgtag) bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP); break; -- cgit v1.2.3 From b2045240058381088e6e367e5f54b2a8bed931e1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 10 Aug 2010 18:01:24 -0700 Subject: scsi: fix pmcraid build errors pmcraid should depend on NET since it uses netlink interfaces. This fixes multiple build errors when CONFIG_NET is not enabled: ERROR: "genl_register_family" [drivers/scsi/pmcraid.ko] undefined! ERROR: "genl_unregister_family" [drivers/scsi/pmcraid.ko] undefined! ERROR: "nla_put" [drivers/scsi/pmcraid.ko] undefined! ERROR: "init_net" [drivers/scsi/pmcraid.ko] undefined! ERROR: "__alloc_skb" [drivers/scsi/pmcraid.ko] undefined! ERROR: "netlink_broadcast" [drivers/scsi/pmcraid.ko] undefined! ERROR: "kfree_skb" [drivers/scsi/pmcraid.ko] undefined! ERROR: "skb_put" [drivers/scsi/pmcraid.ko] undefined! Signed-off-by: Randy Dunlap Cc: Anil Ravindranath Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 158284f05732..6466231f338b 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1853,7 +1853,7 @@ config ZFCP_DIF config SCSI_PMCRAID tristate "PMC SIERRA Linux MaxRAID adapter support" - depends on PCI && SCSI + depends on PCI && SCSI && NET ---help--- This driver supports the PMC SIERRA MaxRAID adapters. -- cgit v1.2.3 From 5c90ad905b401c6675dcb6c9fed7c09c9240205c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 10 Aug 2010 18:01:25 -0700 Subject: scsi: fix bnx2i build errors bnx2i should depend on NET since it selects SCSI_ISCSI_ATTRS, which depends on NET. Also move the dependencies together. The "depends" change fixes multiple build errors when CONFIG_NET is not enabled: ERROR: "skb_trim" [drivers/scsi/scsi_transport_iscsi.ko] undefined! ERROR: "netlink_kernel_create" [drivers/scsi/scsi_transport_iscsi.ko] undefined! ERROR: "netlink_kernel_release" [drivers/scsi/scsi_transport_iscsi.ko] undefined! ERROR: "skb_pull" [drivers/scsi/scsi_transport_iscsi.ko] undefined! ERROR: "init_net" [drivers/scsi/scsi_transport_iscsi.ko] undefined! ERROR: "__alloc_skb" [drivers/scsi/scsi_transport_iscsi.ko] undefined! ERROR: "netlink_broadcast" [drivers/scsi/scsi_transport_iscsi.ko] undefined! ERROR: "kfree_skb" [drivers/scsi/scsi_transport_iscsi.ko] undefined! ERROR: "skb_put" [drivers/scsi/scsi_transport_iscsi.ko] undefined! Signed-off-by: Randy Dunlap Cc: Anil Veerabhadrappa Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/bnx2i/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig index 1e9f7141102b..45a6154ce972 100644 --- a/drivers/scsi/bnx2i/Kconfig +++ b/drivers/scsi/bnx2i/Kconfig @@ -1,10 +1,11 @@ config SCSI_BNX2_ISCSI tristate "Broadcom NetXtreme II iSCSI support" + depends on NET + depends on PCI select SCSI_ISCSI_ATTRS select NETDEVICES select NETDEV_1000 select CNIC - depends on PCI ---help--- This driver supports iSCSI offload for the Broadcom NetXtreme II devices. -- cgit v1.2.3 From a737b88df8d0b4476ae53daaa6db137df0541203 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 10 Aug 2010 18:01:26 -0700 Subject: scsi: remove private BIT macros A couple of scsi drivers define a BIT() macro, duplicating the one in bitops.h. Cc: Jing Huang Cc: Robert Love Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/bfa/include/protocol/fcp.h | 4 +--- drivers/scsi/fnic/fnic.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/include/protocol/fcp.h b/drivers/scsi/bfa/include/protocol/fcp.h index 9ade68ad2853..74ea63ce84b7 100644 --- a/drivers/scsi/bfa/include/protocol/fcp.h +++ b/drivers/scsi/bfa/include/protocol/fcp.h @@ -18,6 +18,7 @@ #ifndef __FCPPROTO_H__ #define __FCPPROTO_H__ +#include #include #pragma pack(1) @@ -102,9 +103,6 @@ enum { /* * Task management flags field - only one bit shall be set */ -#ifndef BIT -#define BIT(_x) (1 << (_x)) -#endif enum fcp_tm_cmnd{ FCP_TM_ABORT_TASK_SET = BIT(1), FCP_TM_CLEAR_TASK_SET = BIT(2), diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 19338e0ba2c5..cbb20b13b228 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include "fnic_io.h" @@ -49,7 +50,6 @@ /* * Tag bits used for special requests. */ -#define BIT(nr) (1UL << (nr)) #define FNIC_TAG_ABORT BIT(30) /* tag bit indicating abort */ #define FNIC_TAG_DEV_RST BIT(29) /* indicates device reset */ #define FNIC_TAG_MASK (BIT(24) - 1) /* mask for lookup */ -- cgit v1.2.3 From 3094141c6532a4f748425c21c091001f218da8ae Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 10 Aug 2010 18:01:27 -0700 Subject: drivers/scsi: use memdup_user Use memdup_user when user data is immediately copied into the allocated region. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression from,to,size,flag; position p; identifier l1,l2; @@ - to = \(kmalloc@p\|kzalloc@p\)(size,flag); + to = memdup_user(from,size); if ( - to==NULL + IS_ERR(to) || ...) { <+... when != goto l1; - -ENOMEM + PTR_ERR(to) ...+> } - if (copy_from_user(to, from, size) != 0) { - <+... when != goto l2; - -EFAULT - ...+> - } // Signed-off-by: Julia Lawall Cc: Doug Gilbert Cc: Boaz Harrosh Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/sg.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2968c6b83ddb..78d616315d8e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1686,14 +1686,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) int len, size = sizeof(struct sg_iovec) * iov_count; struct iovec *iov; - iov = kmalloc(size, GFP_ATOMIC); - if (!iov) - return -ENOMEM; - - if (copy_from_user(iov, hp->dxferp, size)) { - kfree(iov); - return -EFAULT; - } + iov = memdup_user(hp->dxferp, size); + if (IS_ERR(iov)) + return PTR_ERR(iov); len = iov_length(iov, iov_count); if (hp->dxfer_len < len) { -- cgit v1.2.3 From ecc3099002c1cc87e9e4b3dc5fdf7821828f6733 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 10 Aug 2010 18:01:27 -0700 Subject: drivers: scsi: use newly introduced hex_to_bin() method Signed-off-by: Andy Shevchenko Cc: Adaptec OEM Raid Solutions Cc: "James E.J. Bottomley" Cc: James Smart Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/aacraid/rx.c | 5 ++--- drivers/scsi/lpfc/lpfc_attr.c | 23 +++++++++++------------ drivers/scsi/scsi_transport_fc.c | 12 ++++++------ 3 files changed, 19 insertions(+), 21 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 04057ab72a8b..84d77fd86e5b 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -352,9 +352,8 @@ static int aac_rx_check_health(struct aac_dev *dev) pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), post, paddr); if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { - ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); - ret <<= 4; - ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); + ret = (hex_to_bin(buffer[2]) << 4) + + hex_to_bin(buffer[3]); } pci_free_consistent(dev->pdev, 512, buffer, baddr); return ret; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 162704cf6a96..ad05b266e950 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -1795,12 +1796,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, /* Validate and store the new name */ for (i=0, j=0; i < 16; i++) { - if ((*buf >= 'a') && (*buf <= 'f')) - j = ((j << 4) | ((*buf++ -'a') + 10)); - else if ((*buf >= 'A') && (*buf <= 'F')) - j = ((j << 4) | ((*buf++ -'A') + 10)); - else if ((*buf >= '0') && (*buf <= '9')) - j = ((j << 4) | (*buf++ -'0')); + int value; + + value = hex_to_bin(*buf++); + if (value >= 0) + j = (j << 4) | value; else return -EINVAL; if (i % 2) { @@ -1888,12 +1888,11 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr, /* Validate and store the new name */ for (i=0, j=0; i < 16; i++) { - if ((*buf >= 'a') && (*buf <= 'f')) - j = ((j << 4) | ((*buf++ -'a') + 10)); - else if ((*buf >= 'A') && (*buf <= 'F')) - j = ((j << 4) | ((*buf++ -'A') + 10)); - else if ((*buf >= '0') && (*buf <= '9')) - j = ((j << 4) | (*buf++ -'0')); + int value; + + value = hex_to_bin(*buf++); + if (value >= 0) + j = (j << 4) | value; else return -EINVAL; if (i % 2) { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index edb6b362a8fa..d7e470a06180 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1730,12 +1731,11 @@ fc_parse_wwn(const char *ns, u64 *nm) /* Validate and store the new name */ for (i=0, j=0; i < 16; i++) { - if ((*ns >= 'a') && (*ns <= 'f')) - j = ((j << 4) | ((*ns++ -'a') + 10)); - else if ((*ns >= 'A') && (*ns <= 'F')) - j = ((j << 4) | ((*ns++ -'A') + 10)); - else if ((*ns >= '0') && (*ns <= '9')) - j = ((j << 4) | (*ns++ -'0')); + int value; + + value = hex_to_bin(*ns++); + if (value >= 0) + j = (j << 4) | value; else return -EINVAL; if (i % 2) { -- cgit v1.2.3 From d80e0d96a328cc864a1cb359f545a6ed0c61812d Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 10 Aug 2010 18:03:24 -0700 Subject: scsi: 53c700: remove dma_is_consistent usage This driver is the only user of dma_is_consistent(). We plan to remove this API. The driver uses the API in the following way: BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); The above code tries to see if L1_CACHE_BYTES is greater than dma_get_cache_alignment() on sysmtes that can not allocate coherent memory (some old systems can't). James Bottomley exmplained that this is necesary because the driver packs the set of mailboxes into a single coherent area and separates the different usages by a L1 cache stride. So it's fatal if the dma He also pointed out that we can kill this checking because we don't hit this BUG_ON on all architectures that actually use the driver. (akpm: stolen from the scsi tree because dma-mapping-remove-dma_is_consistent-api.patch needs it) Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/53c700.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 80dc3ac12cde..89fc1c8af86b 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -309,9 +309,6 @@ NCR_700_detect(struct scsi_host_template *tpnt, hostdata->msgin = memory + MSGIN_OFFSET; hostdata->msgout = memory + MSGOUT_OFFSET; hostdata->status = memory + STATUS_OFFSET; - /* all of these offsets are L1_CACHE_BYTES separated. It is fatal - * if this isn't sufficient separation to avoid dma flushing issues */ - BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); hostdata->dev = dev; -- cgit v1.2.3