aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 12:47:02 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 12:47:02 -0800
commitda40d036fd716f0efb2917076220814b1e927ae1 (patch)
tree567893573a48e2954d82421e77606034d3b32f84 /drivers/scsi
parentaa58abc20fa85328a9f048e2626c0893691ff284 (diff)
parentc32e061fa19893ce4acf95d97d5613a161f0f1b7 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (147 commits) [SCSI] arcmsr: fix write to device check [SCSI] lpfc: lower stack use in lpfc_fc_frame_check [SCSI] eliminate an unnecessary local variable from scsi_remove_target() [SCSI] libiscsi: use bh locking instead of irq with session lock [SCSI] libiscsi: do not take host lock in queuecommand [SCSI] be2iscsi: fix null ptr when accessing task hdr [SCSI] be2iscsi: fix gfp use in alloc_pdu [SCSI] libiscsi: add more informative failure message during iscsi scsi eh [SCSI] gdth: Add missing call to gdth_ioctl_free [SCSI] bfa: remove unused defintions and misc cleanups [SCSI] bfa: remove inactive functions [SCSI] bfa: replace bfa_assert with WARN_ON [SCSI] qla2xxx: Use sg_next to fetch next sg element while walking sg list. [SCSI] qla2xxx: Fix to avoid recursive lock failure during BSG timeout. [SCSI] qla2xxx: Remove code to not reset ISP82xx on failure. [SCSI] qla2xxx: Display mailbox register 4 during 8012 AEN for ISP82XX parts. [SCSI] qla2xxx: Don't perform a BIG_HAMMER if Get-ID (0x20) mailbox command fails on CNAs. [SCSI] qla2xxx: Remove redundant module parameter permission bits [SCSI] qla2xxx: Add sysfs node for displaying board temperature. [SCSI] qla2xxx: Code cleanup to remove unwanted comments and code. ...
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c3
-rw-r--r--drivers/scsi/be2iscsi/be_main.c5
-rw-r--r--drivers/scsi/bfa/Makefile4
-rw-r--r--drivers/scsi/bfa/bfa.h36
-rw-r--r--drivers/scsi/bfa/bfa_cb_ioim.h169
-rw-r--r--drivers/scsi/bfa/bfa_core.c373
-rw-r--r--drivers/scsi/bfa/bfa_cs.h96
-rw-r--r--drivers/scsi/bfa/bfa_defs.h6
-rw-r--r--drivers/scsi/bfa/bfa_defs_svc.h8
-rw-r--r--drivers/scsi/bfa/bfa_drv.c107
-rw-r--r--drivers/scsi/bfa/bfa_fc.h633
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c109
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.h30
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c698
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.h188
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c206
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h124
-rw-r--r--drivers/scsi/bfa/bfa_fcs_fcpim.c30
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c390
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c230
-rw-r--r--drivers/scsi/bfa/bfa_hw_cb.c3
-rw-r--r--drivers/scsi/bfa/bfa_hw_ct.c5
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c749
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h44
-rw-r--r--drivers/scsi/bfa/bfa_ioc_cb.c97
-rw-r--r--drivers/scsi/bfa/bfa_ioc_ct.c120
-rw-r--r--drivers/scsi/bfa/bfa_modules.h3
-rw-r--r--drivers/scsi/bfa/bfa_os_inc.h143
-rw-r--r--drivers/scsi/bfa/bfa_plog.h4
-rw-r--r--drivers/scsi/bfa/bfa_port.c37
-rw-r--r--drivers/scsi/bfa/bfa_port.h1
-rw-r--r--drivers/scsi/bfa/bfa_svc.c746
-rw-r--r--drivers/scsi/bfa/bfa_svc.h63
-rw-r--r--drivers/scsi/bfa/bfad.c38
-rw-r--r--drivers/scsi/bfa/bfad_attr.c18
-rw-r--r--drivers/scsi/bfa/bfad_debugfs.c46
-rw-r--r--drivers/scsi/bfa/bfad_drv.h45
-rw-r--r--drivers/scsi/bfa/bfad_im.c59
-rw-r--r--drivers/scsi/bfa/bfad_im.h16
-rw-r--r--drivers/scsi/bfa/bfi.h8
-rw-r--r--drivers/scsi/bfa/bfi_cbreg.h1
-rw-r--r--drivers/scsi/bfa/bfi_ctreg.h41
-rw-r--r--drivers/scsi/bfa/bfi_ms.h66
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_constants.h3
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_hsi.h3
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h15
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c96
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c108
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c148
-rw-r--r--drivers/scsi/bnx2i/bnx2i_sysfs.c3
-rw-r--r--drivers/scsi/device_handler/scsi_dh.c11
-rw-r--r--drivers/scsi/fcoe/fcoe.c4
-rw-r--r--drivers/scsi/fcoe/libfcoe.c300
-rw-r--r--drivers/scsi/gdth.c4
-rw-r--r--drivers/scsi/gdth_proc.c16
-rw-r--r--drivers/scsi/hpsa.c11
-rw-r--r--drivers/scsi/hpsa.h1
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c28
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h2
-rw-r--r--drivers/scsi/ipr.c54
-rw-r--r--drivers/scsi/ipr.h2
-rw-r--r--drivers/scsi/libfc/fc_exch.c48
-rw-r--r--drivers/scsi/libfc/fc_fcp.c147
-rw-r--r--drivers/scsi/libfc/fc_libfc.h16
-rw-r--r--drivers/scsi/libfc/fc_lport.c16
-rw-r--r--drivers/scsi/libfc/fc_rport.c3
-rw-r--r--drivers/scsi/libiscsi.c64
-rw-r--r--drivers/scsi/libsas/sas_port.c18
-rw-r--r--drivers/scsi/lpfc/lpfc.h26
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c104
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c65
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h19
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c48
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h19
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c327
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c239
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h222
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h292
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c1062
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c76
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c16
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c82
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c663
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h58
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c10
-rw-r--r--drivers/scsi/megaraid/Makefile2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h78
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c (renamed from drivers/scsi/megaraid/megaraid_sas.c)777
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c516
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c2248
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h695
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h9
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h20
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_history.txt3
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_init.h9
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_ioc.h8
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_raid.h6
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_sas.h9
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_tool.h49
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c199
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h27
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c343
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c185
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c27
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h8
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c89
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c67
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c217
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c63
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c11
-rw-r--r--drivers/scsi/qla4xxx/ql4_dbg.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_dbg.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h5
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_inline.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c9
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c22
-rw-r--r--drivers/scsi/qla4xxx/ql4_nvram.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_nvram.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c62
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.h6
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c30
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h4
-rw-r--r--drivers/scsi/scsi_debug.c1
-rw-r--r--drivers/scsi/scsi_error.c61
-rw-r--r--drivers/scsi/scsi_lib.c5
-rw-r--r--drivers/scsi/scsi_sysfs.c6
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c1
-rw-r--r--drivers/scsi/sd.c99
-rw-r--r--drivers/scsi/st.c7
142 files changed, 10326 insertions, 5957 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 17e3df4f016..1cadcd6b7da 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -1171,9 +1171,8 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb,
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 (pcmd->sc_data_direction == DMA_TO_DEVICE)
arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
- }
ccb->arc_cdb_size = arccdbsize;
return SUCCESS;
}
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 75a85aa9e88..79cefbe3136 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -3785,7 +3785,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
dma_addr_t paddr;
io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool,
- GFP_KERNEL, &paddr);
+ GFP_ATOMIC, &paddr);
if (!io_task->cmd_bhs)
return -ENOMEM;
io_task->bhs_pa.u.a64.address = paddr;
@@ -3914,7 +3914,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
io_task->psgl_handle = NULL;
}
} else {
- if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN)
+ if (task->hdr &&
+ ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN))
return;
if (io_task->psgl_handle) {
spin_lock(&phba->mgmt_sgl_lock);
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile
index d2eefd3e3bd..4ce6f494232 100644
--- a/drivers/scsi/bfa/Makefile
+++ b/drivers/scsi/bfa/Makefile
@@ -3,6 +3,4 @@ obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
-bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_drv.o bfa_svc.o
-
-ccflags-y := -DBFA_PERF_BUILD
+bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
index ff2bd07161f..7be6b5a8114 100644
--- a/drivers/scsi/bfa/bfa.h
+++ b/drivers/scsi/bfa/bfa.h
@@ -17,7 +17,7 @@
#ifndef __BFA_H__
#define __BFA_H__
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
#include "bfa_cs.h"
#include "bfa_plog.h"
#include "bfa_defs_svc.h"
@@ -33,7 +33,6 @@ typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
* Interrupt message handlers
*/
void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
-void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
/*
* Request and response queue related defines
@@ -121,8 +120,8 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
\
struct list_head *waitq = bfa_reqq(__bfa, __reqq); \
\
- bfa_assert(((__reqq) < BFI_IOC_MAX_CQS)); \
- bfa_assert((__wqe)->qresume && (__wqe)->cbarg); \
+ WARN_ON(((__reqq) >= BFI_IOC_MAX_CQS)); \
+ WARN_ON(!((__wqe)->qresume && (__wqe)->cbarg)); \
\
list_add_tail(&(__wqe)->qe, waitq); \
} while (0)
@@ -297,7 +296,6 @@ void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
struct bfa_iocfc_cfg_s *cfg,
struct bfa_meminfo_s *meminfo,
struct bfa_pcidev_s *pcidev);
-void bfa_iocfc_detach(struct bfa_s *bfa);
void bfa_iocfc_init(struct bfa_s *bfa);
void bfa_iocfc_start(struct bfa_s *bfa);
void bfa_iocfc_stop(struct bfa_s *bfa);
@@ -333,12 +331,9 @@ 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_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi);
void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa);
wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa);
-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);
@@ -386,19 +381,11 @@ void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
struct bfa_meminfo_s *meminfo,
struct bfa_pcidev_s *pcidev);
-void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
-void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
void bfa_detach(struct bfa_s *bfa);
-void bfa_init(struct bfa_s *bfa);
-void bfa_start(struct bfa_s *bfa);
-void bfa_stop(struct bfa_s *bfa);
-void bfa_attach_fcs(struct bfa_s *bfa);
void bfa_cb_init(void *bfad, bfa_status_t status);
void bfa_cb_updateq(void *bfad, bfa_status_t status);
bfa_boolean_t bfa_intx(struct bfa_s *bfa);
-void bfa_intx_disable(struct bfa_s *bfa);
-void bfa_intx_enable(struct bfa_s *bfa);
void bfa_isr_enable(struct bfa_s *bfa);
void bfa_isr_disable(struct bfa_s *bfa);
@@ -408,31 +395,14 @@ void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
-void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
-void bfa_adapter_get_attr(struct bfa_s *bfa,
- struct bfa_adapter_attr_s *ad_attr);
-u64 bfa_adapter_get_id(struct bfa_s *bfa);
bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
struct bfa_iocfc_intr_attr_s *attr);
void bfa_iocfc_enable(struct bfa_s *bfa);
void bfa_iocfc_disable(struct bfa_s *bfa);
-void bfa_chip_reset(struct bfa_s *bfa);
-void bfa_timer_tick(struct bfa_s *bfa);
#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \
bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
-/*
- * BFA debug API functions
- */
-bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
-bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
-bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf,
- u32 *offset, int *buflen);
-void bfa_debug_fwsave_clear(struct bfa_s *bfa);
-bfa_status_t bfa_fw_stats_get(struct bfa_s *bfa, void *data);
-bfa_status_t bfa_fw_stats_clear(struct bfa_s *bfa);
-
#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/bfa_cb_ioim.h b/drivers/scsi/bfa/bfa_cb_ioim.h
deleted file mode 100644
index 6f021015f1f..00000000000
--- a/drivers/scsi/bfa/bfa_cb_ioim.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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 __BFA_HCB_IOIM_H__
-#define __BFA_HCB_IOIM_H__
-
-#include "bfa_os_inc.h"
-/*
- * task attribute values in FCP-2 FCP_CMND IU
- */
-#define SIMPLE_Q 0
-#define HEAD_OF_Q 1
-#define ORDERED_Q 2
-#define ACA_Q 4
-#define UNTAGGED 5
-
-static inline lun_t
-bfad_int_to_lun(u32 luno)
-{
- union {
- u16 scsi_lun[4];
- lun_t bfa_lun;
- } lun;
-
- lun.bfa_lun = 0;
- lun.scsi_lun[0] = cpu_to_be16(luno);
-
- return lun.bfa_lun;
-}
-
-/*
- * Get LUN for the I/O request
- */
-#define bfa_cb_ioim_get_lun(__dio) \
- bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun)
-
-/*
- * Get CDB for the I/O request
- */
-static inline u8 *
-bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio)
-{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-
- return (u8 *) cmnd->cmnd;
-}
-
-/*
- * Get I/O direction (read/write) for the I/O request
- */
-static inline enum fcp_iodir
-bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio)
-{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
- enum dma_data_direction dmadir;
-
- dmadir = cmnd->sc_data_direction;
- if (dmadir == DMA_TO_DEVICE)
- return FCP_IODIR_WRITE;
- else if (dmadir == DMA_FROM_DEVICE)
- return FCP_IODIR_READ;
- else
- return FCP_IODIR_NONE;
-}
-
-/*
- * Get IO size in bytes for the I/O request
- */
-static inline u32
-bfa_cb_ioim_get_size(struct bfad_ioim_s *dio)
-{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-
- return scsi_bufflen(cmnd);
-}
-
-/*
- * Get timeout for the I/O request
- */
-static inline u8
-bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio)
-{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
- /*
- * TBD: need a timeout for scsi passthru
- */
- if (cmnd->device->host == NULL)
- return 4;
-
- return 0;
-}
-
-/*
- * Get Command Reference Number for the I/O request. 0 if none.
- */
-static inline u8
-bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio)
-{
- return 0;
-}
-
-/*
- * Get SAM-3 priority for the I/O request. 0 is default.
- */
-static inline u8
-bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio)
-{
- return 0;
-}
-
-/*
- * Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0).
- */
-static inline u8
-bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
-{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
- u8 task_attr = UNTAGGED;
-
- if (cmnd->device->tagged_supported) {
- switch (cmnd->tag) {
- case HEAD_OF_QUEUE_TAG:
- task_attr = HEAD_OF_Q;
- break;
- case ORDERED_QUEUE_TAG:
- task_attr = ORDERED_Q;
- break;
- default:
- task_attr = SIMPLE_Q;
- break;
- }
- }
-
- return task_attr;
-}
-
-/*
- * Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16).
- */
-static inline u8
-bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
-{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)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_H__ */
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 2345f48dc57..1cd5c8b0618 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -15,13 +15,100 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_modules.h"
#include "bfi_ctreg.h"
-#include "bfad_drv.h"
BFA_TRC_FILE(HAL, CORE);
/*
+ * BFA module list terminated by NULL
+ */
+static struct bfa_module_s *hal_mods[] = {
+ &hal_mod_sgpg,
+ &hal_mod_fcport,
+ &hal_mod_fcxp,
+ &hal_mod_lps,
+ &hal_mod_uf,
+ &hal_mod_rport,
+ &hal_mod_fcpim,
+ NULL
+};
+
+/*
+ * Message handlers for various modules.
+ */
+static bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = {
+ bfa_isr_unhandled, /* NONE */
+ bfa_isr_unhandled, /* BFI_MC_IOC */
+ bfa_isr_unhandled, /* BFI_MC_DIAG */
+ bfa_isr_unhandled, /* BFI_MC_FLASH */
+ bfa_isr_unhandled, /* BFI_MC_CEE */
+ bfa_fcport_isr, /* BFI_MC_FCPORT */
+ bfa_isr_unhandled, /* BFI_MC_IOCFC */
+ bfa_isr_unhandled, /* BFI_MC_LL */
+ bfa_uf_isr, /* BFI_MC_UF */
+ bfa_fcxp_isr, /* BFI_MC_FCXP */
+ bfa_lps_isr, /* BFI_MC_LPS */
+ bfa_rport_isr, /* BFI_MC_RPORT */
+ bfa_itnim_isr, /* BFI_MC_ITNIM */
+ bfa_isr_unhandled, /* BFI_MC_IOIM_READ */
+ bfa_isr_unhandled, /* BFI_MC_IOIM_WRITE */
+ bfa_isr_unhandled, /* BFI_MC_IOIM_IO */
+ bfa_ioim_isr, /* BFI_MC_IOIM */
+ bfa_ioim_good_comp_isr, /* BFI_MC_IOIM_IOCOM */
+ bfa_tskim_isr, /* BFI_MC_TSKIM */
+ bfa_isr_unhandled, /* BFI_MC_SBOOT */
+ bfa_isr_unhandled, /* BFI_MC_IPFC */
+ bfa_isr_unhandled, /* BFI_MC_PORT */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+ bfa_isr_unhandled, /* --------- */
+};
+/*
+ * Message handlers for mailbox command classes
+ */
+static bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = {
+ NULL,
+ NULL, /* BFI_MC_IOC */
+ NULL, /* BFI_MC_DIAG */
+ NULL, /* BFI_MC_FLASH */
+ NULL, /* BFI_MC_CEE */
+ NULL, /* BFI_MC_PORT */
+ bfa_iocfc_isr, /* BFI_MC_IOCFC */
+ NULL,
+};
+
+
+
+static void
+bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+{
+ struct bfa_port_s *port = &bfa->modules.port;
+ u32 dm_len;
+ u8 *dm_kva;
+ u64 dm_pa;
+
+ dm_len = bfa_port_meminfo();
+ dm_kva = bfa_meminfo_dma_virt(mi);
+ dm_pa = bfa_meminfo_dma_phys(mi);
+
+ memset(port, 0, sizeof(struct bfa_port_s));
+ bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
+ bfa_port_mem_claim(port, dm_kva, dm_pa);
+
+ bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
+ bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+}
+
+/*
* BFA IOC FC related definitions
*/
@@ -67,18 +154,6 @@ static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
* BFA Interrupt handling functions
*/
static void
-bfa_msix_errint(struct bfa_s *bfa, u32 intr)
-{
- bfa_ioc_error_isr(&bfa->ioc);
-}
-
-static void
-bfa_msix_lpu(struct bfa_s *bfa)
-{
- bfa_ioc_mbox_isr(&bfa->ioc);
-}
-
-static void
bfa_reqq_resume(struct bfa_s *bfa, int qid)
{
struct list_head *waitq, *qe, *qen;
@@ -104,9 +179,6 @@ bfa_msix_all(struct bfa_s *bfa, int vec)
bfa_intx(bfa);
}
-/*
- * hal_intr_api
- */
bfa_boolean_t
bfa_intx(struct bfa_s *bfa)
{
@@ -151,18 +223,6 @@ bfa_intx(struct bfa_s *bfa)
}
void
-bfa_intx_enable(struct bfa_s *bfa)
-{
- writel(bfa->iocfc.intr_mask, bfa->iocfc.bfa_regs.intr_mask);
-}
-
-void
-bfa_intx_disable(struct bfa_s *bfa)
-{
- writel(-1L, bfa->iocfc.bfa_regs.intr_mask);
-}
-
-void
bfa_isr_enable(struct bfa_s *bfa)
{
u32 intr_unmask;
@@ -225,7 +285,7 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
bfa_trc(bfa, m->mhdr.msg_class);
bfa_trc(bfa, m->mhdr.msg_id);
bfa_trc(bfa, m->mhdr.mtag.i2htok);
- bfa_assert(0);
+ WARN_ON(1);
bfa_trc_stop(bfa->trcmod);
}
@@ -236,8 +296,6 @@ bfa_msix_rspq(struct bfa_s *bfa, int qid)
u32 pi, ci;
struct list_head *waitq;
- bfa_trc_fp(bfa, qid);
-
qid &= (BFI_IOC_MAX_CQS - 1);
bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
@@ -245,16 +303,10 @@ bfa_msix_rspq(struct bfa_s *bfa, int qid)
ci = bfa_rspq_ci(bfa, qid);
pi = bfa_rspq_pi(bfa, qid);
- bfa_trc_fp(bfa, ci);
- bfa_trc_fp(bfa, pi);
-
if (bfa->rme_process) {
while (ci != pi) {
m = bfa_rspq_elem(bfa, qid, ci);
- bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
-
bfa_isrs[m->mhdr.msg_class] (bfa, m);
-
CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
}
}
@@ -282,7 +334,7 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
intr = readl(bfa->iocfc.bfa_regs.intr_status);
if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
- bfa_msix_lpu(bfa);
+ bfa_ioc_mbox_isr(&bfa->ioc);
intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
@@ -313,22 +365,16 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
}
writel(intr, bfa->iocfc.bfa_regs.intr_status);
- bfa_msix_errint(bfa, intr);
+ bfa_ioc_error_isr(&bfa->ioc);
}
}
-void
-bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
-{
- bfa_isrs[mc] = isr_func;
-}
-
/*
* BFA IOC FC related functions
*/
/*
- * hal_ioc_pvt BFA IOC private functions
+ * BFA IOC private functions
*/
static void
@@ -379,7 +425,7 @@ bfa_iocfc_send_cfg(void *bfa_arg)
struct bfa_iocfc_cfg_s *cfg = &iocfc->cfg;
int i;
- bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
+ WARN_ON(cfg->fwcfg.num_cqs > BFI_IOC_MAX_CQS);
bfa_trc(bfa, cfg->fwcfg.num_cqs);
bfa_iocfc_reset_queues(bfa);
@@ -488,8 +534,8 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
* First allocate dma memory for IOC.
*/
bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
- dm_kva += bfa_ioc_meminfo();
- dm_pa += bfa_ioc_meminfo();
+ dm_kva += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+ dm_pa += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
/*
* Claim DMA-able memory for the request/response queues and for shadow
@@ -552,7 +598,7 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
bfa_meminfo_dma_virt(meminfo) = dm_kva;
bfa_meminfo_dma_phys(meminfo) = dm_pa;
- dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
+ dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
if (dbgsz > 0) {
bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
bfa_meminfo_kva(meminfo) += dbgsz;
@@ -699,7 +745,7 @@ bfa_iocfc_disable_cbfn(void *bfa_arg)
bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
bfa);
else {
- bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
+ WARN_ON(bfa->iocfc.action != BFA_IOCFC_ACT_DISABLE);
bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
bfa);
}
@@ -735,9 +781,6 @@ bfa_iocfc_reset_cbfn(void *bfa_arg)
bfa_isr_enable(bfa);
}
-/*
- * hal_ioc_public
- */
/*
* Query IOC memory requirement information.
@@ -747,11 +790,11 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
u32 *dm_len)
{
/* dma memory for IOC */
- *dm_len += bfa_ioc_meminfo();
+ *dm_len += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
bfa_iocfc_fw_cfg_sz(cfg, dm_len);
bfa_iocfc_cqs_sz(cfg, dm_len);
- *km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
+ *km_len += (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
}
/*
@@ -783,7 +826,7 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
bfa_iocfc_mem_claim(bfa, cfg, meminfo);
- bfa_timer_init(&bfa->timer_mod);
+ INIT_LIST_HEAD(&bfa->timer_mod.timer_q);
INIT_LIST_HEAD(&bfa->comp_q);
for (i = 0; i < BFI_IOC_MAX_CQS; i++)
@@ -794,15 +837,6 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
* Query IOC memory requirement information.
*/
void
-bfa_iocfc_detach(struct bfa_s *bfa)
-{
- bfa_ioc_detach(&bfa->ioc);
-}
-
-/*
- * Query IOC memory requirement information.
- */
-void
bfa_iocfc_init(struct bfa_s *bfa)
{
bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
@@ -852,23 +886,11 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
}
}
void
-bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
-{
- bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
-}
-
-u64
-bfa_adapter_get_id(struct bfa_s *bfa)
-{
- return bfa_ioc_get_adid(&bfa->ioc);
-}
-
-void
bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
{
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
@@ -976,18 +998,6 @@ bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns)
memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(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));
-}
-
int
bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
{
@@ -998,9 +1008,6 @@ bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
return cfgrsp->pbc_cfg.nvports;
}
-/*
- * hal_api
- */
/*
* Use this function query the memory requirement of the BFA library.
@@ -1036,7 +1043,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
int i;
u32 km_len = 0, dm_len = 0;
- bfa_assert((cfg != NULL) && (meminfo != NULL));
+ WARN_ON((cfg == NULL) || (meminfo == NULL));
memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s));
meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type =
@@ -1090,7 +1097,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa->fcs = BFA_FALSE;
- bfa_assert((cfg != NULL) && (meminfo != NULL));
+ WARN_ON((cfg == NULL) || (meminfo == NULL));
/*
* initialize all memory pointers for iterative allocation
@@ -1129,79 +1136,7 @@ bfa_detach(struct bfa_s *bfa)
for (i = 0; hal_mods[i]; i++)
hal_mods[i]->detach(bfa);
-
- bfa_iocfc_detach(bfa);
-}
-
-
-void
-bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod)
-{
- bfa->trcmod = trcmod;
-}
-
-void
-bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog)
-{
- bfa->plog = plog;
-}
-
-/*
- * Initialize IOC.
- *
- * This function will return immediately, when the IOC initialization is
- * completed, the bfa_cb_init() will be called.
- *
- * @param[in] bfa instance
- *
- * @return void
- *
- * Special Considerations:
- *
- * @note
- * When this function returns, the driver should register the interrupt service
- * routine(s) and enable the device interrupts. If this is not done,
- * bfa_cb_init() will never get called
- */
-void
-bfa_init(struct bfa_s *bfa)
-{
- bfa_iocfc_init(bfa);
-}
-
-/*
- * Use this function initiate the IOC configuration setup. This function
- * will return immediately.
- *
- * @param[in] bfa instance
- *
- * @return None
- */
-void
-bfa_start(struct bfa_s *bfa)
-{
- bfa_iocfc_start(bfa);
-}
-
-/*
- * Use this function quiese the IOC. This function will return immediately,
- * when the IOC is actually stopped, the bfad->comp will be set.
- *
- * @param[in]bfa - pointer to bfa_t.
- *
- * @return None
- *
- * Special Considerations:
- * bfad->comp can be set before or after bfa_stop() returns.
- *
- * @note
- * In case of any failure, we could handle it automatically by doing a
- * reset and then succeed the bfa_stop() call.
- */
-void
-bfa_stop(struct bfa_s *bfa)
-{
- bfa_iocfc_stop(bfa);
+ bfa_ioc_detach(&bfa->ioc);
}
void
@@ -1237,20 +1172,6 @@ bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
}
}
-void
-bfa_attach_fcs(struct bfa_s *bfa)
-{
- bfa->fcs = BFA_TRUE;
-}
-
-/*
- * Periodic timer heart beat from driver
- */
-void
-bfa_timer_tick(struct bfa_s *bfa)
-{
- bfa_timer_beat(&bfa->timer_mod);
-}
/*
* Return the list of PCI vendor/device id lists supported by this
@@ -1321,89 +1242,3 @@ bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg)
cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN;
cfg->drvcfg.min_cfg = BFA_TRUE;
}
-
-void
-bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr)
-{
- bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
-}
-
-/*
- * Retrieve firmware trace information on IOC failure.
- */
-bfa_status_t
-bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen)
-{
- return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen);
-}
-
-/*
- * Clear the saved firmware trace information of an IOC.
- */
-void
-bfa_debug_fwsave_clear(struct bfa_s *bfa)
-{
- bfa_ioc_debug_fwsave_clear(&bfa->ioc);
-}
-
-/*
- * Fetch firmware trace data.
- *
- * @param[in] bfa BFA instance
- * @param[out] trcdata Firmware trace buffer
- * @param[in,out] trclen Firmware trace buffer len
- *
- * @retval BFA_STATUS_OK Firmware trace is fetched.
- * @retval BFA_STATUS_INPROGRESS Firmware trace fetch is in progress.
- */
-bfa_status_t
-bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen)
-{
- return bfa_ioc_debug_fwtrc(&bfa->ioc, trcdata, trclen);
-}
-
-/*
- * Dump firmware memory.
- *
- * @param[in] bfa BFA instance
- * @param[out] buf buffer for dump
- * @param[in,out] offset smem offset to start read
- * @param[in,out] buflen length of buffer
- *
- * @retval BFA_STATUS_OK Firmware memory is dumped.
- * @retval BFA_STATUS_INPROGRESS Firmware memory dump is in progress.
- */
-bfa_status_t
-bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen)
-{
- return bfa_ioc_debug_fwcore(&bfa->ioc, buf, offset, buflen);
-}
-/*
- * Reset hw semaphore & usage cnt regs and initialize.
- */
-void
-bfa_chip_reset(struct bfa_s *bfa)
-{
- bfa_ioc_ownership_reset(&bfa->ioc);
- bfa_ioc_pll_init(&bfa->ioc);
-}
-
-/*
- * Fetch firmware statistics data.
- *
- * @param[in] bfa BFA instance
- * @param[out] data Firmware stats buffer
- *
- * @retval BFA_STATUS_OK Firmware trace is fetched.
- */
-bfa_status_t
-bfa_fw_stats_get(struct bfa_s *bfa, void *data)
-{
- return bfa_ioc_fw_stats_get(&bfa->ioc, data);
-}
-
-bfa_status_t
-bfa_fw_stats_clear(struct bfa_s *bfa)
-{
- return bfa_ioc_fw_stats_clear(&bfa->ioc);
-}
diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h
index 99f242b9aa3..12bfeed268e 100644
--- a/drivers/scsi/bfa/bfa_cs.h
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -22,7 +22,7 @@
#ifndef __BFA_CS_H__
#define __BFA_CS_H__
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
/*
* BFA TRC
@@ -32,12 +32,20 @@
#define BFA_TRC_MAX (4 * 1024)
#endif
+#define BFA_TRC_TS(_trcm) \
+ ({ \
+ struct timeval tv; \
+ \
+ do_gettimeofday(&tv); \
+ (tv.tv_sec*1000000+tv.tv_usec); \
+ })
+
#ifndef BFA_TRC_TS
#define BFA_TRC_TS(_trcm) ((_trcm)->ticks++)
#endif
struct bfa_trc_s {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
u16 fileno;
u16 line;
#else
@@ -99,13 +107,6 @@ bfa_trc_stop(struct bfa_trc_mod_s *trcm)
trcm->stopped = 1;
}
-#ifdef FWTRC
-extern void dc_flush(void *data);
-#else
-#define dc_flush(data)
-#endif
-
-
static inline void
__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
{
@@ -119,12 +120,10 @@ __bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
trc->line = (u16) line;
trc->data.u64 = data;
trc->timestamp = BFA_TRC_TS(trcm);
- dc_flush(trc);
trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
if (trcm->tail == trcm->head)
trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
- dc_flush(trcm);
}
@@ -141,42 +140,18 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
trc->line = (u16) line;
trc->data.u32.u32 = data;
trc->timestamp = BFA_TRC_TS(trcm);
- dc_flush(trc);
trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
if (trcm->tail == trcm->head)
trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
- dc_flush(trcm);
}
-#ifndef BFA_PERF_BUILD
-#define bfa_trc_fp(_trcp, _data) bfa_trc(_trcp, _data)
-#else
-#define bfa_trc_fp(_trcp, _data)
-#endif
-
-/*
- * @ BFA LOG interfaces
- */
-#define bfa_assert(__cond) do { \
- if (!(__cond)) { \
- printk(KERN_ERR "assert(%s) failed at %s:%d\\n", \
- #__cond, __FILE__, __LINE__); \
- } \
-} while (0)
-
#define bfa_sm_fault(__mod, __event) do { \
bfa_trc(__mod, (((u32)0xDEAD << 16) | __event)); \
printk(KERN_ERR "Assertion failure: %s:%d: %d", \
__FILE__, __LINE__, (__event)); \
} while (0)
-#ifndef BFA_PERF_BUILD
-#define bfa_assert_fp(__cond) bfa_assert(__cond)
-#else
-#define bfa_assert_fp(__cond)
-#endif
-
/* BFA queue definitions */
#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
#define bfa_q_next(_qe) (((struct list_head *) (_qe))->next)
@@ -199,7 +174,6 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \
(struct list_head *) (_q); \
bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe));\
- BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \
} else { \
*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
} \
@@ -214,7 +188,6 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = \
(struct list_head *) (_q); \
bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\
- BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \
} else { \
*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
} \
@@ -236,16 +209,6 @@ bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
return 0;
}
-/*
- * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
- * consistent across modules)
- */
-#ifndef BFA_PERF_BUILD
-#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe)
-#else
-#define BFA_Q_DBG_INIT(_qe)
-#endif
-
#define bfa_q_is_on_q(_q, _qe) \
bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
@@ -361,4 +324,43 @@ bfa_wc_wait(struct bfa_wc_s *wc)
bfa_wc_down(wc);
}
+static inline void
+wwn2str(char *wwn_str, u64 wwn)
+{
+ union {
+ u64 wwn;
+ u8 byte[8];
+ } w;
+
+ w.wwn = wwn;
+ sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0],
+ w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5],
+ w.byte[6], w.byte[7]);
+}
+
+static inline void
+fcid2str(char *fcid_str, u32 fcid)
+{
+ union {
+ u32 fcid;
+ u8 byte[4];
+ } f;
+
+ f.fcid = fcid;
+ sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]);
+}
+
+#define bfa_swap_3b(_x) \
+ ((((_x) & 0xff) << 16) | \
+ ((_x) & 0x00ff00) | \
+ (((_x) & 0xff0000) >> 16))
+
+#ifndef __BIG_ENDIAN
+#define bfa_hton3b(_x) bfa_swap_3b(_x)
+#else
+#define bfa_hton3b(_x) (_x)
+#endif
+
+#define bfa_ntoh3b(_x) bfa_hton3b(_x)
+
#endif /* __BFA_CS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index 4b5b9e35abb..d85f93aea46 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -19,7 +19,7 @@
#define __BFA_DEFS_H__
#include "bfa_fc.h"
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
#define BFA_MFG_SERIALNUM_SIZE 11
#define STRSZ(_n) (((_n) + 4) & ~3)
@@ -446,8 +446,8 @@ enum bfa_boot_bootopt {
* Boot lun information.
*/
struct bfa_boot_bootlun_s {
- wwn_t pwwn; /* port wwn of target */
- lun_t lun; /* 64-bit lun */
+ wwn_t pwwn; /* port wwn of target */
+ struct scsi_lun lun; /* 64-bit lun */
};
#pragma pack()
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index e24e9f7ca81..648c8417672 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -34,8 +34,8 @@
struct bfa_iocfc_intr_attr_s {
u8 coalesce; /* enable/disable coalescing */
u8 rsvd[3];
- u16 latency; /* latency in microseconds */
- u16 delay; /* delay in microseconds */
+ __be16 latency; /* latency in microseconds */
+ __be16 delay; /* delay in microseconds */
};
/*
@@ -743,7 +743,7 @@ struct bfa_port_cfg_s {
u8 qos_enabled; /* qos enabled or not */
u8 cfg_hardalpa; /* is hard alpa configured */
u8 hardalpa; /* configured hard alpa */
- u16 maxfrsize; /* maximum frame size */
+ __be16 maxfrsize; /* maximum frame size */
u8 rx_bbcredit; /* receive buffer credits */
u8 tx_bbcredit; /* transmit buffer credits */
u8 ratelimit; /* ratelimit enabled or not */
@@ -843,7 +843,7 @@ struct bfa_fcport_fcf_s {
u8 fka_disabled; /* FKA is disabled */
u8 maxsz_verified; /* FCoE max size verified */
u8 fc_map[3]; /* FC map */
- u16 vlan; /* FCoE vlan tag/priority */
+ __be16 vlan; /* FCoE vlan tag/priority */
u32 fka_adv_per; /* FIP ka advert. period */
mac_t mac; /* FCF mac */
};
diff --git a/drivers/scsi/bfa/bfa_drv.c b/drivers/scsi/bfa/bfa_drv.c
deleted file mode 100644
index 0222d7c88a9..00000000000
--- a/drivers/scsi/bfa/bfa_drv.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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 "bfa_modules.h"
-
-/*
- * BFA module list terminated by NULL
- */
-struct bfa_module_s *hal_mods[] = {
- &hal_mod_sgpg,
- &hal_mod_fcport,
- &hal_mod_fcxp,
- &hal_mod_lps,
- &hal_mod_uf,
- &hal_mod_rport,
- &hal_mod_fcpim,
- NULL
-};
-
-/*
- * Message handlers for various modules.
- */
-bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = {
- bfa_isr_unhandled, /* NONE */
- bfa_isr_unhandled, /* BFI_MC_IOC */
- bfa_isr_unhandled, /* BFI_MC_DIAG */
- bfa_isr_unhandled, /* BFI_MC_FLASH */
- bfa_isr_unhandled, /* BFI_MC_CEE */
- bfa_fcport_isr, /* BFI_MC_FCPORT */
- bfa_isr_unhandled, /* BFI_MC_IOCFC */
- bfa_isr_unhandled, /* BFI_MC_LL */
- bfa_uf_isr, /* BFI_MC_UF */
- bfa_fcxp_isr, /* BFI_MC_FCXP */
- bfa_lps_isr, /* BFI_MC_LPS */
- bfa_rport_isr, /* BFI_MC_RPORT */
- bfa_itnim_isr, /* BFI_MC_ITNIM */
- bfa_isr_unhandled, /* BFI_MC_IOIM_READ */
- bfa_isr_unhandled, /* BFI_MC_IOIM_WRITE */
- bfa_isr_unhandled, /* BFI_MC_IOIM_IO */
- bfa_ioim_isr, /* BFI_MC_IOIM */
- bfa_ioim_good_comp_isr, /* BFI_MC_IOIM_IOCOM */
- bfa_tskim_isr, /* BFI_MC_TSKIM */
- bfa_isr_unhandled, /* BFI_MC_SBOOT */
- bfa_isr_unhandled, /* BFI_MC_IPFC */
- bfa_isr_unhandled, /* BFI_MC_PORT */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
- bfa_isr_unhandled, /* --------- */
-};
-
-
-/*
- * Message handlers for mailbox command classes
- */
-bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = {
- NULL,
- NULL, /* BFI_MC_IOC */
- NULL, /* BFI_MC_DIAG */
- NULL, /* BFI_MC_FLASH */
- NULL, /* BFI_MC_CEE */
- NULL, /* BFI_MC_PORT */
- bfa_iocfc_isr, /* BFI_MC_IOCFC */
- NULL,
-};
-
-
-
-void
-bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
-{
- struct bfa_port_s *port = &bfa->modules.port;
- u32 dm_len;
- u8 *dm_kva;
- u64 dm_pa;
-
- dm_len = bfa_port_meminfo();
- dm_kva = bfa_meminfo_dma_virt(mi);
- dm_pa = bfa_meminfo_dma_phys(mi);
-
- memset(port, 0, sizeof(struct bfa_port_s));
- bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
- bfa_port_mem_claim(port, dm_kva, dm_pa);
-
- bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
- bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
-}
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index e929d25b09e..8e764fae8dc 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -18,14 +18,12 @@
#ifndef __BFA_FC_H__
#define __BFA_FC_H__
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
typedef u64 wwn_t;
-typedef u64 lun_t;
#define WWN_NULL (0)
#define FC_SYMNAME_MAX 256 /* max name server symbolic name size */
-#define FC_ALPA_MAX 128
#pragma pack(1)
@@ -40,7 +38,6 @@ struct mac_s { u8 mac[MAC_ADDRLEN]; };
struct scsi_cdb_s {
u8 scsi_cdb[SCSI_MAX_CDBLEN];
};
-#define scsi_cdb_t struct scsi_cdb_s
/* ------------------------------------------------------------
* SCSI status byte values
@@ -63,7 +60,7 @@ struct scsi_cdb_s {
* Fibre Channel Header Structure (FCHS) definition
*/
struct fchs_s {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
u32 routing:4; /* routing bits */
u32 cat_info:4; /* category info */
#else
@@ -75,34 +72,19 @@ struct fchs_s {
u32 cs_ctl:8; /* class specific control */
u32 s_id:24; /* source identifier */
- u32 type:8; /* data structure type */
+ u32 type:8; /* data structure type */
u32 f_ctl:24; /* initial frame control */
- u8 seq_id; /* sequence identifier */
- u8 df_ctl; /* data field control */
+ u8 seq_id; /* sequence identifier */
+ u8 df_ctl; /* data field control */
u16 seq_cnt; /* sequence count */
- u16 ox_id; /* originator exchange ID */
- u16 rx_id; /* responder exchange ID */
+ __be16 ox_id; /* originator exchange ID */
+ u16 rx_id; /* responder exchange ID */
u32 ro; /* relative offset */
};
-#define FC_SOF_LEN 4
-#define FC_EOF_LEN 4
-#define FC_CRC_LEN 4
-
-/*
- * Fibre Channel BB_E Header Structure
- */
-struct fcbbehs_s {
- u16 ver_rsvd;
- u32 rsvd[2];
- u32 rsvd__sof;
-};
-
-#define FC_SEQ_ID_MAX 256
-
/*
* routing bit definitions
*/
@@ -149,22 +131,6 @@ enum {
};
/*
- * information category for Link Control
- */
-enum {
- FC_CAT_ACK_1 = 0x00,
- FC_CAT_ACK_0_N = 0x01,
- FC_CAT_P_RJT = 0x02,
- FC_CAT_F_RJT = 0x03,
- FC_CAT_P_BSY = 0x04,
- FC_CAT_F_BSY_DATA = 0x05,
- FC_CAT_F_BSY_LINK_CTL = 0x06,
- FC_CAT_F_LCR = 0x07,
- FC_CAT_NTY = 0x08,
- FC_CAT_END = 0x09,
-};
-
-/*
* Type Field Definitions. FC-PH Section 18.5 pg. 165
*/
enum {
@@ -182,10 +148,6 @@ enum {
FC_TYPE_MAX = 256, /* 256 FC-4 types */
};
-struct fc_fc4types_s {
- u8 bits[FC_TYPE_MAX / 8];
-};
-
/*
* Frame Control Definitions. FC-PH Table-45. pg. 168
*/
@@ -288,7 +250,6 @@ enum {
FC_ELS_AUTH = 0x90, /* Authentication. Ref FC-SP */
FC_ELS_RFCN = 0x97, /* Request Fabric Change Notification. Ref
*FC-SP */
-
};
/*
@@ -314,12 +275,12 @@ enum {
* FC-PH-x. Figure-76. pg. 308.
*/
struct fc_plogi_csp_s {
- u8 verhi; /* FC-PH high version */
- u8 verlo; /* FC-PH low version */
- u16 bbcred; /* BB_Credit */
+ u8 verhi; /* FC-PH high version */
+ u8 verlo; /* FC-PH low version */
+ __be16 bbcred; /* BB_Credit */
-#ifdef __BIGENDIAN
- u8 ciro:1, /* continuously increasing RO */
+#ifdef __BIG_ENDIAN
+ u8 ciro:1, /* continuously increasing RO */
rro:1, /* random relative offset */
npiv_supp:1, /* NPIV supported */
port_type:1, /* N_Port/F_port */
@@ -328,7 +289,7 @@ struct fc_plogi_csp_s {
vvl_info:1, /* VVL Info included */
reserved1:1;
- u8 hg_supp:1,
+ u8 hg_supp:1,
query_dbc:1,
security:1,
sync_cap:1,
@@ -337,7 +298,7 @@ struct fc_plogi_csp_s {
cisc:1, /* continuously increasing seq count */
payload:1;
#else
- u8 reserved2:2,
+ u8 reserved2:2,
resolution:1, /* ms/ns ED_TOV resolution */
altbbcred:1, /* alternate BB_Credit */
port_type:1, /* N_Port/F_port */
@@ -345,7 +306,7 @@ struct fc_plogi_csp_s {
rro:1, /* random relative offset */
ciro:1; /* continuously increasing RO */
- u8 payload:1,
+ u8 payload:1,
cisc:1, /* continuously increasing seq count */
dh_dup_supp:1,
r_t_tov:1,
@@ -354,13 +315,10 @@ struct fc_plogi_csp_s {
query_dbc:1,
hg_supp:1;
#endif
-
- u16 rxsz; /* recieve data_field size */
-
- u16 conseq;
- u16 ro_bitmap;
-
- u32 e_d_tov;
+ __be16 rxsz; /* recieve data_field size */
+ __be16 conseq;
+ __be16 ro_bitmap;
+ __be32 e_d_tov;
};
/*
@@ -368,12 +326,11 @@ struct fc_plogi_csp_s {
* FC-PH-x. Figure 78. pg. 318.
*/
struct fc_plogi_clp_s {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
u32 class_valid:1;
u32 intermix:1; /* class intermix supported if set =1.
- * valid only for class1. Reserved for
- * class2 & class3
- */
+ * valid only for class1. Reserved for
+ * class2 & class3 */
u32 reserved1:2;
u32 sequential:1;
u32 reserved2:3;
@@ -382,12 +339,10 @@ struct fc_plogi_clp_s {
u32 sequential:1;
u32 reserved1:2;
u32 intermix:1; /* class intermix supported if set =1.
- * valid only for class1. Reserved for
- * class2 & class3
- */
+ * valid only for class1. Reserved for
+ * class2 & class3 */
u32 class_valid:1;
#endif
-
u32 reserved3:24;
u32 reserved4:16;
@@ -395,7 +350,7 @@ struct fc_plogi_clp_s {
u32 reserved5:8;
u32 conseq:8;
- u32 e2e_credit:16; /* end to end credit */
+ u32 e2e_credit:16; /* end to end credit */
u32 reserved7:8;
u32 ospx:8;
@@ -409,24 +364,24 @@ struct fc_plogi_clp_s {
* PLOGI els command and reply payload
*/
struct fc_logi_s {
- struct fc_els_cmd_s els_cmd; /* ELS command code */
- struct fc_plogi_csp_s csp; /* common service params */
- wwn_t port_name;
- wwn_t node_name;
- struct fc_plogi_clp_s class1; /* class 1 service parameters */
- struct fc_plogi_clp_s class2; /* class 2 service parameters */
- struct fc_plogi_clp_s class3; /* class 3 service parameters */
- struct fc_plogi_clp_s class4; /* class 4 service parameters */
- u8 vvl[16]; /* vendor version level */
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
+ struct fc_plogi_csp_s csp; /* common service params */
+ wwn_t port_name;
+ wwn_t node_name;
+ struct fc_plogi_clp_s class1; /* class 1 service parameters */
+ struct fc_plogi_clp_s class2; /* class 2 service parameters */
+ struct fc_plogi_clp_s class3; /* class 3 service parameters */
+ struct fc_plogi_clp_s class4; /* class 4 service parameters */
+ u8 vvl[16]; /* vendor version level */
};
/*
* LOGO els command payload
*/
struct fc_logo_s {
- struct fc_els_cmd_s els_cmd; /* ELS command code */
- u32 res1:8;
- u32 nport_id:24; /* N_Port identifier of source */
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
+ u32 res1:8;
+ u32 nport_id:24; /* N_Port identifier of source */
wwn_t orig_port_name; /* Port name of the LOGO originator */
};
@@ -435,12 +390,12 @@ struct fc_logo_s {
*/
struct fc_adisc_s {
struct fc_els_cmd_s els_cmd; /* ELS command code */
- u32 res1:8;
- u32 orig_HA:24; /* originator hard address */
- wwn_t orig_port_name; /* originator port name */
- wwn_t orig_node_name; /* originator node name */
- u32 res2:8;
- u32 nport_id:24; /* originator NPortID */
+ u32 res1:8;
+ u32 orig_HA:24; /* originator hard address */
+ wwn_t orig_port_name; /* originator port name */
+ wwn_t orig_node_name; /* originator node name */
+ u32 res2:8;
+ u32 nport_id:24; /* originator NPortID */
};
/*
@@ -466,7 +421,7 @@ struct fc_exch_status_blk_s {
struct fc_res_s {
struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 res1:8;
- u32 nport_id:24; /* N_Port identifier of source */
+ u32 nport_id:24; /* N_Port identifier of source */
u32 oxid:16;
u32 rxid:16;
u8 assoc_hdr[32];
@@ -512,8 +467,8 @@ struct fc_rec_acc_s {
u32 orig_id:24; /* N_Port id of exchange originator */
u32 res2:8;
u32 resp_id:24; /* N_Port id of exchange responder */
- u32 count; /* data transfer count */
- u32 e_stat; /* exchange status */
+ u32 count; /* data transfer count */
+ u32 e_stat; /* exchange status */
};
/*
@@ -533,7 +488,7 @@ struct fc_rsi_s {
*/
struct fc_prli_params_s {
u32 reserved:16;
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
u32 reserved1:5;
u32 rec_support:1;
u32 task_retry_id:1;
@@ -575,7 +530,7 @@ enum {
struct fc_prli_params_page_s {
u32 type:8;
u32 codext:8;
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
u32 origprocasv:1;
u32 rsppav:1;
u32 imagepair:1;
@@ -611,18 +566,14 @@ struct fc_prli_s {
struct fc_prlo_params_page_s {
u32 type:8;
u32 type_ext:8;
-#ifdef __BIGENDIAN
- u32 opa_valid:1; /* originator process associator
- * valid
- */
+#ifdef __BIG_ENDIAN
+ u32 opa_valid:1; /* originator process associator valid */
u32 rpa_valid:1; /* responder process associator valid */
u32 res1:14;
#else
u32 res1:14;
u32 rpa_valid:1; /* responder process associator valid */
- u32 opa_valid:1; /* originator process associator
- * valid
- */
+ u32 opa_valid:1; /* originator process associator valid */
#endif
u32 orig_process_assc;
u32 resp_process_assc;
@@ -647,18 +598,14 @@ struct fc_prlo_acc_params_page_s {
u32 type:8;
u32 type_ext:8;
-#ifdef __BIGENDIAN
- u32 opa_valid:1; /* originator process associator
- * valid
- */
+#ifdef __BIG_ENDIAN
+ u32 opa_valid:1; /* originator process associator valid */
u32 rpa_valid:1; /* responder process associator valid */
u32 res1:14;
#else
u32 res1:14;
u32 rpa_valid:1; /* responder process associator valid */
- u32 opa_valid:1; /* originator process associator
- * valid
- */
+ u32 opa_valid:1; /* originator process associator valid */
#endif
u32 orig_process_assc;
u32 resp_process_assc;
@@ -715,9 +662,9 @@ enum {
* LS_RJT els reply payload
*/
struct fc_ls_rjt_s {
- struct fc_els_cmd_s els_cmd; /* ELS command code */
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 res1:8;
- u32 reason_code:8; /* Reason code for reject */
+ u32 reason_code:8; /* Reason code for reject */
u32 reason_code_expl:8; /* Reason code explanation */
u32 vendor_unique:8; /* Vendor specific */
};
@@ -779,12 +726,12 @@ struct fc_rrq_s {
*/
struct fc_ba_acc_s {
u32 seq_id_valid:8; /* set to 0x00 for Abort Exchange */
- u32 seq_id:8; /* invalid for Abort Exchange */
+ u32 seq_id:8; /* invalid for Abort Exchange */
u32 res2:16;
- u32 ox_id:16; /* OX_ID from ABTS frame */
- u32 rx_id:16; /* RX_ID from ABTS frame */
+ u32 ox_id:16; /* OX_ID from ABTS frame */
+ u32 rx_id:16; /* RX_ID from ABTS frame */
u32 low_seq_cnt:16; /* set to 0x0000 for Abort Exchange */
- u32 high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */
+ u32 high_seq_cnt:16; /* set to 0xFFFF for Abort Exchange */
};
/*
@@ -794,17 +741,17 @@ struct fc_ba_rjt_s {
u32 res1:8; /* Reserved */
u32 reason_code:8; /* reason code for reject */
u32 reason_expl:8; /* reason code explanation */
- u32 vendor_unique:8;/* vendor unique reason code,set to 0 */
+ u32 vendor_unique:8; /* vendor unique reason code,set to 0 */
};
/*
* TPRLO logout parameter page
*/
struct fc_tprlo_params_page_s {
-u32 type:8;
-u32 type_ext:8;
+ u32 type:8;
+ u32 type_ext:8;
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
u32 opa_valid:1;
u32 rpa_valid:1;
u32 tpo_nport_valid:1;
@@ -864,16 +811,16 @@ enum fc_rscn_format {
};
struct fc_rscn_event_s {
- u32 format:2;
- u32 qualifier:4;
- u32 resvd:2;
- u32 portid:24;
+ u32 format:2;
+ u32 qualifier:4;
+ u32 resvd:2;
+ u32 portid:24;
};
struct fc_rscn_pl_s {
- u8 command;
- u8 pagelen;
- u16 payldlen;
+ u8 command;
+ u8 pagelen;
+ __be16 payldlen;
struct fc_rscn_event_s event[1];
};
@@ -887,7 +834,6 @@ struct fc_echo_s {
/*
* RNID els command
*/
-
#define RNID_NODEID_DATA_FORMAT_COMMON 0x00
#define RNID_NODEID_DATA_FORMAT_FCP3 0x08
#define RNID_NODEID_DATA_FORMAT_DISCOVERY 0xDF
@@ -920,15 +866,15 @@ struct fc_rnid_cmd_s {
*/
struct fc_rnid_common_id_data_s {
- wwn_t port_name;
+ wwn_t port_name;
wwn_t node_name;
};
struct fc_rnid_general_topology_data_s {
u32 vendor_unique[4];
- u32 asso_type;
+ __be32 asso_type;
u32 phy_port_num;
- u32 num_attached_nodes;
+ __be32 num_attached_nodes;
u32 node_mgmt:8;
u32 ip_version:8;
u32 udp_tcp_port_num:16;
@@ -980,59 +926,17 @@ enum fc_rpsc_op_speed {
RPSC_OP_SPEED_8G = 0x0800,
RPSC_OP_SPEED_16G = 0x0400,
- RPSC_OP_SPEED_NOT_EST = 0x0001, /*! speed not established */
+ RPSC_OP_SPEED_NOT_EST = 0x0001, /* speed not established */
};
struct fc_rpsc_speed_info_s {
- u16 port_speed_cap; /*! see enum fc_rpsc_speed_cap */
- u16 port_op_speed; /*! see enum fc_rpsc_op_speed */
-};
-
-enum link_e2e_beacon_subcmd {
- LINK_E2E_BEACON_ON = 1,
- LINK_E2E_BEACON_OFF = 2
-};
-
-enum beacon_type {
- BEACON_TYPE_NORMAL = 1, /*! Normal Beaconing. Green */
- BEACON_TYPE_WARN = 2, /*! Warning Beaconing. Yellow/Amber */
- BEACON_TYPE_CRITICAL = 3 /*! Critical Beaconing. Red */
-};
-
-struct link_e2e_beacon_param_s {
- u8 beacon_type; /* Beacon Type. See enum beacon_type */
- u8 beacon_frequency;
- /* Beacon frequency. Number of blinks
- * per 10 seconds
- */
- u16 beacon_duration;/* Beacon duration (in Seconds). The
- * command operation should be
- * terminated at the end of this
- * timeout value.
- *
- * Ignored if diag_sub_cmd is
- * LINK_E2E_BEACON_OFF.
- *
- * If 0, beaconing will continue till a
- * BEACON OFF request is received
- */
-};
-
-/*
- * Link E2E beacon request/good response format.
- * For LS_RJTs use struct fc_ls_rjt_s
- */
-struct link_e2e_beacon_req_s {
- u32 ls_code; /*! FC_ELS_E2E_LBEACON in requests *
- *or FC_ELS_ACC in good replies */
- u32 ls_sub_cmd; /*! See enum link_e2e_beacon_subcmd */
- struct link_e2e_beacon_param_s beacon_parm;
+ __be16 port_speed_cap; /* see enum fc_rpsc_speed_cap */
+ __be16 port_op_speed; /* see enum fc_rpsc_op_speed */
};
/*
* If RPSC request is sent to the Domain Controller, the request is for
- * all the ports within that domain (TODO - I don't think FOS implements
- * this...).
+ * all the ports within that domain.
*/
struct fc_rpsc_cmd_s {
struct fc_els_cmd_s els_cmd;
@@ -1056,9 +960,9 @@ struct fc_rpsc_acc_s {
struct fc_rpsc2_cmd_s {
struct fc_els_cmd_s els_cmd;
- u32 token;
+ __be32 token;
u16 resvd;
- u16 num_pids; /* Number of pids in the request */
+ __be16 num_pids; /* Number of pids in the request */
struct {
u32 rsvd1:8;
u32 pid:24; /* port identifier */
@@ -1072,16 +976,17 @@ enum fc_rpsc2_port_type {
RPSC2_PORT_TYPE_NPIV_PORT = 0x5f,
RPSC2_PORT_TYPE_NPORT_TRUNK = 0x6f,
};
+
/*
* RPSC2 portInfo entry structure
*/
struct fc_rpsc2_port_info_s {
- u32 pid; /* PID */
- u16 resvd1;
- u16 index; /* port number / index */
- u8 resvd2;
- u8 type; /* port type N/NL/... */
- u16 speed; /* port Operating Speed */
+ __be32 pid; /* PID */
+ u16 resvd1;
+ __be16 index; /* port number / index */
+ u8 resvd2;
+ u8 type; /* port type N/NL/... */
+ __be16 speed; /* port Operating Speed */
};
/*
@@ -1090,8 +995,8 @@ struct fc_rpsc2_port_info_s {
struct fc_rpsc2_acc_s {
u8 els_cmd;
u8 resvd;
- u16 num_pids; /* Number of pids in the request */
- struct fc_rpsc2_port_info_s port_info[1]; /* port information */
+ __be16 num_pids; /* Number of pids in the request */
+ struct fc_rpsc2_port_info_s port_info[1]; /* port information */
};
/*
@@ -1110,18 +1015,14 @@ struct fc_symname_s {
u8 symname[FC_SYMNAME_MAX];
};
-struct fc_alpabm_s {
- u8 alpa_bm[FC_ALPA_MAX / 8];
-};
-
/*
* protocol default timeout values
*/
-#define FC_ED_TOV 2
-#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)
+#define FC_ED_TOV 2
+#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
@@ -1157,50 +1058,34 @@ enum {
};
/*
- * SRR FC-4 LS payload
- */
-struct fc_srr_s {
- u32 ls_cmd;
- u32 ox_id:16; /* ox-id */
- u32 rx_id:16; /* rx-id */
- u32 ro; /* relative offset */
- u32 r_ctl:8; /* R_CTL for I.U. */
- u32 res:24;
-};
-
-
-/*
* FCP_CMND definitions
*/
#define FCP_CMND_CDB_LEN 16
#define FCP_CMND_LUN_LEN 8
struct fcp_cmnd_s {
- lun_t lun; /* 64-bit LU number */
- u8 crn; /* command reference number */
-#ifdef __BIGENDIAN
- u8 resvd:1,
+ struct scsi_lun lun; /* 64-bit LU number */
+ u8 crn; /* command reference number */
+#ifdef __BIG_ENDIAN
+ u8 resvd:1,
priority:4, /* FCP-3: SAM-3 priority */
taskattr:3; /* scsi task attribute */
#else
- u8 taskattr:3, /* scsi task attribute */
+ u8 taskattr:3, /* scsi task attribute */
priority:4, /* FCP-3: SAM-3 priority */
resvd:1;
#endif
- u8 tm_flags; /* task management flags */
-#ifdef __BIGENDIAN
- u8 addl_cdb_len:6, /* additional CDB length words */
+ u8 tm_flags; /* task management flags */
+#ifdef __BIG_ENDIAN
+ u8 addl_cdb_len:6, /* additional CDB length words */
iodir:2; /* read/write FCP_DATA IUs */
#else
- u8 iodir:2, /* read/write FCP_DATA IUs */
+ u8 iodir:2, /* read/write FCP_DATA IUs */
addl_cdb_len:6; /* additional CDB length */
#endif
- scsi_cdb_t cdb;
+ struct scsi_cdb_s cdb;
- /*
- * !!! additional cdb bytes follows here!!!
- */
- u32 fcp_dl; /* bytes to be transferred */
+ __be32 fcp_dl; /* bytes to be transferred */
};
#define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
@@ -1210,21 +1095,10 @@ struct fcp_cmnd_s {
* struct fcp_cmnd_s .iodir field values
*/
enum fcp_iodir {
- FCP_IODIR_NONE = 0,
+ FCP_IODIR_NONE = 0,
FCP_IODIR_WRITE = 1,
- FCP_IODIR_READ = 2,
- FCP_IODIR_RW = 3,
-};
-
-/*
- * Task attribute field
- */
-enum {
- FCP_TASK_ATTR_SIMPLE = 0,
- FCP_TASK_ATTR_HOQ = 1,
- FCP_TASK_ATTR_ORDERED = 2,
- FCP_TASK_ATTR_ACA = 4,
- FCP_TASK_ATTR_UNTAGGED = 5, /* obsolete in FCP-3 */
+ FCP_IODIR_READ = 2,
+ FCP_IODIR_RW = 3,
};
/*
@@ -1239,58 +1113,40 @@ enum fcp_tm_cmnd {
};
/*
- * FCP_XFER_RDY IU defines
- */
-struct fcp_xfer_rdy_s {
- u32 data_ro;
- u32 burst_len;
- u32 reserved;
-};
-
-/*
* FCP_RSP residue flags
*/
enum fcp_residue {
- FCP_NO_RESIDUE = 0, /* no residue */
- FCP_RESID_OVER = 1, /* more data left that was not sent */
- FCP_RESID_UNDER = 2, /* less data than requested */
-};
-
-enum {
- FCP_RSPINFO_GOOD = 0,
- FCP_RSPINFO_DATALEN_MISMATCH = 1,
- FCP_RSPINFO_CMND_INVALID = 2,
- FCP_RSPINFO_ROLEN_MISMATCH = 3,
- FCP_RSPINFO_TM_NOT_SUPP = 4,
- FCP_RSPINFO_TM_FAILED = 5,
+ FCP_NO_RESIDUE = 0, /* no residue */
+ FCP_RESID_OVER = 1, /* more data left that was not sent */
+ FCP_RESID_UNDER = 2, /* less data than requested */
};
struct fcp_rspinfo_s {
u32 res0:24;
- u32 rsp_code:8; /* response code (as above) */
+ u32 rsp_code:8; /* response code (as above) */
u32 res1;
};
struct fcp_resp_s {
- u32 reserved[2]; /* 2 words reserved */
+ u32 reserved[2]; /* 2 words reserved */
u16 reserved2;
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
u8 reserved3:3;
u8 fcp_conf_req:1; /* FCP_CONF is requested */
u8 resid_flags:2; /* underflow/overflow */
- u8 sns_len_valid:1;/* sense len is valid */
- u8 rsp_len_valid:1;/* response len is valid */
+ u8 sns_len_valid:1; /* sense len is valid */
+ u8 rsp_len_valid:1; /* response len is valid */
#else
- u8 rsp_len_valid:1;/* response len is valid */
- u8 sns_len_valid:1;/* sense len is valid */
+ u8 rsp_len_valid:1; /* response len is valid */
+ u8 sns_len_valid:1; /* sense len is valid */
u8 resid_flags:2; /* underflow/overflow */
u8 fcp_conf_req:1; /* FCP_CONF is requested */
u8 reserved3:3;
#endif
- u8 scsi_status; /* one byte SCSI status */
- u32 residue; /* residual data bytes */
- u32 sns_len; /* length od sense info */
- u32 rsp_len; /* length of response info */
+ u8 scsi_status; /* one byte SCSI status */
+ u32 residue; /* residual data bytes */
+ u32 sns_len; /* length od sense info */
+ u32 rsp_len; /* length of response info */
};
#define fcp_snslen(__fcprsp) ((__fcprsp)->sns_len_valid ? \
@@ -1300,12 +1156,6 @@ struct fcp_resp_s {
#define fcp_rspinfo(__fcprsp) ((struct fcp_rspinfo_s *)((__fcprsp) + 1))
#define fcp_snsinfo(__fcprsp) (((u8 *)fcp_rspinfo(__fcprsp)) + \
fcp_rsplen(__fcprsp))
-
-struct fcp_cmnd_fr_s {
- struct fchs_s fchs;
- struct fcp_cmnd_s fcp;
-};
-
/*
* CT
*/
@@ -1379,7 +1229,7 @@ enum {
CT_RSN_LOGICAL_BUSY = 0x05,
CT_RSN_PROTO_ERR = 0x07,
CT_RSN_UNABLE_TO_PERF = 0x09,
- CT_RSN_NOT_SUPP = 0x0B,
+ CT_RSN_NOT_SUPP = 0x0B,
CT_RSN_SERVER_NOT_AVBL = 0x0D,
CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
CT_RSN_VENDOR_SPECIFIC = 0xFF,
@@ -1419,10 +1269,10 @@ enum {
* defintions for the explanation code for all servers
*/
enum {
- CT_EXP_AUTH_EXCEPTION = 0xF1,
- CT_EXP_DB_FULL = 0xF2,
- CT_EXP_DB_EMPTY = 0xF3,
- CT_EXP_PROCESSING_REQ = 0xF4,
+ CT_EXP_AUTH_EXCEPTION = 0xF1,
+ CT_EXP_DB_FULL = 0xF2,
+ CT_EXP_DB_EMPTY = 0xF3,
+ CT_EXP_PROCESSING_REQ = 0xF4,
CT_EXP_UNABLE_TO_VERIFY_CONN = 0xF5,
CT_EXP_DEVICES_NOT_IN_CMN_ZONE = 0xF6
};
@@ -1446,7 +1296,7 @@ enum {
GS_RFF_ID = 0x021F, /* Register FC4 Feature */
};
-struct fcgs_id_req_s{
+struct fcgs_id_req_s {
u32 rsvd:8;
u32 dap:24; /* port identifier */
};
@@ -1460,7 +1310,7 @@ struct fcgs_gidpn_req_s {
struct fcgs_gidpn_resp_s {
u32 rsvd:8;
- u32 dap:24; /* port identifier */
+ u32 dap:24; /* port identifier */
};
/*
@@ -1469,22 +1319,21 @@ struct fcgs_gidpn_resp_s {
struct fcgs_rftid_req_s {
u32 rsvd:8;
u32 dap:24; /* port identifier */
- u32 fc4_type[8]; /* fc4 types */
+ __be32 fc4_type[8]; /* fc4 types */
};
/*
* RFF_ID : Register FC4 features.
*/
-
#define FC_GS_FCP_FC4_FEATURE_INITIATOR 0x02
#define FC_GS_FCP_FC4_FEATURE_TARGET 0x01
struct fcgs_rffid_req_s {
- u32 rsvd:8;
- u32 dap:24; /* port identifier */
- u32 rsvd1:16;
- u32 fc4ftr_bits:8; /* fc4 feature bits */
- u32 fc4_type:8; /* corresponding FC4 Type */
+ u32 rsvd:8;
+ u32 dap:24; /* port identifier */
+ u32 rsvd1:16;
+ u32 fc4ftr_bits:8; /* fc4 feature bits */
+ u32 fc4_type:8; /* corresponding FC4 Type */
};
/*
@@ -1495,16 +1344,16 @@ struct fcgs_gidft_req_s {
u8 domain_id; /* domain, 0 - all fabric */
u8 area_id; /* area, 0 - whole domain */
u8 fc4_type; /* FC_TYPE_FCP for SCSI devices */
-}; /* GID_FT Request */
+};
/*
* GID_FT Response
*/
struct fcgs_gidft_resp_s {
- u8 last:1; /* last port identifier flag */
- u8 reserved:7;
- u32 pid:24; /* port identifier */
-}; /* GID_FT Response */
+ u8 last:1; /* last port identifier flag */
+ u8 reserved:7;
+ u32 pid:24; /* port identifier */
+};
/*
* RSPN_ID
@@ -1512,8 +1361,8 @@ struct fcgs_gidft_resp_s {
struct fcgs_rspnid_req_s {
u32 rsvd:8;
u32 dap:24; /* port identifier */
- u8 spn_len; /* symbolic port name length */
- u8 spn[256]; /* symbolic port name */
+ u8 spn_len; /* symbolic port name length */
+ u8 spn[256]; /* symbolic port name */
};
/*
@@ -1522,7 +1371,7 @@ struct fcgs_rspnid_req_s {
struct fcgs_rpnid_req_s {
u32 rsvd:8;
u32 port_id:24;
- wwn_t port_name;
+ wwn_t port_name;
};
/*
@@ -1531,7 +1380,7 @@ struct fcgs_rpnid_req_s {
struct fcgs_rnnid_req_s {
u32 rsvd:8;
u32 port_id:24;
- wwn_t node_name;
+ wwn_t node_name;
};
/*
@@ -1565,8 +1414,8 @@ struct fcgs_ganxt_req_s {
* GA_NXT Response
*/
struct fcgs_ganxt_rsp_s {
- u32 port_type:8; /* Port Type */
- u32 port_id:24; /* Port Identifier */
+ u32 port_type:8; /* Port Type */
+ u32 port_id:24; /* Port Identifier */
wwn_t port_name; /* Port Name */
u8 spn_len; /* Length of Symbolic Port Name */
char spn[255]; /* Symbolic Port Name */
@@ -1575,19 +1424,14 @@ struct fcgs_ganxt_rsp_s {
char snn[255]; /* Symbolic Node Name */
u8 ipa[8]; /* Initial Process Associator */
u8 ip[16]; /* IP Address */
- u32 cos; /* Class of Service */
- u32 fc4types[8]; /* FC-4 TYPEs */
- wwn_t fabric_port_name;
- /* Fabric Port Name */
- u32 rsvd:8; /* Reserved */
- u32 hard_addr:24; /* Hard Address */
+ u32 cos; /* Class of Service */
+ u32 fc4types[8]; /* FC-4 TYPEs */
+ wwn_t fabric_port_name; /* Fabric Port Name */
+ u32 rsvd:8; /* Reserved */
+ u32 hard_addr:24; /* Hard Address */
};
/*
- * Fabric Config Server
- */
-
-/*
* Command codes for Fabric Configuration Server
*/
enum {
@@ -1598,159 +1442,9 @@ enum {
};
/*
- * Source or Destination Port Tags.
- */
-enum {
- GS_FTRACE_TAG_NPORT_ID = 1,
- GS_FTRACE_TAG_NPORT_NAME = 2,
-};
-
-/*
-* Port Value : Could be a Port id or wwn
- */
-union fcgs_port_val_u {
- u32 nport_id;
- wwn_t nport_wwn;
-};
-
-#define GS_FTRACE_MAX_HOP_COUNT 20
-#define GS_FTRACE_REVISION 1
-
-/*
- * Ftrace Related Structures.
- */
-
-/*
- * STR (Switch Trace) Reject Reason Codes. From FC-SW.
- */
-enum {
- GS_FTRACE_STR_CMD_COMPLETED_SUCC = 0,
- GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
- GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
- GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
- GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
- GS_FTRACE_STR_DST_PORT_NOT_FOUND,
- GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
- GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
- GS_FTRACE_STR_NO_ADDL_EXPLN,
- GS_FTRACE_STR_FABRIC_BUSY,
- GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
- GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
- GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
-};
-
-/*
- * Ftrace Request
- */
-struct fcgs_ftrace_req_s {
- u32 revision;
- u16 src_port_tag; /* Source Port tag */
- u16 src_port_len; /* Source Port len */
- union fcgs_port_val_u src_port_val; /* Source Port value */
- u16 dst_port_tag; /* Destination Port tag */
- u16 dst_port_len; /* Destination Port len */
- union fcgs_port_val_u dst_port_val; /* Destination Port value */
- u32 token;
- u8 vendor_id[8]; /* T10 Vendor Identifier */
- u8 vendor_info[8]; /* Vendor specific Info */
- u32 max_hop_cnt; /* Max Hop Count */
-};
-
-/*
- * Path info structure
- */
-struct fcgs_ftrace_path_info_s {
- wwn_t switch_name; /* Switch WWN */
- u32 domain_id;
- wwn_t ingress_port_name; /* Ingress ports wwn */
- u32 ingress_phys_port_num; /* Ingress ports physical port
- * number
- */
- wwn_t egress_port_name; /* Ingress ports wwn */
- u32 egress_phys_port_num; /* Ingress ports physical port
- * number
- */
-};
-
-/*
- * Ftrace Acc Response
- */
-struct fcgs_ftrace_resp_s {
- u32 revision;
- u32 token;
- u8 vendor_id[8]; /* T10 Vendor Identifier */
- u8 vendor_info[8]; /* Vendor specific Info */
- u32 str_rej_reason_code; /* STR Reject Reason Code */
- u32 num_path_info_entries; /* No. of path info entries */
- /*
- * path info entry/entries.
- */
- struct fcgs_ftrace_path_info_s path_info[1];
-
-};
-
-/*
-* Fabric Config Server : FCPing
- */
-
-/*
- * FC Ping Request
- */
-struct fcgs_fcping_req_s {
- u32 revision;
- u16 port_tag;
- u16 port_len; /* Port len */
- union fcgs_port_val_u port_val; /* Port value */
- u32 token;
-};
-
-/*
- * FC Ping Response
- */
-struct fcgs_fcping_resp_s {
- u32 token;
-};
-
-/*
- * Command codes for zone server query.
- */
-enum {
- ZS_GZME = 0x0124, /* Get zone member extended */
-};
-
-/*
- * ZS GZME request
- */
-#define ZS_GZME_ZNAMELEN 32
-struct zs_gzme_req_s {
- u8 znamelen;
- u8 rsvd[3];
- u8 zname[ZS_GZME_ZNAMELEN];
-};
-
-enum zs_mbr_type {
- ZS_MBR_TYPE_PWWN = 1,
- ZS_MBR_TYPE_DOMPORT = 2,
- ZS_MBR_TYPE_PORTID = 3,
- ZS_MBR_TYPE_NWWN = 4,
-};
-
-struct zs_mbr_wwn_s {
- u8 mbr_type;
- u8 rsvd[3];
- wwn_t wwn;
-};
-
-struct zs_query_resp_s {
- u32 nmbrs; /* number of zone members */
- struct zs_mbr_wwn_s mbr[1];
-};
-
-/*
* GMAL Command ( Get ( interconnect Element) Management Address List)
* To retrieve the IP Address of a Switch.
*/
-
#define CT_GMAL_RESP_PREFIX_TELNET "telnet://"
#define CT_GMAL_RESP_PREFIX_HTTP "http://"
@@ -1764,7 +1458,7 @@ struct fcgs_req_s {
/* Accept Response to GMAL */
struct fcgs_gmal_resp_s {
- u32 ms_len; /* Num of entries */
+ __be32 ms_len; /* Num of entries */
u8 ms_ma[256];
};
@@ -1775,9 +1469,6 @@ struct fcgs_gmal_entry_s {
};
/*
- * FDMI
- */
-/*
* FDMI Command Codes
*/
#define FDMI_GRHL 0x0100
@@ -1856,8 +1547,8 @@ enum fdmi_port_attribute_type {
* FDMI attribute
*/
struct fdmi_attr_s {
- u16 type;
- u16 len;
+ __be16 type;
+ __be16 len;
u8 value[1];
};
@@ -1865,7 +1556,7 @@ struct fdmi_attr_s {
* HBA Attribute Block
*/
struct fdmi_hba_attr_s {
- u32 attr_count; /* # of attributes */
+ __be32 attr_count; /* # of attributes */
struct fdmi_attr_s hba_attr; /* n attributes */
};
@@ -1873,15 +1564,15 @@ struct fdmi_hba_attr_s {
* Registered Port List
*/
struct fdmi_port_list_s {
- u32 num_ports; /* number Of Port Entries */
- wwn_t port_entry; /* one or more */
+ __be32 num_ports; /* number Of Port Entries */
+ wwn_t port_entry; /* one or more */
};
/*
* Port Attribute Block
*/
struct fdmi_port_attr_s {
- u32 attr_count; /* # of attributes */
+ __be32 attr_count; /* # of attributes */
struct fdmi_attr_s port_attr; /* n attributes */
};
@@ -1889,7 +1580,7 @@ struct fdmi_port_attr_s {
* FDMI Register HBA Attributes
*/
struct fdmi_rhba_s {
- wwn_t hba_id; /* HBA Identifier */
+ wwn_t hba_id; /* HBA Identifier */
struct fdmi_port_list_s port_list; /* Registered Port List */
struct fdmi_hba_attr_s hba_attr_blk; /* HBA attribute block */
};
@@ -1898,8 +1589,8 @@ struct fdmi_rhba_s {
* FDMI Register Port
*/
struct fdmi_rprt_s {
- wwn_t hba_id; /* HBA Identifier */
- wwn_t port_name; /* Port wwn */
+ wwn_t hba_id; /* HBA Identifier */
+ wwn_t port_name; /* Port wwn */
struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */
};
@@ -1907,7 +1598,7 @@ struct fdmi_rprt_s {
* FDMI Register Port Attributes
*/
struct fdmi_rpa_s {
- wwn_t port_name; /* port wwn */
+ wwn_t port_name; /* port wwn */
struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */
};
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index 9c725314b51..b7e25345165 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -18,16 +18,16 @@
* fcbuild.c - FC link service frame building and parsing routines
*/
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
#include "bfa_fcbuild.h"
/*
* static build functions
*/
static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id);
+ __be16 ox_id);
static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id);
+ __be16 ox_id);
static struct fchs_s fc_els_req_tmpl;
static struct fchs_s fc_els_rsp_tmpl;
static struct fchs_s fc_bls_req_tmpl;
@@ -48,7 +48,7 @@ fcbuild_init(void)
fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
fc_els_req_tmpl.type = FC_TYPE_ELS;
fc_els_req_tmpl.f_ctl =
- bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
+ bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
FCTL_SI_XFER);
fc_els_req_tmpl.rx_id = FC_RXID_ANY;
@@ -59,7 +59,7 @@ fcbuild_init(void)
fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
fc_els_rsp_tmpl.type = FC_TYPE_ELS;
fc_els_rsp_tmpl.f_ctl =
- bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+ bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
FCTL_END_SEQ | FCTL_SI_XFER);
fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
@@ -68,7 +68,7 @@ fcbuild_init(void)
*/
fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
fc_bls_req_tmpl.type = FC_TYPE_BLS;
- fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
+ fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
/*
@@ -78,7 +78,7 @@ fcbuild_init(void)
fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
fc_bls_rsp_tmpl.f_ctl =
- bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+ bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
FCTL_END_SEQ | FCTL_SI_XFER);
fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
@@ -129,7 +129,7 @@ fcbuild_init(void)
fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
fcp_fchs_tmpl.type = FC_TYPE_FCP;
fcp_fchs_tmpl.f_ctl =
- bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
+ bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
fcp_fchs_tmpl.seq_id = 1;
fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
}
@@ -143,7 +143,7 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
fchs->type = FC_TYPE_SERVICES;
fchs->f_ctl =
- bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
+ bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
FCTL_SI_XFER);
fchs->rx_id = FC_RXID_ANY;
fchs->d_id = (d_id);
@@ -157,7 +157,7 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
}
void
-fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
{
memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
fchs->d_id = (d_id);
@@ -166,7 +166,7 @@ fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
}
static void
-fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
{
memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
fchs->d_id = d_id;
@@ -196,7 +196,7 @@ fc_els_rsp_parse(struct fchs_s *fchs, int len)
}
static void
-fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
{
memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
fchs->d_id = d_id;
@@ -206,7 +206,7 @@ fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
static u16
fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name,
+ __be16 ox_id, wwn_t port_name, wwn_t node_name,
u16 pdu_size, u8 els_code)
{
struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
@@ -232,8 +232,8 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
u8 set_npiv, u8 set_auth, u16 local_bb_credits)
{
- u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT);
- u32 *vvl_info;
+ u32 d_id = bfa_hton3b(FC_FABRIC_PORT);
+ __be32 *vvl_info;
memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
@@ -267,7 +267,7 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
u16
fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name,
+ __be16 ox_id, wwn_t port_name, wwn_t node_name,
u16 pdu_size, u16 local_bb_credits)
{
u32 d_id = 0;
@@ -289,7 +289,7 @@ u16
fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
{
- u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT);
+ u32 d_id = bfa_hton3b(FC_FABRIC_PORT);
memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
@@ -392,7 +392,7 @@ fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16
fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
- u16 ox_id, enum bfa_lport_role role)
+ __be16 ox_id, enum bfa_lport_role role)
{
struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
@@ -456,9 +456,9 @@ fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
return sizeof(struct fc_logo_s);
}
-static u16
+static u16
fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
- u32 s_id, u16 ox_id, wwn_t port_name,
+ u32 s_id, __be16 ox_id, wwn_t port_name,
wwn_t node_name, u8 els_code)
{
memset(adisc, '\0', sizeof(struct fc_adisc_s));
@@ -480,7 +480,7 @@ fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
u16
fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
- u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name)
+ u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name)
{
return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
node_name, FC_ELS_ADISC);
@@ -488,7 +488,7 @@ fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
u16
fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
- u32 s_id, u16 ox_id, wwn_t port_name,
+ u32 s_id, __be16 ox_id, wwn_t port_name,
wwn_t node_name)
{
return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
@@ -592,7 +592,7 @@ fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,
u16
fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
- u16 ox_id)
+ __be16 ox_id)
{
struct fc_els_cmd_s *acc = pld;
@@ -606,7 +606,7 @@ fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16
fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
- u32 s_id, u16 ox_id, u8 reason_code,
+ u32 s_id, __be16 ox_id, u8 reason_code,
u8 reason_code_expl)
{
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
@@ -622,7 +622,7 @@ fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
u16
fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
- u32 s_id, u16 ox_id, u16 rx_id)
+ u32 s_id, __be16 ox_id, u16 rx_id)
{
fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
@@ -638,7 +638,7 @@ fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
u16
fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
- u32 s_id, u16 ox_id)
+ u32 s_id, __be16 ox_id)
{
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
@@ -666,7 +666,7 @@ fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
u16
fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
- u32 d_id, u32 s_id, u16 ox_id, int num_pages)
+ u32 d_id, u32 s_id, __be16 ox_id, int num_pages)
{
int page;
@@ -690,7 +690,7 @@ fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
u16
fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
- u32 s_id, u16 ox_id, int num_pages)
+ u32 s_id, __be16 ox_id, int num_pages)
{
int page;
@@ -728,7 +728,7 @@ fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
u16
fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
- u32 s_id, u16 ox_id, u32 data_format,
+ u32 s_id, __be16 ox_id, u32 data_format,
struct fc_rnid_common_id_data_s *common_id_data,
struct fc_rnid_general_topology_data_s *gen_topo_data)
{
@@ -770,10 +770,10 @@ u16
fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
u32 s_id, u32 *pid_list, u16 npids)
{
- u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id));
+ u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id));
int i = 0;
- fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0);
+ fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0);
memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
@@ -788,7 +788,7 @@ fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
u16
fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
- u32 d_id, u32 s_id, u16 ox_id,
+ u32 d_id, u32 s_id, __be16 ox_id,
struct fc_rpsc_speed_info_s *oper_speed)
{
memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
@@ -807,11 +807,6 @@ fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
return sizeof(struct fc_rpsc_acc_s);
}
-/*
- * TBD -
- * . get rid of unnecessary memsets
- */
-
u16
fc_logo_rsp_parse(struct fchs_s *fchs, int len)
{
@@ -995,7 +990,7 @@ fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
}
u16
-fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id,
u32 reason_code, u32 reason_expl)
{
struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
@@ -1045,7 +1040,7 @@ fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
@@ -1061,7 +1056,7 @@ fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
@@ -1077,7 +1072,7 @@ fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
@@ -1104,7 +1099,7 @@ u16
fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
u8 set_br_reg, u32 s_id, u16 ox_id)
{
- u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
+ u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
fc_els_req_build(fchs, d_id, s_id, ox_id);
@@ -1121,7 +1116,7 @@ u16
fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
u32 s_id, u16 ox_id)
{
- u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
+ u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
u16 payldlen;
fc_els_req_build(fchs, d_id, s_id, ox_id);
@@ -1143,7 +1138,7 @@ fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
- u32 type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 type_value, d_id = bfa_hton3b(FC_NAME_SERVER);
u8 index;
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1167,7 +1162,7 @@ fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
@@ -1187,7 +1182,7 @@ fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
@@ -1209,7 +1204,7 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rspnid_req_s *rspnid =
(struct fcgs_rspnid_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
@@ -1229,7 +1224,7 @@ fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1249,7 +1244,7 @@ fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
@@ -1267,7 +1262,7 @@ fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
@@ -1286,7 +1281,7 @@ fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rcsid_req_s *rcsid =
(struct fcgs_rcsid_req_s *) (cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
@@ -1304,7 +1299,7 @@ fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
@@ -1321,7 +1316,7 @@ fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
@@ -1341,7 +1336,7 @@ fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+ u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
@@ -1356,7 +1351,7 @@ void
fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
{
u8 index;
- u32 *ptr = (u32 *) bit_mask;
+ __be32 *ptr = (__be32 *) bit_mask;
u32 type_value;
/*
@@ -1377,7 +1372,7 @@ fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+ u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
@@ -1397,7 +1392,7 @@ fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
{
struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
- u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+ u32 d_id = bfa_hton3b(FC_MGMT_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index 73abd02e53c..ece51ec7620 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -21,7 +21,7 @@
#ifndef __FCBUILD_H__
#define __FCBUILD_H__
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
#include "bfa_fc.h"
#include "bfa_defs_fcs.h"
@@ -138,7 +138,7 @@ u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, u32 s_id,
u16 pdu_size);
u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
- u32 s_id, u16 ox_id,
+ u32 s_id, __be16 ox_id,
wwn_t port_name, wwn_t node_name,
u16 pdu_size,
u16 local_bb_credits);
@@ -186,7 +186,7 @@ u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
u16 pdu_size);
u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
- u32 d_id, u32 s_id, u16 ox_id, wwn_t port_name,
+ u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,
wwn_t node_name);
enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
@@ -196,20 +196,20 @@ enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
wwn_t port_name, wwn_t node_name);
u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
- u32 d_id, u32 s_id, u16 ox_id,
+ u32 d_id, u32 s_id, __be16 ox_id,
wwn_t port_name, wwn_t node_name);
u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
- u32 d_id, u32 s_id, u16 ox_id,
+ u32 d_id, u32 s_id, __be16 ox_id,
u8 reason_code, u8 reason_code_expl);
u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
- u32 d_id, u32 s_id, u16 ox_id);
+ u32 d_id, u32 s_id, __be16 ox_id);
u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
u32 s_id, u16 ox_id);
enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
- u32 s_id, u16 ox_id,
+ u32 s_id, __be16 ox_id,
enum bfa_lport_role role);
u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
@@ -218,7 +218,7 @@ u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
u16 fc_rnid_acc_build(struct fchs_s *fchs,
struct fc_rnid_acc_s *rnid_acc, u32 d_id, u32 s_id,
- u16 ox_id, u32 data_format,
+ __be16 ox_id, u32 data_format,
struct fc_rnid_common_id_data_s *common_id_data,
struct fc_rnid_general_topology_data_s *gen_topo_data);
@@ -228,7 +228,7 @@ u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
u32 d_id, u32 s_id, u16 ox_id);
u16 fc_rpsc_acc_build(struct fchs_s *fchs,
struct fc_rpsc_acc_s *rpsc_acc, u32 d_id, u32 s_id,
- u16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);
+ __be16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);
u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
u8 fc4_type);
@@ -251,7 +251,7 @@ u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
u32 s_id, u16 ox_id, wwn_t port_name);
u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
- u32 s_id, u16 ox_id);
+ u32 s_id, __be16 ox_id);
u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u16 cmd_code);
@@ -261,7 +261,7 @@ u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);
void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id);
+ __be16 ox_id);
enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len);
@@ -274,15 +274,15 @@ enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
wwn_t port_name);
u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
- u32 s_id, u16 ox_id, u16 rx_id);
+ u32 s_id, __be16 ox_id, u16 rx_id);
int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
- u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+ u32 d_id, u32 s_id, __be16 ox_id, int num_pages);
u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
- u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+ u32 d_id, u32 s_id, __be16 ox_id, int num_pages);
u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
@@ -304,7 +304,7 @@ u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, u32 reason_code, u32 reason_expl);
+ __be16 ox_id, u32 reason_code, u32 reason_expl);
u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
u32 port_id);
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 135c4427801..9c410b21db6 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -15,17 +15,12 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_modules.h"
-#include "bfa_cb_ioim.h"
BFA_TRC_FILE(HAL, FCPIM);
BFA_MODULE(fcpim);
-
-#define bfa_fcpim_add_iostats(__l, __r, __stats) \
- (__l->__stats += __r->__stats)
-
-
/*
* BFA ITNIM Related definitions
*/
@@ -37,12 +32,12 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
#define bfa_fcpim_additn(__itnim) \
list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
#define bfa_fcpim_delitn(__itnim) do { \
- bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \
+ WARN_ON(!bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \
bfa_itnim_update_del_itn_stats(__itnim); \
list_del(&(__itnim)->qe); \
- bfa_assert(list_empty(&(__itnim)->io_q)); \
- bfa_assert(list_empty(&(__itnim)->io_cleanup_q)); \
- bfa_assert(list_empty(&(__itnim)->pending_q)); \
+ WARN_ON(!list_empty(&(__itnim)->io_q)); \
+ WARN_ON(!list_empty(&(__itnim)->io_cleanup_q)); \
+ WARN_ON(!list_empty(&(__itnim)->pending_q)); \
} while (0)
#define bfa_itnim_online_cb(__itnim) do { \
@@ -73,10 +68,8 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
} while (0)
/*
- * bfa_itnim_sm BFA itnim state machine
+ * itnim state machine event
*/
-
-
enum bfa_itnim_event {
BFA_ITNIM_SM_CREATE = 1, /* itnim is created */
BFA_ITNIM_SM_ONLINE = 2, /* itnim is online */
@@ -107,9 +100,6 @@ enum bfa_itnim_event {
if ((__fcpim)->profile_start) \
(__fcpim)->profile_start(__ioim); \
} while (0)
-/*
- * hal_ioim_sm
- */
/*
* IO state machine events
@@ -221,8 +211,7 @@ static void bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
* forward declaration for BFA IOIM functions
*/
static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
-static bfa_boolean_t bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
-static void bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
+static bfa_boolean_t bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim);
static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
@@ -232,7 +221,6 @@ static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
static bfa_boolean_t bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
-
/*
* forward declaration of BFA IO state machine
*/
@@ -260,14 +248,13 @@ static void bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
enum bfa_ioim_event event);
static void bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim,
enum bfa_ioim_event event);
-
/*
* forward declaration for BFA TSKIM functions
*/
static void __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
static void __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
- lun_t lun);
+ struct scsi_lun lun);
static void bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
static void bfa_tskim_cleanp_comp(void *tskim_cbarg);
static void bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
@@ -275,7 +262,6 @@ static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
static void bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
-
/*
* forward declaration of BFA TSKIM state machine
*/
@@ -293,13 +279,12 @@ static void bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
enum bfa_tskim_event event);
static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
enum bfa_tskim_event event);
-
/*
- * hal_fcpim_mod BFA FCP Initiator Mode module
+ * BFA FCP Initiator Mode module
*/
/*
- * Compute and return memory needed by FCP(im) module.
+ * Compute and return memory needed by FCP(im) module.
*/
static void
bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
@@ -357,10 +342,6 @@ bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
static void
bfa_fcpim_detach(struct bfa_s *bfa)
{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-
- bfa_ioim_detach(fcpim);
- bfa_tskim_detach(fcpim);
}
static void
@@ -387,56 +368,6 @@ bfa_fcpim_iocdisable(struct bfa_s *bfa)
}
void
-bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
- struct bfa_itnim_iostats_s *rstats)
-{
- bfa_fcpim_add_iostats(lstats, rstats, total_ios);
- bfa_fcpim_add_iostats(lstats, rstats, qresumes);
- bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
- bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
- bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
- bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
- bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
- bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
- bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
- bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
- bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
- bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
- bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
- bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
- bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
- bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
- bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
- bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
- bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
- bfa_fcpim_add_iostats(lstats, rstats, onlines);
- bfa_fcpim_add_iostats(lstats, rstats, offlines);
- bfa_fcpim_add_iostats(lstats, rstats, creates);
- bfa_fcpim_add_iostats(lstats, rstats, deletes);
- bfa_fcpim_add_iostats(lstats, rstats, create_comps);
- bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
- bfa_fcpim_add_iostats(lstats, rstats, sler_events);
- bfa_fcpim_add_iostats(lstats, rstats, fw_create);
- bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
- bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
- bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
- bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
- bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
- bfa_fcpim_add_iostats(lstats, rstats, tm_success);
- bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
- bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
- bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
- bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
- bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
- bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
- bfa_fcpim_add_iostats(lstats, rstats, io_comps);
- bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
- bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
- bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
- bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
-}
-
-void
bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
{
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
@@ -454,128 +385,6 @@ bfa_fcpim_path_tov_get(struct bfa_s *bfa)
return fcpim->path_tov / 1000;
}
-bfa_status_t
-bfa_fcpim_port_iostats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *stats,
- u8 lp_tag)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct list_head *qe, *qen;
- struct bfa_itnim_s *itnim;
-
- /* accumulate IO stats from itnim */
- memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
- list_for_each_safe(qe, qen, &fcpim->itnim_q) {
- itnim = (struct bfa_itnim_s *) qe;
- if (itnim->rport->rport_info.lp_tag != lp_tag)
- continue;
- bfa_fcpim_add_stats(stats, &(itnim->stats));
- }
- return BFA_STATUS_OK;
-}
-bfa_status_t
-bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *modstats)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct list_head *qe, *qen;
- struct bfa_itnim_s *itnim;
-
- /* accumulate IO stats from itnim */
- memset(modstats, 0, sizeof(struct bfa_itnim_iostats_s));
- list_for_each_safe(qe, qen, &fcpim->itnim_q) {
- itnim = (struct bfa_itnim_s *) qe;
- bfa_fcpim_add_stats(modstats, &(itnim->stats));
- }
- return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
- struct bfa_fcpim_del_itn_stats_s *modstats)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-
- *modstats = fcpim->del_itn_stats;
-
- return BFA_STATUS_OK;
-}
-
-
-bfa_status_t
-bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time)
-{
- struct bfa_itnim_s *itnim;
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct list_head *qe, *qen;
-
- /* accumulate IO stats from itnim */
- list_for_each_safe(qe, qen, &fcpim->itnim_q) {
- itnim = (struct bfa_itnim_s *) qe;
- bfa_itnim_clear_stats(itnim);
- }
- fcpim->io_profile = BFA_TRUE;
- fcpim->io_profile_start_time = time;
- fcpim->profile_comp = bfa_ioim_profile_comp;
- fcpim->profile_start = bfa_ioim_profile_start;
-
- return BFA_STATUS_OK;
-}
-bfa_status_t
-bfa_fcpim_profile_off(struct bfa_s *bfa)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- fcpim->io_profile = BFA_FALSE;
- fcpim->io_profile_start_time = 0;
- fcpim->profile_comp = NULL;
- fcpim->profile_start = NULL;
- return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct list_head *qe, *qen;
- struct bfa_itnim_s *itnim;
-
- /* clear IO stats from all active itnims */
- list_for_each_safe(qe, qen, &fcpim->itnim_q) {
- itnim = (struct bfa_itnim_s *) qe;
- if (itnim->rport->rport_info.lp_tag != lp_tag)
- continue;
- bfa_itnim_clear_stats(itnim);
- }
- return BFA_STATUS_OK;
-
-}
-
-bfa_status_t
-bfa_fcpim_clr_modstats(struct bfa_s *bfa)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct list_head *qe, *qen;
- struct bfa_itnim_s *itnim;
-
- /* clear IO stats from all active itnims */
- list_for_each_safe(qe, qen, &fcpim->itnim_q) {
- itnim = (struct bfa_itnim_s *) qe;
- bfa_itnim_clear_stats(itnim);
- }
- memset(&fcpim->del_itn_stats, 0,
- sizeof(struct bfa_fcpim_del_itn_stats_s));
-
- return BFA_STATUS_OK;
-}
-
-void
-bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-
- bfa_assert(q_depth <= BFA_IOCFC_QDEPTH_MAX);
-
- fcpim->q_depth = q_depth;
-}
-
u16
bfa_fcpim_qdepth_get(struct bfa_s *bfa)
{
@@ -584,32 +393,12 @@ 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;
-}
-
-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;
-}
-
-
-
/*
* BFA ITNIM module state machine functions
*/
/*
- * Beginning/unallocated state - no events expected.
+ * Beginning/unallocated state - no events expected.
*/
static void
bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -630,7 +419,7 @@ bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
}
/*
- * Beginning state, only online event expected.
+ * Beginning state, only online event expected.
*/
static void
bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -733,7 +522,7 @@ bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
}
/*
- * Waiting for itnim create response from firmware, a delete is pending.
+ * Waiting for itnim create response from firmware, a delete is pending.
*/
static void
bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
@@ -761,7 +550,7 @@ bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
}
/*
- * Online state - normal parking state.
+ * Online state - normal parking state.
*/
static void
bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -803,7 +592,7 @@ bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
}
/*
- * Second level error recovery need.
+ * Second level error recovery need.
*/
static void
bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -834,7 +623,7 @@ bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
}
/*
- * Going offline. Waiting for active IO cleanup.
+ * Going offline. Waiting for active IO cleanup.
*/
static void
bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
@@ -871,7 +660,7 @@ bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
}
/*
- * Deleting itnim. Waiting for active IO cleanup.
+ * Deleting itnim. Waiting for active IO cleanup.
*/
static void
bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
@@ -956,7 +745,7 @@ bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
}
/*
- * Offline state.
+ * Offline state.
*/
static void
bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -987,9 +776,6 @@ bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
}
}
-/*
- * IOC h/w failed state.
- */
static void
bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event)
@@ -1024,7 +810,7 @@ bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
}
/*
- * Itnim is deleted, waiting for firmware response to delete.
+ * Itnim is deleted, waiting for firmware response to delete.
*/
static void
bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -1069,7 +855,7 @@ bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
}
/*
- * Initiate cleanup of all IOs on an IOC failure.
+ * Initiate cleanup of all IOs on an IOC failure.
*/
static void
bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
@@ -1103,7 +889,7 @@ bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
}
/*
- * IO cleanup completion
+ * IO cleanup completion
*/
static void
bfa_itnim_cleanp_comp(void *itnim_cbarg)
@@ -1115,7 +901,7 @@ bfa_itnim_cleanp_comp(void *itnim_cbarg)
}
/*
- * Initiate cleanup of all IOs.
+ * Initiate cleanup of all IOs.
*/
static void
bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
@@ -1187,9 +973,6 @@ bfa_itnim_qresume(void *cbarg)
bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
}
-
-
-
/*
* bfa_itnim_public
*/
@@ -1401,7 +1184,7 @@ bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
if (itnim->fcpim->path_tov > 0) {
itnim->iotov_active = BFA_TRUE;
- bfa_assert(bfa_itnim_hold_io(itnim));
+ WARN_ON(!bfa_itnim_hold_io(itnim));
bfa_timer_start(itnim->bfa, &itnim->timer,
bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
}
@@ -1457,14 +1240,12 @@ bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns;
}
-
-
/*
- * bfa_itnim_public
+ * bfa_itnim_public
*/
/*
- * Itnim interrupt processing.
+ * Itnim interrupt processing.
*/
void
bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
@@ -1481,7 +1262,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
case BFI_ITNIM_I2H_CREATE_RSP:
itnim = BFA_ITNIM_FROM_TAG(fcpim,
msg.create_rsp->bfa_handle);
- bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+ WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
bfa_stats(itnim, create_comps);
bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
break;
@@ -1489,7 +1270,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
case BFI_ITNIM_I2H_DELETE_RSP:
itnim = BFA_ITNIM_FROM_TAG(fcpim,
msg.delete_rsp->bfa_handle);
- bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+ WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
bfa_stats(itnim, delete_comps);
bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
break;
@@ -1503,14 +1284,12 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
default:
bfa_trc(bfa, m->mhdr.msg_id);
- bfa_assert(0);
+ WARN_ON(1);
}
}
-
-
/*
- * bfa_itnim_api
+ * bfa_itnim_api
*/
struct bfa_itnim_s *
@@ -1520,7 +1299,7 @@ bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
struct bfa_itnim_s *itnim;
itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
- bfa_assert(itnim->rport == rport);
+ WARN_ON(itnim->rport != rport);
itnim->ditn = ditn;
@@ -1568,31 +1347,6 @@ bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));
}
-bfa_status_t
-bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
- struct bfa_itnim_ioprofile_s *ioprofile)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
- if (!fcpim->io_profile)
- return BFA_STATUS_IOPROFILE_OFF;
-
- itnim->ioprofile.index = BFA_IOBUCKET_MAX;
- itnim->ioprofile.io_profile_start_time =
- bfa_io_profile_start_time(itnim->bfa);
- itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;
- itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;
- *ioprofile = itnim->ioprofile;
-
- return BFA_STATUS_OK;
-}
-
-void
-bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
- struct bfa_itnim_iostats_s *stats)
-{
- *stats = itnim->stats;
-}
-
void
bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
{
@@ -1608,14 +1362,11 @@ bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
*/
/*
- * IO is not started (unallocated).
+ * IO is not started (unallocated).
*/
static void
bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_trc_fp(ioim->bfa, event);
-
switch (event) {
case BFA_IOIM_SM_START:
if (!bfa_itnim_is_online(ioim->itnim)) {
@@ -1635,7 +1386,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
if (ioim->nsges > BFI_SGE_INLINE) {
- if (!bfa_ioim_sge_setup(ioim)) {
+ if (!bfa_ioim_sgpg_alloc(ioim)) {
bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
return;
}
@@ -1662,7 +1413,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
* requests immediately.
*/
bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
+ WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
__bfa_cb_ioim_abort, ioim);
break;
@@ -1673,7 +1424,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
/*
- * IO is waiting for SG pages.
+ * IO is waiting for SG pages.
*/
static void
bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -1720,14 +1471,11 @@ bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
/*
- * IO is active.
+ * IO is active.
*/
static void
bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_trc_fp(ioim->bfa, event);
-
switch (event) {
case BFA_IOIM_SM_COMP_GOOD:
bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
@@ -1786,8 +1534,8 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
break;
case BFA_IOIM_SM_SQRETRY:
- if (bfa_ioim_get_iotag(ioim) != BFA_TRUE) {
- /* max retry completed free IO */
+ if (bfa_ioim_maxretry_reached(ioim)) {
+ /* max retry reached, free IO */
bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
bfa_ioim_move_to_comp_q(ioim);
bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
@@ -1804,17 +1552,15 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
/*
-* IO is retried with new tag.
-*/
+ * IO is retried with new tag.
+ */
static void
bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_trc_fp(ioim->bfa, event);
-
switch (event) {
case BFA_IOIM_SM_FREE:
/* abts and rrq done. Now retry the IO with new tag */
+ bfa_ioim_update_iotag(ioim);
if (!bfa_ioim_send_ioreq(ioim)) {
bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
break;
@@ -1858,7 +1604,7 @@ bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
/*
- * IO is being aborted, waiting for completion from firmware.
+ * IO is being aborted, waiting for completion from firmware.
*/
static void
bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -1894,7 +1640,7 @@ bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
break;
case BFA_IOIM_SM_CLEANUP:
- bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+ WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);
ioim->iosp->abort_explicit = BFA_FALSE;
if (bfa_ioim_send_abort(ioim))
@@ -1981,7 +1727,7 @@ bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
/*
- * IO is waiting for room in request CQ
+ * IO is waiting for room in request CQ
*/
static void
bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -2025,7 +1771,7 @@ bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
/*
- * Active IO is being aborted, waiting for room in request CQ.
+ * Active IO is being aborted, waiting for room in request CQ.
*/
static void
bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -2040,7 +1786,7 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
break;
case BFA_IOIM_SM_CLEANUP:
- bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+ WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);
ioim->iosp->abort_explicit = BFA_FALSE;
bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
break;
@@ -2076,7 +1822,7 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
/*
- * Active IO is being cleaned up, waiting for room in request CQ.
+ * Active IO is being cleaned up, waiting for room in request CQ.
*/
static void
bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -2131,9 +1877,6 @@ bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
static void
bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_trc_fp(ioim->bfa, event);
-
switch (event) {
case BFA_IOIM_SM_HCB:
bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
@@ -2213,11 +1956,6 @@ bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
}
-
-/*
- * hal_ioim_private
- */
-
static void
__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
{
@@ -2323,7 +2061,7 @@ bfa_ioim_sgpg_alloced(void *cbarg)
ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
- bfa_ioim_sgpg_setup(ioim);
+ ioim->sgpg = bfa_q_first(&ioim->sgpg_q);
bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
}
@@ -2335,13 +2073,16 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
{
struct bfa_itnim_s *itnim = ioim->itnim;
struct bfi_ioim_req_s *m;
- static struct fcp_cmnd_s cmnd_z0 = { 0 };
- struct bfi_sge_s *sge;
+ static struct fcp_cmnd_s cmnd_z0 = { { { 0 } } };
+ struct bfi_sge_s *sge, *sgpge;
u32 pgdlen = 0;
u32 fcp_dl;
u64 addr;
struct scatterlist *sg;
+ struct bfa_sgpg_s *sgpg;
struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
+ u32 i, sge_id, pgcumsz;
+ enum dma_data_direction dmadir;
/*
* check for room in queue to send request now
@@ -2359,22 +2100,61 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
*/
m->io_tag = cpu_to_be16(ioim->iotag);
m->rport_hdl = ioim->itnim->rport->fw_handle;
- m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
+ m->io_timeout = 0;
- /*
- * build inline IO SG element here
- */
sge = &m->sges[0];
- if (ioim->nsges) {
- sg = (struct scatterlist *)scsi_sglist(cmnd);
- addr = bfa_os_sgaddr(sg_dma_address(sg));
- sge->sga = *(union bfi_addr_u *) &addr;
- pgdlen = sg_dma_len(sg);
- sge->sg_len = pgdlen;
- sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
+ sgpg = ioim->sgpg;
+ sge_id = 0;
+ sgpge = NULL;
+ pgcumsz = 0;
+ scsi_for_each_sg(cmnd, sg, ioim->nsges, i) {
+ if (i == 0) {
+ /* build inline IO SG element */
+ addr = bfa_sgaddr_le(sg_dma_address(sg));
+ sge->sga = *(union bfi_addr_u *) &addr;
+ pgdlen = sg_dma_len(sg);
+ sge->sg_len = pgdlen;
+ sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
- bfa_sge_to_be(sge);
- sge++;
+ bfa_sge_to_be(sge);
+ sge++;
+ } else {
+ if (sge_id == 0)
+ sgpge = sgpg->sgpg->sges;
+
+ addr = bfa_sgaddr_le(sg_dma_address(sg));
+ sgpge->sga = *(union bfi_addr_u *) &addr;
+ sgpge->sg_len = sg_dma_len(sg);
+ pgcumsz += sgpge->sg_len;
+
+ /* set flags */
+ if (i < (ioim->nsges - 1) &&
+ sge_id < (BFI_SGPG_DATA_SGES - 1))
+ sgpge->flags = BFI_SGE_DATA;
+ else if (i < (ioim->nsges - 1))
+ sgpge->flags = BFI_SGE_DATA_CPL;
+ else
+ sgpge->flags = BFI_SGE_DATA_LAST;
+
+ bfa_sge_to_le(sgpge);
+
+ sgpge++;
+ if (i == (ioim->nsges - 1)) {
+ sgpge->flags = BFI_SGE_PGDLEN;
+ sgpge->sga.a32.addr_lo = 0;
+ sgpge->sga.a32.addr_hi = 0;
+ sgpge->sg_len = pgcumsz;
+ bfa_sge_to_le(sgpge);
+ } else if (++sge_id == BFI_SGPG_DATA_SGES) {
+ sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
+ sgpge->flags = BFI_SGE_LINK;
+ sgpge->sga = sgpg->sgpg_pa;
+ sgpge->sg_len = pgcumsz;
+ bfa_sge_to_le(sgpge);
+ sge_id = 0;
+ pgcumsz = 0;
+ }
+ }
}
if (ioim->nsges > BFI_SGE_INLINE) {
@@ -2391,10 +2171,17 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
* set up I/O command parameters
*/
m->cmnd = cmnd_z0;
- m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
- m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
- m->cmnd.cdb = *(scsi_cdb_t *)bfa_cb_ioim_get_cdb(ioim->dio);
- fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
+ int_to_scsilun(cmnd->device->lun, &m->cmnd.lun);
+ dmadir = cmnd->sc_data_direction;
+ if (dmadir == DMA_TO_DEVICE)
+ m->cmnd.iodir = FCP_IODIR_WRITE;
+ else if (dmadir == DMA_FROM_DEVICE)
+ m->cmnd.iodir = FCP_IODIR_READ;
+ else
+ m->cmnd.iodir = FCP_IODIR_NONE;
+
+ m->cmnd.cdb = *(struct scsi_cdb_s *) cmnd->cmnd;
+ fcp_dl = scsi_bufflen(cmnd);
m->cmnd.fcp_dl = cpu_to_be32(fcp_dl);
/*
@@ -2418,28 +2205,9 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
}
if (itnim->seq_rec ||
- (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
+ (scsi_bufflen(cmnd) & (sizeof(u32) - 1)))
bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
-#ifdef IOIM_ADVANCED
- m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
- m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
- m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
-
- /*
- * Handle large CDB (>16 bytes).
- */
- m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
- FCP_CMND_CDB_LEN) / sizeof(u32);
- if (m->cmnd.addl_cdb_len) {
- memcpy(&m->cmnd.cdb + 1, (scsi_cdb_t *)
- bfa_cb_ioim_get_cdb(ioim->dio) + 1,
- m->cmnd.addl_cdb_len * sizeof(u32));
- fcp_cmnd_fcpdl(&m->cmnd) =
- cpu_to_be32(bfa_cb_ioim_get_size(ioim->dio));
- }
-#endif
-
/*
* queue I/O message to firmware
*/
@@ -2452,11 +2220,11 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
* at queuing time.
*/
static bfa_boolean_t
-bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
+bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim)
{
u16 nsgpgs;
- bfa_assert(ioim->nsges > BFI_SGE_INLINE);
+ WARN_ON(ioim->nsges <= BFI_SGE_INLINE);
/*
* allocate SG pages needed
@@ -2472,73 +2240,11 @@ bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
}
ioim->nsgpgs = nsgpgs;
- bfa_ioim_sgpg_setup(ioim);
+ ioim->sgpg = bfa_q_first(&ioim->sgpg_q);
return BFA_TRUE;
}
-static void
-bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
-{
- int sgeid, nsges, i;
- struct bfi_sge_s *sge;
- struct bfa_sgpg_s *sgpg;
- u32 pgcumsz;
- u64 addr;
- struct scatterlist *sg;
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
-
- sgeid = BFI_SGE_INLINE;
- ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
-
- sg = scsi_sglist(cmnd);
- sg = sg_next(sg);
-
- do {
- sge = sgpg->sgpg->sges;
- nsges = ioim->nsges - sgeid;
- if (nsges > BFI_SGPG_DATA_SGES)
- nsges = BFI_SGPG_DATA_SGES;
-
- pgcumsz = 0;
- for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
- addr = bfa_os_sgaddr(sg_dma_address(sg));
- sge->sga = *(union bfi_addr_u *) &addr;
- sge->sg_len = sg_dma_len(sg);
- pgcumsz += sge->sg_len;
-
- /*
- * set flags
- */
- if (i < (nsges - 1))
- sge->flags = BFI_SGE_DATA;
- else if (sgeid < (ioim->nsges - 1))
- sge->flags = BFI_SGE_DATA_CPL;
- else
- sge->flags = BFI_SGE_DATA_LAST;
-
- bfa_sge_to_le(sge);
- }
-
- sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
-
- /*
- * set the link element of each page
- */
- if (sgeid == ioim->nsges) {
- sge->flags = BFI_SGE_PGDLEN;
- sge->sga.a32.addr_lo = 0;
- sge->sga.a32.addr_hi = 0;
- } else {
- sge->flags = BFI_SGE_LINK;
- sge->sga = sgpg->sgpg_pa;
- }
- sge->sg_len = pgcumsz;
-
- bfa_sge_to_le(sge);
- } while (sgeid < ioim->nsges);
-}
-
/*
* Send I/O abort request to firmware.
*/
@@ -2605,7 +2311,7 @@ bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
}
bfa_itnim_iodone(ioim->itnim);
} else
- bfa_tskim_iodone(ioim->iosp->tskim);
+ bfa_wc_down(&ioim->iosp->tskim->wc);
}
static bfa_boolean_t
@@ -2623,9 +2329,6 @@ bfa_ioim_is_abortable(struct bfa_ioim_s *ioim)
return BFA_TRUE;
}
-/*
- * or after the link comes back.
- */
void
bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
{
@@ -2653,11 +2356,6 @@ bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
}
-
-/*
- * hal_ioim_friend
- */
-
/*
* Memory allocation and initialization.
*/
@@ -2722,14 +2420,6 @@ bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
}
}
-/*
- * Driver detach time call.
- */
-void
-bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
-}
-
void
bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
{
@@ -2742,7 +2432,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
iotag = be16_to_cpu(rsp->io_tag);
ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
- bfa_assert(ioim->iotag == iotag);
+ WARN_ON(ioim->iotag != iotag);
bfa_trc(ioim->bfa, ioim->iotag);
bfa_trc(ioim->bfa, rsp->io_status);
@@ -2773,13 +2463,13 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
case BFI_IOIM_STS_PROTO_ERR:
bfa_stats(ioim->itnim, iocom_proto_err);
- bfa_assert(rsp->reuse_io_tag);
+ WARN_ON(!rsp->reuse_io_tag);
evt = BFA_IOIM_SM_COMP;
break;
case BFI_IOIM_STS_SQER_NEEDED:
bfa_stats(ioim->itnim, iocom_sqer_needed);
- bfa_assert(rsp->reuse_io_tag == 0);
+ WARN_ON(rsp->reuse_io_tag != 0);
evt = BFA_IOIM_SM_SQRETRY;
break;
@@ -2808,7 +2498,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
}
bfa_sm_send_event(ioim, evt);
@@ -2825,39 +2515,12 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
iotag = be16_to_cpu(rsp->io_tag);
ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
- bfa_assert(ioim->iotag == iotag);
+ WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag);
- bfa_trc_fp(ioim->bfa, ioim->iotag);
bfa_ioim_cb_profile_comp(fcpim, ioim);
-
bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
}
-void
-bfa_ioim_profile_start(struct bfa_ioim_s *ioim)
-{
- ioim->start_time = jiffies;
-}
-
-void
-bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)
-{
- u32 fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
- u32 index = bfa_ioim_get_index(fcp_dl);
- u64 end_time = jiffies;
- struct bfa_itnim_latency_s *io_lat =
- &(ioim->itnim->ioprofile.io_latency);
- u32 val = (u32)(end_time - ioim->start_time);
-
- bfa_itnim_ioprofile_update(ioim->itnim, index);
-
- io_lat->count[index]++;
- io_lat->min[index] = (io_lat->min[index] < val) ?
- io_lat->min[index] : val;
- io_lat->max[index] = (io_lat->max[index] > val) ?
- io_lat->max[index] : val;
- io_lat->avg[index] += val;
-}
/*
* Called by itnim to clean up IO while going offline.
*/
@@ -2903,11 +2566,6 @@ bfa_ioim_tov(struct bfa_ioim_s *ioim)
}
-
-/*
- * hal_ioim_api
- */
-
/*
* Allocate IOIM resource for initiator mode I/O request.
*/
@@ -2936,7 +2594,6 @@ bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
fcpim->ios_active++;
list_add_tail(&ioim->qe, &itnim->io_q);
- bfa_trc_fp(ioim->bfa, ioim->iotag);
return ioim;
}
@@ -2946,18 +2603,13 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
{
struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
-
- bfa_assert_fp(list_empty(&ioim->sgpg_q) ||
- (ioim->nsges > BFI_SGE_INLINE));
-
if (ioim->nsgpgs > 0)
bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
bfa_stats(ioim->itnim, io_comps);
fcpim->ios_active--;
+ ioim->iotag &= BFA_IOIM_IOTAG_MASK;
list_del(&ioim->qe);
list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
}
@@ -2965,16 +2617,13 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
void
bfa_ioim_start(struct bfa_ioim_s *ioim)
{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
-
bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
/*
* 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_FALSE : bfa_itnim_get_reqq(ioim);
bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
}
@@ -2997,13 +2646,12 @@ bfa_ioim_abort(struct bfa_ioim_s *ioim)
return BFA_STATUS_OK;
}
-
/*
* BFA TSKIM state machine functions
*/
/*
- * Task management command beginning state.
+ * Task management command beginning state.
*/
static void
bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3040,9 +2688,8 @@ bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
}
/*
- * brief
- * TM command is active, awaiting completion from firmware to
- * cleanup IO requests in TM scope.
+ * TM command is active, awaiting completion from firmware to
+ * cleanup IO requests in TM scope.
*/
static void
bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3077,8 +2724,8 @@ bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
}
/*
- * An active TM is being cleaned up since ITN is offline. Awaiting cleanup
- * completion event from firmware.
+ * An active TM is being cleaned up since ITN is offline. Awaiting cleanup
+ * completion event from firmware.
*/
static void
bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3138,7 +2785,7 @@ bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
}
/*
- * Task management command is waiting for room in request CQ
+ * Task management command is waiting for room in request CQ
*/
static void
bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3173,8 +2820,8 @@ bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
}
/*
- * Task management command is active, awaiting for room in request CQ
- * to send clean up request.
+ * Task management command is active, awaiting for room in request CQ
+ * to send clean up request.
*/
static void
bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
@@ -3186,10 +2833,8 @@ bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
case BFA_TSKIM_SM_DONE:
bfa_reqq_wcancel(&tskim->reqq_wait);
/*
- *
* Fall through !!!
*/
-
case BFA_TSKIM_SM_QRESUME:
bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
bfa_tskim_send_abort(tskim);
@@ -3208,7 +2853,7 @@ bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
}
/*
- * BFA callback is pending
+ * BFA callback is pending
*/
static void
bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3233,12 +2878,6 @@ bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
}
}
-
-
-/*
- * hal_tskim_private
- */
-
static void
__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
{
@@ -3268,8 +2907,8 @@ __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
BFI_TSKIM_STS_FAILED);
}
-static bfa_boolean_t
-bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
+static bfa_boolean_t
+bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun)
{
switch (tskim->tm_cmnd) {
case FCP_TM_TARGET_RESET:
@@ -3279,24 +2918,26 @@ bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
case FCP_TM_CLEAR_TASK_SET:
case FCP_TM_LUN_RESET:
case FCP_TM_CLEAR_ACA:
- return (tskim->lun == lun);
+ return !memcmp(&tskim->lun, &lun, sizeof(lun));
default:
- bfa_assert(0);
+ WARN_ON(1);
}
return BFA_FALSE;
}
/*
- * Gather affected IO requests and task management commands.
+ * Gather affected IO requests and task management commands.
*/
static void
bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
{
struct bfa_itnim_s *itnim = tskim->itnim;
struct bfa_ioim_s *ioim;
- struct list_head *qe, *qen;
+ struct list_head *qe, *qen;
+ struct scsi_cmnd *cmnd;
+ struct scsi_lun scsilun;
INIT_LIST_HEAD(&tskim->io_q);
@@ -3305,8 +2946,9 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
*/
list_for_each_safe(qe, qen, &itnim->io_q) {
ioim = (struct bfa_ioim_s *) qe;
- if (bfa_tskim_match_scope
- (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+ cmnd = (struct scsi_cmnd *) ioim->dio;
+ int_to_scsilun(cmnd->device->lun, &scsilun);
+ if (bfa_tskim_match_scope(tskim, scsilun)) {
list_del(&ioim->qe);
list_add_tail(&ioim->qe, &tskim->io_q);
}
@@ -3317,8 +2959,9 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
*/
list_for_each_safe(qe, qen, &itnim->pending_q) {
ioim = (struct bfa_ioim_s *) qe;
- if (bfa_tskim_match_scope
- (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+ cmnd = (struct scsi_cmnd *) ioim->dio;
+ int_to_scsilun(cmnd->device->lun, &scsilun);
+ if (bfa_tskim_match_scope(tskim, scsilun)) {
list_del(&ioim->qe);
list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
bfa_ioim_tov(ioim);
@@ -3327,7 +2970,7 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
}
/*
- * IO cleanup completion
+ * IO cleanup completion
*/
static void
bfa_tskim_cleanp_comp(void *tskim_cbarg)
@@ -3339,7 +2982,7 @@ bfa_tskim_cleanp_comp(void *tskim_cbarg)
}
/*
- * Gather affected IO requests and task management commands.
+ * Gather affected IO requests and task management commands.
*/
static void
bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
@@ -3359,7 +3002,7 @@ bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
}
/*
- * Send task management request to firmware.
+ * Send task management request to firmware.
*/
static bfa_boolean_t
bfa_tskim_send(struct bfa_tskim_s *tskim)
@@ -3394,7 +3037,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)
}
/*
- * Send abort request to cleanup an active TM to firmware.
+ * Send abort request to cleanup an active TM to firmware.
*/
static bfa_boolean_t
bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
@@ -3425,7 +3068,7 @@ bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
}
/*
- * Call to resume task management cmnd waiting for room in request queue.
+ * Call to resume task management cmnd waiting for room in request queue.
*/
static void
bfa_tskim_qresume(void *cbarg)
@@ -3451,12 +3094,6 @@ bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
}
}
-
-
-/*
- * hal_tskim_friend
- */
-
/*
* Notification on completions from related ioim.
*/
@@ -3489,7 +3126,7 @@ bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
}
/*
- * Memory allocation and initialization.
+ * Memory allocation and initialization.
*/
void
bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
@@ -3522,14 +3159,6 @@ bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
}
void
-bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
- /*
- * @todo
- */
-}
-
-void
bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
{
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
@@ -3538,7 +3167,7 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
u16 tsk_tag = be16_to_cpu(rsp->tsk_tag);
tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
- bfa_assert(tskim->tsk_tag == tsk_tag);
+ WARN_ON(tskim->tsk_tag != tsk_tag);
tskim->tsk_status = rsp->tsk_status;
@@ -3556,12 +3185,6 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
}
-
-/*
- * hal_tskim_api
- */
-
-
struct bfa_tskim_s *
bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
{
@@ -3579,13 +3202,13 @@ bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
void
bfa_tskim_free(struct bfa_tskim_s *tskim)
{
- bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
+ WARN_ON(!bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
list_del(&tskim->qe);
list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
}
/*
- * Start a task management command.
+ * Start a task management command.
*
* @param[in] tskim BFA task management command instance
* @param[in] itnim i-t nexus for the task management command
@@ -3596,7 +3219,8 @@ bfa_tskim_free(struct bfa_tskim_s *tskim)
* @return None.
*/
void
-bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
+bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim,
+ struct scsi_lun lun,
enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
{
tskim->itnim = itnim;
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index db53717eeb4..1e38dade842 100644
--- a/drivers/scsi/bfa/bfa_fcpim.h
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -41,7 +41,7 @@
(__itnim->ioprofile.iocomps[__index]++)
#define BFA_IOIM_RETRY_TAG_OFFSET 11
-#define BFA_IOIM_RETRY_TAG_MASK 0x07ff /* 2K IOs */
+#define BFA_IOIM_IOTAG_MASK 0x07ff /* 2K IOs */
#define BFA_IOIM_RETRY_MAX 7
/* Buckets are are 512 bytes to 2MB */
@@ -94,12 +94,12 @@ struct bfa_fcpim_mod_s {
struct list_head ioim_resfree_q; /* IOs waiting for f/w */
struct list_head ioim_comp_q; /* IO global comp Q */
struct list_head tskim_free_q;
- u32 ios_active; /* current active IOs */
- u32 delay_comp;
+ u32 ios_active; /* current active IOs */
+ u32 delay_comp;
struct bfa_fcpim_del_itn_stats_s del_itn_stats;
bfa_boolean_t ioredirect;
bfa_boolean_t io_profile;
- u32 io_profile_start_time;
+ u32 io_profile_start_time;
bfa_fcpim_profile_t profile_comp;
bfa_fcpim_profile_t profile_start;
};
@@ -114,25 +114,24 @@ struct bfa_ioim_s {
struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
struct bfad_ioim_s *dio; /* driver IO handle */
- u16 iotag; /* FWI IO tag */
- u16 abort_tag; /* unqiue abort request tag */
- u16 nsges; /* number of SG elements */
- u16 nsgpgs; /* number of SG pages */
+ u16 iotag; /* FWI IO tag */
+ u16 abort_tag; /* unqiue abort request tag */
+ u16 nsges; /* number of SG elements */
+ u16 nsgpgs; /* number of SG pages */
struct bfa_sgpg_s *sgpg; /* first SG page */
struct list_head sgpg_q; /* allocated SG pages */
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 */
- u64 start_time; /* IO's Profile start val */
+ struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */
+ u8 reqq; /* Request queue for I/O */
+ u64 start_time; /* IO's Profile start val */
};
-
struct bfa_ioim_sp_s {
struct bfi_msg_s comp_rspmsg; /* IO comp f/w response */
u8 *snsinfo; /* sense info for this IO */
- struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */
- struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+ struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */
+ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
bfa_boolean_t abort_explicit; /* aborted by OS */
struct bfa_tskim_s *tskim; /* Relevant TM cmd */
};
@@ -143,35 +142,34 @@ struct bfa_ioim_sp_s {
struct bfa_tskim_s {
struct list_head qe;
bfa_sm_t sm;
- struct bfa_s *bfa; /* BFA module */
+ struct bfa_s *bfa; /* BFA module */
struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
- struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */
- bfa_boolean_t notify; /* notify itnim on TM comp */
- lun_t lun; /* lun if applicable */
- enum fcp_tm_cmnd tm_cmnd; /* task management command */
- u16 tsk_tag; /* FWI IO tag */
- u8 tsecs; /* timeout in seconds */
+ struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */
+ bfa_boolean_t notify; /* notify itnim on TM comp */
+ struct scsi_lun lun; /* lun if applicable */
+ enum fcp_tm_cmnd tm_cmnd; /* task management command */
+ u16 tsk_tag; /* FWI IO tag */
+ u8 tsecs; /* timeout in seconds */
struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
struct list_head io_q; /* queue of affected IOs */
- struct bfa_wc_s wc; /* waiting counter */
+ struct bfa_wc_s wc; /* waiting counter */
struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
enum bfi_tskim_status tsk_status; /* TM status */
};
-
/*
* BFA i-t-n (initiator mode)
*/
struct bfa_itnim_s {
- struct list_head qe; /* queue element */
- bfa_sm_t sm; /* i-t-n im BFA state machine */
- struct bfa_s *bfa; /* bfa instance */
- struct bfa_rport_s *rport; /* bfa rport */
- void *ditn; /* driver i-t-n structure */
+ struct list_head qe; /* queue element */
+ bfa_sm_t sm; /* i-t-n im BFA state machine */
+ struct bfa_s *bfa; /* bfa instance */
+ struct bfa_rport_s *rport; /* bfa rport */
+ void *ditn; /* driver i-t-n structure */
struct bfi_mhdr_s mhdr; /* pre-built mhdr */
- u8 msg_no; /* itnim/rport firmware handle */
- u8 reqq; /* CQ for requests */
+ u8 msg_no; /* itnim/rport firmware handle */
+ u8 reqq; /* CQ for requests */
struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
struct list_head pending_q; /* queue of pending IO requests */
struct list_head io_q; /* queue of active IO requests */
@@ -181,19 +179,19 @@ struct bfa_itnim_s {
bfa_boolean_t seq_rec; /* SQER supported */
bfa_boolean_t is_online; /* itnim is ONLINE for IO */
bfa_boolean_t iotov_active; /* IO TOV timer is active */
- struct bfa_wc_s wc; /* waiting counter */
- struct bfa_timer_s timer; /* pending IO TOV */
+ struct bfa_wc_s wc; /* waiting counter */
+ struct bfa_timer_s timer; /* pending IO TOV */
struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
struct bfa_fcpim_mod_s *fcpim; /* fcpim module */
struct bfa_itnim_iostats_s stats;
struct bfa_itnim_ioprofile_s ioprofile;
};
-
#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_IOIM_TAG_2_ID(_iotag) ((_iotag) & BFA_IOIM_IOTAG_MASK)
#define BFA_IOIM_FROM_TAG(_fcpim, _iotag) \
- (&fcpim->ioim_arr[(_iotag & BFA_IOIM_RETRY_TAG_MASK)])
+ (&fcpim->ioim_arr[(_iotag & BFA_IOIM_IOTAG_MASK)])
#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag) \
(&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
@@ -201,26 +199,26 @@ struct bfa_itnim_s {
(_bfa->modules.fcpim_mod.io_profile_start_time)
#define bfa_fcpim_get_io_profile(_bfa) \
(_bfa->modules.fcpim_mod.io_profile)
+#define bfa_ioim_update_iotag(__ioim) do { \
+ uint16_t k = (__ioim)->iotag >> BFA_IOIM_RETRY_TAG_OFFSET; \
+ k++; (__ioim)->iotag &= BFA_IOIM_IOTAG_MASK; \
+ (__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET; \
+} while (0)
static inline bfa_boolean_t
-bfa_ioim_get_iotag(struct bfa_ioim_s *ioim)
+bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
{
- u16 k = ioim->iotag;
-
- k >>= BFA_IOIM_RETRY_TAG_OFFSET; k++;
-
- if (k > BFA_IOIM_RETRY_MAX)
+ uint16_t k = ioim->iotag >> BFA_IOIM_RETRY_TAG_OFFSET;
+ if (k < BFA_IOIM_RETRY_MAX)
return BFA_FALSE;
- ioim->iotag &= BFA_IOIM_RETRY_TAG_MASK;
- ioim->iotag |= k<<BFA_IOIM_RETRY_TAG_OFFSET;
return BFA_TRUE;
}
+
/*
* function prototypes
*/
void bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
struct bfa_meminfo_s *minfo);
-void bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
void bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
void bfa_ioim_good_comp_isr(struct bfa_s *bfa,
struct bfi_msg_s *msg);
@@ -232,7 +230,6 @@ void bfa_ioim_tov(struct bfa_ioim_s *ioim);
void bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
struct bfa_meminfo_s *minfo);
-void bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
void bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
void bfa_tskim_iodone(struct bfa_tskim_s *tskim);
void bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
@@ -248,32 +245,14 @@ void bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
void bfa_itnim_iodone(struct bfa_itnim_s *itnim);
void bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
bfa_boolean_t bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
-void bfa_ioim_profile_comp(struct bfa_ioim_s *ioim);
-void bfa_ioim_profile_start(struct bfa_ioim_s *ioim);
-
/*
* bfa fcpim module API functions
*/
-void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
+void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
u16 bfa_fcpim_path_tov_get(struct bfa_s *bfa);
-void bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa);
-bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
- struct bfa_itnim_iostats_s *modstats);
-bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
- struct bfa_itnim_iostats_s *stats, u8 lp_tag);
-bfa_status_t bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
- struct bfa_fcpim_del_itn_stats_s *modstats);
-bfa_status_t bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag);
-void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats,
- struct bfa_itnim_iostats_s *itnim_stats);
-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);
-bfa_status_t bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time);
-bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa);
+
#define bfa_fcpim_ioredirect_enabled(__bfa) \
(((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
@@ -291,48 +270,33 @@ bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa);
* bfa itnim API functions
*/
struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
- struct bfa_rport_s *rport, void *itnim);
-void bfa_itnim_delete(struct bfa_itnim_s *itnim);
-void bfa_itnim_online(struct bfa_itnim_s *itnim,
- bfa_boolean_t seq_rec);
-void bfa_itnim_offline(struct bfa_itnim_s *itnim);
-void bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
- struct bfa_itnim_iostats_s *stats);
-void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
-bfa_status_t bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
- struct bfa_itnim_ioprofile_s *ioprofile);
+ struct bfa_rport_s *rport, void *itnim);
+void bfa_itnim_delete(struct bfa_itnim_s *itnim);
+void bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec);
+void bfa_itnim_offline(struct bfa_itnim_s *itnim);
+void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
+bfa_status_t bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+ struct bfa_itnim_ioprofile_s *ioprofile);
+
#define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)
/*
- * BFA completion callback for bfa_itnim_online().
- *
- * @param[in] itnim FCS or driver itnim instance
- *
- * return None
+ * BFA completion callback for bfa_itnim_online().
*/
void bfa_cb_itnim_online(void *itnim);
/*
- * BFA completion callback for bfa_itnim_offline().
- *
- * @param[in] itnim FCS or driver itnim instance
- *
- * return None
+ * BFA completion callback for bfa_itnim_offline().
*/
void bfa_cb_itnim_offline(void *itnim);
void bfa_cb_itnim_tov_begin(void *itnim);
void bfa_cb_itnim_tov(void *itnim);
/*
- * BFA notification to FCS/driver for second level error recovery.
- *
+ * BFA notification to FCS/driver for second level error recovery.
* Atleast one I/O request has timedout and target is unresponsive to
* repeated abort requests. Second level error recovery should be initiated
* by starting implicit logout and recovery procedures.
- *
- * @param[in] itnim FCS or driver itnim instance
- *
- * return None
*/
void bfa_cb_itnim_sler(void *itnim);
@@ -349,10 +313,8 @@ void bfa_ioim_start(struct bfa_ioim_s *ioim);
bfa_status_t bfa_ioim_abort(struct bfa_ioim_s *ioim);
void bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
bfa_boolean_t iotov);
-
-
/*
- * I/O completion notification.
+ * I/O completion notification.
*
* @param[in] dio driver IO structure
* @param[in] io_status IO completion status
@@ -363,39 +325,31 @@ void bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
*
* @return None
*/
-void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
- enum bfi_ioim_status io_status,
- u8 scsi_status, int sns_len,
- u8 *sns_info, s32 residue);
+void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
+ enum bfi_ioim_status io_status,
+ u8 scsi_status, int sns_len,
+ u8 *sns_info, s32 residue);
/*
- * I/O good completion notification.
- *
- * @param[in] dio driver IO structure
- *
- * @return None
+ * I/O good completion notification.
*/
-void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
+void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
/*
- * I/O abort completion notification
- *
- * @param[in] dio driver IO that was aborted
- *
- * @return None
+ * I/O abort completion notification
*/
-void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
+void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
/*
* bfa tskim API functions
*/
-struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa,
- struct bfad_tskim_s *dtsk);
-void bfa_tskim_free(struct bfa_tskim_s *tskim);
-void bfa_tskim_start(struct bfa_tskim_s *tskim,
- struct bfa_itnim_s *itnim, lun_t lun,
- enum fcp_tm_cmnd tm, u8 t_secs);
-void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
- enum bfi_tskim_status tsk_status);
+struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa,
+ struct bfad_tskim_s *dtsk);
+void bfa_tskim_free(struct bfa_tskim_s *tskim);
+void bfa_tskim_start(struct bfa_tskim_s *tskim,
+ struct bfa_itnim_s *itnim, struct scsi_lun lun,
+ enum fcp_tm_cmnd tm, u8 t_secs);
+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/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index 045d7e87b63..f674f931862 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -19,9 +19,9 @@
* bfa_fcs.c BFA FCS main
*/
+#include "bfad_drv.h"
#include "bfa_fcs.h"
#include "bfa_fcbuild.h"
-#include "bfad_drv.h"
BFA_TRC_FILE(FCS, FCS);
@@ -76,7 +76,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
fcs->bfad = bfad;
fcs->min_cfg = min_cfg;
- bfa_attach_fcs(bfa);
+ bfa->fcs = BFA_TRUE;
fcbuild_init();
for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
@@ -110,14 +110,6 @@ bfa_fcs_init(struct bfa_fcs_s *fcs)
}
}
-/*
- * Start FCS operations.
- */
-void
-bfa_fcs_start(struct bfa_fcs_s *fcs)
-{
- bfa_fcs_fabric_modstart(fcs);
-}
/*
* brief
@@ -140,22 +132,6 @@ bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
/*
* brief
- * FCS FDMI Driver Parameter Initialization
- *
- * param[in] fcs FCS instance
- * param[in] fdmi_enable TRUE/FALSE
- *
- * return None
- */
-void
-bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable)
-{
-
- fcs->fdmi_enabled = fdmi_enable;
-
-}
-/*
- * brief
* FCS instance cleanup and exit.
*
* param[in] fcs FCS instance
@@ -184,18 +160,6 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs)
}
-void
-bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod)
-{
- fcs->trcmod = trcmod;
-}
-
-void
-bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)
-{
- bfa_wc_down(&fcs->wc);
-}
-
/*
* Fabric module implementation.
*/
@@ -232,31 +196,6 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
u32 rsp_len,
u32 resid_len,
struct fchs_s *rspfchs);
-/*
- * fcs_fabric_sm fabric state machine functions
- */
-
-/*
- * Fabric state machine events
- */
-enum bfa_fcs_fabric_event {
- BFA_FCS_FABRIC_SM_CREATE = 1, /* create from driver */
- BFA_FCS_FABRIC_SM_DELETE = 2, /* delete from driver */
- BFA_FCS_FABRIC_SM_LINK_DOWN = 3, /* link down from port */
- BFA_FCS_FABRIC_SM_LINK_UP = 4, /* link up from port */
- BFA_FCS_FABRIC_SM_CONT_OP = 5, /* flogi/auth continue op */
- BFA_FCS_FABRIC_SM_RETRY_OP = 6, /* flogi/auth retry op */
- BFA_FCS_FABRIC_SM_NO_FABRIC = 7, /* from flogi/auth */
- BFA_FCS_FABRIC_SM_PERF_EVFP = 8, /* from flogi/auth */
- BFA_FCS_FABRIC_SM_ISOLATE = 9, /* from EVFP processing */
- BFA_FCS_FABRIC_SM_NO_TAGGING = 10, /* no VFT tagging from EVFP */
- BFA_FCS_FABRIC_SM_DELAYED = 11, /* timeout delay event */
- BFA_FCS_FABRIC_SM_AUTH_FAILED = 12, /* auth failed */
- BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13, /* auth successful */
- BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */
- BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */
- BFA_FCS_FABRIC_SM_START = 16, /* from driver */
-};
static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
@@ -270,14 +209,8 @@ static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
@@ -337,7 +270,7 @@ bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_DELETE:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
- bfa_fcs_modexit_comp(fabric->fcs);
+ bfa_wc_down(&fabric->fcs->wc);
break;
default:
@@ -410,7 +343,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_LOOPBACK:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
- bfa_lps_discard(fabric->lps);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
bfa_fcs_fabric_set_opertype(fabric);
break;
@@ -424,12 +357,12 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_LINK_DOWN:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_lps_discard(fabric->lps);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
break;
case BFA_FCS_FABRIC_SM_DELETE:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_lps_discard(fabric->lps);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
bfa_fcs_fabric_delete(fabric);
break;
@@ -481,7 +414,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
switch (event) {
case BFA_FCS_FABRIC_SM_AUTH_FAILED:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
- bfa_lps_discard(fabric->lps);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
break;
case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
@@ -495,7 +428,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_LINK_DOWN:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_lps_discard(fabric->lps);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
break;
case BFA_FCS_FABRIC_SM_DELETE:
@@ -511,7 +444,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
/*
* Authentication failed
*/
-static void
+void
bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event)
{
@@ -537,7 +470,7 @@ bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
/*
* Port is in loopback mode.
*/
-static void
+void
bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event)
{
@@ -573,7 +506,7 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
switch (event) {
case BFA_FCS_FABRIC_SM_LINK_DOWN:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_lps_discard(fabric->lps);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
bfa_fcs_fabric_notify_offline(fabric);
break;
@@ -596,7 +529,7 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
/*
* Fabric is online - normal operating state.
*/
-static void
+void
bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event)
{
@@ -606,7 +539,7 @@ bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
switch (event) {
case BFA_FCS_FABRIC_SM_LINK_DOWN:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_lps_discard(fabric->lps);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
bfa_fcs_fabric_notify_offline(fabric);
break;
@@ -617,7 +550,7 @@ bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_AUTH_FAILED:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
- bfa_lps_discard(fabric->lps);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
break;
case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
@@ -697,7 +630,7 @@ bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
switch (event) {
case BFA_FCS_FABRIC_SM_DELCOMP:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
- bfa_fcs_modexit_comp(fabric->fcs);
+ bfa_wc_down(&fabric->fcs->wc);
break;
case BFA_FCS_FABRIC_SM_LINK_UP:
@@ -724,8 +657,8 @@ bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;
- port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
- port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
+ port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn;
+ port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;
}
/*
@@ -813,7 +746,7 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
return;
case BFA_STATUS_EPROTOCOL:
- switch (bfa_lps_get_extstatus(fabric->lps)) {
+ switch (fabric->lps->ext_status) {
case BFA_EPROTO_BAD_ACCEPT:
fabric->stats.flogi_acc_err++;
break;
@@ -840,26 +773,26 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
return;
}
- fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
+ fabric->bb_credit = fabric->lps->pr_bbcred;
bfa_trc(fabric->fcs, fabric->bb_credit);
- if (!bfa_lps_is_brcd_fabric(fabric->lps))
- fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps);
+ if (!(fabric->lps->brcd_switch))
+ fabric->fabric_name = fabric->lps->pr_nwwn;
/*
* Check port type. It should be 1 = F-port.
*/
- if (bfa_lps_is_fport(fabric->lps)) {
- fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
- fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
- fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
+ if (fabric->lps->fport) {
+ fabric->bport.pid = fabric->lps->lp_pid;
+ fabric->is_npiv = fabric->lps->npiv_en;
+ fabric->is_auth = fabric->lps->auth_req;
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
} else {
/*
* Nport-2-Nport direct attached
*/
fabric->bport.port_topo.pn2n.rem_port_wwn =
- bfa_lps_get_peer_pwwn(fabric->lps);
+ fabric->lps->pr_pwwn;
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
}
@@ -987,7 +920,7 @@ bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
INIT_LIST_HEAD(&fabric->vport_q);
INIT_LIST_HEAD(&fabric->vf_q);
fabric->lps = bfa_lps_alloc(fcs->bfa);
- bfa_assert(fabric->lps);
+ WARN_ON(!fabric->lps);
/*
* Initialize fabric delete completion handler. Fabric deletion is
@@ -1038,31 +971,6 @@ bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
}
-/*
- * Suspend fabric activity as part of driver suspend.
- */
-void
-bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
-{
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
-{
- return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
-{
- return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-}
-
-enum bfa_port_type
-bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
-{
- return fabric->oper_type;
-}
/*
* Link up notification from BFA physical port module.
@@ -1123,40 +1031,6 @@ bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
bfa_wc_down(&fabric->wc);
}
-/*
- * Base port is deleted.
- */
-void
-bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
-{
- bfa_wc_down(&fabric->wc);
-}
-
-
-/*
- * Check if fabric is online.
- *
- * param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
- * @return TRUE/FALSE
- */
-int
-bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
-{
- return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
-}
-
-/*
- * brief
- *
- */
-bfa_status_t
-bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
- struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
-{
- bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
- return BFA_STATUS_OK;
-}
/*
* Lookup for a vport withing a fabric given its pwwn
@@ -1176,18 +1050,6 @@ bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
return NULL;
}
-/*
- * In a given fabric, return the number of lports.
- *
- * param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
- * @return : 1 or more.
- */
-u16
-bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
-{
- return fabric->num_vports;
-}
/*
* Get OUI of the attached switch.
@@ -1207,7 +1069,7 @@ bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
u8 *tmp;
u16 oui;
- fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps);
+ fab_nwwn = fabric->lps->pr_nwwn;
tmp = (u8 *)&fab_nwwn;
oui = (tmp[3] << 8) | tmp[4];
@@ -1235,7 +1097,7 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
* external loopback cable is in place. Our own FLOGI frames are
* sometimes looped back when switch port gets temporarily bypassed.
*/
- if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) &&
+ if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&
(els_cmd->els_code == FC_ELS_FLOGI) &&
(flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
@@ -1245,7 +1107,7 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
/*
* FLOGI/EVFP exchanges should be consumed by base fabric.
*/
- if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
+ if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {
bfa_trc(fabric->fcs, pid);
bfa_fcs_fabric_process_uf(fabric, fchs, len);
return;
@@ -1358,13 +1220,13 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
return;
reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_os_hton3b(FC_FABRIC_PORT),
+ bfa_hton3b(FC_FABRIC_PORT),
n2n_port->reply_oxid, pcfg->pwwn,
pcfg->nwwn,
bfa_fcport_get_maxfrsize(bfa),
bfa_fcport_get_rx_bbcredit(bfa));
- bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
+ bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
BFA_FALSE, FC_CLASS_3,
reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
FC_MAX_PDUSZ, 0);
@@ -1455,7 +1317,7 @@ bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
}
}
@@ -1502,7 +1364,7 @@ bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
* drop frame if vfid is unknown
*/
if (!fabric) {
- bfa_assert(0);
+ WARN_ON(1);
bfa_stats(fcs, uf.vfid_unknown);
bfa_uf_free(uf);
return;
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index 9cb6a55977c..0fd63168573 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -27,6 +27,22 @@
#define BFA_FCS_OS_STR_LEN 64
/*
+ * lps_pvt BFA LPS private functions
+ */
+
+enum bfa_lps_event {
+ BFA_LPS_SM_LOGIN = 1, /* login request from user */
+ BFA_LPS_SM_LOGOUT = 2, /* logout request from user */
+ BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */
+ BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */
+ BFA_LPS_SM_DELETE = 5, /* lps delete from user */
+ BFA_LPS_SM_OFFLINE = 6, /* Link is offline */
+ BFA_LPS_SM_RX_CVL = 7, /* Rx clear virtual link */
+ BFA_LPS_SM_SET_N2N_PID = 8, /* Set assigned PID for n2n */
+};
+
+
+/*
* !!! Only append to the enums defined here to avoid any versioning
* !!! needed between trace utility and driver version
*/
@@ -41,13 +57,12 @@ enum {
struct bfa_fcs_s;
#define __fcs_min_cfg(__fcs) ((__fcs)->min_cfg)
-void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
#define BFA_FCS_BRCD_SWITCH_OUI 0x051e
#define N2N_LOCAL_PID 0x010000
#define N2N_REMOTE_PID 0x020000
#define BFA_FCS_RETRY_TIMEOUT 2000
-#define BFA_FCS_PID_IS_WKA(pid) ((bfa_os_ntoh3b(pid) > 0xFFF000) ? 1 : 0)
+#define BFA_FCS_PID_IS_WKA(pid) ((bfa_ntoh3b(pid) > 0xFFF000) ? 1 : 0)
@@ -109,7 +124,7 @@ struct bfa_fcs_lport_loop_s {
struct bfa_fcs_lport_n2n_s {
u32 rsvd;
- u16 reply_oxid; /* ox_id from the req flogi to be
+ __be16 reply_oxid; /* ox_id from the req flogi to be
*used in flogi acc */
wwn_t rem_port_wwn; /* Attached port's wwn */
};
@@ -316,8 +331,6 @@ void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,
struct bfa_fcs_rport_s *rport);
void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
struct bfa_fcs_rport_s *rport);
-void bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs);
void bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport);
void bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport);
void bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport);
@@ -359,9 +372,6 @@ 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);
void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
struct bfa_vport_attr_s *vport_attr);
-void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
- struct bfa_vport_stats_s *vport_stats);
-void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
u16 vf_id, wwn_t vpwwn);
void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
@@ -406,7 +416,7 @@ struct bfa_fcs_rport_s {
struct bfad_rport_s *rp_drv; /* driver peer instance */
u32 pid; /* port ID of rport */
u16 maxfrsize; /* maximum frame size */
- u16 reply_oxid; /* OX_ID of inbound requests */
+ __be16 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 */
@@ -437,32 +447,18 @@ bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
/*
* bfa fcs rport API functions
*/
-bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
- struct bfa_fcs_rport_s *rport,
- struct bfad_rport_s *rport_drv);
-bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
- struct bfa_rport_attr_s *attr);
-void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
- struct bfa_rport_stats_s *stats);
-void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
wwn_t rpwwn);
struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
struct bfa_fcs_lport_s *port, wwn_t rnwwn);
void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
-void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
- enum bfa_port_speed speed);
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);
struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_lport_s *port,
u32 pid);
-void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
void bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
struct fc_logi_s *plogi_rsp);
void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port,
@@ -470,10 +466,8 @@ void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port,
struct fc_logi_s *plogi);
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, u16 ox_id);
+void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 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_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
int bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
@@ -618,7 +612,7 @@ struct bfa_fcs_fdmi_hba_attr_s {
u8 option_rom_ver[BFA_VERSION_LEN];
u8 fw_version[8];
u8 os_name[256];
- u32 max_ct_pyld;
+ __be32 max_ct_pyld;
};
/*
@@ -626,9 +620,9 @@ struct bfa_fcs_fdmi_hba_attr_s {
*/
struct bfa_fcs_fdmi_port_attr_s {
u8 supp_fc4_types[32]; /* supported FC4 types */
- u32 supp_speed; /* supported speed */
- u32 curr_speed; /* current Speed */
- u32 max_frm_size; /* max frame size */
+ __be32 supp_speed; /* supported speed */
+ __be32 curr_speed; /* current Speed */
+ __be32 max_frm_size; /* max frame size */
u8 os_device_name[256]; /* OS device Name */
u8 host_name[256]; /* host name */
};
@@ -664,6 +658,57 @@ struct bfa_fcs_s {
};
/*
+ * fcs_fabric_sm fabric state machine functions
+ */
+
+/*
+ * Fabric state machine events
+ */
+enum bfa_fcs_fabric_event {
+ BFA_FCS_FABRIC_SM_CREATE = 1, /* create from driver */
+ BFA_FCS_FABRIC_SM_DELETE = 2, /* delete from driver */
+ BFA_FCS_FABRIC_SM_LINK_DOWN = 3, /* link down from port */
+ BFA_FCS_FABRIC_SM_LINK_UP = 4, /* link up from port */
+ BFA_FCS_FABRIC_SM_CONT_OP = 5, /* flogi/auth continue op */
+ BFA_FCS_FABRIC_SM_RETRY_OP = 6, /* flogi/auth retry op */
+ BFA_FCS_FABRIC_SM_NO_FABRIC = 7, /* from flogi/auth */
+ BFA_FCS_FABRIC_SM_PERF_EVFP = 8, /* from flogi/auth */
+ BFA_FCS_FABRIC_SM_ISOLATE = 9, /* from EVFP processing */
+ BFA_FCS_FABRIC_SM_NO_TAGGING = 10, /* no VFT tagging from EVFP */
+ BFA_FCS_FABRIC_SM_DELAYED = 11, /* timeout delay event */
+ BFA_FCS_FABRIC_SM_AUTH_FAILED = 12, /* auth failed */
+ BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13, /* auth successful */
+ BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */
+ BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */
+ BFA_FCS_FABRIC_SM_START = 16, /* from driver */
+};
+
+/*
+ * fcs_rport_sm FCS rport state machine events
+ */
+
+enum rport_event {
+ RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */
+ RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */
+ RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */
+ RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */
+ RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
+ RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
+ RPSM_EVENT_DELETE = 7, /* RPORT delete request */
+ RPSM_EVENT_SCN = 8, /* state change notification */
+ RPSM_EVENT_ACCEPTED = 9, /* Good response from remote device */
+ RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
+ RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
+ RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */
+ 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_PRLO_RCVD = 17, /* PRLO from remote device */
+ RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continously */
+};
+
+/*
* bfa fcs API functions
*/
void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
@@ -672,16 +717,12 @@ void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
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);
-void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);
void bfa_fcs_exit(struct bfa_fcs_s *fcs);
-void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
-void bfa_fcs_start(struct bfa_fcs_s *fcs);
/*
* bfa fcs vf public functions
*/
bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
-u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
/*
* fabric protected interface functions
@@ -689,32 +730,29 @@ u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
struct bfa_fcs_vport_s *vport);
void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
struct bfa_fcs_vport_s *vport);
-int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
struct fchs_s *fchs, u16 len);
-bfa_boolean_t bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
-bfa_boolean_t bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric);
-enum bfa_port_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
-bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
- struct bfa_fcs_s *fcs, struct bfa_lport_cfg_s *port_cfg,
- struct bfad_vf_s *vf_drv);
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_uf_attach(struct bfa_fcs_s *fcs);
void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
/*
* BFA FCS callback interfaces
diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
index 413b58eef93..e7b49f4cb51 100644
--- a/drivers/scsi/bfa/bfa_fcs_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -19,9 +19,9 @@
* fcpim.c - FCP initiator mode i-t nexus state machine
*/
+#include "bfad_drv.h"
#include "bfa_fcs.h"
#include "bfa_fcbuild.h"
-#include "bfad_drv.h"
#include "bfad_im.h"
BFA_TRC_FILE(FCS, FCPIM);
@@ -103,7 +103,7 @@ bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
break;
case BFA_FCS_ITNIM_SM_OFFLINE:
- bfa_fcs_rport_itnim_ack(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
case BFA_FCS_ITNIM_SM_INITIATOR:
@@ -140,7 +140,7 @@ bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
- bfa_fcs_rport_itnim_ack(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
case BFA_FCS_ITNIM_SM_DELETE:
@@ -181,7 +181,7 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_fcxp_discard(itnim->fcxp);
- bfa_fcs_rport_itnim_ack(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
case BFA_FCS_ITNIM_SM_INITIATOR:
@@ -217,7 +217,7 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
} else {
/* invoke target offline */
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
- bfa_fcs_rport_logo_imp(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
}
break;
@@ -225,7 +225,7 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_timer_stop(&itnim->timer);
- bfa_fcs_rport_itnim_ack(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
case BFA_FCS_ITNIM_SM_INITIATOR:
@@ -269,7 +269,7 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_itnim_offline(itnim->bfa_itnim);
- bfa_fcs_rport_itnim_ack(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
case BFA_FCS_ITNIM_SM_DELETE:
@@ -330,7 +330,7 @@ bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
switch (event) {
case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
- bfa_fcs_rport_itnim_ack(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
case BFA_FCS_ITNIM_SM_DELETE:
@@ -358,7 +358,7 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
switch (event) {
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
- bfa_fcs_rport_itnim_ack(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
case BFA_FCS_ITNIM_SM_RSP_ERROR:
@@ -536,7 +536,7 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
if (bfa_itnim == NULL) {
bfa_trc(port->fcs, rport->pwwn);
bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
- bfa_assert(0);
+ WARN_ON(1);
return NULL;
}
@@ -688,7 +688,7 @@ bfa_cb_itnim_sler(void *cb_arg)
itnim->stats.sler++;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
- bfa_fcs_rport_logo_imp(itnim->rport);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
}
struct bfa_fcs_itnim_s *
@@ -700,7 +700,7 @@ bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
if (!rport)
return NULL;
- bfa_assert(rport->itnim != NULL);
+ WARN_ON(rport->itnim == NULL);
return rport->itnim;
}
@@ -729,7 +729,7 @@ bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
{
struct bfa_fcs_itnim_s *itnim = NULL;
- bfa_assert(port != NULL);
+ WARN_ON(port == NULL);
itnim = bfa_fcs_itnim_lookup(port, rpwwn);
@@ -746,7 +746,7 @@ bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
{
struct bfa_fcs_itnim_s *itnim = NULL;
- bfa_assert(port != NULL);
+ WARN_ON(port == NULL);
itnim = bfa_fcs_itnim_lookup(port, rpwwn);
@@ -778,6 +778,6 @@ bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
}
}
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 8d651309302..4e2eb92ba02 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -15,10 +15,10 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_fcs.h"
#include "bfa_fcbuild.h"
#include "bfa_fc.h"
-#include "bfad_drv.h"
BFA_TRC_FILE(FCS, PORT);
@@ -159,7 +159,7 @@ bfa_fcs_lport_sm_online(
bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
list_for_each_safe(qe, qen, &port->rport_q) {
rport = (struct bfa_fcs_rport_s *) qe;
- bfa_fcs_rport_delete(rport);
+ bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
}
}
break;
@@ -197,7 +197,7 @@ bfa_fcs_lport_sm_offline(
bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
list_for_each_safe(qe, qen, &port->rport_q) {
rport = (struct bfa_fcs_rport_s *) qe;
- bfa_fcs_rport_delete(rport);
+ bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
}
}
break;
@@ -309,6 +309,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
return;
}
port->pid = rx_fchs->d_id;
+ bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
}
/*
@@ -323,6 +324,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
port->pid = rx_fchs->d_id;
+ bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
rport->pid = rx_fchs->s_id;
}
bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
@@ -349,8 +351,8 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
* This is a different device with the same pid. Old device
* disappeared. Send implicit LOGO to old device.
*/
- bfa_assert(rport->pwwn != plogi->port_name);
- bfa_fcs_rport_logo_imp(rport);
+ WARN_ON(rport->pwwn == plogi->port_name);
+ bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
/*
* Inbound PLOGI from a new device (with old PID).
@@ -362,7 +364,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
/*
* PLOGI crossing each other.
*/
- bfa_assert(rport->pwwn == WWN_NULL);
+ WARN_ON(rport->pwwn != WWN_NULL);
bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
}
@@ -511,7 +513,8 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
__port_action[port->fabric->fab_type].offline(port);
wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
- if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
+ if (bfa_sm_cmp_state(port->fabric,
+ bfa_fcs_fabric_sm_online) == BFA_TRUE)
BFA_LOG(KERN_ERR, bfad, bfa_log_level,
"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
lpwwn_buf, "Initiator");
@@ -522,26 +525,26 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
list_for_each_safe(qe, qen, &port->rport_q) {
rport = (struct bfa_fcs_rport_s *) qe;
- bfa_fcs_rport_offline(rport);
+ bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
}
}
static void
bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
{
- bfa_assert(0);
+ WARN_ON(1);
}
static void
bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
{
- bfa_assert(0);
+ WARN_ON(1);
}
static void
bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
{
- bfa_assert(0);
+ WARN_ON(1);
}
static void
@@ -584,33 +587,11 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
port->vport ? port->vport->vport_drv : NULL);
bfa_fcs_vport_delete_comp(port->vport);
} else {
- bfa_fcs_fabric_port_delete_comp(port->fabric);
+ bfa_wc_down(&port->fabric->wc);
}
}
-
-/*
- * fcs_lport_api BFA FCS port API
- */
-/*
- * Module initialization
- */
-void
-bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs)
-{
-
-}
-
-/*
- * Module cleanup
- */
-void
-bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs)
-{
- bfa_fcs_modexit_comp(fcs);
-}
-
/*
* Unsolicited frame receive handling.
*/
@@ -623,6 +604,7 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
bfa_stats(lport, uf_recvs);
+ bfa_trc(lport->fcs, fchs->type);
if (!bfa_fcs_lport_is_online(lport)) {
bfa_stats(lport, uf_recv_drops);
@@ -682,8 +664,11 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
* Only handles ELS frames for now.
*/
if (fchs->type != FC_TYPE_ELS) {
- bfa_trc(lport->fcs, fchs->type);
- bfa_assert(0);
+ bfa_trc(lport->fcs, fchs->s_id);
+ bfa_trc(lport->fcs, fchs->d_id);
+ /* ignore type FC_TYPE_FC_FSS */
+ if (fchs->type != FC_TYPE_FC_FSS)
+ bfa_sm_fault(lport->fcs, fchs->type);
return;
}
@@ -792,7 +777,7 @@ bfa_fcs_lport_del_rport(
struct bfa_fcs_lport_s *port,
struct bfa_fcs_rport_s *rport)
{
- bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
+ WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
list_del(&rport->qe);
port->num_rports--;
@@ -850,8 +835,8 @@ bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
lport->fcs = fcs;
lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
lport->vport = vport;
- lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
- bfa_lps_get_tag(lport->fabric->lps);
+ lport->lp_tag = (vport) ? vport->lps->lp_tag :
+ lport->fabric->lps->lp_tag;
INIT_LIST_HEAD(&lport->rport_q);
lport->num_rports = 0;
@@ -903,10 +888,12 @@ bfa_fcs_lport_get_attr(
port_attr->port_cfg = port->port_cfg;
if (port->fabric) {
- port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
- port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
+ port_attr->port_type = port->fabric->oper_type;
+ port_attr->loopback = bfa_sm_cmp_state(port->fabric,
+ bfa_fcs_fabric_sm_loopback);
port_attr->authfail =
- bfa_fcs_fabric_is_auth_failed(port->fabric);
+ bfa_sm_cmp_state(port->fabric,
+ bfa_fcs_fabric_sm_auth_failed);
port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port);
memcpy(port_attr->fabric_ip_addr,
bfa_fcs_lport_get_fabric_ipaddr(port),
@@ -915,10 +902,10 @@ bfa_fcs_lport_get_attr(
if (port->vport != NULL) {
port_attr->port_type = BFA_PORT_TYPE_VPORT;
port_attr->fpma_mac =
- bfa_lps_get_lp_mac(port->vport->lps);
+ port->vport->lps->lp_mac;
} else {
port_attr->fpma_mac =
- bfa_lps_get_lp_mac(port->fabric->lps);
+ port->fabric->lps->lp_mac;
}
} else {
port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
@@ -998,6 +985,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
sizeof(wwn_t)) > 0) {
port->pid = N2N_LOCAL_PID;
+ bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
/*
* First, check if we know the device by pwwn.
*/
@@ -1007,7 +995,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
bfa_trc(port->fcs, rport->pid);
bfa_trc(port->fcs, rport->pwwn);
rport->pid = N2N_REMOTE_PID;
- bfa_fcs_rport_online(rport);
+ bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
return;
}
@@ -1017,10 +1005,10 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
*/
if (port->num_rports > 0) {
rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
- bfa_assert(rport != NULL);
+ WARN_ON(rport == NULL);
if (rport) {
bfa_trc(port->fcs, rport->pwwn);
- bfa_fcs_rport_delete(rport);
+ bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
}
}
bfa_fcs_rport_create(port, N2N_REMOTE_PID);
@@ -1569,6 +1557,7 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
struct fdmi_attr_s *attr;
u8 *curr_ptr;
u16 len, count;
+ u16 templen;
/*
* get hba attributes
@@ -1594,69 +1583,69 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
- attr->len = sizeof(wwn_t);
- memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = sizeof(wwn_t);
+ memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* Manufacturer
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
- attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
- memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_hba_attr->manufacturer);
+ memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* Serial Number
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
- attr->len = (u16) strlen(fcs_hba_attr->serial_num);
- memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_hba_attr->serial_num);
+ memcpy(attr->value, fcs_hba_attr->serial_num, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* Model
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
- attr->len = (u16) strlen(fcs_hba_attr->model);
- memcpy(attr->value, fcs_hba_attr->model, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_hba_attr->model);
+ memcpy(attr->value, fcs_hba_attr->model, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* Model Desc
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
- attr->len = (u16) strlen(fcs_hba_attr->model_desc);
- memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_hba_attr->model_desc);
+ memcpy(attr->value, fcs_hba_attr->model_desc, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* H/W Version
@@ -1664,14 +1653,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
if (fcs_hba_attr->hw_version[0] != '\0') {
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
- attr->len = (u16) strlen(fcs_hba_attr->hw_version);
- memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_hba_attr->hw_version);
+ memcpy(attr->value, fcs_hba_attr->hw_version, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
}
/*
@@ -1679,14 +1668,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
- attr->len = (u16) strlen(fcs_hba_attr->driver_version);
- memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;;
+ templen = (u16) strlen(fcs_hba_attr->driver_version);
+ memcpy(attr->value, fcs_hba_attr->driver_version, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* Option Rom Version
@@ -1694,14 +1683,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
if (fcs_hba_attr->option_rom_ver[0] != '\0') {
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
- attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
- memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
+ memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
}
/*
@@ -1709,14 +1698,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
- attr->len = (u16) strlen(fcs_hba_attr->driver_version);
- memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_hba_attr->driver_version);
+ memcpy(attr->value, fcs_hba_attr->driver_version, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* OS Name
@@ -1724,14 +1713,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
if (fcs_hba_attr->os_name[0] != '\0') {
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
- attr->len = (u16) strlen(fcs_hba_attr->os_name);
- memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_hba_attr->os_name);
+ memcpy(attr->value, fcs_hba_attr->os_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
}
/*
@@ -1739,12 +1728,12 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
- attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
- memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
- len += attr->len;
+ templen = sizeof(fcs_hba_attr->max_ct_pyld);
+ memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
+ len += templen;
count++;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* Update size of payload
@@ -1845,6 +1834,7 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
u8 *curr_ptr;
u16 len;
u8 count = 0;
+ u16 templen;
/*
* get port attributes
@@ -1863,54 +1853,54 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
- attr->len = sizeof(fcs_port_attr.supp_fc4_types);
- memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = sizeof(fcs_port_attr.supp_fc4_types);
+ memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
++count;
attr->len =
- cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* Supported Speed
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
- attr->len = sizeof(fcs_port_attr.supp_speed);
- memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = sizeof(fcs_port_attr.supp_speed);
+ memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
++count;
attr->len =
- cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* current Port Speed
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
- attr->len = sizeof(fcs_port_attr.curr_speed);
- memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = sizeof(fcs_port_attr.curr_speed);
+ memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
++count;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* max frame size
*/
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
- attr->len = sizeof(fcs_port_attr.max_frm_size);
- memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = sizeof(fcs_port_attr.max_frm_size);
+ memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
++count;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
/*
* OS Device Name
@@ -1918,14 +1908,14 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
if (fcs_port_attr.os_device_name[0] != '\0') {
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
- attr->len = (u16) strlen(fcs_port_attr.os_device_name);
- memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_port_attr.os_device_name);
+ memcpy(attr->value, fcs_port_attr.os_device_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
++count;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
}
/*
* Host Name
@@ -1933,14 +1923,14 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
if (fcs_port_attr.host_name[0] != '\0') {
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
- attr->len = (u16) strlen(fcs_port_attr.host_name);
- memcpy(attr->value, fcs_port_attr.host_name, attr->len);
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
+ templen = (u16) strlen(fcs_port_attr.host_name);
+ memcpy(attr->value, fcs_port_attr.host_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
++count;
- attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
}
/*
@@ -2103,7 +2093,7 @@ bfa_fcs_lport_fdmi_timeout(void *arg)
bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
}
-void
+static void
bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
{
@@ -2147,7 +2137,7 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
}
-void
+static void
bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
struct bfa_fcs_fdmi_port_attr_s *port_attr)
{
@@ -2560,7 +2550,7 @@ bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
bfa_fcs_lport_get_fcid(port),
- bfa_lps_get_peer_nwwn(port->fabric->lps));
+ port->fabric->lps->pr_nwwn);
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
FC_CLASS_3, len, &fchs,
@@ -2760,7 +2750,7 @@ bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
bfa_fcs_lport_get_fcid(port),
- bfa_lps_get_peer_nwwn(port->fabric->lps));
+ port->fabric->lps->pr_nwwn);
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
FC_CLASS_3, len, &fchs,
@@ -2836,7 +2826,7 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
ms->fcxp = fcxp;
len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_os_hton3b(FC_MGMT_SERVER),
+ bfa_hton3b(FC_MGMT_SERVER),
bfa_fcs_lport_get_fcid(port), 0,
port->port_cfg.pwwn, port->port_cfg.nwwn,
bfa_fcport_get_maxfrsize(port->fcs->bfa));
@@ -3593,7 +3583,7 @@ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
ns->fcxp = fcxp;
len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_os_hton3b(FC_NAME_SERVER),
+ bfa_hton3b(FC_NAME_SERVER),
bfa_fcs_lport_get_fcid(port), 0,
port->port_cfg.pwwn, port->port_cfg.nwwn,
bfa_fcport_get_maxfrsize(port->fcs->bfa));
@@ -4150,7 +4140,7 @@ bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
}
-void
+static void
bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
{
@@ -4163,7 +4153,7 @@ bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
for (ii = 0 ; ii < nwwns; ++ii) {
rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
- bfa_assert(rport);
+ WARN_ON(!rport);
}
}
@@ -4352,8 +4342,8 @@ bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
/* Handle VU registrations for Base port only */
if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_lps_is_brcd_fabric(port->fabric->lps),
- port->pid, 0);
+ port->fabric->lps->brcd_switch,
+ port->pid, 0);
} else {
len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
BFA_FALSE,
@@ -4626,7 +4616,7 @@ bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
default:
- bfa_assert(0);
+ WARN_ON(1);
nsquery = BFA_TRUE;
}
}
@@ -4672,7 +4662,7 @@ bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
while ((qe != qh) && (i < nrports)) {
rport = (struct bfa_fcs_rport_s *) qe;
- if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+ if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
qe = bfa_q_next(qe);
bfa_trc(fcs, (u32) rport->pwwn);
bfa_trc(fcs, rport->pid);
@@ -4720,7 +4710,7 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
while ((qe != qh) && (i < *nrports)) {
rport = (struct bfa_fcs_rport_s *) qe;
- if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+ if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
qe = bfa_q_next(qe);
bfa_trc(fcs, (u32) rport->pwwn);
bfa_trc(fcs, rport->pid);
@@ -4771,7 +4761,7 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
while (qe != qh) {
rport = (struct bfa_fcs_rport_s *) qe;
- if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
+ if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
(bfa_fcs_rport_get_state(rport) ==
BFA_RPORT_OFFLINE)) {
qe = bfa_q_next(qe);
@@ -4807,7 +4797,7 @@ bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
struct bfa_fcs_vport_s *vport;
bfa_fcs_vf_t *vf;
- bfa_assert(fcs != NULL);
+ WARN_ON(fcs == NULL);
vf = bfa_fcs_vf_lookup(fcs, vf_id);
if (vf == NULL) {
@@ -4853,7 +4843,7 @@ bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
port_info->max_vports_supp =
bfa_lps_get_max_vport(port->fcs->bfa);
port_info->num_vports_inuse =
- bfa_fcs_fabric_vport_count(port->fabric);
+ port->fabric->num_vports;
port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
port_info->num_rports_inuse = port->num_rports;
} else {
@@ -4997,7 +4987,8 @@ bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
switch (event) {
case BFA_FCS_VPORT_SM_START:
- if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
+ if (bfa_sm_cmp_state(__vport_fabric(vport),
+ bfa_fcs_fabric_sm_online)
&& bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
bfa_fcs_vport_do_fdisc(vport);
@@ -5080,13 +5071,13 @@ 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_cleanup);
- bfa_lps_discard(vport->lps);
+ bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
bfa_fcs_lport_delete(&vport->lport);
break;
case BFA_FCS_VPORT_SM_OFFLINE:
bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
- bfa_lps_discard(vport->lps);
+ bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
break;
case BFA_FCS_VPORT_SM_RSP_OK:
@@ -5166,7 +5157,7 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
case BFA_FCS_VPORT_SM_OFFLINE:
bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
- bfa_lps_discard(vport->lps);
+ bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
bfa_fcs_lport_offline(&vport->lport);
break;
@@ -5266,7 +5257,7 @@ bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
switch (event) {
case BFA_FCS_VPORT_SM_OFFLINE:
- bfa_lps_discard(vport->lps);
+ bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
/*
* !!! fall through !!!
*/
@@ -5305,14 +5296,14 @@ bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
static void
bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
{
- u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
- u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
+ u8 lsrjt_rsn = vport->lps->lsrjt_rsn;
+ u8 lsrjt_expl = vport->lps->lsrjt_expl;
bfa_trc(__vport_fcs(vport), lsrjt_rsn);
bfa_trc(__vport_fcs(vport), lsrjt_expl);
/* For certain reason codes, we don't want to retry. */
- switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
+ switch (vport->lps->lsrjt_expl) {
case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
@@ -5476,7 +5467,7 @@ bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
return BFA_STATUS_VPORT_EXISTS;
- if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
+ if (fcs->fabric.num_vports ==
bfa_lps_get_max_vport(fcs->bfa))
return BFA_STATUS_VPORT_MAX;
@@ -5618,33 +5609,6 @@ bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
}
-/*
- * Use this function to get vport's statistics.
- *
- * param[in] vport pointer to bfa_fcs_vport_t.
- * param[out] stats pointer to return vport statistics in
- *
- * return None
- */
-void
-bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
- struct bfa_vport_stats_s *stats)
-{
- *stats = vport->vport_stats;
-}
-
-/*
- * Use this function to clear vport's statistics.
- *
- * param[in] vport pointer to bfa_fcs_vport_t.
- *
- * return None
- */
-void
-bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
-{
- memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
-}
/*
* Lookup a virtual port. Excludes base port from lookup.
@@ -5684,7 +5648,7 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
/*
* Initialiaze the V-Port fields
*/
- __vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
+ __vport_fcid(vport) = vport->lps->lp_pid;
vport->vport_stats.fdisc_accepts++;
bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
break;
@@ -5697,7 +5661,7 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
break;
case BFA_STATUS_EPROTOCOL:
- switch (bfa_lps_get_extstatus(vport->lps)) {
+ switch (vport->lps->ext_status) {
case BFA_EPROTO_BAD_ACCEPT:
vport->vport_stats.fdisc_acc_bad++;
break;
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index cf4a6e73e60..caaee6f0693 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -19,9 +19,9 @@
* rport.c Remote port implementation.
*/
+#include "bfad_drv.h"
#include "bfa_fcs.h"
#include "bfa_fcbuild.h"
-#include "bfad_drv.h"
BFA_TRC_FILE(FCS, RPORT);
@@ -75,30 +75,6 @@ static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
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
- */
-
-enum rport_event {
- RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */
- RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */
- RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */
- RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */
- RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
- RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
- RPSM_EVENT_DELETE = 7, /* RPORT delete request */
- RPSM_EVENT_SCN = 8, /* state change notification */
- RPSM_EVENT_ACCEPTED = 9, /* Good response from remote device */
- RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
- RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
- RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */
- 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_PRLO_RCVD = 17, /* PRLO from remote device */
- RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continously */
-};
static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
enum rport_event event);
@@ -498,24 +474,24 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
case RPSM_EVENT_LOGO_RCVD:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
- bfa_rport_offline(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
break;
case RPSM_EVENT_LOGO_IMP:
case RPSM_EVENT_ADDRESS_CHANGE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
- bfa_rport_offline(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
break;
case RPSM_EVENT_PLOGI_RCVD:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
- bfa_rport_offline(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
case RPSM_EVENT_DELETE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
- bfa_rport_offline(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
break;
case RPSM_EVENT_SCN:
@@ -824,7 +800,7 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FC4_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
- bfa_rport_offline(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
break;
case RPSM_EVENT_DELETE:
@@ -856,7 +832,7 @@ bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FC4_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
- bfa_rport_offline(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
break;
default:
@@ -878,7 +854,7 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FC4_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
- bfa_rport_offline(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
break;
case RPSM_EVENT_SCN:
@@ -1459,7 +1435,7 @@ bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
twin->stats.plogi_accs++;
- bfa_fcs_rport_delete(rport);
+ bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
bfa_fcs_rport_update(twin, plogi_rsp);
twin->pid = rsp_fchs->s_id;
@@ -1992,13 +1968,14 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
/*
* allocate FC-4s
*/
- bfa_assert(bfa_fcs_lport_is_initiator(port));
+ WARN_ON(!bfa_fcs_lport_is_initiator(port));
if (bfa_fcs_lport_is_initiator(port)) {
rport->itnim = bfa_fcs_itnim_create(rport);
if (!rport->itnim) {
bfa_trc(fcs, rpid);
- bfa_rport_delete(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport,
+ BFA_RPORT_SM_DELETE);
kfree(rport_drv);
return NULL;
}
@@ -2032,7 +2009,7 @@ bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
bfa_fcs_rpf_rport_offline(rport);
}
- bfa_rport_delete(rport->bfa_rport);
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
bfa_fcs_lport_del_rport(port, rport);
kfree(rport->rp_drv);
}
@@ -2307,40 +2284,8 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
}
-/*
- * Called by bport/vport to delete a remote port instance.
- *
- * Rport delete is called under the following conditions:
- * - vport is deleted
- * - vf is deleted
- * - explicit request from OS to delete rport
- */
-void
-bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
-{
- bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
-}
/*
- * Called by bport/vport to when a target goes offline.
- *
- */
-void
-bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
-{
- bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
-}
-
-/*
- * Called by bport in n2n when a target (attached port) becomes online.
- *
- */
-void
-bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
-{
- bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
-}
-/*
* Called by bport/vport to notify SCN for the remote port
*/
void
@@ -2350,23 +2295,6 @@ bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
bfa_sm_send_event(rport, RPSM_EVENT_SCN);
}
-/*
- * Called by fcpim to notify that the ITN cleanup is done.
- */
-void
-bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
-{
- bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
-}
-
-/*
- * Called by fcptm to notify that the ITN cleanup is done.
- */
-void
-bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
-{
- bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
-}
/*
* brief
@@ -2465,15 +2393,6 @@ bfa_cb_rport_qos_scn_prio(void *cbarg,
* Called to process any unsolicted frames from this remote port
*/
void
-bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
-{
- bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
-}
-
-/*
- * Called to process any unsolicted frames from this remote port
- */
-void
bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
struct fchs_s *fchs, u16 len)
{
@@ -2586,6 +2505,7 @@ bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
return bfa_sm_to_state(rport_sm_table, rport->sm);
}
+
/*
* brief
* Called by the Driver to set rport delete/ageout timeout
@@ -2602,7 +2522,7 @@ bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
bfa_fcs_rport_del_timeout = rport_tmo * 1000;
}
void
-bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id)
+bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
{
bfa_trc(rport->fcs, rport->pid);
@@ -2621,106 +2541,6 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id)
* fcs_rport_api FCS rport API.
*/
-/*
- * Direct API to add a target by port wwn. This interface is used, for
- * example, by bios when target pwwn is known from boot lun configuration.
- */
-bfa_status_t
-bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
- struct bfa_fcs_rport_s *rport, struct bfad_rport_s *rport_drv)
-{
- bfa_trc(port->fcs, *pwwn);
-
- return BFA_STATUS_OK;
-}
-
-/*
- * Direct API to remove a target and its associated resources. This
- * interface is used, for example, by driver to remove target
- * ports from the target list for a VM.
- */
-bfa_status_t
-bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
-{
-
- struct bfa_fcs_rport_s *rport;
-
- bfa_trc(rport_in->fcs, rport_in->pwwn);
-
- rport = bfa_fcs_lport_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
- if (rport == NULL) {
- /*
- * TBD Error handling
- */
- bfa_trc(rport_in->fcs, rport_in->pid);
- return BFA_STATUS_UNKNOWN_RWWN;
- }
-
- /*
- * TBD if this remote port is online, send a logo
- */
- return BFA_STATUS_OK;
-
-}
-
-/*
- * Remote device status for display/debug.
- */
-void
-bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
- struct bfa_rport_attr_s *rport_attr)
-{
- struct bfa_rport_qos_attr_s qos_attr;
- bfa_fcs_lport_t *port = rport->port;
- bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
-
- memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
-
- rport_attr->pid = rport->pid;
- rport_attr->pwwn = rport->pwwn;
- rport_attr->nwwn = rport->nwwn;
- rport_attr->cos_supported = rport->fc_cos;
- rport_attr->df_sz = rport->maxfrsize;
- rport_attr->state = bfa_fcs_rport_get_state(rport);
- rport_attr->fc_cos = rport->fc_cos;
- rport_attr->cisc = rport->cisc;
- rport_attr->scsi_function = rport->scsi_function;
- rport_attr->curr_speed = rport->rpf.rpsc_speed;
- rport_attr->assigned_speed = rport->rpf.assigned_speed;
-
- bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
- rport_attr->qos_attr = qos_attr;
-
- rport_attr->trl_enforced = BFA_FALSE;
- if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
- if (rport_speed == BFA_PORT_SPEED_UNKNOWN) {
- /* Use default ratelim speed setting */
- rport_speed =
- bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
- }
-
- if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
- rport_attr->trl_enforced = BFA_TRUE;
- }
-}
-
-/*
- * Per remote device statistics.
- */
-void
-bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
- struct bfa_rport_stats_s *stats)
-{
- *stats = rport->stats;
-}
-
-void
-bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
-{
- memset((char *)&rport->stats, 0,
- sizeof(struct bfa_rport_stats_s));
-}
-
struct bfa_fcs_rport_s *
bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
{
@@ -2752,22 +2572,6 @@ bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)
}
/*
- * This API is to set the Rport's speed. Should be used when RPSC is not
- * supported by the rport.
- */
-void
-bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, bfa_port_speed_t speed)
-{
- rport->rpf.assigned_speed = speed;
-
- /* Set this speed in f/w only if the RPSC speed is not available */
- if (rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
- bfa_rport_speed(rport->bfa_rport, speed);
-}
-
-
-
-/*
* Remote port features (RPF) implementation.
*/
@@ -2827,7 +2631,7 @@ bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
case RPFSM_EVENT_RPORT_ONLINE:
/* Send RPSC2 to a Brocade fabric only. */
if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
- ((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
+ ((rport->port->fabric->lps->brcd_switch) ||
(bfa_fcs_fabric_get_switch_oui(fabric) ==
BFA_FCS_BRCD_SWITCH_OUI))) {
bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
@@ -3093,7 +2897,7 @@ bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
num_ents = be16_to_cpu(rpsc2_acc->num_pids);
bfa_trc(rport->fcs, num_ents);
if (num_ents > 0) {
- bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
+ WARN_ON(rpsc2_acc->port_info[0].pid == rport->pid);
bfa_trc(rport->fcs,
be16_to_cpu(rpsc2_acc->port_info[0].pid));
bfa_trc(rport->fcs,
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c
index d8464ae6007..977e681ec80 100644
--- a/drivers/scsi/bfa/bfa_hw_cb.c
+++ b/drivers/scsi/bfa/bfa_hw_cb.c
@@ -15,6 +15,7 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_modules.h"
#include "bfi_cbreg.h"
@@ -110,7 +111,7 @@ bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
{
int i;
- bfa_assert((nvecs == 1) || (nvecs == __HFN_NUMINTS));
+ WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
bfa->msix.nvecs = nvecs;
if (nvecs == 1) {
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c
index b0efbc713ff..21018d98a07 100644
--- a/drivers/scsi/bfa/bfa_hw_ct.c
+++ b/drivers/scsi/bfa/bfa_hw_ct.c
@@ -15,6 +15,7 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_modules.h"
#include "bfi_ctreg.h"
@@ -116,7 +117,7 @@ bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
void
bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
{
- bfa_assert((nvecs == 1) || (nvecs == BFA_MSIX_CT_MAX));
+ WARN_ON((nvecs != 1) && (nvecs != BFA_MSIX_CT_MAX));
bfa_trc(bfa, nvecs);
bfa->msix.nvecs = nvecs;
@@ -143,7 +144,7 @@ bfa_hwct_msix_install(struct bfa_s *bfa)
for (; i <= BFA_MSIX_RME_Q3; i++)
bfa->msix.handler[i] = bfa_msix_rspq;
- bfa_assert(i == BFA_MSIX_LPU_ERR);
+ WARN_ON(i != BFA_MSIX_LPU_ERR);
bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err;
}
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 9f4aa391ea9..c1f72c49196 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -15,11 +15,11 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_ioc.h"
#include "bfi_ctreg.h"
#include "bfa_defs.h"
#include "bfa_defs_svc.h"
-#include "bfad_drv.h"
BFA_TRC_FILE(CNA, IOC);
@@ -29,7 +29,7 @@ BFA_TRC_FILE(CNA, IOC);
#define BFA_IOC_TOV 3000 /* msecs */
#define BFA_IOC_HWSEM_TOV 500 /* msecs */
#define BFA_IOC_HB_TOV 500 /* msecs */
-#define BFA_IOC_HWINIT_MAX 2
+#define BFA_IOC_HWINIT_MAX 5
#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV
#define bfa_ioc_timer_start(__ioc) \
@@ -42,11 +42,6 @@ BFA_TRC_FILE(CNA, IOC);
bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
#define bfa_hb_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->hb_timer)
-#define BFA_DBG_FWTRC_ENTS (BFI_IOC_TRC_ENTS)
-#define BFA_DBG_FWTRC_LEN \
- (BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) + \
- (sizeof(struct bfa_trc_mod_s) - \
- BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
#define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
/*
@@ -59,17 +54,16 @@ BFA_TRC_FILE(CNA, IOC);
((__ioc)->ioc_hwif->ioc_firmware_unlock(__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))
-
-#ifdef BFA_IOC_IS_UEFI
-#define bfa_ioc_is_bios_optrom(__ioc) (0)
-#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI
-#else
-#define bfa_ioc_is_bios_optrom(__ioc) \
- (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
-#define bfa_ioc_is_uefi(__ioc) (0)
-#endif
+#define bfa_ioc_notify_fail(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
+#define bfa_ioc_sync_join(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
+#define bfa_ioc_sync_leave(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))
+#define bfa_ioc_sync_ack(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
+#define bfa_ioc_sync_complete(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
#define bfa_ioc_mbox_cmd_pending(__ioc) \
(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
@@ -81,29 +75,22 @@ bfa_boolean_t bfa_auto_recover = BFA_TRUE;
* forward declarations
*/
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);
static void bfa_ioc_timeout(void *ioc);
static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
-static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
-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);
-static void bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc);
-static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc);
-static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc);
+static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
+static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
-/*
- * hal_ioc_sm
- */
/*
* IOC state machine definitions/declarations
@@ -116,10 +103,11 @@ enum ioc_event {
IOC_E_ENABLED = 5, /* f/w enabled */
IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */
IOC_E_DISABLED = 7, /* f/w disabled */
- IOC_E_FAILED = 8, /* failure notice by iocpf sm */
- IOC_E_HBFAIL = 9, /* heartbeat failure */
- IOC_E_HWERROR = 10, /* hardware error interrupt */
- IOC_E_TIMEOUT = 11, /* timeout */
+ IOC_E_INITFAILED = 8, /* failure notice by iocpf sm */
+ IOC_E_PFFAILED = 9, /* failure notice by iocpf sm */
+ IOC_E_HBFAIL = 10, /* heartbeat failure */
+ IOC_E_HWERROR = 11, /* hardware error interrupt */
+ IOC_E_TIMEOUT = 12, /* timeout */
};
bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
@@ -127,7 +115,7 @@ bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
@@ -138,7 +126,7 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
- {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
+ {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
@@ -165,12 +153,6 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
/*
* Forward declareations for iocpf state machine
*/
-static void bfa_iocpf_enable(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_disable(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_fail(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_initfail(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_stop(struct bfa_ioc_s *ioc);
static void bfa_iocpf_timeout(void *ioc_arg);
static void bfa_iocpf_sem_timeout(void *ioc_arg);
@@ -213,9 +195,14 @@ bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s,
+ enum iocpf_event);
bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event);
bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s,
+ enum iocpf_event);
bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
static struct bfa_sm_table_s iocpf_sm_table[] = {
@@ -226,9 +213,12 @@ static struct bfa_sm_table_s iocpf_sm_table[] = {
{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
+ {BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},
{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
+ {BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},
{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
+ {BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},
{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
};
@@ -301,7 +291,7 @@ bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
{
- bfa_iocpf_enable(ioc);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
}
/*
@@ -318,13 +308,13 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
- case IOC_E_FAILED:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
- break;
-
+ case IOC_E_PFFAILED:
+ /* !!! fall through !!! */
case IOC_E_HWERROR:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
- bfa_iocpf_initfail(ioc);
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+ if (event != IOC_E_PFFAILED)
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
break;
case IOC_E_DISABLE:
@@ -333,7 +323,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
case IOC_E_DETACH:
bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
- bfa_iocpf_stop(ioc);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
break;
case IOC_E_ENABLE:
@@ -367,18 +357,16 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
break;
- case IOC_E_FAILED:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
break;
-
+ case IOC_E_PFFAILED:
case IOC_E_HWERROR:
bfa_ioc_timer_stop(ioc);
- /* fall through */
-
+ /* !!! fall through !!! */
case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
- bfa_iocpf_getattrfail(ioc);
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+ if (event != IOC_E_PFFAILED)
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
break;
case IOC_E_DISABLE:
@@ -415,22 +403,24 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
break;
case IOC_E_DISABLE:
- bfa_ioc_hb_stop(ioc);
+ bfa_hb_timer_stop(ioc);
bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break;
- case IOC_E_FAILED:
- bfa_ioc_hb_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
- break;
-
+ case IOC_E_PFFAILED:
case IOC_E_HWERROR:
- bfa_ioc_hb_stop(ioc);
+ bfa_hb_timer_stop(ioc);
/* !!! fall through !!! */
-
case IOC_E_HBFAIL:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
- bfa_iocpf_fail(ioc);
+ bfa_ioc_fail_notify(ioc);
+
+ if (ioc->iocpf.auto_recover)
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+ else
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+
+ if (event != IOC_E_PFFAILED)
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
break;
default:
@@ -443,7 +433,7 @@ static void
bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
{
struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
- bfa_iocpf_disable(ioc);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
}
@@ -466,7 +456,7 @@ bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
* after iocpf sm completes failure processing and
* moves to disabled state.
*/
- bfa_iocpf_fail(ioc);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
break;
default:
@@ -499,7 +489,7 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
case IOC_E_DETACH:
bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
- bfa_iocpf_stop(ioc);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
break;
default:
@@ -509,16 +499,16 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
-bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
+bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)
{
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_trc(ioc, 0);
}
/*
- * Hardware initialization failed.
+ * Hardware initialization retry.
*/
static void
-bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
{
bfa_trc(ioc, event);
@@ -527,11 +517,21 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
- case IOC_E_FAILED:
+ case IOC_E_PFFAILED:
+ case IOC_E_HWERROR:
/*
- * Initialization failure during iocpf init retry.
+ * Initialization retry failed.
*/
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ if (event != IOC_E_PFFAILED)
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
+ break;
+
+ case IOC_E_INITFAILED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+ break;
+
+ case IOC_E_ENABLE:
break;
case IOC_E_DISABLE:
@@ -540,7 +540,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
case IOC_E_DETACH:
bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
- bfa_iocpf_stop(ioc);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
break;
default:
@@ -552,21 +552,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
{
- struct list_head *qe;
- struct bfa_ioc_hbfail_notify_s *notify;
- struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
-
- /*
- * Notify driver and common modules registered for notification.
- */
- ioc->cbfn->hbfail_cbfn(ioc->bfa);
- list_for_each(qe, &ioc->hb_notify_q) {
- notify = (struct bfa_ioc_hbfail_notify_s *) qe;
- notify->cbfn(notify->cbarg);
- }
-
- BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
- "Heart Beat of IOC has failed\n");
+ bfa_trc(ioc, 0);
}
/*
@@ -579,23 +565,19 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
switch (event) {
- case IOC_E_FAILED:
- /*
- * Initialization failure during iocpf recovery.
- * !!! Fall through !!!
- */
case IOC_E_ENABLE:
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
break;
- case IOC_E_ENABLED:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
- break;
-
case IOC_E_DISABLE:
bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break;
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
+ break;
+
case IOC_E_HWERROR:
/*
* HB failure notification, ignore.
@@ -606,13 +588,10 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
}
}
-
-
/*
* IOCPF State Machine
*/
-
/*
* Reset entry actions -- initialize state machine
*/
@@ -668,22 +647,29 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_SEMLOCKED:
if (bfa_ioc_firmware_lock(ioc)) {
- iocpf->retry_count = 0;
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ if (bfa_ioc_sync_complete(ioc)) {
+ iocpf->retry_count = 0;
+ bfa_ioc_sync_join(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ } else {
+ bfa_ioc_firmware_unlock(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+ bfa_sem_timer_start(ioc);
+ }
} else {
- bfa_ioc_hw_sem_release(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
}
break;
case IOCPF_E_DISABLE:
- bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_sem_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
- bfa_ioc_pf_disabled(ioc);
+ bfa_fsm_send_event(ioc, IOC_E_DISABLED);
break;
case IOCPF_E_STOP:
- bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_sem_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
break;
@@ -726,7 +712,7 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
case IOCPF_E_DISABLE:
bfa_iocpf_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
- bfa_ioc_pf_disabled(ioc);
+ bfa_fsm_send_event(ioc, IOC_E_DISABLED);
break;
case IOCPF_E_STOP:
@@ -760,13 +746,18 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_SEMLOCKED:
- iocpf->retry_count = 0;
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ if (bfa_ioc_sync_complete(ioc)) {
+ bfa_ioc_sync_join(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ } else {
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+ bfa_sem_timer_start(ioc);
+ }
break;
case IOCPF_E_DISABLE:
- bfa_ioc_hw_sem_get_cancel(ioc);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+ bfa_sem_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
default:
@@ -774,12 +765,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
}
-
static void
bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
{
bfa_iocpf_timer_start(iocpf->ioc);
- bfa_ioc_reset(iocpf->ioc, BFA_FALSE);
+ bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
}
/*
@@ -806,23 +796,16 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
*/
case IOCPF_E_TIMEOUT:
- iocpf->retry_count++;
- if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
- bfa_iocpf_timer_start(ioc);
- bfa_ioc_reset(ioc, BFA_TRUE);
- break;
- }
-
- bfa_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
if (event == IOCPF_E_TIMEOUT)
- bfa_ioc_pf_failed(ioc);
+ bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
case IOCPF_E_DISABLE:
- bfa_ioc_hw_sem_release(ioc);
bfa_iocpf_timer_stop(ioc);
+ bfa_ioc_sync_leave(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
@@ -831,7 +814,6 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
}
-
static void
bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
{
@@ -853,7 +835,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_FWRSP_ENABLE:
bfa_iocpf_timer_stop(ioc);
- bfa_ioc_hw_sem_release(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
break;
@@ -864,23 +846,15 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
*/
case IOCPF_E_TIMEOUT:
- iocpf->retry_count++;
- if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
- writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
- break;
- }
-
- bfa_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
if (event == IOCPF_E_TIMEOUT)
- bfa_ioc_pf_failed(ioc);
+ bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
case IOCPF_E_DISABLE:
bfa_iocpf_timer_stop(ioc);
- bfa_ioc_hw_sem_release(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
break;
@@ -893,12 +867,10 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
}
-
-
static void
bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_ioc_pf_enabled(iocpf->ioc);
+ bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);
}
static void
@@ -914,20 +886,21 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
break;
case IOCPF_E_GETATTRFAIL:
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
break;
case IOCPF_E_FAIL:
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
break;
case IOCPF_E_FWREADY:
- if (bfa_ioc_is_operational(ioc))
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
- else
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-
- bfa_ioc_pf_failed(ioc);
+ if (bfa_ioc_is_operational(ioc)) {
+ bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
+ } else {
+ bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
+ }
break;
default:
@@ -935,7 +908,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
}
-
static void
bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
{
@@ -957,7 +929,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
case IOCPF_E_FWRSP_DISABLE:
case IOCPF_E_FWREADY:
bfa_iocpf_timer_stop(ioc);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
case IOCPF_E_FAIL:
@@ -968,7 +940,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
case IOCPF_E_TIMEOUT:
writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
case IOCPF_E_FWRSP_ENABLE:
@@ -979,13 +951,44 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
}
+static void
+bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf)
+{
+ bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/*
+ * IOC hb ack request is being removed.
+ */
+static void
+bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOCPF_E_SEMLOCKED:
+ bfa_ioc_sync_leave(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+ break;
+
+ case IOCPF_E_FAIL:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
/*
* IOC disable completion entry.
*/
static void
bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_ioc_pf_disabled(iocpf->ioc);
+ bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
}
static void
@@ -997,6 +1000,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_ENABLE:
+ iocpf->retry_count = 0;
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
break;
@@ -1010,11 +1014,64 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
}
}
+static void
+bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)
+{
+ bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/*
+ * Hardware initialization failed.
+ */
+static void
+bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOCPF_E_SEMLOCKED:
+ bfa_ioc_notify_fail(ioc);
+ bfa_ioc_sync_ack(ioc);
+ iocpf->retry_count++;
+ if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
+ bfa_ioc_sync_leave(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+ } else {
+ if (bfa_ioc_sync_complete(ioc))
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ else {
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+ }
+ }
+ break;
+
+ case IOCPF_E_DISABLE:
+ bfa_sem_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+ break;
+
+ case IOCPF_E_STOP:
+ bfa_sem_timer_stop(ioc);
+ bfa_ioc_firmware_unlock(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+ break;
+
+ case IOCPF_E_FAIL:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
static void
bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_iocpf_timer_start(iocpf->ioc);
+ bfa_fsm_send_event(iocpf->ioc, IOC_E_INITFAILED);
}
/*
@@ -1029,47 +1086,77 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_DISABLE:
- bfa_iocpf_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
case IOCPF_E_STOP:
- bfa_iocpf_timer_stop(ioc);
bfa_ioc_firmware_unlock(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
break;
- case IOCPF_E_TIMEOUT:
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
- break;
-
default:
bfa_sm_fault(ioc, event);
}
}
-
static void
-bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
+bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
{
/*
* Mark IOC as failed in hardware and stop firmware.
*/
bfa_ioc_lpu_stop(iocpf->ioc);
- writel(BFI_IOC_FAIL, iocpf->ioc->ioc_regs.ioc_fwstate);
-
- /*
- * Notify other functions on HB failure.
- */
- bfa_ioc_notify_hbfail(iocpf->ioc);
/*
* Flush any queued up mailbox requests.
*/
bfa_ioc_mbox_hbfail(iocpf->ioc);
- if (iocpf->auto_recover)
- bfa_iocpf_recovery_timer_start(iocpf->ioc);
+ bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+static void
+bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOCPF_E_SEMLOCKED:
+ iocpf->retry_count = 0;
+ bfa_ioc_sync_ack(ioc);
+ bfa_ioc_notify_fail(ioc);
+ if (!iocpf->auto_recover) {
+ bfa_ioc_sync_leave(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ } else {
+ if (bfa_ioc_sync_complete(ioc))
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ else {
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+ }
+ }
+ break;
+
+ case IOCPF_E_DISABLE:
+ bfa_sem_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+ break;
+
+ case IOCPF_E_FAIL:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
+{
}
/*
@@ -1084,24 +1171,16 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
switch (event) {
case IOCPF_E_DISABLE:
- if (iocpf->auto_recover)
- bfa_iocpf_timer_stop(ioc);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
- case IOCPF_E_TIMEOUT:
- bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
- break;
-
default:
bfa_sm_fault(ioc, event);
}
}
-
-
/*
- * hal_ioc_pvt BFA IOC private functions
+ * BFA IOC private functions
*/
static void
@@ -1139,16 +1218,10 @@ bfa_ioc_sem_get(void __iomem *sem_reg)
if (r32 == 0)
return BFA_TRUE;
- bfa_assert(cnt < BFA_SEM_SPINCNT);
+ WARN_ON(cnt >= BFA_SEM_SPINCNT);
return BFA_FALSE;
}
-void
-bfa_ioc_sem_release(void __iomem *sem_reg)
-{
- writel(1, sem_reg);
-}
-
static void
bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
{
@@ -1167,18 +1240,6 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
bfa_sem_timer_start(ioc);
}
-void
-bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc)
-{
- writel(1, ioc->ioc_regs.ioc_sem_reg);
-}
-
-static void
-bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
-{
- bfa_sem_timer_stop(ioc);
-}
-
/*
* Initialize LPU local memory (aka secondary memory / SRAM)
*/
@@ -1212,7 +1273,7 @@ bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
* If memory initialization is not successful, IOC timeout will catch
* such failures.
*/
- bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE);
+ WARN_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
bfa_trc(ioc, pss_ctl);
pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
@@ -1258,8 +1319,8 @@ bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
int i;
u32 *fwsig = (u32 *) fwhdr;
- pgnum = bfa_ioc_smem_pgnum(ioc, loff);
- pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+ pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+ pgoff = PSS_SMEM_PGOFF(loff);
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
@@ -1304,12 +1365,6 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
{
struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
- /*
- * If bios/efi boot (flash based) -- return true
- */
- if (bfa_ioc_is_bios_optrom(ioc))
- return BFA_TRUE;
-
bfa_ioc_fwver_get(ioc, &fwhdr);
drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
@@ -1342,7 +1397,6 @@ bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
writel(1, ioc->ioc_regs.lpu_mbox_cmd);
}
-
static void
bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
{
@@ -1362,22 +1416,6 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
boot_env = BFI_BOOT_LOADER_OS;
/*
- * Flash based firmware boot BIOS env.
- */
- if (bfa_ioc_is_bios_optrom(ioc)) {
- boot_type = BFI_BOOT_TYPE_FLASH;
- boot_env = BFI_BOOT_LOADER_BIOS;
- }
-
- /*
- * Flash based firmware boot UEFI env.
- */
- if (bfa_ioc_is_uefi(ioc)) {
- boot_type = BFI_BOOT_TYPE_FLASH;
- boot_env = BFI_BOOT_LOADER_UEFI;
- }
-
- /*
* check if firmware is valid
*/
fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
@@ -1405,8 +1443,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
* convergence, IOC will be in operational state when 2nd driver
* is loaded.
*/
- if (ioc_fwstate == BFI_IOC_DISABLED ||
- (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
+ if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
/*
* When using MSI-X any pending firmware ready event should
@@ -1442,7 +1479,7 @@ bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
bfa_trc(ioc, msgp[0]);
bfa_trc(ioc, len);
- bfa_assert(len <= BFI_IOC_MSGLEN_MAX);
+ WARN_ON(len > BFI_IOC_MSGLEN_MAX);
/*
* first write msg to mailbox registers
@@ -1465,12 +1502,12 @@ static void
bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
{
struct bfi_ioc_ctrl_req_s enable_req;
- struct bfa_timeval_s tv;
+ struct timeval tv;
bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
bfa_ioc_portid(ioc));
enable_req.ioc_class = ioc->ioc_mc;
- bfa_os_gettimeofday(&tv);
+ do_gettimeofday(&tv);
enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
}
@@ -1504,7 +1541,6 @@ bfa_ioc_hb_check(void *cbarg)
hb_count = readl(ioc->ioc_regs.heartbeat);
if (ioc->hb_count == hb_count) {
- printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);
bfa_ioc_recover(ioc);
return;
} else {
@@ -1522,13 +1558,6 @@ bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
bfa_hb_timer_start(ioc);
}
-static void
-bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
-{
- bfa_hb_timer_stop(ioc);
-}
-
-
/*
* Initiate a full firmware download.
*/
@@ -1550,8 +1579,8 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
- pgnum = bfa_ioc_smem_pgnum(ioc, loff);
- pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+ pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+ pgoff = PSS_SMEM_PGOFF(loff);
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
@@ -1581,7 +1610,8 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
}
}
- writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
+ writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
+ ioc->ioc_regs.host_page_num_fn);
/*
* Set boot type and boot param at the end.
@@ -1592,11 +1622,6 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
swab32(boot_env));
}
-static void
-bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force)
-{
- bfa_ioc_hwinit(ioc, force);
-}
/*
* Update BFA configuration from firmware configuration.
@@ -1683,12 +1708,13 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
static bfa_status_t
bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
{
- u32 pgnum, loff, r32;
+ u32 pgnum, loff;
+ __be32 r32;
int i, len;
u32 *buf = tbuf;
- pgnum = bfa_ioc_smem_pgnum(ioc, soff);
- loff = bfa_ioc_smem_pgoff(ioc, soff);
+ pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
+ loff = PSS_SMEM_PGOFF(soff);
bfa_trc(ioc, pgnum);
bfa_trc(ioc, loff);
bfa_trc(ioc, sz);
@@ -1719,11 +1745,12 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
}
}
- writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
+ writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
+ ioc->ioc_regs.host_page_num_fn);
/*
* release semaphore.
*/
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
bfa_trc(ioc, pgnum);
return BFA_STATUS_OK;
@@ -1742,8 +1769,8 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
int i, len;
u32 pgnum, loff;
- pgnum = bfa_ioc_smem_pgnum(ioc, soff);
- loff = bfa_ioc_smem_pgoff(ioc, soff);
+ pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
+ loff = PSS_SMEM_PGOFF(soff);
bfa_trc(ioc, pgnum);
bfa_trc(ioc, loff);
bfa_trc(ioc, sz);
@@ -1773,35 +1800,38 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
}
}
- writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
+ writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
+ ioc->ioc_regs.host_page_num_fn);
/*
* release semaphore.
*/
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
bfa_trc(ioc, pgnum);
return BFA_STATUS_OK;
}
-/*
- * hal iocpf to ioc interface
- */
static void
-bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc)
+bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
{
- bfa_fsm_send_event(ioc, IOC_E_ENABLED);
-}
+ struct list_head *qe;
+ struct bfa_ioc_hbfail_notify_s *notify;
+ struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
-static void
-bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc)
-{
- bfa_fsm_send_event(ioc, IOC_E_DISABLED);
-}
+ /*
+ * Notify driver and common modules registered for notification.
+ */
+ ioc->cbfn->hbfail_cbfn(ioc->bfa);
+ list_for_each(qe, &ioc->hb_notify_q) {
+ notify = (struct bfa_ioc_hbfail_notify_s *) qe;
+ notify->cbfn(notify->cbarg);
+ }
+
+ bfa_ioc_debug_save_ftrc(ioc);
+
+ BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
+ "Heart Beat of IOC has failed\n");
-static void
-bfa_ioc_pf_failed(struct bfa_ioc_s *ioc)
-{
- bfa_fsm_send_event(ioc, IOC_E_FAILED);
}
static void
@@ -1817,12 +1847,6 @@ bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
"with the driver version\n");
}
-
-
-/*
- * hal_ioc_public
- */
-
bfa_status_t
bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
{
@@ -1838,7 +1862,7 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
/*
* release semaphore.
*/
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
return BFA_STATUS_OK;
}
@@ -1909,7 +1933,7 @@ bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
void
bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
{
- u32 *msgp = mbmsg;
+ __be32 *msgp = mbmsg;
u32 r32;
int i;
@@ -1962,7 +1986,7 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
default:
bfa_trc(ioc, msg->mh.msg_id);
- bfa_assert(0);
+ WARN_ON(1);
}
}
@@ -2043,15 +2067,6 @@ bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
}
-/*
- * Return size of dma memory required.
- */
-u32
-bfa_ioc_meminfo(void)
-{
- return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
-}
-
void
bfa_ioc_enable(struct bfa_ioc_s *ioc)
{
@@ -2068,18 +2083,6 @@ bfa_ioc_disable(struct bfa_ioc_s *ioc)
bfa_fsm_send_event(ioc, IOC_E_DISABLE);
}
-/*
- * Returns memory required for saving firmware trace in case of crash.
- * Driver must call this interface to allocate memory required for
- * automatic saving of firmware trace. Driver should call
- * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this
- * trace memory.
- */
-int
-bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
-{
- return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
-}
/*
* Initialize memory for saving firmware trace. Driver must initialize
@@ -2089,19 +2092,7 @@ void
bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
{
ioc->dbg_fwsave = dbg_fwsave;
- ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->iocpf.auto_recover);
-}
-
-u32
-bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr)
-{
- return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
-}
-
-u32
-bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr)
-{
- return PSS_SMEM_PGOFF(fmaddr);
+ ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
}
/*
@@ -2265,14 +2256,13 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
}
/*
- * Add to IOC heartbeat failure notification queue. To be used by common
- * modules such as cee, port, diag.
+ * Reset IOC fwstate registers.
*/
void
-bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
- struct bfa_ioc_hbfail_notify_s *notify)
+bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)
{
- list_add_tail(&notify->qe, &ioc->hb_notify_q);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
}
#define BFA_MFG_NAME "Brocade"
@@ -2306,7 +2296,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
else
ad_attr->prototype = 0;
- ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
+ ad_attr->pwwn = ioc->attr->pwwn;
ad_attr->mac = bfa_ioc_get_mac(ioc);
ad_attr->pcie_gen = ioc_attr->pcie_gen;
@@ -2317,7 +2307,8 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
ad_attr->cna_capable = ioc->cna;
- ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
+ ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna &&
+ !ad_attr->is_mezz;
}
enum bfa_ioc_type_e
@@ -2330,7 +2321,7 @@ bfa_ioc_get_type(struct bfa_ioc_s *ioc)
else if (ioc->ioc_mc == BFI_MC_LL)
return BFA_IOC_TYPE_LL;
else {
- bfa_assert(ioc->ioc_mc == BFI_MC_LL);
+ WARN_ON(ioc->ioc_mc != BFI_MC_LL);
return BFA_IOC_TYPE_LL;
}
}
@@ -2354,7 +2345,7 @@ bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)
void
bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)
{
- bfa_assert(chip_rev);
+ WARN_ON(!chip_rev);
memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
@@ -2386,7 +2377,7 @@ bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
{
struct bfi_ioc_attr_s *ioc_attr;
- bfa_assert(model);
+ WARN_ON(!model);
memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
ioc_attr = ioc->attr;
@@ -2455,27 +2446,6 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
}
-/*
- * hal_wwn_public
- */
-wwn_t
-bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
-{
- return ioc->attr->pwwn;
-}
-
-wwn_t
-bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc)
-{
- return ioc->attr->nwwn;
-}
-
-u64
-bfa_ioc_get_adid(struct bfa_ioc_s *ioc)
-{
- return ioc->attr->mfg_pwwn;
-}
-
mac_t
bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
{
@@ -2488,18 +2458,6 @@ bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
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)
{
@@ -2541,14 +2499,6 @@ bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
return BFA_STATUS_OK;
}
-/*
- * Clear saved firmware trace
- */
-void
-bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc)
-{
- ioc->dbg_fwsave_once = BFA_TRUE;
-}
/*
* Retrieve saved firmware trace from a prior IOC failure.
@@ -2701,13 +2651,16 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
* Save firmware trace if configured.
*/
static void
-bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
+bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
{
int tlen;
- if (ioc->dbg_fwsave_len) {
- tlen = ioc->dbg_fwsave_len;
- bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
+ if (ioc->dbg_fwsave_once) {
+ ioc->dbg_fwsave_once = BFA_FALSE;
+ if (ioc->dbg_fwsave_len) {
+ tlen = ioc->dbg_fwsave_len;
+ bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
+ }
}
}
@@ -2717,11 +2670,6 @@ bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
static void
bfa_ioc_recover(struct bfa_ioc_s *ioc)
{
- if (ioc->dbg_fwsave_once) {
- ioc->dbg_fwsave_once = BFA_FALSE;
- bfa_ioc_debug_save(ioc);
- }
-
bfa_ioc_stats(ioc, ioc_hbfails);
bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
}
@@ -2734,45 +2682,8 @@ bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc)
}
/*
- * hal_iocpf_pvt BFA IOC PF private functions
+ * BFA IOC PF private functions
*/
-
-static void
-bfa_iocpf_enable(struct bfa_ioc_s *ioc)
-{
- bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
-}
-
-static void
-bfa_iocpf_disable(struct bfa_ioc_s *ioc)
-{
- bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
-}
-
-static void
-bfa_iocpf_fail(struct bfa_ioc_s *ioc)
-{
- bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
-}
-
-static void
-bfa_iocpf_initfail(struct bfa_ioc_s *ioc)
-{
- bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
-}
-
-static void
-bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc)
-{
- bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
-}
-
-static void
-bfa_iocpf_stop(struct bfa_ioc_s *ioc)
-{
- bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
-}
-
static void
bfa_iocpf_timeout(void *ioc_arg)
{
@@ -2794,12 +2705,6 @@ bfa_iocpf_sem_timeout(void *ioc_arg)
* bfa timer function
*/
void
-bfa_timer_init(struct bfa_timer_mod_s *mod)
-{
- INIT_LIST_HEAD(&mod->timer_q);
-}
-
-void
bfa_timer_beat(struct bfa_timer_mod_s *mod)
{
struct list_head *qh = &mod->timer_q;
@@ -2843,8 +2748,8 @@ bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
void (*timercb) (void *), void *arg, unsigned int timeout)
{
- bfa_assert(timercb != NULL);
- bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
+ WARN_ON(timercb == NULL);
+ WARN_ON(bfa_q_is_on_q(&mod->timer_q, timer));
timer->timeout = timeout;
timer->timercb = timercb;
@@ -2859,7 +2764,7 @@ bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
void
bfa_timer_stop(struct bfa_timer_s *timer)
{
- bfa_assert(!list_empty(&timer->qe));
+ WARN_ON(list_empty(&timer->qe));
list_del(&timer->qe);
}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 9c407a87a1a..ec9cf08b0e7 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -18,10 +18,15 @@
#ifndef __BFA_IOC_H__
#define __BFA_IOC_H__
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
#include "bfa_cs.h"
#include "bfi.h"
+#define BFA_DBG_FWTRC_ENTS (BFI_IOC_TRC_ENTS)
+#define BFA_DBG_FWTRC_LEN \
+ (BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) + \
+ (sizeof(struct bfa_trc_mod_s) - \
+ BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
/*
* BFA timer declarations
*/
@@ -47,7 +52,6 @@ struct bfa_timer_mod_s {
#define BFA_TIMER_FREQ 200 /* specified in millisecs */
void bfa_timer_beat(struct bfa_timer_mod_s *mod);
-void bfa_timer_init(struct bfa_timer_mod_s *mod);
void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
bfa_timer_cbfn_t timercb, void *arg,
unsigned int timeout);
@@ -70,7 +74,7 @@ struct bfa_sge_s {
#define bfa_swap_words(_x) ( \
((_x) << 32) | ((_x) >> 32))
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
#define bfa_sge_to_be(_x)
#define bfa_sge_to_le(_x) bfa_sge_word_swap(_x)
#define bfa_sgaddr_le(_x) bfa_swap_words(_x)
@@ -115,8 +119,8 @@ struct bfa_dma_s {
static inline void
__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
{
- dma_addr->a32.addr_lo = (u32) pa;
- dma_addr->a32.addr_hi = (u32) (bfa_os_u32(pa));
+ dma_addr->a32.addr_lo = (__be32) pa;
+ dma_addr->a32.addr_hi = (__be32) (pa >> 32);
}
@@ -125,8 +129,8 @@ __bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
static inline void
__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
{
- dma_addr->a32.addr_lo = (u32) cpu_to_be32(pa);
- dma_addr->a32.addr_hi = (u32) cpu_to_be32(bfa_os_u32(pa));
+ dma_addr->a32.addr_lo = cpu_to_be32(pa);
+ dma_addr->a32.addr_hi = cpu_to_be32(pa >> 32);
}
struct bfa_ioc_regs_s {
@@ -145,8 +149,11 @@ struct bfa_ioc_regs_s {
void __iomem *host_page_num_fn;
void __iomem *heartbeat;
void __iomem *ioc_fwstate;
+ void __iomem *alt_ioc_fwstate;
void __iomem *ll_halt;
+ void __iomem *alt_ll_halt;
void __iomem *err_set;
+ void __iomem *ioc_fail_sync;
void __iomem *shirq_isr_next;
void __iomem *shirq_msk_next;
void __iomem *smem_page_start;
@@ -254,8 +261,12 @@ struct bfa_ioc_hwif_s {
void (*ioc_map_port) (struct bfa_ioc_s *ioc);
void (*ioc_isr_mode_set) (struct bfa_ioc_s *ioc,
bfa_boolean_t msix);
- void (*ioc_notify_hbfail) (struct bfa_ioc_s *ioc);
+ void (*ioc_notify_fail) (struct bfa_ioc_s *ioc);
void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc);
+ void (*ioc_sync_join) (struct bfa_ioc_s *ioc);
+ void (*ioc_sync_leave) (struct bfa_ioc_s *ioc);
+ void (*ioc_sync_ack) (struct bfa_ioc_s *ioc);
+ bfa_boolean_t (*ioc_sync_complete) (struct bfa_ioc_s *ioc);
};
#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func)
@@ -325,7 +336,6 @@ void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
void bfa_ioc_detach(struct bfa_ioc_s *ioc);
void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
enum bfi_mclass mc);
-u32 bfa_ioc_meminfo(void);
void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa);
void bfa_ioc_enable(struct bfa_ioc_s *ioc);
void bfa_ioc_disable(struct bfa_ioc_s *ioc);
@@ -340,6 +350,7 @@ bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
+void bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc);
enum bfa_ioc_type_e bfa_ioc_get_type(struct bfa_ioc_s *ioc);
void bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num);
void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver);
@@ -353,24 +364,16 @@ enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc_s *ioc);
void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr);
void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
struct bfa_adapter_attr_s *ad_attr);
-int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover);
void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave);
bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata,
int *trclen);
-void bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc);
bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
int *trclen);
bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
u32 *offset, int *buflen);
-u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr);
-u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr);
void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc);
-void bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
- struct bfa_ioc_hbfail_notify_s *notify);
bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg);
-void bfa_ioc_sem_release(void __iomem *sem_reg);
-void bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc);
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,
@@ -381,13 +384,8 @@ bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
/*
* bfa mfg wwn API functions
*/
-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);
/*
* F/W Image Size & Chunk
@@ -421,7 +419,7 @@ bfa_cb_image_get_chunk(int type, u32 off)
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;
+ default: return NULL;
}
}
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 90994504385..e4a0713185b 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -15,6 +15,7 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_ioc.h"
#include "bfi_cbreg.h"
#include "bfa_defs.h"
@@ -29,10 +30,14 @@ static void bfa_ioc_cb_firmware_unlock(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_notify_fail(struct bfa_ioc_s *ioc);
static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc);
+static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc);
-struct bfa_ioc_hwif_s hwif_cb;
+static struct bfa_ioc_hwif_s hwif_cb;
/*
* Called from bfa_ioc_attach() to map asic specific calls.
@@ -46,8 +51,12 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
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_notify_fail = bfa_ioc_cb_notify_fail;
hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset;
+ hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join;
+ hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave;
+ hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack;
+ hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete;
ioc->ioc_hwif = &hwif_cb;
}
@@ -58,6 +67,21 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
static bfa_boolean_t
bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
{
+ struct bfi_ioc_image_hdr_s fwhdr;
+ uint32_t fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ if (fwstate == BFI_IOC_UNINIT)
+ return BFA_TRUE;
+
+ bfa_ioc_fwver_get(ioc, &fwhdr);
+
+ if (swab32(fwhdr.exec) == BFI_BOOT_TYPE_NORMAL)
+ return BFA_TRUE;
+
+ bfa_trc(ioc, fwstate);
+ bfa_trc(ioc, fwhdr.exec);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+
return BFA_TRUE;
}
@@ -70,7 +94,7 @@ bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc)
* Notify other functions on HB failure.
*/
static void
-bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc)
+bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc)
{
writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
readl(ioc->ioc_regs.err_set);
@@ -108,9 +132,11 @@ bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)
if (ioc->port_id == 0) {
ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+ ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
} else {
ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
+ ioc->ioc_regs.alt_ioc_fwstate = (rb + BFA_IOC0_STATE_REG);
}
/*
@@ -181,10 +207,71 @@ bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
* will lock it instead of clearing it.
*/
readl(ioc->ioc_regs.ioc_sem_reg);
- bfa_ioc_hw_sem_release(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
}
+/*
+ * Synchronized IOC failure processing routines
+ */
+static void
+bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc)
+{
+}
+static void
+bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc)
+{
+}
+
+static void
+bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc)
+{
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+}
+
+static bfa_boolean_t
+bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
+{
+ uint32_t fwstate, alt_fwstate;
+ fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ /*
+ * At this point, this IOC is hoding the hw sem in the
+ * start path (fwcheck) OR in the disable/enable path
+ * OR to check if the other IOC has acknowledged failure.
+ *
+ * So, this IOC can be in UNINIT, INITING, DISABLED, FAIL
+ * or in MEMTEST states. In a normal scenario, this IOC
+ * can not be in OP state when this function is called.
+ *
+ * However, this IOC could still be in OP state when
+ * the OS driver is starting up, if the OptROM code has
+ * left it in that state.
+ *
+ * If we had marked this IOC's fwstate as BFI_IOC_FAIL
+ * in the failure case and now, if the fwstate is not
+ * BFI_IOC_FAIL it implies that the other PCI fn have
+ * reinitialized the ASIC or this IOC got disabled, so
+ * return TRUE.
+ */
+ if (fwstate == BFI_IOC_UNINIT ||
+ fwstate == BFI_IOC_INITING ||
+ fwstate == BFI_IOC_DISABLED ||
+ fwstate == BFI_IOC_MEMTEST ||
+ fwstate == BFI_IOC_OP)
+ return BFA_TRUE;
+ else {
+ alt_fwstate = readl(ioc->ioc_regs.alt_ioc_fwstate);
+ if (alt_fwstate == BFI_IOC_FAIL ||
+ alt_fwstate == BFI_IOC_DISABLED ||
+ alt_fwstate == BFI_IOC_UNINIT ||
+ alt_fwstate == BFI_IOC_INITING ||
+ alt_fwstate == BFI_IOC_MEMTEST)
+ return BFA_TRUE;
+ else
+ return BFA_FALSE;
+ }
+}
bfa_status_t
bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 115730c0aa7..008d129ddfc 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -15,12 +15,22 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_ioc.h"
#include "bfi_ctreg.h"
#include "bfa_defs.h"
BFA_TRC_FILE(CNA, IOC_CT);
+#define bfa_ioc_ct_sync_pos(__ioc) \
+ ((uint32_t) (1 << bfa_ioc_pcifn(__ioc)))
+#define BFA_IOC_SYNC_REQD_SH 16
+#define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff)
+#define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000)
+#define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH)
+#define bfa_ioc_ct_sync_reqd_pos(__ioc) \
+ (bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH)
+
/*
* forward declarations
*/
@@ -29,10 +39,14 @@ static void bfa_ioc_ct_firmware_unlock(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_notify_fail(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc);
+static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc);
-struct bfa_ioc_hwif_s hwif_ct;
+static struct bfa_ioc_hwif_s hwif_ct;
/*
* Called from bfa_ioc_attach() to map asic specific calls.
@@ -46,8 +60,12 @@ bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc)
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_notify_fail = bfa_ioc_ct_notify_fail;
hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+ hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
+ hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
+ hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
+ hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
ioc->ioc_hwif = &hwif_ct;
}
@@ -83,7 +101,8 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
*/
if (usecnt == 0) {
writel(1, ioc->ioc_regs.ioc_usage_reg);
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(0, ioc->ioc_regs.ioc_fail_sync);
bfa_trc(ioc, usecnt);
return BFA_TRUE;
}
@@ -94,14 +113,14 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
/*
* Use count cannot be non-zero and chip in uninitialized state.
*/
- bfa_assert(ioc_fwstate != BFI_IOC_UNINIT);
+ WARN_ON(ioc_fwstate == BFI_IOC_UNINIT);
/*
* Check if another driver with a different firmware is active
*/
bfa_ioc_fwver_get(ioc, &fwhdr);
if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
bfa_trc(ioc, usecnt);
return BFA_FALSE;
}
@@ -111,7 +130,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
*/
usecnt++;
writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
bfa_trc(ioc, usecnt);
return BFA_TRUE;
}
@@ -139,25 +158,27 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
*/
bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
- bfa_assert(usecnt > 0);
+ WARN_ON(usecnt <= 0);
usecnt--;
writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
bfa_trc(ioc, usecnt);
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
}
/*
* Notify other functions on HB failure.
*/
static void
-bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc)
+bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc)
{
if (ioc->cna) {
writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
+ writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
/* Wait for halt to take effect */
readl(ioc->ioc_regs.ll_halt);
+ readl(ioc->ioc_regs.alt_ll_halt);
} else {
writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
readl(ioc->ioc_regs.err_set);
@@ -209,15 +230,19 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
if (ioc->port_id == 0) {
ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+ ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+ ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
} else {
ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
+ ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+ ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
}
/*
@@ -235,6 +260,7 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
+ ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC);
/*
* sram memory access
@@ -313,7 +339,7 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
if (ioc->cna) {
bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
writel(0, ioc->ioc_regs.ioc_usage_reg);
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
}
/*
@@ -322,10 +348,80 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
* will lock it instead of clearing it.
*/
readl(ioc->ioc_regs.ioc_sem_reg);
- bfa_ioc_hw_sem_release(ioc);
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+}
+
+/*
+ * Synchronized IOC failure processing routines
+ */
+static void
+bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc)
+{
+ uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ uint32_t sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc);
+
+ writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static void
+bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc)
+{
+ uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ uint32_t sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) |
+ bfa_ioc_ct_sync_pos(ioc);
+
+ writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync);
+}
+
+static void
+bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc)
+{
+ uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+
+ writel((r32 | bfa_ioc_ct_sync_pos(ioc)),
+ ioc->ioc_regs.ioc_fail_sync);
}
+static bfa_boolean_t
+bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc)
+{
+ uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+ uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+ uint32_t sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
+ uint32_t tmp_ackd;
+
+ if (sync_ackd == 0)
+ return BFA_TRUE;
+
+ /*
+ * The check below is to see whether any other PCI fn
+ * has reinitialized the ASIC (reset sync_ackd bits)
+ * and failed again while this IOC was waiting for hw
+ * semaphore (in bfa_iocpf_sm_semwait()).
+ */
+ tmp_ackd = sync_ackd;
+ if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) &&
+ !(sync_ackd & bfa_ioc_ct_sync_pos(ioc)))
+ sync_ackd |= bfa_ioc_ct_sync_pos(ioc);
+
+ if (sync_reqd == sync_ackd) {
+ writel(bfa_ioc_ct_clear_sync_ackd(r32),
+ ioc->ioc_regs.ioc_fail_sync);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate);
+ return BFA_TRUE;
+ }
+
+ /*
+ * If another PCI fn reinitialized and failed again while
+ * this IOC was waiting for hw sem, the sync_ackd bit for
+ * this IOC need to be set again to allow reinitialization.
+ */
+ if (tmp_ackd != sync_ackd)
+ writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync);
+ return BFA_FALSE;
+}
/*
* Check the firmware state to know if pll_init has been completed already
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index 15407ab39e7..ab79ff6fdee 100644
--- a/drivers/scsi/bfa/bfa_modules.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -99,7 +99,6 @@ struct bfa_module_s {
void (*iocdisable) (struct bfa_s *bfa);
};
-extern struct bfa_module_s *hal_mods[];
struct bfa_s {
void *bfad; /* BFA driver instance */
@@ -116,8 +115,6 @@ struct bfa_s {
struct bfa_msix_s msix;
};
-extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX];
-extern bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[];
extern bfa_boolean_t bfa_auto_recover;
extern struct bfa_module_s hal_mod_sgpg;
extern struct bfa_module_s hal_mod_fcport;
diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h
deleted file mode 100644
index 65df62ef437..00000000000
--- a/drivers/scsi/bfa/bfa_os_inc.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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 __BFA_OS_INC_H__
-#define __BFA_OS_INC_H__
-
-#include <linux/types.h>
-#include <linux/version.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/idr.h>
-#include <linux/interrupt.h>
-#include <linux/cdev.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/vmalloc.h>
-#include <linux/workqueue.h>
-#include <linux/bitops.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_transport_fc.h>
-#include <scsi/scsi_transport.h>
-
-#ifdef __BIG_ENDIAN
-#define __BIGENDIAN
-#endif
-
-static inline u64 bfa_os_get_log_time(void)
-{
- u64 system_time = 0;
- struct timeval tv;
- do_gettimeofday(&tv);
-
- /* We are interested in seconds only. */
- system_time = tv.tv_sec;
- return system_time;
-}
-
-#define bfa_io_lat_clock_res_div HZ
-#define bfa_io_lat_clock_res_mul 1000
-
-#define BFA_LOG(level, bfad, mask, fmt, arg...) \
-do { \
- if (((mask) == 4) || (level[1] <= '4')) \
- dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg); \
-} while (0)
-
-#define bfa_swap_3b(_x) \
- ((((_x) & 0xff) << 16) | \
- ((_x) & 0x00ff00) | \
- (((_x) & 0xff0000) >> 16))
-
-#define bfa_os_swap_sgaddr(_x) ((u64)( \
- (((u64)(_x) & (u64)0x00000000000000ffull) << 32) | \
- (((u64)(_x) & (u64)0x000000000000ff00ull) << 32) | \
- (((u64)(_x) & (u64)0x0000000000ff0000ull) << 32) | \
- (((u64)(_x) & (u64)0x00000000ff000000ull) << 32) | \
- (((u64)(_x) & (u64)0x000000ff00000000ull) >> 32) | \
- (((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32) | \
- (((u64)(_x) & (u64)0x00ff000000000000ull) >> 32) | \
- (((u64)(_x) & (u64)0xff00000000000000ull) >> 32)))
-
-#ifndef __BIGENDIAN
-#define bfa_os_hton3b(_x) bfa_swap_3b(_x)
-#define bfa_os_sgaddr(_x) (_x)
-#else
-#define bfa_os_hton3b(_x) (_x)
-#define bfa_os_sgaddr(_x) bfa_os_swap_sgaddr(_x)
-#endif
-
-#define bfa_os_ntoh3b(_x) bfa_os_hton3b(_x)
-#define bfa_os_u32(__pa64) ((__pa64) >> 32)
-
-#define BFA_TRC_TS(_trcm) \
- ({ \
- struct timeval tv; \
- \
- do_gettimeofday(&tv); \
- (tv.tv_sec*1000000+tv.tv_usec); \
- })
-
-#define boolean_t int
-
-/*
- * For current time stamp, OS API will fill-in
- */
-struct bfa_timeval_s {
- u32 tv_sec; /* seconds */
- u32 tv_usec; /* microseconds */
-};
-
-static inline void
-bfa_os_gettimeofday(struct bfa_timeval_s *tv)
-{
- struct timeval tmp_tv;
-
- do_gettimeofday(&tmp_tv);
- tv->tv_sec = (u32) tmp_tv.tv_sec;
- tv->tv_usec = (u32) tmp_tv.tv_usec;
-}
-
-static inline void
-wwn2str(char *wwn_str, u64 wwn)
-{
- union {
- u64 wwn;
- u8 byte[8];
- } w;
-
- w.wwn = wwn;
- sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0],
- w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5],
- w.byte[6], w.byte[7]);
-}
-
-static inline void
-fcid2str(char *fcid_str, u32 fcid)
-{
- union {
- u32 fcid;
- u8 byte[4];
- } f;
-
- f.fcid = fcid;
- sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]);
-}
-
-#endif /* __BFA_OS_INC_H__ */
diff --git a/drivers/scsi/bfa/bfa_plog.h b/drivers/scsi/bfa/bfa_plog.h
index 501f0ed35cf..1c9baa68339 100644
--- a/drivers/scsi/bfa/bfa_plog.h
+++ b/drivers/scsi/bfa/bfa_plog.h
@@ -151,9 +151,5 @@ void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
enum bfa_plog_eid event, u16 misc,
struct fchs_s *fchdr, u32 pld_w0);
-void bfa_plog_clear(struct bfa_plog_s *plog);
-void bfa_plog_enable(struct bfa_plog_s *plog);
-void bfa_plog_disable(struct bfa_plog_s *plog);
-bfa_boolean_t bfa_plog_get_setting(struct bfa_plog_s *plog);
#endif /* __BFA_PORTLOG_H__ */
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index fff96226a38..3f8e9d6066e 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -15,6 +15,7 @@
* General Public License for more details.
*/
+#include "bfad_drv.h"
#include "bfa_defs_svc.h"
#include "bfa_port.h"
#include "bfi.h"
@@ -29,14 +30,14 @@ static void
bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
{
u32 *dip = (u32 *) stats;
- u32 t0, t1;
+ __be32 t0, t1;
int i;
for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32);
i += 2) {
t0 = dip[i];
t1 = dip[i + 1];
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
dip[i] = be32_to_cpu(t0);
dip[i + 1] = be32_to_cpu(t1);
#else
@@ -96,13 +97,13 @@ 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;
+ struct timeval tv;
memcpy(port->stats, port->stats_dma.kva,
sizeof(union bfa_port_stats_u));
bfa_port_stats_swap(port, port->stats);
- bfa_os_gettimeofday(&tv);
+ do_gettimeofday(&tv);
port->stats->fc.secs_reset = tv.tv_sec - port->stats_reset_time;
}
@@ -124,7 +125,7 @@ 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;
+ struct timeval tv;
port->stats_status = status;
port->stats_busy = BFA_FALSE;
@@ -132,7 +133,7 @@ bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)
/*
* re-initialize time stamp for stats reset
*/
- bfa_os_gettimeofday(&tv);
+ do_gettimeofday(&tv);
port->stats_reset_time = tv.tv_sec;
if (port->stats_cbfn) {
@@ -185,7 +186,7 @@ bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
}
}
@@ -432,9 +433,9 @@ void
bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
void *dev, struct bfa_trc_mod_s *trcmod)
{
- struct bfa_timeval_s tv;
+ struct timeval tv;
- bfa_assert(port);
+ WARN_ON(!port);
port->dev = dev;
port->ioc = ioc;
@@ -447,27 +448,13 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
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);
+ list_add_tail(&port->hbfail.qe, &port->ioc->hb_notify_q);
/*
* initialize time stamp for stats reset
*/
- bfa_os_gettimeofday(&tv);
+ do_gettimeofday(&tv);
port->stats_reset_time = tv.tv_sec;
bfa_trc(port, 0);
}
-
-/*
- * bfa_port_detach()
- *
- *
- * @param[in] port - Pointer to the Port module data structure
- *
- * @return void
- */
-void
-bfa_port_detach(struct bfa_port_s *port)
-{
- bfa_trc(port, 0);
-}
diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h
index dbce9dfd056..c4ee9db6b47 100644
--- a/drivers/scsi/bfa/bfa_port.h
+++ b/drivers/scsi/bfa/bfa_port.h
@@ -48,7 +48,6 @@ struct bfa_port_s {
void bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
void *dev, struct bfa_trc_mod_s *trcmod);
-void bfa_port_detach(struct bfa_port_s *port);
void bfa_port_hbfail(void *arg);
bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 37e16ac8f24..1d34921f88b 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -15,11 +15,10 @@
* General Public License for more details.
*/
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
#include "bfa_plog.h"
#include "bfa_cs.h"
#include "bfa_modules.h"
-#include "bfad_drv.h"
BFA_TRC_FILE(HAL, FCXP);
BFA_MODULE(fcxp);
@@ -41,19 +40,6 @@ BFA_MODULE(uf);
#define BFA_LPS_MAX_VPORTS_SUPP_CB 255
#define BFA_LPS_MAX_VPORTS_SUPP_CT 190
-/*
- * lps_pvt BFA LPS private functions
- */
-
-enum bfa_lps_event {
- BFA_LPS_SM_LOGIN = 1, /* login request from user */
- BFA_LPS_SM_LOGOUT = 2, /* logout request from user */
- BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */
- BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */
- BFA_LPS_SM_DELETE = 5, /* lps delete from user */
- BFA_LPS_SM_OFFLINE = 6, /* Link is offline */
- BFA_LPS_SM_RX_CVL = 7, /* Rx clear virtual link */
-};
/*
* FC PORT related definitions
@@ -66,7 +52,6 @@ enum bfa_lps_event {
((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
-
/*
* BFA port state machine events
*/
@@ -113,19 +98,6 @@ enum bfa_fcport_ln_sm_event {
} \
} while (0)
-
-enum bfa_rport_event {
- BFA_RPORT_SM_CREATE = 1, /* rport create event */
- BFA_RPORT_SM_DELETE = 2, /* deleting an existing rport */
- BFA_RPORT_SM_ONLINE = 3, /* rport is online */
- BFA_RPORT_SM_OFFLINE = 4, /* rport is offline */
- BFA_RPORT_SM_FWRSP = 5, /* firmware response */
- BFA_RPORT_SM_HWFAIL = 6, /* IOC h/w failure */
- BFA_RPORT_SM_QOS_SCN = 7, /* QoS SCN from firmware */
- BFA_RPORT_SM_SET_SPEED = 8, /* Set Rport Speed */
- BFA_RPORT_SM_QRESUME = 9, /* space in requeue queue */
-};
-
/*
* forward declarations FCXP related functions
*/
@@ -159,6 +131,7 @@ static void bfa_lps_reqq_resume(void *lps_arg);
static void bfa_lps_free(struct bfa_lps_s *lps);
static void bfa_lps_send_login(struct bfa_lps_s *lps);
static void bfa_lps_send_logout(struct bfa_lps_s *lps);
+static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
static void bfa_lps_login_comp(struct bfa_lps_s *lps);
static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
@@ -171,6 +144,8 @@ static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
event);
static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
+ enum bfa_lps_event event);
static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
event);
@@ -312,6 +287,18 @@ plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
return 0;
}
+static u64
+bfa_get_log_time(void)
+{
+ u64 system_time = 0;
+ struct timeval tv;
+ do_gettimeofday(&tv);
+
+ /* We are interested in seconds only. */
+ system_time = tv.tv_sec;
+ return system_time;
+}
+
static void
bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
{
@@ -322,7 +309,7 @@ bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
return;
if (plkd_validate_logrec(pl_rec)) {
- bfa_assert(0);
+ WARN_ON(1);
return;
}
@@ -332,7 +319,7 @@ bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
- pl_recp->tv = bfa_os_get_log_time();
+ pl_recp->tv = bfa_get_log_time();
BFA_PL_LOG_REC_INCR(plog->tail);
if (plog->head == plog->tail)
@@ -437,29 +424,6 @@ bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
}
}
-void
-bfa_plog_clear(struct bfa_plog_s *plog)
-{
- plog->head = plog->tail = 0;
-}
-
-void
-bfa_plog_enable(struct bfa_plog_s *plog)
-{
- plog->plog_enabled = 1;
-}
-
-void
-bfa_plog_disable(struct bfa_plog_s *plog)
-{
- plog->plog_enabled = 0;
-}
-
-bfa_boolean_t
-bfa_plog_get_setting(struct bfa_plog_s *plog)
-{
- return (bfa_boolean_t)plog->plog_enabled;
-}
/*
* fcxp_pvt BFA FCXP private functions
@@ -637,15 +601,15 @@ bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
bfa_fcxp_get_sglen_t sglen_cbfn)
{
- bfa_assert(bfa != NULL);
+ WARN_ON(bfa == NULL);
bfa_trc(bfa, fcxp->fcxp_tag);
if (n_sgles == 0) {
*use_ibuf = 1;
} else {
- bfa_assert(*sga_cbfn != NULL);
- bfa_assert(*sglen_cbfn != NULL);
+ WARN_ON(*sga_cbfn == NULL);
+ WARN_ON(*sglen_cbfn == NULL);
*use_ibuf = 0;
*r_sga_cbfn = sga_cbfn;
@@ -657,7 +621,7 @@ bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
* alloc required sgpgs
*/
if (n_sgles > BFI_SGE_INLINE)
- bfa_assert(0);
+ WARN_ON(1);
}
}
@@ -671,7 +635,7 @@ bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
{
- bfa_assert(bfa != NULL);
+ WARN_ON(bfa == NULL);
bfa_trc(bfa, fcxp->fcxp_tag);
@@ -708,7 +672,7 @@ bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
return;
}
- bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
+ WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
list_del(&fcxp->qe);
list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
}
@@ -757,7 +721,7 @@ hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
- bfa_assert(fcxp->send_cbfn != NULL);
+ WARN_ON(fcxp->send_cbfn == NULL);
hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
@@ -913,13 +877,13 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
BFA_FCXP_REQ_PLD_PA(fcxp));
} else {
if (fcxp->nreq_sgles > 0) {
- bfa_assert(fcxp->nreq_sgles == 1);
+ WARN_ON(fcxp->nreq_sgles != 1);
hal_fcxp_set_local_sges(send_req->req_sge,
reqi->req_tot_len,
fcxp->req_sga_cbfn(fcxp->caller,
0));
} else {
- bfa_assert(reqi->req_tot_len == 0);
+ WARN_ON(reqi->req_tot_len != 0);
hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
}
}
@@ -928,20 +892,20 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
* setup rsp sgles
*/
if (fcxp->use_irspbuf == 1) {
- bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
+ WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
BFA_FCXP_RSP_PLD_PA(fcxp));
} else {
if (fcxp->nrsp_sgles > 0) {
- bfa_assert(fcxp->nrsp_sgles == 1);
+ WARN_ON(fcxp->nrsp_sgles != 1);
hal_fcxp_set_local_sges(send_req->rsp_sge,
rspi->rsp_maxlen,
fcxp->rsp_sga_cbfn(fcxp->caller,
0));
} else {
- bfa_assert(rspi->rsp_maxlen == 0);
+ WARN_ON(rspi->rsp_maxlen != 0);
hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
}
}
@@ -955,10 +919,6 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
}
/*
- * hal_fcxp_api BFA FCXP API
- */
-
-/*
* Allocate an FCXP instance to send a response or to send a request
* that has a response. Request/response buffers are allocated by caller.
*
@@ -990,7 +950,7 @@ bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
{
struct bfa_fcxp_s *fcxp = NULL;
- bfa_assert(bfa != NULL);
+ WARN_ON(bfa == NULL);
fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
if (fcxp == NULL)
@@ -1017,7 +977,7 @@ bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
void *reqbuf;
- bfa_assert(fcxp->use_ireqbuf == 1);
+ WARN_ON(fcxp->use_ireqbuf != 1);
reqbuf = ((u8 *)mod->req_pld_list_kva) +
fcxp->fcxp_tag * mod->req_pld_sz;
return reqbuf;
@@ -1044,7 +1004,7 @@ bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
void *rspbuf;
- bfa_assert(fcxp->use_irspbuf == 1);
+ WARN_ON(fcxp->use_irspbuf != 1);
rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
fcxp->fcxp_tag * mod->rsp_pld_sz;
@@ -1052,7 +1012,7 @@ bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
}
/*
- * Free the BFA FCXP
+ * Free the BFA FCXP
*
* @param[in] fcxp BFA fcxp pointer
*
@@ -1063,7 +1023,7 @@ bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
{
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
- bfa_assert(fcxp != NULL);
+ WARN_ON(fcxp == NULL);
bfa_trc(mod->bfa, fcxp->fcxp_tag);
bfa_fcxp_put(fcxp);
}
@@ -1142,7 +1102,7 @@ bfa_status_t
bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
{
bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
- bfa_assert(0);
+ WARN_ON(1);
return BFA_STATUS_OK;
}
@@ -1157,7 +1117,7 @@ bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
{
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
- bfa_assert(list_empty(&mod->fcxp_free_q));
+ WARN_ON(!list_empty(&mod->fcxp_free_q));
wqe->alloc_cbfn = alloc_cbfn;
wqe->alloc_cbarg = alloc_cbarg;
@@ -1178,7 +1138,7 @@ bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
{
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
- bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
+ WARN_ON(!bfa_q_is_on_q(&mod->wait_q, wqe));
list_del(&wqe->qe);
}
@@ -1199,12 +1159,6 @@ bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
fcxp->send_cbfn = bfa_fcxp_null_comp;
}
-
-
-/*
- * hal_fcxp_public BFA FCXP public functions
- */
-
void
bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
{
@@ -1215,7 +1169,7 @@ bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
default:
bfa_trc(bfa, msg->mhdr.msg_id);
- bfa_assert(0);
+ WARN_ON(1);
}
}
@@ -1303,6 +1257,12 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
else
bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
+ /* If N2N, send the assigned PID to FW */
+ bfa_trc(lps->bfa, lps->fport);
+ bfa_trc(lps->bfa, lps->lp_pid);
+
+ if (!lps->fport && lps->lp_pid)
+ bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
} else {
bfa_sm_set_state(lps, bfa_lps_sm_init);
if (lps->fdisc)
@@ -1321,6 +1281,11 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
bfa_sm_set_state(lps, bfa_lps_sm_init);
break;
+ case BFA_LPS_SM_SET_N2N_PID:
+ bfa_trc(lps->bfa, lps->fport);
+ bfa_trc(lps->bfa, lps->lp_pid);
+ break;
+
default:
bfa_sm_fault(lps->bfa, event);
}
@@ -1389,9 +1354,59 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
break;
+ case BFA_LPS_SM_SET_N2N_PID:
+ if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+ bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
+ bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+ } else
+ bfa_lps_send_set_n2n_pid(lps);
+ break;
+
+ case BFA_LPS_SM_OFFLINE:
+ case BFA_LPS_SM_DELETE:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ break;
+
+ default:
+ bfa_sm_fault(lps->bfa, event);
+ }
+}
+
+/*
+ * login complete
+ */
+static void
+bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+ bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, event);
+
+ switch (event) {
+ case BFA_LPS_SM_RESUME:
+ bfa_sm_set_state(lps, bfa_lps_sm_online);
+ bfa_lps_send_set_n2n_pid(lps);
+ break;
+
+ case BFA_LPS_SM_LOGOUT:
+ bfa_sm_set_state(lps, bfa_lps_sm_logowait);
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_LOGO, 0, "Logout");
+ break;
+
+ case BFA_LPS_SM_RX_CVL:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ bfa_reqq_wcancel(&lps->wqe);
+
+ /* Let the vport module know about this event */
+ bfa_lps_cvl_event(lps);
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
+ break;
+
case BFA_LPS_SM_OFFLINE:
case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
+ bfa_reqq_wcancel(&lps->wqe);
break;
default:
@@ -1540,15 +1555,16 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
struct bfa_lps_s *lps;
- bfa_assert(rsp->lp_tag < mod->num_lps);
+ WARN_ON(rsp->lp_tag >= mod->num_lps);
lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
lps->status = rsp->status;
switch (rsp->status) {
case BFA_STATUS_OK:
lps->fport = rsp->f_port;
+ if (lps->fport)
+ lps->lp_pid = rsp->lp_pid;
lps->npiv_en = rsp->npiv_en;
- lps->lp_pid = rsp->lp_pid;
lps->pr_bbcred = be16_to_cpu(rsp->bb_credit);
lps->pr_pwwn = rsp->port_name;
lps->pr_nwwn = rsp->node_name;
@@ -1587,7 +1603,7 @@ bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
struct bfa_lps_s *lps;
- bfa_assert(rsp->lp_tag < mod->num_lps);
+ WARN_ON(rsp->lp_tag >= mod->num_lps);
lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
@@ -1640,7 +1656,7 @@ bfa_lps_send_login(struct bfa_lps_s *lps)
struct bfi_lps_login_req_s *m;
m = bfa_reqq_next(lps->bfa, lps->reqq);
- bfa_assert(m);
+ WARN_ON(!m);
bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
bfa_lpuid(lps->bfa));
@@ -1665,7 +1681,7 @@ bfa_lps_send_logout(struct bfa_lps_s *lps)
struct bfi_lps_logout_req_s *m;
m = bfa_reqq_next(lps->bfa, lps->reqq);
- bfa_assert(m);
+ WARN_ON(!m);
bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
bfa_lpuid(lps->bfa));
@@ -1676,6 +1692,25 @@ bfa_lps_send_logout(struct bfa_lps_s *lps)
}
/*
+ * send n2n pid set request to firmware
+ */
+static void
+bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
+{
+ struct bfi_lps_n2n_pid_req_s *m;
+
+ m = bfa_reqq_next(lps->bfa, lps->reqq);
+ WARN_ON(!m);
+
+ bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
+ bfa_lpuid(lps->bfa));
+
+ m->lp_tag = lps->lp_tag;
+ m->lp_pid = lps->lp_pid;
+ bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/*
* Indirect login completion handler for non-fcs
*/
static void
@@ -1853,14 +1888,6 @@ bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
}
-/*
- * Initiate a lport logout (flogi).
- */
-void
-bfa_lps_flogo(struct bfa_lps_s *lps)
-{
- bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
-}
/*
* Initiate a lport FDSIC logout.
@@ -1871,24 +1898,6 @@ bfa_lps_fdisclogo(struct bfa_lps_s *lps)
bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
}
-/*
- * Discard a pending login request -- should be called only for
- * link down handling.
- */
-void
-bfa_lps_discard(struct bfa_lps_s *lps)
-{
- bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
-}
-
-/*
- * Return lport services tag
- */
-u8
-bfa_lps_get_tag(struct bfa_lps_s *lps)
-{
- return lps->lp_tag;
-}
/*
* Return lport services tag given the pid
@@ -1909,55 +1918,6 @@ bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
return 0;
}
-/*
- * return if fabric login indicates support for NPIV
- */
-bfa_boolean_t
-bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
-{
- return lps->npiv_en;
-}
-
-/*
- * Return TRUE if attached to F-Port, else return FALSE
- */
-bfa_boolean_t
-bfa_lps_is_fport(struct bfa_lps_s *lps)
-{
- return lps->fport;
-}
-
-/*
- * Return TRUE if attached to a Brocade Fabric
- */
-bfa_boolean_t
-bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
-{
- return lps->brcd_switch;
-}
-/*
- * return TRUE if authentication is required
- */
-bfa_boolean_t
-bfa_lps_is_authreq(struct bfa_lps_s *lps)
-{
- return lps->auth_req;
-}
-
-bfa_eproto_status_t
-bfa_lps_get_extstatus(struct bfa_lps_s *lps)
-{
- return lps->ext_status;
-}
-
-/*
- * return port id assigned to the lport
- */
-u32
-bfa_lps_get_pid(struct bfa_lps_s *lps)
-{
- return lps->lp_pid;
-}
/*
* return port id assigned to the base lport
@@ -1971,57 +1931,16 @@ bfa_lps_get_base_pid(struct bfa_s *bfa)
}
/*
- * Return bb_credit assigned in FLOGI response
- */
-u16
-bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
-{
- return lps->pr_bbcred;
-}
-
-/*
- * Return peer port name
- */
-wwn_t
-bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
-{
- return lps->pr_pwwn;
-}
-
-/*
- * Return peer node name
- */
-wwn_t
-bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
-{
- return lps->pr_nwwn;
-}
-
-/*
- * return reason code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
-{
- return lps->lsrjt_rsn;
-}
-
-/*
- * return explanation code if login request is rejected
+ * Set PID in case of n2n (which is assigned during PLOGI)
*/
-u8
-bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
+void
+bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
{
- return lps->lsrjt_expl;
-}
+ bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, n2n_pid);
-/*
- * Return fpma/spma MAC for lport
- */
-mac_t
-bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
-{
- return lps->lp_mac;
+ lps->lp_pid = n2n_pid;
+ bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
}
/*
@@ -2050,7 +1969,7 @@ bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
default:
bfa_trc(bfa, m->mhdr.msg_id);
- bfa_assert(0);
+ WARN_ON(1);
}
}
@@ -2068,6 +1987,8 @@ bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
/*
* Start event after IOC is configured and BFA is started.
*/
+ fcport->use_flash_cfg = BFA_TRUE;
+
if (bfa_fcport_send_enable(fcport)) {
bfa_trc(fcport->bfa, BFA_TRUE);
bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
@@ -2178,7 +2099,7 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
bfa_fcport_update_linkinfo(fcport);
bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
- bfa_assert(fcport->event_cbfn);
+ WARN_ON(!fcport->event_cbfn);
bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
break;
@@ -2229,7 +2150,7 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
case BFA_FCPORT_SM_LINKUP:
bfa_fcport_update_linkinfo(fcport);
bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
- bfa_assert(fcport->event_cbfn);
+ WARN_ON(!fcport->event_cbfn);
bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
@@ -2803,12 +2724,6 @@ bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
}
}
-
-
-/*
- * hal_port_private
- */
-
static void
__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
{
@@ -2839,7 +2754,7 @@ bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
}
}
@@ -2906,7 +2821,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_port_cfg_s *port_cfg = &fcport->cfg;
struct bfa_fcport_ln_s *ln = &fcport->ln;
- struct bfa_timeval_s tv;
+ struct timeval tv;
memset(fcport, 0, sizeof(struct bfa_fcport_s));
fcport->bfa = bfa;
@@ -2920,7 +2835,7 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
/*
* initialize time stamp for stats reset
*/
- bfa_os_gettimeofday(&tv);
+ do_gettimeofday(&tv);
fcport->stats_reset_time = tv.tv_sec;
/*
@@ -3039,6 +2954,7 @@ bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
m->port_cfg = fcport->cfg;
m->msgtag = fcport->msgtag;
m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
+ m->use_flash_cfg = fcport->use_flash_cfg;
bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
@@ -3089,8 +3005,8 @@ bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
static void
bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
{
- fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc);
- fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc);
+ fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
+ fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
bfa_trc(fcport->bfa, fcport->pwwn);
bfa_trc(fcport->bfa, fcport->nwwn);
@@ -3127,7 +3043,7 @@ bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
struct bfa_qos_stats_s *s)
{
u32 *dip = (u32 *) d;
- u32 *sip = (u32 *) s;
+ __be32 *sip = (__be32 *) s;
int i;
/* Now swap the 32 bit fields */
@@ -3140,12 +3056,12 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
struct bfa_fcoe_stats_s *s)
{
u32 *dip = (u32 *) d;
- u32 *sip = (u32 *) s;
+ __be32 *sip = (__be32 *) s;
int i;
for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
i = i + 2) {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
dip[i] = be32_to_cpu(sip[i]);
dip[i + 1] = be32_to_cpu(sip[i + 1]);
#else
@@ -3162,7 +3078,7 @@ __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;
+ struct timeval tv;
/* Swap FC QoS or FCoE stats */
if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
@@ -3174,7 +3090,7 @@ __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
&fcport->stats_ret->fcoe,
&fcport->stats->fcoe);
- bfa_os_gettimeofday(&tv);
+ do_gettimeofday(&tv);
fcport->stats_ret->fcoe.secs_reset =
tv.tv_sec - fcport->stats_reset_time;
}
@@ -3233,12 +3149,12 @@ __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
struct bfa_fcport_s *fcport = cbarg;
if (complete) {
- struct bfa_timeval_s tv;
+ struct timeval tv;
/*
* re-initialize time stamp for stats reset
*/
- bfa_os_gettimeofday(&tv);
+ do_gettimeofday(&tv);
fcport->stats_reset_time = tv.tv_sec;
fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
@@ -3303,8 +3219,8 @@ bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
int link_bm = 0;
bfa_trc(fcport->bfa, fcport->cfg.trunked);
- bfa_assert(scn->trunk_state == BFA_TRUNK_ONLINE ||
- scn->trunk_state == BFA_TRUNK_OFFLINE);
+ WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
+ scn->trunk_state != BFA_TRUNK_OFFLINE);
bfa_trc(fcport->bfa, trunk->attr.state);
bfa_trc(fcport->bfa, scn->trunk_state);
@@ -3396,12 +3312,6 @@ bfa_trunk_iocdisable(struct bfa_s *bfa)
}
}
-
-
-/*
- * hal_port_public
- */
-
/*
* Called to initialize port attributes
*/
@@ -3419,9 +3329,9 @@ bfa_fcport_init(struct bfa_s *bfa)
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);
+ WARN_ON(!fcport->cfg.maxfrsize);
+ WARN_ON(!fcport->cfg.rx_bbcredit);
+ WARN_ON(!fcport->speed_sup);
}
/*
@@ -3441,8 +3351,28 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
switch (msg->mhdr.msg_id) {
case BFI_FCPORT_I2H_ENABLE_RSP:
- if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
+ if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
+
+ if (fcport->use_flash_cfg) {
+ fcport->cfg = i2hmsg.penable_rsp->port_cfg;
+ fcport->cfg.maxfrsize =
+ cpu_to_be16(fcport->cfg.maxfrsize);
+ fcport->cfg.path_tov =
+ cpu_to_be16(fcport->cfg.path_tov);
+ fcport->cfg.q_depth =
+ cpu_to_be16(fcport->cfg.q_depth);
+
+ if (fcport->cfg.trunked)
+ fcport->trunk.attr.state =
+ BFA_TRUNK_OFFLINE;
+ else
+ fcport->trunk.attr.state =
+ BFA_TRUNK_DISABLED;
+ fcport->use_flash_cfg = BFA_FALSE;
+ }
+
bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
+ }
break;
case BFI_FCPORT_I2H_DISABLE_RSP:
@@ -3498,17 +3428,11 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
break;
}
}
-
-
-/*
- * hal_port_api
- */
-
/*
* Registered callback for port events.
*/
@@ -3732,8 +3656,8 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_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);
+ attr->factorypwwn = bfa->ioc.attr->mfg_pwwn;
+ attr->factorynwwn = bfa->ioc.attr->mfg_nwwn;
memcpy(&attr->pport_cfg, &fcport->cfg,
sizeof(struct bfa_port_cfg_s));
@@ -3751,7 +3675,7 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
/* beacon attributes */
attr->beacon = fcport->beacon;
attr->link_e2e_beacon = fcport->link_e2e_beacon;
- attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog);
+ attr->plog_enabled = (bfa_boolean_t)fcport->bfa->plog->plog_enabled;
attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
@@ -3818,89 +3742,6 @@ bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
return BFA_STATUS_OK;
}
-/*
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
- bfa_cb_port_t cbfn, void *cbarg)
-{
- /* Meaningful only for FC mode */
- bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
- return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/*
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
-{
- /* Meaningful only for FC mode */
- bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
- return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-/*
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
- bfa_cb_port_t cbfn, void *cbarg)
-{
- /* Meaningful only for FCoE mode */
- bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
- return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/*
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
-{
- /* Meaningful only for FCoE mode */
- bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
- return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-void
-bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- qos_attr->state = fcport->qos_attr.state;
- qos_attr->total_bb_cr = be32_to_cpu(fcport->qos_attr.total_bb_cr);
-}
-
-void
-bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
- struct bfa_qos_vc_attr_s *qos_vc_attr)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
- u32 i = 0;
-
- qos_vc_attr->total_vc_count = be16_to_cpu(bfa_vc_attr->total_vc_count);
- qos_vc_attr->shared_credit = be16_to_cpu(bfa_vc_attr->shared_credit);
- qos_vc_attr->elp_opmode_flags =
- be32_to_cpu(bfa_vc_attr->elp_opmode_flags);
-
- /* Individual VC info */
- while (i < qos_vc_attr->total_vc_count) {
- qos_vc_attr->vc_info[i].vc_credit =
- bfa_vc_attr->vc_info[i].vc_credit;
- qos_vc_attr->vc_info[i].borrow_credit =
- bfa_vc_attr->vc_info[i].borrow_credit;
- qos_vc_attr->vc_info[i].priority =
- bfa_vc_attr->vc_info[i].priority;
- ++i;
- }
-}
/*
* Fetch port attributes.
@@ -3924,60 +3765,6 @@ bfa_fcport_is_ratelim(struct bfa_s *bfa)
}
-void
-bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
-
- bfa_trc(bfa, on_off);
- bfa_trc(bfa, fcport->cfg.qos_enabled);
-
- bfa_trc(bfa, ioc_type);
-
- 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
-bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, on_off);
- bfa_trc(bfa, fcport->cfg.ratelimit);
-
- fcport->cfg.ratelimit = on_off;
- if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
- fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
-}
-
-/*
- * Configure default minimum ratelim speed
- */
-bfa_status_t
-bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, speed);
-
- /* Auto and speeds greater than the supported speed, are invalid */
- if ((speed == BFA_PORT_SPEED_AUTO) || (speed > fcport->speed_sup)) {
- bfa_trc(bfa, fcport->speed_sup);
- return BFA_STATUS_UNSUPP_SPEED;
- }
-
- fcport->cfg.trl_def_speed = speed;
-
- return BFA_STATUS_OK;
-}
-
/*
* Get default minimum ratelim speed
*/
@@ -3990,32 +3777,6 @@ bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
return fcport->cfg.trl_def_speed;
}
-void
-bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, status);
- bfa_trc(bfa, fcport->diag_busy);
-
- fcport->diag_busy = status;
-}
-
-void
-bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
- bfa_boolean_t link_e2e_beacon)
-{
- struct bfa_s *bfa = dev;
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, beacon);
- bfa_trc(bfa, link_e2e_beacon);
- bfa_trc(bfa, fcport->beacon);
- bfa_trc(bfa, fcport->link_e2e_beacon);
-
- fcport->beacon = beacon;
- fcport->link_e2e_beacon = link_e2e_beacon;
-}
bfa_boolean_t
bfa_fcport_is_linkup(struct bfa_s *bfa)
@@ -4036,63 +3797,6 @@ bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
return fcport->cfg.qos_enabled;
}
-bfa_status_t
-bfa_trunk_get_attr(struct bfa_s *bfa, struct bfa_trunk_attr_s *attr)
-
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
-
- bfa_trc(bfa, fcport->cfg.trunked);
- bfa_trc(bfa, trunk->attr.state);
- *attr = trunk->attr;
- attr->port_id = bfa_lps_get_base_pid(bfa);
-
- return BFA_STATUS_OK;
-}
-
-void
-bfa_trunk_enable_cfg(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
-
- bfa_trc(bfa, 1);
- trunk->attr.state = BFA_TRUNK_OFFLINE;
- fcport->cfg.trunked = BFA_TRUE;
-}
-
-bfa_status_t
-bfa_trunk_enable(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
-
- bfa_trc(bfa, 1);
-
- trunk->attr.state = BFA_TRUNK_OFFLINE;
- bfa_fcport_disable(bfa);
- fcport->cfg.trunked = BFA_TRUE;
- bfa_fcport_enable(bfa);
-
- return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_trunk_disable(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
-
- bfa_trc(bfa, 0);
- trunk->attr.state = BFA_TRUNK_DISABLED;
- bfa_fcport_disable(bfa);
- fcport->cfg.trunked = BFA_FALSE;
- bfa_fcport_enable(bfa);
- return BFA_STATUS_OK;
-}
-
-
/*
* Rport State machine functions
*/
@@ -4606,8 +4310,8 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
mod->rps_list = rp;
mod->num_rports = cfg->fwcfg.num_rports;
- bfa_assert(mod->num_rports &&
- !(mod->num_rports & (mod->num_rports - 1)));
+ WARN_ON(!mod->num_rports ||
+ (mod->num_rports & (mod->num_rports - 1)));
for (i = 0; i < mod->num_rports; i++, rp++) {
memset(rp, 0, sizeof(struct bfa_rport_s));
@@ -4675,7 +4379,7 @@ bfa_rport_free(struct bfa_rport_s *rport)
{
struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
- bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
+ WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
list_del(&rport->qe);
list_add_tail(&rport->qe, &mod->rp_free_q);
}
@@ -4788,13 +4492,13 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
rp->fw_handle = msg.create_rsp->fw_handle;
rp->qos_attr = msg.create_rsp->qos_attr;
- bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+ WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
break;
case BFI_RPORT_I2H_DELETE_RSP:
rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
- bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+ WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
break;
@@ -4806,7 +4510,7 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
default:
bfa_trc(bfa, m->mhdr.msg_id);
- bfa_assert(0);
+ WARN_ON(1);
}
}
@@ -4828,24 +4532,18 @@ bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
rp->bfa = bfa;
rp->rport_drv = rport_drv;
- bfa_rport_clear_stats(rp);
+ memset(&rp->stats, 0, sizeof(rp->stats));
- bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
+ WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
return rp;
}
void
-bfa_rport_delete(struct bfa_rport_s *rport)
-{
- bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
-}
-
-void
bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
{
- bfa_assert(rport_info->max_frmsz != 0);
+ WARN_ON(rport_info->max_frmsz == 0);
/*
* Some JBODs are seen to be not setting PDU size correctly in PLOGI
@@ -4861,43 +4559,15 @@ bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
}
void
-bfa_rport_offline(struct bfa_rport_s *rport)
-{
- bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
-}
-
-void
bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
{
- bfa_assert(speed != 0);
- bfa_assert(speed != BFA_PORT_SPEED_AUTO);
+ WARN_ON(speed == 0);
+ WARN_ON(speed == BFA_PORT_SPEED_AUTO);
rport->rport_info.speed = speed;
bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
}
-void
-bfa_rport_get_stats(struct bfa_rport_s *rport,
- struct bfa_rport_hal_stats_s *stats)
-{
- *stats = rport->stats;
-}
-
-void
-bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
- struct bfa_rport_qos_attr_s *qos_attr)
-{
- qos_attr->qos_priority = rport->qos_attr.qos_priority;
- qos_attr->qos_flow_id = be32_to_cpu(rport->qos_attr.qos_flow_id);
-
-}
-
-void
-bfa_rport_clear_stats(struct bfa_rport_s *rport)
-{
- memset(&rport->stats, 0, sizeof(rport->stats));
-}
-
/*
* SGPG related functions
@@ -4952,7 +4622,7 @@ bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
sgpg_pa.pa = mod->sgpg_arr_pa;
mod->free_sgpgs = mod->num_sgpgs;
- bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
+ WARN_ON(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1));
for (i = 0; i < mod->num_sgpgs; i++) {
memset(hsgpg, 0, sizeof(*hsgpg));
@@ -4993,12 +4663,6 @@ bfa_sgpg_iocdisable(struct bfa_s *bfa)
{
}
-
-
-/*
- * hal_sgpg_public BFA SGPG public functions
- */
-
bfa_status_t
bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
{
@@ -5006,14 +4670,12 @@ bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
struct bfa_sgpg_s *hsgpg;
int i;
- bfa_trc_fp(bfa, nsgpgs);
-
if (mod->free_sgpgs < nsgpgs)
return BFA_STATUS_ENOMEM;
for (i = 0; i < nsgpgs; i++) {
bfa_q_deq(&mod->sgpg_q, &hsgpg);
- bfa_assert(hsgpg);
+ WARN_ON(!hsgpg);
list_add_tail(&hsgpg->qe, sgpg_q);
}
@@ -5027,10 +4689,8 @@ bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
struct bfa_sgpg_wqe_s *wqe;
- bfa_trc_fp(bfa, nsgpg);
-
mod->free_sgpgs += nsgpg;
- bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
+ WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
list_splice_tail_init(sgpg_q, &mod->sgpg_q);
@@ -5060,8 +4720,8 @@ bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
{
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
- bfa_assert(nsgpg > 0);
- bfa_assert(nsgpg > mod->free_sgpgs);
+ WARN_ON(nsgpg <= 0);
+ WARN_ON(nsgpg <= mod->free_sgpgs);
wqe->nsgpg_total = wqe->nsgpg = nsgpg;
@@ -5072,7 +4732,7 @@ bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
/*
* no one else is waiting for SGPG
*/
- bfa_assert(list_empty(&mod->sgpg_wait_q));
+ WARN_ON(!list_empty(&mod->sgpg_wait_q));
list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
wqe->nsgpg -= mod->free_sgpgs;
mod->free_sgpgs = 0;
@@ -5086,7 +4746,7 @@ bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
{
struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
- bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
+ WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
list_del(&wqe->qe);
if (wqe->nsgpg_total != wqe->nsgpg)
@@ -5318,7 +4978,7 @@ uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
uf->data_ptr = buf;
uf->data_len = m->xfr_len;
- bfa_assert(uf->data_len >= sizeof(struct fchs_s));
+ WARN_ON(uf->data_len < sizeof(struct fchs_s));
if (uf->data_len == sizeof(struct fchs_s)) {
bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
@@ -5361,12 +5021,6 @@ bfa_uf_start(struct bfa_s *bfa)
bfa_uf_post_all(BFA_UF_MOD(bfa));
}
-
-
-/*
- * hal_uf_api
- */
-
/*
* Register handler for all unsolicted recieve frames.
*
@@ -5414,7 +5068,7 @@ bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
default:
bfa_trc(bfa, msg->mhdr.msg_id);
- bfa_assert(0);
+ WARN_ON(1);
}
}
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index e2349d5cdb9..331ad992a58 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -220,6 +220,18 @@ void bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
/*
* RPORT related defines
*/
+enum bfa_rport_event {
+ BFA_RPORT_SM_CREATE = 1, /* rport create event */
+ BFA_RPORT_SM_DELETE = 2, /* deleting an existing rport */
+ BFA_RPORT_SM_ONLINE = 3, /* rport is online */
+ BFA_RPORT_SM_OFFLINE = 4, /* rport is offline */
+ BFA_RPORT_SM_FWRSP = 5, /* firmware response */
+ BFA_RPORT_SM_HWFAIL = 6, /* IOC h/w failure */
+ BFA_RPORT_SM_QOS_SCN = 7, /* QoS SCN from firmware */
+ BFA_RPORT_SM_SET_SPEED = 8, /* Set Rport Speed */
+ BFA_RPORT_SM_QRESUME = 9, /* space in requeue queue */
+};
+
#define BFA_RPORT_MIN 4
struct bfa_rport_mod_s {
@@ -432,6 +444,7 @@ struct bfa_fcport_s {
u8 myalpa; /* my ALPA in LOOP topology */
u8 rsvd[3];
struct bfa_port_cfg_s cfg; /* current port configuration */
+ bfa_boolean_t use_flash_cfg; /* get port cfg from flash */
struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */
struct bfa_reqq_wait_s reqq_wait;
@@ -500,30 +513,9 @@ void bfa_fcport_event_register(struct bfa_s *bfa,
void (*event_cbfn) (void *cbarg,
enum bfa_port_linkstate event), void *event_cbarg);
bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
-void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
-void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
-bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa,
- enum bfa_port_speed speed);
enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
-void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status);
-void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
- bfa_boolean_t link_e2e_beacon);
-void bfa_fcport_qos_get_attr(struct bfa_s *bfa,
- struct bfa_qos_attr_s *qos_attr);
-void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
- struct bfa_qos_vc_attr_s *qos_vc_attr);
-bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa,
- union bfa_fcport_stats_u *stats,
- bfa_cb_port_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
- void *cbarg);
-bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa,
- union bfa_fcport_stats_u *stats,
- bfa_cb_port_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
- void *cbarg);
bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa);
bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
@@ -537,14 +529,9 @@ bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
* bfa rport API functions
*/
struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
-void bfa_rport_delete(struct bfa_rport_s *rport);
void bfa_rport_online(struct bfa_rport_s *rport,
struct bfa_rport_info_s *rport_info);
-void bfa_rport_offline(struct bfa_rport_s *rport);
void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed);
-void bfa_rport_get_stats(struct bfa_rport_s *rport,
- struct bfa_rport_hal_stats_s *stats);
-void bfa_rport_clear_stats(struct bfa_rport_s *rport);
void bfa_cb_rport_online(void *rport);
void bfa_cb_rport_offline(void *rport);
void bfa_cb_rport_qos_scn_flowid(void *rport,
@@ -553,8 +540,6 @@ void bfa_cb_rport_qos_scn_flowid(void *rport,
void bfa_cb_rport_qos_scn_prio(void *rport,
struct bfa_rport_qos_attr_s old_qos_attr,
struct bfa_rport_qos_attr_s new_qos_attr);
-void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
- struct bfa_rport_qos_attr_s *qos_attr);
/*
* bfa fcxp API functions
@@ -619,38 +604,18 @@ void bfa_uf_free(struct bfa_uf_s *uf);
u32 bfa_lps_get_max_vport(struct bfa_s *bfa);
struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
void bfa_lps_delete(struct bfa_lps_s *lps);
-void bfa_lps_discard(struct bfa_lps_s *lps);
void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
u16 pdusz, wwn_t pwwn, wwn_t nwwn,
bfa_boolean_t auth_en);
void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
wwn_t pwwn, wwn_t nwwn);
-void bfa_lps_flogo(struct bfa_lps_s *lps);
void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
-u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
-bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
-u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
+void bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, u32 n2n_pid);
u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
-u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
-mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);
void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
-void bfa_trunk_enable_cfg(struct bfa_s *bfa);
-bfa_status_t bfa_trunk_enable(struct bfa_s *bfa);
-bfa_status_t bfa_trunk_disable(struct bfa_s *bfa);
-bfa_status_t bfa_trunk_get_attr(struct bfa_s *bfa,
- struct bfa_trunk_attr_s *attr);
-
#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 6797720213b..44524cf55d3 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -32,7 +32,6 @@
#include "bfad_drv.h"
#include "bfad_im.h"
#include "bfa_fcs.h"
-#include "bfa_os_inc.h"
#include "bfa_defs.h"
#include "bfa.h"
@@ -61,12 +60,12 @@ int msix_disable_cb = 0, msix_disable_ct = 0;
u32 bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size;
u32 *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc;
-const char *msix_name_ct[] = {
+static const char *msix_name_ct[] = {
"cpe0", "cpe1", "cpe2", "cpe3",
"rme0", "rme1", "rme2", "rme3",
"ctrl" };
-const char *msix_name_cb[] = {
+static const char *msix_name_cb[] = {
"cpe0", "cpe1", "cpe2", "cpe3",
"rme0", "rme1", "rme2", "rme3",
"eemc", "elpu0", "elpu1", "epss", "mlpu" };
@@ -206,7 +205,7 @@ bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
}
spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_init(&bfad->bfa);
+ bfa_iocfc_init(&bfad->bfa);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
/* Set up interrupt handler for each vectors */
@@ -533,7 +532,7 @@ bfad_hal_mem_release(struct bfad_s *bfad)
(dma_addr_t) meminfo_elem->dma);
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
break;
}
}
@@ -725,7 +724,7 @@ bfad_bfa_tmo(unsigned long data)
spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_timer_tick(&bfad->bfa);
+ bfa_timer_beat(&bfad->bfa.timer_mod);
bfa_comp_deq(&bfad->bfa, &doneq);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -882,8 +881,8 @@ bfad_drv_init(struct bfad_s *bfad)
goto out_hal_mem_alloc_failure;
}
- bfa_init_trc(&bfad->bfa, bfad->trcmod);
- bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
+ bfad->bfa.trcmod = bfad->trcmod;
+ bfad->bfa.plog = &bfad->plog_buf;
bfa_plog_init(&bfad->plog_buf);
bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
0, "Driver Attach");
@@ -893,9 +892,9 @@ bfad_drv_init(struct bfad_s *bfad)
/* FCS INIT */
spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
+ bfad->bfa_fcs.trcmod = bfad->trcmod;
bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
- bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable);
+ bfad->bfa_fcs.fdmi_enabled = fdmi_enable;
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
@@ -913,7 +912,7 @@ bfad_drv_uninit(struct bfad_s *bfad)
spin_lock_irqsave(&bfad->bfad_lock, flags);
init_completion(&bfad->comp);
- bfa_stop(&bfad->bfa);
+ bfa_iocfc_stop(&bfad->bfa);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
wait_for_completion(&bfad->comp);
@@ -932,8 +931,8 @@ bfad_drv_start(struct bfad_s *bfad)
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_start(&bfad->bfa);
- bfa_fcs_start(&bfad->bfa_fcs);
+ bfa_iocfc_start(&bfad->bfa);
+ bfa_fcs_fabric_modstart(&bfad->bfa_fcs);
bfad->bfad_flags |= BFAD_HAL_START_DONE;
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -963,7 +962,7 @@ bfad_stop(struct bfad_s *bfad)
spin_lock_irqsave(&bfad->bfad_lock, flags);
init_completion(&bfad->comp);
- bfa_stop(&bfad->bfa);
+ bfa_iocfc_stop(&bfad->bfa);
bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
wait_for_completion(&bfad->comp);
@@ -1102,15 +1101,15 @@ bfad_start_ops(struct bfad_s *bfad) {
/*
* If bfa_linkup_delay is set to -1 default; try to retrive the
- * value using the bfad_os_get_linkup_delay(); else use the
+ * value using the bfad_get_linkup_delay(); else use the
* passed in module param value as the bfa_linkup_delay.
*/
if (bfa_linkup_delay < 0) {
- bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
- bfad_os_rport_online_wait(bfad);
+ bfa_linkup_delay = bfad_get_linkup_delay(bfad);
+ bfad_rport_online_wait(bfad);
bfa_linkup_delay = -1;
} else
- bfad_os_rport_online_wait(bfad);
+ bfad_rport_online_wait(bfad);
BFA_LOG(KERN_INFO, bfad, bfa_log_level, "bfa device claimed\n");
@@ -1167,7 +1166,6 @@ bfad_intx(int irq, void *dev_id)
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_comp_free(&bfad->bfa, &doneq);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- bfa_trc_fp(bfad, irq);
}
return IRQ_HANDLED;
@@ -1524,7 +1522,7 @@ bfad_init(void)
if (strcmp(FCPI_NAME, " fcpim") == 0)
supported_fc4s |= BFA_LPORT_ROLE_FCP_IM;
- bfa_ioc_auto_recover(ioc_auto_recover);
+ bfa_auto_recover = ioc_auto_recover;
bfa_fcs_rport_set_del_timeout(rport_del_timeout);
error = pci_register_driver(&bfad_pci_driver);
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index ed9fff440b5..a94ea423543 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -25,7 +25,7 @@
/*
* FC transport template entry, get SCSI target port ID.
*/
-void
+static void
bfad_im_get_starget_port_id(struct scsi_target *starget)
{
struct Scsi_Host *shost;
@@ -40,7 +40,7 @@ bfad_im_get_starget_port_id(struct scsi_target *starget)
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- itnim = bfad_os_get_itnim(im_port, starget->id);
+ itnim = bfad_get_itnim(im_port, starget->id);
if (itnim)
fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
@@ -51,7 +51,7 @@ bfad_im_get_starget_port_id(struct scsi_target *starget)
/*
* FC transport template entry, get SCSI target nwwn.
*/
-void
+static void
bfad_im_get_starget_node_name(struct scsi_target *starget)
{
struct Scsi_Host *shost;
@@ -66,7 +66,7 @@ bfad_im_get_starget_node_name(struct scsi_target *starget)
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- itnim = bfad_os_get_itnim(im_port, starget->id);
+ itnim = bfad_get_itnim(im_port, starget->id);
if (itnim)
node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim);
@@ -77,7 +77,7 @@ bfad_im_get_starget_node_name(struct scsi_target *starget)
/*
* FC transport template entry, get SCSI target pwwn.
*/
-void
+static void
bfad_im_get_starget_port_name(struct scsi_target *starget)
{
struct Scsi_Host *shost;
@@ -92,7 +92,7 @@ bfad_im_get_starget_port_name(struct scsi_target *starget)
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- itnim = bfad_os_get_itnim(im_port, starget->id);
+ itnim = bfad_get_itnim(im_port, starget->id);
if (itnim)
port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
@@ -103,7 +103,7 @@ bfad_im_get_starget_port_name(struct scsi_target *starget)
/*
* FC transport template entry, get SCSI host port ID.
*/
-void
+static void
bfad_im_get_host_port_id(struct Scsi_Host *shost)
{
struct bfad_im_port_s *im_port =
@@ -111,7 +111,7 @@ bfad_im_get_host_port_id(struct Scsi_Host *shost)
struct bfad_port_s *port = im_port->port;
fc_host_port_id(shost) =
- bfa_os_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
+ bfa_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
}
/*
@@ -487,7 +487,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)
wait_for_completion(vport->comp_del);
free_scsi_host:
- bfad_os_scsi_host_free(bfad, im_port);
+ bfad_scsi_host_free(bfad, im_port);
kfree(vport);
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 1fedeeb4ac1..c66e32eced7 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -90,7 +90,7 @@ bfad_debugfs_open_fwtrc(struct inode *inode, struct file *file)
memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len);
spin_lock_irqsave(&bfad->bfad_lock, flags);
- rc = bfa_debug_fwtrc(&bfad->bfa,
+ rc = bfa_ioc_debug_fwtrc(&bfad->bfa.ioc,
fw_debug->debug_buffer,
&fw_debug->buffer_len);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -134,7 +134,7 @@ bfad_debugfs_open_fwsave(struct inode *inode, struct file *file)
memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len);
spin_lock_irqsave(&bfad->bfad_lock, flags);
- rc = bfa_debug_fwsave(&bfad->bfa,
+ rc = bfa_ioc_debug_fwsave(&bfad->bfa.ioc,
fw_debug->debug_buffer,
&fw_debug->buffer_len);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -208,7 +208,7 @@ bfad_debugfs_read(struct file *file, char __user *buf,
if (!debug || !debug->debug_buffer)
return 0;
- return memory_read_from_buffer(buf, nbytes, pos,
+ return simple_read_from_buffer(buf, nbytes, pos,
debug->debug_buffer, debug->buffer_len);
}
@@ -254,7 +254,7 @@ bfad_debugfs_read_regrd(struct file *file, char __user *buf,
if (!bfad->regdata)
return 0;
- rc = memory_read_from_buffer(buf, nbytes, pos,
+ rc = simple_read_from_buffer(buf, nbytes, pos,
bfad->regdata, bfad->reglen);
if ((*pos + nbytes) >= bfad->reglen) {
@@ -279,15 +279,31 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
u32 *regbuf;
void __iomem *rb, *reg_addr;
unsigned long flags;
+ void *kern_buf;
- rc = sscanf(buf, "%x:%x", &addr, &len);
+ kern_buf = kzalloc(nbytes, GFP_KERNEL);
+
+ if (!kern_buf) {
+ printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
+ bfad->inst_no);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) {
+ kfree(kern_buf);
+ return -ENOMEM;
+ }
+
+ rc = sscanf(kern_buf, "%x:%x", &addr, &len);
if (rc < 2) {
printk(KERN_INFO
"bfad[%d]: %s failed to read user buf\n",
bfad->inst_no, __func__);
+ kfree(kern_buf);
return -EINVAL;
}
+ kfree(kern_buf);
kfree(bfad->regdata);
bfad->regdata = NULL;
bfad->reglen = 0;
@@ -339,14 +355,30 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
int addr, val, rc;
void __iomem *reg_addr;
unsigned long flags;
+ void *kern_buf;
+
+ kern_buf = kzalloc(nbytes, GFP_KERNEL);
+
+ if (!kern_buf) {
+ printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
+ bfad->inst_no);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) {
+ kfree(kern_buf);
+ return -ENOMEM;
+ }
- rc = sscanf(buf, "%x:%x", &addr, &val);
+ rc = sscanf(kern_buf, "%x:%x", &addr, &val);
if (rc < 2) {
printk(KERN_INFO
"bfad[%d]: %s failed to read user buf\n",
bfad->inst_no, __func__);
+ kfree(kern_buf);
return -EINVAL;
}
+ kfree(kern_buf);
addr &= BFA_REG_ADDRMSK(bfa); /* offset only 17 bit and word align */
@@ -359,7 +391,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
return -EINVAL;
}
- reg_addr = (u32 *) ((u8 *) bfa_ioc_bar0(ioc) + addr);
+ reg_addr = (bfa_ioc_bar0(ioc)) + addr;
spin_lock_irqsave(&bfad->bfad_lock, flags);
writel(val, reg_addr);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index d5ce2349ac5..7f9ea90254c 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -26,7 +26,23 @@
#ifndef __BFAD_DRV_H__
#define __BFAD_DRV_H__
-#include "bfa_os_inc.h"
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_fc.h>
+#include <scsi/scsi_transport.h>
#include "bfa_modules.h"
#include "bfa_fcs.h"
@@ -39,7 +55,7 @@
#ifdef BFA_DRIVER_VERSION
#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
#else
-#define BFAD_DRIVER_VERSION "2.3.2.0"
+#define BFAD_DRIVER_VERSION "2.3.2.3"
#endif
#define BFAD_PROTO_NAME FCPI_NAME
@@ -263,28 +279,21 @@ struct bfad_hal_comp {
*/
#define nextLowerInt(x) \
do { \
- int i; \
+ int __i; \
(*x)--; \
- for (i = 1; i < (sizeof(int)*8); i <<= 1) \
- (*x) = (*x) | (*x) >> i; \
+ for (__i = 1; __i < (sizeof(int)*8); __i <<= 1) \
+ (*x) = (*x) | (*x) >> __i; \
(*x)++; \
(*x) = (*x) >> 1; \
} while (0)
-#define list_remove_head(list, entry, type, member) \
-do { \
- entry = NULL; \
- if (!list_empty(list)) { \
- entry = list_entry((list)->next, type, member); \
- list_del_init(&entry->member); \
- } \
+#define BFA_LOG(level, bfad, mask, fmt, arg...) \
+do { \
+ if (((mask) == 4) || (level[1] <= '4')) \
+ dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg); \
} while (0)
-#define list_get_first(list, type, member) \
-((list_empty(list)) ? NULL : \
- list_entry((list)->next, type, member))
-
bfa_status_t bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
struct bfa_lport_cfg_s *port_cfg,
struct device *dev);
@@ -316,8 +325,8 @@ 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);
-void bfad_os_rport_online_wait(struct bfad_s *bfad);
-int bfad_os_get_linkup_delay(struct bfad_s *bfad);
+void bfad_rport_online_wait(struct bfad_s *bfad);
+int bfad_get_linkup_delay(struct bfad_s *bfad);
int bfad_install_msix_handler(struct bfad_s *bfad);
extern struct idr bfad_im_port_index;
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index fbad5e9b240..c2b36179e8e 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -21,7 +21,6 @@
#include "bfad_drv.h"
#include "bfad_im.h"
-#include "bfa_cb_ioim.h"
#include "bfa_fcs.h"
BFA_TRC_FILE(LDRV, IM);
@@ -93,10 +92,10 @@ bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
if (!cmnd->result && itnim &&
(bfa_lun_queue_depth > cmnd->device->queue_depth)) {
/* Queue depth adjustment for good status completion */
- bfad_os_ramp_up_qdepth(itnim, cmnd->device);
+ bfad_ramp_up_qdepth(itnim, cmnd->device);
} else if (cmnd->result == SAM_STAT_TASK_SET_FULL && itnim) {
/* qfull handling */
- bfad_os_handle_qfull(itnim, cmnd->device);
+ bfad_handle_qfull(itnim, cmnd->device);
}
}
@@ -124,7 +123,7 @@ bfa_cb_ioim_good_comp(void *drv, struct bfad_ioim_s *dio)
if (itnim_data) {
itnim = itnim_data->itnim;
if (itnim)
- bfad_os_ramp_up_qdepth(itnim, cmnd->device);
+ bfad_ramp_up_qdepth(itnim, cmnd->device);
}
}
@@ -183,7 +182,7 @@ bfad_im_info(struct Scsi_Host *shost)
bfa_get_adapter_model(bfa, model);
memset(bfa_buf, 0, sizeof(bfa_buf));
- if (ioc->ctdev)
+ if (ioc->ctdev && !ioc->fcmode)
snprintf(bfa_buf, sizeof(bfa_buf),
"Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s",
model, bfad->pci_name, BFAD_DRIVER_VERSION);
@@ -258,6 +257,7 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,
struct bfa_tskim_s *tskim;
struct bfa_itnim_s *bfa_itnim;
bfa_status_t rc = BFA_STATUS_OK;
+ struct scsi_lun scsilun;
tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
if (!tskim) {
@@ -274,7 +274,8 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,
cmnd->host_scribble = NULL;
cmnd->SCp.Status = 0;
bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
- bfa_tskim_start(tskim, bfa_itnim, (lun_t)0,
+ memset(&scsilun, 0, sizeof(scsilun));
+ bfa_tskim_start(tskim, bfa_itnim, scsilun,
FCP_TM_TARGET_RESET, BFAD_TARGET_RESET_TMO);
out:
return rc;
@@ -301,6 +302,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)
int rc = SUCCESS;
unsigned long flags;
enum bfi_tskim_status task_status;
+ struct scsi_lun scsilun;
spin_lock_irqsave(&bfad->bfad_lock, flags);
itnim = itnim_data->itnim;
@@ -327,8 +329,8 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)
cmnd->SCp.ptr = (char *)&wq;
cmnd->SCp.Status = 0;
bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
- bfa_tskim_start(tskim, bfa_itnim,
- bfad_int_to_lun(cmnd->device->lun),
+ int_to_scsilun(cmnd->device->lun, &scsilun);
+ bfa_tskim_start(tskim, bfa_itnim, scsilun,
FCP_TM_LUN_RESET, BFAD_LUN_RESET_TMO);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -364,7 +366,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
for (i = 0; i < MAX_FCP_TARGET; i++) {
- itnim = bfad_os_get_itnim(im_port, i);
+ itnim = bfad_get_itnim(im_port, i);
if (itnim) {
cmnd->SCp.ptr = (char *)&wq;
rc = bfad_im_target_reset_send(bfad, cmnd, itnim);
@@ -447,7 +449,7 @@ bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)
struct bfad_im_s *im = itnim_drv->im;
/* online to free state transtion should not happen */
- bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE);
+ WARN_ON(itnim_drv->state == ITNIM_STATE_ONLINE);
itnim_drv->queue_work = 1;
/* offline request is not yet done, use the same request to free */
@@ -545,7 +547,7 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
mutex_unlock(&bfad_mutex);
- im_port->shost = bfad_os_scsi_host_alloc(im_port, bfad);
+ im_port->shost = bfad_scsi_host_alloc(im_port, bfad);
if (!im_port->shost) {
error = 1;
goto out_free_idr;
@@ -571,7 +573,7 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
}
/* setup host fixed attribute if the lk supports */
- bfad_os_fc_host_init(im_port);
+ bfad_fc_host_init(im_port);
return 0;
@@ -662,7 +664,7 @@ bfad_im_port_clean(struct bfad_im_port_s *im_port)
}
/* the itnim_mapped_list must be empty at this time */
- bfa_assert(list_empty(&im_port->itnim_mapped_list));
+ WARN_ON(!list_empty(&im_port->itnim_mapped_list));
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}
@@ -682,7 +684,7 @@ bfad_im_probe(struct bfad_s *bfad)
bfad->im = im;
im->bfad = bfad;
- if (bfad_os_thread_workq(bfad) != BFA_STATUS_OK) {
+ if (bfad_thread_workq(bfad) != BFA_STATUS_OK) {
kfree(im);
rc = BFA_STATUS_FAILED;
}
@@ -695,14 +697,14 @@ void
bfad_im_probe_undo(struct bfad_s *bfad)
{
if (bfad->im) {
- bfad_os_destroy_workq(bfad->im);
+ bfad_destroy_workq(bfad->im);
kfree(bfad->im);
bfad->im = NULL;
}
}
struct Scsi_Host *
-bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
+bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
{
struct scsi_host_template *sht;
@@ -717,7 +719,7 @@ bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
}
void
-bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
+bfad_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
{
if (!(im_port->flags & BFAD_PORT_DELETE))
flush_workqueue(bfad->im->drv_workq);
@@ -727,7 +729,7 @@ bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
}
void
-bfad_os_destroy_workq(struct bfad_im_s *im)
+bfad_destroy_workq(struct bfad_im_s *im)
{
if (im && im->drv_workq) {
flush_workqueue(im->drv_workq);
@@ -737,7 +739,7 @@ bfad_os_destroy_workq(struct bfad_im_s *im)
}
bfa_status_t
-bfad_os_thread_workq(struct bfad_s *bfad)
+bfad_thread_workq(struct bfad_s *bfad)
{
struct bfad_im_s *im = bfad->im;
@@ -841,7 +843,7 @@ bfad_im_module_exit(void)
}
void
-bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
+bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
{
struct scsi_device *tmp_sdev;
@@ -869,7 +871,7 @@ bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
}
void
-bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
+bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
{
struct scsi_device *tmp_sdev;
@@ -883,7 +885,7 @@ bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
}
struct bfad_itnim_s *
-bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id)
+bfad_get_itnim(struct bfad_im_port_s *im_port, int id)
{
struct bfad_itnim_s *itnim = NULL;
@@ -922,7 +924,7 @@ bfad_im_supported_speeds(struct bfa_s *bfa)
if (!ioc_attr)
return 0;
- bfa_get_attr(bfa, ioc_attr);
+ bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
if (ioc_attr->adapter_attr.is_mezz) {
supported_speed |= FC_PORTSPEED_8GBIT |
@@ -944,7 +946,7 @@ bfad_im_supported_speeds(struct bfa_s *bfa)
}
void
-bfad_os_fc_host_init(struct bfad_im_port_s *im_port)
+bfad_fc_host_init(struct bfad_im_port_s *im_port)
{
struct Scsi_Host *host = im_port->shost;
struct bfad_s *bfad = im_port->bfad;
@@ -988,7 +990,7 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)
rport_ids.port_name =
cpu_to_be64(bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim));
rport_ids.port_id =
- bfa_os_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim));
+ bfa_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim));
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
itnim->fc_rport = fc_rport =
@@ -1109,7 +1111,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)
kfree(itnim);
break;
default:
- bfa_assert(0);
+ WARN_ON(1);
break;
}
@@ -1172,7 +1174,6 @@ bfad_im_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd
}
cmnd->host_scribble = (char *)hal_io;
- bfa_trc_fp(bfad, hal_io->iotag);
bfa_ioim_start(hal_io);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -1190,7 +1191,7 @@ out_fail_cmd:
static DEF_SCSI_QCMD(bfad_im_queuecommand)
void
-bfad_os_rport_online_wait(struct bfad_s *bfad)
+bfad_rport_online_wait(struct bfad_s *bfad)
{
int i;
int rport_delay = 10;
@@ -1218,7 +1219,7 @@ bfad_os_rport_online_wait(struct bfad_s *bfad)
}
int
-bfad_os_get_linkup_delay(struct bfad_s *bfad)
+bfad_get_linkup_delay(struct bfad_s *bfad)
{
u8 nwwns = 0;
wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index b038c0e0892..bfee63b16fa 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -117,17 +117,17 @@ struct bfad_im_s {
char drv_workq_name[KOBJ_NAME_LEN];
};
-struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port,
+struct Scsi_Host *bfad_scsi_host_alloc(struct bfad_im_port_s *im_port,
struct bfad_s *);
-bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad);
-void bfad_os_destroy_workq(struct bfad_im_s *im);
-void bfad_os_fc_host_init(struct bfad_im_port_s *im_port);
-void bfad_os_scsi_host_free(struct bfad_s *bfad,
+bfa_status_t bfad_thread_workq(struct bfad_s *bfad);
+void bfad_destroy_workq(struct bfad_im_s *im);
+void bfad_fc_host_init(struct bfad_im_port_s *im_port);
+void bfad_scsi_host_free(struct bfad_s *bfad,
struct bfad_im_port_s *im_port);
-void bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim,
+void bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim,
struct scsi_device *sdev);
-void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
-struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id);
+void bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
+struct bfad_itnim_s *bfad_get_itnim(struct bfad_im_port_s *im_port, int id);
extern struct scsi_host_template bfad_im_scsi_host_template;
extern struct scsi_host_template bfad_im_vport_template;
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index 58796d1284b..72b69a0c3b5 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -95,8 +95,8 @@ enum {
*/
union bfi_addr_u {
struct {
- u32 addr_lo;
- u32 addr_hi;
+ __be32 addr_lo;
+ __be32 addr_hi;
} a32;
};
@@ -104,7 +104,7 @@ union bfi_addr_u {
* Scatter Gather Element
*/
struct bfi_sge_s {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
u32 flags:2,
rsvd:2,
sg_len:28;
@@ -399,7 +399,7 @@ union bfi_ioc_i2h_msg_u {
*/
struct bfi_pbc_blun_s {
wwn_t tgt_pwwn;
- lun_t tgt_lun;
+ struct scsi_lun tgt_lun;
};
/*
diff --git a/drivers/scsi/bfa/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h
index 6f03ed382c6..39ad42b66b5 100644
--- a/drivers/scsi/bfa/bfi_cbreg.h
+++ b/drivers/scsi/bfa/bfi_cbreg.h
@@ -208,6 +208,7 @@
#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG
#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG
#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG
+#define BFA_IOC_FAIL_SYNC HOST_SEM5_INFO_REG
#define CPE_Q_DEPTH(__n) \
(CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH))
diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h
index 62b86a4b0e4..fc4ce4a5a18 100644
--- a/drivers/scsi/bfa/bfi_ctreg.h
+++ b/drivers/scsi/bfa/bfi_ctreg.h
@@ -522,6 +522,7 @@ enum {
#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG
#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG
#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG
+#define BFA_IOC_FAIL_SYNC HOST_SEM5_INFO_REG
#define CPE_DEPTH_Q(__n) \
(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
@@ -539,22 +540,30 @@ enum {
(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
#define RME_CI_PTR_Q(__n) \
(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \
- * (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \
- * (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \
- * (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \
- * (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \
- * (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \
- * (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \
- * (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \
- * (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
+#define HQM_QSET_RXQ_DRBL_P0(__n) \
+ (HQM_QSET0_RXQ_DRBL_P0 + (__n) * \
+ (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) \
+ (HQM_QSET0_TXQ_DRBL_P0 + (__n) * \
+ (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) \
+ (HQM_QSET0_IB_DRBL_1_P0 + (__n) * \
+ (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) \
+ (HQM_QSET0_IB_DRBL_2_P0 + (__n) * \
+ (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) \
+ (HQM_QSET0_RXQ_DRBL_P1 + (__n) * \
+ (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) \
+ (HQM_QSET0_TXQ_DRBL_P1 + (__n) * \
+ (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) \
+ (HQM_QSET0_IB_DRBL_1_P1 + (__n) * \
+ (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) \
+ (HQM_QSET0_IB_DRBL_2_P1 + (__n) * \
+ (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
index fa9f6fb9d45..19e888a5755 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -47,10 +47,10 @@ struct bfi_iocfc_cfg_s {
*/
union bfi_addr_u req_cq_ba[BFI_IOC_MAX_CQS];
union bfi_addr_u req_shadow_ci[BFI_IOC_MAX_CQS];
- u16 req_cq_elems[BFI_IOC_MAX_CQS];
+ __be16 req_cq_elems[BFI_IOC_MAX_CQS];
union bfi_addr_u rsp_cq_ba[BFI_IOC_MAX_CQS];
union bfi_addr_u rsp_shadow_pi[BFI_IOC_MAX_CQS];
- u16 rsp_cq_elems[BFI_IOC_MAX_CQS];
+ __be16 rsp_cq_elems[BFI_IOC_MAX_CQS];
union bfi_addr_u stats_addr; /* DMA-able address for stats */
union bfi_addr_u cfgrsp_addr; /* config response dma address */
@@ -102,8 +102,8 @@ struct bfi_iocfc_set_intr_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 coalesce; /* enable intr coalescing */
u8 rsvd[3];
- u16 delay; /* delay timer 0..1125us */
- u16 latency; /* latency timer 0..225us */
+ __be16 delay; /* delay timer 0..1125us */
+ __be16 latency; /* latency timer 0..225us */
};
@@ -188,7 +188,8 @@ struct bfi_fcport_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 status; /* port enable status */
u8 rsvd[3];
- u32 msgtag; /* msgtag for reply */
+ struct bfa_port_cfg_s port_cfg;/* port configuration */
+ u32 msgtag; /* msgtag for reply */
};
/*
@@ -202,7 +203,8 @@ struct bfi_fcport_enable_req_s {
struct bfa_port_cfg_s port_cfg; /* port configuration */
union bfi_addr_u stats_dma_addr; /* DMA address for stats */
u32 msgtag; /* msgtag for reply */
- u32 rsvd2;
+ u8 use_flash_cfg; /* get prot cfg from flash */
+ u8 rsvd2[3];
};
/*
@@ -210,7 +212,7 @@ struct bfi_fcport_enable_req_s {
*/
struct bfi_fcport_set_svc_params_req_s {
struct bfi_mhdr_s mh; /* msg header */
- u16 tx_bbcredit; /* Tx credits */
+ __be16 tx_bbcredit; /* Tx credits */
u16 rsvd;
};
@@ -231,7 +233,7 @@ struct bfi_fcport_trunk_link_s {
u8 state; /* bfa_trunk_link_state_t */
u8 speed; /* bfa_port_speed_t */
u8 rsvd;
- u32 deskew;
+ __be32 deskew;
};
#define BFI_FCPORT_MAX_LINKS 2
@@ -284,17 +286,17 @@ enum bfi_fcxp_i2h {
*/
struct bfi_fcxp_send_req_s {
struct bfi_mhdr_s mh; /* Common msg header */
- u16 fcxp_tag; /* driver request tag */
- u16 max_frmsz; /* max send frame size */
- u16 vf_id; /* vsan tag if applicable */
+ __be16 fcxp_tag; /* driver request tag */
+ __be16 max_frmsz; /* max send frame size */
+ __be16 vf_id; /* vsan tag if applicable */
u16 rport_fw_hndl; /* FW Handle for the remote port */
u8 class; /* FC class used for req/rsp */
u8 rsp_timeout; /* timeout in secs, 0-no response */
u8 cts; /* continue sequence */
u8 lp_tag; /* lport tag */
struct fchs_s fchs; /* request FC header structure */
- u32 req_len; /* request payload length */
- u32 rsp_maxlen; /* max response length expected */
+ __be32 req_len; /* request payload length */
+ __be32 rsp_maxlen; /* max response length expected */
struct bfi_sge_s req_sge[BFA_FCXP_MAX_SGES]; /* request buf */
struct bfi_sge_s rsp_sge[BFA_FCXP_MAX_SGES]; /* response buf */
};
@@ -304,11 +306,11 @@ struct bfi_fcxp_send_req_s {
*/
struct bfi_fcxp_send_rsp_s {
struct bfi_mhdr_s mh; /* Common msg header */
- u16 fcxp_tag; /* send request tag */
+ __be16 fcxp_tag; /* send request tag */
u8 req_status; /* request status */
u8 rsvd;
- u32 rsp_len; /* actual response length */
- u32 residue_len; /* residual response length */
+ __be32 rsp_len; /* actual response length */
+ __be32 residue_len; /* residual response length */
struct fchs_s fchs; /* response FC header structure */
};
@@ -325,7 +327,7 @@ enum bfi_uf_i2h {
struct bfi_uf_buf_post_s {
struct bfi_mhdr_s mh; /* Common msg header */
u16 buf_tag; /* buffer tag */
- u16 buf_len; /* total buffer length */
+ __be16 buf_len; /* total buffer length */
struct bfi_sge_s sge[BFA_UF_MAX_SGES]; /* buffer DMA SGEs */
};
@@ -340,6 +342,7 @@ struct bfi_uf_frm_rcvd_s {
enum bfi_lps_h2i_msgs {
BFI_LPS_H2I_LOGIN_REQ = 1,
BFI_LPS_H2I_LOGOUT_REQ = 2,
+ BFI_LPS_H2I_N2N_PID_REQ = 3,
};
enum bfi_lps_i2h_msgs {
@@ -352,7 +355,7 @@ struct bfi_lps_login_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 lp_tag;
u8 alpa;
- u16 pdu_size;
+ __be16 pdu_size;
wwn_t pwwn;
wwn_t nwwn;
u8 fdisc;
@@ -368,7 +371,7 @@ struct bfi_lps_login_rsp_s {
u8 lsrjt_expl;
wwn_t port_name;
wwn_t node_name;
- u16 bb_credit;
+ __be16 bb_credit;
u8 f_port;
u8 npiv_en;
u32 lp_pid:24;
@@ -399,10 +402,17 @@ struct bfi_lps_cvl_event_s {
u8 rsvd[3];
};
+struct bfi_lps_n2n_pid_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 lp_tag;
+ u32 lp_pid:24;
+};
+
union bfi_lps_h2i_msg_u {
struct bfi_mhdr_s *msg;
struct bfi_lps_login_req_s *login_req;
struct bfi_lps_logout_req_s *logout_req;
+ struct bfi_lps_n2n_pid_req_s *n2n_pid_req;
};
union bfi_lps_i2h_msg_u {
@@ -427,7 +437,7 @@ enum bfi_rport_i2h_msgs {
struct bfi_rport_create_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 bfa_handle; /* host rport handle */
- u16 max_frmsz; /* max rcv pdu size */
+ __be16 max_frmsz; /* max rcv pdu size */
u32 pid:24, /* remote port ID */
lp_tag:8; /* local port tag */
u32 local_pid:24, /* local port ID */
@@ -583,7 +593,7 @@ struct bfi_ioim_dif_s {
*/
struct bfi_ioim_req_s {
struct bfi_mhdr_s mh; /* Common msg header */
- u16 io_tag; /* I/O tag */
+ __be16 io_tag; /* I/O tag */
u16 rport_hdl; /* itnim/rport firmware handle */
struct fcp_cmnd_s cmnd; /* IO request info */
@@ -689,7 +699,7 @@ enum bfi_ioim_status {
*/
struct bfi_ioim_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
- u16 io_tag; /* completed IO tag */
+ __be16 io_tag; /* completed IO tag */
u16 bfa_rport_hndl; /* releated rport handle */
u8 io_status; /* IO completion status */
u8 reuse_io_tag; /* IO tag can be reused */
@@ -698,13 +708,13 @@ struct bfi_ioim_rsp_s {
u8 sns_len; /* scsi sense length */
u8 resid_flags; /* IO residue flags */
u8 rsvd_a;
- u32 residue; /* IO residual length in bytes */
+ __be32 residue; /* IO residual length in bytes */
u32 rsvd_b[3];
};
struct bfi_ioim_abort_req_s {
struct bfi_mhdr_s mh; /* Common msg header */
- u16 io_tag; /* I/O tag */
+ __be16 io_tag; /* I/O tag */
u16 abort_tag; /* unique request tag */
};
@@ -723,9 +733,9 @@ enum bfi_tskim_i2h {
struct bfi_tskim_req_s {
struct bfi_mhdr_s mh; /* Common msg header */
- u16 tsk_tag; /* task management tag */
+ __be16 tsk_tag; /* task management tag */
u16 itn_fhdl; /* itn firmware handle */
- lun_t lun; /* LU number */
+ struct scsi_lun lun; /* LU number */
u8 tm_flags; /* see enum fcp_tm_cmnd */
u8 t_secs; /* Timeout value in seconds */
u8 rsvd[2];
@@ -733,7 +743,7 @@ struct bfi_tskim_req_s {
struct bfi_tskim_abortreq_s {
struct bfi_mhdr_s mh; /* Common msg header */
- u16 tsk_tag; /* task management tag */
+ __be16 tsk_tag; /* task management tag */
u16 rsvd;
};
@@ -755,7 +765,7 @@ enum bfi_tskim_status {
struct bfi_tskim_rsp_s {
struct bfi_mhdr_s mh; /* Common msg header */
- u16 tsk_tag; /* task mgmt cmnd tag */
+ __be16 tsk_tag; /* task mgmt cmnd tag */
u8 tsk_status; /* @ref bfi_tskim_status */
u8 rsvd;
};
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 1b6f86b2482..30e6bdbd65a 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -1,12 +1,13 @@
/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
*
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
*/
#ifndef __57XX_ISCSI_CONSTANTS_H_
#define __57XX_ISCSI_CONSTANTS_H_
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index 36af1afef9b..dad6c8a3431 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -1,12 +1,13 @@
/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
*
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
*/
#ifndef __57XX_ISCSI_HSI_LINUX_LE__
#define __57XX_ISCSI_HSI_LINUX_LE__
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index a44b1b33fa1..e1ca5fe7e6b 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -1,6 +1,6 @@
/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -9,6 +9,7 @@
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
*/
#ifndef _BNX2I_H_
@@ -649,6 +650,7 @@ enum {
EP_STATE_OFLD_FAILED = 0x8000000,
EP_STATE_CONNECT_FAILED = 0x10000000,
EP_STATE_DISCONN_TIMEDOUT = 0x20000000,
+ EP_STATE_OFLD_FAILED_CID_BUSY = 0x80000000,
};
/**
@@ -717,14 +719,11 @@ extern struct device_attribute *bnx2i_dev_attributes[];
* Function Prototypes
*/
extern void bnx2i_identify_device(struct bnx2i_hba *hba);
-extern void bnx2i_register_device(struct bnx2i_hba *hba);
extern void bnx2i_ulp_init(struct cnic_dev *dev);
extern void bnx2i_ulp_exit(struct cnic_dev *dev);
extern void bnx2i_start(void *handle);
extern void bnx2i_stop(void *handle);
-extern void bnx2i_reg_dev_all(void);
-extern void bnx2i_unreg_dev_all(void);
extern struct bnx2i_hba *get_adapter_list_head(void);
struct bnx2i_conn *bnx2i_get_conn_from_id(struct bnx2i_hba *hba,
@@ -761,11 +760,11 @@ extern int bnx2i_send_iscsi_logout(struct bnx2i_conn *conn,
struct iscsi_task *mtask);
extern void bnx2i_send_cmd_cleanup_req(struct bnx2i_hba *hba,
struct bnx2i_cmd *cmd);
-extern void bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba,
- struct bnx2i_endpoint *ep);
-extern void bnx2i_update_iscsi_conn(struct iscsi_conn *conn);
-extern void bnx2i_send_conn_destroy(struct bnx2i_hba *hba,
+extern int bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba,
struct bnx2i_endpoint *ep);
+extern void bnx2i_update_iscsi_conn(struct iscsi_conn *conn);
+extern int bnx2i_send_conn_destroy(struct bnx2i_hba *hba,
+ struct bnx2i_endpoint *ep);
extern int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba,
struct bnx2i_endpoint *ep);
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 2f9622ebbd8..96505e3ab98 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1,6 +1,6 @@
/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -9,6 +9,7 @@
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
*/
#include <linux/gfp.h>
@@ -385,6 +386,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
struct bnx2i_cmd *bnx2i_cmd;
struct bnx2i_tmf_request *tmfabort_wqe;
u32 dword;
+ u32 scsi_lun[2];
bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
tmfabort_hdr = (struct iscsi_tm *)mtask->hdr;
@@ -426,7 +428,10 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
default:
tmfabort_wqe->ref_itt = RESERVED_ITT;
}
- memcpy(tmfabort_wqe->lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
+ memcpy(scsi_lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
+ tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
+ tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
+
tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn);
tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma;
@@ -697,10 +702,11 @@ void bnx2i_send_cmd_cleanup_req(struct bnx2i_hba *hba, struct bnx2i_cmd *cmd)
* this routine prepares and posts CONN_OFLD_REQ1/2 KWQE to initiate
* iscsi connection context clean-up process
*/
-void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
+int bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
{
struct kwqe *kwqe_arr[2];
struct iscsi_kwqe_conn_destroy conn_cleanup;
+ int rc = -EINVAL;
memset(&conn_cleanup, 0x00, sizeof(struct iscsi_kwqe_conn_destroy));
@@ -717,7 +723,9 @@ void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
kwqe_arr[0] = (struct kwqe *) &conn_cleanup;
if (hba->cnic && hba->cnic->submit_kwqes)
- hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, 1);
+ rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, 1);
+
+ return rc;
}
@@ -728,8 +736,8 @@ void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
*
* 5706/5708/5709 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE
*/
-static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba,
- struct bnx2i_endpoint *ep)
+static int bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba,
+ struct bnx2i_endpoint *ep)
{
struct kwqe *kwqe_arr[2];
struct iscsi_kwqe_conn_offload1 ofld_req1;
@@ -737,6 +745,7 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba,
dma_addr_t dma_addr;
int num_kwqes = 2;
u32 *ptbl;
+ int rc = -EINVAL;
ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1;
ofld_req1.hdr.flags =
@@ -774,7 +783,9 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba,
ofld_req2.num_additional_wqes = 0;
if (hba->cnic && hba->cnic->submit_kwqes)
- hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+ rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+ return rc;
}
@@ -785,8 +796,8 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba,
*
* 57710 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE
*/
-static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba,
- struct bnx2i_endpoint *ep)
+static int bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba,
+ struct bnx2i_endpoint *ep)
{
struct kwqe *kwqe_arr[5];
struct iscsi_kwqe_conn_offload1 ofld_req1;
@@ -795,6 +806,7 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba,
dma_addr_t dma_addr;
int num_kwqes = 2;
u32 *ptbl;
+ int rc = -EINVAL;
ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1;
ofld_req1.hdr.flags =
@@ -840,7 +852,9 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba,
num_kwqes += 1;
if (hba->cnic && hba->cnic->submit_kwqes)
- hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+ rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+ return rc;
}
/**
@@ -851,12 +865,16 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba,
*
* this routine prepares and posts CONN_OFLD_REQ1/2 KWQE
*/
-void bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
+int bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
{
+ int rc;
+
if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type))
- bnx2i_5771x_send_conn_ofld_req(hba, ep);
+ rc = bnx2i_5771x_send_conn_ofld_req(hba, ep);
else
- bnx2i_570x_send_conn_ofld_req(hba, ep);
+ rc = bnx2i_570x_send_conn_ofld_req(hba, ep);
+
+ return rc;
}
@@ -1513,7 +1531,7 @@ static void bnx2i_process_nopin_local_cmpl(struct iscsi_session *session,
task = iscsi_itt_to_task(conn,
nop_in->itt & ISCSI_NOP_IN_MSG_INDEX);
if (task)
- iscsi_put_task(task);
+ __iscsi_put_task(task);
spin_unlock(&session->lock);
}
@@ -1549,11 +1567,9 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session,
struct iscsi_task *task;
struct bnx2i_nop_in_msg *nop_in;
struct iscsi_nopin *hdr;
- u32 itt;
int tgt_async_nop = 0;
nop_in = (struct bnx2i_nop_in_msg *)cqe;
- itt = nop_in->itt & ISCSI_NOP_IN_MSG_INDEX;
spin_lock(&session->lock);
hdr = (struct iscsi_nopin *)&bnx2i_conn->gen_pdu.resp_hdr;
@@ -1563,7 +1579,7 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session,
hdr->exp_cmdsn = cpu_to_be32(nop_in->exp_cmd_sn);
hdr->ttt = cpu_to_be32(nop_in->ttt);
- if (itt == (u16) RESERVED_ITT) {
+ if (nop_in->itt == (u16) RESERVED_ITT) {
bnx2i_unsol_pdu_adjust_rq(bnx2i_conn);
hdr->itt = RESERVED_ITT;
tgt_async_nop = 1;
@@ -1571,7 +1587,8 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session,
}
/* this is a response to one of our nop-outs */
- task = iscsi_itt_to_task(conn, itt);
+ task = iscsi_itt_to_task(conn,
+ (itt_t) (nop_in->itt & ISCSI_NOP_IN_MSG_INDEX));
if (task) {
hdr->flags = ISCSI_FLAG_CMD_FINAL;
hdr->itt = task->hdr->itt;
@@ -1721,9 +1738,18 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
break;
- if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx)))
+ if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) {
+ if (nopin->op_code == ISCSI_OP_NOOP_IN &&
+ nopin->itt == (u16) RESERVED_ITT) {
+ printk(KERN_ALERT "bnx2i: Unsolicited "
+ "NOP-In detected for suspended "
+ "connection dev=%s!\n",
+ bnx2i_conn->hba->netdev->name);
+ bnx2i_unsol_pdu_adjust_rq(bnx2i_conn);
+ goto cqe_out;
+ }
break;
-
+ }
tgt_async_msg = 0;
switch (nopin->op_code) {
@@ -1770,10 +1796,9 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n",
nopin->op_code);
}
-
if (!tgt_async_msg)
bnx2i_conn->ep->num_active_cmds--;
-
+cqe_out:
/* clear out in production version only, till beta keep opcode
* field intact, will be helpful in debugging (context dump)
* nopin->op_code = 0;
@@ -2154,11 +2179,24 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba,
}
if (ofld_kcqe->completion_status) {
+ ep->state = EP_STATE_OFLD_FAILED;
if (ofld_kcqe->completion_status ==
ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE)
- printk(KERN_ALERT "bnx2i: unable to allocate"
- " iSCSI context resources\n");
- ep->state = EP_STATE_OFLD_FAILED;
+ printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - unable "
+ "to allocate iSCSI context resources\n",
+ hba->netdev->name);
+ else if (ofld_kcqe->completion_status ==
+ ISCSI_KCQE_COMPLETION_STATUS_INVALID_OPCODE)
+ printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
+ "opcode\n", hba->netdev->name);
+ else if (ofld_kcqe->completion_status ==
+ ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
+ /* error status code valid only for 5771x chipset */
+ ep->state = EP_STATE_OFLD_FAILED_CID_BUSY;
+ else
+ printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
+ "error code %d\n", hba->netdev->name,
+ ofld_kcqe->completion_status);
} else {
ep->state = EP_STATE_OFLD_COMPL;
cid_addr = ofld_kcqe->iscsi_conn_context_id;
@@ -2339,10 +2377,14 @@ static void bnx2i_cm_remote_close(struct cnic_sock *cm_sk)
static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk)
{
struct bnx2i_endpoint *ep = (struct bnx2i_endpoint *) cm_sk->context;
+ u32 old_state = ep->state;
ep->state = EP_STATE_TCP_RST_RCVD;
- if (ep->conn)
- bnx2i_recovery_que_add_conn(ep->hba, ep->conn);
+ if (old_state == EP_STATE_DISCONN_START)
+ wake_up_interruptible(&ep->ofld_wait);
+ else
+ if (ep->conn)
+ bnx2i_recovery_que_add_conn(ep->hba, ep->conn);
}
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 50c2aa3b8eb..72a7b2d4a43 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -1,6 +1,6 @@
/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -9,6 +9,7 @@
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
*/
#include "bnx2i.h"
@@ -17,8 +18,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.3"
-#define DRV_MODULE_RELDATE "Aug 10, 2010"
+#define DRV_MODULE_VERSION "2.6.2.2"
+#define DRV_MODULE_RELDATE "Nov 23, 2010"
static char version[] __devinitdata =
"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -65,8 +66,6 @@ MODULE_PARM_DESC(rq_size, "Configure RQ size");
u64 iscsi_error_mask = 0x00;
-static void bnx2i_unreg_one_device(struct bnx2i_hba *hba) ;
-
/**
* bnx2i_identify_device - identifies NetXtreme II device type
@@ -211,13 +210,24 @@ void bnx2i_stop(void *handle)
{
struct bnx2i_hba *hba = handle;
int conns_active;
+ int wait_delay = 1 * HZ;
/* check if cleanup happened in GOING_DOWN context */
- if (!test_and_clear_bit(ADAPTER_STATE_GOING_DOWN,
- &hba->adapter_state))
+ if (!test_and_set_bit(ADAPTER_STATE_GOING_DOWN,
+ &hba->adapter_state)) {
iscsi_host_for_each_session(hba->shost,
bnx2i_drop_session);
-
+ wait_delay = hba->hba_shutdown_tmo;
+ }
+ /* Wait for inflight offload connection tasks to complete before
+ * proceeding. Forcefully terminate all connection recovery in
+ * progress at the earliest, either in bind(), send_pdu(LOGIN),
+ * or conn_start()
+ */
+ wait_event_interruptible_timeout(hba->eh_wait,
+ (list_empty(&hba->ep_ofld_list) &&
+ list_empty(&hba->ep_destroy_list)),
+ 10 * HZ);
/* Wait for all endpoints to be torn down, Chip will be reset once
* control returns to network driver. So it is required to cleanup and
* release all connection resources before returning from this routine.
@@ -226,7 +236,7 @@ void bnx2i_stop(void *handle)
conns_active = hba->ofld_conns_active;
wait_event_interruptible_timeout(hba->eh_wait,
(hba->ofld_conns_active != conns_active),
- hba->hba_shutdown_tmo);
+ wait_delay);
if (hba->ofld_conns_active == conns_active)
break;
}
@@ -235,88 +245,10 @@ void bnx2i_stop(void *handle)
/* This flag should be cleared last so that ep_disconnect() gracefully
* cleans up connection context
*/
+ clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
}
-/**
- * bnx2i_register_device - register bnx2i adapter instance with the cnic driver
- * @hba: Adapter instance to register
- *
- * registers bnx2i adapter instance with the cnic driver while holding the
- * adapter structure lock
- */
-void bnx2i_register_device(struct bnx2i_hba *hba)
-{
- int rc;
-
- if (test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state) ||
- test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
- return;
- }
-
- rc = hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba);
-
- if (!rc)
- set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
-}
-
-
-/**
- * bnx2i_reg_dev_all - registers all adapter instances with the cnic driver
- *
- * registers all bnx2i adapter instances with the cnic driver while holding
- * the global resource lock
- */
-void bnx2i_reg_dev_all(void)
-{
- struct bnx2i_hba *hba, *temp;
-
- mutex_lock(&bnx2i_dev_lock);
- list_for_each_entry_safe(hba, temp, &adapter_list, link)
- bnx2i_register_device(hba);
- mutex_unlock(&bnx2i_dev_lock);
-}
-
-
-/**
- * bnx2i_unreg_one_device - unregister adapter instance with the cnic driver
- * @hba: Adapter instance to unregister
- *
- * registers bnx2i adapter instance with the cnic driver while holding
- * the adapter structure lock
- */
-static void bnx2i_unreg_one_device(struct bnx2i_hba *hba)
-{
- if (hba->ofld_conns_active ||
- !test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic) ||
- test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state))
- return;
-
- hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
-
- /* ep_disconnect could come before NETDEV_DOWN, driver won't
- * see NETDEV_DOWN as it already unregistered itself.
- */
- hba->adapter_state = 0;
- clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
-}
-
-/**
- * bnx2i_unreg_dev_all - unregisters all bnx2i instances with the cnic driver
- *
- * unregisters all bnx2i adapter instances with the cnic driver while holding
- * the global resource lock
- */
-void bnx2i_unreg_dev_all(void)
-{
- struct bnx2i_hba *hba, *temp;
-
- mutex_lock(&bnx2i_dev_lock);
- list_for_each_entry_safe(hba, temp, &adapter_list, link)
- bnx2i_unreg_one_device(hba);
- mutex_unlock(&bnx2i_dev_lock);
-}
-
/**
* bnx2i_init_one - initialize an adapter instance and allocate memory resources
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index fb50efbce08..f0dce26593e 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1,7 +1,7 @@
/*
* bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
*
@@ -10,6 +10,7 @@
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
*/
#include <linux/slab.h>
@@ -411,7 +412,9 @@ static void bnx2i_free_ep(struct iscsi_endpoint *ep)
bnx2i_ep->state = EP_STATE_IDLE;
bnx2i_ep->hba->ofld_conns_active--;
- bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid);
+ if (bnx2i_ep->ep_iscsi_cid != (u16) -1)
+ bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid);
+
if (bnx2i_ep->conn) {
bnx2i_ep->conn->ep = NULL;
bnx2i_ep->conn = NULL;
@@ -1383,6 +1386,12 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
ep = iscsi_lookup_endpoint(transport_fd);
if (!ep)
return -EINVAL;
+ /*
+ * Forcefully terminate all in progress connection recovery at the
+ * earliest, either in bind(), send_pdu(LOGIN), or conn_start()
+ */
+ if (bnx2i_adapter_ready(hba))
+ return -EIO;
bnx2i_ep = ep->dd_data;
if ((bnx2i_ep->state == EP_STATE_TCP_FIN_RCVD) ||
@@ -1404,7 +1413,6 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
hba->netdev->name);
return -EEXIST;
}
-
bnx2i_ep->conn = bnx2i_conn;
bnx2i_conn->ep = bnx2i_ep;
bnx2i_conn->iscsi_conn_cid = bnx2i_ep->ep_iscsi_cid;
@@ -1461,21 +1469,28 @@ static int bnx2i_conn_get_param(struct iscsi_cls_conn *cls_conn,
struct bnx2i_conn *bnx2i_conn = conn->dd_data;
int len = 0;
+ if (!(bnx2i_conn && bnx2i_conn->ep && bnx2i_conn->ep->hba))
+ goto out;
+
switch (param) {
case ISCSI_PARAM_CONN_PORT:
- if (bnx2i_conn->ep)
+ mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
+ if (bnx2i_conn->ep->cm_sk)
len = sprintf(buf, "%hu\n",
bnx2i_conn->ep->cm_sk->dst_port);
+ mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
break;
case ISCSI_PARAM_CONN_ADDRESS:
- if (bnx2i_conn->ep)
+ mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
+ if (bnx2i_conn->ep->cm_sk)
len = sprintf(buf, "%pI4\n",
&bnx2i_conn->ep->cm_sk->dst_ip);
+ mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
break;
default:
return iscsi_conn_get_param(cls_conn, param, buf);
}
-
+out:
return len;
}
@@ -1599,8 +1614,6 @@ static struct bnx2i_hba *bnx2i_check_route(struct sockaddr *dst_addr)
struct bnx2i_hba *hba;
struct cnic_dev *cnic = NULL;
- bnx2i_reg_dev_all();
-
hba = get_adapter_list_head();
if (hba && hba->cnic)
cnic = hba->cnic->cm_select_dev(desti, CNIC_ULP_ISCSI);
@@ -1640,18 +1653,26 @@ no_nx2_route:
static int bnx2i_tear_down_conn(struct bnx2i_hba *hba,
struct bnx2i_endpoint *ep)
{
- if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic))
+ if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic) && ep->cm_sk)
hba->cnic->cm_destroy(ep->cm_sk);
- if (test_bit(ADAPTER_STATE_GOING_DOWN, &ep->hba->adapter_state))
- ep->state = EP_STATE_DISCONN_COMPL;
-
if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type) &&
ep->state == EP_STATE_DISCONN_TIMEDOUT) {
- printk(KERN_ALERT "bnx2i - ERROR - please submit GRC Dump,"
- " NW/PCIe trace, driver msgs to developers"
- " for analysis\n");
- return 1;
+ if (ep->conn && ep->conn->cls_conn &&
+ ep->conn->cls_conn->dd_data) {
+ struct iscsi_conn *conn = ep->conn->cls_conn->dd_data;
+
+ /* Must suspend all rx queue activity for this ep */
+ set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+ }
+ /* CONN_DISCONNECT timeout may or may not be an issue depending
+ * on what transcribed in TCP layer, different targets behave
+ * differently
+ */
+ printk(KERN_ALERT "bnx2i (%s): - WARN - CONN_DISCON timed out, "
+ "please submit GRC Dump, NW/PCIe trace, "
+ "driver msgs to developers for analysis\n",
+ hba->netdev->name);
}
ep->state = EP_STATE_CLEANUP_START;
@@ -1664,7 +1685,9 @@ static int bnx2i_tear_down_conn(struct bnx2i_hba *hba,
bnx2i_ep_destroy_list_add(hba, ep);
/* destroy iSCSI context, wait for it to complete */
- bnx2i_send_conn_destroy(hba, ep);
+ if (bnx2i_send_conn_destroy(hba, ep))
+ ep->state = EP_STATE_CLEANUP_CMPL;
+
wait_event_interruptible(ep->ofld_wait,
(ep->state != EP_STATE_CLEANUP_START));
@@ -1711,8 +1734,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
if (shost) {
/* driver is given scsi host to work with */
hba = iscsi_host_priv(shost);
- /* Register the device with cnic if not already done so */
- bnx2i_register_device(hba);
} else
/*
* check if the given destination can be reached through
@@ -1720,13 +1741,17 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
*/
hba = bnx2i_check_route(dst_addr);
- if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) {
+ if (!hba) {
rc = -EINVAL;
goto nohba;
}
+ mutex_lock(&hba->net_dev_lock);
+ if (bnx2i_adapter_ready(hba) || !hba->cid_que.cid_free_cnt) {
+ rc = -EPERM;
+ goto check_busy;
+ }
cnic = hba->cnic;
- mutex_lock(&hba->net_dev_lock);
ep = bnx2i_alloc_ep(hba);
if (!ep) {
rc = -ENOMEM;
@@ -1734,23 +1759,21 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
}
bnx2i_ep = ep->dd_data;
- if (bnx2i_adapter_ready(hba)) {
- rc = -EPERM;
- goto net_if_down;
- }
-
bnx2i_ep->num_active_cmds = 0;
iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
if (iscsi_cid == -1) {
- printk(KERN_ALERT "alloc_ep: unable to allocate iscsi cid\n");
+ printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate "
+ "iscsi cid\n", hba->netdev->name);
rc = -ENOMEM;
- goto iscsi_cid_err;
+ bnx2i_free_ep(ep);
+ goto check_busy;
}
bnx2i_ep->hba_age = hba->age;
rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep);
if (rc != 0) {
- printk(KERN_ALERT "bnx2i: ep_conn, alloc QP resc error\n");
+ printk(KERN_ALERT "bnx2i (%s): ep_conn - alloc QP resc error"
+ "\n", hba->netdev->name);
rc = -ENOMEM;
goto qp_resc_err;
}
@@ -1765,7 +1788,18 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep;
add_timer(&bnx2i_ep->ofld_timer);
- bnx2i_send_conn_ofld_req(hba, bnx2i_ep);
+ if (bnx2i_send_conn_ofld_req(hba, bnx2i_ep)) {
+ if (bnx2i_ep->state == EP_STATE_OFLD_FAILED_CID_BUSY) {
+ printk(KERN_ALERT "bnx2i (%s): iscsi cid %d is busy\n",
+ hba->netdev->name, bnx2i_ep->ep_iscsi_cid);
+ rc = -EBUSY;
+ } else
+ rc = -ENOSPC;
+ printk(KERN_ALERT "bnx2i (%s): unable to send conn offld kwqe"
+ "\n", hba->netdev->name);
+ bnx2i_ep_ofld_list_del(hba, bnx2i_ep);
+ goto conn_failed;
+ }
/* Wait for CNIC hardware to setup conn context and return 'cid' */
wait_event_interruptible(bnx2i_ep->ofld_wait,
@@ -1778,7 +1812,12 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
bnx2i_ep_ofld_list_del(hba, bnx2i_ep);
if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) {
- rc = -ENOSPC;
+ if (bnx2i_ep->state == EP_STATE_OFLD_FAILED_CID_BUSY) {
+ printk(KERN_ALERT "bnx2i (%s): iscsi cid %d is busy\n",
+ hba->netdev->name, bnx2i_ep->ep_iscsi_cid);
+ rc = -EBUSY;
+ } else
+ rc = -ENOSPC;
goto conn_failed;
}
@@ -1786,7 +1825,8 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep);
if (rc) {
rc = -EINVAL;
- goto conn_failed;
+ /* Need to terminate and cleanup the connection */
+ goto release_ep;
}
bnx2i_ep->cm_sk->rcv_buf = 256 * 1024;
@@ -1830,15 +1870,12 @@ release_ep:
return ERR_PTR(rc);
}
conn_failed:
-net_if_down:
-iscsi_cid_err:
bnx2i_free_qp_resc(hba, bnx2i_ep);
qp_resc_err:
bnx2i_free_ep(ep);
check_busy:
mutex_unlock(&hba->net_dev_lock);
nohba:
- bnx2i_unreg_dev_all();
return ERR_PTR(rc);
}
@@ -1898,12 +1935,13 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep)
cnic_dev_10g = 1;
switch (bnx2i_ep->state) {
- case EP_STATE_CONNECT_START:
+ case EP_STATE_CONNECT_FAILED:
case EP_STATE_CLEANUP_FAILED:
case EP_STATE_OFLD_FAILED:
case EP_STATE_DISCONN_TIMEDOUT:
ret = 0;
break;
+ case EP_STATE_CONNECT_START:
case EP_STATE_CONNECT_COMPL:
case EP_STATE_ULP_UPDATE_START:
case EP_STATE_ULP_UPDATE_COMPL:
@@ -1914,13 +1952,10 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep)
ret = 1;
break;
case EP_STATE_TCP_RST_RCVD:
- ret = 0;
- break;
- case EP_STATE_CONNECT_FAILED:
if (cnic_dev_10g)
- ret = 1;
- else
ret = 0;
+ else
+ ret = 1;
break;
default:
ret = 0;
@@ -1953,7 +1988,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
if (!cnic)
return 0;
- if (bnx2i_ep->state == EP_STATE_IDLE)
+ if (bnx2i_ep->state == EP_STATE_IDLE ||
+ bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT)
return 0;
if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
@@ -1979,9 +2015,10 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
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");
+ printk(KERN_ALERT "bnx2i (%s): WARNING"
+ " logout response was not "
+ "received!\n",
+ bnx2i_ep->hba->netdev->name);
} else if (bnx2i_ep->state ==
EP_STATE_LOGOUT_RESP_RCVD)
close = 1;
@@ -1999,9 +2036,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
else
close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);
- /* No longer allow CFC delete if cm_close/abort fails the request */
if (close_ret)
- printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n",
+ printk(KERN_ALERT "bnx2i (%s): close/abort(%d) returned %d\n",
bnx2i_ep->hba->netdev->name, close, close_ret);
else
/* wait for option-2 conn teardown */
@@ -2015,7 +2051,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
destroy_conn:
bnx2i_ep_active_list_del(hba, bnx2i_ep);
if (bnx2i_tear_down_conn(hba, bnx2i_ep))
- ret = -EINVAL;
+ return -EINVAL;
out:
bnx2i_ep->state = EP_STATE_IDLE;
return ret;
@@ -2054,14 +2090,17 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
mutex_lock(&hba->net_dev_lock);
- if (bnx2i_ep->state == EP_STATE_IDLE)
- goto return_bnx2i_ep;
+ if (bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT)
+ goto out;
- if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
+ if (bnx2i_ep->state == EP_STATE_IDLE)
goto free_resc;
- if (bnx2i_ep->hba_age != hba->age)
+ if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) ||
+ (bnx2i_ep->hba_age != hba->age)) {
+ bnx2i_ep_active_list_del(hba, bnx2i_ep);
goto free_resc;
+ }
/* Do all chip cleanup here */
if (bnx2i_hw_ep_disconnect(bnx2i_ep)) {
@@ -2070,14 +2109,13 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
}
free_resc:
bnx2i_free_qp_resc(hba, bnx2i_ep);
-return_bnx2i_ep:
+
if (bnx2i_conn)
bnx2i_conn->ep = NULL;
bnx2i_free_ep(ep);
+out:
mutex_unlock(&hba->net_dev_lock);
- if (!hba->ofld_conns_active)
- bnx2i_unreg_dev_all();
wake_up_interruptible(&hba->eh_wait);
}
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index 96426b751eb..9174196d903 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -1,12 +1,13 @@
/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
*
- * Copyright (c) 2004 - 2009 Broadcom Corporation
+ * Copyright (c) 2004 - 2010 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
*/
#include "bnx2i.h"
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index 6fae3d285ae..b837c5b3c8f 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -442,12 +442,19 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
sdev = q->queuedata;
if (sdev && sdev->scsi_dh_data)
scsi_dh = sdev->scsi_dh_data->scsi_dh;
- if (!scsi_dh || !get_device(&sdev->sdev_gendev))
+ if (!scsi_dh || !get_device(&sdev->sdev_gendev) ||
+ sdev->sdev_state == SDEV_CANCEL ||
+ sdev->sdev_state == SDEV_DEL)
err = SCSI_DH_NOSYS;
+ if (sdev->sdev_state == SDEV_OFFLINE)
+ err = SCSI_DH_DEV_OFFLINED;
spin_unlock_irqrestore(q->queue_lock, flags);
- if (err)
+ if (err) {
+ if (fn)
+ fn(data, err);
return err;
+ }
if (scsi_dh->activate)
err = scsi_dh->activate(sdev, fn, data);
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index d23a538a9df..9f9600b6700 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -854,7 +854,6 @@ static void fcoe_if_destroy(struct fc_lport *lport)
/* Cleanup the fc_lport */
fc_lport_destroy(lport);
- fc_fcp_destroy(lport);
/* Stop the transmit retry timer */
del_timer_sync(&port->timer);
@@ -876,6 +875,9 @@ static void fcoe_if_destroy(struct fc_lport *lport)
fc_remove_host(lport->host);
scsi_remove_host(lport->host);
+ /* Destroy lport scsi_priv */
+ fc_fcp_destroy(lport);
+
/* There are no more rports or I/O, free the EM */
fc_exch_mgr_free(lport);
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index bc17c712320..625c6be2539 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -54,6 +54,7 @@ MODULE_LICENSE("GPL v2");
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 int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *);
static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
@@ -176,6 +177,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
fip->mode = mode;
INIT_LIST_HEAD(&fip->fcfs);
mutex_init(&fip->ctlr_mutex);
+ spin_lock_init(&fip->ctlr_lock);
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);
@@ -231,6 +233,49 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
EXPORT_SYMBOL(fcoe_ctlr_destroy);
/**
+ * fcoe_ctlr_announce() - announce new FCF selection
+ * @fip: The FCoE controller
+ *
+ * Also sets the destination MAC for FCoE and control packets
+ *
+ * Called with neither ctlr_mutex nor ctlr_lock held.
+ */
+static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
+{
+ struct fcoe_fcf *sel;
+ struct fcoe_fcf *fcf;
+
+ mutex_lock(&fip->ctlr_mutex);
+ spin_lock_bh(&fip->ctlr_lock);
+
+ kfree_skb(fip->flogi_req);
+ fip->flogi_req = NULL;
+ list_for_each_entry(fcf, &fip->fcfs, list)
+ fcf->flogi_sent = 0;
+
+ spin_unlock_bh(&fip->ctlr_lock);
+ sel = fip->sel_fcf;
+
+ if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr))
+ goto unlock;
+ if (!is_zero_ether_addr(fip->dest_addr)) {
+ printk(KERN_NOTICE "libfcoe: host%d: "
+ "FIP Fibre-Channel Forwarder MAC %pM deselected\n",
+ fip->lp->host->host_no, fip->dest_addr);
+ memset(fip->dest_addr, 0, ETH_ALEN);
+ }
+ if (sel) {
+ printk(KERN_INFO "libfcoe: host%d: FIP selected "
+ "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;
+ }
+unlock:
+ mutex_unlock(&fip->ctlr_mutex);
+}
+
+/**
* fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port
* @fip: The FCoE controller to get the maximum FCoE size from
*
@@ -564,6 +609,9 @@ 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.
+ *
+ * This is called from the lower-level driver with spinlocks held,
+ * so we must not take a mutex here.
*/
int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
struct sk_buff *skb)
@@ -601,7 +649,15 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
switch (op) {
case ELS_FLOGI:
op = FIP_DT_FLOGI;
- break;
+ if (fip->mode == FIP_MODE_VN2VN)
+ break;
+ spin_lock_bh(&fip->ctlr_lock);
+ kfree_skb(fip->flogi_req);
+ fip->flogi_req = skb;
+ fip->flogi_req_send = 1;
+ spin_unlock_bh(&fip->ctlr_lock);
+ schedule_work(&fip->timer_work);
+ return -EINPROGRESS;
case ELS_FDISC:
if (ntoh24(fh->fh_s_id))
return 0;
@@ -922,11 +978,9 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
}
mtu_valid = fcoe_ctlr_mtu_valid(fcf);
fcf->time = jiffies;
- if (!found) {
- LIBFCOE_FIP_DBG(fip, "New FCF for fab %16.16llx "
- "map %x val %d\n",
- fcf->fabric_name, fcf->fc_map, mtu_valid);
- }
+ if (!found)
+ LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n",
+ fcf->fabric_name, fcf->fcf_mac);
/*
* If this advertisement is not solicited and our max receive size
@@ -945,6 +999,17 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
fcoe_ctlr_solicit(fip, NULL);
/*
+ * Put this FCF at the head of the list for priority among equals.
+ * This helps in the case of an NPV switch which insists we use
+ * the FCF that answers multicast solicitations, not the others that
+ * are sending periodic multicast advertisements.
+ */
+ if (mtu_valid) {
+ list_del(&fcf->list);
+ list_add(&fcf->list, &fip->fcfs);
+ }
+
+ /*
* If this is the first validated FCF, note the time and
* set a timer to trigger selection.
*/
@@ -1061,18 +1126,24 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
els_op = *(u8 *)(fh + 1);
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);
+ sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) {
+ if (els_op == ELS_LS_ACC) {
+ 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 (fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
+ fip->flogi_oxid = FC_XID_UNKNOWN;
+ if (els_dtype == FIP_DT_FLOGI)
+ fcoe_ctlr_announce(fip);
+ }
+ } else if (els_dtype == FIP_DT_FLOGI &&
+ !fcoe_ctlr_flogi_retry(fip))
+ goto drop; /* retrying FLOGI so drop reject */
}
if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
@@ -1326,20 +1397,39 @@ drop:
* fcoe_ctlr_select() - Select the best FCF (if possible)
* @fip: The FCoE controller
*
+ * Returns the selected FCF, or NULL if none are usable.
+ *
* If there are conflicting advertisements, no FCF can be chosen.
*
+ * If there is already a selected FCF, this will choose a better one or
+ * an equivalent one that hasn't already been sent a FLOGI.
+ *
* Called with lock held.
*/
-static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
+static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
{
struct fcoe_fcf *fcf;
- struct fcoe_fcf *best = NULL;
+ struct fcoe_fcf *best = fip->sel_fcf;
+ struct fcoe_fcf *first;
+
+ first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
list_for_each_entry(fcf, &fip->fcfs, list) {
- LIBFCOE_FIP_DBG(fip, "consider FCF for fab %16.16llx "
- "VFID %d map %x val %d\n",
- fcf->fabric_name, fcf->vfid,
- fcf->fc_map, fcoe_ctlr_mtu_valid(fcf));
+ LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx "
+ "VFID %d mac %pM map %x val %d "
+ "sent %u pri %u\n",
+ fcf->fabric_name, fcf->vfid, fcf->fcf_mac,
+ fcf->fc_map, fcoe_ctlr_mtu_valid(fcf),
+ fcf->flogi_sent, fcf->pri);
+ if (fcf->fabric_name != first->fabric_name ||
+ fcf->vfid != first->vfid ||
+ fcf->fc_map != first->fc_map) {
+ LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
+ "or FC-MAP\n");
+ return NULL;
+ }
+ if (fcf->flogi_sent)
+ continue;
if (!fcoe_ctlr_fcf_usable(fcf)) {
LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
"map %x %svalid %savailable\n",
@@ -1349,21 +1439,131 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
"" : "un");
continue;
}
- if (!best) {
- best = fcf;
- continue;
- }
- if (fcf->fabric_name != best->fabric_name ||
- fcf->vfid != best->vfid ||
- fcf->fc_map != best->fc_map) {
- LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
- "or FC-MAP\n");
- return;
- }
- if (fcf->pri < best->pri)
+ if (!best || fcf->pri < best->pri || best->flogi_sent)
best = fcf;
}
fip->sel_fcf = best;
+ if (best) {
+ LIBFCOE_FIP_DBG(fip, "using FCF mac %pM\n", best->fcf_mac);
+ fip->port_ka_time = jiffies +
+ msecs_to_jiffies(FIP_VN_KA_PERIOD);
+ fip->ctlr_ka_time = jiffies + best->fka_period;
+ if (time_before(fip->ctlr_ka_time, fip->timer.expires))
+ mod_timer(&fip->timer, fip->ctlr_ka_time);
+ }
+ return best;
+}
+
+/**
+ * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF
+ * @fip: The FCoE controller
+ *
+ * Returns non-zero error if it could not be sent.
+ *
+ * Called with ctlr_mutex and ctlr_lock held.
+ * Caller must verify that fip->sel_fcf is not NULL.
+ */
+static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
+{
+ struct sk_buff *skb;
+ struct sk_buff *skb_orig;
+ struct fc_frame_header *fh;
+ int error;
+
+ skb_orig = fip->flogi_req;
+ if (!skb_orig)
+ return -EINVAL;
+
+ /*
+ * Clone and send the FLOGI request. If clone fails, use original.
+ */
+ skb = skb_clone(skb_orig, GFP_ATOMIC);
+ if (!skb) {
+ skb = skb_orig;
+ fip->flogi_req = NULL;
+ }
+ fh = (struct fc_frame_header *)skb->data;
+ error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb,
+ ntoh24(fh->fh_d_id));
+ if (error) {
+ kfree_skb(skb);
+ return error;
+ }
+ fip->send(fip, skb);
+ fip->sel_fcf->flogi_sent = 1;
+ return 0;
+}
+
+/**
+ * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible
+ * @fip: The FCoE controller
+ *
+ * Returns non-zero error code if there's no FLOGI request to retry or
+ * no alternate FCF available.
+ */
+static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
+{
+ struct fcoe_fcf *fcf;
+ int error;
+
+ mutex_lock(&fip->ctlr_mutex);
+ spin_lock_bh(&fip->ctlr_lock);
+ LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
+ fcf = fcoe_ctlr_select(fip);
+ if (!fcf || fcf->flogi_sent) {
+ kfree_skb(fip->flogi_req);
+ fip->flogi_req = NULL;
+ error = -ENOENT;
+ } else {
+ fcoe_ctlr_solicit(fip, NULL);
+ error = fcoe_ctlr_flogi_send_locked(fip);
+ }
+ spin_unlock_bh(&fip->ctlr_lock);
+ mutex_unlock(&fip->ctlr_mutex);
+ return error;
+}
+
+
+/**
+ * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI.
+ * @fip: The FCoE controller that timed out
+ *
+ * Done here because fcoe_ctlr_els_send() can't get mutex.
+ *
+ * Called with ctlr_mutex held. The caller must not hold ctlr_lock.
+ */
+static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
+{
+ struct fcoe_fcf *fcf;
+
+ spin_lock_bh(&fip->ctlr_lock);
+ fcf = fip->sel_fcf;
+ if (!fcf || !fip->flogi_req_send)
+ goto unlock;
+
+ LIBFCOE_FIP_DBG(fip, "sending FLOGI\n");
+
+ /*
+ * If this FLOGI is being sent due to a timeout retry
+ * to the same FCF as before, select a different FCF if possible.
+ */
+ if (fcf->flogi_sent) {
+ LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n");
+ fcf = fcoe_ctlr_select(fip);
+ if (!fcf || fcf->flogi_sent) {
+ LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n");
+ list_for_each_entry(fcf, &fip->fcfs, list)
+ fcf->flogi_sent = 0;
+ fcf = fcoe_ctlr_select(fip);
+ }
+ }
+ if (fcf) {
+ fcoe_ctlr_flogi_send_locked(fip);
+ fip->flogi_req_send = 0;
+ } else /* XXX */
+ LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
+unlock:
+ spin_unlock_bh(&fip->ctlr_lock);
}
/**
@@ -1411,34 +1611,16 @@ static void fcoe_ctlr_timer_work(struct work_struct *work)
sel = fip->sel_fcf;
if (!sel && fip->sel_time) {
if (time_after_eq(jiffies, fip->sel_time)) {
- fcoe_ctlr_select(fip);
- sel = fip->sel_fcf;
+ sel = fcoe_ctlr_select(fip);
fip->sel_time = 0;
} else if (time_after(next_timer, fip->sel_time))
next_timer = fip->sel_time;
}
- if (sel != fcf) {
- fcf = sel; /* the old FCF may have been freed */
- if (sel) {
- printk(KERN_INFO "libfcoe: host%d: FIP selected "
- "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;
- 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. "
- "Starting FCF discovery.\n",
- fip->lp->host->host_no);
- reset = 1;
- }
- }
+ if (sel && fip->flogi_req_send)
+ fcoe_ctlr_flogi_send(fip);
+ else if (!sel && fcf)
+ reset = 1;
if (sel && !sel->fd_flags) {
if (time_after_eq(jiffies, fip->ctlr_ka_time)) {
@@ -2475,7 +2657,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
case FIP_ST_LINK_WAIT:
goto unlock;
default:
- WARN(1, "unexpected state %d", fip->state);
+ WARN(1, "unexpected state %d\n", fip->state);
goto unlock;
}
mod_timer(&fip->timer, next_time);
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 76365700e2d..3242bcabad9 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4273,8 +4273,10 @@ static int ioc_general(void __user *arg, char *cmnd)
}
rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, &gen.info);
- if (rval < 0)
+ if (rval < 0) {
+ gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
return rval;
+ }
gen.status = rval;
if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf,
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 0572b9bf4bd..652754319a4 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -365,8 +365,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
len = 0;
begin = pos;
}
- if (pos > offset + length)
+ if (pos > offset + length) {
+ gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
goto stop_output;
+ }
}
}
gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
@@ -450,8 +452,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
len = 0;
begin = pos;
}
- if (pos > offset + length)
+ if (pos > offset + length) {
+ gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
goto stop_output;
+ }
} while (drv_no != -1);
if (is_mirr) {
@@ -472,8 +476,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
len = 0;
begin = pos;
}
- if (pos > offset + length)
+ if (pos > offset + length) {
+ gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
goto stop_output;
+ }
}
gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
@@ -542,8 +548,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
len = 0;
begin = pos;
}
- if (pos > offset + length)
+ if (pos > offset + length) {
+ gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
goto stop_output;
+ }
}
}
gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a6dea08664f..12deffccb8d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -641,11 +641,6 @@ static void fixup_botched_add(struct ctlr_info *h,
static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1,
struct hpsa_scsi_dev_t *dev2)
{
- if ((is_logical_dev_addr_mode(dev1->scsi3addr) ||
- (dev1->lun != -1 && dev2->lun != -1)) &&
- dev1->devtype != 0x0C)
- return (memcmp(dev1, dev2, sizeof(*dev1)) == 0);
-
/* we compare everything except lun and target as these
* are not yet assigned. Compare parts likely
* to differ first
@@ -660,12 +655,8 @@ static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1,
return 0;
if (memcmp(dev1->vendor, dev2->vendor, sizeof(dev1->vendor)) != 0)
return 0;
- if (memcmp(dev1->revision, dev2->revision, sizeof(dev1->revision)) != 0)
- return 0;
if (dev1->devtype != dev2->devtype)
return 0;
- if (dev1->raid_level != dev2->raid_level)
- return 0;
if (dev1->bus != dev2->bus)
return 0;
return 1;
@@ -1477,8 +1468,6 @@ static int hpsa_update_device_info(struct ctlr_info *h,
sizeof(this_device->vendor));
memcpy(this_device->model, &inq_buff[16],
sizeof(this_device->model));
- memcpy(this_device->revision, &inq_buff[32],
- sizeof(this_device->revision));
memset(this_device->device_id, 0,
sizeof(this_device->device_id));
hpsa_get_device_id(h, scsi3addr, this_device->device_id,
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index a203ef65cb5..19586e189f0 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -45,7 +45,6 @@ struct hpsa_scsi_dev_t {
unsigned char device_id[16]; /* from inquiry pg. 0x83 */
unsigned char vendor[8]; /* bytes 8-15 of inquiry data */
unsigned char model[16]; /* bytes 16-31 of inquiry data */
- unsigned char revision[4]; /* bytes 32-35 of inquiry data */
unsigned char raid_level; /* from inquiry page 0xC1 */
};
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 57cad7e20ca..b7650613b8c 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2493,23 +2493,23 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport)
}
static const struct ibmvfc_async_desc ae_desc [] = {
- { IBMVFC_AE_ELS_PLOGI, "PLOGI", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
- { IBMVFC_AE_ELS_LOGO, "LOGO", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
- { IBMVFC_AE_ELS_PRLO, "PRLO", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
- { IBMVFC_AE_SCN_NPORT, "N-Port SCN", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
- { IBMVFC_AE_SCN_GROUP, "Group SCN", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
- { IBMVFC_AE_SCN_DOMAIN, "Domain SCN", IBMVFC_DEFAULT_LOG_LEVEL },
- { IBMVFC_AE_SCN_FABRIC, "Fabric SCN", IBMVFC_DEFAULT_LOG_LEVEL },
- { IBMVFC_AE_LINK_UP, "Link Up", IBMVFC_DEFAULT_LOG_LEVEL },
- { IBMVFC_AE_LINK_DOWN, "Link Down", IBMVFC_DEFAULT_LOG_LEVEL },
- { IBMVFC_AE_LINK_DEAD, "Link Dead", IBMVFC_DEFAULT_LOG_LEVEL },
- { IBMVFC_AE_HALT, "Halt", IBMVFC_DEFAULT_LOG_LEVEL },
- { IBMVFC_AE_RESUME, "Resume", IBMVFC_DEFAULT_LOG_LEVEL },
- { IBMVFC_AE_ADAPTER_FAILED, "Adapter Failed", IBMVFC_DEFAULT_LOG_LEVEL },
+ { "PLOGI", IBMVFC_AE_ELS_PLOGI, IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { "LOGO", IBMVFC_AE_ELS_LOGO, IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { "PRLO", IBMVFC_AE_ELS_PRLO, IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { "N-Port SCN", IBMVFC_AE_SCN_NPORT, IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { "Group SCN", IBMVFC_AE_SCN_GROUP, IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { "Domain SCN", IBMVFC_AE_SCN_DOMAIN, IBMVFC_DEFAULT_LOG_LEVEL },
+ { "Fabric SCN", IBMVFC_AE_SCN_FABRIC, IBMVFC_DEFAULT_LOG_LEVEL },
+ { "Link Up", IBMVFC_AE_LINK_UP, IBMVFC_DEFAULT_LOG_LEVEL },
+ { "Link Down", IBMVFC_AE_LINK_DOWN, IBMVFC_DEFAULT_LOG_LEVEL },
+ { "Link Dead", IBMVFC_AE_LINK_DEAD, IBMVFC_DEFAULT_LOG_LEVEL },
+ { "Halt", IBMVFC_AE_HALT, IBMVFC_DEFAULT_LOG_LEVEL },
+ { "Resume", IBMVFC_AE_RESUME, IBMVFC_DEFAULT_LOG_LEVEL },
+ { "Adapter Failed", IBMVFC_AE_ADAPTER_FAILED, IBMVFC_DEFAULT_LOG_LEVEL },
};
static const struct ibmvfc_async_desc unknown_ae = {
- 0, "Unknown async", IBMVFC_DEFAULT_LOG_LEVEL
+ "Unknown async", 0, IBMVFC_DEFAULT_LOG_LEVEL
};
/**
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index ef663e7c9bb..834c37fc7ce 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -542,8 +542,8 @@ enum ibmvfc_async_event {
};
struct ibmvfc_async_desc {
- enum ibmvfc_async_event ae;
const char *desc;
+ enum ibmvfc_async_event ae;
int log_level;
};
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5bbaee597e8..de2e09e49a3 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -146,7 +146,7 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
}
},
{ /* CRoC */
- .mailbox = 0x00040,
+ .mailbox = 0x00044,
.cache_line_size = 0x20,
{
.set_interrupt_mask_reg = 0x00010,
@@ -1048,6 +1048,8 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res,
sizeof(res->res_path));
res->bus = 0;
+ memcpy(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
+ sizeof(res->dev_lun.scsi_lun));
res->lun = scsilun_to_int(&res->dev_lun);
if (res->type == IPR_RES_TYPE_GENERIC_SCSI) {
@@ -1063,9 +1065,6 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res,
ioa_cfg->max_devs_supported);
set_bit(res->target, ioa_cfg->target_ids);
}
-
- memcpy(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
- sizeof(res->dev_lun.scsi_lun));
} else if (res->type == IPR_RES_TYPE_IOAFP) {
res->bus = IPR_IOAFP_VIRTUAL_BUS;
res->target = 0;
@@ -1116,7 +1115,7 @@ static int ipr_is_same_device(struct ipr_resource_entry *res,
if (res->ioa_cfg->sis64) {
if (!memcmp(&res->dev_id, &cfgtew->u.cfgte64->dev_id,
sizeof(cfgtew->u.cfgte64->dev_id)) &&
- !memcmp(&res->lun, &cfgtew->u.cfgte64->lun,
+ !memcmp(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
sizeof(cfgtew->u.cfgte64->lun))) {
return 1;
}
@@ -2901,6 +2900,12 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
return;
}
+ if (ioa_cfg->sis64) {
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ ssleep(IPR_DUMP_DELAY_SECONDS);
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ }
+
start_addr = readl(ioa_cfg->ioa_mailbox);
if (!ioa_cfg->sis64 && !ipr_sdt_is_fmt2(start_addr)) {
@@ -7473,6 +7478,29 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
}
/**
+ * ipr_reset_get_unit_check_job - Call to get the unit check buffer.
+ * @ipr_cmd: ipr command struct
+ *
+ * Description: This function will call to get the unit check buffer.
+ *
+ * Return value:
+ * IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd)
+{
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
+ ENTER;
+ ioa_cfg->ioa_unit_checked = 0;
+ ipr_get_unit_check_buffer(ioa_cfg);
+ ipr_cmd->job_step = ipr_reset_alert;
+ ipr_reset_start_timer(ipr_cmd, 0);
+
+ LEAVE;
+ return IPR_RC_JOB_RETURN;
+}
+
+/**
* ipr_reset_restore_cfg_space - Restore PCI config space.
* @ipr_cmd: ipr command struct
*
@@ -7512,11 +7540,17 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
}
if (ioa_cfg->ioa_unit_checked) {
- ioa_cfg->ioa_unit_checked = 0;
- ipr_get_unit_check_buffer(ioa_cfg);
- ipr_cmd->job_step = ipr_reset_alert;
- ipr_reset_start_timer(ipr_cmd, 0);
- return IPR_RC_JOB_RETURN;
+ if (ioa_cfg->sis64) {
+ ipr_cmd->job_step = ipr_reset_get_unit_check_job;
+ ipr_reset_start_timer(ipr_cmd, IPR_DUMP_DELAY_TIMEOUT);
+ return IPR_RC_JOB_RETURN;
+ } else {
+ ioa_cfg->ioa_unit_checked = 0;
+ ipr_get_unit_check_buffer(ioa_cfg);
+ ipr_cmd->job_step = ipr_reset_alert;
+ ipr_reset_start_timer(ipr_cmd, 0);
+ return IPR_RC_JOB_RETURN;
+ }
}
if (ioa_cfg->in_ioa_bringdown) {
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index b28a00f1082..13f425fb885 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -218,6 +218,8 @@
#define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ)
#define IPR_PCI_RESET_TIMEOUT (HZ / 2)
#define IPR_DUMP_TIMEOUT (15 * HZ)
+#define IPR_DUMP_DELAY_SECONDS 4
+#define IPR_DUMP_DELAY_TIMEOUT (IPR_DUMP_DELAY_SECONDS * HZ)
/*
* SCSI Literals
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index ec2a1aec235..d21367d3305 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -67,6 +67,11 @@ struct workqueue_struct *fc_exch_workqueue;
struct fc_exch_pool {
u16 next_index;
u16 total_exches;
+
+ /* two cache of free slot in exch array */
+ u16 left;
+ u16 right;
+
spinlock_t lock;
struct list_head ex_list;
};
@@ -108,7 +113,6 @@ struct fc_exch_mgr {
atomic_t non_bls_resp;
} stats;
};
-#define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
/**
* struct fc_exch_mgr_anchor - primary structure for list of EMs
@@ -397,13 +401,23 @@ static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index,
static void fc_exch_delete(struct fc_exch *ep)
{
struct fc_exch_pool *pool;
+ u16 index;
pool = ep->pool;
spin_lock_bh(&pool->lock);
WARN_ON(pool->total_exches <= 0);
pool->total_exches--;
- fc_exch_ptr_set(pool, (ep->xid - ep->em->min_xid) >> fc_cpu_order,
- NULL);
+
+ /* update cache of free slot */
+ index = (ep->xid - ep->em->min_xid) >> fc_cpu_order;
+ if (pool->left == FC_XID_UNKNOWN)
+ pool->left = index;
+ else if (pool->right == FC_XID_UNKNOWN)
+ pool->right = index;
+ else
+ pool->next_index = index;
+
+ fc_exch_ptr_set(pool, index, NULL);
list_del(&ep->ex_list);
spin_unlock_bh(&pool->lock);
fc_exch_release(ep); /* drop hold for exch in mp */
@@ -636,10 +650,13 @@ static void fc_exch_timeout(struct work_struct *work)
if (e_stat & ESB_ST_ABNORMAL)
rc = fc_exch_done_locked(ep);
spin_unlock_bh(&ep->ex_lock);
- if (!rc)
- fc_exch_delete(ep);
if (resp)
resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
+ if (!rc) {
+ /* delete the exchange if it's already being aborted */
+ fc_exch_delete(ep);
+ return;
+ }
fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
goto done;
}
@@ -679,6 +696,19 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
pool = per_cpu_ptr(mp->pool, cpu);
spin_lock_bh(&pool->lock);
put_cpu();
+
+ /* peek cache of free slot */
+ if (pool->left != FC_XID_UNKNOWN) {
+ index = pool->left;
+ pool->left = FC_XID_UNKNOWN;
+ goto hit;
+ }
+ if (pool->right != FC_XID_UNKNOWN) {
+ index = pool->right;
+ pool->right = FC_XID_UNKNOWN;
+ goto hit;
+ }
+
index = pool->next_index;
/* allocate new exch from pool */
while (fc_exch_ptr_get(pool, index)) {
@@ -687,7 +717,7 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
goto err;
}
pool->next_index = index == mp->pool_max_index ? 0 : index + 1;
-
+hit:
fc_exch_hold(ep); /* hold for exch in mp */
spin_lock_init(&ep->ex_lock);
/*
@@ -1247,7 +1277,7 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp)
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)
+ fc_seq_lookup_recip(lport, ema->mp, fp) == FC_RJT_NONE)
break;
return fr_seq(fp);
}
@@ -1343,7 +1373,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
}
if (ep->esb_stat & ESB_ST_COMPLETE) {
atomic_inc(&mp->stats.xid_not_found);
- goto out;
+ goto rel;
}
if (ep->rxid == FC_XID_UNKNOWN)
ep->rxid = ntohs(fh->fh_rx_id);
@@ -2181,6 +2211,8 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
goto free_mempool;
for_each_possible_cpu(cpu) {
pool = per_cpu_ptr(mp->pool, cpu);
+ pool->left = FC_XID_UNKNOWN;
+ pool->right = FC_XID_UNKNOWN;
spin_lock_init(&pool->lock);
INIT_LIST_HEAD(&pool->ex_list);
}
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 2924363d142..cdc06cda76e 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -57,6 +57,9 @@ struct kmem_cache *scsi_pkt_cachep;
#define FC_SRB_READ (1 << 1)
#define FC_SRB_WRITE (1 << 0)
+/* constant added to e_d_tov timeout to get rec_tov value */
+#define REC_TOV_CONST 1
+
/*
* The SCp.ptr should be tested and set under the scsi_pkt_queue lock
*/
@@ -96,7 +99,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *, struct fc_frame *);
static void fc_fcp_complete_locked(struct fc_fcp_pkt *);
static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *);
static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *);
-static void fc_fcp_recovery(struct fc_fcp_pkt *);
+static void fc_fcp_recovery(struct fc_fcp_pkt *, u8 code);
static void fc_fcp_timeout(unsigned long);
static void fc_fcp_rec(struct fc_fcp_pkt *);
static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *);
@@ -120,14 +123,13 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *);
#define FC_DATA_UNDRUN 7
#define FC_ERROR 8
#define FC_HRD_ERROR 9
-#define FC_CMD_RECOVERY 10
+#define FC_CRC_ERROR 10
+#define FC_TIMED_OUT 11
/*
* Error recovery timeout values.
*/
-#define FC_SCSI_ER_TIMEOUT (10 * HZ)
#define FC_SCSI_TM_TOV (10 * HZ)
-#define FC_SCSI_REC_TOV (2 * HZ)
#define FC_HOST_RESET_TIMEOUT (30 * HZ)
#define FC_CAN_QUEUE_PERIOD (60 * HZ)
@@ -438,6 +440,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
void *buf;
struct scatterlist *sg;
u32 nents;
+ u8 host_bcode = FC_COMPLETE;
fh = fc_frame_header_get(fp);
offset = ntohl(fh->fh_parm_offset);
@@ -446,13 +449,16 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
buf = fc_frame_payload_get(fp, 0);
/*
- * if this I/O is ddped then clear it
- * and initiate recovery since data
- * frames are expected to be placed
- * directly in that case.
+ * if this I/O is ddped then clear it and initiate recovery since data
+ * frames are expected to be placed directly in that case.
+ *
+ * Indicate error to scsi-ml because something went wrong with the
+ * ddp handling to get us here.
*/
if (fsp->xfer_ddp != FC_XID_UNKNOWN) {
fc_fcp_ddp_done(fsp);
+ FC_FCP_DBG(fsp, "DDP I/O in fc_fcp_recv_data set ERROR\n");
+ host_bcode = FC_ERROR;
goto err;
}
if (offset + len > fsp->data_len) {
@@ -462,6 +468,9 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
goto crc_err;
FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx "
"data_len %x\n", len, offset, fsp->data_len);
+
+ /* Data is corrupted indicate scsi-ml should retry */
+ host_bcode = FC_DATA_OVRRUN;
goto err;
}
if (offset != fsp->xfer_len)
@@ -498,8 +507,10 @@ crc_err:
* If so, we need to retry the entire operation.
* Otherwise, ignore it.
*/
- if (fsp->state & FC_SRB_DISCONTIG)
+ if (fsp->state & FC_SRB_DISCONTIG) {
+ host_bcode = FC_CRC_ERROR;
goto err;
+ }
return;
}
}
@@ -517,7 +528,7 @@ crc_err:
fc_fcp_complete_locked(fsp);
return;
err:
- fc_fcp_recovery(fsp);
+ fc_fcp_recovery(fsp, host_bcode);
}
/**
@@ -962,7 +973,13 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp)
}
lport->tt.exch_done(seq);
}
- fc_io_compl(fsp);
+ /*
+ * Some resets driven by SCSI are not I/Os and do not have
+ * SCSI commands associated with the requests. We should not
+ * call I/O completion if we do not have a SCSI command.
+ */
+ if (fsp->cmd)
+ fc_io_compl(fsp);
}
/**
@@ -1073,6 +1090,21 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
}
/**
+ * get_fsp_rec_tov() - Helper function to get REC_TOV
+ * @fsp: the FCP packet
+ */
+static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
+{
+ struct fc_rport *rport;
+ struct fc_rport_libfc_priv *rpriv;
+
+ rport = fsp->rport;
+ rpriv = rport->dd_data;
+
+ return rpriv->e_d_tov + REC_TOV_CONST;
+}
+
+/**
* fc_fcp_cmd_send() - Send a FCP command
* @lport: The local port to send the command on
* @fsp: The FCP packet the command is on
@@ -1089,6 +1121,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
struct fc_rport_libfc_priv *rpriv;
const size_t len = sizeof(fsp->cdb_cmd);
int rc = 0;
+ unsigned int rec_tov;
if (fc_fcp_lock_pkt(fsp))
return 0;
@@ -1119,10 +1152,13 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
fsp->seq_ptr = seq;
fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
+ rec_tov = get_fsp_rec_tov(fsp);
+
setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
- fc_fcp_timer_set(fsp,
- (fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED) ?
- FC_SCSI_REC_TOV : FC_SCSI_ER_TIMEOUT);
+
+ if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
+ fc_fcp_timer_set(fsp, rec_tov);
+
unlock:
fc_fcp_unlock_pkt(fsp);
return rc;
@@ -1197,13 +1233,16 @@ static void fc_lun_reset_send(unsigned long data)
{
struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data;
struct fc_lport *lport = fsp->lp;
+ unsigned int rec_tov;
+
if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) {
if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY)
return;
if (fc_fcp_lock_pkt(fsp))
return;
+ rec_tov = get_fsp_rec_tov(fsp);
setup_timer(&fsp->timer, fc_lun_reset_send, (unsigned long)fsp);
- fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
+ fc_fcp_timer_set(fsp, rec_tov);
fc_fcp_unlock_pkt(fsp);
}
}
@@ -1282,27 +1321,27 @@ static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg)
*
* scsi-eh will escalate for when either happens.
*/
- return;
+ goto out;
}
if (fc_fcp_lock_pkt(fsp))
- return;
+ goto out;
/*
* raced with eh timeout handler.
*/
- if (!fsp->seq_ptr || !fsp->wait_for_comp) {
- spin_unlock_bh(&fsp->scsi_pkt_lock);
- return;
- }
+ if (!fsp->seq_ptr || !fsp->wait_for_comp)
+ goto out_unlock;
fh = fc_frame_header_get(fp);
if (fh->fh_type != FC_TYPE_BLS)
fc_fcp_resp(fsp, fp);
fsp->seq_ptr = NULL;
fsp->lp->tt.exch_done(seq);
- fc_frame_free(fp);
+out_unlock:
fc_fcp_unlock_pkt(fsp);
+out:
+ fc_frame_free(fp);
}
/**
@@ -1341,13 +1380,10 @@ static void fc_fcp_timeout(unsigned long data)
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
fc_fcp_rec(fsp);
- else if (time_after_eq(fsp->last_pkt_time + (FC_SCSI_ER_TIMEOUT / 2),
- jiffies))
- fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
else if (fsp->state & FC_SRB_RCV_STATUS)
fc_fcp_complete_locked(fsp);
else
- fc_fcp_recovery(fsp);
+ fc_fcp_recovery(fsp, FC_TIMED_OUT);
fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;
unlock:
fc_fcp_unlock_pkt(fsp);
@@ -1373,6 +1409,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
fc_fcp_complete_locked(fsp);
return;
}
+
fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec));
if (!fp)
goto retry;
@@ -1383,15 +1420,15 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
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))) {
+ 2 * lport->r_a_tov)) {
fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */
return;
}
retry:
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
- fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
+ fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
else
- fc_fcp_recovery(fsp);
+ fc_fcp_recovery(fsp, FC_TIMED_OUT);
}
/**
@@ -1445,7 +1482,6 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
* making progress.
*/
rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED;
- fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
break;
case ELS_RJT_LOGIC:
case ELS_RJT_UNAB:
@@ -1460,7 +1496,7 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fc_fcp_retry_cmd(fsp);
break;
}
- fc_fcp_recovery(fsp);
+ fc_fcp_recovery(fsp, FC_ERROR);
break;
}
} else if (opcode == ELS_LS_ACC) {
@@ -1498,12 +1534,12 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
}
fc_fcp_srr(fsp, r_ctl, offset);
} else if (e_stat & ESB_ST_SEQ_INIT) {
-
+ unsigned int rec_tov = get_fsp_rec_tov(fsp);
/*
* The remote port has the initiative, so just
* keep waiting for it to complete.
*/
- fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
+ fc_fcp_timer_set(fsp, rec_tov);
} else {
/*
@@ -1575,7 +1611,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
fc_fcp_rec(fsp);
else
- fc_fcp_recovery(fsp);
+ fc_fcp_recovery(fsp, FC_ERROR);
break;
}
fc_fcp_unlock_pkt(fsp);
@@ -1587,9 +1623,9 @@ out:
* fc_fcp_recovery() - Handler for fcp_pkt recovery
* @fsp: The FCP pkt that needs to be aborted
*/
-static void fc_fcp_recovery(struct fc_fcp_pkt *fsp)
+static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code)
{
- fsp->status_code = FC_CMD_RECOVERY;
+ fsp->status_code = code;
fsp->cdb_status = 0;
fsp->io_status = 0;
/*
@@ -1616,6 +1652,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
struct fcp_srr *srr;
struct fc_frame *fp;
u8 cdb_op;
+ unsigned int rec_tov;
rport = fsp->rport;
rpriv = rport->dd_data;
@@ -1640,8 +1677,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
rpriv->local_port->port_id, FC_TYPE_FCP,
FC_FCTL_REQ, 0);
+ rec_tov = get_fsp_rec_tov(fsp);
seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL,
- fsp, jiffies_to_msecs(FC_SCSI_REC_TOV));
+ fsp, jiffies_to_msecs(rec_tov));
if (!seq)
goto retry;
@@ -1665,6 +1703,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
{
struct fc_fcp_pkt *fsp = arg;
struct fc_frame_header *fh;
+ unsigned int rec_tov;
if (IS_ERR(fp)) {
fc_fcp_srr_error(fsp, fp);
@@ -1691,11 +1730,12 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
switch (fc_frame_payload_op(fp)) {
case ELS_LS_ACC:
fsp->recov_retry = 0;
- fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
+ rec_tov = get_fsp_rec_tov(fsp);
+ fc_fcp_timer_set(fsp, rec_tov);
break;
case ELS_LS_RJT:
default:
- fc_fcp_recovery(fsp);
+ fc_fcp_recovery(fsp, FC_ERROR);
break;
}
fc_fcp_unlock_pkt(fsp);
@@ -1721,7 +1761,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
fc_fcp_rec(fsp);
else
- fc_fcp_recovery(fsp);
+ fc_fcp_recovery(fsp, FC_TIMED_OUT);
break;
case -FC_EX_CLOSED: /* e.g., link failure */
/* fall through */
@@ -1820,19 +1860,17 @@ static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scs
if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
fsp->req_flags = FC_SRB_READ;
stats->InputRequests++;
- stats->InputMegabytes = fsp->data_len;
+ stats->InputBytes += fsp->data_len;
} else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
fsp->req_flags = FC_SRB_WRITE;
stats->OutputRequests++;
- stats->OutputMegabytes = fsp->data_len;
+ stats->OutputBytes += fsp->data_len;
} else {
fsp->req_flags = 0;
stats->ControlRequests++;
}
put_cpu();
- fsp->tgt_flags = rpriv->flags;
-
init_timer(&fsp->timer);
fsp->timer.data = (unsigned long)fsp;
@@ -1946,18 +1984,29 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
break;
case FC_CMD_ABORTED:
FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
- "due to FC_CMD_ABORTED\n");
+ "due to FC_CMD_ABORTED\n");
sc_cmd->result = (DID_ERROR << 16) | fsp->io_status;
break;
- case FC_CMD_RECOVERY:
- sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
- break;
case FC_CMD_RESET:
+ FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml "
+ "due to FC_CMD_RESET\n");
sc_cmd->result = (DID_RESET << 16);
break;
case FC_HRD_ERROR:
+ FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml "
+ "due to FC_HRD_ERROR\n");
sc_cmd->result = (DID_NO_CONNECT << 16);
break;
+ case FC_CRC_ERROR:
+ FC_FCP_DBG(fsp, "Returning DID_PARITY to scsi-ml "
+ "due to FC_CRC_ERROR\n");
+ sc_cmd->result = (DID_PARITY << 16);
+ break;
+ case FC_TIMED_OUT:
+ FC_FCP_DBG(fsp, "Returning DID_BUS_BUSY to scsi-ml "
+ "due to FC_TIMED_OUT\n");
+ sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
+ break;
default:
FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
"due to unknown error\n");
@@ -2004,7 +2053,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
fsp = CMD_SP(sc_cmd);
if (!fsp) {
/* command completed while scsi eh was setting up */
- spin_unlock_irqrestore(lport->host->host_lock, flags);
+ spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
return SUCCESS;
}
/* grab a ref so the fsp and sc_cmd cannot be relased from under us */
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
index 16d2162dda1..eea0c3541b7 100644
--- a/drivers/scsi/libfc/fc_libfc.h
+++ b/drivers/scsi/libfc/fc_libfc.h
@@ -66,9 +66,21 @@ extern unsigned int fc_debug_logging;
#define FC_FCP_DBG(pkt, fmt, args...) \
FC_CHECK_LOGGING(FC_FCP_LOGGING, \
- printk(KERN_INFO "host%u: fcp: %6.6x: " fmt, \
+ { \
+ if ((pkt)->seq_ptr) { \
+ struct fc_exch *_ep = NULL; \
+ _ep = fc_seq_exch((pkt)->seq_ptr); \
+ printk(KERN_INFO "host%u: fcp: %6.6x: " \
+ "xid %04x-%04x: " fmt, \
(pkt)->lp->host->host_no, \
- pkt->rport->port_id, ##args))
+ (pkt)->rport->port_id, \
+ (_ep)->oxid, (_ep)->rxid, ##args); \
+ } else { \
+ printk(KERN_INFO "host%u: fcp: %6.6x: " fmt, \
+ (pkt)->lp->host->host_no, \
+ (pkt)->rport->port_id, ##args); \
+ } \
+ })
#define FC_EXCH_DBG(exch, fmt, args...) \
FC_CHECK_LOGGING(FC_EXCH_LOGGING, \
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 9be63edbf8f..c5a10f94f84 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -288,6 +288,8 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
struct fc_lport *lport = shost_priv(shost);
struct timespec v0, v1;
unsigned int cpu;
+ u64 fcp_in_bytes = 0;
+ u64 fcp_out_bytes = 0;
fcoe_stats = &lport->host_stats;
memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
@@ -310,10 +312,12 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
fcoe_stats->fcp_input_requests += stats->InputRequests;
fcoe_stats->fcp_output_requests += stats->OutputRequests;
fcoe_stats->fcp_control_requests += stats->ControlRequests;
- fcoe_stats->fcp_input_megabytes += stats->InputMegabytes;
- fcoe_stats->fcp_output_megabytes += stats->OutputMegabytes;
+ fcp_in_bytes += stats->InputBytes;
+ fcp_out_bytes += stats->OutputBytes;
fcoe_stats->link_failure_count += stats->LinkFailureCount;
}
+ fcoe_stats->fcp_input_megabytes = div_u64(fcp_in_bytes, 1000000);
+ fcoe_stats->fcp_output_megabytes = div_u64(fcp_out_bytes, 1000000);
fcoe_stats->lip_count = -1;
fcoe_stats->nos_count = -1;
fcoe_stats->loss_of_sync_count = -1;
@@ -1703,8 +1707,10 @@ static int fc_lport_els_request(struct fc_bsg_job *job,
info->sg = job->reply_payload.sg_list;
if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp,
- NULL, info, tov))
+ NULL, info, tov)) {
+ kfree(info);
return -ECOMM;
+ }
return 0;
}
@@ -1762,8 +1768,10 @@ static int fc_lport_ct_request(struct fc_bsg_job *job,
info->sg = job->reply_payload.sg_list;
if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp,
- NULL, info, tov))
+ NULL, info, tov)) {
+ kfree(info);
return -ECOMM;
+ }
return 0;
}
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a84ef13ed74..a7175adab32 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -652,7 +652,7 @@ void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp));
if (fp == ERR_PTR(-FC_EX_CLOSED))
- return;
+ goto put;
mutex_lock(&rdata->rp_mutex);
@@ -689,6 +689,7 @@ out:
fc_frame_free(fp);
err:
mutex_unlock(&rdata->rp_mutex);
+put:
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
return;
bad:
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index c15fde808c3..da8b61543ee 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -505,6 +505,7 @@ static void iscsi_free_task(struct iscsi_task *task)
struct iscsi_conn *conn = task->conn;
struct iscsi_session *session = conn->session;
struct scsi_cmnd *sc = task->sc;
+ int oldstate = task->state;
ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n",
task->itt, task->state, task->sc);
@@ -525,10 +526,10 @@ static void iscsi_free_task(struct iscsi_task *task)
/* SCSI eh reuses commands to verify us */
sc->SCp.ptr = NULL;
/*
- * queue command may call this to free the task, but
- * not have setup the sc callback
+ * queue command may call this to free the task, so
+ * it will decide how to return sc to scsi-ml.
*/
- if (sc->scsi_done)
+ if (oldstate != ISCSI_TASK_REQUEUE_SCSIQ)
sc->scsi_done(sc);
}
}
@@ -539,11 +540,12 @@ void __iscsi_get_task(struct iscsi_task *task)
}
EXPORT_SYMBOL_GPL(__iscsi_get_task);
-static void __iscsi_put_task(struct iscsi_task *task)
+void __iscsi_put_task(struct iscsi_task *task)
{
if (atomic_dec_and_test(&task->refcount))
iscsi_free_task(task);
}
+EXPORT_SYMBOL_GPL(__iscsi_put_task);
void iscsi_put_task(struct iscsi_task *task)
{
@@ -571,7 +573,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)
task->itt, task->state, task->sc);
if (task->state == ISCSI_TASK_COMPLETED ||
task->state == ISCSI_TASK_ABRT_TMF ||
- task->state == ISCSI_TASK_ABRT_SESS_RECOV)
+ task->state == ISCSI_TASK_ABRT_SESS_RECOV ||
+ task->state == ISCSI_TASK_REQUEUE_SCSIQ)
return;
WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
task->state = state;
@@ -1335,17 +1338,16 @@ void iscsi_session_failure(struct iscsi_session *session,
{
struct iscsi_conn *conn;
struct device *dev;
- unsigned long flags;
- spin_lock_irqsave(&session->lock, flags);
+ spin_lock_bh(&session->lock);
conn = session->leadconn;
if (session->state == ISCSI_STATE_TERMINATE || !conn) {
- spin_unlock_irqrestore(&session->lock, flags);
+ spin_unlock_bh(&session->lock);
return;
}
dev = get_device(&conn->cls_conn->dev);
- spin_unlock_irqrestore(&session->lock, flags);
+ spin_unlock_bh(&session->lock);
if (!dev)
return;
/*
@@ -1364,17 +1366,16 @@ EXPORT_SYMBOL_GPL(iscsi_session_failure);
void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
{
struct iscsi_session *session = conn->session;
- unsigned long flags;
- spin_lock_irqsave(&session->lock, flags);
+ spin_lock_bh(&session->lock);
if (session->state == ISCSI_STATE_FAILED) {
- spin_unlock_irqrestore(&session->lock, flags);
+ spin_unlock_bh(&session->lock);
return;
}
if (conn->stop_stage == 0)
session->state = ISCSI_STATE_FAILED;
- spin_unlock_irqrestore(&session->lock, flags);
+ spin_unlock_bh(&session->lock);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
@@ -1599,27 +1600,23 @@ enum {
FAILURE_SESSION_NOT_READY,
};
-static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
{
struct iscsi_cls_session *cls_session;
- struct Scsi_Host *host;
struct iscsi_host *ihost;
int reason = 0;
struct iscsi_session *session;
struct iscsi_conn *conn;
struct iscsi_task *task = NULL;
- sc->scsi_done = done;
sc->result = 0;
sc->SCp.ptr = NULL;
- host = sc->device->host;
ihost = shost_priv(host);
- spin_unlock(host->host_lock);
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
- spin_lock(&session->lock);
+ spin_lock_bh(&session->lock);
reason = iscsi_session_chkready(cls_session);
if (reason) {
@@ -1705,25 +1702,21 @@ static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi
}
session->queued_cmdsn++;
- spin_unlock(&session->lock);
- spin_lock(host->host_lock);
+ spin_unlock_bh(&session->lock);
return 0;
prepd_reject:
- sc->scsi_done = NULL;
- iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
reject:
- spin_unlock(&session->lock);
+ spin_unlock_bh(&session->lock);
ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
sc->cmnd[0], reason);
- spin_lock(host->host_lock);
return SCSI_MLQUEUE_TARGET_BUSY;
prepd_fault:
- sc->scsi_done = NULL;
- iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+ iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
fault:
- spin_unlock(&session->lock);
+ spin_unlock_bh(&session->lock);
ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
sc->cmnd[0], reason);
if (!scsi_bidi_cmnd(sc))
@@ -1732,12 +1725,9 @@ fault:
scsi_out(sc)->resid = scsi_out(sc)->length;
scsi_in(sc)->resid = scsi_in(sc)->length;
}
- done(sc);
- spin_lock(host->host_lock);
+ sc->scsi_done(sc);
return 0;
}
-
-DEF_SCSI_QCMD(iscsi_queuecommand)
EXPORT_SYMBOL_GPL(iscsi_queuecommand);
int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
@@ -1795,9 +1785,9 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
NULL, 0);
if (!task) {
spin_unlock_bh(&session->lock);
+ iscsi_conn_printk(KERN_ERR, conn, "Could not send TMF.\n");
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
spin_lock_bh(&session->lock);
- ISCSI_DBG_EH(session, "tmf exec failure\n");
return -EPERM;
}
conn->tmfcmd_pdus_cnt++;
@@ -2202,7 +2192,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
goto success_unlocked;
case TMF_TIMEDOUT:
spin_unlock_bh(&session->lock);
- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
goto failed_unlocked;
case TMF_NOT_FOUND:
if (!sc->SCp.ptr) {
@@ -2289,7 +2279,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
break;
case TMF_TIMEDOUT:
spin_unlock_bh(&session->lock);
- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
goto done;
default:
conn->tmf_state = TMF_INITIAL;
@@ -2370,7 +2360,7 @@ failed:
* we drop the lock here but the leadconn cannot be destoyed while
* we are in the scsi eh
*/
- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
ISCSI_DBG_EH(session, "wait for relogin\n");
wait_event_interruptible(conn->ehwait,
@@ -2452,7 +2442,7 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc)
break;
case TMF_TIMEDOUT:
spin_unlock_bh(&session->lock);
- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
goto done;
default:
conn->tmf_state = TMF_INITIAL;
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index fe8b74c706d..5257fdfe699 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -28,6 +28,17 @@
#include <scsi/scsi_transport_sas.h>
#include "../scsi_sas_internal.h"
+static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy *phy)
+{
+ struct sas_ha_struct *sas_ha = phy->ha;
+
+ if (memcmp(port->attached_sas_addr, phy->attached_sas_addr,
+ SAS_ADDR_SIZE) != 0 || (sas_ha->strict_wide_ports &&
+ memcmp(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE) != 0))
+ return false;
+ return true;
+}
+
/**
* sas_form_port -- add this phy to a port
* @phy: the phy of interest
@@ -45,8 +56,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
unsigned long flags;
if (port) {
- if (memcmp(port->attached_sas_addr, phy->attached_sas_addr,
- SAS_ADDR_SIZE) != 0)
+ if (!phy_is_wideport_member(port, phy))
sas_deform_port(phy);
else {
SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n",
@@ -62,9 +72,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
port = sas_ha->sas_port[i];
spin_lock(&port->phy_list_lock);
if (*(u64 *) port->sas_addr &&
- memcmp(port->attached_sas_addr,
- phy->attached_sas_addr, SAS_ADDR_SIZE) == 0 &&
- port->num_phys > 0) {
+ phy_is_wideport_member(port, phy) && port->num_phys > 0) {
/* wide port */
SAS_DPRINTK("phy%d matched wide port%d\n", phy->id,
port->id);
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 196de40b906..746dd3d7a09 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -464,12 +464,29 @@ struct unsol_rcv_ct_ctx {
#define UNSOL_VALID 0x00000001
};
+#define LPFC_USER_LINK_SPEED_AUTO 0 /* auto select (default)*/
+#define LPFC_USER_LINK_SPEED_1G 1 /* 1 Gigabaud */
+#define LPFC_USER_LINK_SPEED_2G 2 /* 2 Gigabaud */
+#define LPFC_USER_LINK_SPEED_4G 4 /* 4 Gigabaud */
+#define LPFC_USER_LINK_SPEED_8G 8 /* 8 Gigabaud */
+#define LPFC_USER_LINK_SPEED_10G 10 /* 10 Gigabaud */
+#define LPFC_USER_LINK_SPEED_16G 16 /* 16 Gigabaud */
+#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_16G
+#define LPFC_USER_LINK_SPEED_BITMAP ((1 << LPFC_USER_LINK_SPEED_16G) | \
+ (1 << LPFC_USER_LINK_SPEED_10G) | \
+ (1 << LPFC_USER_LINK_SPEED_8G) | \
+ (1 << LPFC_USER_LINK_SPEED_4G) | \
+ (1 << LPFC_USER_LINK_SPEED_2G) | \
+ (1 << LPFC_USER_LINK_SPEED_1G) | \
+ (1 << LPFC_USER_LINK_SPEED_AUTO))
+#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16"
+
struct lpfc_hba {
/* SCSI interface function jump table entries */
int (*lpfc_new_scsi_buf)
(struct lpfc_vport *, int);
struct lpfc_scsi_buf * (*lpfc_get_scsi_buf)
- (struct lpfc_hba *);
+ (struct lpfc_hba *, struct lpfc_nodelist *);
int (*lpfc_scsi_prep_dma_buf)
(struct lpfc_hba *, struct lpfc_scsi_buf *);
void (*lpfc_scsi_unprep_dma_buf)
@@ -545,7 +562,7 @@ struct lpfc_hba {
uint32_t hba_flag; /* hba generic flags */
#define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */
#define DEFER_ERATT 0x2 /* Deferred error attention in progress */
-#define HBA_FCOE_SUPPORT 0x4 /* HBA function supports FCOE */
+#define HBA_FCOE_MODE 0x4 /* HBA function in FCoE Mode */
#define HBA_SP_QUEUE_EVT 0x8 /* Slow-path qevt posted to worker thread*/
#define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */
#define FCP_XRI_ABORT_EVENT 0x20
@@ -557,6 +574,7 @@ struct lpfc_hba {
#define HBA_FIP_SUPPORT 0x800 /* FIP support in HBA */
#define HBA_AER_ENABLED 0x1000 /* AER enabled with HBA */
#define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */
+#define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */
uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
struct lpfc_dmabuf slim2p;
@@ -606,6 +624,7 @@ struct lpfc_hba {
/* HBA Config Parameters */
uint32_t cfg_ack0;
uint32_t cfg_enable_npiv;
+ uint32_t cfg_enable_rrq;
uint32_t cfg_topology;
uint32_t cfg_link_speed;
uint32_t cfg_cr_delay;
@@ -716,6 +735,7 @@ struct lpfc_hba {
uint32_t total_scsi_bufs;
struct list_head lpfc_iocb_list;
uint32_t total_iocbq_bufs;
+ struct list_head active_rrq_list;
spinlock_t hbalock;
/* pci_mem_pools */
@@ -728,6 +748,7 @@ struct lpfc_hba {
mempool_t *mbox_mem_pool;
mempool_t *nlp_mem_pool;
+ mempool_t *rrq_pool;
struct fc_host_statistics link_stats;
enum intr_type_t intr_type;
@@ -784,6 +805,7 @@ struct lpfc_hba {
unsigned long skipped_hb;
struct timer_list hb_tmofunc;
uint8_t hb_outstanding;
+ struct timer_list rrq_tmr;
enum hba_temp_state over_temp_state;
/* ndlp reference management */
spinlock_t ndlp_lock;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index c1cbec01345..c06491b5862 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -52,10 +52,6 @@
#define LPFC_MIN_DEVLOSS_TMO 1
#define LPFC_MAX_DEVLOSS_TMO 255
-#define LPFC_MAX_LINK_SPEED 8
-#define LPFC_LINK_SPEED_BITMAP 0x00000117
-#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8"
-
/**
* lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
* @incr: integer to convert.
@@ -463,7 +459,7 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
if (phba->sli.sli_flag & LPFC_MENLO_MAINT)
len += snprintf(buf + len, PAGE_SIZE-len,
" Menlo Maint Mode\n");
- else if (phba->fc_topology == TOPOLOGY_LOOP) {
+ else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
if (vport->fc_flag & FC_PUBLIC_LOOP)
len += snprintf(buf + len, PAGE_SIZE-len,
" Public Loop\n");
@@ -1981,6 +1977,13 @@ lpfc_param_show(enable_npiv);
lpfc_param_init(enable_npiv, 1, 0, 1);
static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
+int lpfc_enable_rrq;
+module_param(lpfc_enable_rrq, int, 0);
+MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
+lpfc_param_show(enable_rrq);
+lpfc_param_init(enable_rrq, 0, 0, 1);
+static DEVICE_ATTR(lpfc_enable_rrq, S_IRUGO, lpfc_enable_rrq_show, NULL);
+
/*
# lpfc_suppress_link_up: Bring link up at initialization
# 0x0 = bring link up (issue MBX_INIT_LINK)
@@ -2837,14 +2840,8 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = {
/*
# lpfc_link_speed: Link speed selection for initializing the Fibre Channel
# connection.
-# 0 = auto select (default)
-# 1 = 1 Gigabaud
-# 2 = 2 Gigabaud
-# 4 = 4 Gigabaud
-# 8 = 8 Gigabaud
-# Value range is [0,8]. Default value is 0.
+# Value range is [0,16]. Default value is 0.
*/
-
/**
* lpfc_link_speed_set - Set the adapters link speed
* @phba: lpfc_hba pointer.
@@ -2869,7 +2866,7 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
- int val = 0;
+ int val = LPFC_USER_LINK_SPEED_AUTO;
int nolip = 0;
const char *val_buf = buf;
int err;
@@ -2885,15 +2882,20 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
if (sscanf(val_buf, "%i", &val) != 1)
return -EINVAL;
- if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
- ((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
- ((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
- ((val == LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
- ((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)))
+ if (((val == LPFC_USER_LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
+ ((val == LPFC_USER_LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
+ ((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
+ ((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
+ ((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) ||
+ ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb))) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2879 lpfc_link_speed attribute cannot be set "
+ "to %d. Speed is not supported by this port.\n",
+ val);
return -EINVAL;
-
- if ((val >= 0 && val <= 8)
- && (LPFC_LINK_SPEED_BITMAP & (1 << val))) {
+ }
+ if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
+ (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
prev_val = phba->cfg_link_speed;
phba->cfg_link_speed = val;
if (nolip)
@@ -2906,11 +2908,9 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
} else
return strlen(buf);
}
-
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "%d:0469 lpfc_link_speed attribute cannot be set to %d, "
- "allowed range is [0, 8]\n",
- phba->brd_no, val);
+ "0469 lpfc_link_speed attribute cannot be set to %d, "
+ "allowed values are ["LPFC_LINK_SPEED_STRING"]\n", val);
return -EINVAL;
}
@@ -2938,8 +2938,8 @@ lpfc_param_show(link_speed)
static int
lpfc_link_speed_init(struct lpfc_hba *phba, int val)
{
- if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED)
- && (LPFC_LINK_SPEED_BITMAP & (1 << val))) {
+ if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
+ (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
phba->cfg_link_speed = val;
return 0;
}
@@ -2947,12 +2947,12 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val)
"0405 lpfc_link_speed attribute cannot "
"be set to %d, allowed values are "
"["LPFC_LINK_SPEED_STRING"]\n", val);
- phba->cfg_link_speed = 0;
+ phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
return -EINVAL;
}
static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
- lpfc_link_speed_show, lpfc_link_speed_store);
+ lpfc_link_speed_show, lpfc_link_speed_store);
/*
# lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER)
@@ -3305,12 +3305,12 @@ LPFC_ATTR_R(fcp_eq_count, LPFC_FP_EQN_DEF, LPFC_FP_EQN_MIN, LPFC_FP_EQN_MAX,
LPFC_ATTR_R(enable_hba_reset, 1, 0, 1, "Enable HBA resets from the driver.");
/*
-# lpfc_enable_hba_heartbeat: Enable HBA heartbeat timer..
+# lpfc_enable_hba_heartbeat: Disable HBA heartbeat timer..
# 0 = HBA Heartbeat disabled
# 1 = HBA Heartbeat enabled (default)
# Value range is [0,1]. Default value is 1.
*/
-LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat.");
+LPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat.");
/*
# lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF)
@@ -3401,6 +3401,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_fdmi_on,
&dev_attr_lpfc_max_luns,
&dev_attr_lpfc_enable_npiv,
+ &dev_attr_lpfc_enable_rrq,
&dev_attr_nport_evt_cnt,
&dev_attr_board_mode,
&dev_attr_max_vpi,
@@ -3798,8 +3799,7 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj,
}
break;
case MBX_READ_SPARM64:
- case MBX_READ_LA:
- case MBX_READ_LA64:
+ case MBX_READ_TOPOLOGY:
case MBX_REG_LOGIN:
case MBX_REG_LOGIN64:
case MBX_CONFIG_PORT:
@@ -3989,7 +3989,7 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)
if (vport->port_type == LPFC_NPIV_PORT) {
fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
} else if (lpfc_is_link_up(phba)) {
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
if (vport->fc_flag & FC_PUBLIC_LOOP)
fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
else
@@ -4058,23 +4058,26 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
if (lpfc_is_link_up(phba)) {
switch(phba->fc_linkspeed) {
- case LA_1GHZ_LINK:
- fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+ case LPFC_LINK_SPEED_1GHZ:
+ fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
break;
- case LA_2GHZ_LINK:
- fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
+ case LPFC_LINK_SPEED_2GHZ:
+ fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
break;
- case LA_4GHZ_LINK:
- fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
+ case LPFC_LINK_SPEED_4GHZ:
+ fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
break;
- case LA_8GHZ_LINK:
- fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
+ case LPFC_LINK_SPEED_8GHZ:
+ fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
break;
- case LA_10GHZ_LINK:
- fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+ case LPFC_LINK_SPEED_10GHZ:
+ fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
break;
- default:
- fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+ case LPFC_LINK_SPEED_16GHZ:
+ fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
+ break;
+ default:
+ fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
}
} else
@@ -4097,7 +4100,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
spin_lock_irq(shost->host_lock);
if ((vport->fc_flag & FC_FABRIC) ||
- ((phba->fc_topology == TOPOLOGY_LOOP) &&
+ ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
(vport->fc_flag & FC_PUBLIC_LOOP)))
node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
else
@@ -4208,11 +4211,11 @@ lpfc_get_stats(struct Scsi_Host *shost)
hs->invalid_crc_count -= lso->invalid_crc_count;
hs->error_frames -= lso->error_frames;
- if (phba->hba_flag & HBA_FCOE_SUPPORT) {
+ if (phba->hba_flag & HBA_FCOE_MODE) {
hs->lip_count = -1;
hs->nos_count = (phba->link_events >> 1);
hs->nos_count -= lso->link_events;
- } else if (phba->fc_topology == TOPOLOGY_LOOP) {
+ } else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
hs->lip_count = (phba->fc_eventTag >> 1);
hs->lip_count -= lso->link_events;
hs->nos_count = -1;
@@ -4303,7 +4306,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord;
lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
lso->error_frames = pmb->un.varRdLnk.crcCnt;
- if (phba->hba_flag & HBA_FCOE_SUPPORT)
+ if (phba->hba_flag & HBA_FCOE_MODE)
lso->link_events = (phba->link_events >> 1);
else
lso->link_events = (phba->fc_eventTag >> 1);
@@ -4615,6 +4618,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_link_speed_init(phba, lpfc_link_speed);
lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
lpfc_enable_npiv_init(phba, lpfc_enable_npiv);
+ lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
lpfc_use_msi_init(phba, lpfc_use_msi);
lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 7260c3af555..0dd43bb9161 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -162,7 +162,6 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocbq,
struct lpfc_iocbq *rspiocbq)
{
- unsigned long iflags;
struct bsg_job_data *dd_data;
struct fc_bsg_job *job;
IOCB_t *rsp;
@@ -173,9 +172,10 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
int rc = 0;
spin_lock_irqsave(&phba->ct_ev_lock, flags);
- dd_data = cmdiocbq->context1;
+ dd_data = cmdiocbq->context2;
if (!dd_data) {
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+ lpfc_sli_release_iocbq(phba, cmdiocbq);
return;
}
@@ -183,17 +183,9 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
job = iocb->set_job;
job->dd_data = NULL; /* so timeout handler does not reply */
- spin_lock_irqsave(&phba->hbalock, iflags);
- cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
- if (cmdiocbq->context2 && rspiocbq)
- memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
- &rspiocbq->iocb, sizeof(IOCB_t));
- spin_unlock_irqrestore(&phba->hbalock, iflags);
-
bmp = iocb->bmp;
- rspiocbq = iocb->rspiocbq;
rsp = &rspiocbq->iocb;
- ndlp = iocb->ndlp;
+ ndlp = cmdiocbq->context1;
pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -220,7 +212,6 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
rsp->un.genreq64.bdl.bdeSize;
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
- lpfc_sli_release_iocbq(phba, rspiocbq);
lpfc_sli_release_iocbq(phba, cmdiocbq);
lpfc_nlp_put(ndlp);
kfree(bmp);
@@ -247,9 +238,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
struct ulp_bde64 *bpl = NULL;
uint32_t timeout;
struct lpfc_iocbq *cmdiocbq = NULL;
- struct lpfc_iocbq *rspiocbq = NULL;
IOCB_t *cmd;
- IOCB_t *rsp;
struct lpfc_dmabuf *bmp = NULL;
int request_nseg;
int reply_nseg;
@@ -296,17 +285,10 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
}
cmd = &cmdiocbq->iocb;
- rspiocbq = lpfc_sli_get_iocbq(phba);
- if (!rspiocbq) {
- rc = -ENOMEM;
- goto free_cmdiocbq;
- }
-
- rsp = &rspiocbq->iocb;
bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
if (!bmp->virt) {
rc = -ENOMEM;
- goto free_rspiocbq;
+ goto free_cmdiocbq;
}
INIT_LIST_HEAD(&bmp->list);
@@ -358,14 +340,12 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
cmd->ulpTimeout = timeout;
cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;
- cmdiocbq->context1 = dd_data;
- cmdiocbq->context2 = rspiocbq;
+ cmdiocbq->context1 = ndlp;
+ cmdiocbq->context2 = dd_data;
dd_data->type = TYPE_IOCB;
dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
- dd_data->context_un.iocb.rspiocbq = rspiocbq;
dd_data->context_un.iocb.set_job = job;
dd_data->context_un.iocb.bmp = bmp;
- dd_data->context_un.iocb.ndlp = ndlp;
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
creg_val = readl(phba->HCregaddr);
@@ -391,8 +371,6 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-free_rspiocbq:
- lpfc_sli_release_iocbq(phba, rspiocbq);
free_cmdiocbq:
lpfc_sli_release_iocbq(phba, cmdiocbq);
free_bmp:
@@ -1220,7 +1198,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
int rc = 0;
spin_lock_irqsave(&phba->ct_ev_lock, flags);
- dd_data = cmdiocbq->context1;
+ dd_data = cmdiocbq->context2;
/* normal completion and timeout crossed paths, already done */
if (!dd_data) {
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
@@ -1369,8 +1347,8 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
ctiocb->context3 = bmp;
ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp;
- ctiocb->context1 = dd_data;
- ctiocb->context2 = NULL;
+ ctiocb->context2 = dd_data;
+ ctiocb->context1 = ndlp;
dd_data->type = TYPE_IOCB;
dd_data->context_un.iocb.cmdiocbq = ctiocb;
dd_data->context_un.iocb.rspiocbq = NULL;
@@ -1641,7 +1619,7 @@ job_error:
* This function obtains a remote port login id so the diag loopback test
* can send and receive its own unsolicited CT command.
**/
-static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi)
+static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi)
{
LPFC_MBOXQ_t *mbox;
struct lpfc_dmabuf *dmabuff;
@@ -1651,10 +1629,14 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi)
if (!mbox)
return -ENOMEM;
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ *rpi = lpfc_sli4_alloc_rpi(phba);
status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,
- (uint8_t *)&phba->pport->fc_sparam, mbox, 0);
+ (uint8_t *)&phba->pport->fc_sparam, mbox, *rpi);
if (status) {
mempool_free(mbox, phba->mbox_mem_pool);
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ lpfc_sli4_free_rpi(phba, *rpi);
return -ENOMEM;
}
@@ -1668,6 +1650,8 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi)
kfree(dmabuff);
if (status != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ lpfc_sli4_free_rpi(phba, *rpi);
return -ENODEV;
}
@@ -1704,8 +1688,9 @@ static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi)
mempool_free(mbox, phba->mbox_mem_pool);
return -EIO;
}
-
mempool_free(mbox, phba->mbox_mem_pool);
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ lpfc_sli4_free_rpi(phba, rpi);
return 0;
}
@@ -2102,7 +2087,7 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
uint32_t size;
uint32_t full_size;
size_t segment_len = 0, segment_offset = 0, current_offset = 0;
- uint16_t rpi;
+ uint16_t rpi = 0;
struct lpfc_iocbq *cmdiocbq, *rspiocbq;
IOCB_t *cmd, *rsp;
struct lpfc_sli_ct_request *ctreq;
@@ -2162,7 +2147,7 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
goto loopback_test_exit;
}
- if (size >= BUF_SZ_4K) {
+ if (full_size >= BUF_SZ_4K) {
/*
* Allocate memory for ioctl data. If buffer is bigger than 64k,
* then we allocate 64k and re-use that buffer over and over to
@@ -2171,7 +2156,7 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
* problem with GET_FCPTARGETMAPPING...
*/
if (size <= (64 * 1024))
- total_mem = size;
+ total_mem = full_size;
else
total_mem = 64 * 1024;
} else
@@ -2189,7 +2174,6 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
sg_copy_to_buffer(job->request_payload.sg_list,
job->request_payload.sg_cnt,
ptr, size);
-
rc = lpfcdiag_loop_self_reg(phba, &rpi);
if (rc)
goto loopback_test_exit;
@@ -2601,12 +2585,11 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba,
phba->wait_4_mlo_maint_flg = 1;
} else if (mb->un.varWords[0] == SETVAR_MLORST) {
phba->link_flag &= ~LS_LOOPBACK_MODE;
- phba->fc_topology = TOPOLOGY_PT_PT;
+ phba->fc_topology = LPFC_TOPOLOGY_PT_PT;
}
break;
case MBX_READ_SPARM64:
- case MBX_READ_LA:
- case MBX_READ_LA64:
+ case MBX_READ_TOPOLOGY:
case MBX_REG_LOGIN:
case MBX_REG_LOGIN64:
case MBX_CONFIG_PORT:
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index a5f5a093a8a..17fde522c84 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -31,7 +31,7 @@ void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
-int lpfc_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *);
+int lpfc_read_topology(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *);
void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_issue_clear_la(struct lpfc_hba *, struct lpfc_vport *);
void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -40,7 +40,7 @@ int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *, int);
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);
+ LPFC_MBOXQ_t *, uint16_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 *);
@@ -64,7 +64,7 @@ void lpfc_cleanup_pending_mbox(struct lpfc_vport *);
int lpfc_linkdown(struct lpfc_hba *);
void lpfc_linkdown_port(struct lpfc_vport *);
void lpfc_port_link_failure(struct lpfc_vport *);
-void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
+void lpfc_mbx_cmpl_read_topology(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *);
void lpfc_retry_pport_discovery(struct lpfc_hba *);
@@ -121,6 +121,7 @@ void lpfc_end_rscn(struct lpfc_vport *);
int lpfc_els_chk_latt(struct lpfc_vport *);
int lpfc_els_abort_flogi(struct lpfc_hba *);
int lpfc_initial_flogi(struct lpfc_vport *);
+void lpfc_issue_init_vfi(struct lpfc_vport *);
int lpfc_initial_fdisc(struct lpfc_vport *);
int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t);
int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
@@ -415,5 +416,13 @@ struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *,
int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
struct lpfc_iocbq *, uint32_t);
uint32_t lpfc_drain_txq(struct lpfc_hba *);
-
-
+void lpfc_clr_rrq_active(struct lpfc_hba *, uint16_t, struct lpfc_node_rrq *);
+int lpfc_test_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, uint16_t);
+void lpfc_handle_rrq_active(struct lpfc_hba *);
+int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *);
+int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *,
+ uint16_t, uint16_t, uint16_t);
+void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
+void lpfc_cleanup_vports_rrqs(struct lpfc_vport *);
+struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
+ uint32_t);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 463b74902ac..c004fa9a681 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -48,14 +48,14 @@
#include "lpfc_vport.h"
#include "lpfc_debugfs.h"
-#define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver
- * incapable of reporting */
-#define HBA_PORTSPEED_1GBIT 1 /* 1 GBit/sec */
-#define HBA_PORTSPEED_2GBIT 2 /* 2 GBit/sec */
-#define HBA_PORTSPEED_4GBIT 8 /* 4 GBit/sec */
-#define HBA_PORTSPEED_8GBIT 16 /* 8 GBit/sec */
-#define HBA_PORTSPEED_10GBIT 4 /* 10 GBit/sec */
-#define HBA_PORTSPEED_NOT_NEGOTIATED 5 /* Speed not established */
+/* FDMI Port Speed definitions */
+#define HBA_PORTSPEED_1GBIT 0x0001 /* 1 GBit/sec */
+#define HBA_PORTSPEED_2GBIT 0x0002 /* 2 GBit/sec */
+#define HBA_PORTSPEED_4GBIT 0x0008 /* 4 GBit/sec */
+#define HBA_PORTSPEED_10GBIT 0x0004 /* 10 GBit/sec */
+#define HBA_PORTSPEED_8GBIT 0x0010 /* 8 GBit/sec */
+#define HBA_PORTSPEED_16GBIT 0x0020 /* 16 GBit/sec */
+#define HBA_PORTSPEED_UNKNOWN 0x0800 /* Unknown */
#define FOURBYTES 4
@@ -1593,8 +1593,10 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
ae->un.SupportSpeed = 0;
+ if (phba->lmt & LMT_16Gb)
+ ae->un.SupportSpeed |= HBA_PORTSPEED_16GBIT;
if (phba->lmt & LMT_10Gb)
- ae->un.SupportSpeed = HBA_PORTSPEED_10GBIT;
+ ae->un.SupportSpeed |= HBA_PORTSPEED_10GBIT;
if (phba->lmt & LMT_8Gb)
ae->un.SupportSpeed |= HBA_PORTSPEED_8GBIT;
if (phba->lmt & LMT_4Gb)
@@ -1612,24 +1614,26 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
ae->ad.bits.AttrType = be16_to_cpu(PORT_SPEED);
ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
switch(phba->fc_linkspeed) {
- case LA_1GHZ_LINK:
- ae->un.PortSpeed = HBA_PORTSPEED_1GBIT;
+ case LPFC_LINK_SPEED_1GHZ:
+ ae->un.PortSpeed = HBA_PORTSPEED_1GBIT;
break;
- case LA_2GHZ_LINK:
- ae->un.PortSpeed = HBA_PORTSPEED_2GBIT;
+ case LPFC_LINK_SPEED_2GHZ:
+ ae->un.PortSpeed = HBA_PORTSPEED_2GBIT;
break;
- case LA_4GHZ_LINK:
- ae->un.PortSpeed = HBA_PORTSPEED_4GBIT;
+ case LPFC_LINK_SPEED_4GHZ:
+ ae->un.PortSpeed = HBA_PORTSPEED_4GBIT;
break;
- case LA_8GHZ_LINK:
- ae->un.PortSpeed = HBA_PORTSPEED_8GBIT;
+ case LPFC_LINK_SPEED_8GHZ:
+ ae->un.PortSpeed = HBA_PORTSPEED_8GBIT;
break;
- case LA_10GHZ_LINK:
- ae->un.PortSpeed = HBA_PORTSPEED_10GBIT;
+ case LPFC_LINK_SPEED_10GHZ:
+ ae->un.PortSpeed = HBA_PORTSPEED_10GBIT;
break;
- default:
- ae->un.PortSpeed =
- HBA_PORTSPEED_UNKNOWN;
+ case LPFC_LINK_SPEED_16GHZ:
+ ae->un.PortSpeed = HBA_PORTSPEED_16GBIT;
+ break;
+ default:
+ ae->un.PortSpeed = HBA_PORTSPEED_UNKNOWN;
break;
}
pab->ab.EntryCnt++;
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 7cae69de36f..1d84b63fcca 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -68,6 +68,12 @@ struct lpfc_fast_path_event {
} un;
};
+#define LPFC_SLI4_MAX_XRI 1024 /* Used to make the ndlp's xri_bitmap */
+#define XRI_BITMAP_ULONGS (LPFC_SLI4_MAX_XRI / BITS_PER_LONG)
+struct lpfc_node_rrqs {
+ unsigned long xri_bitmap[XRI_BITMAP_ULONGS];
+};
+
struct lpfc_nodelist {
struct list_head nlp_listp;
struct lpfc_name nlp_portname;
@@ -110,8 +116,19 @@ struct lpfc_nodelist {
atomic_t cmd_pending;
uint32_t cmd_qdepth;
unsigned long last_change_time;
+ struct lpfc_node_rrqs active_rrqs;
struct lpfc_scsicmd_bkt *lat_data; /* Latency data */
};
+struct lpfc_node_rrq {
+ struct list_head list;
+ uint16_t xritag;
+ uint16_t send_rrq;
+ uint16_t rxid;
+ uint32_t nlp_DID; /* FC D_ID of entry */
+ struct lpfc_vport *vport;
+ struct lpfc_nodelist *ndlp;
+ unsigned long rrq_stop_time;
+};
/* Defines for nlp_flag (uint32) */
#define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */
@@ -136,7 +153,7 @@ struct lpfc_nodelist {
#define NLP_NODEV_REMOVE 0x08000000 /* Defer removal till discovery ends */
#define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */
#define NLP_SC_REQ 0x20000000 /* Target requires authentication */
-#define NLP_RPI_VALID 0x80000000 /* nlp_rpi is valid */
+#define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */
/* ndlp usage management macros */
#define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 884f4d32179..c62d567cc84 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -375,7 +375,8 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
err = 4;
goto fail;
}
- rc = lpfc_reg_rpi(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox, 0);
+ rc = lpfc_reg_rpi(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
+ ndlp->nlp_rpi);
if (rc) {
err = 5;
goto fail_free_mbox;
@@ -523,7 +524,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
phba->fc_edtovResol = sp->cmn.edtovResolution;
phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_PUBLIC_LOOP;
spin_unlock_irq(shost->host_lock);
@@ -832,6 +833,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
goto out;
+ /* FLOGI failure */
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0100 FLOGI failure Status:x%x/x%x TMO:x%x\n",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout);
+
/* FLOGI failed, so there is no fabric */
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
@@ -843,13 +850,16 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
*/
if (phba->alpa_map[0] == 0) {
vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
+ if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ (!(vport->fc_flag & FC_VFI_REGISTERED) ||
+ (vport->fc_prevDID != vport->fc_myDID))) {
+ if (vport->fc_flag & FC_VFI_REGISTERED)
+ lpfc_sli4_unreg_all_rpis(vport);
+ lpfc_issue_reg_vfi(vport);
+ lpfc_nlp_put(ndlp);
+ goto out;
+ }
}
-
- /* FLOGI failure */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "0100 FLOGI failure Status:x%x/x%x TMO:x%x\n",
- irsp->ulpStatus, irsp->un.ulpWord[4],
- irsp->ulpTimeout);
goto flogifail;
}
spin_lock_irq(shost->host_lock);
@@ -879,7 +889,7 @@ 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 if (!(phba->hba_flag & HBA_FCOE_SUPPORT))
+ else if (!(phba->hba_flag & HBA_FCOE_MODE))
rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp);
else {
lpfc_printf_vlog(vport, KERN_ERR,
@@ -1014,7 +1024,9 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (sp->cmn.fcphHigh < FC_PH3)
sp->cmn.fcphHigh = FC_PH3;
- if (phba->sli_rev == LPFC_SLI_REV4) {
+ if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_IF_TYPE_0)) {
elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1);
elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1);
/* FLOGI needs to be 3 for WQE FCFI */
@@ -1027,7 +1039,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
icmd->ulpCt_l = 0;
}
- if (phba->fc_topology != TOPOLOGY_LOOP) {
+ if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
icmd->un.elsreq64.myID = 0;
icmd->un.elsreq64.fl = 1;
}
@@ -1281,6 +1293,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
uint32_t rc, keepDID = 0;
int put_node;
int put_rport;
+ struct lpfc_node_rrqs rrq;
/* Fabric nodes can have the same WWPN so we don't bother searching
* by WWPN. Just return the ndlp that was given to us.
@@ -1298,6 +1311,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp))
return ndlp;
+ memset(&rrq.xri_bitmap, 0, sizeof(new_ndlp->active_rrqs.xri_bitmap));
if (!new_ndlp) {
rc = memcmp(&ndlp->nlp_portname, name,
@@ -1318,12 +1332,25 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
if (!new_ndlp)
return ndlp;
keepDID = new_ndlp->nlp_DID;
- } else
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ memcpy(&rrq.xri_bitmap,
+ &new_ndlp->active_rrqs.xri_bitmap,
+ sizeof(new_ndlp->active_rrqs.xri_bitmap));
+ } else {
keepDID = new_ndlp->nlp_DID;
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ memcpy(&rrq.xri_bitmap,
+ &new_ndlp->active_rrqs.xri_bitmap,
+ sizeof(new_ndlp->active_rrqs.xri_bitmap));
+ }
lpfc_unreg_rpi(vport, new_ndlp);
new_ndlp->nlp_DID = ndlp->nlp_DID;
new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ memcpy(new_ndlp->active_rrqs.xri_bitmap,
+ &ndlp->active_rrqs.xri_bitmap,
+ sizeof(ndlp->active_rrqs.xri_bitmap));
if (ndlp->nlp_flag & NLP_NPR_2B_DISC)
new_ndlp->nlp_flag |= NLP_NPR_2B_DISC;
@@ -1362,12 +1389,20 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
/* Two ndlps cannot have the same did on the nodelist */
ndlp->nlp_DID = keepDID;
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ memcpy(&ndlp->active_rrqs.xri_bitmap,
+ &rrq.xri_bitmap,
+ sizeof(ndlp->active_rrqs.xri_bitmap));
lpfc_drop_node(vport, ndlp);
}
else {
lpfc_unreg_rpi(vport, ndlp);
/* Two ndlps cannot have the same did */
ndlp->nlp_DID = keepDID;
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ memcpy(&ndlp->active_rrqs.xri_bitmap,
+ &rrq.xri_bitmap,
+ sizeof(ndlp->active_rrqs.xri_bitmap));
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
@@ -1428,6 +1463,73 @@ lpfc_end_rscn(struct lpfc_vport *vport)
}
/**
+ * lpfc_cmpl_els_rrq - Completion handled for els RRQs.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine will call the clear rrq function to free the rrq and
+ * clear the xri's bit in the ndlp's xri_bitmap. If the ndlp does not
+ * exist then the clear_rrq is still called because the rrq needs to
+ * be freed.
+ **/
+
+static void
+lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ struct lpfc_iocbq *rspiocb)
+{
+ struct lpfc_vport *vport = cmdiocb->vport;
+ IOCB_t *irsp;
+ struct lpfc_nodelist *ndlp;
+ struct lpfc_node_rrq *rrq;
+
+ /* we pass cmdiocb to state machine which needs rspiocb as well */
+ rrq = cmdiocb->context_un.rrq;
+ cmdiocb->context_un.rsp_iocb = rspiocb;
+
+ irsp = &rspiocb->iocb;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "RRQ cmpl: status:x%x/x%x did:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->un.elsreq64.remoteID);
+
+ ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ndlp != rrq->ndlp) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "2882 RRQ completes to NPort x%x "
+ "with no ndlp. Data: x%x x%x x%x\n",
+ irsp->un.elsreq64.remoteID,
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpIoTag);
+ goto out;
+ }
+
+ /* rrq completes to NPort <nlp_DID> */
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "2880 RRQ completes to NPort x%x "
+ "Data: x%x x%x x%x x%x x%x\n",
+ ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout, rrq->xritag, rrq->rxid);
+
+ if (irsp->ulpStatus) {
+ /* Check for retry */
+ /* RRQ 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,
+ "2881 RRQ failure DID:%06X Status:x%x/x%x\n",
+ ndlp->nlp_DID, irsp->ulpStatus,
+ irsp->un.ulpWord[4]);
+ }
+out:
+ if (rrq)
+ lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+ lpfc_els_free_iocb(phba, cmdiocb);
+ return;
+}
+/**
* lpfc_cmpl_els_plogi - Completion callback function for plogi
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
@@ -2722,7 +2824,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
if (cmd == ELS_CMD_FLOGI) {
if (PCI_DEVICE_ID_HORNET ==
phba->pcidev->device) {
- phba->fc_topology = TOPOLOGY_LOOP;
+ phba->fc_topology = LPFC_TOPOLOGY_LOOP;
phba->pport->fc_myDID = 0;
phba->alpa_map[0] = 0;
phba->alpa_map[1] = 0;
@@ -2877,7 +2979,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
retry = 1;
if (((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) &&
- (phba->fc_topology != TOPOLOGY_LOOP) &&
+ (phba->fc_topology != LPFC_TOPOLOGY_LOOP) &&
!lpfc_error_lost_link(irsp)) {
/* FLOGI retry policy */
retry = 1;
@@ -3219,14 +3321,6 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
- /*
- * This routine is used to register and unregister in previous SLI
- * modes.
- */
- if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) &&
- (phba->sli_rev == LPFC_SLI_REV4))
- lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi);
-
pmb->context1 = NULL;
pmb->context2 = NULL;
@@ -3904,6 +3998,47 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
}
/**
+ * lpfc_els_clear_rrq - Clear the rq that this rrq describes.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @iocb: pointer to the lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * Return
+ **/
+static void
+lpfc_els_clear_rrq(struct lpfc_vport *vport,
+ struct lpfc_iocbq *iocb, struct lpfc_nodelist *ndlp)
+{
+ struct lpfc_hba *phba = vport->phba;
+ uint8_t *pcmd;
+ struct RRQ *rrq;
+ uint16_t rxid;
+ struct lpfc_node_rrq *prrq;
+
+
+ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt);
+ pcmd += sizeof(uint32_t);
+ rrq = (struct RRQ *)pcmd;
+ rxid = bf_get(rrq_oxid, rrq);
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x"
+ " x%x x%x\n",
+ bf_get(rrq_did, rrq),
+ bf_get(rrq_oxid, rrq),
+ rxid,
+ iocb->iotag, iocb->iocb.ulpContext);
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+ "Clear RRQ: did:x%x flg:x%x exchg:x%.08x",
+ ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg);
+ prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID);
+ if (prrq)
+ lpfc_clr_rrq_active(phba, rxid, prrq);
+ return;
+}
+
+/**
* lpfc_els_rsp_echo_acc - Issue echo acc response
* @vport: pointer to a virtual N_Port data structure.
* @data: pointer to echo data to return in the accept.
@@ -4597,7 +4732,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
lpfc_set_disctmo(vport);
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
/* We should never receive a FLOGI in loop mode, ignore it */
did = icmd->un.elsreq64.remoteID;
@@ -4792,6 +4927,8 @@ lpfc_els_rcv_rrq(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
{
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
+ if (vport->phba->sli_rev == LPFC_SLI_REV4)
+ lpfc_els_clear_rrq(vport, cmdiocb, ndlp);
}
/**
@@ -4940,7 +5077,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
pcmd += sizeof(uint32_t); /* Skip past command */
rps_rsp = (RPS_RSP *)pcmd;
- if (phba->fc_topology != TOPOLOGY_LOOP)
+ if (phba->fc_topology != LPFC_TOPOLOGY_LOOP)
status = 0x10;
else
status = 0x8;
@@ -5194,6 +5331,97 @@ reject_out:
return 0;
}
+/* lpfc_issue_els_rrq - Process an unsolicited rps iocb
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @did: DID of the target.
+ * @rrq: Pointer to the rrq struct.
+ *
+ * Build a ELS RRQ command and send it to the target. If the issue_iocb is
+ * Successful the the completion handler will clear the RRQ.
+ *
+ * Return codes
+ * 0 - Successfully sent rrq els iocb.
+ * 1 - Failed to send rrq els iocb.
+ **/
+static int
+lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ uint32_t did, struct lpfc_node_rrq *rrq)
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct RRQ *els_rrq;
+ IOCB_t *icmd;
+ struct lpfc_iocbq *elsiocb;
+ uint8_t *pcmd;
+ uint16_t cmdsize;
+ int ret;
+
+
+ if (ndlp != rrq->ndlp)
+ ndlp = rrq->ndlp;
+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+ return 1;
+
+ /* If ndlp is not NULL, we will bump the reference count on it */
+ cmdsize = (sizeof(uint32_t) + sizeof(struct RRQ));
+ elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, did,
+ ELS_CMD_RRQ);
+ if (!elsiocb)
+ return 1;
+
+ icmd = &elsiocb->iocb;
+ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+
+ /* For RRQ request, remainder of payload is Exchange IDs */
+ *((uint32_t *) (pcmd)) = ELS_CMD_RRQ;
+ pcmd += sizeof(uint32_t);
+ els_rrq = (struct RRQ *) pcmd;
+
+ bf_set(rrq_oxid, els_rrq, rrq->xritag);
+ bf_set(rrq_rxid, els_rrq, rrq->rxid);
+ bf_set(rrq_did, els_rrq, vport->fc_myDID);
+ els_rrq->rrq = cpu_to_be32(els_rrq->rrq);
+ els_rrq->rrq_exchg = cpu_to_be32(els_rrq->rrq_exchg);
+
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue RRQ: did:x%x",
+ did, rrq->xritag, rrq->rxid);
+ elsiocb->context_un.rrq = rrq;
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq;
+ ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
+
+ if (ret == IOCB_ERROR) {
+ lpfc_els_free_iocb(phba, elsiocb);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * lpfc_send_rrq - Sends ELS RRQ if needed.
+ * @phba: pointer to lpfc hba data structure.
+ * @rrq: pointer to the active rrq.
+ *
+ * This routine will call the lpfc_issue_els_rrq if the rrq is
+ * still active for the xri. If this function returns a failure then
+ * the caller needs to clean up the RRQ by calling lpfc_clr_active_rrq.
+ *
+ * Returns 0 Success.
+ * 1 Failure.
+ **/
+int
+lpfc_send_rrq(struct lpfc_hba *phba, struct lpfc_node_rrq *rrq)
+{
+ struct lpfc_nodelist *ndlp = lpfc_findnode_did(rrq->vport,
+ rrq->nlp_DID);
+ if (lpfc_test_rrq_active(phba, ndlp, rrq->xritag))
+ return lpfc_issue_els_rrq(rrq->vport, ndlp,
+ rrq->nlp_DID, rrq);
+ else
+ return 1;
+}
+
/**
* lpfc_els_rsp_rpl_acc - Issue an accept rpl els command
* @vport: pointer to a host virtual N_Port data structure.
@@ -5482,7 +5710,7 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
(memcmp(&phba->fc_fabparam.portName, &fp->FportName,
sizeof(struct lpfc_name)))) {
/* This port has switched fabrics. FLOGI is required */
- lpfc_initial_flogi(vport);
+ lpfc_issue_init_vfi(vport);
} else {
/* FAN verified - skip FLOGI */
vport->fc_myDID = vport->fc_prevDID;
@@ -6201,7 +6429,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
cmd, did, vport->port_state);
/* Unsupported ELS command, reject */
- rjt_err = LSRJT_INVALID_CMD;
+ rjt_err = LSRJT_CMD_UNSUPPORTED;
/* Unknown ELS command <elsCmd> received from NPORT <did> */
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -6373,7 +6601,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
if (!ndlp) {
ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
if (!ndlp) {
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
lpfc_disc_start(vport);
return;
}
@@ -6386,7 +6614,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
} else if (!NLP_CHK_NODE_ACT(ndlp)) {
ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
if (!ndlp) {
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
lpfc_disc_start(vport);
return;
}
@@ -6408,18 +6636,31 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
}
if (vport->cfg_fdmi_on) {
- ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
- GFP_KERNEL);
+ /* If this is the first time, allocate an ndlp and initialize
+ * it. Otherwise, make sure the node is enabled and then do the
+ * login.
+ */
+ ndlp_fdmi = lpfc_findnode_did(vport, FDMI_DID);
+ if (!ndlp_fdmi) {
+ ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
+ GFP_KERNEL);
+ if (ndlp_fdmi) {
+ lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
+ ndlp_fdmi->nlp_type |= NLP_FABRIC;
+ } else
+ return;
+ }
+ if (!NLP_CHK_NODE_ACT(ndlp_fdmi))
+ ndlp_fdmi = lpfc_enable_node(vport,
+ ndlp_fdmi,
+ NLP_STE_NPR_NODE);
+
if (ndlp_fdmi) {
- lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
- ndlp_fdmi->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp_fdmi,
- NLP_STE_PLOGI_ISSUE);
- lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
- 0);
+ NLP_STE_PLOGI_ISSUE);
+ lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID, 0);
}
}
- return;
}
/**
@@ -6497,7 +6738,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
spin_unlock_irq(shost->host_lock);
if (vport->port_type == LPFC_PHYSICAL_PORT
&& !(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG))
- lpfc_initial_flogi(vport);
+ lpfc_issue_init_vfi(vport);
else
lpfc_initial_fdisc(vport);
break;
@@ -6734,7 +6975,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
vport->fc_flag &= ~FC_VPORT_CVL_RCVD;
vport->fc_flag &= ~FC_VPORT_LOGO_RCVD;
vport->fc_flag |= FC_FABRIC;
- if (vport->phba->fc_topology == TOPOLOGY_LOOP)
+ if (vport->phba->fc_topology == LPFC_TOPOLOGY_LOOP)
vport->fc_flag |= FC_PUBLIC_LOOP;
spin_unlock_irq(shost->host_lock);
@@ -6844,7 +7085,9 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
icmd->un.elsreq64.myID = 0;
icmd->un.elsreq64.fl = 1;
- if (phba->sli_rev == LPFC_SLI_REV4) {
+ if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_IF_TYPE_0)) {
/* FDISC needs to be 1 for WQE VPI */
elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1;
elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ;
@@ -7351,8 +7594,11 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
struct sli4_wcqe_xri_aborted *axri)
{
uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
+ uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
+
struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
unsigned long iflag = 0;
+ struct lpfc_nodelist *ndlp;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
spin_lock_irqsave(&phba->hbalock, iflag);
@@ -7361,11 +7607,14 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
&phba->sli4_hba.lpfc_abts_els_sgl_list, list) {
if (sglq_entry->sli4_xritag == xri) {
list_del(&sglq_entry->list);
+ ndlp = sglq_entry->ndlp;
+ sglq_entry->ndlp = NULL;
list_add_tail(&sglq_entry->list,
&phba->sli4_hba.lpfc_sgl_list);
sglq_entry->state = SGL_FREED;
spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
spin_unlock_irqrestore(&phba->hbalock, iflag);
+ lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1);
/* Check if TXQ queue needs to be serviced */
if (pring->txq_cnt)
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index a5d1695dac3..f9f160ab2ee 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -607,6 +607,8 @@ lpfc_work_done(struct lpfc_hba *phba)
/* Process SLI4 events */
if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) {
+ if (phba->hba_flag & HBA_RRQ_ACTIVE)
+ lpfc_handle_rrq_active(phba);
if (phba->hba_flag & FCP_XRI_ABORT_EVENT)
lpfc_sli4_fcp_xri_abort_event_proc(phba);
if (phba->hba_flag & ELS_XRI_ABORT_EVENT)
@@ -966,6 +968,7 @@ lpfc_linkup(struct lpfc_hba *phba)
struct lpfc_vport **vports;
int i;
+ lpfc_cleanup_wt_rrqs(phba);
phba->link_state = LPFC_LINK_UP;
/* Unblock fabric iocbs if they are blocked */
@@ -1064,7 +1067,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
mempool_free(pmb, phba->mbox_mem_pool);
- if (phba->fc_topology == TOPOLOGY_LOOP &&
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP &&
vport->fc_flag & FC_PUBLIC_LOOP &&
!(vport->fc_flag & FC_LBIT)) {
/* Need to wait for FAN - use discovery timer
@@ -1078,9 +1081,8 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
/* Start discovery by sending a FLOGI. port_state is identically
* LPFC_FLOGI while waiting for FLOGI cmpl
*/
- if (vport->port_state != LPFC_FLOGI) {
+ if (vport->port_state != LPFC_FLOGI)
lpfc_initial_flogi(vport);
- }
return;
out:
@@ -1131,7 +1133,7 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
if (vport->port_state != LPFC_FLOGI) {
phba->hba_flag |= FCF_RR_INPROG;
spin_unlock_irq(&phba->hbalock);
- lpfc_initial_flogi(vport);
+ lpfc_issue_init_vfi(vport);
goto out;
}
spin_unlock_irq(&phba->hbalock);
@@ -1353,7 +1355,7 @@ lpfc_register_fcf(struct lpfc_hba *phba)
if (phba->pport->port_state != LPFC_FLOGI) {
phba->hba_flag |= FCF_RR_INPROG;
spin_unlock_irq(&phba->hbalock);
- lpfc_initial_flogi(phba->pport);
+ lpfc_issue_init_vfi(phba->pport);
return;
}
spin_unlock_irq(&phba->hbalock);
@@ -2331,7 +2333,7 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
phba->fcf.current_rec.fcf_indx, fcf_index);
/* Wait 500 ms before retrying FLOGI to current FCF */
msleep(500);
- lpfc_initial_flogi(phba->pport);
+ lpfc_issue_init_vfi(phba->pport);
goto out;
}
@@ -2422,6 +2424,63 @@ out:
}
/**
+ * lpfc_init_vfi_cmpl - Completion handler for init_vfi mbox command.
+ * @phba: pointer to lpfc hba data structure.
+ * @mboxq: pointer to mailbox data structure.
+ *
+ * This function handles completion of init vfi mailbox command.
+ */
+void
+lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+{
+ struct lpfc_vport *vport = mboxq->vport;
+
+ if (mboxq->u.mb.mbxStatus && (mboxq->u.mb.mbxStatus != 0x4002)) {
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_MBOX,
+ "2891 Init VFI mailbox failed 0x%x\n",
+ mboxq->u.mb.mbxStatus);
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ return;
+ }
+ lpfc_initial_flogi(vport);
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ return;
+}
+
+/**
+ * lpfc_issue_init_vfi - Issue init_vfi mailbox command.
+ * @vport: pointer to lpfc_vport data structure.
+ *
+ * This function issue a init_vfi mailbox command to initialize the VFI and
+ * VPI for the physical port.
+ */
+void
+lpfc_issue_init_vfi(struct lpfc_vport *vport)
+{
+ LPFC_MBOXQ_t *mboxq;
+ int rc;
+ struct lpfc_hba *phba = vport->phba;
+
+ mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!mboxq) {
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_MBOX, "2892 Failed to allocate "
+ "init_vfi mailbox\n");
+ return;
+ }
+ lpfc_init_vfi(mboxq, vport);
+ mboxq->mbox_cmpl = lpfc_init_vfi_cmpl;
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED) {
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_MBOX, "2893 Failed to issue init_vfi mailbox\n");
+ mempool_free(mboxq, vport->phba->mbox_mem_pool);
+ }
+}
+
+/**
* lpfc_init_vpi_cmpl - Completion handler for init_vpi mbox command.
* @phba: pointer to lpfc hba data structure.
* @mboxq: pointer to mailbox data structure.
@@ -2528,7 +2587,7 @@ lpfc_start_fdiscs(struct lpfc_hba *phba)
FC_VPORT_FAILED);
continue;
}
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
lpfc_vport_set_state(vports[i],
FC_VPORT_LINKDOWN);
continue;
@@ -2564,7 +2623,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
"2018 REG_VFI mbxStatus error x%x "
"HBA state x%x\n",
mboxq->u.mb.mbxStatus, vport->port_state);
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
/* FLOGI failed, use loop map to make discovery list */
lpfc_disc_list_loopmap(vport);
/* Start discovery */
@@ -2582,8 +2641,18 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
spin_unlock_irq(shost->host_lock);
if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
- lpfc_start_fdiscs(phba);
- lpfc_do_scr_ns_plogi(phba, vport);
+ /* For private loop just start discovery and we are done. */
+ if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
+ (phba->alpa_map[0] == 0) &&
+ !(vport->fc_flag & FC_PUBLIC_LOOP)) {
+ /* Use loop map to make discovery list */
+ lpfc_disc_list_loopmap(vport);
+ /* Start discovery */
+ lpfc_disc_start(vport);
+ } else {
+ lpfc_start_fdiscs(phba);
+ lpfc_do_scr_ns_plogi(phba, vport);
+ }
}
fail_free_mem:
@@ -2644,7 +2713,7 @@ out:
}
static void
-lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
+lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
{
struct lpfc_vport *vport = phba->pport;
LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox = NULL;
@@ -2654,31 +2723,24 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
struct fcf_record *fcf_record;
spin_lock_irq(&phba->hbalock);
- switch (la->UlnkSpeed) {
- case LA_1GHZ_LINK:
- phba->fc_linkspeed = LA_1GHZ_LINK;
- break;
- case LA_2GHZ_LINK:
- phba->fc_linkspeed = LA_2GHZ_LINK;
- break;
- case LA_4GHZ_LINK:
- phba->fc_linkspeed = LA_4GHZ_LINK;
- break;
- case LA_8GHZ_LINK:
- phba->fc_linkspeed = LA_8GHZ_LINK;
- break;
- case LA_10GHZ_LINK:
- phba->fc_linkspeed = LA_10GHZ_LINK;
+ switch (bf_get(lpfc_mbx_read_top_link_spd, la)) {
+ case LPFC_LINK_SPEED_1GHZ:
+ case LPFC_LINK_SPEED_2GHZ:
+ case LPFC_LINK_SPEED_4GHZ:
+ case LPFC_LINK_SPEED_8GHZ:
+ case LPFC_LINK_SPEED_10GHZ:
+ case LPFC_LINK_SPEED_16GHZ:
+ phba->fc_linkspeed = bf_get(lpfc_mbx_read_top_link_spd, la);
break;
default:
- phba->fc_linkspeed = LA_UNKNW_LINK;
+ phba->fc_linkspeed = LPFC_LINK_SPEED_UNKNOWN;
break;
}
- phba->fc_topology = la->topology;
+ phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la);
phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
/* if npiv is enabled and this adapter supports npiv log
@@ -2689,11 +2751,11 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
"1309 Link Up Event npiv not supported in loop "
"topology\n");
/* Get Loop Map information */
- if (la->il)
+ if (bf_get(lpfc_mbx_read_top_il, la))
vport->fc_flag |= FC_LBIT;
- vport->fc_myDID = la->granted_AL_PA;
- i = la->un.lilpBde64.tus.f.bdeSize;
+ vport->fc_myDID = bf_get(lpfc_mbx_read_top_alpa_granted, la);
+ i = la->lilpBde64.tus.f.bdeSize;
if (i == 0) {
phba->alpa_map[0] = 0;
@@ -2764,7 +2826,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
goto out;
}
- if (!(phba->hba_flag & HBA_FCOE_SUPPORT)) {
+ if (!(phba->hba_flag & HBA_FCOE_MODE)) {
cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!cfglink_mbox)
goto out;
@@ -2874,17 +2936,17 @@ lpfc_mbx_issue_link_down(struct lpfc_hba *phba)
/*
- * This routine handles processing a READ_LA mailbox
+ * This routine handles processing a READ_TOPOLOGY mailbox
* command upon completion. It is setup in the LPFC_MBOXQ
* as the completion routine when the command is
* handed off to the SLI layer.
*/
void
-lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_vport *vport = pmb->vport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
- READ_LA_VAR *la;
+ struct lpfc_mbx_read_top *la;
MAILBOX_t *mb = &pmb->u.mb;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
@@ -2897,15 +2959,15 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
mb->mbxStatus, vport->port_state);
lpfc_mbx_issue_link_down(phba);
phba->link_state = LPFC_HBA_ERROR;
- goto lpfc_mbx_cmpl_read_la_free_mbuf;
+ goto lpfc_mbx_cmpl_read_topology_free_mbuf;
}
- la = (READ_LA_VAR *) &pmb->u.mb.un.varReadLA;
+ la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop;
memcpy(&phba->alpa_map[0], mp->virt, 128);
spin_lock_irq(shost->host_lock);
- if (la->pb)
+ if (bf_get(lpfc_mbx_read_top_pb, la))
vport->fc_flag |= FC_BYPASSED_MODE;
else
vport->fc_flag &= ~FC_BYPASSED_MODE;
@@ -2914,41 +2976,48 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
if ((phba->fc_eventTag < la->eventTag) ||
(phba->fc_eventTag == la->eventTag)) {
phba->fc_stat.LinkMultiEvent++;
- if (la->attType == AT_LINK_UP)
+ if (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)
if (phba->fc_eventTag != 0)
lpfc_linkdown(phba);
}
phba->fc_eventTag = la->eventTag;
spin_lock_irq(&phba->hbalock);
- if (la->mm)
+ if (bf_get(lpfc_mbx_read_top_mm, la))
phba->sli.sli_flag |= LPFC_MENLO_MAINT;
else
phba->sli.sli_flag &= ~LPFC_MENLO_MAINT;
spin_unlock_irq(&phba->hbalock);
phba->link_events++;
- if (la->attType == AT_LINK_UP && (!la->mm)) {
+ if ((bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP) &&
+ (!bf_get(lpfc_mbx_read_top_mm, la))) {
phba->fc_stat.LinkUp++;
if (phba->link_flag & LS_LOOPBACK_MODE) {
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
"1306 Link Up Event in loop back mode "
"x%x received Data: x%x x%x x%x x%x\n",
la->eventTag, phba->fc_eventTag,
- la->granted_AL_PA, la->UlnkSpeed,
+ bf_get(lpfc_mbx_read_top_alpa_granted,
+ la),
+ bf_get(lpfc_mbx_read_top_link_spd, la),
phba->alpa_map[0]);
} else {
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
"1303 Link Up Event x%x received "
"Data: x%x x%x x%x x%x x%x x%x %d\n",
la->eventTag, phba->fc_eventTag,
- la->granted_AL_PA, la->UlnkSpeed,
+ bf_get(lpfc_mbx_read_top_alpa_granted,
+ la),
+ bf_get(lpfc_mbx_read_top_link_spd, la),
phba->alpa_map[0],
- la->mm, la->fa,
+ bf_get(lpfc_mbx_read_top_mm, la),
+ bf_get(lpfc_mbx_read_top_fa, la),
phba->wait_4_mlo_maint_flg);
}
lpfc_mbx_process_link_up(phba, la);
- } else if (la->attType == AT_LINK_DOWN) {
+ } else if (bf_get(lpfc_mbx_read_top_att_type, la) ==
+ LPFC_ATT_LINK_DOWN) {
phba->fc_stat.LinkDown++;
if (phba->link_flag & LS_LOOPBACK_MODE) {
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -2964,11 +3033,13 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
"Data: x%x x%x x%x x%x x%x\n",
la->eventTag, phba->fc_eventTag,
phba->pport->port_state, vport->fc_flag,
- la->mm, la->fa);
+ bf_get(lpfc_mbx_read_top_mm, la),
+ bf_get(lpfc_mbx_read_top_fa, la));
}
lpfc_mbx_issue_link_down(phba);
}
- if (la->mm && la->attType == AT_LINK_UP) {
+ if ((bf_get(lpfc_mbx_read_top_mm, la)) &&
+ (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)) {
if (phba->link_state != LPFC_LINK_DOWN) {
phba->fc_stat.LinkDown++;
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -2996,14 +3067,15 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
}
- if (la->fa) {
- if (la->mm)
+ if (bf_get(lpfc_mbx_read_top_fa, la)) {
+ if (bf_get(lpfc_mbx_read_top_mm, la))
lpfc_issue_clear_la(phba, vport);
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
- "1311 fa %d\n", la->fa);
+ "1311 fa %d\n",
+ bf_get(lpfc_mbx_read_top_fa, la));
}
-lpfc_mbx_cmpl_read_la_free_mbuf:
+lpfc_mbx_cmpl_read_topology_free_mbuf:
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free(pmb, phba->mbox_mem_pool);
@@ -3030,8 +3102,8 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
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) {
+ 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
@@ -3043,10 +3115,6 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
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,
@@ -3092,6 +3160,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
spin_unlock_irq(shost->host_lock);
vport->unreg_vpi_cmpl = VPORT_OK;
mempool_free(pmb, phba->mbox_mem_pool);
+ lpfc_cleanup_vports_rrqs(vport);
/*
* This shost reference might have been taken at the beginning of
* lpfc_vport_delete()
@@ -3333,7 +3402,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
kfree(mp);
mempool_free(pmb, phba->mbox_mem_pool);
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
/* FLOGI failed, use loop map to make discovery list */
lpfc_disc_list_loopmap(vport);
@@ -3355,7 +3424,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
}
ndlp->nlp_rpi = mb->un.varWords[0];
- ndlp->nlp_flag |= NLP_RPI_VALID;
+ ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
@@ -3413,7 +3482,7 @@ out:
/* If no other thread is using the ndlp, free it */
lpfc_nlp_not_used(ndlp);
- if (phba->fc_topology == TOPOLOGY_LOOP) {
+ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
/*
* RegLogin failed, use loop map to make discovery
* list
@@ -3429,7 +3498,7 @@ out:
}
ndlp->nlp_rpi = mb->un.varWords[0];
- ndlp->nlp_flag |= NLP_RPI_VALID;
+ ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
@@ -3762,6 +3831,8 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
NLP_INT_NODE_ACT(ndlp);
atomic_set(&ndlp->cmd_pending, 0);
ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth;
+ if (vport->phba->sli_rev == LPFC_SLI_REV4)
+ ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba);
}
struct lpfc_nodelist *
@@ -3975,7 +4046,7 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
* by firmware with a no rpi error.
*/
psli = &phba->sli;
- if (ndlp->nlp_flag & NLP_RPI_VALID) {
+ if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
/* Now process each ring */
for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i];
@@ -4023,7 +4094,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
LPFC_MBOXQ_t *mbox;
int rc;
- if (ndlp->nlp_flag & NLP_RPI_VALID) {
+ if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox) {
lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox);
@@ -4035,8 +4106,9 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
}
lpfc_no_rpi(phba, ndlp);
- ndlp->nlp_rpi = 0;
- ndlp->nlp_flag &= ~NLP_RPI_VALID;
+ if (phba->sli_rev != LPFC_SLI_REV4)
+ ndlp->nlp_rpi = 0;
+ ndlp->nlp_flag &= ~NLP_RPI_REGISTERED;
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
return 1;
}
@@ -4059,11 +4131,16 @@ lpfc_unreg_hba_rpis(struct lpfc_hba *phba)
int i;
vports = lpfc_create_vport_work_array(phba);
+ if (!vports) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ "2884 Vport array allocation failed \n");
+ return;
+ }
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irq(shost->host_lock);
list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) {
- if (ndlp->nlp_flag & NLP_RPI_VALID) {
+ if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
/* The mempool_alloc might sleep */
spin_unlock_irq(shost->host_lock);
lpfc_unreg_rpi(vports[i], ndlp);
@@ -4192,9 +4269,6 @@ 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
@@ -4236,15 +4310,15 @@ 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)) {
+ !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) &&
+ !(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
/* For this case we need to cleanup the default rpi
* allocated by the firmware.
*/
if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))
!= NULL) {
rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID,
- (uint8_t *) &vport->fc_sparam, mbox, 0);
+ (uint8_t *) &vport->fc_sparam, mbox, ndlp->nlp_rpi);
if (rc) {
mempool_free(mbox, phba->mbox_mem_pool);
}
@@ -4436,7 +4510,7 @@ lpfc_disc_list_loopmap(struct lpfc_vport *vport)
if (!lpfc_is_link_up(phba))
return;
- if (phba->fc_topology != TOPOLOGY_LOOP)
+ if (phba->fc_topology != LPFC_TOPOLOGY_LOOP)
return;
/* Check for loop map present or not */
@@ -4788,7 +4862,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
}
}
if (vport->port_state != LPFC_FLOGI) {
- lpfc_initial_flogi(vport);
+ if (phba->sli_rev <= LPFC_SLI_REV3)
+ lpfc_initial_flogi(vport);
+ else
+ lpfc_issue_init_vfi(vport);
return;
}
break;
@@ -4979,7 +5056,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
pmb->context2 = NULL;
ndlp->nlp_rpi = mb->un.varWords[0];
- ndlp->nlp_flag |= NLP_RPI_VALID;
+ ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
@@ -5103,6 +5180,8 @@ lpfc_nlp_release(struct kref *kref)
spin_lock_irqsave(&phba->ndlp_lock, flags);
NLP_CLR_NODE_ACT(ndlp);
spin_unlock_irqrestore(&phba->ndlp_lock, flags);
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
/* free ndlp memory for final ndlp release */
if (NLP_CHK_FREE_REQ(ndlp)) {
@@ -5254,6 +5333,10 @@ lpfc_fcf_inuse(struct lpfc_hba *phba)
vports = lpfc_create_vport_work_array(phba);
+ /* If driver cannot allocate memory, indicate fcf is in use */
+ if (!vports)
+ return 1;
+
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
shost = lpfc_shost_from_vport(vports[i]);
spin_lock_irq(shost->host_lock);
@@ -5269,7 +5352,7 @@ lpfc_fcf_inuse(struct lpfc_hba *phba)
"logged in\n",
ndlp->nlp_rpi, ndlp->nlp_DID,
ndlp->nlp_flag);
- if (ndlp->nlp_flag & NLP_RPI_VALID)
+ if (ndlp->nlp_flag & NLP_RPI_REGISTERED)
ret = 1;
}
}
@@ -5550,7 +5633,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba)
* registered, do nothing.
*/
spin_lock_irq(&phba->hbalock);
- if (!(phba->hba_flag & HBA_FCOE_SUPPORT) ||
+ if (!(phba->hba_flag & HBA_FCOE_MODE) ||
!(phba->fcf.fcf_flag & FCF_REGISTERED) ||
!(phba->hba_flag & HBA_FIP_SUPPORT) ||
(phba->fcf.fcf_flag & FCF_DISCOVERY) ||
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 9b833345646..96ed3ba6ba9 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -880,6 +880,24 @@ struct RLS_RSP { /* Structure is in Big Endian format */
uint32_t crcCnt;
};
+struct RRQ { /* Structure is in Big Endian format */
+ uint32_t rrq;
+#define rrq_rsvd_SHIFT 24
+#define rrq_rsvd_MASK 0x000000ff
+#define rrq_rsvd_WORD rrq
+#define rrq_did_SHIFT 0
+#define rrq_did_MASK 0x00ffffff
+#define rrq_did_WORD rrq
+ uint32_t rrq_exchg;
+#define rrq_oxid_SHIFT 16
+#define rrq_oxid_MASK 0xffff
+#define rrq_oxid_WORD rrq_exchg
+#define rrq_rxid_SHIFT 0
+#define rrq_rxid_MASK 0xffff
+#define rrq_rxid_WORD rrq_exchg
+};
+
+
struct RTV_RSP { /* Structure is in Big Endian format */
uint32_t ratov;
uint32_t edtov;
@@ -1172,7 +1190,10 @@ typedef struct {
#define PCI_VENDOR_ID_EMULEX 0x10df
#define PCI_DEVICE_ID_FIREFLY 0x1ae5
#define PCI_DEVICE_ID_PROTEUS_VF 0xe100
+#define PCI_DEVICE_ID_BALIUS 0xe131
#define PCI_DEVICE_ID_PROTEUS_PF 0xe180
+#define PCI_DEVICE_ID_LANCER_FC 0xe200
+#define PCI_DEVICE_ID_LANCER_FCOE 0xe260
#define PCI_DEVICE_ID_SAT_SMB 0xf011
#define PCI_DEVICE_ID_SAT_MID 0xf015
#define PCI_DEVICE_ID_RFLY 0xf095
@@ -1189,6 +1210,7 @@ typedef struct {
#define PCI_DEVICE_ID_SAT 0xf100
#define PCI_DEVICE_ID_SAT_SCSP 0xf111
#define PCI_DEVICE_ID_SAT_DCSP 0xf112
+#define PCI_DEVICE_ID_FALCON 0xf180
#define PCI_DEVICE_ID_SUPERFLY 0xf700
#define PCI_DEVICE_ID_DRAGONFLY 0xf800
#define PCI_DEVICE_ID_CENTAUR 0xf900
@@ -1210,8 +1232,6 @@ typedef struct {
#define PCI_VENDOR_ID_SERVERENGINE 0x19a2
#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
@@ -1368,7 +1388,6 @@ typedef struct { /* FireFly BIU registers */
#define MBX_READ_LNK_STAT 0x12
#define MBX_REG_LOGIN 0x13
#define MBX_UNREG_LOGIN 0x14
-#define MBX_READ_LA 0x15
#define MBX_CLEAR_LA 0x16
#define MBX_DUMP_MEMORY 0x17
#define MBX_DUMP_CONTEXT 0x18
@@ -1402,7 +1421,7 @@ typedef struct { /* FireFly BIU registers */
#define MBX_READ_SPARM64 0x8D
#define MBX_READ_RPI64 0x8F
#define MBX_REG_LOGIN64 0x93
-#define MBX_READ_LA64 0x95
+#define MBX_READ_TOPOLOGY 0x95
#define MBX_REG_VPI 0x96
#define MBX_UNREG_VPI 0x97
@@ -1823,12 +1842,13 @@ typedef struct {
#define FLAGS_IMED_ABORT 0x04000 /* Bit 14 */
uint32_t link_speed;
-#define LINK_SPEED_AUTO 0 /* Auto selection */
-#define LINK_SPEED_1G 1 /* 1 Gigabaud */
-#define LINK_SPEED_2G 2 /* 2 Gigabaud */
-#define LINK_SPEED_4G 4 /* 4 Gigabaud */
-#define LINK_SPEED_8G 8 /* 8 Gigabaud */
-#define LINK_SPEED_10G 16 /* 10 Gigabaud */
+#define LINK_SPEED_AUTO 0x0 /* Auto selection */
+#define LINK_SPEED_1G 0x1 /* 1 Gigabaud */
+#define LINK_SPEED_2G 0x2 /* 2 Gigabaud */
+#define LINK_SPEED_4G 0x4 /* 4 Gigabaud */
+#define LINK_SPEED_8G 0x8 /* 8 Gigabaud */
+#define LINK_SPEED_10G 0x10 /* 10 Gigabaud */
+#define LINK_SPEED_16G 0x11 /* 16 Gigabaud */
} INIT_LINK_VAR;
@@ -1999,6 +2019,7 @@ typedef struct {
#define LMT_4Gb 0x040
#define LMT_8Gb 0x080
#define LMT_10Gb 0x100
+#define LMT_16Gb 0x200
uint32_t rsvd2;
uint32_t rsvd3;
uint32_t max_xri;
@@ -2394,100 +2415,93 @@ typedef struct {
#endif
} UNREG_D_ID_VAR;
-/* Structure for MB Command READ_LA (21) */
-/* Structure for MB Command READ_LA64 (0x95) */
-
-typedef struct {
+/* Structure for MB Command READ_TOPOLOGY (0x95) */
+struct lpfc_mbx_read_top {
uint32_t eventTag; /* Event tag */
-#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t rsvd1:19;
- uint32_t fa:1;
- uint32_t mm:1; /* Menlo Maintenance mode enabled */
- uint32_t rx:1;
- uint32_t pb:1;
- uint32_t il:1;
- uint32_t attType:8;
-#else /* __LITTLE_ENDIAN_BITFIELD */
- uint32_t attType:8;
- uint32_t il:1;
- uint32_t pb:1;
- uint32_t rx:1;
- uint32_t mm:1;
- uint32_t fa:1;
- uint32_t rsvd1:19;
-#endif
-
-#define AT_RESERVED 0x00 /* Reserved - attType */
-#define AT_LINK_UP 0x01 /* Link is up */
-#define AT_LINK_DOWN 0x02 /* Link is down */
-
-#ifdef __BIG_ENDIAN_BITFIELD
- uint8_t granted_AL_PA;
- uint8_t lipAlPs;
- uint8_t lipType;
- uint8_t topology;
-#else /* __LITTLE_ENDIAN_BITFIELD */
- uint8_t topology;
- uint8_t lipType;
- uint8_t lipAlPs;
- uint8_t granted_AL_PA;
-#endif
-
-#define TOPOLOGY_PT_PT 0x01 /* Topology is pt-pt / pt-fabric */
-#define TOPOLOGY_LOOP 0x02 /* Topology is FC-AL */
-#define TOPOLOGY_LNK_MENLO_MAINTENANCE 0x05 /* maint mode zephtr to menlo */
-
- union {
- struct ulp_bde lilpBde; /* This BDE points to a 128 byte buffer
- to */
- /* store the LILP AL_PA position map into */
- struct ulp_bde64 lilpBde64;
- } un;
-
-#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t Dlu:1;
- uint32_t Dtf:1;
- uint32_t Drsvd2:14;
- uint32_t DlnkSpeed:8;
- uint32_t DnlPort:4;
- uint32_t Dtx:2;
- uint32_t Drx:2;
-#else /* __LITTLE_ENDIAN_BITFIELD */
- uint32_t Drx:2;
- uint32_t Dtx:2;
- uint32_t DnlPort:4;
- uint32_t DlnkSpeed:8;
- uint32_t Drsvd2:14;
- uint32_t Dtf:1;
- uint32_t Dlu:1;
-#endif
-
-#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t Ulu:1;
- uint32_t Utf:1;
- uint32_t Ursvd2:14;
- uint32_t UlnkSpeed:8;
- uint32_t UnlPort:4;
- uint32_t Utx:2;
- uint32_t Urx:2;
-#else /* __LITTLE_ENDIAN_BITFIELD */
- uint32_t Urx:2;
- uint32_t Utx:2;
- uint32_t UnlPort:4;
- uint32_t UlnkSpeed:8;
- uint32_t Ursvd2:14;
- uint32_t Utf:1;
- uint32_t Ulu:1;
-#endif
-
-#define LA_UNKNW_LINK 0x0 /* lnkSpeed */
-#define LA_1GHZ_LINK 0x04 /* lnkSpeed */
-#define LA_2GHZ_LINK 0x08 /* lnkSpeed */
-#define LA_4GHZ_LINK 0x10 /* lnkSpeed */
-#define LA_8GHZ_LINK 0x20 /* lnkSpeed */
-#define LA_10GHZ_LINK 0x40 /* lnkSpeed */
-
-} READ_LA_VAR;
+ uint32_t word2;
+#define lpfc_mbx_read_top_fa_SHIFT 12
+#define lpfc_mbx_read_top_fa_MASK 0x00000001
+#define lpfc_mbx_read_top_fa_WORD word2
+#define lpfc_mbx_read_top_mm_SHIFT 11
+#define lpfc_mbx_read_top_mm_MASK 0x00000001
+#define lpfc_mbx_read_top_mm_WORD word2
+#define lpfc_mbx_read_top_pb_SHIFT 9
+#define lpfc_mbx_read_top_pb_MASK 0X00000001
+#define lpfc_mbx_read_top_pb_WORD word2
+#define lpfc_mbx_read_top_il_SHIFT 8
+#define lpfc_mbx_read_top_il_MASK 0x00000001
+#define lpfc_mbx_read_top_il_WORD word2
+#define lpfc_mbx_read_top_att_type_SHIFT 0
+#define lpfc_mbx_read_top_att_type_MASK 0x000000FF
+#define lpfc_mbx_read_top_att_type_WORD word2
+#define LPFC_ATT_RESERVED 0x00 /* Reserved - attType */
+#define LPFC_ATT_LINK_UP 0x01 /* Link is up */
+#define LPFC_ATT_LINK_DOWN 0x02 /* Link is down */
+ uint32_t word3;
+#define lpfc_mbx_read_top_alpa_granted_SHIFT 24
+#define lpfc_mbx_read_top_alpa_granted_MASK 0x000000FF
+#define lpfc_mbx_read_top_alpa_granted_WORD word3
+#define lpfc_mbx_read_top_lip_alps_SHIFT 16
+#define lpfc_mbx_read_top_lip_alps_MASK 0x000000FF
+#define lpfc_mbx_read_top_lip_alps_WORD word3
+#define lpfc_mbx_read_top_lip_type_SHIFT 8
+#define lpfc_mbx_read_top_lip_type_MASK 0x000000FF
+#define lpfc_mbx_read_top_lip_type_WORD word3
+#define lpfc_mbx_read_top_topology_SHIFT 0
+#define lpfc_mbx_read_top_topology_MASK 0x000000FF
+#define lpfc_mbx_read_top_topology_WORD word3
+#define LPFC_TOPOLOGY_PT_PT 0x01 /* Topology is pt-pt / pt-fabric */
+#define LPFC_TOPOLOGY_LOOP 0x02 /* Topology is FC-AL */
+#define LPFC_TOPOLOGY_MM 0x05 /* maint mode zephtr to menlo */
+ /* store the LILP AL_PA position map into */
+ struct ulp_bde64 lilpBde64;
+#define LPFC_ALPA_MAP_SIZE 128
+ uint32_t word7;
+#define lpfc_mbx_read_top_ld_lu_SHIFT 31
+#define lpfc_mbx_read_top_ld_lu_MASK 0x00000001
+#define lpfc_mbx_read_top_ld_lu_WORD word7
+#define lpfc_mbx_read_top_ld_tf_SHIFT 30
+#define lpfc_mbx_read_top_ld_tf_MASK 0x00000001
+#define lpfc_mbx_read_top_ld_tf_WORD word7
+#define lpfc_mbx_read_top_ld_link_spd_SHIFT 8
+#define lpfc_mbx_read_top_ld_link_spd_MASK 0x000000FF
+#define lpfc_mbx_read_top_ld_link_spd_WORD word7
+#define lpfc_mbx_read_top_ld_nl_port_SHIFT 4
+#define lpfc_mbx_read_top_ld_nl_port_MASK 0x0000000F
+#define lpfc_mbx_read_top_ld_nl_port_WORD word7
+#define lpfc_mbx_read_top_ld_tx_SHIFT 2
+#define lpfc_mbx_read_top_ld_tx_MASK 0x00000003
+#define lpfc_mbx_read_top_ld_tx_WORD word7
+#define lpfc_mbx_read_top_ld_rx_SHIFT 0
+#define lpfc_mbx_read_top_ld_rx_MASK 0x00000003
+#define lpfc_mbx_read_top_ld_rx_WORD word7
+ uint32_t word8;
+#define lpfc_mbx_read_top_lu_SHIFT 31
+#define lpfc_mbx_read_top_lu_MASK 0x00000001
+#define lpfc_mbx_read_top_lu_WORD word8
+#define lpfc_mbx_read_top_tf_SHIFT 30
+#define lpfc_mbx_read_top_tf_MASK 0x00000001
+#define lpfc_mbx_read_top_tf_WORD word8
+#define lpfc_mbx_read_top_link_spd_SHIFT 8
+#define lpfc_mbx_read_top_link_spd_MASK 0x000000FF
+#define lpfc_mbx_read_top_link_spd_WORD word8
+#define lpfc_mbx_read_top_nl_port_SHIFT 4
+#define lpfc_mbx_read_top_nl_port_MASK 0x0000000F
+#define lpfc_mbx_read_top_nl_port_WORD word8
+#define lpfc_mbx_read_top_tx_SHIFT 2
+#define lpfc_mbx_read_top_tx_MASK 0x00000003
+#define lpfc_mbx_read_top_tx_WORD word8
+#define lpfc_mbx_read_top_rx_SHIFT 0
+#define lpfc_mbx_read_top_rx_MASK 0x00000003
+#define lpfc_mbx_read_top_rx_WORD word8
+#define LPFC_LINK_SPEED_UNKNOWN 0x0
+#define LPFC_LINK_SPEED_1GHZ 0x04
+#define LPFC_LINK_SPEED_2GHZ 0x08
+#define LPFC_LINK_SPEED_4GHZ 0x10
+#define LPFC_LINK_SPEED_8GHZ 0x20
+#define LPFC_LINK_SPEED_10GHZ 0x40
+#define LPFC_LINK_SPEED_16GHZ 0x80
+};
/* Structure for MB Command CLEAR_LA (22) */
@@ -3016,7 +3030,6 @@ typedef union {
READ_LNK_VAR varRdLnk; /* cmd = 18 (READ_LNK_STAT) */
REG_LOGIN_VAR varRegLogin; /* cmd = 19 (REG_LOGIN(64)) */
UNREG_LOGIN_VAR varUnregLogin; /* cmd = 20 (UNREG_LOGIN) */
- READ_LA_VAR varReadLA; /* cmd = 21 (READ_LA(64)) */
CLEAR_LA_VAR varClearLA; /* cmd = 22 (CLEAR_LA) */
DUMP_VAR varDmp; /* Warm Start DUMP mbx cmd */
UNREG_D_ID_VAR varUnregDID; /* cmd = 0x23 (UNREG_D_ID) */
@@ -3026,6 +3039,7 @@ typedef union {
struct config_hbq_var varCfgHbq;/* cmd = 0x7c (CONFIG_HBQ) */
struct update_cfg_var varUpdateCfg; /* cmd = 0x1B (UPDATE_CFG)*/
CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT) */
+ struct lpfc_mbx_read_top varReadTop; /* cmd = 0x95 (READ_TOPOLOGY) */
REG_VPI_VAR varRegVpi; /* cmd = 0x96 (REG_VPI) */
UNREG_VPI_VAR varUnregVpi; /* cmd = 0x97 (UNREG_VPI) */
ASYNCEVT_ENABLE_VAR varCfgAsyncEvent; /*cmd = x33 (CONFIG_ASYNC) */
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 6e4bc34e1d0..94c1aa1136d 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -64,29 +64,39 @@ struct lpfc_sli_intf {
#define lpfc_sli_intf_valid_MASK 0x00000007
#define lpfc_sli_intf_valid_WORD word0
#define LPFC_SLI_INTF_VALID 6
-#define lpfc_sli_intf_featurelevel2_SHIFT 24
-#define lpfc_sli_intf_featurelevel2_MASK 0x0000001F
-#define lpfc_sli_intf_featurelevel2_WORD word0
-#define lpfc_sli_intf_featurelevel1_SHIFT 16
-#define lpfc_sli_intf_featurelevel1_MASK 0x000000FF
-#define lpfc_sli_intf_featurelevel1_WORD word0
-#define LPFC_SLI_INTF_FEATURELEVEL1_1 1
-#define LPFC_SLI_INTF_FEATURELEVEL1_2 2
+#define lpfc_sli_intf_sli_hint2_SHIFT 24
+#define lpfc_sli_intf_sli_hint2_MASK 0x0000001F
+#define lpfc_sli_intf_sli_hint2_WORD word0
+#define LPFC_SLI_INTF_SLI_HINT2_NONE 0
+#define lpfc_sli_intf_sli_hint1_SHIFT 16
+#define lpfc_sli_intf_sli_hint1_MASK 0x000000FF
+#define lpfc_sli_intf_sli_hint1_WORD word0
+#define LPFC_SLI_INTF_SLI_HINT1_NONE 0
+#define LPFC_SLI_INTF_SLI_HINT1_1 1
+#define LPFC_SLI_INTF_SLI_HINT1_2 2
+#define lpfc_sli_intf_if_type_SHIFT 12
+#define lpfc_sli_intf_if_type_MASK 0x0000000F
+#define lpfc_sli_intf_if_type_WORD word0
+#define LPFC_SLI_INTF_IF_TYPE_0 0
+#define LPFC_SLI_INTF_IF_TYPE_1 1
+#define LPFC_SLI_INTF_IF_TYPE_2 2
#define lpfc_sli_intf_sli_family_SHIFT 8
-#define lpfc_sli_intf_sli_family_MASK 0x000000FF
+#define lpfc_sli_intf_sli_family_MASK 0x0000000F
#define lpfc_sli_intf_sli_family_WORD word0
-#define LPFC_SLI_INTF_FAMILY_BE2 0
-#define LPFC_SLI_INTF_FAMILY_BE3 1
+#define LPFC_SLI_INTF_FAMILY_BE2 0x0
+#define LPFC_SLI_INTF_FAMILY_BE3 0x1
+#define LPFC_SLI_INTF_FAMILY_LNCR_A0 0xa
+#define LPFC_SLI_INTF_FAMILY_LNCR_B0 0xb
#define lpfc_sli_intf_slirev_SHIFT 4
#define lpfc_sli_intf_slirev_MASK 0x0000000F
#define lpfc_sli_intf_slirev_WORD word0
#define LPFC_SLI_INTF_REV_SLI3 3
#define LPFC_SLI_INTF_REV_SLI4 4
-#define lpfc_sli_intf_if_type_SHIFT 0
-#define lpfc_sli_intf_if_type_MASK 0x00000007
-#define lpfc_sli_intf_if_type_WORD word0
-#define LPFC_SLI_INTF_IF_TYPE_0 0
-#define LPFC_SLI_INTF_IF_TYPE_1 1
+#define lpfc_sli_intf_func_type_SHIFT 0
+#define lpfc_sli_intf_func_type_MASK 0x00000001
+#define lpfc_sli_intf_func_type_WORD word0
+#define LPFC_SLI_INTF_IF_TYPE_PHYS 0
+#define LPFC_SLI_INTF_IF_TYPE_VIRT 1
};
#define LPFC_SLI4_MBX_EMBED true
@@ -450,35 +460,40 @@ struct lpfc_register {
uint32_t word0;
};
+/* The following BAR0 Registers apply to SLI4 if_type 0 UCNAs. */
#define LPFC_UERR_STATUS_HI 0x00A4
#define LPFC_UERR_STATUS_LO 0x00A0
#define LPFC_UE_MASK_HI 0x00AC
#define LPFC_UE_MASK_LO 0x00A8
+
+/* The following BAR0 register sets are defined for if_type 0 and 2 UCNAs. */
#define LPFC_SLI_INTF 0x0058
-/* BAR0 Registers */
-#define LPFC_HST_STATE 0x00AC
-#define lpfc_hst_state_perr_SHIFT 31
-#define lpfc_hst_state_perr_MASK 0x1
-#define lpfc_hst_state_perr_WORD word0
-#define lpfc_hst_state_sfi_SHIFT 30
-#define lpfc_hst_state_sfi_MASK 0x1
-#define lpfc_hst_state_sfi_WORD word0
-#define lpfc_hst_state_nip_SHIFT 29
-#define lpfc_hst_state_nip_MASK 0x1
-#define lpfc_hst_state_nip_WORD word0
-#define lpfc_hst_state_ipc_SHIFT 28
-#define lpfc_hst_state_ipc_MASK 0x1
-#define lpfc_hst_state_ipc_WORD word0
-#define lpfc_hst_state_xrom_SHIFT 27
-#define lpfc_hst_state_xrom_MASK 0x1
-#define lpfc_hst_state_xrom_WORD word0
-#define lpfc_hst_state_dl_SHIFT 26
-#define lpfc_hst_state_dl_MASK 0x1
-#define lpfc_hst_state_dl_WORD word0
-#define lpfc_hst_state_port_status_SHIFT 0
-#define lpfc_hst_state_port_status_MASK 0xFFFF
-#define lpfc_hst_state_port_status_WORD word0
+#define LPFC_SLIPORT_IF2_SMPHR 0x0400
+#define lpfc_port_smphr_perr_SHIFT 31
+#define lpfc_port_smphr_perr_MASK 0x1
+#define lpfc_port_smphr_perr_WORD word0
+#define lpfc_port_smphr_sfi_SHIFT 30
+#define lpfc_port_smphr_sfi_MASK 0x1
+#define lpfc_port_smphr_sfi_WORD word0
+#define lpfc_port_smphr_nip_SHIFT 29
+#define lpfc_port_smphr_nip_MASK 0x1
+#define lpfc_port_smphr_nip_WORD word0
+#define lpfc_port_smphr_ipc_SHIFT 28
+#define lpfc_port_smphr_ipc_MASK 0x1
+#define lpfc_port_smphr_ipc_WORD word0
+#define lpfc_port_smphr_scr1_SHIFT 27
+#define lpfc_port_smphr_scr1_MASK 0x1
+#define lpfc_port_smphr_scr1_WORD word0
+#define lpfc_port_smphr_scr2_SHIFT 26
+#define lpfc_port_smphr_scr2_MASK 0x1
+#define lpfc_port_smphr_scr2_WORD word0
+#define lpfc_port_smphr_host_scratch_SHIFT 16
+#define lpfc_port_smphr_host_scratch_MASK 0xFF
+#define lpfc_port_smphr_host_scratch_WORD word0
+#define lpfc_port_smphr_port_status_SHIFT 0
+#define lpfc_port_smphr_port_status_MASK 0xFFFF
+#define lpfc_port_smphr_port_status_WORD word0
#define LPFC_POST_STAGE_POWER_ON_RESET 0x0000
#define LPFC_POST_STAGE_AWAITING_HOST_RDY 0x0001
@@ -511,10 +526,46 @@ struct lpfc_register {
#define LPFC_POST_STAGE_RC_DONE 0x0B07
#define LPFC_POST_STAGE_REBOOT_SYSTEM 0x0B08
#define LPFC_POST_STAGE_MAC_ADDRESS 0x0C00
-#define LPFC_POST_STAGE_ARMFW_READY 0xC000
-#define LPFC_POST_STAGE_ARMFW_UE 0xF000
+#define LPFC_POST_STAGE_PORT_READY 0xC000
+#define LPFC_POST_STAGE_PORT_UE 0xF000
+
+#define LPFC_SLIPORT_STATUS 0x0404
+#define lpfc_sliport_status_err_SHIFT 31
+#define lpfc_sliport_status_err_MASK 0x1
+#define lpfc_sliport_status_err_WORD word0
+#define lpfc_sliport_status_end_SHIFT 30
+#define lpfc_sliport_status_end_MASK 0x1
+#define lpfc_sliport_status_end_WORD word0
+#define lpfc_sliport_status_oti_SHIFT 29
+#define lpfc_sliport_status_oti_MASK 0x1
+#define lpfc_sliport_status_oti_WORD word0
+#define lpfc_sliport_status_rn_SHIFT 24
+#define lpfc_sliport_status_rn_MASK 0x1
+#define lpfc_sliport_status_rn_WORD word0
+#define lpfc_sliport_status_rdy_SHIFT 23
+#define lpfc_sliport_status_rdy_MASK 0x1
+#define lpfc_sliport_status_rdy_WORD word0
+#define MAX_IF_TYPE_2_RESETS 1000
+
+#define LPFC_SLIPORT_CNTRL 0x0408
+#define lpfc_sliport_ctrl_end_SHIFT 30
+#define lpfc_sliport_ctrl_end_MASK 0x1
+#define lpfc_sliport_ctrl_end_WORD word0
+#define LPFC_SLIPORT_LITTLE_ENDIAN 0
+#define LPFC_SLIPORT_BIG_ENDIAN 1
+#define lpfc_sliport_ctrl_ip_SHIFT 27
+#define lpfc_sliport_ctrl_ip_MASK 0x1
+#define lpfc_sliport_ctrl_ip_WORD word0
+#define LPFC_SLIPORT_INIT_PORT 1
+
+#define LPFC_SLIPORT_ERR_1 0x040C
+#define LPFC_SLIPORT_ERR_2 0x0410
+
+/* The following Registers apply to SLI4 if_type 0 UCNAs. They typically
+ * reside in BAR 2.
+ */
+#define LPFC_SLIPORT_IF0_SMPHR 0x00AC
-/* BAR1 Registers */
#define LPFC_IMR_MASK_ALL 0xFFFFFFFF
#define LPFC_ISCR_CLEAR_ALL 0xFFFFFFFF
@@ -569,14 +620,21 @@ struct lpfc_register {
#define LPFC_SLI4_INTR30 BIT30
#define LPFC_SLI4_INTR31 BIT31
-/* BAR2 Registers */
+/*
+ * The Doorbell registers defined here exist in different BAR
+ * register sets depending on the UCNA Port's reported if_type
+ * value. For UCNA ports running SLI4 and if_type 0, they reside in
+ * BAR4. For UCNA ports running SLI4 and if_type 2, they reside in
+ * BAR0. The offsets are the same so the driver must account for
+ * any base address difference.
+ */
#define LPFC_RQ_DOORBELL 0x00A0
#define lpfc_rq_doorbell_num_posted_SHIFT 16
#define lpfc_rq_doorbell_num_posted_MASK 0x3FFF
#define lpfc_rq_doorbell_num_posted_WORD word0
#define LPFC_RQ_POST_BATCH 8 /* RQEs to post at one time */
#define lpfc_rq_doorbell_id_SHIFT 0
-#define lpfc_rq_doorbell_id_MASK 0x03FF
+#define lpfc_rq_doorbell_id_MASK 0xFFFF
#define lpfc_rq_doorbell_id_WORD word0
#define LPFC_WQ_DOORBELL 0x0040
@@ -591,6 +649,11 @@ struct lpfc_register {
#define lpfc_wq_doorbell_id_WORD word0
#define LPFC_EQCQ_DOORBELL 0x0120
+#define lpfc_eqcq_doorbell_se_SHIFT 31
+#define lpfc_eqcq_doorbell_se_MASK 0x0001
+#define lpfc_eqcq_doorbell_se_WORD word0
+#define LPFC_EQCQ_SOLICIT_ENABLE_OFF 0
+#define LPFC_EQCQ_SOLICIT_ENABLE_ON 1
#define lpfc_eqcq_doorbell_arm_SHIFT 29
#define lpfc_eqcq_doorbell_arm_MASK 0x0001
#define lpfc_eqcq_doorbell_arm_WORD word0
@@ -628,7 +691,7 @@ struct lpfc_register {
#define lpfc_mq_doorbell_num_posted_MASK 0x3FFF
#define lpfc_mq_doorbell_num_posted_WORD word0
#define lpfc_mq_doorbell_id_SHIFT 0
-#define lpfc_mq_doorbell_id_MASK 0x03FF
+#define lpfc_mq_doorbell_id_MASK 0xFFFF
#define lpfc_mq_doorbell_id_WORD word0
struct lpfc_sli4_cfg_mhdr {
@@ -1048,12 +1111,18 @@ struct lpfc_mbx_mq_create_ext {
#define lpfc_mbx_mq_create_ext_async_evt_link_SHIFT LPFC_TRAILER_CODE_LINK
#define lpfc_mbx_mq_create_ext_async_evt_link_MASK 0x00000001
#define lpfc_mbx_mq_create_ext_async_evt_link_WORD async_evt_bmap
-#define lpfc_mbx_mq_create_ext_async_evt_fcfste_SHIFT LPFC_TRAILER_CODE_FCOE
-#define lpfc_mbx_mq_create_ext_async_evt_fcfste_MASK 0x00000001
-#define lpfc_mbx_mq_create_ext_async_evt_fcfste_WORD async_evt_bmap
+#define lpfc_mbx_mq_create_ext_async_evt_fip_SHIFT LPFC_TRAILER_CODE_FCOE
+#define lpfc_mbx_mq_create_ext_async_evt_fip_MASK 0x00000001
+#define lpfc_mbx_mq_create_ext_async_evt_fip_WORD async_evt_bmap
#define lpfc_mbx_mq_create_ext_async_evt_group5_SHIFT LPFC_TRAILER_CODE_GRP5
#define lpfc_mbx_mq_create_ext_async_evt_group5_MASK 0x00000001
#define lpfc_mbx_mq_create_ext_async_evt_group5_WORD async_evt_bmap
+#define lpfc_mbx_mq_create_ext_async_evt_fc_SHIFT LPFC_TRAILER_CODE_FC
+#define lpfc_mbx_mq_create_ext_async_evt_fc_MASK 0x00000001
+#define lpfc_mbx_mq_create_ext_async_evt_fc_WORD async_evt_bmap
+#define lpfc_mbx_mq_create_ext_async_evt_sli_SHIFT LPFC_TRAILER_CODE_SLI
+#define lpfc_mbx_mq_create_ext_async_evt_sli_MASK 0x00000001
+#define lpfc_mbx_mq_create_ext_async_evt_sli_WORD async_evt_bmap
struct mq_context context;
struct dma_address page[LPFC_MAX_MQ_PAGE];
} request;
@@ -1307,7 +1376,7 @@ struct lpfc_mbx_query_fw_cfg {
#define lpfc_function_mode_dal_WORD function_mode
#define lpfc_function_mode_lro_SHIFT 9
#define lpfc_function_mode_lro_MASK 0x00000001
-#define lpfc_function_mode_lro_WORD function_mode9
+#define lpfc_function_mode_lro_WORD function_mode
#define lpfc_function_mode_flex10_SHIFT 10
#define lpfc_function_mode_flex10_MASK 0x00000001
#define lpfc_function_mode_flex10_WORD function_mode
@@ -1358,10 +1427,16 @@ struct lpfc_mbx_init_vfi {
#define lpfc_init_vfi_vf_SHIFT 29
#define lpfc_init_vfi_vf_MASK 0x00000001
#define lpfc_init_vfi_vf_WORD word1
+#define lpfc_init_vfi_vp_SHIFT 28
+#define lpfc_init_vfi_vp_MASK 0x00000001
+#define lpfc_init_vfi_vp_WORD word1
#define lpfc_init_vfi_vfi_SHIFT 0
#define lpfc_init_vfi_vfi_MASK 0x0000FFFF
#define lpfc_init_vfi_vfi_WORD word1
uint32_t word2;
+#define lpfc_init_vfi_vpi_SHIFT 16
+#define lpfc_init_vfi_vpi_MASK 0x0000FFFF
+#define lpfc_init_vfi_vpi_WORD word2
#define lpfc_init_vfi_fcfi_SHIFT 0
#define lpfc_init_vfi_fcfi_MASK 0x0000FFFF
#define lpfc_init_vfi_fcfi_WORD word2
@@ -2069,6 +2144,8 @@ struct lpfc_mcqe {
#define LPFC_TRAILER_CODE_FCOE 0x2
#define LPFC_TRAILER_CODE_DCBX 0x3
#define LPFC_TRAILER_CODE_GRP5 0x5
+#define LPFC_TRAILER_CODE_FC 0x10
+#define LPFC_TRAILER_CODE_SLI 0x11
};
struct lpfc_acqe_link {
@@ -2094,11 +2171,12 @@ struct lpfc_acqe_link {
#define LPFC_ASYNC_LINK_STATUS_UP 0x1
#define LPFC_ASYNC_LINK_STATUS_LOGICAL_DOWN 0x2
#define LPFC_ASYNC_LINK_STATUS_LOGICAL_UP 0x3
-#define lpfc_acqe_link_physical_SHIFT 0
-#define lpfc_acqe_link_physical_MASK 0x000000FF
-#define lpfc_acqe_link_physical_WORD word0
-#define LPFC_ASYNC_LINK_PORT_A 0x0
-#define LPFC_ASYNC_LINK_PORT_B 0x1
+#define lpfc_acqe_link_type_SHIFT 6
+#define lpfc_acqe_link_type_MASK 0x00000003
+#define lpfc_acqe_link_type_WORD word0
+#define lpfc_acqe_link_number_SHIFT 0
+#define lpfc_acqe_link_number_MASK 0x0000003F
+#define lpfc_acqe_link_number_WORD word0
uint32_t word1;
#define lpfc_acqe_link_fault_SHIFT 0
#define lpfc_acqe_link_fault_MASK 0x000000FF
@@ -2106,29 +2184,31 @@ struct lpfc_acqe_link {
#define LPFC_ASYNC_LINK_FAULT_NONE 0x0
#define LPFC_ASYNC_LINK_FAULT_LOCAL 0x1
#define LPFC_ASYNC_LINK_FAULT_REMOTE 0x2
-#define lpfc_acqe_qos_link_speed_SHIFT 16
-#define lpfc_acqe_qos_link_speed_MASK 0x0000FFFF
-#define lpfc_acqe_qos_link_speed_WORD word1
+#define lpfc_acqe_logical_link_speed_SHIFT 16
+#define lpfc_acqe_logical_link_speed_MASK 0x0000FFFF
+#define lpfc_acqe_logical_link_speed_WORD word1
uint32_t event_tag;
uint32_t trailer;
+#define LPFC_LINK_EVENT_TYPE_PHYSICAL 0x0
+#define LPFC_LINK_EVENT_TYPE_VIRTUAL 0x1
};
-struct lpfc_acqe_fcoe {
+struct lpfc_acqe_fip {
uint32_t index;
uint32_t word1;
-#define lpfc_acqe_fcoe_fcf_count_SHIFT 0
-#define lpfc_acqe_fcoe_fcf_count_MASK 0x0000FFFF
-#define lpfc_acqe_fcoe_fcf_count_WORD word1
-#define lpfc_acqe_fcoe_event_type_SHIFT 16
-#define lpfc_acqe_fcoe_event_type_MASK 0x0000FFFF
-#define lpfc_acqe_fcoe_event_type_WORD word1
-#define LPFC_FCOE_EVENT_TYPE_NEW_FCF 0x1
-#define LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL 0x2
-#define LPFC_FCOE_EVENT_TYPE_FCF_DEAD 0x3
-#define LPFC_FCOE_EVENT_TYPE_CVL 0x4
-#define LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD 0x5
+#define lpfc_acqe_fip_fcf_count_SHIFT 0
+#define lpfc_acqe_fip_fcf_count_MASK 0x0000FFFF
+#define lpfc_acqe_fip_fcf_count_WORD word1
+#define lpfc_acqe_fip_event_type_SHIFT 16
+#define lpfc_acqe_fip_event_type_MASK 0x0000FFFF
+#define lpfc_acqe_fip_event_type_WORD word1
uint32_t event_tag;
uint32_t trailer;
+#define LPFC_FIP_EVENT_TYPE_NEW_FCF 0x1
+#define LPFC_FIP_EVENT_TYPE_FCF_TABLE_FULL 0x2
+#define LPFC_FIP_EVENT_TYPE_FCF_DEAD 0x3
+#define LPFC_FIP_EVENT_TYPE_CVL 0x4
+#define LPFC_FIP_EVENT_TYPE_FCF_PARAM_MOD 0x5
};
struct lpfc_acqe_dcbx {
@@ -2140,9 +2220,12 @@ struct lpfc_acqe_dcbx {
struct lpfc_acqe_grp5 {
uint32_t word0;
-#define lpfc_acqe_grp5_pport_SHIFT 0
-#define lpfc_acqe_grp5_pport_MASK 0x000000FF
-#define lpfc_acqe_grp5_pport_WORD word0
+#define lpfc_acqe_grp5_type_SHIFT 6
+#define lpfc_acqe_grp5_type_MASK 0x00000003
+#define lpfc_acqe_grp5_type_WORD word0
+#define lpfc_acqe_grp5_number_SHIFT 0
+#define lpfc_acqe_grp5_number_MASK 0x0000003F
+#define lpfc_acqe_grp5_number_WORD word0
uint32_t word1;
#define lpfc_acqe_grp5_llink_spd_SHIFT 16
#define lpfc_acqe_grp5_llink_spd_MASK 0x0000FFFF
@@ -2151,6 +2234,68 @@ struct lpfc_acqe_grp5 {
uint32_t trailer;
};
+struct lpfc_acqe_fc_la {
+ uint32_t word0;
+#define lpfc_acqe_fc_la_speed_SHIFT 24
+#define lpfc_acqe_fc_la_speed_MASK 0x000000FF
+#define lpfc_acqe_fc_la_speed_WORD word0
+#define LPFC_FC_LA_SPEED_UNKOWN 0x0
+#define LPFC_FC_LA_SPEED_1G 0x1
+#define LPFC_FC_LA_SPEED_2G 0x2
+#define LPFC_FC_LA_SPEED_4G 0x4
+#define LPFC_FC_LA_SPEED_8G 0x8
+#define LPFC_FC_LA_SPEED_10G 0xA
+#define LPFC_FC_LA_SPEED_16G 0x10
+#define lpfc_acqe_fc_la_topology_SHIFT 16
+#define lpfc_acqe_fc_la_topology_MASK 0x000000FF
+#define lpfc_acqe_fc_la_topology_WORD word0
+#define LPFC_FC_LA_TOP_UNKOWN 0x0
+#define LPFC_FC_LA_TOP_P2P 0x1
+#define LPFC_FC_LA_TOP_FCAL 0x2
+#define LPFC_FC_LA_TOP_INTERNAL_LOOP 0x3
+#define LPFC_FC_LA_TOP_SERDES_LOOP 0x4
+#define lpfc_acqe_fc_la_att_type_SHIFT 8
+#define lpfc_acqe_fc_la_att_type_MASK 0x000000FF
+#define lpfc_acqe_fc_la_att_type_WORD word0
+#define LPFC_FC_LA_TYPE_LINK_UP 0x1
+#define LPFC_FC_LA_TYPE_LINK_DOWN 0x2
+#define LPFC_FC_LA_TYPE_NO_HARD_ALPA 0x3
+#define lpfc_acqe_fc_la_port_type_SHIFT 6
+#define lpfc_acqe_fc_la_port_type_MASK 0x00000003
+#define lpfc_acqe_fc_la_port_type_WORD word0
+#define LPFC_LINK_TYPE_ETHERNET 0x0
+#define LPFC_LINK_TYPE_FC 0x1
+#define lpfc_acqe_fc_la_port_number_SHIFT 0
+#define lpfc_acqe_fc_la_port_number_MASK 0x0000003F
+#define lpfc_acqe_fc_la_port_number_WORD word0
+ uint32_t word1;
+#define lpfc_acqe_fc_la_llink_spd_SHIFT 16
+#define lpfc_acqe_fc_la_llink_spd_MASK 0x0000FFFF
+#define lpfc_acqe_fc_la_llink_spd_WORD word1
+#define lpfc_acqe_fc_la_fault_SHIFT 0
+#define lpfc_acqe_fc_la_fault_MASK 0x000000FF
+#define lpfc_acqe_fc_la_fault_WORD word1
+#define LPFC_FC_LA_FAULT_NONE 0x0
+#define LPFC_FC_LA_FAULT_LOCAL 0x1
+#define LPFC_FC_LA_FAULT_REMOTE 0x2
+ uint32_t event_tag;
+ uint32_t trailer;
+#define LPFC_FC_LA_EVENT_TYPE_FC_LINK 0x1
+#define LPFC_FC_LA_EVENT_TYPE_SHARED_LINK 0x2
+};
+
+struct lpfc_acqe_sli {
+ uint32_t event_data1;
+ uint32_t event_data2;
+ uint32_t reserved;
+ uint32_t trailer;
+#define LPFC_SLI_EVENT_TYPE_PORT_ERROR 0x1
+#define LPFC_SLI_EVENT_TYPE_OVER_TEMP 0x2
+#define LPFC_SLI_EVENT_TYPE_NORM_TEMP 0x3
+#define LPFC_SLI_EVENT_TYPE_NVLOG_POST 0x4
+#define LPFC_SLI_EVENT_TYPE_DIAG_DUMP 0x5
+};
+
/*
* Define the bootstrap mailbox (bmbx) region used to communicate
* mailbox command between the host and port. The mailbox consists
@@ -2210,7 +2355,7 @@ struct wqe_common {
#define wqe_rcvoxid_WORD word9
uint32_t word10;
#define wqe_ebde_cnt_SHIFT 0
-#define wqe_ebde_cnt_MASK 0x00000007
+#define wqe_ebde_cnt_MASK 0x0000000f
#define wqe_ebde_cnt_WORD word10
#define wqe_lenloc_SHIFT 7
#define wqe_lenloc_MASK 0x00000003
@@ -2402,7 +2547,6 @@ struct xmit_seq64_wqe {
uint32_t relative_offset;
struct wqe_rctl_dfctl wge_ctl;
struct wqe_common wqe_com; /* words 6-11 */
- /* Note: word10 different REVISIT */
uint32_t xmit_len;
uint32_t rsvd_12_15[3];
};
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b3065791f30..462242dcdd0 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -446,23 +446,25 @@ lpfc_config_port_post(struct lpfc_hba *phba)
/* Get the default values for Model Name and Description */
lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
- if ((phba->cfg_link_speed > LINK_SPEED_10G)
- || ((phba->cfg_link_speed == LINK_SPEED_1G)
+ if ((phba->cfg_link_speed > LPFC_USER_LINK_SPEED_16G)
+ || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_1G)
&& !(phba->lmt & LMT_1Gb))
- || ((phba->cfg_link_speed == LINK_SPEED_2G)
+ || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_2G)
&& !(phba->lmt & LMT_2Gb))
- || ((phba->cfg_link_speed == LINK_SPEED_4G)
+ || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_4G)
&& !(phba->lmt & LMT_4Gb))
- || ((phba->cfg_link_speed == LINK_SPEED_8G)
+ || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_8G)
&& !(phba->lmt & LMT_8Gb))
- || ((phba->cfg_link_speed == LINK_SPEED_10G)
- && !(phba->lmt & LMT_10Gb))) {
+ || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G)
+ && !(phba->lmt & LMT_10Gb))
+ || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G)
+ && !(phba->lmt & LMT_16Gb))) {
/* Reset link speed to auto */
lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
"1302 Invalid speed for this board: "
"Reset link speed to auto: x%x\n",
phba->cfg_link_speed);
- phba->cfg_link_speed = LINK_SPEED_AUTO;
+ phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
}
phba->link_state = LPFC_LINK_DOWN;
@@ -648,22 +650,23 @@ lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag)
mb = &pmb->u.mb;
pmb->vport = vport;
- lpfc_init_link(phba, pmb, phba->cfg_topology,
- phba->cfg_link_speed);
+ lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
lpfc_set_loopback_flag(phba);
rc = lpfc_sli_issue_mbox(phba, pmb, flag);
- if (rc != MBX_SUCCESS) {
+ if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0498 Adapter failed to init, mbxCmd x%x "
"INIT_LINK, mbxStatus x%x\n",
mb->mbxCommand, mb->mbxStatus);
- /* Clear all interrupt enable conditions */
- writel(0, phba->HCregaddr);
- readl(phba->HCregaddr); /* flush */
- /* Clear all pending interrupts */
- writel(0xffffffff, phba->HAregaddr);
- readl(phba->HAregaddr); /* flush */
+ if (phba->sli_rev <= LPFC_SLI_REV3) {
+ /* Clear all interrupt enable conditions */
+ writel(0, phba->HCregaddr);
+ readl(phba->HCregaddr); /* flush */
+ /* Clear all pending interrupts */
+ writel(0xffffffff, phba->HAregaddr);
+ readl(phba->HAregaddr); /* flush */
+ }
phba->link_state = LPFC_HBA_ERROR;
if (rc != MBX_BUSY || flag == MBX_POLL)
mempool_free(pmb, phba->mbox_mem_pool);
@@ -927,6 +930,35 @@ lpfc_hb_timeout(unsigned long ptr)
}
/**
+ * lpfc_rrq_timeout - The RRQ-timer timeout handler
+ * @ptr: unsigned long holds the pointer to lpfc hba data structure.
+ *
+ * This is the RRQ-timer timeout handler registered to the lpfc driver. When
+ * this timer fires, a RRQ timeout event shall be posted to the lpfc driver
+ * work-port-events bitmap and the worker thread is notified. This timeout
+ * event will be used by the worker thread to invoke the actual timeout
+ * handler routine, lpfc_rrq_handler. Any periodical operations will
+ * be performed in the timeout handler and the RRQ timeout event bit shall
+ * be cleared by the worker thread after it has taken the event bitmap out.
+ **/
+static void
+lpfc_rrq_timeout(unsigned long ptr)
+{
+ struct lpfc_hba *phba;
+ uint32_t tmo_posted;
+ unsigned long iflag;
+
+ phba = (struct lpfc_hba *)ptr;
+ spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
+ tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE;
+ if (!tmo_posted)
+ phba->hba_flag |= HBA_RRQ_ACTIVE;
+ spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+ if (!tmo_posted)
+ lpfc_worker_wake_up(phba);
+}
+
+/**
* lpfc_hb_mbox_cmpl - The lpfc heart-beat mailbox command callback function
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
@@ -1374,6 +1406,8 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
struct lpfc_vport *vport = phba->pport;
uint32_t event_data;
struct Scsi_Host *shost;
+ uint32_t if_type;
+ struct lpfc_register portstat_reg;
/* If the pci channel is offline, ignore possible errors, since
* we cannot communicate with the pci card anyway.
@@ -1390,17 +1424,49 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
/* For now, the actual action for SLI4 device handling is not
* specified yet, just treated it as adaptor hardware failure
*/
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0143 SLI4 Adapter Hardware Error Data: x%x x%x\n",
- phba->work_status[0], phba->work_status[1]);
-
event_data = FC_REG_DUMP_EVENT;
shost = lpfc_shost_from_vport(vport);
fc_host_post_vendor_event(shost, fc_get_event_number(),
sizeof(event_data), (char *) &event_data,
SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
- lpfc_sli4_offline_eratt(phba);
+ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+ switch (if_type) {
+ case LPFC_SLI_INTF_IF_TYPE_0:
+ lpfc_sli4_offline_eratt(phba);
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_2:
+ portstat_reg.word0 =
+ readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
+
+ if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) {
+ /* TODO: Register for Overtemp async events. */
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2889 Port Overtemperature event, "
+ "taking port\n");
+ spin_lock_irq(&phba->hbalock);
+ phba->over_temp_state = HBA_OVER_TEMP;
+ spin_unlock_irq(&phba->hbalock);
+ lpfc_sli4_offline_eratt(phba);
+ return;
+ }
+ if (bf_get(lpfc_sliport_status_rn, &portstat_reg)) {
+ /*
+ * TODO: Attempt port recovery via a port reset.
+ * When fully implemented, the driver should
+ * attempt to recover the port here and return.
+ * For now, log an error and take the port offline.
+ */
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2887 Port Error: Attempting "
+ "Port Recovery\n");
+ }
+ lpfc_sli4_offline_eratt(phba);
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_1:
+ default:
+ break;
+ }
}
/**
@@ -1459,8 +1525,8 @@ lpfc_handle_latt(struct lpfc_hba *phba)
lpfc_els_flush_all_cmd(phba);
psli->slistat.link_event++;
- lpfc_read_la(phba, pmb, mp);
- pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
+ lpfc_read_topology(phba, pmb, mp);
+ pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
pmb->vport = vport;
/* Block ELS IOCBs until we have processed this mbox command */
phba->sli.ring[LPFC_ELS_RING].flag |= LPFC_STOP_IOCB_EVENT;
@@ -1853,6 +1919,14 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
m = (typeof(m)){"LPVe12002", "PCIe Shared I/O",
"Fibre Channel Adapter"};
break;
+ case PCI_DEVICE_ID_LANCER_FC:
+ oneConnect = 1;
+ m = (typeof(m)){"Undefined", "PCIe", "Fibre Channel Adapter"};
+ break;
+ case PCI_DEVICE_ID_LANCER_FCOE:
+ oneConnect = 1;
+ m = (typeof(m)){"Undefined", "PCIe", "FCoE"};
+ break;
default:
m = (typeof(m)){"Unknown", "", ""};
break;
@@ -2943,63 +3017,6 @@ lpfc_sli4_fcf_redisc_wait_tmo(unsigned long ptr)
}
/**
- * lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support
- * @phba: pointer to lpfc hba data structure.
- *
- * This function uses the QUERY_FW_CFG mailbox command to determine if the
- * firmware loaded supports FCoE. A return of zero indicates that the mailbox
- * was successful and the firmware supports FCoE. Any other return indicates
- * a error. It is assumed that this function will be called before interrupts
- * are enabled.
- **/
-static int
-lpfc_sli4_fw_cfg_check(struct lpfc_hba *phba)
-{
- int rc = 0;
- LPFC_MBOXQ_t *mboxq;
- struct lpfc_mbx_query_fw_cfg *query_fw_cfg;
- uint32_t length;
- uint32_t shdr_status, shdr_add_status;
-
- mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2621 Failed to allocate mbox for "
- "query firmware config cmd\n");
- return -ENOMEM;
- }
- query_fw_cfg = &mboxq->u.mqe.un.query_fw_cfg;
- length = (sizeof(struct lpfc_mbx_query_fw_cfg) -
- sizeof(struct lpfc_sli4_cfg_mhdr));
- lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
- LPFC_MBOX_OPCODE_QUERY_FW_CFG,
- length, LPFC_SLI4_MBX_EMBED);
- rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- /* The IOCTL status is embedded in the mailbox subheader. */
- shdr_status = bf_get(lpfc_mbox_hdr_status,
- &query_fw_cfg->header.cfg_shdr.response);
- shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
- &query_fw_cfg->header.cfg_shdr.response);
- if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2622 Query Firmware Config failed "
- "mbx status x%x, status x%x add_status x%x\n",
- rc, shdr_status, shdr_add_status);
- return -EINVAL;
- }
- if (!bf_get(lpfc_function_mode_fcoe_i, query_fw_cfg)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2623 FCoE Function not supported by firmware. "
- "Function mode = %08x\n",
- query_fw_cfg->function_mode);
- return -EINVAL;
- }
- if (rc != MBX_TIMEOUT)
- mempool_free(mboxq, phba->mbox_mem_pool);
- return 0;
-}
-
-/**
* lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code
* @phba: pointer to lpfc hba data structure.
* @acqe_link: pointer to the async link completion queue entry.
@@ -3051,20 +3068,20 @@ lpfc_sli4_parse_latt_type(struct lpfc_hba *phba,
switch (bf_get(lpfc_acqe_link_status, acqe_link)) {
case LPFC_ASYNC_LINK_STATUS_DOWN:
case LPFC_ASYNC_LINK_STATUS_LOGICAL_DOWN:
- att_type = AT_LINK_DOWN;
+ att_type = LPFC_ATT_LINK_DOWN;
break;
case LPFC_ASYNC_LINK_STATUS_UP:
/* Ignore physical link up events - wait for logical link up */
- att_type = AT_RESERVED;
+ att_type = LPFC_ATT_RESERVED;
break;
case LPFC_ASYNC_LINK_STATUS_LOGICAL_UP:
- att_type = AT_LINK_UP;
+ att_type = LPFC_ATT_LINK_UP;
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0399 Invalid link attention type: x%x\n",
bf_get(lpfc_acqe_link_status, acqe_link));
- att_type = AT_RESERVED;
+ att_type = LPFC_ATT_RESERVED;
break;
}
return att_type;
@@ -3088,36 +3105,32 @@ lpfc_sli4_parse_latt_link_speed(struct lpfc_hba *phba,
switch (bf_get(lpfc_acqe_link_speed, acqe_link)) {
case LPFC_ASYNC_LINK_SPEED_ZERO:
- link_speed = LA_UNKNW_LINK;
- break;
case LPFC_ASYNC_LINK_SPEED_10MBPS:
- link_speed = LA_UNKNW_LINK;
- break;
case LPFC_ASYNC_LINK_SPEED_100MBPS:
- link_speed = LA_UNKNW_LINK;
+ link_speed = LPFC_LINK_SPEED_UNKNOWN;
break;
case LPFC_ASYNC_LINK_SPEED_1GBPS:
- link_speed = LA_1GHZ_LINK;
+ link_speed = LPFC_LINK_SPEED_1GHZ;
break;
case LPFC_ASYNC_LINK_SPEED_10GBPS:
- link_speed = LA_10GHZ_LINK;
+ link_speed = LPFC_LINK_SPEED_10GHZ;
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0483 Invalid link-attention link speed: x%x\n",
bf_get(lpfc_acqe_link_speed, acqe_link));
- link_speed = LA_UNKNW_LINK;
+ link_speed = LPFC_LINK_SPEED_UNKNOWN;
break;
}
return link_speed;
}
/**
- * lpfc_sli4_async_link_evt - Process the asynchronous link event
+ * lpfc_sli4_async_link_evt - Process the asynchronous FCoE link event
* @phba: pointer to lpfc hba data structure.
* @acqe_link: pointer to the async link completion queue entry.
*
- * This routine is to handle the SLI4 asynchronous link event.
+ * This routine is to handle the SLI4 asynchronous FCoE link event.
**/
static void
lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
@@ -3126,11 +3139,12 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
struct lpfc_dmabuf *mp;
LPFC_MBOXQ_t *pmb;
MAILBOX_t *mb;
- READ_LA_VAR *la;
+ struct lpfc_mbx_read_top *la;
uint8_t att_type;
+ int rc;
att_type = lpfc_sli4_parse_latt_type(phba, acqe_link);
- if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP)
+ if (att_type != LPFC_ATT_LINK_DOWN && att_type != LPFC_ATT_LINK_UP)
return;
phba->fcoe_eventtag = acqe_link->event_tag;
pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -3161,45 +3175,168 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
/* Update link event statistics */
phba->sli.slistat.link_event++;
- /* Create pseudo lpfc_handle_latt mailbox command from link ACQE */
- lpfc_read_la(phba, pmb, mp);
+ /* Create lpfc_handle_latt mailbox command from link ACQE */
+ lpfc_read_topology(phba, pmb, mp);
+ pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
pmb->vport = phba->pport;
+ /* Keep the link status for extra SLI4 state machine reference */
+ phba->sli4_hba.link_state.speed =
+ bf_get(lpfc_acqe_link_speed, acqe_link);
+ phba->sli4_hba.link_state.duplex =
+ bf_get(lpfc_acqe_link_duplex, acqe_link);
+ phba->sli4_hba.link_state.status =
+ bf_get(lpfc_acqe_link_status, acqe_link);
+ phba->sli4_hba.link_state.type =
+ bf_get(lpfc_acqe_link_type, acqe_link);
+ phba->sli4_hba.link_state.number =
+ bf_get(lpfc_acqe_link_number, acqe_link);
+ phba->sli4_hba.link_state.fault =
+ bf_get(lpfc_acqe_link_fault, acqe_link);
+ phba->sli4_hba.link_state.logical_speed =
+ bf_get(lpfc_acqe_logical_link_speed, acqe_link);
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "2900 Async FCoE Link event - Speed:%dGBit duplex:x%x "
+ "LA Type:x%x Port Type:%d Port Number:%d Logical "
+ "speed:%dMbps Fault:%d\n",
+ phba->sli4_hba.link_state.speed,
+ phba->sli4_hba.link_state.topology,
+ phba->sli4_hba.link_state.status,
+ phba->sli4_hba.link_state.type,
+ phba->sli4_hba.link_state.number,
+ phba->sli4_hba.link_state.logical_speed * 10,
+ phba->sli4_hba.link_state.fault);
+ /*
+ * For FC Mode: issue the READ_TOPOLOGY mailbox command to fetch
+ * topology info. Note: Optional for non FC-AL ports.
+ */
+ if (!(phba->hba_flag & HBA_FCOE_MODE)) {
+ rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED)
+ goto out_free_dmabuf;
+ return;
+ }
+ /*
+ * For FCoE Mode: fill in all the topology information we need and call
+ * the READ_TOPOLOGY completion routine to continue without actually
+ * sending the READ_TOPOLOGY mailbox command to the port.
+ */
/* Parse and translate status field */
mb = &pmb->u.mb;
mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba, acqe_link);
/* Parse and translate link attention fields */
- la = (READ_LA_VAR *) &pmb->u.mb.un.varReadLA;
+ la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop;
la->eventTag = acqe_link->event_tag;
- la->attType = att_type;
- la->UlnkSpeed = lpfc_sli4_parse_latt_link_speed(phba, acqe_link);
+ bf_set(lpfc_mbx_read_top_att_type, la, att_type);
+ bf_set(lpfc_mbx_read_top_link_spd, la,
+ lpfc_sli4_parse_latt_link_speed(phba, acqe_link));
/* Fake the the following irrelvant fields */
- la->topology = TOPOLOGY_PT_PT;
- la->granted_AL_PA = 0;
- la->il = 0;
- la->pb = 0;
- la->fa = 0;
- la->mm = 0;
+ bf_set(lpfc_mbx_read_top_topology, la, LPFC_TOPOLOGY_PT_PT);
+ bf_set(lpfc_mbx_read_top_alpa_granted, la, 0);
+ bf_set(lpfc_mbx_read_top_il, la, 0);
+ bf_set(lpfc_mbx_read_top_pb, la, 0);
+ bf_set(lpfc_mbx_read_top_fa, la, 0);
+ bf_set(lpfc_mbx_read_top_mm, la, 0);
+
+ /* Invoke the lpfc_handle_latt mailbox command callback function */
+ lpfc_mbx_cmpl_read_topology(phba, pmb);
+
+ return;
+out_free_dmabuf:
+ kfree(mp);
+out_free_pmb:
+ mempool_free(pmb, phba->mbox_mem_pool);
+}
+
+/**
+ * lpfc_sli4_async_fc_evt - Process the asynchronous FC link event
+ * @phba: pointer to lpfc hba data structure.
+ * @acqe_fc: pointer to the async fc completion queue entry.
+ *
+ * This routine is to handle the SLI4 asynchronous FC event. It will simply log
+ * that the event was received and then issue a read_topology mailbox command so
+ * that the rest of the driver will treat it the same as SLI3.
+ **/
+static void
+lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
+{
+ struct lpfc_dmabuf *mp;
+ LPFC_MBOXQ_t *pmb;
+ int rc;
+
+ if (bf_get(lpfc_trailer_type, acqe_fc) !=
+ LPFC_FC_LA_EVENT_TYPE_FC_LINK) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2895 Non FC link Event detected.(%d)\n",
+ bf_get(lpfc_trailer_type, acqe_fc));
+ return;
+ }
/* Keep the link status for extra SLI4 state machine reference */
phba->sli4_hba.link_state.speed =
- bf_get(lpfc_acqe_link_speed, acqe_link);
- phba->sli4_hba.link_state.duplex =
- bf_get(lpfc_acqe_link_duplex, acqe_link);
+ bf_get(lpfc_acqe_fc_la_speed, acqe_fc);
+ phba->sli4_hba.link_state.duplex = LPFC_ASYNC_LINK_DUPLEX_FULL;
+ phba->sli4_hba.link_state.topology =
+ bf_get(lpfc_acqe_fc_la_topology, acqe_fc);
phba->sli4_hba.link_state.status =
- bf_get(lpfc_acqe_link_status, acqe_link);
- phba->sli4_hba.link_state.physical =
- bf_get(lpfc_acqe_link_physical, acqe_link);
+ bf_get(lpfc_acqe_fc_la_att_type, acqe_fc);
+ phba->sli4_hba.link_state.type =
+ bf_get(lpfc_acqe_fc_la_port_type, acqe_fc);
+ phba->sli4_hba.link_state.number =
+ bf_get(lpfc_acqe_fc_la_port_number, acqe_fc);
phba->sli4_hba.link_state.fault =
- bf_get(lpfc_acqe_link_fault, acqe_link);
+ bf_get(lpfc_acqe_link_fault, acqe_fc);
phba->sli4_hba.link_state.logical_speed =
- bf_get(lpfc_acqe_qos_link_speed, acqe_link);
+ bf_get(lpfc_acqe_fc_la_llink_spd, acqe_fc);
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "2896 Async FC event - Speed:%dGBaud Topology:x%x "
+ "LA Type:x%x Port Type:%d Port Number:%d Logical speed:"
+ "%dMbps Fault:%d\n",
+ phba->sli4_hba.link_state.speed,
+ phba->sli4_hba.link_state.topology,
+ phba->sli4_hba.link_state.status,
+ phba->sli4_hba.link_state.type,
+ phba->sli4_hba.link_state.number,
+ phba->sli4_hba.link_state.logical_speed * 10,
+ phba->sli4_hba.link_state.fault);
+ pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+ if (!pmb) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2897 The mboxq allocation failed\n");
+ return;
+ }
+ mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+ if (!mp) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2898 The lpfc_dmabuf allocation failed\n");
+ goto out_free_pmb;
+ }
+ mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
+ if (!mp->virt) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2899 The mbuf allocation failed\n");
+ goto out_free_dmabuf;
+ }
- /* Invoke the lpfc_handle_latt mailbox command callback function */
- lpfc_mbx_cmpl_read_la(phba, pmb);
+ /* Cleanup any outstanding ELS commands */
+ lpfc_els_flush_all_cmd(phba);
+
+ /* Block ELS IOCBs until we have done process link event */
+ phba->sli.ring[LPFC_ELS_RING].flag |= LPFC_STOP_IOCB_EVENT;
+
+ /* Update link event statistics */
+ phba->sli.slistat.link_event++;
+
+ /* Create lpfc_handle_latt mailbox command from link ACQE */
+ lpfc_read_topology(phba, pmb, mp);
+ pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
+ pmb->vport = phba->pport;
+ rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED)
+ goto out_free_dmabuf;
return;
out_free_dmabuf:
@@ -3209,6 +3346,24 @@ out_free_pmb:
}
/**
+ * lpfc_sli4_async_sli_evt - Process the asynchronous SLI link event
+ * @phba: pointer to lpfc hba data structure.
+ * @acqe_fc: pointer to the async SLI completion queue entry.
+ *
+ * This routine is to handle the SLI4 asynchronous SLI events.
+ **/
+static void
+lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
+{
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "2901 Async SLI event - Event Data1:x%08x Event Data2:"
+ "x%08x SLI Event Type:%d",
+ acqe_sli->event_data1, acqe_sli->event_data2,
+ bf_get(lpfc_trailer_type, acqe_sli));
+ return;
+}
+
+/**
* lpfc_sli4_perform_vport_cvl - Perform clear virtual link on a vport
* @vport: pointer to vport data structure.
*
@@ -3247,10 +3402,12 @@ 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) &&
+ (phba->pport->port_state != LPFC_VPORT_FAILED))
return NULL;
/* If virtual link is not yet instantiated ignore CVL */
- if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC))
+ if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)
+ && (vport->port_state != LPFC_VPORT_FAILED))
return NULL;
shost = lpfc_shost_from_vport(vport);
if (!shost)
@@ -3285,17 +3442,17 @@ lpfc_sli4_perform_all_vport_cvl(struct lpfc_hba *phba)
}
/**
- * lpfc_sli4_async_fcoe_evt - Process the asynchronous fcoe event
+ * lpfc_sli4_async_fip_evt - Process the asynchronous FCoE FIP event
* @phba: pointer to lpfc hba data structure.
* @acqe_link: pointer to the async fcoe completion queue entry.
*
* This routine is to handle the SLI4 asynchronous fcoe event.
**/
static void
-lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
- struct lpfc_acqe_fcoe *acqe_fcoe)
+lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
+ struct lpfc_acqe_fip *acqe_fip)
{
- uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe);
+ uint8_t event_type = bf_get(lpfc_trailer_type, acqe_fip);
int rc;
struct lpfc_vport *vport;
struct lpfc_nodelist *ndlp;
@@ -3304,25 +3461,25 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
struct lpfc_vport **vports;
int i;
- phba->fc_eventTag = acqe_fcoe->event_tag;
- phba->fcoe_eventtag = acqe_fcoe->event_tag;
+ phba->fc_eventTag = acqe_fip->event_tag;
+ phba->fcoe_eventtag = acqe_fip->event_tag;
switch (event_type) {
- case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
- case LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD:
- if (event_type == LPFC_FCOE_EVENT_TYPE_NEW_FCF)
+ case LPFC_FIP_EVENT_TYPE_NEW_FCF:
+ case LPFC_FIP_EVENT_TYPE_FCF_PARAM_MOD:
+ if (event_type == LPFC_FIP_EVENT_TYPE_NEW_FCF)
lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
LOG_DISCOVERY,
"2546 New FCF event, evt_tag:x%x, "
"index:x%x\n",
- acqe_fcoe->event_tag,
- acqe_fcoe->index);
+ acqe_fip->event_tag,
+ acqe_fip->index);
else
lpfc_printf_log(phba, KERN_WARNING, LOG_FIP |
LOG_DISCOVERY,
"2788 FCF param modified event, "
"evt_tag:x%x, index:x%x\n",
- acqe_fcoe->event_tag,
- acqe_fcoe->index);
+ acqe_fip->event_tag,
+ acqe_fip->index);
if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
/*
* During period of FCF discovery, read the FCF
@@ -3333,8 +3490,8 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
LOG_DISCOVERY,
"2779 Read FCF (x%x) for updating "
"roundrobin FCF failover bmask\n",
- acqe_fcoe->index);
- rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index);
+ acqe_fip->index);
+ rc = lpfc_sli4_read_fcf_rec(phba, acqe_fip->index);
}
/* If the FCF discovery is in progress, do nothing. */
@@ -3360,7 +3517,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
"2770 Start FCF table scan per async FCF "
"event, evt_tag:x%x, index:x%x\n",
- acqe_fcoe->event_tag, acqe_fcoe->index);
+ acqe_fip->event_tag, acqe_fip->index);
rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba,
LPFC_FCOE_FCF_GET_FIRST);
if (rc)
@@ -3369,17 +3526,17 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
"command failed (x%x)\n", rc);
break;
- case LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL:
+ case LPFC_FIP_EVENT_TYPE_FCF_TABLE_FULL:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"2548 FCF Table full count 0x%x tag 0x%x\n",
- bf_get(lpfc_acqe_fcoe_fcf_count, acqe_fcoe),
- acqe_fcoe->event_tag);
+ bf_get(lpfc_acqe_fip_fcf_count, acqe_fip),
+ acqe_fip->event_tag);
break;
- case LPFC_FCOE_EVENT_TYPE_FCF_DEAD:
+ case LPFC_FIP_EVENT_TYPE_FCF_DEAD:
lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
"2549 FCF (x%x) disconnected from network, "
- "tag:x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
+ "tag:x%x\n", acqe_fip->index, acqe_fip->event_tag);
/*
* If we are in the middle of FCF failover process, clear
* the corresponding FCF bit in the roundrobin bitmap.
@@ -3388,13 +3545,13 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
spin_unlock_irq(&phba->hbalock);
/* Update FLOGI FCF failover eligible FCF bmask */
- lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index);
+ lpfc_sli4_fcf_rr_index_clear(phba, acqe_fip->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)
+ if (phba->fcf.current_rec.fcf_indx != acqe_fip->index)
break;
/*
@@ -3411,7 +3568,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
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 "
- "\n", acqe_fcoe->event_tag, acqe_fcoe->index);
+ "\n", acqe_fip->event_tag, acqe_fip->index);
rc = lpfc_sli4_redisc_fcf_table(phba);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
@@ -3438,12 +3595,12 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
lpfc_sli4_perform_all_vport_cvl(phba);
}
break;
- case LPFC_FCOE_EVENT_TYPE_CVL:
+ case LPFC_FIP_EVENT_TYPE_CVL:
lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
"2718 Clear Virtual Link Received for VPI 0x%x"
- " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
+ " tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag);
vport = lpfc_find_vport_by_vpid(phba,
- acqe_fcoe->index - phba->vpi_base);
+ acqe_fip->index - phba->vpi_base);
ndlp = lpfc_sli4_perform_vport_cvl(vport);
if (!ndlp)
break;
@@ -3494,7 +3651,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
lpfc_printf_log(phba, KERN_INFO, LOG_FIP |
LOG_DISCOVERY,
"2773 Start FCF failover per CVL, "
- "evt_tag:x%x\n", acqe_fcoe->event_tag);
+ "evt_tag:x%x\n", acqe_fip->event_tag);
rc = lpfc_sli4_redisc_fcf_table(phba);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
@@ -3522,7 +3679,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
default:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0288 Unknown FCoE event type 0x%x event tag "
- "0x%x\n", event_type, acqe_fcoe->event_tag);
+ "0x%x\n", event_type, acqe_fip->event_tag);
break;
}
}
@@ -3599,8 +3756,7 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba)
&cq_event->cqe.acqe_link);
break;
case LPFC_TRAILER_CODE_FCOE:
- lpfc_sli4_async_fcoe_evt(phba,
- &cq_event->cqe.acqe_fcoe);
+ lpfc_sli4_async_fip_evt(phba, &cq_event->cqe.acqe_fip);
break;
case LPFC_TRAILER_CODE_DCBX:
lpfc_sli4_async_dcbx_evt(phba,
@@ -3610,6 +3766,12 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba)
lpfc_sli4_async_grp5_evt(phba,
&cq_event->cqe.acqe_grp5);
break;
+ case LPFC_TRAILER_CODE_FC:
+ lpfc_sli4_async_fc_evt(phba, &cq_event->cqe.acqe_fc);
+ break;
+ case LPFC_TRAILER_CODE_SLI:
+ lpfc_sli4_async_sli_evt(phba, &cq_event->cqe.acqe_sli);
+ break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"1804 Invalid asynchrous event code: "
@@ -3948,7 +4110,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
int rc, i, hbq_count, buf_size, dma_buf_size, max_buf_size;
uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0};
struct lpfc_mqe *mqe;
- int longs;
+ int longs, sli_family;
/* Before proceed, wait for POST done and device ready */
rc = lpfc_sli4_post_status_check(phba);
@@ -3963,6 +4125,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
init_timer(&phba->hb_tmofunc);
phba->hb_tmofunc.function = lpfc_hb_timeout;
phba->hb_tmofunc.data = (unsigned long)phba;
+ init_timer(&phba->rrq_tmr);
+ phba->rrq_tmr.function = lpfc_rrq_timeout;
+ phba->rrq_tmr.data = (unsigned long)phba;
psli = &phba->sli;
/* MBOX heartbeat timer */
@@ -4010,12 +4175,22 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
*/
buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) +
((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge)));
- /* Feature Level 1 hardware is limited to 2 pages */
- if ((bf_get(lpfc_sli_intf_featurelevel1, &phba->sli4_hba.sli_intf) ==
- LPFC_SLI_INTF_FEATURELEVEL1_1))
- max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE;
- else
- max_buf_size = LPFC_SLI4_MAX_BUF_SIZE;
+
+ sli_family = bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf);
+ max_buf_size = LPFC_SLI4_MAX_BUF_SIZE;
+ switch (sli_family) {
+ case LPFC_SLI_INTF_FAMILY_BE2:
+ case LPFC_SLI_INTF_FAMILY_BE3:
+ /* There is a single hint for BE - 2 pages per BPL. */
+ if (bf_get(lpfc_sli_intf_sli_hint1, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_SLI_HINT1_1)
+ max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE;
+ break;
+ case LPFC_SLI_INTF_FAMILY_LNCR_A0:
+ case LPFC_SLI_INTF_FAMILY_LNCR_B0:
+ default:
+ break;
+ }
for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE;
dma_buf_size < max_buf_size && buf_size > dma_buf_size;
dma_buf_size = dma_buf_size << 1)
@@ -4070,6 +4245,14 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
if (rc)
return -ENOMEM;
+ /* IF Type 2 ports get initialized now. */
+ if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_IF_TYPE_2) {
+ rc = lpfc_pci_function_reset(phba);
+ if (unlikely(rc))
+ return -ENODEV;
+ }
+
/* Create the bootstrap mailbox command */
rc = lpfc_create_bootstrap_mbox(phba);
if (unlikely(rc))
@@ -4080,19 +4263,18 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
if (unlikely(rc))
goto out_free_bsmbx;
- rc = lpfc_sli4_fw_cfg_check(phba);
- if (unlikely(rc))
- goto out_free_bsmbx;
-
/* Set up the hba's configuration parameters. */
rc = lpfc_sli4_read_config(phba);
if (unlikely(rc))
goto out_free_bsmbx;
- /* Perform a function reset */
- rc = lpfc_pci_function_reset(phba);
- if (unlikely(rc))
- goto out_free_bsmbx;
+ /* IF Type 0 ports get initialized now. */
+ if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_IF_TYPE_0) {
+ rc = lpfc_pci_function_reset(phba);
+ if (unlikely(rc))
+ goto out_free_bsmbx;
+ }
mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
@@ -5190,97 +5372,183 @@ lpfc_sli_pci_mem_unset(struct lpfc_hba *phba)
int
lpfc_sli4_post_status_check(struct lpfc_hba *phba)
{
- struct lpfc_register sta_reg, uerrlo_reg, uerrhi_reg;
- int i, port_error = -ENODEV;
+ struct lpfc_register portsmphr_reg, uerrlo_reg, uerrhi_reg;
+ struct lpfc_register reg_data;
+ int i, port_error = 0;
+ uint32_t if_type;
- if (!phba->sli4_hba.STAregaddr)
+ if (!phba->sli4_hba.PSMPHRregaddr)
return -ENODEV;
/* Wait up to 30 seconds for the SLI Port POST done and ready */
for (i = 0; i < 3000; i++) {
- sta_reg.word0 = readl(phba->sli4_hba.STAregaddr);
- /* Encounter fatal POST error, break out */
- if (bf_get(lpfc_hst_state_perr, &sta_reg)) {
+ portsmphr_reg.word0 = readl(phba->sli4_hba.PSMPHRregaddr);
+ if (bf_get(lpfc_port_smphr_perr, &portsmphr_reg)) {
+ /* Port has a fatal POST error, break out */
port_error = -ENODEV;
break;
}
- if (LPFC_POST_STAGE_ARMFW_READY ==
- bf_get(lpfc_hst_state_port_status, &sta_reg)) {
- port_error = 0;
+ if (LPFC_POST_STAGE_PORT_READY ==
+ bf_get(lpfc_port_smphr_port_status, &portsmphr_reg))
break;
- }
msleep(10);
}
- if (port_error)
+ /*
+ * If there was a port error during POST, then don't proceed with
+ * other register reads as the data may not be valid. Just exit.
+ */
+ if (port_error) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1408 Failure HBA POST Status: sta_reg=0x%x, "
- "perr=x%x, sfi=x%x, nip=x%x, ipc=x%x, xrom=x%x, "
- "dl=x%x, pstatus=x%x\n", sta_reg.word0,
- bf_get(lpfc_hst_state_perr, &sta_reg),
- bf_get(lpfc_hst_state_sfi, &sta_reg),
- bf_get(lpfc_hst_state_nip, &sta_reg),
- bf_get(lpfc_hst_state_ipc, &sta_reg),
- bf_get(lpfc_hst_state_xrom, &sta_reg),
- bf_get(lpfc_hst_state_dl, &sta_reg),
- bf_get(lpfc_hst_state_port_status, &sta_reg));
-
- /* Log device information */
- phba->sli4_hba.sli_intf.word0 = readl(phba->sli4_hba.SLIINTFregaddr);
- if (bf_get(lpfc_sli_intf_valid,
- &phba->sli4_hba.sli_intf) == LPFC_SLI_INTF_VALID) {
+ "1408 Port Failed POST - portsmphr=0x%x, "
+ "perr=x%x, sfi=x%x, nip=x%x, ipc=x%x, scr1=x%x, "
+ "scr2=x%x, hscratch=x%x, pstatus=x%x\n",
+ portsmphr_reg.word0,
+ bf_get(lpfc_port_smphr_perr, &portsmphr_reg),
+ bf_get(lpfc_port_smphr_sfi, &portsmphr_reg),
+ bf_get(lpfc_port_smphr_nip, &portsmphr_reg),
+ bf_get(lpfc_port_smphr_ipc, &portsmphr_reg),
+ bf_get(lpfc_port_smphr_scr1, &portsmphr_reg),
+ bf_get(lpfc_port_smphr_scr2, &portsmphr_reg),
+ bf_get(lpfc_port_smphr_host_scratch, &portsmphr_reg),
+ bf_get(lpfc_port_smphr_port_status, &portsmphr_reg));
+ } else {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "2534 Device Info: ChipType=0x%x, SliRev=0x%x, "
- "FeatureL1=0x%x, FeatureL2=0x%x\n",
+ "2534 Device Info: SLIFamily=0x%x, "
+ "SLIRev=0x%x, IFType=0x%x, SLIHint_1=0x%x, "
+ "SLIHint_2=0x%x, FT=0x%x\n",
bf_get(lpfc_sli_intf_sli_family,
&phba->sli4_hba.sli_intf),
bf_get(lpfc_sli_intf_slirev,
&phba->sli4_hba.sli_intf),
- bf_get(lpfc_sli_intf_featurelevel1,
+ bf_get(lpfc_sli_intf_if_type,
+ &phba->sli4_hba.sli_intf),
+ bf_get(lpfc_sli_intf_sli_hint1,
&phba->sli4_hba.sli_intf),
- bf_get(lpfc_sli_intf_featurelevel2,
+ bf_get(lpfc_sli_intf_sli_hint2,
+ &phba->sli4_hba.sli_intf),
+ bf_get(lpfc_sli_intf_func_type,
&phba->sli4_hba.sli_intf));
+ /*
+ * Check for other Port errors during the initialization
+ * process. Fail the load if the port did not come up
+ * correctly.
+ */
+ if_type = bf_get(lpfc_sli_intf_if_type,
+ &phba->sli4_hba.sli_intf);
+ switch (if_type) {
+ case LPFC_SLI_INTF_IF_TYPE_0:
+ phba->sli4_hba.ue_mask_lo =
+ readl(phba->sli4_hba.u.if_type0.UEMASKLOregaddr);
+ phba->sli4_hba.ue_mask_hi =
+ readl(phba->sli4_hba.u.if_type0.UEMASKHIregaddr);
+ uerrlo_reg.word0 =
+ readl(phba->sli4_hba.u.if_type0.UERRLOregaddr);
+ uerrhi_reg.word0 =
+ readl(phba->sli4_hba.u.if_type0.UERRHIregaddr);
+ if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) ||
+ (~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "1422 Unrecoverable Error "
+ "Detected during POST "
+ "uerr_lo_reg=0x%x, "
+ "uerr_hi_reg=0x%x, "
+ "ue_mask_lo_reg=0x%x, "
+ "ue_mask_hi_reg=0x%x\n",
+ uerrlo_reg.word0,
+ uerrhi_reg.word0,
+ phba->sli4_hba.ue_mask_lo,
+ phba->sli4_hba.ue_mask_hi);
+ port_error = -ENODEV;
+ }
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_2:
+ /* Final checks. The port status should be clean. */
+ reg_data.word0 =
+ readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
+ if (bf_get(lpfc_sliport_status_err, &reg_data)) {
+ phba->work_status[0] =
+ readl(phba->sli4_hba.u.if_type2.
+ ERR1regaddr);
+ phba->work_status[1] =
+ readl(phba->sli4_hba.u.if_type2.
+ ERR2regaddr);
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2888 Port Error Detected "
+ "during POST: "
+ "port status reg 0x%x, "
+ "port_smphr reg 0x%x, "
+ "error 1=0x%x, error 2=0x%x\n",
+ reg_data.word0,
+ portsmphr_reg.word0,
+ phba->work_status[0],
+ phba->work_status[1]);
+ port_error = -ENODEV;
+ }
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_1:
+ default:
+ break;
+ }
}
- phba->sli4_hba.ue_mask_lo = readl(phba->sli4_hba.UEMASKLOregaddr);
- phba->sli4_hba.ue_mask_hi = readl(phba->sli4_hba.UEMASKHIregaddr);
- /* With uncoverable error, log the error message and return error */
- uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr);
- uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr);
- if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) ||
- (~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1422 HBA Unrecoverable error: "
- "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
- "ue_mask_lo_reg=0x%x, ue_mask_hi_reg=0x%x\n",
- uerrlo_reg.word0, uerrhi_reg.word0,
- phba->sli4_hba.ue_mask_lo,
- phba->sli4_hba.ue_mask_hi);
- return -ENODEV;
- }
-
return port_error;
}
/**
* lpfc_sli4_bar0_register_memmap - Set up SLI4 BAR0 register memory map.
* @phba: pointer to lpfc hba data structure.
+ * @if_type: The SLI4 interface type getting configured.
*
* This routine is invoked to set up SLI4 BAR0 PCI config space register
* memory map.
**/
static void
-lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba)
-{
- phba->sli4_hba.UERRLOregaddr = phba->sli4_hba.conf_regs_memmap_p +
- LPFC_UERR_STATUS_LO;
- phba->sli4_hba.UERRHIregaddr = phba->sli4_hba.conf_regs_memmap_p +
- LPFC_UERR_STATUS_HI;
- phba->sli4_hba.UEMASKLOregaddr = phba->sli4_hba.conf_regs_memmap_p +
- LPFC_UE_MASK_LO;
- phba->sli4_hba.UEMASKHIregaddr = phba->sli4_hba.conf_regs_memmap_p +
- LPFC_UE_MASK_HI;
- phba->sli4_hba.SLIINTFregaddr = phba->sli4_hba.conf_regs_memmap_p +
- LPFC_SLI_INTF;
+lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type)
+{
+ switch (if_type) {
+ case LPFC_SLI_INTF_IF_TYPE_0:
+ phba->sli4_hba.u.if_type0.UERRLOregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_UERR_STATUS_LO;
+ phba->sli4_hba.u.if_type0.UERRHIregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_UERR_STATUS_HI;
+ phba->sli4_hba.u.if_type0.UEMASKLOregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_UE_MASK_LO;
+ phba->sli4_hba.u.if_type0.UEMASKHIregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_UE_MASK_HI;
+ phba->sli4_hba.SLIINTFregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_SLI_INTF;
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_2:
+ phba->sli4_hba.u.if_type2.ERR1regaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_ERR_1;
+ phba->sli4_hba.u.if_type2.ERR2regaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_ERR_2;
+ phba->sli4_hba.u.if_type2.CTRLregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_CNTRL;
+ phba->sli4_hba.u.if_type2.STATUSregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_STATUS;
+ phba->sli4_hba.SLIINTFregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_SLI_INTF;
+ phba->sli4_hba.PSMPHRregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_IF2_SMPHR;
+ phba->sli4_hba.RQDBregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_RQ_DOORBELL;
+ phba->sli4_hba.WQDBregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_WQ_DOORBELL;
+ phba->sli4_hba.EQCQDBregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL;
+ phba->sli4_hba.MQDBregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_MQ_DOORBELL;
+ phba->sli4_hba.BMBXregaddr =
+ phba->sli4_hba.conf_regs_memmap_p + LPFC_BMBX;
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_1:
+ default:
+ dev_printk(KERN_ERR, &phba->pcidev->dev,
+ "FATAL - unsupported SLI4 interface type - %d\n",
+ if_type);
+ break;
+ }
}
/**
@@ -5293,16 +5561,14 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba)
static void
lpfc_sli4_bar1_register_memmap(struct lpfc_hba *phba)
{
-
- phba->sli4_hba.STAregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
- LPFC_HST_STATE;
+ phba->sli4_hba.PSMPHRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
+ LPFC_SLIPORT_IF0_SMPHR;
phba->sli4_hba.ISRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
- LPFC_HST_ISR0;
+ LPFC_HST_ISR0;
phba->sli4_hba.IMRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
- LPFC_HST_IMR0;
+ LPFC_HST_IMR0;
phba->sli4_hba.ISCRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
- LPFC_HST_ISCR0;
- return;
+ LPFC_HST_ISCR0;
}
/**
@@ -5542,11 +5808,12 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
}
/**
- * lpfc_dev_endian_order_setup - Notify the port of the host's endian order.
+ * lpfc_setup_endian_order - Write endian order to an SLI4 if_type 0 port.
* @phba: pointer to lpfc hba data structure.
*
- * This routine is invoked to setup the host-side endian order to the
- * HBA consistent with the SLI-4 interface spec.
+ * This routine is invoked to setup the port-side endian order when
+ * the port if_type is 0. This routine has no function for other
+ * if_types.
*
* Return codes
* 0 - successful
@@ -5557,34 +5824,44 @@ static int
lpfc_setup_endian_order(struct lpfc_hba *phba)
{
LPFC_MBOXQ_t *mboxq;
- uint32_t rc = 0;
+ uint32_t if_type, rc = 0;
uint32_t endian_mb_data[2] = {HOST_ENDIAN_LOW_WORD0,
HOST_ENDIAN_HIGH_WORD1};
- mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0492 Unable to allocate memory for issuing "
- "SLI_CONFIG_SPECIAL mailbox command\n");
- return -ENOMEM;
- }
+ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+ switch (if_type) {
+ case LPFC_SLI_INTF_IF_TYPE_0:
+ mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
+ GFP_KERNEL);
+ if (!mboxq) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0492 Unable to allocate memory for "
+ "issuing SLI_CONFIG_SPECIAL mailbox "
+ "command\n");
+ return -ENOMEM;
+ }
- /*
- * The SLI4_CONFIG_SPECIAL mailbox command requires the first two
- * words to contain special data values and no other data.
- */
- memset(mboxq, 0, sizeof(LPFC_MBOXQ_t));
- memcpy(&mboxq->u.mqe, &endian_mb_data, sizeof(endian_mb_data));
- rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0493 SLI_CONFIG_SPECIAL mailbox failed with "
- "status x%x\n",
- rc);
- rc = -EIO;
+ /*
+ * The SLI4_CONFIG_SPECIAL mailbox command requires the first
+ * two words to contain special data values and no other data.
+ */
+ memset(mboxq, 0, sizeof(LPFC_MBOXQ_t));
+ memcpy(&mboxq->u.mqe, &endian_mb_data, sizeof(endian_mb_data));
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ if (rc != MBX_SUCCESS) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0493 SLI_CONFIG_SPECIAL mailbox "
+ "failed with status x%x\n",
+ rc);
+ rc = -EIO;
+ }
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_2:
+ case LPFC_SLI_INTF_IF_TYPE_1:
+ default:
+ break;
}
-
- mempool_free(mboxq, phba->mbox_mem_pool);
return rc;
}
@@ -6416,36 +6693,124 @@ int
lpfc_pci_function_reset(struct lpfc_hba *phba)
{
LPFC_MBOXQ_t *mboxq;
- uint32_t rc = 0;
+ uint32_t rc = 0, if_type;
uint32_t shdr_status, shdr_add_status;
+ uint32_t rdy_chk, num_resets = 0, reset_again = 0;
union lpfc_sli4_cfg_shdr *shdr;
+ struct lpfc_register reg_data;
- mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0494 Unable to allocate memory for issuing "
- "SLI_FUNCTION_RESET mailbox command\n");
- return -ENOMEM;
- }
+ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+ switch (if_type) {
+ case LPFC_SLI_INTF_IF_TYPE_0:
+ mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
+ GFP_KERNEL);
+ if (!mboxq) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0494 Unable to allocate memory for "
+ "issuing SLI_FUNCTION_RESET mailbox "
+ "command\n");
+ return -ENOMEM;
+ }
- /* Set up PCI function reset SLI4_CONFIG mailbox-ioctl command */
- lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
- LPFC_MBOX_OPCODE_FUNCTION_RESET, 0,
- LPFC_SLI4_MBX_EMBED);
- rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- shdr = (union lpfc_sli4_cfg_shdr *)
- &mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
- shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
- shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
- if (rc != MBX_TIMEOUT)
- mempool_free(mboxq, phba->mbox_mem_pool);
- if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0495 SLI_FUNCTION_RESET mailbox failed with "
- "status x%x add_status x%x, mbx status x%x\n",
- shdr_status, shdr_add_status, rc);
- rc = -ENXIO;
+ /* Setup PCI function reset mailbox-ioctl command */
+ lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+ LPFC_MBOX_OPCODE_FUNCTION_RESET, 0,
+ LPFC_SLI4_MBX_EMBED);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ shdr = (union lpfc_sli4_cfg_shdr *)
+ &mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
+ shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+ shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
+ &shdr->response);
+ if (rc != MBX_TIMEOUT)
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ if (shdr_status || shdr_add_status || rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0495 SLI_FUNCTION_RESET mailbox "
+ "failed with status x%x add_status x%x,"
+ " mbx status x%x\n",
+ shdr_status, shdr_add_status, rc);
+ rc = -ENXIO;
+ }
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_2:
+ for (num_resets = 0;
+ num_resets < MAX_IF_TYPE_2_RESETS;
+ num_resets++) {
+ reg_data.word0 = 0;
+ bf_set(lpfc_sliport_ctrl_end, &reg_data,
+ LPFC_SLIPORT_LITTLE_ENDIAN);
+ bf_set(lpfc_sliport_ctrl_ip, &reg_data,
+ LPFC_SLIPORT_INIT_PORT);
+ writel(reg_data.word0, phba->sli4_hba.u.if_type2.
+ CTRLregaddr);
+
+ /*
+ * Poll the Port Status Register and wait for RDY for
+ * up to 10 seconds. If the port doesn't respond, treat
+ * it as an error. If the port responds with RN, start
+ * the loop again.
+ */
+ for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) {
+ reg_data.word0 =
+ readl(phba->sli4_hba.u.if_type2.
+ STATUSregaddr);
+ if (bf_get(lpfc_sliport_status_rdy, &reg_data))
+ break;
+ if (bf_get(lpfc_sliport_status_rn, &reg_data)) {
+ reset_again++;
+ break;
+ }
+ msleep(10);
+ }
+
+ /*
+ * If the port responds to the init request with
+ * reset needed, delay for a bit and restart the loop.
+ */
+ if (reset_again) {
+ msleep(10);
+ reset_again = 0;
+ continue;
+ }
+
+ /* Detect any port errors. */
+ reg_data.word0 = readl(phba->sli4_hba.u.if_type2.
+ STATUSregaddr);
+ if ((bf_get(lpfc_sliport_status_err, &reg_data)) ||
+ (rdy_chk >= 1000)) {
+ phba->work_status[0] = readl(
+ phba->sli4_hba.u.if_type2.ERR1regaddr);
+ phba->work_status[1] = readl(
+ phba->sli4_hba.u.if_type2.ERR2regaddr);
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2890 Port Error Detected "
+ "during Port Reset: "
+ "port status reg 0x%x, "
+ "error 1=0x%x, error 2=0x%x\n",
+ reg_data.word0,
+ phba->work_status[0],
+ phba->work_status[1]);
+ rc = -ENODEV;
+ }
+
+ /*
+ * Terminate the outer loop provided the Port indicated
+ * ready within 10 seconds.
+ */
+ if (rdy_chk < 1000)
+ break;
+ }
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_1:
+ default:
+ break;
}
+
+ /* Catch the not-ready port failure after a port reset. */
+ if (num_resets >= MAX_IF_TYPE_2_RESETS)
+ rc = -ENODEV;
+
return rc;
}
@@ -6536,6 +6901,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
struct pci_dev *pdev;
unsigned long bar0map_len, bar1map_len, bar2map_len;
int error = -ENODEV;
+ uint32_t if_type;
/* Obtain PCI device reference */
if (!phba->pcidev)
@@ -6552,61 +6918,105 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
}
}
- /* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the
- * number of bytes required by each mapping. They are actually
- * mapping to the PCI BAR regions 0 or 1, 2, and 4 by the SLI4 device.
+ /*
+ * The BARs and register set definitions and offset locations are
+ * dependent on the if_type.
+ */
+ if (pci_read_config_dword(pdev, LPFC_SLI_INTF,
+ &phba->sli4_hba.sli_intf.word0)) {
+ return error;
+ }
+
+ /* There is no SLI3 failback for SLI4 devices. */
+ if (bf_get(lpfc_sli_intf_valid, &phba->sli4_hba.sli_intf) !=
+ LPFC_SLI_INTF_VALID) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2894 SLI_INTF reg contents invalid "
+ "sli_intf reg 0x%x\n",
+ phba->sli4_hba.sli_intf.word0);
+ return error;
+ }
+
+ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+ /*
+ * Get the bus address of SLI4 device Bar regions and the
+ * number of bytes required by each mapping. The mapping of the
+ * particular PCI BARs regions is dependent on the type of
+ * SLI4 device.
*/
if (pci_resource_start(pdev, 0)) {
phba->pci_bar0_map = pci_resource_start(pdev, 0);
bar0map_len = pci_resource_len(pdev, 0);
+
+ /*
+ * Map SLI4 PCI Config Space Register base to a kernel virtual
+ * addr
+ */
+ phba->sli4_hba.conf_regs_memmap_p =
+ ioremap(phba->pci_bar0_map, bar0map_len);
+ if (!phba->sli4_hba.conf_regs_memmap_p) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "ioremap failed for SLI4 PCI config "
+ "registers.\n");
+ goto out;
+ }
+ /* Set up BAR0 PCI config space register memory map */
+ lpfc_sli4_bar0_register_memmap(phba, if_type);
} else {
phba->pci_bar0_map = pci_resource_start(pdev, 1);
bar0map_len = pci_resource_len(pdev, 1);
- }
- phba->pci_bar1_map = pci_resource_start(pdev, 2);
- bar1map_len = pci_resource_len(pdev, 2);
-
- phba->pci_bar2_map = pci_resource_start(pdev, 4);
- bar2map_len = pci_resource_len(pdev, 4);
-
- /* Map SLI4 PCI Config Space Register base to a kernel virtual addr */
- phba->sli4_hba.conf_regs_memmap_p =
+ if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "FATAL - No BAR0 mapping for SLI4, if_type 2\n");
+ goto out;
+ }
+ phba->sli4_hba.conf_regs_memmap_p =
ioremap(phba->pci_bar0_map, bar0map_len);
- if (!phba->sli4_hba.conf_regs_memmap_p) {
- dev_printk(KERN_ERR, &pdev->dev,
- "ioremap failed for SLI4 PCI config registers.\n");
- goto out;
+ if (!phba->sli4_hba.conf_regs_memmap_p) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "ioremap failed for SLI4 PCI config "
+ "registers.\n");
+ goto out;
+ }
+ lpfc_sli4_bar0_register_memmap(phba, if_type);
}
- /* Map SLI4 HBA Control Register base to a kernel virtual address. */
- phba->sli4_hba.ctrl_regs_memmap_p =
+ if (pci_resource_start(pdev, 2)) {
+ /*
+ * Map SLI4 if type 0 HBA Control Register base to a kernel
+ * virtual address and setup the registers.
+ */
+ phba->pci_bar1_map = pci_resource_start(pdev, 2);
+ bar1map_len = pci_resource_len(pdev, 2);
+ phba->sli4_hba.ctrl_regs_memmap_p =
ioremap(phba->pci_bar1_map, bar1map_len);
- if (!phba->sli4_hba.ctrl_regs_memmap_p) {
- dev_printk(KERN_ERR, &pdev->dev,
+ if (!phba->sli4_hba.ctrl_regs_memmap_p) {
+ dev_printk(KERN_ERR, &pdev->dev,
"ioremap failed for SLI4 HBA control registers.\n");
- goto out_iounmap_conf;
+ goto out_iounmap_conf;
+ }
+ lpfc_sli4_bar1_register_memmap(phba);
}
- /* Map SLI4 HBA Doorbell Register base to a kernel virtual address. */
- phba->sli4_hba.drbl_regs_memmap_p =
+ if (pci_resource_start(pdev, 4)) {
+ /*
+ * Map SLI4 if type 0 HBA Doorbell Register base to a kernel
+ * virtual address and setup the registers.
+ */
+ phba->pci_bar2_map = pci_resource_start(pdev, 4);
+ bar2map_len = pci_resource_len(pdev, 4);
+ phba->sli4_hba.drbl_regs_memmap_p =
ioremap(phba->pci_bar2_map, bar2map_len);
- if (!phba->sli4_hba.drbl_regs_memmap_p) {
- dev_printk(KERN_ERR, &pdev->dev,
+ if (!phba->sli4_hba.drbl_regs_memmap_p) {
+ dev_printk(KERN_ERR, &pdev->dev,
"ioremap failed for SLI4 HBA doorbell registers.\n");
- goto out_iounmap_ctrl;
+ goto out_iounmap_ctrl;
+ }
+ error = lpfc_sli4_bar2_register_memmap(phba, LPFC_VF0);
+ if (error)
+ goto out_iounmap_all;
}
- /* Set up BAR0 PCI config space register memory map */
- lpfc_sli4_bar0_register_memmap(phba);
-
- /* Set up BAR1 register memory map */
- lpfc_sli4_bar1_register_memmap(phba);
-
- /* Set up BAR2 register memory map */
- error = lpfc_sli4_bar2_register_memmap(phba, LPFC_VF0);
- if (error)
- goto out_iounmap_all;
-
return 0;
out_iounmap_all:
@@ -8149,6 +8559,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_unset_driver_resource_s4;
}
+ INIT_LIST_HEAD(&phba->active_rrq_list);
+
/* Set up common device driver resources */
error = lpfc_setup_driver_resource_phase2(phba);
if (error) {
@@ -8218,7 +8630,11 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
"0451 Configure interrupt mode (%d) "
"failed active interrupt test.\n",
intr_mode);
- /* Unset the preivous SLI-4 HBA setup */
+ /* Unset the previous SLI-4 HBA setup. */
+ /*
+ * TODO: Is this operation compatible with IF TYPE 2
+ * devices? All port state is deleted and cleared.
+ */
lpfc_sli4_unset_hba(phba);
/* Try next level of interrupt mode */
cfg_mode = --intr_mode;
@@ -8990,6 +9406,10 @@ static struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BALIUS,
PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE,
+ PCI_ANY_ID, PCI_ANY_ID, },
{ 0 }
};
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index bb59e927312..e3b790e5915 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -33,7 +33,7 @@
#define LOG_FCP_ERROR 0x00001000 /* log errors, not underruns */
#define LOG_LIBDFC 0x00002000 /* Libdfc events */
#define LOG_VPORT 0x00004000 /* NPIV events */
-#define LOF_SECURITY 0x00008000 /* Security events */
+#define LOG_SECURITY 0x00008000 /* Security events */
#define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */
#define LOG_FIP 0x00020000 /* FIP events */
#define LOG_ALL_MSG 0xffffffff /* LOG all messages */
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 62d0957e1d4..23403c65020 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -263,18 +263,19 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
}
/**
- * lpfc_read_la - Prepare a mailbox command for reading HBA link attention
+ * lpfc_read_topology - Prepare a mailbox command for reading HBA topology
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @mp: DMA buffer memory for reading the link attention information into.
*
- * The read link attention mailbox command is issued to read the Link Event
- * Attention information indicated by the HBA port when the Link Event bit
- * of the Host Attention (HSTATT) register is set to 1. A Link Event
+ * The read topology mailbox command is issued to read the link topology
+ * information indicated by the HBA port when the Link Event bit of the Host
+ * Attention (HSTATT) register is set to 1 (For SLI-3) or when an FC Link
+ * Attention ACQE is received from the port (For SLI-4). A Link Event
* Attention occurs based on an exception detected at the Fibre Channel link
* interface.
*
- * This routine prepares the mailbox command for reading HBA link attention
+ * This routine prepares the mailbox command for reading HBA link topology
* information. A DMA memory has been set aside and address passed to the
* HBA through @mp for the HBA to DMA link attention information into the
* memory as part of the execution of the mailbox command.
@@ -283,7 +284,8 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
* 0 - Success (currently always return 0)
**/
int
-lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
+lpfc_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb,
+ struct lpfc_dmabuf *mp)
{
MAILBOX_t *mb;
struct lpfc_sli *psli;
@@ -293,15 +295,15 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
INIT_LIST_HEAD(&mp->list);
- mb->mbxCommand = MBX_READ_LA64;
- mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
- mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys);
- mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys);
+ mb->mbxCommand = MBX_READ_TOPOLOGY;
+ mb->un.varReadTop.lilpBde64.tus.f.bdeSize = LPFC_ALPA_MAP_SIZE;
+ mb->un.varReadTop.lilpBde64.addrHigh = putPaddrHigh(mp->phys);
+ mb->un.varReadTop.lilpBde64.addrLow = putPaddrLow(mp->phys);
/* Save address for later completion and set the owner to host so that
* the FW knows this mailbox is available for processing.
*/
- pmb->context1 = (uint8_t *) mp;
+ pmb->context1 = (uint8_t *)mp;
mb->mbxOwner = OWN_HOST;
return (0);
}
@@ -516,18 +518,33 @@ lpfc_init_link(struct lpfc_hba * phba,
vpd = &phba->vpd;
if (vpd->rev.feaLevelHigh >= 0x02){
switch(linkspeed){
- case LINK_SPEED_1G:
- case LINK_SPEED_2G:
- case LINK_SPEED_4G:
- case LINK_SPEED_8G:
- mb->un.varInitLnk.link_flags |=
- FLAGS_LINK_SPEED;
- mb->un.varInitLnk.link_speed = linkspeed;
+ case LPFC_USER_LINK_SPEED_1G:
+ mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
+ mb->un.varInitLnk.link_speed = LINK_SPEED_1G;
+ break;
+ case LPFC_USER_LINK_SPEED_2G:
+ mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
+ mb->un.varInitLnk.link_speed = LINK_SPEED_2G;
+ break;
+ case LPFC_USER_LINK_SPEED_4G:
+ mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
+ mb->un.varInitLnk.link_speed = LINK_SPEED_4G;
+ break;
+ case LPFC_USER_LINK_SPEED_8G:
+ mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
+ mb->un.varInitLnk.link_speed = LINK_SPEED_8G;
+ break;
+ case LPFC_USER_LINK_SPEED_10G:
+ mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
+ mb->un.varInitLnk.link_speed = LINK_SPEED_10G;
break;
- case LINK_SPEED_AUTO:
- default:
- mb->un.varInitLnk.link_speed =
- LINK_SPEED_AUTO;
+ case LPFC_USER_LINK_SPEED_16G:
+ mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
+ mb->un.varInitLnk.link_speed = LINK_SPEED_16G;
+ break;
+ case LPFC_USER_LINK_SPEED_AUTO:
+ default:
+ mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
break;
}
@@ -693,7 +710,7 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
* @did: remote port identifier.
* @param: pointer to memory holding the server parameters.
* @pmb: pointer to the driver internal queue element for mailbox command.
- * @flag: action flag to be passed back for the complete function.
+ * @rpi: the rpi to use in the registration (usually only used for SLI4.
*
* The registration login mailbox command is used to register an N_Port or
* F_Port login. This registration allows the HBA to cache the remote N_Port
@@ -712,7 +729,7 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
**/
int
lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
- uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag)
+ uint8_t *param, LPFC_MBOXQ_t *pmb, uint16_t rpi)
{
MAILBOX_t *mb = &pmb->u.mb;
uint8_t *sparam;
@@ -722,17 +739,13 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
mb->un.varRegLogin.rpi = 0;
if (phba->sli_rev == LPFC_SLI_REV4) {
- mb->un.varRegLogin.rpi = lpfc_sli4_alloc_rpi(phba);
+ mb->un.varRegLogin.rpi = rpi;
if (mb->un.varRegLogin.rpi == LPFC_RPI_ALLOC_ERROR)
return 1;
}
-
mb->un.varRegLogin.vpi = vpi + phba->vpi_base;
mb->un.varRegLogin.did = did;
- mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */
-
mb->mbxOwner = OWN_HOST;
-
/* Get a buffer to hold NPorts Service Parameters */
mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
if (mp)
@@ -743,7 +756,7 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
/* REG_LOGIN: no buffers */
lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
"0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, "
- "flag x%x\n", vpi, did, flag);
+ "rpi x%x\n", vpi, did, rpi);
return (1);
}
INIT_LIST_HEAD(&mp->list);
@@ -1918,11 +1931,14 @@ lpfc_init_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport)
struct lpfc_mbx_init_vfi *init_vfi;
memset(mbox, 0, sizeof(*mbox));
+ mbox->vport = vport;
init_vfi = &mbox->u.mqe.un.init_vfi;
bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VFI);
bf_set(lpfc_init_vfi_vr, init_vfi, 1);
bf_set(lpfc_init_vfi_vt, init_vfi, 1);
+ bf_set(lpfc_init_vfi_vp, init_vfi, 1);
bf_set(lpfc_init_vfi_vfi, init_vfi, vport->vfi + vport->phba->vfi_base);
+ bf_set(lpfc_init_vpi_vpi, init_vfi, vport->vpi + vport->phba->vpi_base);
bf_set(lpfc_init_vfi_fcfi, init_vfi, vport->phba->fcf.fcfi);
}
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 8f879e477e9..cbb48ee8b0b 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -113,11 +113,16 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align)
goto fail_free_mbox_pool;
if (phba->sli_rev == LPFC_SLI_REV4) {
+ phba->rrq_pool =
+ mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
+ sizeof(struct lpfc_node_rrq));
+ if (!phba->rrq_pool)
+ goto fail_free_nlp_mem_pool;
phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool",
phba->pcidev,
LPFC_HDR_BUF_SIZE, align, 0);
if (!phba->lpfc_hrb_pool)
- goto fail_free_nlp_mem_pool;
+ goto fail_free_rrq_mem_pool;
phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool",
phba->pcidev,
@@ -147,6 +152,9 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align)
fail_free_hrb_pool:
pci_pool_destroy(phba->lpfc_hrb_pool);
phba->lpfc_hrb_pool = NULL;
+ fail_free_rrq_mem_pool:
+ mempool_destroy(phba->rrq_pool);
+ phba->rrq_pool = NULL;
fail_free_nlp_mem_pool:
mempool_destroy(phba->nlp_mem_pool);
phba->nlp_mem_pool = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index bccc9c66fa3..d85a7423a69 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -386,7 +386,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
goto out;
rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
- (uint8_t *) sp, mbox, 0);
+ (uint8_t *) sp, mbox, ndlp->nlp_rpi);
if (rc) {
mempool_free(mbox, phba->mbox_mem_pool);
goto out;
@@ -632,7 +632,7 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
- if (!(ndlp->nlp_flag & NLP_RPI_VALID)) {
+ if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
return 0;
}
@@ -968,7 +968,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
lpfc_unreg_rpi(vport, ndlp);
if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID,
- (uint8_t *) sp, mbox, 0) == 0) {
+ (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) {
switch (ndlp->nlp_DID) {
case NameServer_DID:
mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
@@ -1338,12 +1338,6 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
(ndlp == (struct lpfc_nodelist *) mb->context2)) {
- if (phba->sli_rev == LPFC_SLI_REV4) {
- spin_unlock_irq(&phba->hbalock);
- lpfc_sli4_free_rpi(phba,
- mb->u.mb.un.varRegLogin.rpi);
- spin_lock_irq(&phba->hbalock);
- }
mp = (struct lpfc_dmabuf *) (mb->context1);
if (mp) {
__lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -1426,7 +1420,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
}
ndlp->nlp_rpi = mb->un.varWords[0];
- ndlp->nlp_flag |= NLP_RPI_VALID;
+ ndlp->nlp_flag |= NLP_RPI_REGISTERED;
/* Only if we are not a fabric nport do we issue PRLI */
if (!(ndlp->nlp_type & NLP_FABRIC)) {
@@ -2027,7 +2021,7 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,
if (!mb->mbxStatus) {
ndlp->nlp_rpi = mb->un.varWords[0];
- ndlp->nlp_flag |= NLP_RPI_VALID;
+ ndlp->nlp_flag |= NLP_RPI_REGISTERED;
} else {
if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
lpfc_drop_node(vport, ndlp);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 581837b3c71..c97751c95d7 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -621,10 +621,13 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
struct sli4_wcqe_xri_aborted *axri)
{
uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
+ uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
struct lpfc_scsi_buf *psb, *next_psb;
unsigned long iflag = 0;
struct lpfc_iocbq *iocbq;
int i;
+ struct lpfc_nodelist *ndlp;
+ int rrq_empty = 0;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
spin_lock_irqsave(&phba->hbalock, iflag);
@@ -637,8 +640,14 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
psb->status = IOSTAT_SUCCESS;
spin_unlock(
&phba->sli4_hba.abts_scsi_buf_list_lock);
+ ndlp = psb->rdata->pnode;
+ rrq_empty = list_empty(&phba->active_rrq_list);
spin_unlock_irqrestore(&phba->hbalock, iflag);
+ if (ndlp)
+ lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1);
lpfc_release_scsi_buf_s4(phba, psb);
+ if (rrq_empty)
+ lpfc_worker_wake_up(phba);
return;
}
}
@@ -914,7 +923,7 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport, int num_to_alloc)
}
/**
- * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
+ * lpfc_get_scsi_buf_s3 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
* @phba: The HBA for which this call is being executed.
*
* This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
@@ -925,7 +934,7 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport, int num_to_alloc)
* Pointer to lpfc_scsi_buf - Success
**/
static struct lpfc_scsi_buf*
-lpfc_get_scsi_buf(struct lpfc_hba * phba)
+lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
struct lpfc_scsi_buf * lpfc_cmd = NULL;
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
@@ -941,6 +950,67 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
return lpfc_cmd;
}
+/**
+ * lpfc_get_scsi_buf_s4 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
+ * @phba: The HBA for which this call is being executed.
+ *
+ * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
+ * and returns to caller.
+ *
+ * Return codes:
+ * NULL - Error
+ * Pointer to lpfc_scsi_buf - Success
+ **/
+static struct lpfc_scsi_buf*
+lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+{
+ struct lpfc_scsi_buf *lpfc_cmd = NULL;
+ struct lpfc_scsi_buf *start_lpfc_cmd = NULL;
+ struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+ unsigned long iflag = 0;
+ int found = 0;
+
+ spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
+ list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+ while (!found && lpfc_cmd) {
+ if (lpfc_test_rrq_active(phba, ndlp,
+ lpfc_cmd->cur_iocbq.sli4_xritag)) {
+ lpfc_release_scsi_buf_s4(phba, lpfc_cmd);
+ spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
+ list_remove_head(scsi_buf_list, lpfc_cmd,
+ struct lpfc_scsi_buf, list);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
+ iflag);
+ if (lpfc_cmd == start_lpfc_cmd) {
+ lpfc_cmd = NULL;
+ break;
+ } else
+ continue;
+ }
+ found = 1;
+ lpfc_cmd->seg_cnt = 0;
+ lpfc_cmd->nonsg_phys = 0;
+ lpfc_cmd->prot_seg_cnt = 0;
+ }
+ return lpfc_cmd;
+}
+/**
+ * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
+ * @phba: The HBA for which this call is being executed.
+ *
+ * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
+ * and returns to caller.
+ *
+ * Return codes:
+ * NULL - Error
+ * Pointer to lpfc_scsi_buf - Success
+ **/
+static struct lpfc_scsi_buf*
+lpfc_get_scsi_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+{
+ return phba->lpfc_get_scsi_buf(phba, ndlp);
+}
/**
* lpfc_release_scsi_buf - Return a scsi buffer back to hba scsi buf list
@@ -2744,18 +2814,19 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf;
phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd;
- phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf;
switch (dev_grp) {
case LPFC_PCI_DEV_LP:
phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s3;
phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s3;
phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3;
+ phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3;
break;
case LPFC_PCI_DEV_OC:
phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s4;
phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4;
phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4;
+ phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4;
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -2764,7 +2835,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
return -ENODEV;
break;
}
- phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf;
phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth;
phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
return 0;
@@ -2940,7 +3010,7 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)
goto out_host_busy;
- lpfc_cmd = lpfc_get_scsi_buf(phba);
+ lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
if (lpfc_cmd == NULL) {
lpfc_rampdown_queue_depth(phba);
@@ -3239,7 +3309,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata,
if (!pnode || !NLP_CHK_NODE_ACT(pnode))
return FAILED;
- lpfc_cmd = lpfc_get_scsi_buf(phba);
+ lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode);
if (lpfc_cmd == NULL)
return FAILED;
lpfc_cmd->timeout = 60;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 554efa6623f..634b2fea9c4 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -513,8 +513,344 @@ __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag)
}
/**
+ * __lpfc_set_rrq_active - set RRQ active bit in the ndlp's xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @ndlp: nodelist pointer for this target.
+ * @xritag: xri used in this exchange.
+ * @rxid: Remote Exchange ID.
+ * @send_rrq: Flag used to determine if we should send rrq els cmd.
+ *
+ * This function is called with hbalock held.
+ * The active bit is set in the ndlp's active rrq xri_bitmap. Allocates an
+ * rrq struct and adds it to the active_rrq_list.
+ *
+ * returns 0 for rrq slot for this xri
+ * < 0 Were not able to get rrq mem or invalid parameter.
+ **/
+static int
+__lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
+{
+ uint16_t adj_xri;
+ struct lpfc_node_rrq *rrq;
+ int empty;
+
+ /*
+ * set the active bit even if there is no mem available.
+ */
+ adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
+ if (!ndlp)
+ return -EINVAL;
+ if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap))
+ return -EINVAL;
+ rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
+ if (rrq) {
+ rrq->send_rrq = send_rrq;
+ rrq->xritag = xritag;
+ rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
+ rrq->ndlp = ndlp;
+ rrq->nlp_DID = ndlp->nlp_DID;
+ rrq->vport = ndlp->vport;
+ rrq->rxid = rxid;
+ empty = list_empty(&phba->active_rrq_list);
+ if (phba->cfg_enable_rrq && send_rrq)
+ /*
+ * We need the xri before we can add this to the
+ * phba active rrq list.
+ */
+ rrq->send_rrq = send_rrq;
+ else
+ rrq->send_rrq = 0;
+ list_add_tail(&rrq->list, &phba->active_rrq_list);
+ if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) {
+ phba->hba_flag |= HBA_RRQ_ACTIVE;
+ if (empty)
+ lpfc_worker_wake_up(phba);
+ }
+ return 0;
+ }
+ return -ENOMEM;
+}
+
+/**
+ * __lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @xritag: xri used in this exchange.
+ * @rrq: The RRQ to be cleared.
+ *
+ * This function is called with hbalock held. This function
+ **/
+static void
+__lpfc_clr_rrq_active(struct lpfc_hba *phba,
+ uint16_t xritag,
+ struct lpfc_node_rrq *rrq)
+{
+ uint16_t adj_xri;
+ struct lpfc_nodelist *ndlp;
+
+ ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID);
+
+ /* The target DID could have been swapped (cable swap)
+ * we should use the ndlp from the findnode if it is
+ * available.
+ */
+ if (!ndlp)
+ ndlp = rrq->ndlp;
+
+ adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
+ if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) {
+ rrq->send_rrq = 0;
+ rrq->xritag = 0;
+ rrq->rrq_stop_time = 0;
+ }
+ mempool_free(rrq, phba->rrq_pool);
+}
+
+/**
+ * lpfc_handle_rrq_active - Checks if RRQ has waithed RATOV.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called with hbalock held. This function
+ * Checks if stop_time (ratov from setting rrq active) has
+ * been reached, if it has and the send_rrq flag is set then
+ * it will call lpfc_send_rrq. If the send_rrq flag is not set
+ * then it will just call the routine to clear the rrq and
+ * free the rrq resource.
+ * The timer is set to the next rrq that is going to expire before
+ * leaving the routine.
+ *
+ **/
+void
+lpfc_handle_rrq_active(struct lpfc_hba *phba)
+{
+ struct lpfc_node_rrq *rrq;
+ struct lpfc_node_rrq *nextrrq;
+ unsigned long next_time;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+ next_time = jiffies + HZ * (phba->fc_ratov + 1);
+ list_for_each_entry_safe(rrq, nextrrq,
+ &phba->active_rrq_list, list) {
+ if (time_after(jiffies, rrq->rrq_stop_time)) {
+ list_del(&rrq->list);
+ if (!rrq->send_rrq)
+ /* this call will free the rrq */
+ __lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+ else {
+ /* if we send the rrq then the completion handler
+ * will clear the bit in the xribitmap.
+ */
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ if (lpfc_send_rrq(phba, rrq)) {
+ lpfc_clr_rrq_active(phba, rrq->xritag,
+ rrq);
+ }
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ }
+ } else if (time_before(rrq->rrq_stop_time, next_time))
+ next_time = rrq->rrq_stop_time;
+ }
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ if (!list_empty(&phba->active_rrq_list))
+ mod_timer(&phba->rrq_tmr, next_time);
+}
+
+/**
+ * lpfc_get_active_rrq - Get the active RRQ for this exchange.
+ * @vport: Pointer to vport context object.
+ * @xri: The xri used in the exchange.
+ * @did: The targets DID for this exchange.
+ *
+ * returns NULL = rrq not found in the phba->active_rrq_list.
+ * rrq = rrq for this xri and target.
+ **/
+struct lpfc_node_rrq *
+lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did)
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_node_rrq *rrq;
+ struct lpfc_node_rrq *nextrrq;
+ unsigned long iflags;
+
+ if (phba->sli_rev != LPFC_SLI_REV4)
+ return NULL;
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+ if (rrq->vport == vport && rrq->xritag == xri &&
+ rrq->nlp_DID == did){
+ list_del(&rrq->list);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return rrq;
+ }
+ }
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return NULL;
+}
+
+/**
+ * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport.
+ * @vport: Pointer to vport context object.
+ *
+ * Remove all active RRQs for this vport from the phba->active_rrq_list and
+ * clear the rrq.
+ **/
+void
+lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport)
+
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_node_rrq *rrq;
+ struct lpfc_node_rrq *nextrrq;
+ unsigned long iflags;
+
+ if (phba->sli_rev != LPFC_SLI_REV4)
+ return;
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+ if (rrq->vport == vport) {
+ list_del(&rrq->list);
+ __lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+ }
+ }
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+}
+
+/**
+ * lpfc_cleanup_wt_rrqs - Remove all rrq's from the active list.
+ * @phba: Pointer to HBA context object.
+ *
+ * Remove all rrqs from the phba->active_rrq_list and free them by
+ * calling __lpfc_clr_active_rrq
+ *
+ **/
+void
+lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba)
+{
+ struct lpfc_node_rrq *rrq;
+ struct lpfc_node_rrq *nextrrq;
+ unsigned long next_time;
+ unsigned long iflags;
+
+ if (phba->sli_rev != LPFC_SLI_REV4)
+ return;
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+ next_time = jiffies + HZ * (phba->fc_ratov * 2);
+ list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+ list_del(&rrq->list);
+ __lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+ }
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ if (!list_empty(&phba->active_rrq_list))
+ mod_timer(&phba->rrq_tmr, next_time);
+}
+
+
+/**
+ * __lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @ndlp: Targets nodelist pointer for this exchange.
+ * @xritag the xri in the bitmap to test.
+ *
+ * This function is called with hbalock held. This function
+ * returns 0 = rrq not active for this xri
+ * 1 = rrq is valid for this xri.
+ **/
+static int
+__lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ uint16_t xritag)
+{
+ uint16_t adj_xri;
+
+ adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
+ if (!ndlp)
+ return 0;
+ if (test_bit(adj_xri, ndlp->active_rrqs.xri_bitmap))
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * lpfc_set_rrq_active - set RRQ active bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @ndlp: nodelist pointer for this target.
+ * @xritag: xri used in this exchange.
+ * @rxid: Remote Exchange ID.
+ * @send_rrq: Flag used to determine if we should send rrq els cmd.
+ *
+ * This function takes the hbalock.
+ * The active bit is always set in the active rrq xri_bitmap even
+ * if there is no slot avaiable for the other rrq information.
+ *
+ * returns 0 rrq actived for this xri
+ * < 0 No memory or invalid ndlp.
+ **/
+int
+lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
+{
+ int ret;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ ret = __lpfc_set_rrq_active(phba, ndlp, xritag, rxid, send_rrq);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return ret;
+}
+
+/**
+ * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @xritag: xri used in this exchange.
+ * @rrq: The RRQ to be cleared.
+ *
+ * This function is takes the hbalock.
+ **/
+void
+lpfc_clr_rrq_active(struct lpfc_hba *phba,
+ uint16_t xritag,
+ struct lpfc_node_rrq *rrq)
+{
+ unsigned long iflags;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ __lpfc_clr_rrq_active(phba, xritag, rrq);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return;
+}
+
+
+
+/**
+ * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @ndlp: Targets nodelist pointer for this exchange.
+ * @xritag the xri in the bitmap to test.
+ *
+ * This function takes the hbalock.
+ * returns 0 = rrq not active for this xri
+ * 1 = rrq is valid for this xri.
+ **/
+int
+lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ uint16_t xritag)
+{
+ int ret;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ ret = __lpfc_test_rrq_active(phba, ndlp, xritag);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return ret;
+}
+
+/**
* __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool
* @phba: Pointer to HBA context object.
+ * @piocb: Pointer to the iocbq.
*
* This function is called with hbalock held. This function
* Gets a new driver sglq object from the sglq list. If the
@@ -522,17 +858,51 @@ __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag)
* allocated sglq object else it returns NULL.
**/
static struct lpfc_sglq *
-__lpfc_sli_get_sglq(struct lpfc_hba *phba)
+__lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
{
struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list;
struct lpfc_sglq *sglq = NULL;
+ struct lpfc_sglq *start_sglq = NULL;
uint16_t adj_xri;
+ struct lpfc_scsi_buf *lpfc_cmd;
+ struct lpfc_nodelist *ndlp;
+ int found = 0;
+
+ if (piocbq->iocb_flag & LPFC_IO_FCP) {
+ lpfc_cmd = (struct lpfc_scsi_buf *) piocbq->context1;
+ ndlp = lpfc_cmd->rdata->pnode;
+ } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) &&
+ !(piocbq->iocb_flag & LPFC_IO_LIBDFC))
+ ndlp = piocbq->context_un.ndlp;
+ else
+ ndlp = piocbq->context1;
+
list_remove_head(lpfc_sgl_list, sglq, struct lpfc_sglq, list);
- if (!sglq)
- return NULL;
- adj_xri = sglq->sli4_xritag - phba->sli4_hba.max_cfg_param.xri_base;
- phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq;
- sglq->state = SGL_ALLOCATED;
+ start_sglq = sglq;
+ while (!found) {
+ if (!sglq)
+ return NULL;
+ adj_xri = sglq->sli4_xritag -
+ phba->sli4_hba.max_cfg_param.xri_base;
+ if (__lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
+ /* This xri has an rrq outstanding for this DID.
+ * put it back in the list and get another xri.
+ */
+ list_add_tail(&sglq->list, lpfc_sgl_list);
+ sglq = NULL;
+ list_remove_head(lpfc_sgl_list, sglq,
+ struct lpfc_sglq, list);
+ if (sglq == start_sglq) {
+ sglq = NULL;
+ break;
+ } else
+ continue;
+ }
+ sglq->ndlp = ndlp;
+ found = 1;
+ phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq;
+ sglq->state = SGL_ALLOCATED;
+ }
return sglq;
}
@@ -598,6 +968,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
&phba->sli4_hba.abts_sgl_list_lock, iflag);
} else {
sglq->state = SGL_FREED;
+ sglq->ndlp = NULL;
list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list);
/* Check if TXQ queue needs to be serviced */
@@ -1634,7 +2005,6 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
case MBX_READ_LNK_STAT:
case MBX_REG_LOGIN:
case MBX_UNREG_LOGIN:
- case MBX_READ_LA:
case MBX_CLEAR_LA:
case MBX_DUMP_MEMORY:
case MBX_DUMP_CONTEXT:
@@ -1656,7 +2026,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
case MBX_READ_SPARM64:
case MBX_READ_RPI64:
case MBX_REG_LOGIN64:
- case MBX_READ_LA64:
+ case MBX_READ_TOPOLOGY:
case MBX_WRITE_WWN:
case MBX_SET_DEBUG:
case MBX_LOAD_EXP_ROM:
@@ -1746,11 +2116,6 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
kfree(mp);
}
- if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) &&
- (phba->sli_rev == LPFC_SLI_REV4) &&
- (pmb->u.mb.un.varUnregLogin.rsvd1 == 0x0))
- lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi);
-
/*
* If a REG_LOGIN succeeded after node is destroyed or node
* is in re-discovery driver need to cleanup the RPI.
@@ -3483,12 +3848,6 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
phba->pport->fc_myDID = 0;
phba->pport->fc_prevDID = 0;
- /* Turn off parity checking and serr during the physical reset */
- pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
- pci_write_config_word(phba->pcidev, PCI_COMMAND,
- (cfg_value &
- ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
-
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~(LPFC_PROCESS_LA);
phba->fcf.fcf_flag = 0;
@@ -3508,9 +3867,18 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
/* Now physically reset the device */
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"0389 Performing PCI function reset!\n");
+
+ /* Turn off parity checking and serr during the physical reset */
+ pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
+ pci_write_config_word(phba->pcidev, PCI_COMMAND, (cfg_value &
+ ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
+
/* Perform FCoE PCI function reset */
lpfc_pci_function_reset(phba);
+ /* Restore PCI cmd register */
+ pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value);
+
return 0;
}
@@ -4317,6 +4685,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
struct lpfc_vport *vport = phba->pport;
struct lpfc_dmabuf *mp;
+ /*
+ * TODO: Why does this routine execute these task in a different
+ * order from probe?
+ */
/* Perform a PCI function reset to start from clean */
rc = lpfc_pci_function_reset(phba);
if (unlikely(rc))
@@ -4357,13 +4729,16 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
}
rc = lpfc_sli4_read_rev(phba, mboxq, vpd, &vpd_size);
- if (unlikely(rc))
- goto out_free_vpd;
-
+ if (unlikely(rc)) {
+ kfree(vpd);
+ goto out_free_mbox;
+ }
mqe = &mboxq->u.mqe;
phba->sli_rev = bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev);
if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev))
- phba->hba_flag |= HBA_FCOE_SUPPORT;
+ phba->hba_flag |= HBA_FCOE_MODE;
+ else
+ phba->hba_flag &= ~HBA_FCOE_MODE;
if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) ==
LPFC_DCBX_CEE_MODE)
@@ -4372,13 +4747,14 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
phba->hba_flag &= ~HBA_FIP_SUPPORT;
if (phba->sli_rev != LPFC_SLI_REV4 ||
- !(phba->hba_flag & HBA_FCOE_SUPPORT)) {
+ !(phba->hba_flag & HBA_FCOE_MODE)) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"0376 READ_REV Error. SLI Level %d "
"FCoE enabled %d\n",
- phba->sli_rev, phba->hba_flag & HBA_FCOE_SUPPORT);
+ phba->sli_rev, phba->hba_flag & HBA_FCOE_MODE);
rc = -EIO;
- goto out_free_vpd;
+ kfree(vpd);
+ goto out_free_mbox;
}
/*
* Evaluate the read rev and vpd data. Populate the driver
@@ -4392,6 +4768,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
"Using defaults.\n", rc);
rc = 0;
}
+ kfree(vpd);
/* Save information as VPD data */
phba->vpd.rev.biuRev = mqe->un.read_rev.first_hw_rev;
@@ -4428,7 +4805,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
if (unlikely(rc)) {
rc = -EIO;
- goto out_free_vpd;
+ goto out_free_mbox;
}
/*
@@ -4476,7 +4853,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
if (rc) {
phba->link_state = LPFC_HBA_ERROR;
rc = -ENOMEM;
- goto out_free_vpd;
+ goto out_free_mbox;
}
mboxq->vport = vport;
@@ -4501,7 +4878,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
rc, bf_get(lpfc_mqe_status, mqe));
phba->link_state = LPFC_HBA_ERROR;
rc = -EIO;
- goto out_free_vpd;
+ goto out_free_mbox;
}
if (phba->cfg_soft_wwnn)
@@ -4526,7 +4903,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
"0582 Error %d during sgl post operation\n",
rc);
rc = -ENODEV;
- goto out_free_vpd;
+ goto out_free_mbox;
}
/* Register SCSI SGL pool to the device */
@@ -4538,7 +4915,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
/* Some Scsi buffers were moved to the abort scsi list */
/* A pci function reset will repost them */
rc = -ENODEV;
- goto out_free_vpd;
+ goto out_free_mbox;
}
/* Post the rpi header region to the device. */
@@ -4548,7 +4925,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
"0393 Error %d during rpi post operation\n",
rc);
rc = -ENODEV;
- goto out_free_vpd;
+ goto out_free_mbox;
}
/* Set up all the queues to the device */
@@ -4608,33 +4985,33 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
}
}
+ if (!(phba->hba_flag & HBA_FCOE_MODE)) {
+ /*
+ * The FC Port needs to register FCFI (index 0)
+ */
+ lpfc_reg_fcfi(phba, mboxq);
+ mboxq->vport = phba->pport;
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ if (rc == MBX_SUCCESS)
+ rc = 0;
+ else
+ goto out_unset_queue;
+ }
/*
* The port is ready, set the host's link state to LINK_DOWN
* in preparation for link interrupts.
*/
- lpfc_init_link(phba, mboxq, phba->cfg_topology, phba->cfg_link_speed);
- mboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
- lpfc_set_loopback_flag(phba);
- /* Change driver state to LPFC_LINK_DOWN right before init link */
spin_lock_irq(&phba->hbalock);
phba->link_state = LPFC_LINK_DOWN;
spin_unlock_irq(&phba->hbalock);
- rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
- if (unlikely(rc != MBX_NOT_FINISHED)) {
- kfree(vpd);
- return 0;
- } else
- rc = -EIO;
-
+ rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+out_unset_queue:
/* Unset all the queues set up in this routine when error out */
if (rc)
lpfc_sli4_queue_unset(phba);
-
out_stop_timers:
if (rc)
lpfc_stop_hba_timers(phba);
-out_free_vpd:
- kfree(vpd);
out_free_mbox:
mempool_free(mboxq, phba->mbox_mem_pool);
return rc;
@@ -5863,6 +6240,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
IOCB_t *icmd;
int numBdes = 0;
int i = 0;
+ uint32_t offset = 0; /* accumulated offset in the sg request list */
+ int inbound = 0; /* number of sg reply entries inbound from firmware */
if (!piocbq || !sglq)
return xritag;
@@ -5897,6 +6276,20 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
*/
bde.tus.w = le32_to_cpu(bpl->tus.w);
sgl->sge_len = cpu_to_le32(bde.tus.f.bdeSize);
+ /* The offsets in the sgl need to be accumulated
+ * separately for the request and reply lists.
+ * The request is always first, the reply follows.
+ */
+ if (piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) {
+ /* add up the reply sg entries */
+ if (bpl->tus.f.bdeFlags == BUFF_TYPE_BDE_64I)
+ inbound++;
+ /* first inbound? reset the offset */
+ if (inbound == 1)
+ offset = 0;
+ bf_set(lpfc_sli4_sge_offset, sgl, offset);
+ offset += bde.tus.f.bdeSize;
+ }
bpl++;
sgl++;
}
@@ -6028,11 +6421,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
bf_set(els_req64_vf, &wqe->els_req, 0);
/* And a VFID for word 12 */
bf_set(els_req64_vfid, &wqe->els_req, 0);
- /*
- * Set ct field to 3, indicates that the context_tag field
- * contains the FCFI and remote N_Port_ID is
- * in word 5.
- */
ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l);
bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
iocbq->iocb.ulpContext);
@@ -6140,6 +6528,18 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0);
break;
case CMD_GEN_REQUEST64_CR:
+ /* For this command calculate the xmit length of the
+ * request bde.
+ */
+ xmit_len = 0;
+ numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize /
+ sizeof(struct ulp_bde64);
+ for (i = 0; i < numBdes; i++) {
+ if (bpl[i].tus.f.bdeFlags != BUFF_TYPE_BDE_64)
+ break;
+ bde.tus.w = le32_to_cpu(bpl[i].tus.w);
+ xmit_len += bde.tus.f.bdeSize;
+ }
/* word3 iocb=IO_TAG wqe=request_payload_len */
wqe->gen_req.request_payload_len = xmit_len;
/* word4 iocb=parameter wqe=relative_offset memcpy */
@@ -6320,7 +6720,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
return IOCB_BUSY;
}
} else {
- sglq = __lpfc_sli_get_sglq(phba);
+ sglq = __lpfc_sli_get_sglq(phba, piocb);
if (!sglq) {
if (!(flag & SLI_IOCB_RET_IOCB)) {
__lpfc_sli_ringtx_put(phba,
@@ -8033,29 +8433,66 @@ static int
lpfc_sli4_eratt_read(struct lpfc_hba *phba)
{
uint32_t uerr_sta_hi, uerr_sta_lo;
+ uint32_t if_type, portsmphr;
+ struct lpfc_register portstat_reg;
- /* For now, use the SLI4 device internal unrecoverable error
+ /*
+ * For now, use the SLI4 device internal unrecoverable error
* registers for error attention. This can be changed later.
*/
- uerr_sta_lo = readl(phba->sli4_hba.UERRLOregaddr);
- uerr_sta_hi = readl(phba->sli4_hba.UERRHIregaddr);
- if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
- (~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
+ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+ switch (if_type) {
+ case LPFC_SLI_INTF_IF_TYPE_0:
+ uerr_sta_lo = readl(phba->sli4_hba.u.if_type0.UERRLOregaddr);
+ uerr_sta_hi = readl(phba->sli4_hba.u.if_type0.UERRHIregaddr);
+ if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
+ (~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "1423 HBA Unrecoverable error: "
+ "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
+ "ue_mask_lo_reg=0x%x, "
+ "ue_mask_hi_reg=0x%x\n",
+ uerr_sta_lo, uerr_sta_hi,
+ phba->sli4_hba.ue_mask_lo,
+ phba->sli4_hba.ue_mask_hi);
+ phba->work_status[0] = uerr_sta_lo;
+ phba->work_status[1] = uerr_sta_hi;
+ phba->work_ha |= HA_ERATT;
+ phba->hba_flag |= HBA_ERATT_HANDLED;
+ return 1;
+ }
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_2:
+ portstat_reg.word0 =
+ readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
+ portsmphr = readl(phba->sli4_hba.PSMPHRregaddr);
+ if (bf_get(lpfc_sliport_status_err, &portstat_reg)) {
+ phba->work_status[0] =
+ readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
+ phba->work_status[1] =
+ readl(phba->sli4_hba.u.if_type2.ERR2regaddr);
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2885 Port Error Detected: "
+ "port status reg 0x%x, "
+ "port smphr reg 0x%x, "
+ "error 1=0x%x, error 2=0x%x\n",
+ portstat_reg.word0,
+ portsmphr,
+ phba->work_status[0],
+ phba->work_status[1]);
+ phba->work_ha |= HA_ERATT;
+ phba->hba_flag |= HBA_ERATT_HANDLED;
+ return 1;
+ }
+ break;
+ case LPFC_SLI_INTF_IF_TYPE_1:
+ default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "1423 HBA Unrecoverable error: "
- "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
- "ue_mask_lo_reg=0x%x, ue_mask_hi_reg=0x%x\n",
- uerr_sta_lo, uerr_sta_hi,
- phba->sli4_hba.ue_mask_lo,
- phba->sli4_hba.ue_mask_hi);
- phba->work_status[0] = uerr_sta_lo;
- phba->work_status[1] = uerr_sta_hi;
- /* Set the driver HA work bitmap */
- phba->work_ha |= HA_ERATT;
- /* Indicate polling handles this ERATT */
- phba->hba_flag |= HBA_ERATT_HANDLED;
+ "2886 HBA Error Attention on unsupported "
+ "if type %d.", if_type);
return 1;
}
+
return 0;
}
@@ -8110,7 +8547,7 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba)
ha_copy = lpfc_sli_eratt_read(phba);
break;
case LPFC_SLI_REV4:
- /* Read devcie Uncoverable Error (UERR) registers */
+ /* Read device Uncoverable Error (UERR) registers */
ha_copy = lpfc_sli4_eratt_read(phba);
break;
default:
@@ -10155,16 +10592,20 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
length, LPFC_SLI4_MBX_EMBED);
mq_create_ext = &mbox->u.mqe.un.mq_create_ext;
- bf_set(lpfc_mbx_mq_create_ext_num_pages, &mq_create_ext->u.request,
- mq->page_count);
- bf_set(lpfc_mbx_mq_create_ext_async_evt_link, &mq_create_ext->u.request,
- 1);
- bf_set(lpfc_mbx_mq_create_ext_async_evt_fcfste,
+ bf_set(lpfc_mbx_mq_create_ext_num_pages,
+ &mq_create_ext->u.request, mq->page_count);
+ bf_set(lpfc_mbx_mq_create_ext_async_evt_link,
+ &mq_create_ext->u.request, 1);
+ bf_set(lpfc_mbx_mq_create_ext_async_evt_fip,
&mq_create_ext->u.request, 1);
bf_set(lpfc_mbx_mq_create_ext_async_evt_group5,
&mq_create_ext->u.request, 1);
- bf_set(lpfc_mq_context_cq_id, &mq_create_ext->u.request.context,
- cq->queue_id);
+ bf_set(lpfc_mbx_mq_create_ext_async_evt_fc,
+ &mq_create_ext->u.request, 1);
+ bf_set(lpfc_mbx_mq_create_ext_async_evt_sli,
+ &mq_create_ext->u.request, 1);
+ bf_set(lpfc_mq_context_cq_id,
+ &mq_create_ext->u.request.context, cq->queue_id);
bf_set(lpfc_mq_context_valid, &mq_create_ext->u.request.context, 1);
switch (mq->entry_count) {
default:
@@ -11137,7 +11578,8 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
static int
lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
{
- char *rctl_names[] = FC_RCTL_NAMES_INIT;
+ /* make rctl_names static to save stack space */
+ static char *rctl_names[] = FC_RCTL_NAMES_INIT;
char *type_names[] = FC_TYPE_NAMES_INIT;
struct fc_vft_header *fc_vft_hdr;
@@ -11538,6 +11980,10 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
"SID:x%x\n", oxid, sid);
return;
}
+ if (rxid >= phba->sli4_hba.max_cfg_param.xri_base
+ && rxid <= (phba->sli4_hba.max_cfg_param.max_xri
+ + phba->sli4_hba.max_cfg_param.xri_base))
+ lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0);
/* Allocate buffer for acc iocb */
ctiocb = lpfc_sli_get_iocbq(phba);
@@ -11560,6 +12006,7 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
icmd->ulpLe = 1;
icmd->ulpClass = CLASS3;
icmd->ulpContext = ndlp->nlp_rpi;
+ ctiocb->context1 = ndlp;
ctiocb->iocb_cmpl = NULL;
ctiocb->vport = phba->pport;
@@ -12129,42 +12576,37 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp)
/**
* lpfc_sli4_init_vpi - Initialize a vpi with the port
- * @phba: pointer to lpfc hba data structure.
- * @vpi: vpi value to activate with the port.
+ * @vport: Pointer to the vport for which the vpi is being initialized
*
- * This routine is invoked to activate a vpi with the
- * port when the host intends to use vports with a
- * nonzero vpi.
+ * This routine is invoked to activate a vpi with the port.
*
* Returns:
* 0 success
* -Evalue otherwise
**/
int
-lpfc_sli4_init_vpi(struct lpfc_hba *phba, uint16_t vpi)
+lpfc_sli4_init_vpi(struct lpfc_vport *vport)
{
LPFC_MBOXQ_t *mboxq;
int rc = 0;
int retval = MBX_SUCCESS;
uint32_t mbox_tmo;
-
- if (vpi == 0)
- return -EINVAL;
+ struct lpfc_hba *phba = vport->phba;
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq)
return -ENOMEM;
- lpfc_init_vpi(phba, mboxq, vpi);
+ lpfc_init_vpi(phba, mboxq, vport->vpi);
mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
"2022 INIT VPI Mailbox failed "
"status %d, mbxStatus x%x\n", rc,
bf_get(lpfc_mqe_status, &mboxq->u.mqe));
retval = -EIO;
}
if (rc != MBX_TIMEOUT)
- mempool_free(mboxq, phba->mbox_mem_pool);
+ mempool_free(mboxq, vport->phba->mbox_mem_pool);
return retval;
}
@@ -12854,6 +13296,7 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
struct lpfc_nodelist *act_mbx_ndlp = NULL;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
LIST_HEAD(mbox_cmd_list);
+ uint8_t restart_loop;
/* Clean up internally queued mailbox commands with the vport */
spin_lock_irq(&phba->hbalock);
@@ -12882,15 +13325,44 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
}
}
+ /* Cleanup any mailbox completions which are not yet processed */
+ do {
+ restart_loop = 0;
+ list_for_each_entry(mb, &phba->sli.mboxq_cmpl, list) {
+ /*
+ * If this mailox is already processed or it is
+ * for another vport ignore it.
+ */
+ if ((mb->vport != vport) ||
+ (mb->mbox_flag & LPFC_MBX_IMED_UNREG))
+ continue;
+
+ if ((mb->u.mb.mbxCommand != MBX_REG_LOGIN64) &&
+ (mb->u.mb.mbxCommand != MBX_REG_VPI))
+ continue;
+
+ mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+ if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+ ndlp = (struct lpfc_nodelist *)mb->context2;
+ /* Unregister the RPI when mailbox complete */
+ mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
+ restart_loop = 1;
+ spin_unlock_irq(&phba->hbalock);
+ spin_lock(shost->host_lock);
+ ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
+ spin_unlock(shost->host_lock);
+ spin_lock_irq(&phba->hbalock);
+ break;
+ }
+ }
+ } while (restart_loop);
+
spin_unlock_irq(&phba->hbalock);
/* Release the cleaned-up mailbox commands */
while (!list_empty(&mbox_cmd_list)) {
list_remove_head(&mbox_cmd_list, mb, LPFC_MBOXQ_t, list);
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);
@@ -12948,12 +13420,13 @@ lpfc_drain_txq(struct lpfc_hba *phba)
while (pring->txq_cnt) {
spin_lock_irqsave(&phba->hbalock, iflags);
- sglq = __lpfc_sli_get_sglq(phba);
+ piocbq = lpfc_sli_ringtx_get(phba, pring);
+ sglq = __lpfc_sli_get_sglq(phba, piocbq);
if (!sglq) {
+ __lpfc_sli_ringtx_put(phba, pring, piocbq);
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
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index cd56d6cce6c..453577c21c1 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -34,9 +34,11 @@ struct lpfc_cq_event {
union {
struct lpfc_mcqe mcqe_cmpl;
struct lpfc_acqe_link acqe_link;
- struct lpfc_acqe_fcoe acqe_fcoe;
+ struct lpfc_acqe_fip acqe_fip;
struct lpfc_acqe_dcbx acqe_dcbx;
struct lpfc_acqe_grp5 acqe_grp5;
+ struct lpfc_acqe_fc_la acqe_fc;
+ struct lpfc_acqe_sli acqe_sli;
struct lpfc_rcqe rcqe_cmpl;
struct sli4_wcqe_xri_aborted wcqe_axri;
struct lpfc_wcqe_complete wcqe_cmpl;
@@ -82,6 +84,7 @@ struct lpfc_iocbq {
struct lpfc_iocbq *rsp_iocb;
struct lpfcMboxq *mbox;
struct lpfc_nodelist *ndlp;
+ struct lpfc_node_rrq *rrq;
} context_un;
void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index c4483feb8b7..c7217d579e0 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -137,9 +137,11 @@ struct lpfc_sli4_link {
uint8_t speed;
uint8_t duplex;
uint8_t status;
- uint8_t physical;
+ uint8_t type;
+ uint8_t number;
uint8_t fault;
uint16_t logical_speed;
+ uint16_t topology;
};
struct lpfc_fcf_rec {
@@ -367,23 +369,39 @@ struct lpfc_sli4_hba {
PCI BAR1, control registers */
void __iomem *drbl_regs_memmap_p; /* Kernel memory mapped address for
PCI BAR2, doorbell registers */
- /* BAR0 PCI config space register memory map */
- void __iomem *UERRLOregaddr; /* Address to UERR_STATUS_LO register */
- void __iomem *UERRHIregaddr; /* Address to UERR_STATUS_HI register */
- void __iomem *UEMASKLOregaddr; /* Address to UE_MASK_LO register */
- void __iomem *UEMASKHIregaddr; /* Address to UE_MASK_HI register */
- void __iomem *SLIINTFregaddr; /* Address to SLI_INTF register */
- /* BAR1 FCoE function CSR register memory map */
- void __iomem *STAregaddr; /* Address to HST_STATE register */
- void __iomem *ISRregaddr; /* Address to HST_ISR register */
- void __iomem *IMRregaddr; /* Address to HST_IMR register */
- void __iomem *ISCRregaddr; /* Address to HST_ISCR register */
- /* BAR2 VF-0 doorbell register memory map */
- void __iomem *RQDBregaddr; /* Address to RQ_DOORBELL register */
- void __iomem *WQDBregaddr; /* Address to WQ_DOORBELL register */
- void __iomem *EQCQDBregaddr; /* Address to EQCQ_DOORBELL register */
- void __iomem *MQDBregaddr; /* Address to MQ_DOORBELL register */
- void __iomem *BMBXregaddr; /* Address to BootStrap MBX register */
+ union {
+ struct {
+ /* IF Type 0, BAR 0 PCI cfg space reg mem map */
+ void __iomem *UERRLOregaddr;
+ void __iomem *UERRHIregaddr;
+ void __iomem *UEMASKLOregaddr;
+ void __iomem *UEMASKHIregaddr;
+ } if_type0;
+ struct {
+ /* IF Type 2, BAR 0 PCI cfg space reg mem map. */
+ void __iomem *STATUSregaddr;
+ void __iomem *CTRLregaddr;
+ void __iomem *ERR1regaddr;
+ void __iomem *ERR2regaddr;
+ } if_type2;
+ } u;
+
+ /* IF type 0, BAR1 and if type 2, Bar 0 CSR register memory map */
+ void __iomem *PSMPHRregaddr;
+
+ /* Well-known SLI INTF register memory map. */
+ void __iomem *SLIINTFregaddr;
+
+ /* IF type 0, BAR 1 function CSR register memory map */
+ void __iomem *ISRregaddr; /* HST_ISR register */
+ void __iomem *IMRregaddr; /* HST_IMR register */
+ void __iomem *ISCRregaddr; /* HST_ISCR register */
+ /* IF type 0, BAR 0 and if type 2, BAR 0 doorbell register memory map */
+ void __iomem *RQDBregaddr; /* RQ_DOORBELL register */
+ void __iomem *WQDBregaddr; /* WQ_DOORBELL register */
+ void __iomem *EQCQDBregaddr; /* EQCQ_DOORBELL register */
+ void __iomem *MQDBregaddr; /* MQ_DOORBELL register */
+ void __iomem *BMBXregaddr; /* BootStrap MBX register */
uint32_t ue_mask_lo;
uint32_t ue_mask_hi;
@@ -466,6 +484,7 @@ struct lpfc_sglq {
struct list_head clist;
enum lpfc_sge_type buff_type; /* is this a scsi sgl */
enum lpfc_sgl_state state;
+ struct lpfc_nodelist *ndlp; /* ndlp associated with IO */
uint16_t iotag; /* pre-assigned IO tag */
uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */
struct sli4_sge *sgl; /* pre-assigned SGL */
@@ -532,7 +551,6 @@ 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 *);
@@ -548,7 +566,7 @@ int lpfc_sli4_brdreset(struct lpfc_hba *);
int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *);
void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *);
int lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *);
-int lpfc_sli4_init_vpi(struct lpfc_hba *, uint16_t);
+int lpfc_sli4_init_vpi(struct lpfc_vport *);
uint32_t lpfc_sli4_cq_release(struct lpfc_queue *, bool);
uint32_t lpfc_sli4_eq_release(struct lpfc_queue *, bool);
void lpfc_sli4_fcfi_unreg(struct lpfc_hba *, uint16_t);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 7a1b5b112a0..386cf92de49 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.18"
+#define LPFC_DRIVER_VERSION "8.3.20"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index a5281ce893d..6b8d2952e32 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -395,8 +395,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
* by the port.
*/
if ((phba->sli_rev == LPFC_SLI_REV4) &&
- (pport->fc_flag & FC_VFI_REGISTERED)) {
- rc = lpfc_sli4_init_vpi(phba, vpi);
+ (pport->fc_flag & FC_VFI_REGISTERED)) {
+ rc = lpfc_sli4_init_vpi(vport);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
"1838 Failed to INIT_VPI on vpi %d "
@@ -418,7 +418,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
if ((phba->link_state < LPFC_LINK_UP) ||
(pport->port_state < LPFC_FABRIC_CFG_LINK) ||
- (phba->fc_topology == TOPOLOGY_LOOP)) {
+ (phba->fc_topology == LPFC_TOPOLOGY_LOOP)) {
lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
rc = VPORT_OK;
goto out;
@@ -514,7 +514,7 @@ enable_vport(struct fc_vport *fc_vport)
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if ((phba->link_state < LPFC_LINK_UP) ||
- (phba->fc_topology == TOPOLOGY_LOOP)) {
+ (phba->fc_topology == LPFC_TOPOLOGY_LOOP)) {
lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
return VPORT_OK;
}
@@ -665,7 +665,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
phba->link_state >= LPFC_LINK_UP &&
- phba->fc_topology != TOPOLOGY_LOOP) {
+ phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
if (vport->cfg_enable_da_id) {
timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0))
diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile
index f469915b97c..5826ed509e3 100644
--- a/drivers/scsi/megaraid/Makefile
+++ b/drivers/scsi/megaraid/Makefile
@@ -1,3 +1,5 @@
obj-$(CONFIG_MEGARAID_MM) += megaraid_mm.o
obj-$(CONFIG_MEGARAID_MAILBOX) += megaraid_mbox.o
obj-$(CONFIG_MEGARAID_SAS) += megaraid_sas.o
+megaraid_sas-objs := megaraid_sas_base.o megaraid_sas_fusion.o \
+ megaraid_sas_fp.o
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index ad16f5e6004..1b5e375732c 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1,15 +1,30 @@
/*
+ * Linux MegaRAID driver for SAS based RAID controllers
*
- * Linux MegaRAID driver for SAS based RAID controllers
+ * Copyright (c) 2009-2011 LSI Corporation.
*
- * Copyright (c) 2003-2005 LSI Corporation.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * 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.
*
- * FILE : megaraid_sas.h
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * FILE: megaraid_sas.h
+ *
+ * Authors: LSI Corporation
+ *
+ * Send feedback to: <megaraidlinux@lsi.com>
+ *
+ * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ * ATTN: Linuxraid
*/
#ifndef LSI_MEGARAID_SAS_H
@@ -18,9 +33,9 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.04.31-rc1"
-#define MEGASAS_RELDATE "May 3, 2010"
-#define MEGASAS_EXT_VERSION "Mon. May 3, 11:41:51 PST 2010"
+#define MEGASAS_VERSION "00.00.05.29-rc1"
+#define MEGASAS_RELDATE "Dec. 7, 2010"
+#define MEGASAS_EXT_VERSION "Tue. Dec. 7 17:00:00 PDT 2010"
/*
* Device IDs
@@ -32,6 +47,7 @@
#define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079
#define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073
#define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071
+#define PCI_DEVICE_ID_LSI_FUSION 0x005b
/*
* =====================================
@@ -421,7 +437,6 @@ struct megasas_ctrl_prop {
* Add properties that can be controlled by
* a bit in the following structure.
*/
-
struct {
u32 copyBackDisabled : 1;
u32 SMARTerEnabled : 1;
@@ -701,6 +716,7 @@ struct megasas_ctrl_info {
#define MEGASAS_DEFAULT_INIT_ID -1
#define MEGASAS_MAX_LUN 8
#define MEGASAS_MAX_LD 64
+#define MEGASAS_DEFAULT_CMD_PER_LUN 128
#define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \
MEGASAS_MAX_DEV_PER_CHANNEL)
#define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \
@@ -769,7 +785,10 @@ struct megasas_ctrl_info {
*/
struct megasas_register_set {
- u32 reserved_0[4]; /*0000h*/
+ u32 doorbell; /*0000h*/
+ u32 fusion_seq_offset; /*0004h*/
+ u32 fusion_host_diag; /*0008h*/
+ u32 reserved_01; /*000Ch*/
u32 inbound_msg_0; /*0010h*/
u32 inbound_msg_1; /*0014h*/
@@ -789,15 +808,18 @@ struct megasas_register_set {
u32 inbound_queue_port; /*0040h*/
u32 outbound_queue_port; /*0044h*/
- u32 reserved_2[22]; /*0048h*/
+ u32 reserved_2[9]; /*0048h*/
+ u32 reply_post_host_index; /*006Ch*/
+ u32 reserved_2_2[12]; /*0070h*/
u32 outbound_doorbell_clear; /*00A0h*/
u32 reserved_3[3]; /*00A4h*/
u32 outbound_scratch_pad ; /*00B0h*/
+ u32 outbound_scratch_pad_2; /*00B4h*/
- u32 reserved_4[3]; /*00B4h*/
+ u32 reserved_4[2]; /*00B8h*/
u32 inbound_low_queue_port ; /*00C0h*/
@@ -1272,6 +1294,9 @@ struct megasas_instance {
u16 max_num_sge;
u16 max_fw_cmds;
+ /* For Fusion its num IOCTL cmds, for others MFI based its
+ max_fw_cmds */
+ u16 max_mfi_cmds;
u32 max_sectors_per_req;
struct megasas_aen_event *ev;
@@ -1320,6 +1345,16 @@ struct megasas_instance {
struct timer_list io_completion_timer;
struct list_head internal_reset_pending_q;
+
+ /* Ptr to hba specfic information */
+ void *ctrl_context;
+ u8 msi_flag;
+ struct msix_entry msixentry;
+ u64 map_id;
+ struct megasas_cmd *map_update_cmd;
+ unsigned long bar;
+ long reset_flags;
+ struct mutex reset_mutex;
};
enum {
@@ -1345,6 +1380,13 @@ struct megasas_instance_template {
struct megasas_register_set __iomem *);
int (*check_reset)(struct megasas_instance *, \
struct megasas_register_set __iomem *);
+ irqreturn_t (*service_isr)(int irq, void *devp);
+ void (*tasklet)(unsigned long);
+ u32 (*init_adapter)(struct megasas_instance *);
+ u32 (*build_and_issue_cmd) (struct megasas_instance *,
+ struct scsi_cmnd *);
+ void (*issue_dcmd) (struct megasas_instance *instance,
+ struct megasas_cmd *cmd);
};
#define MEGASAS_IS_LOGICAL(scp) \
@@ -1371,7 +1413,13 @@ struct megasas_cmd {
struct list_head list;
struct scsi_cmnd *scmd;
struct megasas_instance *instance;
- u32 frame_count;
+ union {
+ struct {
+ u16 smid;
+ u16 resvd;
+ } context;
+ u32 frame_count;
+ };
};
#define MAX_MGMT_ADAPTERS 1024
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 7451bc096a0..5d6d07bd1cd 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -1,27 +1,34 @@
/*
+ * Linux MegaRAID driver for SAS based RAID controllers
*
- * Linux MegaRAID driver for SAS based RAID controllers
+ * Copyright (c) 2009-2011 LSI Corporation.
*
- * Copyright (c) 2003-2005 LSI Corporation.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * 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.
*
- * FILE : megaraid_sas.c
- * Version : v00.00.04.31-rc1
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Authors:
- * (email-id : megaraidlinux@lsi.com)
- * Sreenivas Bagalkote
- * Sumant Patro
- * Bo Yang
+ * FILE: megaraid_sas_base.c
+ * Version : v00.00.05.29-rc1
*
- * List of supported controllers
+ * Authors: LSI Corporation
+ * Sreenivas Bagalkote
+ * Sumant Patro
+ * Bo Yang
*
- * OEM Product Name VID DID SSVID SSID
- * --- ------------ --- --- ---- ----
+ * Send feedback to: <megaraidlinux@lsi.com>
+ *
+ * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ * ATTN: Linuxraid
*/
#include <linux/kernel.h>
@@ -46,6 +53,7 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include "megaraid_sas_fusion.h"
#include "megaraid_sas.h"
/*
@@ -65,12 +73,16 @@ module_param_named(max_sectors, max_sectors, int, 0);
MODULE_PARM_DESC(max_sectors,
"Maximum number of sectors per IO command");
+static int msix_disable;
+module_param(msix_disable, int, S_IRUGO);
+MODULE_PARM_DESC(msix_disable, "Disable MSI-X interrupt handling. Default: 0");
+
MODULE_LICENSE("GPL");
MODULE_VERSION(MEGASAS_VERSION);
MODULE_AUTHOR("megaraidlinux@lsi.com");
MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
-static int megasas_transition_to_ready(struct megasas_instance *instance);
+int megasas_transition_to_ready(struct megasas_instance *instance);
static int megasas_get_pd_list(struct megasas_instance *instance);
static int megasas_issue_init_mfi(struct megasas_instance *instance);
static int megasas_register_aen(struct megasas_instance *instance,
@@ -98,6 +110,8 @@ static struct pci_device_id megasas_pci_table[] = {
/* xscale IOP, vega */
{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
/* xscale IOP */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)},
+ /* Fusion */
{}
};
@@ -111,23 +125,55 @@ static DEFINE_MUTEX(megasas_async_queue_mutex);
static int megasas_poll_wait_aen;
static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
static u32 support_poll_for_event;
-static u32 megasas_dbg_lvl;
+u32 megasas_dbg_lvl;
static u32 support_device_change;
/* define lock for aen poll */
spinlock_t poll_aen_lock;
-static void
+void
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
u8 alt_status);
+static irqreturn_t megasas_isr(int irq, void *devp);
+static u32
+megasas_init_adapter_mfi(struct megasas_instance *instance);
+u32
+megasas_build_and_issue_cmd(struct megasas_instance *instance,
+ struct scsi_cmnd *scmd);
+static void megasas_complete_cmd_dpc(unsigned long instance_addr);
+void
+megasas_release_fusion(struct megasas_instance *instance);
+int
+megasas_ioc_init_fusion(struct megasas_instance *instance);
+void
+megasas_free_cmds_fusion(struct megasas_instance *instance);
+u8
+megasas_get_map_info(struct megasas_instance *instance);
+int
+megasas_sync_map_info(struct megasas_instance *instance);
+int
+wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
+void megasas_reset_reply_desc(struct megasas_instance *instance);
+u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
+ struct LD_LOAD_BALANCE_INFO *lbInfo);
+int megasas_reset_fusion(struct Scsi_Host *shost);
+void megasas_fusion_ocr_wq(struct work_struct *work);
+
+void
+megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+ instance->instancet->fire_cmd(instance,
+ cmd->frame_phys_addr, 0, instance->reg_set);
+}
+
/**
* megasas_get_cmd - Get a command from the free pool
* @instance: Adapter soft state
*
* Returns a free command from the pool
*/
-static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+struct megasas_cmd *megasas_get_cmd(struct megasas_instance
*instance)
{
unsigned long flags;
@@ -152,7 +198,7 @@ static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
* @instance: Adapter soft state
* @cmd: Command packet to be returned to free command pool
*/
-static inline void
+inline void
megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
{
unsigned long flags;
@@ -160,6 +206,7 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
spin_lock_irqsave(&instance->cmd_pool_lock, flags);
cmd->scmd = NULL;
+ cmd->frame_count = 0;
list_add_tail(&cmd->list, &instance->cmd_pool);
spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
@@ -167,7 +214,7 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
/**
-* The following functions are defined for xscale
+* The following functions are defined for xscale
* (deviceid : 1064R, PERC5) controllers
*/
@@ -210,7 +257,7 @@ megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs)
* megasas_clear_interrupt_xscale - Check & clear interrupt
* @regs: MFI register set
*/
-static int
+static int
megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
{
u32 status;
@@ -243,7 +290,7 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
* @frame_count : Number of frames for the command
* @regs : MFI register set
*/
-static inline void
+static inline void
megasas_fire_cmd_xscale(struct megasas_instance *instance,
dma_addr_t frame_phys_addr,
u32 frame_count,
@@ -323,15 +370,20 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
.adp_reset = megasas_adp_reset_xscale,
.check_reset = megasas_check_reset_xscale,
+ .service_isr = megasas_isr,
+ .tasklet = megasas_complete_cmd_dpc,
+ .init_adapter = megasas_init_adapter_mfi,
+ .build_and_issue_cmd = megasas_build_and_issue_cmd,
+ .issue_dcmd = megasas_issue_dcmd,
};
/**
-* This is the end of set of functions & definitions specific
+* This is the end of set of functions & definitions specific
* to xscale (deviceid : 1064R, PERC5) controllers
*/
/**
-* The following functions are defined for ppc (deviceid : 0x60)
+* The following functions are defined for ppc (deviceid : 0x60)
* controllers
*/
@@ -343,7 +395,7 @@ static inline void
megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
{
writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
-
+
writel(~0x80000000, &(regs)->outbound_intr_mask);
/* Dummy readl to force pci flush */
@@ -377,7 +429,7 @@ megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
* megasas_clear_interrupt_ppc - Check & clear interrupt
* @regs: MFI register set
*/
-static int
+static int
megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
{
u32 status;
@@ -406,7 +458,7 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
* @frame_count : Number of frames for the command
* @regs : MFI register set
*/
-static inline void
+static inline void
megasas_fire_cmd_ppc(struct megasas_instance *instance,
dma_addr_t frame_phys_addr,
u32 frame_count,
@@ -414,7 +466,7 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance,
{
unsigned long flags;
spin_lock_irqsave(&instance->hba_lock, flags);
- writel((frame_phys_addr | (frame_count<<1))|1,
+ writel((frame_phys_addr | (frame_count<<1))|1,
&(regs)->inbound_queue_port);
spin_unlock_irqrestore(&instance->hba_lock, flags);
}
@@ -441,7 +493,7 @@ megasas_check_reset_ppc(struct megasas_instance *instance,
return 0;
}
static struct megasas_instance_template megasas_instance_template_ppc = {
-
+
.fire_cmd = megasas_fire_cmd_ppc,
.enable_intr = megasas_enable_intr_ppc,
.disable_intr = megasas_disable_intr_ppc,
@@ -449,6 +501,11 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
.adp_reset = megasas_adp_reset_ppc,
.check_reset = megasas_check_reset_ppc,
+ .service_isr = megasas_isr,
+ .tasklet = megasas_complete_cmd_dpc,
+ .init_adapter = megasas_init_adapter_mfi,
+ .build_and_issue_cmd = megasas_build_and_issue_cmd,
+ .issue_dcmd = megasas_issue_dcmd,
};
/**
@@ -570,6 +627,11 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
.adp_reset = megasas_adp_reset_skinny,
.check_reset = megasas_check_reset_skinny,
+ .service_isr = megasas_isr,
+ .tasklet = megasas_complete_cmd_dpc,
+ .init_adapter = megasas_init_adapter_mfi,
+ .build_and_issue_cmd = megasas_build_and_issue_cmd,
+ .issue_dcmd = megasas_issue_dcmd,
};
@@ -744,6 +806,11 @@ static struct megasas_instance_template megasas_instance_template_gen2 = {
.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
.adp_reset = megasas_adp_reset_gen2,
.check_reset = megasas_check_reset_gen2,
+ .service_isr = megasas_isr,
+ .tasklet = megasas_complete_cmd_dpc,
+ .init_adapter = megasas_init_adapter_mfi,
+ .build_and_issue_cmd = megasas_build_and_issue_cmd,
+ .issue_dcmd = megasas_issue_dcmd,
};
/**
@@ -751,18 +818,21 @@ static struct megasas_instance_template megasas_instance_template_gen2 = {
* specific to gen2 (deviceid : 0x78, 0x79) controllers
*/
+/*
+ * Template added for TB (Fusion)
+ */
+extern struct megasas_instance_template megasas_instance_template_fusion;
+
/**
* megasas_issue_polled - Issues a polling command
* @instance: Adapter soft state
- * @cmd: Command packet to be issued
+ * @cmd: Command packet to be issued
*
* For polling, MFI requires the cmd_status to be set to 0xFF before posting.
*/
-static int
+int
megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
{
- int i;
- u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
struct megasas_header *frame_hdr = &cmd->frame->hdr;
@@ -772,21 +842,12 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
/*
* Issue the frame using inbound queue port
*/
- instance->instancet->fire_cmd(instance,
- cmd->frame_phys_addr, 0, instance->reg_set);
+ instance->instancet->issue_dcmd(instance, cmd);
/*
* Wait for cmd_status to change
*/
- for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) {
- rmb();
- msleep(1);
- }
-
- if (frame_hdr->cmd_status == 0xff)
- return -ETIME;
-
- return 0;
+ return wait_and_poll(instance, cmd);
}
/**
@@ -804,8 +865,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance,
{
cmd->cmd_status = ENODATA;
- instance->instancet->fire_cmd(instance,
- cmd->frame_phys_addr, 0, instance->reg_set);
+ instance->instancet->issue_dcmd(instance, cmd);
wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
@@ -849,8 +909,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
cmd->sync_cmd = 1;
cmd->cmd_status = 0xFF;
- instance->instancet->fire_cmd(instance,
- cmd->frame_phys_addr, 0, instance->reg_set);
+ instance->instancet->issue_dcmd(instance, cmd);
/*
* Wait for this cmd to complete
@@ -1242,11 +1301,11 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
/**
* megasas_is_ldio - Checks if the cmd is for logical drive
* @scmd: SCSI command
- *
+ *
* Called by megasas_queue_command to find out if the command to be queued
- * is a logical drive command
+ * is a logical drive command
*/
-static inline int megasas_is_ldio(struct scsi_cmnd *cmd)
+inline int megasas_is_ldio(struct scsi_cmnd *cmd)
{
if (!MEGASAS_IS_LOGICAL(cmd))
return 0;
@@ -1328,6 +1387,51 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
}
+u32
+megasas_build_and_issue_cmd(struct megasas_instance *instance,
+ struct scsi_cmnd *scmd)
+{
+ struct megasas_cmd *cmd;
+ u32 frame_count;
+
+ cmd = megasas_get_cmd(instance);
+ if (!cmd)
+ return SCSI_MLQUEUE_HOST_BUSY;
+
+ /*
+ * Logical drive command
+ */
+ if (megasas_is_ldio(scmd))
+ frame_count = megasas_build_ldio(instance, scmd, cmd);
+ else
+ frame_count = megasas_build_dcdb(instance, scmd, cmd);
+
+ if (!frame_count)
+ goto out_return_cmd;
+
+ cmd->scmd = scmd;
+ scmd->SCp.ptr = (char *)cmd;
+
+ /*
+ * Issue the command to the FW
+ */
+ atomic_inc(&instance->fw_outstanding);
+
+ instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
+ cmd->frame_count-1, instance->reg_set);
+ /*
+ * Check if we have pend cmds to be completed
+ */
+ if (poll_mode_io && atomic_read(&instance->fw_outstanding))
+ tasklet_schedule(&instance->isr_tasklet);
+
+ return 0;
+out_return_cmd:
+ megasas_return_cmd(instance, cmd);
+ return 1;
+}
+
+
/**
* megasas_queue_command - Queue entry point
* @scmd: SCSI command to be queued
@@ -1336,8 +1440,6 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
static int
megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
{
- u32 frame_count;
- struct megasas_cmd *cmd;
struct megasas_instance *instance;
unsigned long flags;
@@ -1376,42 +1478,13 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd
break;
}
- cmd = megasas_get_cmd(instance);
- if (!cmd)
+ if (instance->instancet->build_and_issue_cmd(instance, scmd)) {
+ printk(KERN_ERR "megasas: Err returned from build_and_issue_cmd\n");
return SCSI_MLQUEUE_HOST_BUSY;
-
- /*
- * Logical drive command
- */
- if (megasas_is_ldio(scmd))
- frame_count = megasas_build_ldio(instance, scmd, cmd);
- else
- frame_count = megasas_build_dcdb(instance, scmd, cmd);
-
- if (!frame_count)
- goto out_return_cmd;
-
- cmd->scmd = scmd;
- scmd->SCp.ptr = (char *)cmd;
-
- /*
- * Issue the command to the FW
- */
- atomic_inc(&instance->fw_outstanding);
-
- instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
- cmd->frame_count-1, instance->reg_set);
- /*
- * Check if we have pend cmds to be completed
- */
- if (poll_mode_io && atomic_read(&instance->fw_outstanding))
- tasklet_schedule(&instance->isr_tasklet);
-
+ }
return 0;
- out_return_cmd:
- megasas_return_cmd(instance, cmd);
out_done:
done(scmd);
return 0;
@@ -1492,15 +1565,44 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
return 0;
}
-static void megaraid_sas_kill_hba(struct megasas_instance *instance)
+void megaraid_sas_kill_hba(struct megasas_instance *instance)
{
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
- writel(MFI_STOP_ADP,
- &instance->reg_set->reserved_0[0]);
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)) {
+ writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
} else {
- writel(MFI_STOP_ADP,
- &instance->reg_set->inbound_doorbell);
+ writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
+ }
+}
+
+ /**
+ * megasas_check_and_restore_queue_depth - Check if queue depth needs to be
+ * restored to max value
+ * @instance: Adapter soft state
+ *
+ */
+void
+megasas_check_and_restore_queue_depth(struct megasas_instance *instance)
+{
+ unsigned long flags;
+ if (instance->flag & MEGASAS_FW_BUSY
+ && time_after(jiffies, instance->last_time + 5 * HZ)
+ && atomic_read(&instance->fw_outstanding) < 17) {
+
+ spin_lock_irqsave(instance->host->host_lock, flags);
+ instance->flag &= ~MEGASAS_FW_BUSY;
+ if ((instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+ instance->host->can_queue =
+ instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
+ } else
+ instance->host->can_queue =
+ instance->max_fw_cmds - MEGASAS_INT_CMDS;
+
+ spin_unlock_irqrestore(instance->host->host_lock, flags);
}
}
@@ -1554,24 +1656,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
/*
* Check if we can restore can_queue
*/
- if (instance->flag & MEGASAS_FW_BUSY
- && time_after(jiffies, instance->last_time + 5 * HZ)
- && atomic_read(&instance->fw_outstanding) < 17) {
-
- spin_lock_irqsave(instance->host->host_lock, flags);
- instance->flag &= ~MEGASAS_FW_BUSY;
- if ((instance->pdev->device ==
- PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
- instance->host->can_queue =
- instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
- } else
- instance->host->can_queue =
- instance->max_fw_cmds - MEGASAS_INT_CMDS;
-
- spin_unlock_irqrestore(instance->host->host_lock, flags);
- }
+ megasas_check_and_restore_queue_depth(instance);
}
static void
@@ -1749,7 +1834,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
(instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
writel(MFI_STOP_ADP,
- &instance->reg_set->reserved_0[0]);
+ &instance->reg_set->doorbell);
} else {
writel(MFI_STOP_ADP,
&instance->reg_set->inbound_doorbell);
@@ -1853,11 +1938,16 @@ static int megasas_reset_device(struct scsi_cmnd *scmd)
static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
{
int ret;
+ struct megasas_instance *instance;
+ instance = (struct megasas_instance *)scmd->device->host->hostdata;
/*
* First wait for all commands to complete
*/
- ret = megasas_generic_reset(scmd);
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ ret = megasas_reset_fusion(scmd->device->host);
+ else
+ ret = megasas_generic_reset(scmd);
return ret;
}
@@ -2000,8 +2090,8 @@ megasas_complete_int_cmd(struct megasas_instance *instance,
* @instance: Adapter soft state
* @cmd: Cmd that was issued to abort another cmd
*
- * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q
- * after it issues an abort on a previously issued command. This function
+ * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q
+ * after it issues an abort on a previously issued command. This function
* wakes up all functions waiting on the same wait queue.
*/
static void
@@ -2021,19 +2111,20 @@ megasas_complete_abort(struct megasas_instance *instance,
* megasas_complete_cmd - Completes a command
* @instance: Adapter soft state
* @cmd: Command to be completed
- * @alt_status: If non-zero, use this value as status to
+ * @alt_status: If non-zero, use this value as status to
* SCSI mid-layer instead of the value returned
* by the FW. This should be used if caller wants
* an alternate status (as in the case of aborted
* commands)
*/
-static void
+void
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
u8 alt_status)
{
int exception = 0;
struct megasas_header *hdr = &cmd->frame->hdr;
unsigned long flags;
+ struct fusion_context *fusion = instance->ctrl_context;
/* flag for the retry reset */
cmd->retry_for_fw_reset = 0;
@@ -2126,6 +2217,37 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
case MFI_CMD_SMP:
case MFI_CMD_STP:
case MFI_CMD_DCMD:
+ /* Check for LD map update */
+ if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) &&
+ (cmd->frame->dcmd.mbox.b[1] == 1)) {
+ spin_lock_irqsave(instance->host->host_lock, flags);
+ if (cmd->frame->hdr.cmd_status != 0) {
+ if (cmd->frame->hdr.cmd_status !=
+ MFI_STAT_NOT_FOUND)
+ printk(KERN_WARNING "megasas: map sync"
+ "failed, status = 0x%x.\n",
+ cmd->frame->hdr.cmd_status);
+ else {
+ megasas_return_cmd(instance, cmd);
+ spin_unlock_irqrestore(
+ instance->host->host_lock,
+ flags);
+ break;
+ }
+ } else
+ instance->map_id++;
+ megasas_return_cmd(instance, cmd);
+ if (MR_ValidateMapInfo(
+ fusion->ld_map[(instance->map_id & 1)],
+ fusion->load_balance_info))
+ fusion->fast_path_io = 1;
+ else
+ fusion->fast_path_io = 0;
+ megasas_sync_map_info(instance);
+ spin_unlock_irqrestore(instance->host->host_lock,
+ flags);
+ break;
+ }
if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
spin_lock_irqsave(&poll_aen_lock, flags);
@@ -2464,7 +2586,7 @@ static irqreturn_t megasas_isr(int irq, void *devp)
* states, driver must take steps to bring it to ready state. Otherwise, it
* has to wait for the ready state.
*/
-static int
+int
megasas_transition_to_ready(struct megasas_instance* instance)
{
int i;
@@ -2476,8 +2598,8 @@ megasas_transition_to_ready(struct megasas_instance* instance)
fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
if (fw_state != MFI_STATE_READY)
- printk(KERN_INFO "megasas: Waiting for FW to come to ready"
- " state\n");
+ printk(KERN_INFO "megasas: Waiting for FW to come to ready"
+ " state\n");
while (fw_state != MFI_STATE_READY) {
@@ -2498,11 +2620,12 @@ megasas_transition_to_ready(struct megasas_instance* instance)
if ((instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-
+ PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FUSION)) {
writel(
MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
- &instance->reg_set->reserved_0[0]);
+ &instance->reg_set->doorbell);
} else {
writel(
MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
@@ -2515,11 +2638,13 @@ megasas_transition_to_ready(struct megasas_instance* instance)
case MFI_STATE_BOOT_MESSAGE_PENDING:
if ((instance->pdev->device ==
- PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
- (instance->pdev->device ==
- PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+ PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FUSION)) {
writel(MFI_INIT_HOTPLUG,
- &instance->reg_set->reserved_0[0]);
+ &instance->reg_set->doorbell);
} else
writel(MFI_INIT_HOTPLUG,
&instance->reg_set->inbound_doorbell);
@@ -2536,9 +2661,23 @@ megasas_transition_to_ready(struct megasas_instance* instance)
if ((instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device ==
- PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+ PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+ (instance->pdev->device
+ == PCI_DEVICE_ID_LSI_FUSION)) {
writel(MFI_RESET_FLAGS,
- &instance->reg_set->reserved_0[0]);
+ &instance->reg_set->doorbell);
+ if (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_FUSION) {
+ for (i = 0; i < (10 * 1000); i += 20) {
+ if (readl(
+ &instance->
+ reg_set->
+ doorbell) & 1)
+ msleep(20);
+ else
+ break;
+ }
+ }
} else
writel(MFI_RESET_FLAGS,
&instance->reg_set->inbound_doorbell);
@@ -2590,7 +2729,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
* The cur_state should not last for more than max_wait secs
*/
for (i = 0; i < (max_wait * 1000); i++) {
- fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &
+ fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &
MFI_STATE_MASK ;
curr_abs_state =
instance->instancet->read_fw_status_reg(instance->reg_set);
@@ -2610,7 +2749,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
return -ENODEV;
}
}
- printk(KERN_INFO "megasas: FW now in Ready state\n");
+ printk(KERN_INFO "megasas: FW now in Ready state\n");
return 0;
}
@@ -2622,7 +2761,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
static void megasas_teardown_frame_pool(struct megasas_instance *instance)
{
int i;
- u32 max_cmd = instance->max_fw_cmds;
+ u32 max_cmd = instance->max_mfi_cmds;
struct megasas_cmd *cmd;
if (!instance->frame_dma_pool)
@@ -2673,7 +2812,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
u32 frame_count;
struct megasas_cmd *cmd;
- max_cmd = instance->max_fw_cmds;
+ max_cmd = instance->max_mfi_cmds;
/*
* Size of our frame is 64 bytes for MFI frame, followed by max SG
@@ -2760,14 +2899,15 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
* megasas_free_cmds - Free all the cmds in the free cmd pool
* @instance: Adapter soft state
*/
-static void megasas_free_cmds(struct megasas_instance *instance)
+void megasas_free_cmds(struct megasas_instance *instance)
{
int i;
/* First free the MFI frame pool */
megasas_teardown_frame_pool(instance);
/* Free all the commands in the cmd_list */
- for (i = 0; i < instance->max_fw_cmds; i++)
+ for (i = 0; i < instance->max_mfi_cmds; i++)
+
kfree(instance->cmd_list[i]);
/* Free the cmd_list buffer itself */
@@ -2795,14 +2935,14 @@ static void megasas_free_cmds(struct megasas_instance *instance)
* This array is used only to look up the megasas_cmd given the context. The
* free commands themselves are maintained in a linked list called cmd_pool.
*/
-static int megasas_alloc_cmds(struct megasas_instance *instance)
+int megasas_alloc_cmds(struct megasas_instance *instance)
{
int i;
int j;
u32 max_cmd;
struct megasas_cmd *cmd;
- max_cmd = instance->max_fw_cmds;
+ max_cmd = instance->max_mfi_cmds;
/*
* instance->cmd_list is an array of struct megasas_cmd pointers.
@@ -2816,6 +2956,7 @@ static int megasas_alloc_cmds(struct megasas_instance *instance)
return -ENOMEM;
}
+ memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) *max_cmd);
for (i = 0; i < max_cmd; i++) {
instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd),
@@ -3210,76 +3351,15 @@ megasas_io_completion_timer(unsigned long instance_addr)
jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
}
-/**
- * megasas_init_mfi - Initializes the FW
- * @instance: Adapter soft state
- *
- * This is the main function for initializing MFI firmware.
- */
-static int megasas_init_mfi(struct megasas_instance *instance)
+static u32
+megasas_init_adapter_mfi(struct megasas_instance *instance)
{
+ struct megasas_register_set __iomem *reg_set;
u32 context_sz;
u32 reply_q_sz;
- u32 max_sectors_1;
- u32 max_sectors_2;
- u32 tmp_sectors;
- struct megasas_register_set __iomem *reg_set;
- struct megasas_ctrl_info *ctrl_info;
- /*
- * Map the message registers
- */
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
- instance->base_addr = pci_resource_start(instance->pdev, 1);
- } else {
- instance->base_addr = pci_resource_start(instance->pdev, 0);
- }
-
- if (pci_request_selected_regions(instance->pdev,
- pci_select_bars(instance->pdev, IORESOURCE_MEM),
- "megasas: LSI")) {
- printk(KERN_DEBUG "megasas: IO memory region busy!\n");
- return -EBUSY;
- }
-
- instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
-
- if (!instance->reg_set) {
- printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
- goto fail_ioremap;
- }
reg_set = instance->reg_set;
- switch(instance->pdev->device)
- {
- case PCI_DEVICE_ID_LSI_SAS1078R:
- case PCI_DEVICE_ID_LSI_SAS1078DE:
- instance->instancet = &megasas_instance_template_ppc;
- break;
- case PCI_DEVICE_ID_LSI_SAS1078GEN2:
- case PCI_DEVICE_ID_LSI_SAS0079GEN2:
- instance->instancet = &megasas_instance_template_gen2;
- break;
- case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
- case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
- instance->instancet = &megasas_instance_template_skinny;
- break;
- case PCI_DEVICE_ID_LSI_SAS1064R:
- case PCI_DEVICE_ID_DELL_PERC5:
- default:
- instance->instancet = &megasas_instance_template_xscale;
- break;
- }
-
- /*
- * We expect the FW state to be READY
- */
- if (megasas_transition_to_ready(instance))
- goto fail_ready_state;
-
/*
* Get various operational parameters from status register
*/
@@ -3290,7 +3370,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
* does not exceed max cmds that the FW can support
*/
instance->max_fw_cmds = instance->max_fw_cmds-1;
- instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >>
+ instance->max_mfi_cmds = instance->max_fw_cmds;
+ instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >>
0x10;
/*
* Create a pool of commands
@@ -3333,6 +3414,90 @@ static int megasas_init_mfi(struct megasas_instance *instance)
if (instance->fw_support_ieee)
instance->flag_ieee = 1;
+ return 0;
+
+fail_fw_init:
+
+ pci_free_consistent(instance->pdev, reply_q_sz,
+ instance->reply_queue, instance->reply_queue_h);
+fail_reply_queue:
+ megasas_free_cmds(instance);
+
+fail_alloc_cmds:
+ iounmap(instance->reg_set);
+ return 1;
+}
+
+/**
+ * megasas_init_fw - Initializes the FW
+ * @instance: Adapter soft state
+ *
+ * This is the main function for initializing firmware
+ */
+
+static int megasas_init_fw(struct megasas_instance *instance)
+{
+ u32 max_sectors_1;
+ u32 max_sectors_2;
+ u32 tmp_sectors;
+ struct megasas_register_set __iomem *reg_set;
+ struct megasas_ctrl_info *ctrl_info;
+ unsigned long bar_list;
+
+ /* Find first memory bar */
+ bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
+ instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
+ instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
+ if (pci_request_selected_regions(instance->pdev, instance->bar,
+ "megasas: LSI")) {
+ printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+ return -EBUSY;
+ }
+
+ instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
+
+ if (!instance->reg_set) {
+ printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
+ goto fail_ioremap;
+ }
+
+ reg_set = instance->reg_set;
+
+ switch (instance->pdev->device) {
+ case PCI_DEVICE_ID_LSI_FUSION:
+ instance->instancet = &megasas_instance_template_fusion;
+ break;
+ case PCI_DEVICE_ID_LSI_SAS1078R:
+ case PCI_DEVICE_ID_LSI_SAS1078DE:
+ instance->instancet = &megasas_instance_template_ppc;
+ break;
+ case PCI_DEVICE_ID_LSI_SAS1078GEN2:
+ case PCI_DEVICE_ID_LSI_SAS0079GEN2:
+ instance->instancet = &megasas_instance_template_gen2;
+ break;
+ case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
+ case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
+ instance->instancet = &megasas_instance_template_skinny;
+ break;
+ case PCI_DEVICE_ID_LSI_SAS1064R:
+ case PCI_DEVICE_ID_DELL_PERC5:
+ default:
+ instance->instancet = &megasas_instance_template_xscale;
+ break;
+ }
+
+ /*
+ * We expect the FW state to be READY
+ */
+ if (megasas_transition_to_ready(instance))
+ goto fail_ready_state;
+
+ /* Get operational params, sge flags, send init cmd to controller */
+ if (instance->instancet->init_adapter(instance))
+ return -ENODEV;
+
+ printk(KERN_ERR "megasas: INIT adapter done\n");
+
/** for passthrough
* the following function will get the PD LIST.
*/
@@ -3388,20 +3553,11 @@ static int megasas_init_mfi(struct megasas_instance *instance)
MEGASAS_COMPLETION_TIMER_INTERVAL);
return 0;
- fail_fw_init:
-
- pci_free_consistent(instance->pdev, reply_q_sz,
- instance->reply_queue, instance->reply_queue_h);
- fail_reply_queue:
- megasas_free_cmds(instance);
-
- fail_alloc_cmds:
- fail_ready_state:
+fail_ready_state:
iounmap(instance->reg_set);
fail_ioremap:
- pci_release_selected_regions(instance->pdev,
- pci_select_bars(instance->pdev, IORESOURCE_MEM));
+ pci_release_selected_regions(instance->pdev, instance->bar);
return -EINVAL;
}
@@ -3412,17 +3568,17 @@ static int megasas_init_mfi(struct megasas_instance *instance)
*/
static void megasas_release_mfi(struct megasas_instance *instance)
{
- u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1);
+ u32 reply_q_sz = sizeof(u32) *(instance->max_mfi_cmds + 1);
- pci_free_consistent(instance->pdev, reply_q_sz,
+ if (instance->reply_queue)
+ pci_free_consistent(instance->pdev, reply_q_sz,
instance->reply_queue, instance->reply_queue_h);
megasas_free_cmds(instance);
iounmap(instance->reg_set);
- pci_release_selected_regions(instance->pdev,
- pci_select_bars(instance->pdev, IORESOURCE_MEM));
+ pci_release_selected_regions(instance->pdev, instance->bar);
}
/**
@@ -3609,8 +3765,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
/*
* Issue the aen registration frame
*/
- instance->instancet->fire_cmd(instance,
- cmd->frame_phys_addr, 0, instance->reg_set);
+ instance->instancet->issue_dcmd(instance, cmd);
return 0;
}
@@ -3687,12 +3842,18 @@ static int megasas_io_attach(struct megasas_instance *instance)
}
host->max_sectors = instance->max_sectors_per_req;
- host->cmd_per_lun = 128;
+ host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
host->max_channel = MEGASAS_MAX_CHANNELS - 1;
host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
host->max_lun = MEGASAS_MAX_LUN;
host->max_cmd_len = 16;
+ /* Fusion only supports host reset */
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
+ host->hostt->eh_device_reset_handler = NULL;
+ host->hostt->eh_bus_reset_handler = NULL;
+ }
+
/*
* Notify the mid-layer about the new controller
*/
@@ -3733,7 +3894,7 @@ fail_set_dma_mask:
/**
* megasas_probe_one - PCI hotplug entry point
* @pdev: PCI device structure
- * @id: PCI ids of supported hotplugged adapter
+ * @id: PCI ids of supported hotplugged adapter
*/
static int __devinit
megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -3777,20 +3938,45 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance = (struct megasas_instance *)host->hostdata;
memset(instance, 0, sizeof(*instance));
atomic_set( &instance->fw_reset_no_pci_access, 0 );
+ instance->pdev = pdev;
- instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
- &instance->producer_h);
- instance->consumer = pci_alloc_consistent(pdev, sizeof(u32),
- &instance->consumer_h);
+ switch (instance->pdev->device) {
+ case PCI_DEVICE_ID_LSI_FUSION:
+ {
+ struct fusion_context *fusion;
+
+ instance->ctrl_context =
+ kzalloc(sizeof(struct fusion_context), GFP_KERNEL);
+ if (!instance->ctrl_context) {
+ printk(KERN_DEBUG "megasas: Failed to allocate "
+ "memory for Fusion context info\n");
+ goto fail_alloc_dma_buf;
+ }
+ fusion = instance->ctrl_context;
+ INIT_LIST_HEAD(&fusion->cmd_pool);
+ spin_lock_init(&fusion->cmd_pool_lock);
+ }
+ break;
+ default: /* For all other supported controllers */
+
+ instance->producer =
+ pci_alloc_consistent(pdev, sizeof(u32),
+ &instance->producer_h);
+ instance->consumer =
+ pci_alloc_consistent(pdev, sizeof(u32),
+ &instance->consumer_h);
+
+ if (!instance->producer || !instance->consumer) {
+ printk(KERN_DEBUG "megasas: Failed to allocate"
+ "memory for producer, consumer\n");
+ goto fail_alloc_dma_buf;
+ }
- if (!instance->producer || !instance->consumer) {
- printk(KERN_DEBUG "megasas: Failed to allocate memory for "
- "producer, consumer\n");
- goto fail_alloc_dma_buf;
+ *instance->producer = 0;
+ *instance->consumer = 0;
+ break;
}
- *instance->producer = 0;
- *instance->consumer = 0;
megasas_poll_wait_aen = 0;
instance->flag_ieee = 0;
instance->ev = NULL;
@@ -3826,11 +4012,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
spin_lock_init(&poll_aen_lock);
mutex_init(&instance->aen_mutex);
+ mutex_init(&instance->reset_mutex);
/*
* Initialize PCI related and misc parameters
*/
- instance->pdev = pdev;
instance->host = host;
instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
instance->init_id = MEGASAS_DEFAULT_INIT_ID;
@@ -3848,18 +4034,31 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->last_time = 0;
instance->disableOnlineCtrlReset = 1;
- INIT_WORK(&instance->work_init, process_fw_state_change_wq);
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+ INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
+ else
+ INIT_WORK(&instance->work_init, process_fw_state_change_wq);
/*
* Initialize MFI Firmware
*/
- if (megasas_init_mfi(instance))
+ if (megasas_init_fw(instance))
goto fail_init_mfi;
+ /* Try to enable MSI-X */
+ if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) &&
+ (instance->pdev->device != PCI_DEVICE_ID_LSI_VERDE_ZCR) &&
+ !msix_disable && !pci_enable_msix(instance->pdev,
+ &instance->msixentry, 1))
+ instance->msi_flag = 1;
+
/*
* Register IRQ
*/
- if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) {
+ if (request_irq(instance->msi_flag ? instance->msixentry.vector :
+ pdev->irq, instance->instancet->service_isr,
+ IRQF_SHARED, "megasas", instance)) {
printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
goto fail_irq;
}
@@ -3904,9 +4103,10 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, NULL);
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->pdev->irq, instance);
-
- megasas_release_mfi(instance);
+ free_irq(instance->msi_flag ? instance->msixentry.vector :
+ instance->pdev->irq, instance);
+ if (instance->msi_flag)
+ pci_disable_msix(instance->pdev);
fail_irq:
fail_init_mfi:
@@ -3916,9 +4116,13 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->evt_detail,
instance->evt_detail_h);
- if (instance->producer)
+ if (instance->producer) {
pci_free_consistent(pdev, sizeof(u32), instance->producer,
instance->producer_h);
+ megasas_release_mfi(instance);
+ } else {
+ megasas_release_fusion(instance);
+ }
if (instance->consumer)
pci_free_consistent(pdev, sizeof(u32), instance->consumer,
instance->consumer_h);
@@ -3990,7 +4194,9 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
if (instance->aen_cmd)
megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
-
+ if (instance->map_update_cmd)
+ megasas_issue_blocked_abort_cmd(instance,
+ instance->map_update_cmd);
dcmd = &cmd->frame->dcmd;
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
@@ -4046,7 +4252,10 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
pci_set_drvdata(instance->pdev, instance);
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->pdev->irq, instance);
+ free_irq(instance->msi_flag ? instance->msixentry.vector :
+ instance->pdev->irq, instance);
+ if (instance->msi_flag)
+ pci_disable_msix(instance->pdev);
pci_save_state(pdev);
pci_disable_device(pdev);
@@ -4092,9 +4301,6 @@ megasas_resume(struct pci_dev *pdev)
* Initialize MFI Firmware
*/
- *instance->producer = 0;
- *instance->consumer = 0;
-
atomic_set(&instance->fw_outstanding, 0);
/*
@@ -4103,17 +4309,40 @@ megasas_resume(struct pci_dev *pdev)
if (megasas_transition_to_ready(instance))
goto fail_ready_state;
- if (megasas_issue_init_mfi(instance))
- goto fail_init_mfi;
+ switch (instance->pdev->device) {
+ case PCI_DEVICE_ID_LSI_FUSION:
+ {
+ megasas_reset_reply_desc(instance);
+ if (megasas_ioc_init_fusion(instance)) {
+ megasas_free_cmds(instance);
+ megasas_free_cmds_fusion(instance);
+ goto fail_init_mfi;
+ }
+ if (!megasas_get_map_info(instance))
+ megasas_sync_map_info(instance);
+ }
+ break;
+ default:
+ *instance->producer = 0;
+ *instance->consumer = 0;
+ if (megasas_issue_init_mfi(instance))
+ goto fail_init_mfi;
+ break;
+ }
- tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
- (unsigned long)instance);
+ tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
+ (unsigned long)instance);
+
+ /* Now re-enable MSI-X */
+ if (instance->msi_flag)
+ pci_enable_msix(instance->pdev, &instance->msixentry, 1);
/*
* Register IRQ
*/
- if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
- "megasas", instance)) {
+ if (request_irq(instance->msi_flag ? instance->msixentry.vector :
+ pdev->irq, instance->instancet->service_isr,
+ IRQF_SHARED, "megasas", instance)) {
printk(KERN_ERR "megasas: Failed to register IRQ\n");
goto fail_irq;
}
@@ -4171,10 +4400,12 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
int i;
struct Scsi_Host *host;
struct megasas_instance *instance;
+ struct fusion_context *fusion;
instance = pci_get_drvdata(pdev);
instance->unload = 1;
host = instance->host;
+ fusion = instance->ctrl_context;
if (poll_mode_io)
del_timer_sync(&instance->io_completion_timer);
@@ -4211,18 +4442,37 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
instance->instancet->disable_intr(instance->reg_set);
- free_irq(instance->pdev->irq, instance);
-
- megasas_release_mfi(instance);
-
- pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
- instance->evt_detail, instance->evt_detail_h);
-
- pci_free_consistent(pdev, sizeof(u32), instance->producer,
- instance->producer_h);
-
- pci_free_consistent(pdev, sizeof(u32), instance->consumer,
- instance->consumer_h);
+ free_irq(instance->msi_flag ? instance->msixentry.vector :
+ instance->pdev->irq, instance);
+ if (instance->msi_flag)
+ pci_disable_msix(instance->pdev);
+
+ switch (instance->pdev->device) {
+ case PCI_DEVICE_ID_LSI_FUSION:
+ megasas_release_fusion(instance);
+ for (i = 0; i < 2 ; i++)
+ if (fusion->ld_map[i])
+ dma_free_coherent(&instance->pdev->dev,
+ fusion->map_sz,
+ fusion->ld_map[i],
+ fusion->
+ ld_map_phys[i]);
+ kfree(instance->ctrl_context);
+ break;
+ default:
+ megasas_release_mfi(instance);
+ pci_free_consistent(pdev,
+ sizeof(struct megasas_evt_detail),
+ instance->evt_detail,
+ instance->evt_detail_h);
+ pci_free_consistent(pdev, sizeof(u32),
+ instance->producer,
+ instance->producer_h);
+ pci_free_consistent(pdev, sizeof(u32),
+ instance->consumer,
+ instance->consumer_h);
+ break;
+ }
scsi_host_put(host);
@@ -4986,6 +5236,7 @@ megasas_aen_polling(struct work_struct *work)
break;
case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
case MR_EVT_FOREIGN_CFG_IMPORTED:
+ case MR_EVT_LD_STATE_CHANGE:
doscan = 1;
break;
default:
@@ -5165,7 +5416,7 @@ err_dcf_attr_ver:
pci_unregister_driver(&megasas_pci_driver);
err_pcidrv:
unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
- return rval;
+ return rval;
}
/**
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
new file mode 100644
index 00000000000..53fa96ae2b3
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -0,0 +1,516 @@
+/*
+ * Linux MegaRAID driver for SAS based RAID controllers
+ *
+ * Copyright (c) 2009-2011 LSI Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * FILE: megaraid_sas_fp.c
+ *
+ * Authors: LSI Corporation
+ * Sumant Patro
+ * Varad Talamacki
+ * Manoj Jose
+ *
+ * Send feedback to: <megaraidlinux@lsi.com>
+ *
+ * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ * ATTN: Linuxraid
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/smp_lock.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <linux/blkdev.h>
+#include <linux/poll.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#include "megaraid_sas_fusion.h"
+#include <asm/div64.h>
+
+#define ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
+#define MR_LD_STATE_OPTIMAL 3
+#define FALSE 0
+#define TRUE 1
+
+/* Prototypes */
+void
+mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
+ struct LD_LOAD_BALANCE_INFO *lbInfo);
+
+u32 mega_mod64(u64 dividend, u32 divisor)
+{
+ u64 d;
+ u32 remainder;
+
+ if (!divisor)
+ printk(KERN_ERR "megasas : DIVISOR is zero, in div fn\n");
+ d = dividend;
+ remainder = do_div(d, divisor);
+ return remainder;
+}
+
+/**
+ * @param dividend : Dividend
+ * @param divisor : Divisor
+ *
+ * @return quotient
+ **/
+u64 mega_div64_32(uint64_t dividend, uint32_t divisor)
+{
+ u32 remainder;
+ u64 d;
+
+ if (!divisor)
+ printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n");
+
+ d = dividend;
+ remainder = do_div(d, divisor);
+
+ return d;
+}
+
+struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map)
+{
+ return &map->raidMap.ldSpanMap[ld].ldRaid;
+}
+
+static struct MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u32 ld,
+ struct MR_FW_RAID_MAP_ALL
+ *map)
+{
+ return &map->raidMap.ldSpanMap[ld].spanBlock[0];
+}
+
+static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_FW_RAID_MAP_ALL *map)
+{
+ return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx];
+}
+
+static u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map)
+{
+ return map->raidMap.arMapInfo[ar].pd[arm];
+}
+
+static u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map)
+{
+ return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef;
+}
+
+static u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map)
+{
+ return map->raidMap.devHndlInfo[pd].curDevHdl;
+}
+
+u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map)
+{
+ return map->raidMap.ldSpanMap[ld].ldRaid.targetId;
+}
+
+u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map)
+{
+ return map->raidMap.ldTgtIdToLd[ldTgtId];
+}
+
+static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span,
+ struct MR_FW_RAID_MAP_ALL *map)
+{
+ return &map->raidMap.ldSpanMap[ld].spanBlock[span].span;
+}
+
+/*
+ * This function will validate Map info data provided by FW
+ */
+u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
+ struct LD_LOAD_BALANCE_INFO *lbInfo)
+{
+ struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap;
+
+ if (pFwRaidMap->totalSize !=
+ (sizeof(struct MR_FW_RAID_MAP) -sizeof(struct MR_LD_SPAN_MAP) +
+ (sizeof(struct MR_LD_SPAN_MAP) *pFwRaidMap->ldCount))) {
+ printk(KERN_ERR "megasas: map info structure size 0x%x is not matching with ld count\n",
+ (unsigned int)((sizeof(struct MR_FW_RAID_MAP) -
+ sizeof(struct MR_LD_SPAN_MAP)) +
+ (sizeof(struct MR_LD_SPAN_MAP) *
+ pFwRaidMap->ldCount)));
+ printk(KERN_ERR "megasas: span map %x, pFwRaidMap->totalSize "
+ ": %x\n", (unsigned int)sizeof(struct MR_LD_SPAN_MAP),
+ pFwRaidMap->totalSize);
+ return 0;
+ }
+
+ mr_update_load_balance_params(map, lbInfo);
+
+ return 1;
+}
+
+u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
+ struct MR_FW_RAID_MAP_ALL *map, int *div_error)
+{
+ struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
+ struct MR_QUAD_ELEMENT *quad;
+ struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ u32 span, j;
+
+ for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) {
+
+ for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) {
+ quad = &pSpanBlock->block_span_info.quad[j];
+
+ if (quad->diff == 0) {
+ *div_error = 1;
+ return span;
+ }
+ if (quad->logStart <= row && row <= quad->logEnd &&
+ (mega_mod64(row-quad->logStart, quad->diff)) == 0) {
+ if (span_blk != NULL) {
+ u64 blk, debugBlk;
+ blk =
+ mega_div64_32(
+ (row-quad->logStart),
+ quad->diff);
+ debugBlk = blk;
+
+ blk = (blk + quad->offsetInSpan) <<
+ raid->stripeShift;
+ *span_blk = blk;
+ }
+ return span;
+ }
+ }
+ }
+ return span;
+}
+
+/*
+******************************************************************************
+*
+* This routine calculates the arm, span and block for the specified stripe and
+* reference in stripe.
+*
+* Inputs :
+*
+* ld - Logical drive number
+* stripRow - Stripe number
+* stripRef - Reference in stripe
+*
+* Outputs :
+*
+* span - Span number
+* block - Absolute Block number in the physical disk
+*/
+u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
+ u16 *pDevHandle, struct RAID_CONTEXT *pRAID_Context,
+ struct MR_FW_RAID_MAP_ALL *map)
+{
+ struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ u32 pd, arRef;
+ u8 physArm, span;
+ u64 row;
+ u8 retval = TRUE;
+ int error_code = 0;
+
+ row = mega_div64_32(stripRow, raid->rowDataSize);
+
+ if (raid->level == 6) {
+ /* logical arm within row */
+ u32 logArm = mega_mod64(stripRow, raid->rowDataSize);
+ u32 rowMod, armQ, arm;
+
+ if (raid->rowSize == 0)
+ return FALSE;
+ /* get logical row mod */
+ rowMod = mega_mod64(row, raid->rowSize);
+ armQ = raid->rowSize-1-rowMod; /* index of Q drive */
+ arm = armQ+1+logArm; /* data always logically follows Q */
+ if (arm >= raid->rowSize) /* handle wrap condition */
+ arm -= raid->rowSize;
+ physArm = (u8)arm;
+ } else {
+ if (raid->modFactor == 0)
+ return FALSE;
+ physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow,
+ raid->modFactor),
+ map);
+ }
+
+ if (raid->spanDepth == 1) {
+ span = 0;
+ *pdBlock = row << raid->stripeShift;
+ } else {
+ span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code);
+ if (error_code == 1)
+ return FALSE;
+ }
+
+ /* Get the array on which this span is present */
+ arRef = MR_LdSpanArrayGet(ld, span, map);
+ pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */
+
+ if (pd != MR_PD_INVALID)
+ /* Get dev handle from Pd. */
+ *pDevHandle = MR_PdDevHandleGet(pd, map);
+ else {
+ *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
+ if (raid->level >= 5)
+ pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
+ else if (raid->level == 1) {
+ /* Get alternate Pd. */
+ pd = MR_ArPdGet(arRef, physArm + 1, map);
+ if (pd != MR_PD_INVALID)
+ /* Get dev handle from Pd */
+ *pDevHandle = MR_PdDevHandleGet(pd, map);
+ }
+ retval = FALSE;
+ }
+
+ *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
+ pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
+ physArm;
+ return retval;
+}
+
+/*
+******************************************************************************
+*
+* MR_BuildRaidContext function
+*
+* This function will initiate command processing. The start/end row and strip
+* information is calculated then the lock is acquired.
+* This function will return 0 if region lock was acquired OR return num strips
+*/
+u8
+MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
+ struct RAID_CONTEXT *pRAID_Context,
+ struct MR_FW_RAID_MAP_ALL *map)
+{
+ struct MR_LD_RAID *raid;
+ u32 ld, stripSize, stripe_mask;
+ u64 endLba, endStrip, endRow, start_row, start_strip;
+ u64 regStart;
+ u32 regSize;
+ u8 num_strips, numRows;
+ u16 ref_in_start_stripe, ref_in_end_stripe;
+ u64 ldStartBlock;
+ u32 numBlocks, ldTgtId;
+ u8 isRead;
+ u8 retval = 0;
+
+ ldStartBlock = io_info->ldStartBlock;
+ numBlocks = io_info->numBlocks;
+ ldTgtId = io_info->ldTgtId;
+ isRead = io_info->isRead;
+
+ ld = MR_TargetIdToLdGet(ldTgtId, map);
+ raid = MR_LdRaidGet(ld, map);
+
+ stripSize = 1 << raid->stripeShift;
+ stripe_mask = stripSize-1;
+ /*
+ * calculate starting row and stripe, and number of strips and rows
+ */
+ start_strip = ldStartBlock >> raid->stripeShift;
+ ref_in_start_stripe = (u16)(ldStartBlock & stripe_mask);
+ endLba = ldStartBlock + numBlocks - 1;
+ ref_in_end_stripe = (u16)(endLba & stripe_mask);
+ endStrip = endLba >> raid->stripeShift;
+ num_strips = (u8)(endStrip - start_strip + 1); /* End strip */
+ if (raid->rowDataSize == 0)
+ return FALSE;
+ start_row = mega_div64_32(start_strip, raid->rowDataSize);
+ endRow = mega_div64_32(endStrip, raid->rowDataSize);
+ numRows = (u8)(endRow - start_row + 1);
+
+ /*
+ * calculate region info.
+ */
+
+ /* assume region is at the start of the first row */
+ regStart = start_row << raid->stripeShift;
+ /* assume this IO needs the full row - we'll adjust if not true */
+ regSize = stripSize;
+
+ /* If IO spans more than 1 strip, fp is not possible
+ FP is not possible for writes on non-0 raid levels
+ FP is not possible if LD is not capable */
+ if (num_strips > 1 || (!isRead && raid->level != 0) ||
+ !raid->capability.fpCapable) {
+ io_info->fpOkForIo = FALSE;
+ } else {
+ io_info->fpOkForIo = TRUE;
+ }
+
+ if (numRows == 1) {
+ /* single-strip IOs can always lock only the data needed */
+ if (num_strips == 1) {
+ regStart += ref_in_start_stripe;
+ regSize = numBlocks;
+ }
+ /* multi-strip IOs always need to full stripe locked */
+ } else {
+ if (start_strip == (start_row + 1) * raid->rowDataSize - 1) {
+ /* If the start strip is the last in the start row */
+ regStart += ref_in_start_stripe;
+ regSize = stripSize - ref_in_start_stripe;
+ /* initialize count to sectors from startref to end
+ of strip */
+ }
+
+ if (numRows > 2)
+ /* Add complete rows in the middle of the transfer */
+ regSize += (numRows-2) << raid->stripeShift;
+
+ /* if IO ends within first strip of last row */
+ if (endStrip == endRow*raid->rowDataSize)
+ regSize += ref_in_end_stripe+1;
+ else
+ regSize += stripSize;
+ }
+
+ pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec;
+ pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ :
+ raid->regTypeReqOnWrite;
+ pRAID_Context->VirtualDiskTgtId = raid->targetId;
+ pRAID_Context->regLockRowLBA = regStart;
+ pRAID_Context->regLockLength = regSize;
+ pRAID_Context->configSeqNum = raid->seqNum;
+
+ /*Get Phy Params only if FP capable, or else leave it to MR firmware
+ to do the calculation.*/
+ if (io_info->fpOkForIo) {
+ retval = MR_GetPhyParams(ld, start_strip, ref_in_start_stripe,
+ &io_info->pdBlock,
+ &io_info->devHandle, pRAID_Context,
+ map);
+ /* If IO on an invalid Pd, then FP i snot possible */
+ if (io_info->devHandle == MR_PD_INVALID)
+ io_info->fpOkForIo = FALSE;
+ return retval;
+ } else if (isRead) {
+ uint stripIdx;
+ for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
+ if (!MR_GetPhyParams(ld, start_strip + stripIdx,
+ ref_in_start_stripe,
+ &io_info->pdBlock,
+ &io_info->devHandle,
+ pRAID_Context, map))
+ return TRUE;
+ }
+ }
+ return TRUE;
+}
+
+void
+mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
+ struct LD_LOAD_BALANCE_INFO *lbInfo)
+{
+ int ldCount;
+ u16 ld;
+ struct MR_LD_RAID *raid;
+
+ for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
+ ld = MR_TargetIdToLdGet(ldCount, map);
+ if (ld >= MAX_LOGICAL_DRIVES) {
+ lbInfo[ldCount].loadBalanceFlag = 0;
+ continue;
+ }
+
+ raid = MR_LdRaidGet(ld, map);
+
+ /* Two drive Optimal RAID 1 */
+ if ((raid->level == 1) && (raid->rowSize == 2) &&
+ (raid->spanDepth == 1) && raid->ldState ==
+ MR_LD_STATE_OPTIMAL) {
+ u32 pd, arRef;
+
+ lbInfo[ldCount].loadBalanceFlag = 1;
+
+ /* Get the array on which this span is present */
+ arRef = MR_LdSpanArrayGet(ld, 0, map);
+
+ /* Get the Pd */
+ pd = MR_ArPdGet(arRef, 0, map);
+ /* Get dev handle from Pd */
+ lbInfo[ldCount].raid1DevHandle[0] =
+ MR_PdDevHandleGet(pd, map);
+ /* Get the Pd */
+ pd = MR_ArPdGet(arRef, 1, map);
+
+ /* Get the dev handle from Pd */
+ lbInfo[ldCount].raid1DevHandle[1] =
+ MR_PdDevHandleGet(pd, map);
+ } else
+ lbInfo[ldCount].loadBalanceFlag = 0;
+ }
+}
+
+u8 megasas_get_best_arm(struct LD_LOAD_BALANCE_INFO *lbInfo, u8 arm, u64 block,
+ u32 count)
+{
+ u16 pend0, pend1;
+ u64 diff0, diff1;
+ u8 bestArm;
+
+ /* get the pending cmds for the data and mirror arms */
+ pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]);
+ pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]);
+
+ /* Determine the disk whose head is nearer to the req. block */
+ diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]);
+ diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]);
+ bestArm = (diff0 <= diff1 ? 0 : 1);
+
+ if ((bestArm == arm && pend0 > pend1 + 16) ||
+ (bestArm != arm && pend1 > pend0 + 16))
+ bestArm ^= 1;
+
+ /* Update the last accessed block on the correct pd */
+ lbInfo->last_accessed_block[bestArm] = block + count - 1;
+
+ return bestArm;
+}
+
+u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
+ struct IO_REQUEST_INFO *io_info)
+{
+ u8 arm, old_arm;
+ u16 devHandle;
+
+ old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1;
+
+ /* get best new arm */
+ arm = megasas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock,
+ io_info->numBlocks);
+ devHandle = lbInfo->raid1DevHandle[arm];
+ atomic_inc(&lbInfo->scsi_pending_cmds[arm]);
+
+ return devHandle;
+}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
new file mode 100644
index 00000000000..c1e09d5a619
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -0,0 +1,2248 @@
+/*
+ * Linux MegaRAID driver for SAS based RAID controllers
+ *
+ * Copyright (c) 2009-2011 LSI Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * FILE: megaraid_sas_fusion.c
+ *
+ * Authors: LSI Corporation
+ * Sumant Patro
+ * Adam Radford <linuxraid@lsi.com>
+ *
+ * Send feedback to: <megaraidlinux@lsi.com>
+ *
+ * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ * ATTN: Linuxraid
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/smp_lock.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <linux/blkdev.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#include "megaraid_sas_fusion.h"
+#include "megaraid_sas.h"
+
+extern void megasas_free_cmds(struct megasas_instance *instance);
+extern struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+ *instance);
+extern void
+megasas_complete_cmd(struct megasas_instance *instance,
+ struct megasas_cmd *cmd, u8 alt_status);
+int megasas_is_ldio(struct scsi_cmnd *cmd);
+int
+wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
+
+void
+megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd);
+int megasas_alloc_cmds(struct megasas_instance *instance);
+int
+megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs);
+int
+megasas_issue_polled(struct megasas_instance *instance,
+ struct megasas_cmd *cmd);
+
+u8
+MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
+ struct RAID_CONTEXT *pRAID_Context,
+ struct MR_FW_RAID_MAP_ALL *map);
+u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
+struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
+
+u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
+u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
+ struct LD_LOAD_BALANCE_INFO *lbInfo);
+u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
+ struct IO_REQUEST_INFO *in_info);
+int megasas_transition_to_ready(struct megasas_instance *instance);
+void megaraid_sas_kill_hba(struct megasas_instance *instance);
+
+extern u32 megasas_dbg_lvl;
+
+/**
+ * megasas_enable_intr_fusion - Enables interrupts
+ * @regs: MFI register set
+ */
+void
+megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
+{
+ writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
+
+ /* Dummy readl to force pci flush */
+ readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_fusion - Disables interrupt
+ * @regs: MFI register set
+ */
+void
+megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs)
+{
+ u32 mask = 0xFFFFFFFF;
+ u32 status;
+
+ writel(mask, &regs->outbound_intr_mask);
+ /* Dummy readl to force pci flush */
+ status = readl(&regs->outbound_intr_mask);
+}
+
+int
+megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs)
+{
+ u32 status;
+ /*
+ * Check if it is our interrupt
+ */
+ status = readl(&regs->outbound_intr_status);
+
+ if (status & 1) {
+ writel(status, &regs->outbound_intr_status);
+ readl(&regs->outbound_intr_status);
+ return 1;
+ }
+ if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
+ return 0;
+
+ /*
+ * dummy read to flush PCI
+ */
+ readl(&regs->outbound_intr_status);
+
+ return 1;
+}
+
+/**
+ * megasas_get_cmd_fusion - Get a command from the free pool
+ * @instance: Adapter soft state
+ *
+ * Returns a free command from the pool
+ */
+struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance
+ *instance)
+{
+ unsigned long flags;
+ struct fusion_context *fusion =
+ (struct fusion_context *)instance->ctrl_context;
+ struct megasas_cmd_fusion *cmd = NULL;
+
+ spin_lock_irqsave(&fusion->cmd_pool_lock, flags);
+
+ if (!list_empty(&fusion->cmd_pool)) {
+ cmd = list_entry((&fusion->cmd_pool)->next,
+ struct megasas_cmd_fusion, list);
+ list_del_init(&cmd->list);
+ } else {
+ printk(KERN_ERR "megasas: Command pool (fusion) empty!\n");
+ }
+
+ spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags);
+ return cmd;
+}
+
+/**
+ * megasas_return_cmd_fusion - Return a cmd to free command pool
+ * @instance: Adapter soft state
+ * @cmd: Command packet to be returned to free command pool
+ */
+static inline void
+megasas_return_cmd_fusion(struct megasas_instance *instance,
+ struct megasas_cmd_fusion *cmd)
+{
+ unsigned long flags;
+ struct fusion_context *fusion =
+ (struct fusion_context *)instance->ctrl_context;
+
+ spin_lock_irqsave(&fusion->cmd_pool_lock, flags);
+
+ cmd->scmd = NULL;
+ cmd->sync_cmd_idx = (u32)ULONG_MAX;
+ list_add_tail(&cmd->list, &fusion->cmd_pool);
+
+ spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags);
+}
+
+/**
+ * megasas_teardown_frame_pool_fusion - Destroy the cmd frame DMA pool
+ * @instance: Adapter soft state
+ */
+static void megasas_teardown_frame_pool_fusion(
+ struct megasas_instance *instance)
+{
+ int i;
+ struct fusion_context *fusion = instance->ctrl_context;
+
+ u16 max_cmd = instance->max_fw_cmds;
+
+ struct megasas_cmd_fusion *cmd;
+
+ if (!fusion->sg_dma_pool || !fusion->sense_dma_pool) {
+ printk(KERN_ERR "megasas: dma pool is null. SG Pool %p, "
+ "sense pool : %p\n", fusion->sg_dma_pool,
+ fusion->sense_dma_pool);
+ return;
+ }
+
+ /*
+ * Return all frames to pool
+ */
+ for (i = 0; i < max_cmd; i++) {
+
+ cmd = fusion->cmd_list[i];
+
+ if (cmd->sg_frame)
+ pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame,
+ cmd->sg_frame_phys_addr);
+
+ if (cmd->sense)
+ pci_pool_free(fusion->sense_dma_pool, cmd->sense,
+ cmd->sense_phys_addr);
+ }
+
+ /*
+ * Now destroy the pool itself
+ */
+ pci_pool_destroy(fusion->sg_dma_pool);
+ pci_pool_destroy(fusion->sense_dma_pool);
+
+ fusion->sg_dma_pool = NULL;
+ fusion->sense_dma_pool = NULL;
+}
+
+/**
+ * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool
+ * @instance: Adapter soft state
+ */
+void
+megasas_free_cmds_fusion(struct megasas_instance *instance)
+{
+ int i;
+ struct fusion_context *fusion = instance->ctrl_context;
+
+ u32 max_cmds, req_sz, reply_sz, io_frames_sz;
+
+
+ req_sz = fusion->request_alloc_sz;
+ reply_sz = fusion->reply_alloc_sz;
+ io_frames_sz = fusion->io_frames_alloc_sz;
+
+ max_cmds = instance->max_fw_cmds;
+
+ /* Free descriptors and request Frames memory */
+ if (fusion->req_frames_desc)
+ dma_free_coherent(&instance->pdev->dev, req_sz,
+ fusion->req_frames_desc,
+ fusion->req_frames_desc_phys);
+
+ if (fusion->reply_frames_desc) {
+ pci_pool_free(fusion->reply_frames_desc_pool,
+ fusion->reply_frames_desc,
+ fusion->reply_frames_desc_phys);
+ pci_pool_destroy(fusion->reply_frames_desc_pool);
+ }
+
+ if (fusion->io_request_frames) {
+ pci_pool_free(fusion->io_request_frames_pool,
+ fusion->io_request_frames,
+ fusion->io_request_frames_phys);
+ pci_pool_destroy(fusion->io_request_frames_pool);
+ }
+
+ /* Free the Fusion frame pool */
+ megasas_teardown_frame_pool_fusion(instance);
+
+ /* Free all the commands in the cmd_list */
+ for (i = 0; i < max_cmds; i++)
+ kfree(fusion->cmd_list[i]);
+
+ /* Free the cmd_list buffer itself */
+ kfree(fusion->cmd_list);
+ fusion->cmd_list = NULL;
+
+ INIT_LIST_HEAD(&fusion->cmd_pool);
+}
+
+/**
+ * megasas_create_frame_pool_fusion - Creates DMA pool for cmd frames
+ * @instance: Adapter soft state
+ *
+ */
+static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
+{
+ int i;
+ u32 max_cmd;
+ struct fusion_context *fusion;
+ struct megasas_cmd_fusion *cmd;
+ u32 total_sz_chain_frame;
+
+ fusion = instance->ctrl_context;
+ max_cmd = instance->max_fw_cmds;
+
+ total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME;
+
+ /*
+ * Use DMA pool facility provided by PCI layer
+ */
+
+ fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion",
+ instance->pdev,
+ total_sz_chain_frame, 4,
+ 0);
+ if (!fusion->sg_dma_pool) {
+ printk(KERN_DEBUG "megasas: failed to setup request pool "
+ "fusion\n");
+ return -ENOMEM;
+ }
+ fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion",
+ instance->pdev,
+ SCSI_SENSE_BUFFERSIZE, 64, 0);
+
+ if (!fusion->sense_dma_pool) {
+ printk(KERN_DEBUG "megasas: failed to setup sense pool "
+ "fusion\n");
+ pci_pool_destroy(fusion->sg_dma_pool);
+ fusion->sg_dma_pool = NULL;
+ return -ENOMEM;
+ }
+
+ /*
+ * Allocate and attach a frame to each of the commands in cmd_list
+ */
+ for (i = 0; i < max_cmd; i++) {
+
+ cmd = fusion->cmd_list[i];
+
+ cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool,
+ GFP_KERNEL,
+ &cmd->sg_frame_phys_addr);
+
+ cmd->sense = pci_pool_alloc(fusion->sense_dma_pool,
+ GFP_KERNEL, &cmd->sense_phys_addr);
+ /*
+ * megasas_teardown_frame_pool_fusion() takes care of freeing
+ * whatever has been allocated
+ */
+ if (!cmd->sg_frame || !cmd->sense) {
+ printk(KERN_DEBUG "megasas: pci_pool_alloc failed\n");
+ megasas_teardown_frame_pool_fusion(instance);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+/**
+ * megasas_alloc_cmds_fusion - Allocates the command packets
+ * @instance: Adapter soft state
+ *
+ *
+ * Each frame has a 32-bit field called context. This context is used to get
+ * back the megasas_cmd_fusion from the frame when a frame gets completed
+ * In this driver, the 32 bit values are the indices into an array cmd_list.
+ * This array is used only to look up the megasas_cmd_fusion given the context.
+ * The free commands themselves are maintained in a linked list called cmd_pool.
+ *
+ * cmds are formed in the io_request and sg_frame members of the
+ * megasas_cmd_fusion. The context field is used to get a request descriptor
+ * and is used as SMID of the cmd.
+ * SMID value range is from 1 to max_fw_cmds.
+ */
+int
+megasas_alloc_cmds_fusion(struct megasas_instance *instance)
+{
+ int i, j;
+ u32 max_cmd, io_frames_sz;
+ struct fusion_context *fusion;
+ struct megasas_cmd_fusion *cmd;
+ union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
+ u32 offset;
+ dma_addr_t io_req_base_phys;
+ u8 *io_req_base;
+
+ fusion = instance->ctrl_context;
+
+ max_cmd = instance->max_fw_cmds;
+
+ fusion->req_frames_desc =
+ dma_alloc_coherent(&instance->pdev->dev,
+ fusion->request_alloc_sz,
+ &fusion->req_frames_desc_phys, GFP_KERNEL);
+
+ if (!fusion->req_frames_desc) {
+ printk(KERN_ERR "megasas; Could not allocate memory for "
+ "request_frames\n");
+ goto fail_req_desc;
+ }
+
+ fusion->reply_frames_desc_pool =
+ pci_pool_create("reply_frames pool", instance->pdev,
+ fusion->reply_alloc_sz, 16, 0);
+
+ if (!fusion->reply_frames_desc_pool) {
+ printk(KERN_ERR "megasas; Could not allocate memory for "
+ "reply_frame pool\n");
+ goto fail_reply_desc;
+ }
+
+ fusion->reply_frames_desc =
+ pci_pool_alloc(fusion->reply_frames_desc_pool, GFP_KERNEL,
+ &fusion->reply_frames_desc_phys);
+ if (!fusion->reply_frames_desc) {
+ printk(KERN_ERR "megasas; Could not allocate memory for "
+ "reply_frame pool\n");
+ pci_pool_destroy(fusion->reply_frames_desc_pool);
+ goto fail_reply_desc;
+ }
+
+ reply_desc = fusion->reply_frames_desc;
+ for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++)
+ reply_desc->Words = ULLONG_MAX;
+
+ io_frames_sz = fusion->io_frames_alloc_sz;
+
+ fusion->io_request_frames_pool =
+ pci_pool_create("io_request_frames pool", instance->pdev,
+ fusion->io_frames_alloc_sz, 16, 0);
+
+ if (!fusion->io_request_frames_pool) {
+ printk(KERN_ERR "megasas: Could not allocate memory for "
+ "io_request_frame pool\n");
+ goto fail_io_frames;
+ }
+
+ fusion->io_request_frames =
+ pci_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL,
+ &fusion->io_request_frames_phys);
+ if (!fusion->io_request_frames) {
+ printk(KERN_ERR "megasas: Could not allocate memory for "
+ "io_request_frames frames\n");
+ pci_pool_destroy(fusion->io_request_frames_pool);
+ goto fail_io_frames;
+ }
+
+ /*
+ * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers.
+ * Allocate the dynamic array first and then allocate individual
+ * commands.
+ */
+ fusion->cmd_list = kmalloc(sizeof(struct megasas_cmd_fusion *)
+ *max_cmd, GFP_KERNEL);
+
+ if (!fusion->cmd_list) {
+ printk(KERN_DEBUG "megasas: out of memory. Could not alloc "
+ "memory for cmd_list_fusion\n");
+ goto fail_cmd_list;
+ }
+
+ memset(fusion->cmd_list, 0, sizeof(struct megasas_cmd_fusion *)
+ *max_cmd);
+
+ max_cmd = instance->max_fw_cmds;
+ for (i = 0; i < max_cmd; i++) {
+ fusion->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd_fusion),
+ GFP_KERNEL);
+ if (!fusion->cmd_list[i]) {
+ printk(KERN_ERR "Could not alloc cmd list fusion\n");
+
+ for (j = 0; j < i; j++)
+ kfree(fusion->cmd_list[j]);
+
+ kfree(fusion->cmd_list);
+ fusion->cmd_list = NULL;
+ goto fail_cmd_list;
+ }
+ }
+
+ /* The first 256 bytes (SMID 0) is not used. Don't add to cmd list */
+ io_req_base = fusion->io_request_frames +
+ MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
+ io_req_base_phys = fusion->io_request_frames_phys +
+ MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
+
+ /*
+ * Add all the commands to command pool (fusion->cmd_pool)
+ */
+
+ /* SMID 0 is reserved. Set SMID/index from 1 */
+ for (i = 0; i < max_cmd; i++) {
+ cmd = fusion->cmd_list[i];
+ offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
+ memset(cmd, 0, sizeof(struct megasas_cmd_fusion));
+ cmd->index = i + 1;
+ cmd->scmd = NULL;
+ cmd->sync_cmd_idx = (u32)ULONG_MAX; /* Set to Invalid */
+ cmd->instance = instance;
+ cmd->io_request =
+ (struct MPI2_RAID_SCSI_IO_REQUEST *)
+ (io_req_base + offset);
+ memset(cmd->io_request, 0,
+ sizeof(struct MPI2_RAID_SCSI_IO_REQUEST));
+ cmd->io_request_phys_addr = io_req_base_phys + offset;
+
+ list_add_tail(&cmd->list, &fusion->cmd_pool);
+ }
+
+ /*
+ * Create a frame pool and assign one frame to each cmd
+ */
+ if (megasas_create_frame_pool_fusion(instance)) {
+ printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
+ megasas_free_cmds_fusion(instance);
+ goto fail_req_desc;
+ }
+
+ return 0;
+
+fail_cmd_list:
+ pci_pool_free(fusion->io_request_frames_pool, fusion->io_request_frames,
+ fusion->io_request_frames_phys);
+ pci_pool_destroy(fusion->io_request_frames_pool);
+fail_io_frames:
+ dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
+ fusion->reply_frames_desc,
+ fusion->reply_frames_desc_phys);
+ pci_pool_free(fusion->reply_frames_desc_pool,
+ fusion->reply_frames_desc,
+ fusion->reply_frames_desc_phys);
+ pci_pool_destroy(fusion->reply_frames_desc_pool);
+
+fail_reply_desc:
+ dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
+ fusion->req_frames_desc,
+ fusion->req_frames_desc_phys);
+fail_req_desc:
+ return -ENOMEM;
+}
+
+/**
+ * wait_and_poll - Issues a polling command
+ * @instance: Adapter soft state
+ * @cmd: Command packet to be issued
+ *
+ * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
+ */
+int
+wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+ int i;
+ struct megasas_header *frame_hdr = &cmd->frame->hdr;
+
+ u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
+
+ /*
+ * Wait for cmd_status to change
+ */
+ for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i += 20) {
+ rmb();
+ msleep(20);
+ }
+
+ if (frame_hdr->cmd_status == 0xff)
+ return -ETIME;
+
+ return 0;
+}
+
+/**
+ * megasas_ioc_init_fusion - Initializes the FW
+ * @instance: Adapter soft state
+ *
+ * Issues the IOC Init cmd
+ */
+int
+megasas_ioc_init_fusion(struct megasas_instance *instance)
+{
+ struct megasas_init_frame *init_frame;
+ struct MPI2_IOC_INIT_REQUEST *IOCInitMessage;
+ dma_addr_t ioc_init_handle;
+ u32 context;
+ struct megasas_cmd *cmd;
+ u8 ret;
+ struct fusion_context *fusion;
+ union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+ int i;
+ struct megasas_header *frame_hdr;
+
+ fusion = instance->ctrl_context;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ printk(KERN_ERR "Could not allocate cmd for INIT Frame\n");
+ ret = 1;
+ goto fail_get_cmd;
+ }
+
+ IOCInitMessage =
+ dma_alloc_coherent(&instance->pdev->dev,
+ sizeof(struct MPI2_IOC_INIT_REQUEST),
+ &ioc_init_handle, GFP_KERNEL);
+
+ if (!IOCInitMessage) {
+ printk(KERN_ERR "Could not allocate memory for "
+ "IOCInitMessage\n");
+ ret = 1;
+ goto fail_fw_init;
+ }
+
+ memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST));
+
+ IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT;
+ IOCInitMessage->WhoInit = MPI2_WHOINIT_HOST_DRIVER;
+ IOCInitMessage->MsgVersion = MPI2_VERSION;
+ IOCInitMessage->HeaderVersion = MPI2_HEADER_VERSION;
+ IOCInitMessage->SystemRequestFrameSize =
+ MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4;
+
+ IOCInitMessage->ReplyDescriptorPostQueueDepth = fusion->reply_q_depth;
+ IOCInitMessage->ReplyDescriptorPostQueueAddress =
+ fusion->reply_frames_desc_phys;
+ IOCInitMessage->SystemRequestFrameBaseAddress =
+ fusion->io_request_frames_phys;
+
+ init_frame = (struct megasas_init_frame *)cmd->frame;
+ memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
+
+ frame_hdr = &cmd->frame->hdr;
+ context = init_frame->context;
+ init_frame->context = context;
+
+ frame_hdr->cmd_status = 0xFF;
+ frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+ init_frame->cmd = MFI_CMD_INIT;
+ init_frame->cmd_status = 0xFF;
+
+ init_frame->queue_info_new_phys_addr_lo = ioc_init_handle;
+ init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
+
+ req_desc =
+ (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)fusion->req_frames_desc;
+
+ req_desc->Words = cmd->frame_phys_addr;
+ req_desc->MFAIo.RequestFlags =
+ (MEGASAS_REQ_DESCRIPT_FLAGS_MFA <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+
+ /*
+ * disable the intr before firing the init frame
+ */
+ instance->instancet->disable_intr(instance->reg_set);
+
+ for (i = 0; i < (10 * 1000); i += 20) {
+ if (readl(&instance->reg_set->doorbell) & 1)
+ msleep(20);
+ else
+ break;
+ }
+
+ instance->instancet->fire_cmd(instance, req_desc->u.low,
+ req_desc->u.high, instance->reg_set);
+
+ wait_and_poll(instance, cmd);
+
+ frame_hdr = &cmd->frame->hdr;
+ if (frame_hdr->cmd_status != 0) {
+ ret = 1;
+ goto fail_fw_init;
+ }
+ printk(KERN_ERR "megasas:IOC Init cmd success\n");
+
+ ret = 0;
+
+fail_fw_init:
+ megasas_return_cmd(instance, cmd);
+ if (IOCInitMessage)
+ dma_free_coherent(&instance->pdev->dev,
+ sizeof(struct MPI2_IOC_INIT_REQUEST),
+ IOCInitMessage, ioc_init_handle);
+fail_get_cmd:
+ return ret;
+}
+
+/*
+ * megasas_return_cmd_for_smid - Returns a cmd_fusion for a SMID
+ * @instance: Adapter soft state
+ *
+ */
+void
+megasas_return_cmd_for_smid(struct megasas_instance *instance, u16 smid)
+{
+ struct fusion_context *fusion;
+ struct megasas_cmd_fusion *cmd;
+
+ fusion = instance->ctrl_context;
+ cmd = fusion->cmd_list[smid - 1];
+ megasas_return_cmd_fusion(instance, cmd);
+}
+
+/*
+ * megasas_get_ld_map_info - Returns FW's ld_map structure
+ * @instance: Adapter soft state
+ * @pend: Pend the command or not
+ * Issues an internal command (DCMD) to get the FW's controller PD
+ * list structure. This information is mainly used to find out SYSTEM
+ * supported by the FW.
+ */
+static int
+megasas_get_ld_map_info(struct megasas_instance *instance)
+{
+ int ret = 0;
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+ struct MR_FW_RAID_MAP_ALL *ci;
+ dma_addr_t ci_h = 0;
+ u32 size_map_info;
+ struct fusion_context *fusion;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ printk(KERN_DEBUG "megasas: Failed to get cmd for map info.\n");
+ return -ENOMEM;
+ }
+
+ fusion = instance->ctrl_context;
+
+ if (!fusion) {
+ megasas_return_cmd(instance, cmd);
+ return 1;
+ }
+
+ dcmd = &cmd->frame->dcmd;
+
+ size_map_info = sizeof(struct MR_FW_RAID_MAP) +
+ (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
+
+ ci = fusion->ld_map[(instance->map_id & 1)];
+ ci_h = fusion->ld_map_phys[(instance->map_id & 1)];
+
+ if (!ci) {
+ printk(KERN_DEBUG "Failed to alloc mem for ld_map_info\n");
+ megasas_return_cmd(instance, cmd);
+ return -ENOMEM;
+ }
+
+ memset(ci, 0, sizeof(*ci));
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = size_map_info;
+ dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
+ dcmd->sgl.sge32[0].phys_addr = ci_h;
+ dcmd->sgl.sge32[0].length = size_map_info;
+
+ if (!megasas_issue_polled(instance, cmd))
+ ret = 0;
+ else {
+ printk(KERN_ERR "megasas: Get LD Map Info Failed\n");
+ ret = -1;
+ }
+
+ megasas_return_cmd(instance, cmd);
+
+ return ret;
+}
+
+u8
+megasas_get_map_info(struct megasas_instance *instance)
+{
+ struct fusion_context *fusion = instance->ctrl_context;
+
+ fusion->fast_path_io = 0;
+ if (!megasas_get_ld_map_info(instance)) {
+ if (MR_ValidateMapInfo(fusion->ld_map[(instance->map_id & 1)],
+ fusion->load_balance_info)) {
+ fusion->fast_path_io = 1;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * megasas_sync_map_info - Returns FW's ld_map structure
+ * @instance: Adapter soft state
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD
+ * list structure. This information is mainly used to find out SYSTEM
+ * supported by the FW.
+ */
+int
+megasas_sync_map_info(struct megasas_instance *instance)
+{
+ int ret = 0, i;
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+ u32 size_sync_info, num_lds;
+ struct fusion_context *fusion;
+ struct MR_LD_TARGET_SYNC *ci = NULL;
+ struct MR_FW_RAID_MAP_ALL *map;
+ struct MR_LD_RAID *raid;
+ struct MR_LD_TARGET_SYNC *ld_sync;
+ dma_addr_t ci_h = 0;
+ u32 size_map_info;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ printk(KERN_DEBUG "megasas: Failed to get cmd for sync"
+ "info.\n");
+ return -ENOMEM;
+ }
+
+ fusion = instance->ctrl_context;
+
+ if (!fusion) {
+ megasas_return_cmd(instance, cmd);
+ return 1;
+ }
+
+ map = fusion->ld_map[instance->map_id & 1];
+
+ num_lds = map->raidMap.ldCount;
+
+ dcmd = &cmd->frame->dcmd;
+
+ size_sync_info = sizeof(struct MR_LD_TARGET_SYNC) *num_lds;
+
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ ci = (struct MR_LD_TARGET_SYNC *)
+ fusion->ld_map[(instance->map_id - 1) & 1];
+ memset(ci, 0, sizeof(struct MR_FW_RAID_MAP_ALL));
+
+ ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1];
+
+ ld_sync = (struct MR_LD_TARGET_SYNC *)ci;
+
+ for (i = 0; i < num_lds; i++, ld_sync++) {
+ raid = MR_LdRaidGet(i, map);
+ ld_sync->targetId = MR_GetLDTgtId(i, map);
+ ld_sync->seqNum = raid->seqNum;
+ }
+
+ size_map_info = sizeof(struct MR_FW_RAID_MAP) +
+ (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_WRITE;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = size_map_info;
+ dcmd->mbox.b[0] = num_lds;
+ dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG;
+ dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
+ dcmd->sgl.sge32[0].phys_addr = ci_h;
+ dcmd->sgl.sge32[0].length = size_map_info;
+
+ instance->map_update_cmd = cmd;
+
+ instance->instancet->issue_dcmd(instance, cmd);
+
+ return ret;
+}
+
+/**
+ * megasas_init_adapter_fusion - Initializes the FW
+ * @instance: Adapter soft state
+ *
+ * This is the main function for initializing firmware.
+ */
+u32
+megasas_init_adapter_fusion(struct megasas_instance *instance)
+{
+ struct megasas_register_set __iomem *reg_set;
+ struct fusion_context *fusion;
+ u32 max_cmd;
+ int i = 0;
+
+ fusion = instance->ctrl_context;
+
+ reg_set = instance->reg_set;
+
+ /*
+ * Get various operational parameters from status register
+ */
+ instance->max_fw_cmds =
+ instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
+ instance->max_fw_cmds = min(instance->max_fw_cmds, (u16)1008);
+
+ /*
+ * Reduce the max supported cmds by 1. This is to ensure that the
+ * reply_q_sz (1 more than the max cmd that driver may send)
+ * does not exceed max cmds that the FW can support
+ */
+ instance->max_fw_cmds = instance->max_fw_cmds-1;
+ /* Only internal cmds (DCMD) need to have MFI frames */
+ instance->max_mfi_cmds = MEGASAS_INT_CMDS;
+
+ max_cmd = instance->max_fw_cmds;
+
+ fusion->reply_q_depth = ((max_cmd + 1 + 15)/16)*16;
+
+ fusion->request_alloc_sz =
+ sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *max_cmd;
+ fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)
+ *(fusion->reply_q_depth);
+ fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE +
+ (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE *
+ (max_cmd + 1)); /* Extra 1 for SMID 0 */
+
+ fusion->max_sge_in_main_msg =
+ (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
+ offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
+
+ fusion->max_sge_in_chain =
+ MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION);
+
+ instance->max_num_sge = fusion->max_sge_in_main_msg +
+ fusion->max_sge_in_chain - 2;
+
+ /* Used for pass thru MFI frame (DCMD) */
+ fusion->chain_offset_mfi_pthru =
+ offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL)/16;
+
+ fusion->chain_offset_io_request =
+ (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
+ sizeof(union MPI2_SGE_IO_UNION))/16;
+
+ fusion->last_reply_idx = 0;
+
+ /*
+ * Allocate memory for descriptors
+ * Create a pool of commands
+ */
+ if (megasas_alloc_cmds(instance))
+ goto fail_alloc_mfi_cmds;
+ if (megasas_alloc_cmds_fusion(instance))
+ goto fail_alloc_cmds;
+
+ if (megasas_ioc_init_fusion(instance))
+ goto fail_ioc_init;
+
+ instance->flag_ieee = 1;
+
+ fusion->map_sz = sizeof(struct MR_FW_RAID_MAP) +
+ (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
+
+ fusion->fast_path_io = 0;
+
+ for (i = 0; i < 2; i++) {
+ fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
+ fusion->map_sz,
+ &fusion->ld_map_phys[i],
+ GFP_KERNEL);
+ if (!fusion->ld_map[i]) {
+ printk(KERN_ERR "megasas: Could not allocate memory "
+ "for map info\n");
+ goto fail_map_info;
+ }
+ }
+
+ if (!megasas_get_map_info(instance))
+ megasas_sync_map_info(instance);
+
+ return 0;
+
+fail_alloc_cmds:
+fail_alloc_mfi_cmds:
+fail_map_info:
+ if (i == 1)
+ dma_free_coherent(&instance->pdev->dev, fusion->map_sz,
+ fusion->ld_map[0], fusion->ld_map_phys[0]);
+fail_ioc_init:
+ return 1;
+}
+
+/**
+ * megasas_fire_cmd_fusion - Sends command to the FW
+ * @frame_phys_addr : Physical address of cmd
+ * @frame_count : Number of frames for the command
+ * @regs : MFI register set
+ */
+void
+megasas_fire_cmd_fusion(struct megasas_instance *instance,
+ dma_addr_t req_desc_lo,
+ u32 req_desc_hi,
+ struct megasas_register_set __iomem *regs)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&instance->hba_lock, flags);
+
+ writel(req_desc_lo,
+ &(regs)->inbound_low_queue_port);
+ writel(req_desc_hi, &(regs)->inbound_high_queue_port);
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * map_cmd_status - Maps FW cmd status to OS cmd status
+ * @cmd : Pointer to cmd
+ * @status : status of cmd returned by FW
+ * @ext_status : ext status of cmd returned by FW
+ */
+
+void
+map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status)
+{
+
+ switch (status) {
+
+ case MFI_STAT_OK:
+ cmd->scmd->result = DID_OK << 16;
+ break;
+
+ case MFI_STAT_SCSI_IO_FAILED:
+ case MFI_STAT_LD_INIT_IN_PROGRESS:
+ cmd->scmd->result = (DID_ERROR << 16) | ext_status;
+ break;
+
+ case MFI_STAT_SCSI_DONE_WITH_ERROR:
+
+ cmd->scmd->result = (DID_OK << 16) | ext_status;
+ if (ext_status == SAM_STAT_CHECK_CONDITION) {
+ memset(cmd->scmd->sense_buffer, 0,
+ SCSI_SENSE_BUFFERSIZE);
+ memcpy(cmd->scmd->sense_buffer, cmd->sense,
+ SCSI_SENSE_BUFFERSIZE);
+ cmd->scmd->result |= DRIVER_SENSE << 24;
+ }
+ break;
+
+ case MFI_STAT_LD_OFFLINE:
+ case MFI_STAT_DEVICE_NOT_FOUND:
+ cmd->scmd->result = DID_BAD_TARGET << 16;
+ break;
+
+ default:
+ printk(KERN_DEBUG "megasas: FW status %#x\n", status);
+ cmd->scmd->result = DID_ERROR << 16;
+ break;
+ }
+}
+
+/**
+ * megasas_make_sgl_fusion - Prepares 32-bit SGL
+ * @instance: Adapter soft state
+ * @scp: SCSI command from the mid-layer
+ * @sgl_ptr: SGL to be filled in
+ * @cmd: cmd we are working on
+ *
+ * If successful, this function returns the number of SG elements.
+ */
+static int
+megasas_make_sgl_fusion(struct megasas_instance *instance,
+ struct scsi_cmnd *scp,
+ struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
+ struct megasas_cmd_fusion *cmd)
+{
+ int i, sg_processed;
+ int sge_count, sge_idx;
+ struct scatterlist *os_sgl;
+ struct fusion_context *fusion;
+
+ fusion = instance->ctrl_context;
+
+ cmd->io_request->ChainOffset = 0;
+
+ sge_count = scsi_dma_map(scp);
+
+ BUG_ON(sge_count < 0);
+
+ if (sge_count > instance->max_num_sge || !sge_count)
+ return sge_count;
+
+ if (sge_count > fusion->max_sge_in_main_msg) {
+ /* One element to store the chain info */
+ sge_idx = fusion->max_sge_in_main_msg - 1;
+ } else
+ sge_idx = sge_count;
+
+ scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+ sgl_ptr->Length = sg_dma_len(os_sgl);
+ sgl_ptr->Address = sg_dma_address(os_sgl);
+ sgl_ptr->Flags = 0;
+ sgl_ptr++;
+
+ sg_processed = i + 1;
+
+ if ((sg_processed == (fusion->max_sge_in_main_msg - 1)) &&
+ (sge_count > fusion->max_sge_in_main_msg)) {
+
+ struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
+ cmd->io_request->ChainOffset =
+ fusion->chain_offset_io_request;
+ sg_chain = sgl_ptr;
+ /* Prepare chain element */
+ sg_chain->NextChainOffset = 0;
+ sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+ MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
+ sg_chain->Length = (sizeof(union MPI2_SGE_IO_UNION)
+ *(sge_count - sg_processed));
+ sg_chain->Address = cmd->sg_frame_phys_addr;
+
+ sgl_ptr =
+ (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame;
+ }
+ }
+
+ return sge_count;
+}
+
+/**
+ * megasas_set_pd_lba - Sets PD LBA
+ * @cdb: CDB
+ * @cdb_len: cdb length
+ * @start_blk: Start block of IO
+ *
+ * Used to set the PD LBA in CDB for FP IOs
+ */
+void
+megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
+ struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
+ struct MR_FW_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
+{
+ struct MR_LD_RAID *raid;
+ u32 ld;
+ u64 start_blk = io_info->pdBlock;
+ u8 *cdb = io_request->CDB.CDB32;
+ u32 num_blocks = io_info->numBlocks;
+ u8 opcode, flagvals, groupnum, control;
+
+ /* Check if T10 PI (DIF) is enabled for this LD */
+ ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
+ raid = MR_LdRaidGet(ld, local_map_ptr);
+ if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) {
+ memset(cdb, 0, sizeof(io_request->CDB.CDB32));
+ cdb[0] = MEGASAS_SCSI_VARIABLE_LENGTH_CMD;
+ cdb[7] = MEGASAS_SCSI_ADDL_CDB_LEN;
+
+ if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+ cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_READ32;
+ else
+ cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_WRITE32;
+ cdb[10] = MEGASAS_RD_WR_PROTECT_CHECK_ALL;
+
+ /* LBA */
+ cdb[12] = (u8)((start_blk >> 56) & 0xff);
+ cdb[13] = (u8)((start_blk >> 48) & 0xff);
+ cdb[14] = (u8)((start_blk >> 40) & 0xff);
+ cdb[15] = (u8)((start_blk >> 32) & 0xff);
+ cdb[16] = (u8)((start_blk >> 24) & 0xff);
+ cdb[17] = (u8)((start_blk >> 16) & 0xff);
+ cdb[18] = (u8)((start_blk >> 8) & 0xff);
+ cdb[19] = (u8)(start_blk & 0xff);
+
+ /* Logical block reference tag */
+ io_request->CDB.EEDP32.PrimaryReferenceTag =
+ cpu_to_be32(ref_tag);
+ io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
+
+ io_request->DataLength = num_blocks * 512;
+ io_request->IoFlags = 32; /* Specify 32-byte cdb */
+
+ /* Transfer length */
+ cdb[28] = (u8)((num_blocks >> 24) & 0xff);
+ cdb[29] = (u8)((num_blocks >> 16) & 0xff);
+ cdb[30] = (u8)((num_blocks >> 8) & 0xff);
+ cdb[31] = (u8)(num_blocks & 0xff);
+
+ /* set SCSI IO EEDPFlags */
+ if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) {
+ io_request->EEDPFlags =
+ MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
+ } else {
+ io_request->EEDPFlags =
+ MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
+ MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
+ }
+ io_request->Control |= (0x4 << 26);
+ io_request->EEDPBlockSize = MEGASAS_EEDPBLOCKSIZE;
+ } else {
+ /* Some drives don't support 16/12 byte CDB's, convert to 10 */
+ if (((cdb_len == 12) || (cdb_len == 16)) &&
+ (start_blk <= 0xffffffff)) {
+ if (cdb_len == 16) {
+ opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
+ flagvals = cdb[1];
+ groupnum = cdb[14];
+ control = cdb[15];
+ } else {
+ opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
+ flagvals = cdb[1];
+ groupnum = cdb[10];
+ control = cdb[11];
+ }
+
+ memset(cdb, 0, sizeof(io_request->CDB.CDB32));
+
+ cdb[0] = opcode;
+ cdb[1] = flagvals;
+ cdb[6] = groupnum;
+ cdb[9] = control;
+
+ /* Transfer length */
+ cdb[8] = (u8)(num_blocks & 0xff);
+ cdb[7] = (u8)((num_blocks >> 8) & 0xff);
+
+ cdb_len = 10;
+ }
+
+ /* Normal case, just load LBA here */
+ switch (cdb_len) {
+ case 6:
+ {
+ u8 val = cdb[1] & 0xE0;
+ cdb[3] = (u8)(start_blk & 0xff);
+ cdb[2] = (u8)((start_blk >> 8) & 0xff);
+ cdb[1] = val | ((u8)(start_blk >> 16) & 0x1f);
+ break;
+ }
+ case 10:
+ cdb[5] = (u8)(start_blk & 0xff);
+ cdb[4] = (u8)((start_blk >> 8) & 0xff);
+ cdb[3] = (u8)((start_blk >> 16) & 0xff);
+ cdb[2] = (u8)((start_blk >> 24) & 0xff);
+ break;
+ case 12:
+ cdb[5] = (u8)(start_blk & 0xff);
+ cdb[4] = (u8)((start_blk >> 8) & 0xff);
+ cdb[3] = (u8)((start_blk >> 16) & 0xff);
+ cdb[2] = (u8)((start_blk >> 24) & 0xff);
+ break;
+ case 16:
+ cdb[9] = (u8)(start_blk & 0xff);
+ cdb[8] = (u8)((start_blk >> 8) & 0xff);
+ cdb[7] = (u8)((start_blk >> 16) & 0xff);
+ cdb[6] = (u8)((start_blk >> 24) & 0xff);
+ cdb[5] = (u8)((start_blk >> 32) & 0xff);
+ cdb[4] = (u8)((start_blk >> 40) & 0xff);
+ cdb[3] = (u8)((start_blk >> 48) & 0xff);
+ cdb[2] = (u8)((start_blk >> 56) & 0xff);
+ break;
+ }
+ }
+}
+
+/**
+ * megasas_build_ldio_fusion - Prepares IOs to devices
+ * @instance: Adapter soft state
+ * @scp: SCSI command
+ * @cmd: Command to be prepared
+ *
+ * Prepares the io_request and chain elements (sg_frame) for IO
+ * The IO can be for PD (Fast Path) or LD
+ */
+void
+megasas_build_ldio_fusion(struct megasas_instance *instance,
+ struct scsi_cmnd *scp,
+ struct megasas_cmd_fusion *cmd)
+{
+ u8 fp_possible;
+ u32 start_lba_lo, start_lba_hi, device_id;
+ struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
+ union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+ struct IO_REQUEST_INFO io_info;
+ struct fusion_context *fusion;
+ struct MR_FW_RAID_MAP_ALL *local_map_ptr;
+
+ device_id = MEGASAS_DEV_INDEX(instance, scp);
+
+ fusion = instance->ctrl_context;
+
+ io_request = cmd->io_request;
+ io_request->RaidContext.VirtualDiskTgtId = device_id;
+ io_request->RaidContext.status = 0;
+ io_request->RaidContext.exStatus = 0;
+
+ req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc;
+
+ start_lba_lo = 0;
+ start_lba_hi = 0;
+ fp_possible = 0;
+
+ /*
+ * 6-byte READ(0x08) or WRITE(0x0A) cdb
+ */
+ if (scp->cmd_len == 6) {
+ io_request->DataLength = (u32) scp->cmnd[4];
+ start_lba_lo = ((u32) scp->cmnd[1] << 16) |
+ ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
+
+ start_lba_lo &= 0x1FFFFF;
+ }
+
+ /*
+ * 10-byte READ(0x28) or WRITE(0x2A) cdb
+ */
+ else if (scp->cmd_len == 10) {
+ io_request->DataLength = (u32) scp->cmnd[8] |
+ ((u32) scp->cmnd[7] << 8);
+ start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+ ((u32) scp->cmnd[3] << 16) |
+ ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+ }
+
+ /*
+ * 12-byte READ(0xA8) or WRITE(0xAA) cdb
+ */
+ else if (scp->cmd_len == 12) {
+ io_request->DataLength = ((u32) scp->cmnd[6] << 24) |
+ ((u32) scp->cmnd[7] << 16) |
+ ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+ start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+ ((u32) scp->cmnd[3] << 16) |
+ ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+ }
+
+ /*
+ * 16-byte READ(0x88) or WRITE(0x8A) cdb
+ */
+ else if (scp->cmd_len == 16) {
+ io_request->DataLength = ((u32) scp->cmnd[10] << 24) |
+ ((u32) scp->cmnd[11] << 16) |
+ ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
+ start_lba_lo = ((u32) scp->cmnd[6] << 24) |
+ ((u32) scp->cmnd[7] << 16) |
+ ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+
+ start_lba_hi = ((u32) scp->cmnd[2] << 24) |
+ ((u32) scp->cmnd[3] << 16) |
+ ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+ }
+
+ memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
+ io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo;
+ io_info.numBlocks = io_request->DataLength;
+ io_info.ldTgtId = device_id;
+
+ if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+ io_info.isRead = 1;
+
+ local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
+
+ if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >=
+ MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io)) {
+ io_request->RaidContext.regLockFlags = 0;
+ fp_possible = 0;
+ } else {
+ if (MR_BuildRaidContext(&io_info, &io_request->RaidContext,
+ local_map_ptr))
+ fp_possible = io_info.fpOkForIo;
+ }
+
+ if (fp_possible) {
+ megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
+ local_map_ptr, start_lba_lo);
+ io_request->DataLength = scsi_bufflen(scp);
+ io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
+ << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
+ (io_info.isRead)) {
+ io_info.devHandle =
+ get_updated_dev_handle(
+ &fusion->load_balance_info[device_id],
+ &io_info);
+ scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG;
+ } else
+ scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
+ cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
+ io_request->DevHandle = io_info.devHandle;
+ } else {
+ io_request->RaidContext.timeoutValue =
+ local_map_ptr->raidMap.fpPdIoTimeoutSec;
+ io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
+ io_request->DevHandle = device_id;
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
+ << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ } /* Not FP */
+}
+
+/**
+ * megasas_build_dcdb_fusion - Prepares IOs to devices
+ * @instance: Adapter soft state
+ * @scp: SCSI command
+ * @cmd: Command to be prepared
+ *
+ * Prepares the io_request frame for non-io cmds
+ */
+static void
+megasas_build_dcdb_fusion(struct megasas_instance *instance,
+ struct scsi_cmnd *scmd,
+ struct megasas_cmd_fusion *cmd)
+{
+ u32 device_id;
+ struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
+ u16 pd_index = 0;
+ struct MR_FW_RAID_MAP_ALL *local_map_ptr;
+ struct fusion_context *fusion = instance->ctrl_context;
+
+ io_request = cmd->io_request;
+ device_id = MEGASAS_DEV_INDEX(instance, scmd);
+ pd_index = (scmd->device->channel * MEGASAS_MAX_DEV_PER_CHANNEL)
+ +scmd->device->id;
+ local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
+
+ /* Check if this is a system PD I/O */
+ if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) &&
+ (instance->pd_list[pd_index].driveType == TYPE_DISK)) {
+ io_request->Function = 0;
+ io_request->DevHandle =
+ local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+ io_request->RaidContext.timeoutValue =
+ local_map_ptr->raidMap.fpPdIoTimeoutSec;
+ io_request->RaidContext.regLockFlags = 0;
+ io_request->RaidContext.regLockRowLBA = 0;
+ io_request->RaidContext.regLockLength = 0;
+ io_request->RaidContext.RAIDFlags =
+ MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD <<
+ MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ } else {
+ io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
+ io_request->DevHandle = device_id;
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ }
+ io_request->RaidContext.VirtualDiskTgtId = device_id;
+ io_request->LUN[0] = scmd->device->lun;
+ io_request->DataLength = scsi_bufflen(scmd);
+}
+
+/**
+ * megasas_build_io_fusion - Prepares IOs to devices
+ * @instance: Adapter soft state
+ * @scp: SCSI command
+ * @cmd: Command to be prepared
+ *
+ * Invokes helper functions to prepare request frames
+ * and sets flags appropriate for IO/Non-IO cmd
+ */
+int
+megasas_build_io_fusion(struct megasas_instance *instance,
+ struct scsi_cmnd *scp,
+ struct megasas_cmd_fusion *cmd)
+{
+ u32 device_id, sge_count;
+ struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request;
+
+ device_id = MEGASAS_DEV_INDEX(instance, scp);
+
+ /* Zero out some fields so they don't get reused */
+ io_request->LUN[0] = 0;
+ io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
+ io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
+ io_request->EEDPFlags = 0;
+ io_request->Control = 0;
+ io_request->EEDPBlockSize = 0;
+ io_request->IoFlags = 0;
+ io_request->RaidContext.RAIDFlags = 0;
+
+ memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
+ /*
+ * Just the CDB length,rest of the Flags are zero
+ * This will be modified for FP in build_ldio_fusion
+ */
+ io_request->IoFlags = scp->cmd_len;
+
+ if (megasas_is_ldio(scp))
+ megasas_build_ldio_fusion(instance, scp, cmd);
+ else
+ megasas_build_dcdb_fusion(instance, scp, cmd);
+
+ /*
+ * Construct SGL
+ */
+
+ sge_count =
+ megasas_make_sgl_fusion(instance, scp,
+ (struct MPI25_IEEE_SGE_CHAIN64 *)
+ &io_request->SGL, cmd);
+
+ if (sge_count > instance->max_num_sge) {
+ printk(KERN_ERR "megasas: Error. sge_count (0x%x) exceeds "
+ "max (0x%x) allowed\n", sge_count,
+ instance->max_num_sge);
+ return 1;
+ }
+
+ io_request->RaidContext.numSGE = sge_count;
+
+ io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
+
+ if (scp->sc_data_direction == PCI_DMA_TODEVICE)
+ io_request->Control |= MPI2_SCSIIO_CONTROL_WRITE;
+ else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+ io_request->Control |= MPI2_SCSIIO_CONTROL_READ;
+
+ io_request->SGLOffset0 =
+ offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4;
+
+ io_request->SenseBufferLowAddress = cmd->sense_phys_addr;
+ io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
+
+ cmd->scmd = scp;
+ scp->SCp.ptr = (char *)cmd;
+
+ return 0;
+}
+
+union MEGASAS_REQUEST_DESCRIPTOR_UNION *
+megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
+{
+ u8 *p;
+ struct fusion_context *fusion;
+
+ if (index >= instance->max_fw_cmds) {
+ printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for "
+ "descriptor\n", index);
+ return NULL;
+ }
+ fusion = instance->ctrl_context;
+ p = fusion->req_frames_desc
+ +sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *index;
+
+ return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p;
+}
+
+/**
+ * megasas_build_and_issue_cmd_fusion -Main routine for building and
+ * issuing non IOCTL cmd
+ * @instance: Adapter soft state
+ * @scmd: pointer to scsi cmd from OS
+ */
+static u32
+megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
+ struct scsi_cmnd *scmd)
+{
+ struct megasas_cmd_fusion *cmd;
+ union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+ u32 index;
+ struct fusion_context *fusion;
+
+ fusion = instance->ctrl_context;
+
+ cmd = megasas_get_cmd_fusion(instance);
+ if (!cmd)
+ return SCSI_MLQUEUE_HOST_BUSY;
+
+ index = cmd->index;
+
+ req_desc = megasas_get_request_descriptor(instance, index-1);
+ if (!req_desc)
+ return 1;
+
+ req_desc->Words = 0;
+ cmd->request_desc = req_desc;
+ cmd->request_desc->Words = 0;
+
+ if (megasas_build_io_fusion(instance, scmd, cmd)) {
+ megasas_return_cmd_fusion(instance, cmd);
+ printk(KERN_ERR "megasas: Error building command.\n");
+ cmd->request_desc = NULL;
+ return 1;
+ }
+
+ req_desc = cmd->request_desc;
+ req_desc->SCSIIO.SMID = index;
+
+ if (cmd->io_request->ChainOffset != 0 &&
+ cmd->io_request->ChainOffset != 0xF)
+ printk(KERN_ERR "megasas: The chain offset value is not "
+ "correct : %x\n", cmd->io_request->ChainOffset);
+
+ /*
+ * Issue the command to the FW
+ */
+ atomic_inc(&instance->fw_outstanding);
+
+ instance->instancet->fire_cmd(instance,
+ req_desc->u.low, req_desc->u.high,
+ instance->reg_set);
+
+ return 0;
+}
+
+/**
+ * complete_cmd_fusion - Completes command
+ * @instance: Adapter soft state
+ * Completes all commands that is in reply descriptor queue
+ */
+int
+complete_cmd_fusion(struct megasas_instance *instance)
+{
+ union MPI2_REPLY_DESCRIPTORS_UNION *desc;
+ struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
+ struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req;
+ struct fusion_context *fusion;
+ struct megasas_cmd *cmd_mfi;
+ struct megasas_cmd_fusion *cmd_fusion;
+ u16 smid, num_completed;
+ u8 reply_descript_type, arm;
+ u32 status, extStatus, device_id;
+ union desc_value d_val;
+ struct LD_LOAD_BALANCE_INFO *lbinfo;
+
+ fusion = instance->ctrl_context;
+
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+ return IRQ_HANDLED;
+
+ desc = fusion->reply_frames_desc;
+ desc += fusion->last_reply_idx;
+
+ reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
+
+ d_val.word = desc->Words;
+
+ reply_descript_type = reply_desc->ReplyFlags &
+ MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+
+ if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+ return IRQ_NONE;
+
+ d_val.word = desc->Words;
+
+ num_completed = 0;
+
+ while ((d_val.u.low != UINT_MAX) && (d_val.u.high != UINT_MAX)) {
+ smid = reply_desc->SMID;
+
+ cmd_fusion = fusion->cmd_list[smid - 1];
+
+ scsi_io_req =
+ (struct MPI2_RAID_SCSI_IO_REQUEST *)
+ cmd_fusion->io_request;
+
+ if (cmd_fusion->scmd)
+ cmd_fusion->scmd->SCp.ptr = NULL;
+
+ status = scsi_io_req->RaidContext.status;
+ extStatus = scsi_io_req->RaidContext.exStatus;
+
+ switch (scsi_io_req->Function) {
+ case MPI2_FUNCTION_SCSI_IO_REQUEST: /*Fast Path IO.*/
+ /* Update load balancing info */
+ device_id = MEGASAS_DEV_INDEX(instance,
+ cmd_fusion->scmd);
+ lbinfo = &fusion->load_balance_info[device_id];
+ if (cmd_fusion->scmd->SCp.Status &
+ MEGASAS_LOAD_BALANCE_FLAG) {
+ arm = lbinfo->raid1DevHandle[0] ==
+ cmd_fusion->io_request->DevHandle ? 0 :
+ 1;
+ atomic_dec(&lbinfo->scsi_pending_cmds[arm]);
+ cmd_fusion->scmd->SCp.Status &=
+ ~MEGASAS_LOAD_BALANCE_FLAG;
+ }
+ if (reply_descript_type ==
+ MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
+ if (megasas_dbg_lvl == 5)
+ printk(KERN_ERR "\nmegasas: FAST Path "
+ "IO Success\n");
+ }
+ /* Fall thru and complete IO */
+ case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */
+ /* Map the FW Cmd Status */
+ map_cmd_status(cmd_fusion, status, extStatus);
+ scsi_dma_unmap(cmd_fusion->scmd);
+ cmd_fusion->scmd->scsi_done(cmd_fusion->scmd);
+ scsi_io_req->RaidContext.status = 0;
+ scsi_io_req->RaidContext.exStatus = 0;
+ megasas_return_cmd_fusion(instance, cmd_fusion);
+ atomic_dec(&instance->fw_outstanding);
+
+ break;
+ case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */
+ cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
+ megasas_complete_cmd(instance, cmd_mfi, DID_OK);
+ cmd_fusion->flags = 0;
+ megasas_return_cmd_fusion(instance, cmd_fusion);
+
+ break;
+ }
+
+ fusion->last_reply_idx++;
+ if (fusion->last_reply_idx >= fusion->reply_q_depth)
+ fusion->last_reply_idx = 0;
+
+ desc->Words = ULLONG_MAX;
+ num_completed++;
+
+ /* Get the next reply descriptor */
+ if (!fusion->last_reply_idx)
+ desc = fusion->reply_frames_desc;
+ else
+ desc++;
+
+ reply_desc =
+ (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
+
+ d_val.word = desc->Words;
+
+ reply_descript_type = reply_desc->ReplyFlags &
+ MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+
+ if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+ break;
+ }
+
+ if (!num_completed)
+ return IRQ_NONE;
+
+ wmb();
+ writel(fusion->last_reply_idx,
+ &instance->reg_set->reply_post_host_index);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * megasas_complete_cmd_dpc_fusion - Completes command
+ * @instance: Adapter soft state
+ *
+ * Tasklet to complete cmds
+ */
+void
+megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
+{
+ struct megasas_instance *instance =
+ (struct megasas_instance *)instance_addr;
+ unsigned long flags;
+
+ /* If we have already declared adapter dead, donot complete cmds */
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+ spin_lock_irqsave(&instance->completion_lock, flags);
+ complete_cmd_fusion(instance);
+ spin_unlock_irqrestore(&instance->completion_lock, flags);
+}
+
+/**
+ * megasas_isr_fusion - isr entry point
+ */
+irqreturn_t megasas_isr_fusion(int irq, void *devp)
+{
+ struct megasas_instance *instance = (struct megasas_instance *)devp;
+ u32 mfiStatus, fw_state;
+
+ if (!instance->msi_flag) {
+ mfiStatus = instance->instancet->clear_intr(instance->reg_set);
+ if (!mfiStatus)
+ return IRQ_NONE;
+ }
+
+ /* If we are resetting, bail */
+ if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags))
+ return IRQ_HANDLED;
+
+ if (!complete_cmd_fusion(instance)) {
+ /* If we didn't complete any commands, check for FW fault */
+ fw_state = instance->instancet->read_fw_status_reg(
+ instance->reg_set) & MFI_STATE_MASK;
+ if (fw_state == MFI_STATE_FAULT)
+ schedule_work(&instance->work_init);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru
+ * @instance: Adapter soft state
+ * mfi_cmd: megasas_cmd pointer
+ *
+ */
+u8
+build_mpt_mfi_pass_thru(struct megasas_instance *instance,
+ struct megasas_cmd *mfi_cmd)
+{
+ struct MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
+ struct MPI2_RAID_SCSI_IO_REQUEST *io_req;
+ struct megasas_cmd_fusion *cmd;
+ struct fusion_context *fusion;
+ struct megasas_header *frame_hdr = &mfi_cmd->frame->hdr;
+
+ cmd = megasas_get_cmd_fusion(instance);
+ if (!cmd)
+ return 1;
+
+ /* Save the smid. To be used for returning the cmd */
+ mfi_cmd->context.smid = cmd->index;
+
+ cmd->sync_cmd_idx = mfi_cmd->index;
+
+ /*
+ * For cmds where the flag is set, store the flag and check
+ * on completion. For cmds with this flag, don't call
+ * megasas_complete_cmd
+ */
+
+ if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE)
+ cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+ fusion = instance->ctrl_context;
+ io_req = cmd->io_request;
+ mpi25_ieee_chain =
+ (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
+
+ io_req->Function = MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
+ io_req->SGLOffset0 = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST,
+ SGL) / 4;
+ io_req->ChainOffset = fusion->chain_offset_mfi_pthru;
+
+ mpi25_ieee_chain->Address = mfi_cmd->frame_phys_addr;
+
+ mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+ MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
+
+ mpi25_ieee_chain->Length = MEGASAS_MAX_SZ_CHAIN_FRAME;
+
+ return 0;
+}
+
+/**
+ * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd
+ * @instance: Adapter soft state
+ * @cmd: mfi cmd to build
+ *
+ */
+union MEGASAS_REQUEST_DESCRIPTOR_UNION *
+build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+ union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+ u16 index;
+
+ if (build_mpt_mfi_pass_thru(instance, cmd)) {
+ printk(KERN_ERR "Couldn't build MFI pass thru cmd\n");
+ return NULL;
+ }
+
+ index = cmd->context.smid;
+
+ req_desc = megasas_get_request_descriptor(instance, index - 1);
+
+ if (!req_desc)
+ return NULL;
+
+ req_desc->Words = 0;
+ req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+
+ req_desc->SCSIIO.SMID = index;
+
+ return req_desc;
+}
+
+/**
+ * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd
+ * @instance: Adapter soft state
+ * @cmd: mfi cmd pointer
+ *
+ */
+void
+megasas_issue_dcmd_fusion(struct megasas_instance *instance,
+ struct megasas_cmd *cmd)
+{
+ union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+ union desc_value d_val;
+
+ req_desc = build_mpt_cmd(instance, cmd);
+ if (!req_desc) {
+ printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n");
+ return;
+ }
+ d_val.word = req_desc->Words;
+
+ instance->instancet->fire_cmd(instance, req_desc->u.low,
+ req_desc->u.high, instance->reg_set);
+}
+
+/**
+ * megasas_release_fusion - Reverses the FW initialization
+ * @intance: Adapter soft state
+ */
+void
+megasas_release_fusion(struct megasas_instance *instance)
+{
+ megasas_free_cmds(instance);
+ megasas_free_cmds_fusion(instance);
+
+ iounmap(instance->reg_set);
+
+ pci_release_selected_regions(instance->pdev, instance->bar);
+}
+
+/**
+ * megasas_read_fw_status_reg_fusion - returns the current FW status value
+ * @regs: MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs)
+{
+ return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_adp_reset_fusion - For controller reset
+ * @regs: MFI register set
+ */
+static int
+megasas_adp_reset_fusion(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ return 0;
+}
+
+/**
+ * megasas_check_reset_fusion - For controller reset check
+ * @regs: MFI register set
+ */
+static int
+megasas_check_reset_fusion(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ return 0;
+}
+
+/* This function waits for outstanding commands on fusion to complete */
+int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance)
+{
+ int i, outstanding, retval = 0;
+ u32 fw_state, wait_time = MEGASAS_RESET_WAIT_TIME;
+
+ for (i = 0; i < wait_time; i++) {
+ /* Check if firmware is in fault state */
+ fw_state = instance->instancet->read_fw_status_reg(
+ instance->reg_set) & MFI_STATE_MASK;
+ if (fw_state == MFI_STATE_FAULT) {
+ printk(KERN_WARNING "megasas: Found FW in FAULT state,"
+ " will reset adapter.\n");
+ retval = 1;
+ goto out;
+ }
+
+ outstanding = atomic_read(&instance->fw_outstanding);
+ if (!outstanding)
+ goto out;
+
+ if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+ printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
+ "commands to complete\n", i, outstanding);
+ megasas_complete_cmd_dpc_fusion(
+ (unsigned long)instance);
+ }
+ msleep(1000);
+ }
+
+ if (atomic_read(&instance->fw_outstanding)) {
+ printk("megaraid_sas: pending commands remain after waiting, "
+ "will reset adapter.\n");
+ retval = 1;
+ }
+out:
+ return retval;
+}
+
+void megasas_reset_reply_desc(struct megasas_instance *instance)
+{
+ int i;
+ struct fusion_context *fusion;
+ union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
+
+ fusion = instance->ctrl_context;
+ fusion->last_reply_idx = 0;
+ reply_desc = fusion->reply_frames_desc;
+ for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++)
+ reply_desc->Words = ULLONG_MAX;
+}
+
+/* Core fusion reset function */
+int megasas_reset_fusion(struct Scsi_Host *shost)
+{
+ int retval = SUCCESS, i, j, retry = 0;
+ struct megasas_instance *instance;
+ struct megasas_cmd_fusion *cmd_fusion;
+ struct fusion_context *fusion;
+ struct megasas_cmd *cmd_mfi;
+ union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+ u32 host_diag, abs_state;
+
+ instance = (struct megasas_instance *)shost->hostdata;
+ fusion = instance->ctrl_context;
+
+ mutex_lock(&instance->reset_mutex);
+ set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
+ instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
+ instance->instancet->disable_intr(instance->reg_set);
+ msleep(1000);
+
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+ printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
+ "returning FAILED.\n");
+ retval = FAILED;
+ goto out;
+ }
+
+ /* First try waiting for commands to complete */
+ if (megasas_wait_for_outstanding_fusion(instance)) {
+ printk(KERN_WARNING "megaraid_sas: resetting fusion "
+ "adapter.\n");
+ /* Now return commands back to the OS */
+ for (i = 0 ; i < instance->max_fw_cmds; i++) {
+ cmd_fusion = fusion->cmd_list[i];
+ if (cmd_fusion->scmd) {
+ scsi_dma_unmap(cmd_fusion->scmd);
+ cmd_fusion->scmd->result = (DID_RESET << 16);
+ cmd_fusion->scmd->scsi_done(cmd_fusion->scmd);
+ megasas_return_cmd_fusion(instance, cmd_fusion);
+ atomic_dec(&instance->fw_outstanding);
+ }
+ }
+
+ if (instance->disableOnlineCtrlReset == 1) {
+ /* Reset not supported, kill adapter */
+ printk(KERN_WARNING "megaraid_sas: Reset not supported"
+ ", killing adapter.\n");
+ megaraid_sas_kill_hba(instance);
+ instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
+ retval = FAILED;
+ goto out;
+ }
+
+ /* Now try to reset the chip */
+ for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
+ writel(MPI2_WRSEQ_FLUSH_KEY_VALUE,
+ &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_1ST_KEY_VALUE,
+ &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_2ND_KEY_VALUE,
+ &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_3RD_KEY_VALUE,
+ &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_4TH_KEY_VALUE,
+ &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_5TH_KEY_VALUE,
+ &instance->reg_set->fusion_seq_offset);
+ writel(MPI2_WRSEQ_6TH_KEY_VALUE,
+ &instance->reg_set->fusion_seq_offset);
+
+ /* Check that the diag write enable (DRWE) bit is on */
+ host_diag = readl(&instance->reg_set->fusion_host_diag);
+ while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
+ msleep(100);
+ host_diag =
+ readl(&instance->reg_set->fusion_host_diag);
+ if (retry++ == 100) {
+ printk(KERN_WARNING "megaraid_sas: "
+ "Host diag unlock failed!\n");
+ break;
+ }
+ }
+ if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
+ continue;
+
+ /* Send chip reset command */
+ writel(host_diag | HOST_DIAG_RESET_ADAPTER,
+ &instance->reg_set->fusion_host_diag);
+ msleep(3000);
+
+ /* Make sure reset adapter bit is cleared */
+ host_diag = readl(&instance->reg_set->fusion_host_diag);
+ retry = 0;
+ while (host_diag & HOST_DIAG_RESET_ADAPTER) {
+ msleep(100);
+ host_diag =
+ readl(&instance->reg_set->fusion_host_diag);
+ if (retry++ == 1000) {
+ printk(KERN_WARNING "megaraid_sas: "
+ "Diag reset adapter never "
+ "cleared!\n");
+ break;
+ }
+ }
+ if (host_diag & HOST_DIAG_RESET_ADAPTER)
+ continue;
+
+ abs_state =
+ instance->instancet->read_fw_status_reg(
+ instance->reg_set);
+ retry = 0;
+
+ while ((abs_state <= MFI_STATE_FW_INIT) &&
+ (retry++ < 1000)) {
+ msleep(100);
+ abs_state =
+ instance->instancet->read_fw_status_reg(
+ instance->reg_set);
+ }
+ if (abs_state <= MFI_STATE_FW_INIT) {
+ printk(KERN_WARNING "megaraid_sas: firmware "
+ "state < MFI_STATE_FW_INIT, state = "
+ "0x%x\n", abs_state);
+ continue;
+ }
+
+ /* Wait for FW to become ready */
+ if (megasas_transition_to_ready(instance)) {
+ printk(KERN_WARNING "megaraid_sas: Failed to "
+ "transition controller to ready.\n");
+ continue;
+ }
+
+ megasas_reset_reply_desc(instance);
+ if (megasas_ioc_init_fusion(instance)) {
+ printk(KERN_WARNING "megaraid_sas: "
+ "megasas_ioc_init_fusion() failed!\n");
+ continue;
+ }
+
+ instance->instancet->enable_intr(instance->reg_set);
+ instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+
+ /* Re-fire management commands */
+ for (j = 0 ; j < instance->max_fw_cmds; j++) {
+ cmd_fusion = fusion->cmd_list[j];
+ if (cmd_fusion->sync_cmd_idx !=
+ (u32)ULONG_MAX) {
+ cmd_mfi =
+ instance->
+ cmd_list[cmd_fusion->sync_cmd_idx];
+ if (cmd_mfi->frame->dcmd.opcode ==
+ MR_DCMD_LD_MAP_GET_INFO) {
+ megasas_return_cmd(instance,
+ cmd_mfi);
+ megasas_return_cmd_fusion(
+ instance, cmd_fusion);
+ } else {
+ req_desc =
+ megasas_get_request_descriptor(
+ instance,
+ cmd_mfi->context.smid
+ -1);
+ if (!req_desc)
+ printk(KERN_WARNING
+ "req_desc NULL"
+ "\n");
+ else {
+ instance->instancet->
+ fire_cmd(instance,
+ req_desc->
+ u.low,
+ req_desc->
+ u.high,
+ instance->
+ reg_set);
+ }
+ }
+ }
+ }
+
+ /* Reset load balance info */
+ memset(fusion->load_balance_info, 0,
+ sizeof(struct LD_LOAD_BALANCE_INFO)
+ *MAX_LOGICAL_DRIVES);
+
+ if (!megasas_get_map_info(instance))
+ megasas_sync_map_info(instance);
+
+ /* Adapter reset completed successfully */
+ printk(KERN_WARNING "megaraid_sas: Reset "
+ "successful.\n");
+ retval = SUCCESS;
+ goto out;
+ }
+ /* Reset failed, kill the adapter */
+ printk(KERN_WARNING "megaraid_sas: Reset failed, killing "
+ "adapter.\n");
+ megaraid_sas_kill_hba(instance);
+ retval = FAILED;
+ } else {
+ instance->instancet->enable_intr(instance->reg_set);
+ instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+ }
+out:
+ clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
+ mutex_unlock(&instance->reset_mutex);
+ return retval;
+}
+
+/* Fusion OCR work queue */
+void megasas_fusion_ocr_wq(struct work_struct *work)
+{
+ struct megasas_instance *instance =
+ container_of(work, struct megasas_instance, work_init);
+
+ megasas_reset_fusion(instance->host);
+}
+
+struct megasas_instance_template megasas_instance_template_fusion = {
+ .fire_cmd = megasas_fire_cmd_fusion,
+ .enable_intr = megasas_enable_intr_fusion,
+ .disable_intr = megasas_disable_intr_fusion,
+ .clear_intr = megasas_clear_intr_fusion,
+ .read_fw_status_reg = megasas_read_fw_status_reg_fusion,
+ .adp_reset = megasas_adp_reset_fusion,
+ .check_reset = megasas_check_reset_fusion,
+ .service_isr = megasas_isr_fusion,
+ .tasklet = megasas_complete_cmd_dpc_fusion,
+ .init_adapter = megasas_init_adapter_fusion,
+ .build_and_issue_cmd = megasas_build_and_issue_cmd_fusion,
+ .issue_dcmd = megasas_issue_dcmd_fusion,
+};
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
new file mode 100644
index 00000000000..82b577a72c8
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -0,0 +1,695 @@
+/*
+ * Linux MegaRAID driver for SAS based RAID controllers
+ *
+ * Copyright (c) 2009-2011 LSI Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * FILE: megaraid_sas_fusion.h
+ *
+ * Authors: LSI Corporation
+ * Manoj Jose
+ * Sumant Patro
+ *
+ * Send feedback to: <megaraidlinux@lsi.com>
+ *
+ * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ * ATTN: Linuxraid
+ */
+
+#ifndef _MEGARAID_SAS_FUSION_H_
+#define _MEGARAID_SAS_FUSION_H_
+
+/* Fusion defines */
+#define MEGASAS_MAX_SZ_CHAIN_FRAME 1024
+#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009)
+#define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256
+#define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0
+#define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST 0xF1
+#define MEGASAS_LOAD_BALANCE_FLAG 0x1
+#define MEGASAS_DCMD_MBOX_PEND_FLAG 0x1
+#define HOST_DIAG_WRITE_ENABLE 0x80
+#define HOST_DIAG_RESET_ADAPTER 0x4
+#define MEGASAS_FUSION_MAX_RESET_TRIES 3
+
+/* T10 PI defines */
+#define MR_PROT_INFO_TYPE_CONTROLLER 0x8
+#define MEGASAS_SCSI_VARIABLE_LENGTH_CMD 0x7f
+#define MEGASAS_SCSI_SERVICE_ACTION_READ32 0x9
+#define MEGASAS_SCSI_SERVICE_ACTION_WRITE32 0xB
+#define MEGASAS_SCSI_ADDL_CDB_LEN 0x18
+#define MEGASAS_RD_WR_PROTECT_CHECK_ALL 0x20
+#define MEGASAS_RD_WR_PROTECT_CHECK_NONE 0x60
+#define MEGASAS_EEDPBLOCKSIZE 512
+
+/*
+ * Raid context flags
+ */
+
+#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT 0x4
+#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_MASK 0x30
+enum MR_RAID_FLAGS_IO_SUB_TYPE {
+ MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0,
+ MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1,
+};
+
+/*
+ * Request descriptor types
+ */
+#define MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO 0x7
+#define MEGASAS_REQ_DESCRIPT_FLAGS_MFA 0x1
+
+#define MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT 1
+
+#define MEGASAS_FP_CMD_LEN 16
+#define MEGASAS_FUSION_IN_RESET 0
+
+/*
+ * Raid Context structure which describes MegaRAID specific IO Paramenters
+ * This resides at offset 0x60 where the SGL normally starts in MPT IO Frames
+ */
+
+struct RAID_CONTEXT {
+ u16 resvd0;
+ u16 timeoutValue;
+ u8 regLockFlags;
+ u8 resvd1;
+ u16 VirtualDiskTgtId;
+ u64 regLockRowLBA;
+ u32 regLockLength;
+ u16 nextLMId;
+ u8 exStatus;
+ u8 status;
+ u8 RAIDFlags;
+ u8 numSGE;
+ u16 configSeqNum;
+ u8 spanArm;
+ u8 resvd2[3];
+};
+
+#define RAID_CTX_SPANARM_ARM_SHIFT (0)
+#define RAID_CTX_SPANARM_ARM_MASK (0x1f)
+
+#define RAID_CTX_SPANARM_SPAN_SHIFT (5)
+#define RAID_CTX_SPANARM_SPAN_MASK (0xE0)
+
+/*
+ * define region lock types
+ */
+enum REGION_TYPE {
+ REGION_TYPE_UNUSED = 0,
+ REGION_TYPE_SHARED_READ = 1,
+ REGION_TYPE_SHARED_WRITE = 2,
+ REGION_TYPE_EXCLUSIVE = 3,
+};
+
+/* MPI2 defines */
+#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */
+#define MPI2_WHOINIT_HOST_DRIVER (0x04)
+#define MPI2_VERSION_MAJOR (0x02)
+#define MPI2_VERSION_MINOR (0x00)
+#define MPI2_VERSION_MAJOR_MASK (0xFF00)
+#define MPI2_VERSION_MAJOR_SHIFT (8)
+#define MPI2_VERSION_MINOR_MASK (0x00FF)
+#define MPI2_VERSION_MINOR_SHIFT (0)
+#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
+ MPI2_VERSION_MINOR)
+#define MPI2_HEADER_VERSION_UNIT (0x10)
+#define MPI2_HEADER_VERSION_DEV (0x00)
+#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
+#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
+#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF)
+#define MPI2_HEADER_VERSION_DEV_SHIFT (0)
+#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \
+ MPI2_HEADER_VERSION_DEV)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
+#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
+#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */
+#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02)
+#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000)
+#define MPI2_SCSIIO_CONTROL_READ (0x02000000)
+#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F)
+#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0)
+#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004)
+#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF)
+#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4)
+#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB)
+#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2)
+#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7)
+#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD)
+
+struct MPI25_IEEE_SGE_CHAIN64 {
+ u64 Address;
+ u32 Length;
+ u16 Reserved1;
+ u8 NextChainOffset;
+ u8 Flags;
+};
+
+struct MPI2_SGE_SIMPLE_UNION {
+ u32 FlagsLength;
+ union {
+ u32 Address32;
+ u64 Address64;
+ } u;
+};
+
+struct MPI2_SCSI_IO_CDB_EEDP32 {
+ u8 CDB[20]; /* 0x00 */
+ u32 PrimaryReferenceTag; /* 0x14 */
+ u16 PrimaryApplicationTag; /* 0x18 */
+ u16 PrimaryApplicationTagMask; /* 0x1A */
+ u32 TransferLength; /* 0x1C */
+};
+
+struct MPI2_SGE_CHAIN_UNION {
+ u16 Length;
+ u8 NextChainOffset;
+ u8 Flags;
+ union {
+ u32 Address32;
+ u64 Address64;
+ } u;
+};
+
+struct MPI2_IEEE_SGE_SIMPLE32 {
+ u32 Address;
+ u32 FlagsLength;
+};
+
+struct MPI2_IEEE_SGE_CHAIN32 {
+ u32 Address;
+ u32 FlagsLength;
+};
+
+struct MPI2_IEEE_SGE_SIMPLE64 {
+ u64 Address;
+ u32 Length;
+ u16 Reserved1;
+ u8 Reserved2;
+ u8 Flags;
+};
+
+struct MPI2_IEEE_SGE_CHAIN64 {
+ u64 Address;
+ u32 Length;
+ u16 Reserved1;
+ u8 Reserved2;
+ u8 Flags;
+};
+
+union MPI2_IEEE_SGE_SIMPLE_UNION {
+ struct MPI2_IEEE_SGE_SIMPLE32 Simple32;
+ struct MPI2_IEEE_SGE_SIMPLE64 Simple64;
+};
+
+union MPI2_IEEE_SGE_CHAIN_UNION {
+ struct MPI2_IEEE_SGE_CHAIN32 Chain32;
+ struct MPI2_IEEE_SGE_CHAIN64 Chain64;
+};
+
+union MPI2_SGE_IO_UNION {
+ struct MPI2_SGE_SIMPLE_UNION MpiSimple;
+ struct MPI2_SGE_CHAIN_UNION MpiChain;
+ union MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
+ union MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;
+};
+
+union MPI2_SCSI_IO_CDB_UNION {
+ u8 CDB32[32];
+ struct MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
+ struct MPI2_SGE_SIMPLE_UNION SGE;
+};
+
+/*
+ * RAID SCSI IO Request Message
+ * Total SGE count will be one less than _MPI2_SCSI_IO_REQUEST
+ */
+struct MPI2_RAID_SCSI_IO_REQUEST {
+ u16 DevHandle; /* 0x00 */
+ u8 ChainOffset; /* 0x02 */
+ u8 Function; /* 0x03 */
+ u16 Reserved1; /* 0x04 */
+ u8 Reserved2; /* 0x06 */
+ u8 MsgFlags; /* 0x07 */
+ u8 VP_ID; /* 0x08 */
+ u8 VF_ID; /* 0x09 */
+ u16 Reserved3; /* 0x0A */
+ u32 SenseBufferLowAddress; /* 0x0C */
+ u16 SGLFlags; /* 0x10 */
+ u8 SenseBufferLength; /* 0x12 */
+ u8 Reserved4; /* 0x13 */
+ u8 SGLOffset0; /* 0x14 */
+ u8 SGLOffset1; /* 0x15 */
+ u8 SGLOffset2; /* 0x16 */
+ u8 SGLOffset3; /* 0x17 */
+ u32 SkipCount; /* 0x18 */
+ u32 DataLength; /* 0x1C */
+ u32 BidirectionalDataLength; /* 0x20 */
+ u16 IoFlags; /* 0x24 */
+ u16 EEDPFlags; /* 0x26 */
+ u32 EEDPBlockSize; /* 0x28 */
+ u32 SecondaryReferenceTag; /* 0x2C */
+ u16 SecondaryApplicationTag; /* 0x30 */
+ u16 ApplicationTagTranslationMask; /* 0x32 */
+ u8 LUN[8]; /* 0x34 */
+ u32 Control; /* 0x3C */
+ union MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
+ struct RAID_CONTEXT RaidContext; /* 0x60 */
+ union MPI2_SGE_IO_UNION SGL; /* 0x80 */
+};
+
+/*
+ * MPT RAID MFA IO Descriptor.
+ */
+struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR {
+ u32 RequestFlags:8;
+ u32 MessageAddress1:24; /* bits 31:8*/
+ u32 MessageAddress2; /* bits 61:32 */
+};
+
+/* Default Request Descriptor */
+struct MPI2_DEFAULT_REQUEST_DESCRIPTOR {
+ u8 RequestFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u16 LMID; /* 0x04 */
+ u16 DescriptorTypeDependent; /* 0x06 */
+};
+
+/* High Priority Request Descriptor */
+struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR {
+ u8 RequestFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u16 LMID; /* 0x04 */
+ u16 Reserved1; /* 0x06 */
+};
+
+/* SCSI IO Request Descriptor */
+struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR {
+ u8 RequestFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u16 LMID; /* 0x04 */
+ u16 DevHandle; /* 0x06 */
+};
+
+/* SCSI Target Request Descriptor */
+struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR {
+ u8 RequestFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u16 LMID; /* 0x04 */
+ u16 IoIndex; /* 0x06 */
+};
+
+/* RAID Accelerator Request Descriptor */
+struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR {
+ u8 RequestFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u16 LMID; /* 0x04 */
+ u16 Reserved; /* 0x06 */
+};
+
+/* union of Request Descriptors */
+union MEGASAS_REQUEST_DESCRIPTOR_UNION {
+ struct MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
+ struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority;
+ struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO;
+ struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
+ struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator;
+ struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR MFAIo;
+ union {
+ struct {
+ u32 low;
+ u32 high;
+ } u;
+ u64 Words;
+ };
+};
+
+/* Default Reply Descriptor */
+struct MPI2_DEFAULT_REPLY_DESCRIPTOR {
+ u8 ReplyFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 DescriptorTypeDependent1; /* 0x02 */
+ u32 DescriptorTypeDependent2; /* 0x04 */
+};
+
+/* Address Reply Descriptor */
+struct MPI2_ADDRESS_REPLY_DESCRIPTOR {
+ u8 ReplyFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u32 ReplyFrameAddress; /* 0x04 */
+};
+
+/* SCSI IO Success Reply Descriptor */
+struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR {
+ u8 ReplyFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u16 TaskTag; /* 0x04 */
+ u16 Reserved1; /* 0x06 */
+};
+
+/* TargetAssist Success Reply Descriptor */
+struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR {
+ u8 ReplyFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u8 SequenceNumber; /* 0x04 */
+ u8 Reserved1; /* 0x05 */
+ u16 IoIndex; /* 0x06 */
+};
+
+/* Target Command Buffer Reply Descriptor */
+struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR {
+ u8 ReplyFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u8 VP_ID; /* 0x02 */
+ u8 Flags; /* 0x03 */
+ u16 InitiatorDevHandle; /* 0x04 */
+ u16 IoIndex; /* 0x06 */
+};
+
+/* RAID Accelerator Success Reply Descriptor */
+struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR {
+ u8 ReplyFlags; /* 0x00 */
+ u8 MSIxIndex; /* 0x01 */
+ u16 SMID; /* 0x02 */
+ u32 Reserved; /* 0x04 */
+};
+
+/* union of Reply Descriptors */
+union MPI2_REPLY_DESCRIPTORS_UNION {
+ struct MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
+ struct MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply;
+ struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess;
+ struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
+ struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
+ struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR
+ RAIDAcceleratorSuccess;
+ u64 Words;
+};
+
+/* IOCInit Request message */
+struct MPI2_IOC_INIT_REQUEST {
+ u8 WhoInit; /* 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 */
+ u16 MsgVersion; /* 0x0C */
+ u16 HeaderVersion; /* 0x0E */
+ u32 Reserved5; /* 0x10 */
+ u16 Reserved6; /* 0x14 */
+ u8 Reserved7; /* 0x16 */
+ u8 HostMSIxVectors; /* 0x17 */
+ u16 Reserved8; /* 0x18 */
+ u16 SystemRequestFrameSize; /* 0x1A */
+ u16 ReplyDescriptorPostQueueDepth; /* 0x1C */
+ u16 ReplyFreeQueueDepth; /* 0x1E */
+ u32 SenseBufferAddressHigh; /* 0x20 */
+ u32 SystemReplyAddressHigh; /* 0x24 */
+ u64 SystemRequestFrameBaseAddress; /* 0x28 */
+ u64 ReplyDescriptorPostQueueAddress;/* 0x30 */
+ u64 ReplyFreeQueueAddress; /* 0x38 */
+ u64 TimeStamp; /* 0x40 */
+};
+
+/* mrpriv defines */
+#define MR_PD_INVALID 0xFFFF
+#define MAX_SPAN_DEPTH 8
+#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
+#define MAX_ROW_SIZE 32
+#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
+#define MAX_LOGICAL_DRIVES 64
+#define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES)
+#define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES)
+#define MAX_ARRAYS 128
+#define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS)
+#define MAX_PHYSICAL_DEVICES 256
+#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
+#define MR_DCMD_LD_MAP_GET_INFO 0x0300e101
+
+struct MR_DEV_HANDLE_INFO {
+ u16 curDevHdl;
+ u8 validHandles;
+ u8 reserved;
+ u16 devHandle[2];
+};
+
+struct MR_ARRAY_INFO {
+ u16 pd[MAX_RAIDMAP_ROW_SIZE];
+};
+
+struct MR_QUAD_ELEMENT {
+ u64 logStart;
+ u64 logEnd;
+ u64 offsetInSpan;
+ u32 diff;
+ u32 reserved1;
+};
+
+struct MR_SPAN_INFO {
+ u32 noElements;
+ u32 reserved1;
+ struct MR_QUAD_ELEMENT quad[MAX_RAIDMAP_SPAN_DEPTH];
+};
+
+struct MR_LD_SPAN {
+ u64 startBlk;
+ u64 numBlks;
+ u16 arrayRef;
+ u8 reserved[6];
+};
+
+struct MR_SPAN_BLOCK_INFO {
+ u64 num_rows;
+ struct MR_LD_SPAN span;
+ struct MR_SPAN_INFO block_span_info;
+};
+
+struct MR_LD_RAID {
+ struct {
+ u32 fpCapable:1;
+ u32 reserved5:3;
+ u32 ldPiMode:4;
+ u32 pdPiMode:4;
+ u32 encryptionType:8;
+ u32 fpWriteCapable:1;
+ u32 fpReadCapable:1;
+ u32 fpWriteAcrossStripe:1;
+ u32 fpReadAcrossStripe:1;
+ u32 reserved4:8;
+ } capability;
+ u32 reserved6;
+ u64 size;
+ u8 spanDepth;
+ u8 level;
+ u8 stripeShift;
+ u8 rowSize;
+ u8 rowDataSize;
+ u8 writeMode;
+ u8 PRL;
+ u8 SRL;
+ u16 targetId;
+ u8 ldState;
+ u8 regTypeReqOnWrite;
+ u8 modFactor;
+ u8 reserved2[1];
+ u16 seqNum;
+
+ struct {
+ u32 ldSyncRequired:1;
+ u32 reserved:31;
+ } flags;
+
+ u8 reserved3[0x5C];
+};
+
+struct MR_LD_SPAN_MAP {
+ struct MR_LD_RAID ldRaid;
+ u8 dataArmMap[MAX_RAIDMAP_ROW_SIZE];
+ struct MR_SPAN_BLOCK_INFO spanBlock[MAX_RAIDMAP_SPAN_DEPTH];
+};
+
+struct MR_FW_RAID_MAP {
+ u32 totalSize;
+ union {
+ struct {
+ u32 maxLd;
+ u32 maxSpanDepth;
+ u32 maxRowSize;
+ u32 maxPdCount;
+ u32 maxArrays;
+ } validationInfo;
+ u32 version[5];
+ u32 reserved1[5];
+ };
+
+ u32 ldCount;
+ u32 Reserved1;
+ u8 ldTgtIdToLd[MAX_RAIDMAP_LOGICAL_DRIVES+
+ MAX_RAIDMAP_VIEWS];
+ u8 fpPdIoTimeoutSec;
+ u8 reserved2[7];
+ struct MR_ARRAY_INFO arMapInfo[MAX_RAIDMAP_ARRAYS];
+ struct MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
+ struct MR_LD_SPAN_MAP ldSpanMap[1];
+};
+
+struct IO_REQUEST_INFO {
+ u64 ldStartBlock;
+ u32 numBlocks;
+ u16 ldTgtId;
+ u8 isRead;
+ u16 devHandle;
+ u64 pdBlock;
+ u8 fpOkForIo;
+};
+
+struct MR_LD_TARGET_SYNC {
+ u8 targetId;
+ u8 reserved;
+ u16 seqNum;
+};
+
+#define IEEE_SGE_FLAGS_ADDR_MASK (0x03)
+#define IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
+#define IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
+#define IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
+#define IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
+#define IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
+#define IEEE_SGE_FLAGS_END_OF_LIST (0x40)
+
+struct megasas_register_set;
+struct megasas_instance;
+
+union desc_word {
+ u64 word;
+ struct {
+ u32 low;
+ u32 high;
+ } u;
+};
+
+struct megasas_cmd_fusion {
+ struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
+ dma_addr_t io_request_phys_addr;
+
+ union MPI2_SGE_IO_UNION *sg_frame;
+ dma_addr_t sg_frame_phys_addr;
+
+ u8 *sense;
+ dma_addr_t sense_phys_addr;
+
+ struct list_head list;
+ struct scsi_cmnd *scmd;
+ struct megasas_instance *instance;
+
+ u8 retry_for_fw_reset;
+ union MEGASAS_REQUEST_DESCRIPTOR_UNION *request_desc;
+
+ /*
+ * Context for a MFI frame.
+ * Used to get the mfi cmd from list when a MFI cmd is completed
+ */
+ u32 sync_cmd_idx;
+ u32 index;
+ u8 flags;
+};
+
+struct LD_LOAD_BALANCE_INFO {
+ u8 loadBalanceFlag;
+ u8 reserved1;
+ u16 raid1DevHandle[2];
+ atomic_t scsi_pending_cmds[2];
+ u64 last_accessed_block[2];
+};
+
+struct MR_FW_RAID_MAP_ALL {
+ struct MR_FW_RAID_MAP raidMap;
+ struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
+} __attribute__ ((packed));
+
+struct fusion_context {
+ struct megasas_cmd_fusion **cmd_list;
+ struct list_head cmd_pool;
+
+ spinlock_t cmd_pool_lock;
+
+ dma_addr_t req_frames_desc_phys;
+ u8 *req_frames_desc;
+
+ struct dma_pool *io_request_frames_pool;
+ dma_addr_t io_request_frames_phys;
+ u8 *io_request_frames;
+
+ struct dma_pool *sg_dma_pool;
+ struct dma_pool *sense_dma_pool;
+
+ dma_addr_t reply_frames_desc_phys;
+ union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc;
+ struct dma_pool *reply_frames_desc_pool;
+
+ u16 last_reply_idx;
+
+ u32 reply_q_depth;
+ u32 request_alloc_sz;
+ u32 reply_alloc_sz;
+ u32 io_frames_alloc_sz;
+
+ u16 max_sge_in_main_msg;
+ u16 max_sge_in_chain;
+
+ u8 chain_offset_io_request;
+ u8 chain_offset_mfi_pthru;
+
+ struct MR_FW_RAID_MAP_ALL *ld_map[2];
+ dma_addr_t ld_map_phys[2];
+
+ u32 map_sz;
+ u8 fast_path_io;
+ struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
+};
+
+union desc_value {
+ u64 word;
+ struct {
+ u32 low;
+ u32 high;
+ } u;
+};
+
+#endif /* _MEGARAID_SAS_FUSION_H_ */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index 4b1c2f0350f..8be75e65f76 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.15
+ * mpi2.h Version: 02.00.16
*
* Version History
* ---------------
@@ -61,6 +61,8 @@
* Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL.
* Added defines for product-specific range of message
* function codes, 0xF0 to 0xFF.
+ * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Added alternative defines for the SGE Direction bit.
* --------------------------------------------------------------------------
*/
@@ -86,7 +88,7 @@
#define MPI2_VERSION_02_00 (0x0200)
/* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x0F)
+#define MPI2_HEADER_VERSION_UNIT (0x10)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@@ -929,6 +931,9 @@ typedef struct _MPI2_MPI_SGE_UNION
#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00)
#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04)
+#define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST)
+#define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC)
+
/* Address Size */
#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
index e3728d736d8..d76a6584760 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.14
+ * mpi2_cnfg.h Version: 02.00.15
*
* Version History
* ---------------
@@ -121,6 +121,10 @@
* 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.
+ * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT
+ * define.
+ * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
+ * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
* --------------------------------------------------------------------------
*/
@@ -333,7 +337,7 @@ typedef struct _MPI2_CONFIG_REQUEST
#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06)
#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07)
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
/* Config Reply Message */
@@ -379,6 +383,8 @@ typedef struct _MPI2_CONFIG_REPLY
#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064)
#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065)
+#define MPI2_MFGPAGE_DEVID_SSS6200 (0x007E)
+
#define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080)
#define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081)
#define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082)
@@ -390,6 +396,8 @@ typedef struct _MPI2_CONFIG_REPLY
#define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E)
+
+
/* Manufacturing Page 0 */
typedef struct _MPI2_CONFIG_PAGE_MAN_0
@@ -729,6 +737,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1
/* IO Unit Page 1 Flags defines */
#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY (0x00000800)
#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600)
+#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT (9)
#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000)
#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200)
#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400)
@@ -1347,6 +1356,7 @@ typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0
#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000)
#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000)
#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT (0x00000080)
#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040)
#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020)
#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000)
@@ -1469,11 +1479,15 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0
#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03)
#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04)
#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE (0x06)
#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF)
/* PhysDiskAttributes defines */
+#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK (0x0C)
#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08)
#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04)
+
+#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK (0x03)
#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02)
#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01)
@@ -1545,6 +1559,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03)
#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04)
#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05)
+#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06)
#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08)
#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09)
#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A)
@@ -1571,6 +1586,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000)
#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000)
+#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION (27)
#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE (0x00000000)
#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL (0x08000000)
#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER (0x10000000)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
index bd6c92b5fae..b1e88f26b74 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
@@ -291,6 +291,7 @@ mpi2_raid.h
* can be sized by the build environment.
* 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of
* VolumeCreationFlags and marked the old one as obsolete.
+ * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
* --------------------------------------------------------------------------
mpi2_sas.h
@@ -301,6 +302,7 @@ mpi2_sas.h
* Request.
* 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
* to MPI2_SGE_IO_UNION since it supports chained SGLs.
+ * 05-12-10 02.00.04 Modified some comments.
* --------------------------------------------------------------------------
mpi2_targ.h
@@ -324,6 +326,7 @@ mpi2_tool.h
* and reply messages.
* Added MPI2_DIAG_BUF_TYPE_EXTENDED.
* Incremented MPI2_DIAG_BUF_TYPE_COUNT.
+ * 05-12-10 02.00.05 Added Diagnostic Data Upload tool.
* --------------------------------------------------------------------------
mpi2_type.h
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
index c4c99dfcb82..20e6b886934 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.09
+ * mpi2_init.h Version: 02.00.10
*
* Version History
* ---------------
@@ -32,6 +32,7 @@
* 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.
+ * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request.
* --------------------------------------------------------------------------
*/
@@ -98,7 +99,13 @@ typedef struct _MPI2_SCSI_IO_REQUEST
U8 LUN[8]; /* 0x34 */
U32 Control; /* 0x3C */
MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
+
+#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */
+ MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion;
+#endif
+
MPI2_SGE_IO_UNION SGL; /* 0x60 */
+
} MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST,
Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t;
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
index 495bedc4d1f..761cbdb8a03 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.14
+ * mpi2_ioc.h Version: 02.00.15
*
* Version History
* ---------------
@@ -101,6 +101,8 @@
* 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines.
* Added PowerManagementControl Request structures and
* defines.
+ * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete.
+ * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
* --------------------------------------------------------------------------
*/
@@ -456,7 +458,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
#define MPI2_EVENT_STATE_CHANGE (0x0002)
#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005)
#define MPI2_EVENT_EVENT_CHANGE (0x000A)
-#define MPI2_EVENT_TASK_SET_FULL (0x000E)
+#define MPI2_EVENT_TASK_SET_FULL (0x000E) /* obsolete */
#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F)
#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014)
#define MPI2_EVENT_SAS_DISCOVERY (0x0016)
@@ -517,6 +519,7 @@ typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED
MPI2_POINTER pMpi2EventDataHardResetReceived_t;
/* Task Set Full Event data */
+/* this event is obsolete */
typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL
{
@@ -831,6 +834,7 @@ typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST
#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03)
#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04)
#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05)
+#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06)
#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08)
#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09)
#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
index 5160c33d2a0..bd61a7b60a2 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2008 LSI Corporation.
+ * Copyright (c) 2000-2010 LSI Corporation.
*
*
* Name: mpi2_raid.h
* Title: MPI Integrated RAID messages and structures
* Creation Date: April 26, 2007
*
- * mpi2_raid.h Version: 02.00.04
+ * mpi2_raid.h Version: 02.00.05
*
* Version History
* ---------------
@@ -22,6 +22,7 @@
* can be sized by the build environment.
* 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of
* VolumeCreationFlags and marked the old one as obsolete.
+ * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
* --------------------------------------------------------------------------
*/
@@ -260,6 +261,7 @@ typedef struct _MPI2_RAID_VOL_INDICATOR
#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002)
#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003)
+#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004)
/* RAID Action Reply ActionData union */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
index 2d8aeed5139..608f6d6e6fc 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2007 LSI Corporation.
+ * Copyright (c) 2000-2010 LSI Corporation.
*
*
* Name: mpi2_sas.h
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: February 9, 2007
*
- * mpi2.h Version: 02.00.03
+ * mpi2_sas.h Version: 02.00.04
*
* Version History
* ---------------
@@ -20,6 +20,7 @@
* Request.
* 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
* to MPI2_SGE_IO_UNION since it supports chained SGLs.
+ * 05-12-10 02.00.04 Modified some comments.
* --------------------------------------------------------------------------
*/
@@ -110,7 +111,7 @@ typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST
/* values for PassthroughFlags field */
#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
/* SMP Passthrough Reply Message */
@@ -174,7 +175,7 @@ typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
/* SATA Passthrough Reply Message */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
index 686b09b8121..5c6e3a67bb9 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
@@ -6,7 +6,7 @@
* Title: MPI diagnostic tool structures and definitions
* Creation Date: March 26, 2007
*
- * mpi2_tool.h Version: 02.00.04
+ * mpi2_tool.h Version: 02.00.05
*
* Version History
* ---------------
@@ -22,6 +22,7 @@
* and reply messages.
* Added MPI2_DIAG_BUF_TYPE_EXTENDED.
* Incremented MPI2_DIAG_BUF_TYPE_COUNT.
+ * 05-12-10 02.00.05 Added Diagnostic Data Upload tool.
* --------------------------------------------------------------------------
*/
@@ -37,6 +38,7 @@
/* defines for the Tools */
#define MPI2_TOOLBOX_CLEAN_TOOL (0x00)
#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01)
+#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02)
#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03)
#define MPI2_TOOLBOX_BEACON_TOOL (0x05)
#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06)
@@ -102,8 +104,7 @@ typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST
* Toolbox Memory Move request
****************************************************************************/
-typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST
-{
+typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST {
U8 Tool; /* 0x00 */
U8 Reserved1; /* 0x01 */
U8 ChainOffset; /* 0x02 */
@@ -120,6 +121,44 @@ typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST
/****************************************************************************
+* Toolbox Diagnostic Data Upload request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST {
+ U8 Tool; /* 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 SGLFlags; /* 0x0C */
+ U8 Reserved5; /* 0x0D */
+ U16 Reserved6; /* 0x0E */
+ U32 Flags; /* 0x10 */
+ U32 DataLength; /* 0x14 */
+ MPI2_SGE_SIMPLE_UNION SGL; /* 0x18 */
+} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
+MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
+Mpi2ToolboxDiagDataUploadRequest_t,
+MPI2_POINTER pMpi2ToolboxDiagDataUploadRequest_t;
+
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER {
+ U32 DiagDataLength; /* 00h */
+ U8 FormatCode; /* 04h */
+ U8 Reserved1; /* 05h */
+ U16 Reserved2; /* 06h */
+} MPI2_DIAG_DATA_UPLOAD_HEADER, MPI2_POINTER PTR_MPI2_DIAG_DATA_UPLOAD_HEADER,
+Mpi2DiagDataUploadHeader_t, MPI2_POINTER pMpi2DiagDataUploadHeader_t;
+
+
+/****************************************************************************
* Toolbox ISTWI Read Write Tool
****************************************************************************/
@@ -162,7 +201,7 @@ typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST {
#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11)
#define MPI2_TOOL_ISTWI_ACTION_RESET (0x12)
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
/* Toolbox ISTWI Read Write Tool reply message */
@@ -248,7 +287,7 @@ typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
Mpi2ToolboxDiagnosticCliRequest_t,
MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t;
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
/* Toolbox Diagnostic CLI Tool reply message */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 12faf64f91b..b2a817055b8 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -65,7 +65,6 @@
static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
-#define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */
static int max_queue_depth = -1;
module_param(max_queue_depth, int, 0);
@@ -79,6 +78,10 @@ static int msix_disable = -1;
module_param(msix_disable, int, 0);
MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
+static int missing_delay[2] = {-1, -1};
+module_param_array(missing_delay, int, NULL, 0);
+MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
+
/* diag_buffer_enable is bitwise
* bit 0 set = TRACE
* bit 1 set = SNAPSHOT
@@ -515,9 +518,6 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
case MPI2_EVENT_EVENT_CHANGE:
desc = "Event Change";
break;
- case MPI2_EVENT_TASK_SET_FULL:
- desc = "Task Set Full";
- break;
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
desc = "Device Status Change";
break;
@@ -758,7 +758,7 @@ _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
if (smid < ioc->internal_smid) {
i = smid - ioc->hi_priority_smid;
cb_idx = ioc->hpr_lookup[i].cb_idx;
- } else {
+ } else if (smid <= ioc->hba_queue_depth) {
i = smid - ioc->internal_smid;
cb_idx = ioc->internal_lookup[i].cb_idx;
}
@@ -848,6 +848,7 @@ _base_interrupt(int irq, void *bus_id)
return IRQ_NONE;
completed_cmds = 0;
+ cb_idx = 0xFF;
do {
rd.word = rpf->Words;
if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
@@ -860,6 +861,9 @@ _base_interrupt(int irq, void *bus_id)
MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
reply = le32_to_cpu
(rpf->AddressReply.ReplyFrameAddress);
+ if (reply > ioc->reply_dma_max_address ||
+ reply < ioc->reply_dma_min_address)
+ reply = 0;
} else if (request_desript_type ==
MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
goto next;
@@ -1489,6 +1493,7 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
{
unsigned long flags;
int i;
+ struct chain_tracker *chain_req, *next;
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
if (smid >= ioc->hi_priority_smid) {
@@ -1511,6 +1516,14 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
/* scsiio queue */
i = smid - 1;
+ if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
+ list_for_each_entry_safe(chain_req, next,
+ &ioc->scsi_lookup[i].chain_list, tracker_list) {
+ list_del_init(&chain_req->tracker_list);
+ list_add_tail(&chain_req->tracker_list,
+ &ioc->free_chain_list);
+ }
+ }
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].scmd = NULL;
list_add_tail(&ioc->scsi_lookup[i].tracker_list,
@@ -1819,6 +1832,97 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
}
/**
+ * _base_update_missing_delay - change the missing delay timers
+ * @ioc: per adapter object
+ * @device_missing_delay: amount of time till device is reported missing
+ * @io_missing_delay: interval IO is returned when there is a missing device
+ *
+ * Return nothing.
+ *
+ * Passed on the command line, this function will modify the device missing
+ * delay, as well as the io missing delay. This should be called at driver
+ * load time.
+ */
+static void
+_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
+ u16 device_missing_delay, u8 io_missing_delay)
+{
+ u16 dmd, dmd_new, dmd_orignal;
+ u8 io_missing_delay_original;
+ u16 sz;
+ Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+ Mpi2ConfigReply_t mpi_reply;
+ u8 num_phys = 0;
+ u16 ioc_status;
+
+ mpt2sas_config_get_number_hba_phys(ioc, &num_phys);
+ if (!num_phys)
+ return;
+
+ sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
+ sizeof(Mpi2SasIOUnit1PhyData_t));
+ sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
+ if (!sas_iounit_pg1) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
+ sas_iounit_pg1, sz))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+
+ /* device missing delay */
+ dmd = sas_iounit_pg1->ReportDeviceMissingDelay;
+ if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
+ dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
+ else
+ dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
+ dmd_orignal = dmd;
+ if (device_missing_delay > 0x7F) {
+ dmd = (device_missing_delay > 0x7F0) ? 0x7F0 :
+ device_missing_delay;
+ dmd = dmd / 16;
+ dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16;
+ } else
+ dmd = device_missing_delay;
+ sas_iounit_pg1->ReportDeviceMissingDelay = dmd;
+
+ /* io missing delay */
+ io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay;
+ sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay;
+
+ if (!mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
+ sz)) {
+ if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
+ dmd_new = (dmd &
+ MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
+ else
+ dmd_new =
+ dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
+ printk(MPT2SAS_INFO_FMT "device_missing_delay: old(%d), "
+ "new(%d)\n", ioc->name, dmd_orignal, dmd_new);
+ printk(MPT2SAS_INFO_FMT "ioc_missing_delay: old(%d), "
+ "new(%d)\n", ioc->name, io_missing_delay_original,
+ io_missing_delay);
+ ioc->device_missing_delay = dmd_new;
+ ioc->io_missing_delay = io_missing_delay;
+ }
+
+out:
+ kfree(sas_iounit_pg1);
+}
+
+/**
* _base_static_config_pages - static start of day config pages
* @ioc: per adapter object
*
@@ -1855,6 +1959,7 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
+
}
/**
@@ -1868,6 +1973,8 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
static void
_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
{
+ int i;
+
dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -1932,6 +2039,20 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
}
kfree(ioc->hpr_lookup);
kfree(ioc->internal_lookup);
+ if (ioc->chain_lookup) {
+ for (i = 0; i < ioc->chain_depth; i++) {
+ if (ioc->chain_lookup[i].chain_buffer)
+ pci_pool_free(ioc->chain_dma_pool,
+ ioc->chain_lookup[i].chain_buffer,
+ ioc->chain_lookup[i].chain_buffer_dma);
+ }
+ if (ioc->chain_dma_pool)
+ pci_pool_destroy(ioc->chain_dma_pool);
+ }
+ if (ioc->chain_lookup) {
+ free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
+ ioc->chain_lookup = NULL;
+ }
}
@@ -1953,6 +2074,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
u32 sz, total_sz;
u32 retry_sz;
u16 max_request_credit;
+ int i;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@@ -1970,14 +2092,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
}
/* command line tunables for max controller queue depth */
- if (max_queue_depth != -1) {
+ if (max_queue_depth != -1)
max_request_credit = (max_queue_depth < facts->RequestCredit)
? max_queue_depth : facts->RequestCredit;
- } else {
- max_request_credit = (facts->RequestCredit >
- MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE :
- facts->RequestCredit;
- }
+ else
+ max_request_credit = facts->RequestCredit;
ioc->hba_queue_depth = max_request_credit;
ioc->hi_priority_depth = facts->HighPriorityCredit;
@@ -2083,7 +2202,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
* "frame for smid=0
*/
ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
- sz = ((ioc->scsiio_depth + 1 + ioc->chain_depth) * ioc->request_sz);
+ sz = ((ioc->scsiio_depth + 1) * ioc->request_sz);
/* hi-priority queue */
sz += (ioc->hi_priority_depth * ioc->request_sz);
@@ -2124,19 +2243,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
ioc->request_sz);
- ioc->chain = ioc->internal + (ioc->internal_depth *
- ioc->request_sz);
- ioc->chain_dma = ioc->internal_dma + (ioc->internal_depth *
- ioc->request_sz);
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
"depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
ioc->request, ioc->hba_queue_depth, ioc->request_sz,
(ioc->hba_queue_depth * ioc->request_sz)/1024));
- dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth"
- "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain,
- ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
- ioc->request_sz))/1024));
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
ioc->name, (unsigned long long) ioc->request_dma));
total_sz += sz;
@@ -2155,6 +2266,38 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
"depth(%d)\n", ioc->name, ioc->request,
ioc->scsiio_depth));
+ /* loop till the allocation succeeds */
+ do {
+ sz = ioc->chain_depth * sizeof(struct chain_tracker);
+ ioc->chain_pages = get_order(sz);
+ ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
+ GFP_KERNEL, ioc->chain_pages);
+ if (ioc->chain_lookup == NULL)
+ ioc->chain_depth -= 100;
+ } while (ioc->chain_lookup == NULL);
+ ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
+ ioc->request_sz, 16, 0);
+ if (!ioc->chain_dma_pool) {
+ printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create "
+ "failed\n", ioc->name);
+ goto out;
+ }
+ for (i = 0; i < ioc->chain_depth; i++) {
+ ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
+ ioc->chain_dma_pool , GFP_KERNEL,
+ &ioc->chain_lookup[i].chain_buffer_dma);
+ if (!ioc->chain_lookup[i].chain_buffer) {
+ ioc->chain_depth = i;
+ goto chain_done;
+ }
+ total_sz += ioc->request_sz;
+ }
+chain_done:
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth"
+ "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
+ ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
+ ioc->request_sz))/1024));
+
/* initialize hi-priority queue smid's */
ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
sizeof(struct request_tracker), GFP_KERNEL);
@@ -2221,6 +2364,8 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
ioc->name);
goto out;
}
+ ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
+ ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
"(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
@@ -2302,7 +2447,6 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
return 0;
out:
- _base_release_memory_pools(ioc);
return -ENOMEM;
}
@@ -3485,6 +3629,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
INIT_LIST_HEAD(&ioc->free_list);
smid = 1;
for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
+ INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].smid = smid;
ioc->scsi_lookup[i].scmd = NULL;
@@ -3511,6 +3656,13 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
list_add_tail(&ioc->internal_lookup[i].tracker_list,
&ioc->internal_free_list);
}
+
+ /* chain pool */
+ INIT_LIST_HEAD(&ioc->free_chain_list);
+ for (i = 0; i < ioc->chain_depth; i++)
+ list_add_tail(&ioc->chain_lookup[i].tracker_list,
+ &ioc->free_chain_list);
+
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
/* initialize Reply Free Queue */
@@ -3708,12 +3860,15 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
_base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
_base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
_base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
- _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL);
_base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
r = _base_make_ioc_operational(ioc, CAN_SLEEP);
if (r)
goto out_free_resources;
+ if (missing_delay[0] != -1 && missing_delay[1] != -1)
+ _base_update_missing_delay(ioc, missing_delay[0],
+ missing_delay[1]);
+
mpt2sas_base_start_watchdog(ioc);
return 0;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 0b15a8bdebf..283568c6fb0 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,8 +69,8 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "06.100.00.00"
-#define MPT2SAS_MAJOR_VERSION 06
+#define MPT2SAS_DRIVER_VERSION "07.100.00.00"
+#define MPT2SAS_MAJOR_VERSION 07
#define MPT2SAS_MINOR_VERSION 100
#define MPT2SAS_BUILD_VERSION 00
#define MPT2SAS_RELEASE_VERSION 00
@@ -419,6 +419,18 @@ enum reset_type {
};
/**
+ * struct chain_tracker - firmware chain tracker
+ * @chain_buffer: chain buffer
+ * @chain_buffer_dma: physical address
+ * @tracker_list: list of free request (ioc->free_chain_list)
+ */
+struct chain_tracker {
+ void *chain_buffer;
+ dma_addr_t chain_buffer_dma;
+ struct list_head tracker_list;
+};
+
+/**
* struct request_tracker - firmware request tracker
* @smid: system message id
* @scmd: scsi request pointer
@@ -430,6 +442,7 @@ struct request_tracker {
u16 smid;
struct scsi_cmnd *scmd;
u8 cb_idx;
+ struct list_head chain_list;
struct list_head tracker_list;
};
@@ -704,8 +717,10 @@ struct MPT2SAS_ADAPTER {
wait_queue_head_t reset_wq;
/* chain */
- u8 *chain;
- dma_addr_t chain_dma;
+ struct chain_tracker *chain_lookup;
+ struct list_head free_chain_list;
+ struct dma_pool *chain_dma_pool;
+ ulong chain_pages;
u16 max_sges_in_main_message;
u16 max_sges_in_chain_message;
u16 chains_needed_per_io;
@@ -737,6 +752,8 @@ struct MPT2SAS_ADAPTER {
u16 reply_sz;
u8 *reply;
dma_addr_t reply_dma;
+ u32 reply_dma_max_address;
+ u32 reply_dma_min_address;
struct dma_pool *reply_dma_pool;
/* reply free queue */
@@ -832,6 +849,8 @@ int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
ulong timeout, struct scsi_cmnd *scmd);
void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
+void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
+void mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc,
u16 handle);
struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 40cb8aeb21b..e92b77af548 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -81,6 +81,7 @@ enum block_state {
BLOCKING,
};
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
/**
* _ctl_sas_device_find_by_handle - sas device search
* @ioc: per adapter object
@@ -107,7 +108,6 @@ _ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
return r;
}
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
/**
* _ctl_display_some_debug - debug routine
* @ioc: per adapter object
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 1a96a00418a..eda347c5797 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -931,31 +931,32 @@ _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id,
}
/**
- * _scsih_get_chain_buffer_dma - obtain block of chains (dma address)
+ * _scsih_get_chain_buffer_tracker - obtain chain tracker
* @ioc: per adapter object
- * @smid: system request message index
+ * @smid: smid associated to an IO request
*
- * Returns phys pointer to chain buffer.
+ * Returns chain tracker(from ioc->free_chain_list)
*/
-static dma_addr_t
-_scsih_get_chain_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+static struct chain_tracker *
+_scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
{
- return ioc->chain_dma + ((smid - 1) * (ioc->request_sz *
- ioc->chains_needed_per_io));
-}
+ struct chain_tracker *chain_req;
+ unsigned long flags;
-/**
- * _scsih_get_chain_buffer - obtain block of chains assigned to a mf request
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns virt pointer to chain buffer.
- */
-static void *
-_scsih_get_chain_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
- return (void *)(ioc->chain + ((smid - 1) * (ioc->request_sz *
- ioc->chains_needed_per_io)));
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ if (list_empty(&ioc->free_chain_list)) {
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ printk(MPT2SAS_WARN_FMT "chain buffers not available\n",
+ ioc->name);
+ return NULL;
+ }
+ chain_req = list_entry(ioc->free_chain_list.next,
+ struct chain_tracker, tracker_list);
+ list_del_init(&chain_req->tracker_list);
+ list_add_tail(&chain_req->tracker_list,
+ &ioc->scsi_lookup[smid - 1].chain_list);
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ return chain_req;
}
/**
@@ -986,6 +987,7 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
u32 sgl_flags;
u32 sgl_flags_last_element;
u32 sgl_flags_end_buffer;
+ struct chain_tracker *chain_req;
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
@@ -1033,8 +1035,11 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
/* initializing the chain flags and pointers */
chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
- chain = _scsih_get_chain_buffer(ioc, smid);
- chain_dma = _scsih_get_chain_buffer_dma(ioc, smid);
+ chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
+ if (!chain_req)
+ return -1;
+ chain = chain_req->chain_buffer;
+ chain_dma = chain_req->chain_buffer_dma;
do {
sges_in_segment = (sges_left <=
ioc->max_sges_in_chain_message) ? sges_left :
@@ -1070,8 +1075,11 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
sges_in_segment--;
}
- chain_dma += ioc->request_sz;
- chain += ioc->request_sz;
+ chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
+ if (!chain_req)
+ return -1;
+ chain = chain_req->chain_buffer;
+ chain_dma = chain_req->chain_buffer_dma;
} while (1);
@@ -1094,28 +1102,24 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
}
/**
- * _scsih_change_queue_depth - setting device queue depth
+ * _scsih_adjust_queue_depth - setting device queue depth
* @sdev: scsi device struct
* @qdepth: requested queue depth
- * @reason: calling context
*
- * Returns queue depth.
+ *
+ * Returns nothing
*/
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+static void
+_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
{
struct Scsi_Host *shost = sdev->host;
int max_depth;
- int tag_type;
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
struct MPT2SAS_DEVICE *sas_device_priv_data;
struct MPT2SAS_TARGET *sas_target_priv_data;
struct _sas_device *sas_device;
unsigned long flags;
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
max_depth = shost->can_queue;
/* limit max device queue for SATA to 32 */
@@ -1141,8 +1145,27 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
max_depth = 1;
if (qdepth > max_depth)
qdepth = max_depth;
- tag_type = (qdepth == 1) ? 0 : MSG_SIMPLE_TAG;
- scsi_adjust_queue_depth(sdev, tag_type, qdepth);
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+}
+
+/**
+ * _scsih_change_queue_depth - setting device queue depth
+ * @sdev: scsi device struct
+ * @qdepth: requested queue depth
+ * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
+ * (see include/scsi/scsi_host.h for definition)
+ *
+ * Returns queue depth.
+ */
+static int
+_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+{
+ if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
+ _scsih_adjust_queue_depth(sdev, qdepth);
+ else if (reason == SCSI_QDEPTH_QFULL)
+ scsi_track_queue_full(sdev, qdepth);
+ else
+ return -EOPNOTSUPP;
if (sdev->inquiry_len > 7)
sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
@@ -2251,13 +2274,13 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
struct scsi_target *starget = scmd->device->sdev_target;
- starget_printk(KERN_INFO, starget, "attempting target reset! "
+ starget_printk(KERN_INFO, starget, "attempting device 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) {
- starget_printk(KERN_INFO, starget, "target been deleted! "
+ starget_printk(KERN_INFO, starget, "device been deleted! "
"scmd(%p)\n", scmd);
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
@@ -2576,9 +2599,9 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
&sas_expander->sas_port_list, port_list) {
if (mpt2sas_port->remote_identify.device_type ==
- MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+ SAS_EDGE_EXPANDER_DEVICE ||
mpt2sas_port->remote_identify.device_type ==
- MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
+ SAS_FANOUT_EXPANDER_DEVICE) {
spin_lock_irqsave(&ioc->sas_node_lock, flags);
expander_sibling =
@@ -2715,9 +2738,10 @@ static u8
_scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
u8 msix_index, u32 reply)
{
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
Mpi2SasIoUnitControlReply_t *mpi_reply =
mpt2sas_base_get_reply_virt_addr(ioc, reply);
-
+#endif
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
"sc_complete:handle(0x%04x), (open) "
"smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -3963,6 +3987,7 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
Mpi2ConfigReply_t mpi_reply;
Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
u16 attached_handle;
+ u8 link_rate;
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
"updating handles for sas_host(0x%016llx)\n",
@@ -3984,15 +4009,17 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
goto out;
for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
+ link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
if (i == 0)
ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
PhyData[0].ControllerDevHandle);
ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
AttachedDevHandle);
+ if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
+ link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
- attached_handle, i, sas_iounit_pg0->PhyData[i].
- NegotiatedLinkRate >> 4);
+ attached_handle, i, link_rate);
}
out:
kfree(sas_iounit_pg0);
@@ -4336,14 +4363,14 @@ _scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
}
/**
- * _scsih_expander_remove - removing expander object
+ * mpt2sas_expander_remove - removing expander object
* @ioc: per adapter object
* @sas_address: expander sas_address
*
* Return nothing.
*/
-static void
-_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
+void
+mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
{
struct _sas_node *sas_expander;
unsigned long flags;
@@ -4354,6 +4381,11 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
spin_lock_irqsave(&ioc->sas_node_lock, flags);
sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
sas_address);
+ if (!sas_expander) {
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ return;
+ }
+ list_del(&sas_expander->list);
spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
_scsih_expander_node_remove(ioc, sas_expander);
}
@@ -4643,6 +4675,33 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
sas_device_backup.sas_address));
}
+/**
+ * mpt2sas_device_remove - removing device object
+ * @ioc: per adapter object
+ * @sas_address: expander sas_address
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
+{
+ struct _sas_device *sas_device;
+ unsigned long flags;
+
+ if (ioc->shost_recovery)
+ return;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_address);
+ if (!sas_device) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ _scsih_remove_device(ioc, sas_device);
+}
+
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
/**
* _scsih_sas_topology_change_event_debug - debug for topology event
@@ -4737,7 +4796,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
int i;
u16 parent_handle, handle;
u16 reason_code;
- u8 phy_number;
+ u8 phy_number, max_phys;
struct _sas_node *sas_expander;
struct _sas_device *sas_device;
u64 sas_address;
@@ -4775,11 +4834,13 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
parent_handle);
spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- if (sas_expander)
+ if (sas_expander) {
sas_address = sas_expander->sas_address;
- else if (parent_handle < ioc->sas_hba.num_phys)
+ max_phys = sas_expander->num_phys;
+ } else if (parent_handle < ioc->sas_hba.num_phys) {
sas_address = ioc->sas_hba.sas_address;
- else
+ max_phys = ioc->sas_hba.num_phys;
+ } else
return;
/* handle siblings events */
@@ -4793,6 +4854,8 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
ioc->pci_error_recovery)
return;
phy_number = event_data->StartPhyNum + i;
+ if (phy_number >= max_phys)
+ continue;
reason_code = event_data->PHY[i].PhyStatus &
MPI2_EVENT_SAS_TOPO_RC_MASK;
if ((event_data->PHY[i].PhyStatus &
@@ -4844,7 +4907,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
/* handle expander removal */
if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
sas_expander)
- _scsih_expander_remove(ioc, sas_address);
+ mpt2sas_expander_remove(ioc, sas_address);
}
@@ -5773,90 +5836,6 @@ _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
}
/**
- * _scsih_task_set_full - handle task set full
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Throttle back qdepth.
- */
-static void
-_scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
- *fw_event)
-{
- unsigned long flags;
- struct _sas_device *sas_device;
- static struct _raid_device *raid_device;
- struct scsi_device *sdev;
- int depth;
- u16 current_depth;
- u16 handle;
- int id, channel;
- u64 sas_address;
- Mpi2EventDataTaskSetFull_t *event_data = fw_event->event_data;
-
- current_depth = le16_to_cpu(event_data->CurrentDepth);
- handle = le16_to_cpu(event_data->DevHandle);
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
- if (!sas_device) {
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- return;
- }
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- id = sas_device->id;
- channel = sas_device->channel;
- sas_address = sas_device->sas_address;
-
- /* if hidden raid component, then change to volume characteristics */
- 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);
- spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
- if (raid_device) {
- id = raid_device->id;
- channel = raid_device->channel;
- handle = raid_device->handle;
- sas_address = raid_device->wwid;
- }
- }
-
- if (ioc->logging_level & MPT_DEBUG_TASK_SET_FULL)
- 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);
-
- shost_for_each_device(sdev, ioc->shost) {
- if (sdev->id == id && sdev->channel == channel) {
- if (current_depth > sdev->queue_depth) {
- if (ioc->logging_level &
- MPT_DEBUG_TASK_SET_FULL)
- sdev_printk(KERN_INFO, sdev, "strange "
- "observation, the queue depth is"
- " (%d) meanwhile fw queue depth "
- "is (%d)\n", sdev->queue_depth,
- current_depth);
- continue;
- }
- depth = scsi_track_queue_full(sdev,
- current_depth - 1);
- if (depth > 0)
- sdev_printk(KERN_INFO, sdev, "Queue depth "
- "reduced to (%d)\n", depth);
- else if (depth < 0)
- sdev_printk(KERN_INFO, sdev, "Tagged Command "
- "Queueing is being disabled\n");
- else if (depth == 0)
- if (ioc->logging_level &
- MPT_DEBUG_TASK_SET_FULL)
- sdev_printk(KERN_INFO, sdev,
- "Queue depth not changed yet\n");
- }
- }
-}
-
-/**
* _scsih_prep_device_scan - initialize parameters prior to device scan
* @ioc: per adapter object
*
@@ -6219,7 +6198,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
sas_expander->responding = 0;
continue;
}
- _scsih_expander_remove(ioc, sas_expander->sas_address);
+ mpt2sas_expander_remove(ioc, sas_expander->sas_address);
goto retry_expander_search;
}
}
@@ -6343,9 +6322,6 @@ _firmware_event_work(struct work_struct *work)
case MPI2_EVENT_IR_OPERATION_STATUS:
_scsih_sas_ir_operation_status_event(ioc, fw_event);
break;
- case MPI2_EVENT_TASK_SET_FULL:
- _scsih_task_set_full(ioc, fw_event);
- break;
}
_scsih_fw_event_free(ioc, fw_event);
}
@@ -6415,7 +6391,6 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
case MPI2_EVENT_SAS_DISCOVERY:
case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
case MPI2_EVENT_IR_PHYSICAL_DISK:
- case MPI2_EVENT_TASK_SET_FULL:
break;
default: /* ignore the rest */
@@ -6490,56 +6465,23 @@ static void
_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
struct _sas_node *sas_expander)
{
- struct _sas_port *mpt2sas_port;
- struct _sas_device *sas_device;
- struct _sas_node *expander_sibling;
- unsigned long flags;
-
- if (!sas_expander)
- return;
+ struct _sas_port *mpt2sas_port, *next;
/* remove sibling ports attached to this expander */
- retry_device_search:
- list_for_each_entry(mpt2sas_port,
+ list_for_each_entry_safe(mpt2sas_port, next,
&sas_expander->sas_port_list, port_list) {
+ if (ioc->shost_recovery)
+ return;
if (mpt2sas_port->remote_identify.device_type ==
- SAS_END_DEVICE) {
- spin_lock_irqsave(&ioc->sas_device_lock, flags);
- sas_device =
- mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
- mpt2sas_port->remote_identify.sas_address);
- spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!sas_device)
- continue;
- _scsih_remove_device(ioc, sas_device);
- if (ioc->shost_recovery)
- return;
- goto retry_device_search;
- }
- }
-
- retry_expander_search:
- list_for_each_entry(mpt2sas_port,
- &sas_expander->sas_port_list, port_list) {
-
- if (mpt2sas_port->remote_identify.device_type ==
- MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+ SAS_END_DEVICE)
+ mpt2sas_device_remove(ioc,
+ mpt2sas_port->remote_identify.sas_address);
+ else if (mpt2sas_port->remote_identify.device_type ==
+ SAS_EDGE_EXPANDER_DEVICE ||
mpt2sas_port->remote_identify.device_type ==
- MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
-
- spin_lock_irqsave(&ioc->sas_node_lock, flags);
- expander_sibling =
- mpt2sas_scsih_expander_find_by_sas_address(
- ioc, mpt2sas_port->remote_identify.sas_address);
- spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
- if (!expander_sibling)
- continue;
- _scsih_expander_remove(ioc,
- expander_sibling->sas_address);
- if (ioc->shost_recovery)
- return;
- goto retry_expander_search;
- }
+ SAS_FANOUT_EXPANDER_DEVICE)
+ mpt2sas_expander_remove(ioc,
+ mpt2sas_port->remote_identify.sas_address);
}
mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
@@ -6550,7 +6492,6 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
sas_expander->handle, (unsigned long long)
sas_expander->sas_address);
- list_del(&sas_expander->list);
kfree(sas_expander->phy);
kfree(sas_expander);
}
@@ -6668,9 +6609,7 @@ _scsih_remove(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
- struct _sas_port *mpt2sas_port;
- struct _sas_device *sas_device;
- struct _sas_node *expander_sibling;
+ struct _sas_port *mpt2sas_port, *next_port;
struct _raid_device *raid_device, *next;
struct MPT2SAS_TARGET *sas_target_priv_data;
struct workqueue_struct *wq;
@@ -6702,28 +6641,18 @@ _scsih_remove(struct pci_dev *pdev)
}
/* free ports attached to the sas_host */
- retry_again:
- list_for_each_entry(mpt2sas_port,
+ list_for_each_entry_safe(mpt2sas_port, next_port,
&ioc->sas_hba.sas_port_list, port_list) {
if (mpt2sas_port->remote_identify.device_type ==
- SAS_END_DEVICE) {
- sas_device =
- mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
- mpt2sas_port->remote_identify.sas_address);
- if (sas_device) {
- _scsih_remove_device(ioc, sas_device);
- goto retry_again;
- }
- } else {
- expander_sibling =
- mpt2sas_scsih_expander_find_by_sas_address(ioc,
+ SAS_END_DEVICE)
+ mpt2sas_device_remove(ioc,
+ mpt2sas_port->remote_identify.sas_address);
+ else if (mpt2sas_port->remote_identify.device_type ==
+ SAS_EDGE_EXPANDER_DEVICE ||
+ mpt2sas_port->remote_identify.device_type ==
+ SAS_FANOUT_EXPANDER_DEVICE)
+ mpt2sas_expander_remove(ioc,
mpt2sas_port->remote_identify.sas_address);
- if (expander_sibling) {
- _scsih_expander_remove(ioc,
- expander_sibling->sas_address);
- goto retry_again;
- }
- }
}
/* free phys attached to the sas_host */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index b55c6dc0747..cb1cdecbe0f 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -465,62 +465,149 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
return rc;
}
+/**
+ * _transport_delete_port - helper function to removing a port
+ * @ioc: per adapter object
+ * @mpt2sas_port: mpt2sas per port object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_port *mpt2sas_port)
+{
+ u64 sas_address = mpt2sas_port->remote_identify.sas_address;
+ enum sas_device_type device_type =
+ mpt2sas_port->remote_identify.device_type;
+
+ dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
+ "remove: sas_addr(0x%016llx)\n",
+ (unsigned long long) sas_address);
+
+ ioc->logging_level |= MPT_DEBUG_TRANSPORT;
+ if (device_type == SAS_END_DEVICE)
+ mpt2sas_device_remove(ioc, sas_address);
+ else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
+ device_type == SAS_FANOUT_EXPANDER_DEVICE)
+ mpt2sas_expander_remove(ioc, sas_address);
+ ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
+}
/**
- * _transport_delete_duplicate_port - (see below description)
+ * _transport_delete_phy - helper function to removing single phy from port
* @ioc: per adapter object
- * @sas_node: sas node object (either expander or sas host)
- * @sas_address: sas address of device being added
- * @phy_num: phy number
+ * @mpt2sas_port: mpt2sas per port object
+ * @mpt2sas_phy: mpt2sas per phy object
*
- * This function is called when attempting to add a new port that is claiming
- * the same phy resources already in use by another port. If we don't release
- * the claimed phy resources, the sas transport layer will hang from the BUG
- * in sas_port_add_phy.
+ * Returns nothing.
+ */
+static void
+_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
+{
+ u64 sas_address = mpt2sas_port->remote_identify.sas_address;
+
+ dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
+ "remove: sas_addr(0x%016llx), phy(%d)\n",
+ (unsigned long long) sas_address, mpt2sas_phy->phy_id);
+
+ list_del(&mpt2sas_phy->port_siblings);
+ mpt2sas_port->num_phys--;
+ sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
+ mpt2sas_phy->phy_belongs_to_port = 0;
+}
+
+/**
+ * _transport_add_phy - helper function to adding single phy to port
+ * @ioc: per adapter object
+ * @mpt2sas_port: mpt2sas per port object
+ * @mpt2sas_phy: mpt2sas per phy object
*
- * The reason we would hit this issue is becuase someone is changing the
- * sas address of a device on the fly, meanwhile controller firmware sends
- * EVENTs out of order when removing the previous instance of the device.
+ * Returns nothing.
*/
static void
-_transport_delete_duplicate_port(struct MPT2SAS_ADAPTER *ioc,
- struct _sas_node *sas_node, u64 sas_address, int phy_num)
+_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
+ struct _sas_phy *mpt2sas_phy)
{
- struct _sas_port *mpt2sas_port, *mpt2sas_port_duplicate;
- struct _sas_phy *mpt2sas_phy;
+ u64 sas_address = mpt2sas_port->remote_identify.sas_address;
- printk(MPT2SAS_ERR_FMT "new device located at sas_addr(0x%016llx), "
- "phy_id(%d)\n", ioc->name, (unsigned long long)sas_address,
- phy_num);
+ dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
+ "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
+ sas_address, mpt2sas_phy->phy_id);
- mpt2sas_port_duplicate = NULL;
- list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list, port_list) {
- dev_printk(KERN_ERR, &mpt2sas_port->port->dev,
- "existing device at sas_addr(0x%016llx), num_phys(%d)\n",
- (unsigned long long)
- mpt2sas_port->remote_identify.sas_address,
- mpt2sas_port->num_phys);
- list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
+ list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
+ mpt2sas_port->num_phys++;
+ sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
+ mpt2sas_phy->phy_belongs_to_port = 1;
+}
+
+/**
+ * _transport_add_phy_to_an_existing_port - adding new phy to existing port
+ * @ioc: per adapter object
+ * @sas_node: sas node object (either expander or sas host)
+ * @mpt2sas_phy: mpt2sas per phy object
+ * @sas_address: sas address of device/expander were phy needs to be added to
+ *
+ * Returns nothing.
+ */
+static void
+_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
+struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
+{
+ struct _sas_port *mpt2sas_port;
+ struct _sas_phy *phy_srch;
+
+ if (mpt2sas_phy->phy_belongs_to_port == 1)
+ return;
+
+ list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
+ port_list) {
+ if (mpt2sas_port->remote_identify.sas_address !=
+ sas_address)
+ continue;
+ list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
port_siblings) {
- dev_printk(KERN_ERR, &mpt2sas_phy->phy->dev,
- "phy_number(%d)\n", mpt2sas_phy->phy_id);
- if (mpt2sas_phy->phy_id == phy_num)
- mpt2sas_port_duplicate = mpt2sas_port;
+ if (phy_srch == mpt2sas_phy)
+ return;
}
+ _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
+ return;
}
- if (!mpt2sas_port_duplicate)
+}
+
+/**
+ * _transport_del_phy_from_an_existing_port - delete phy from existing port
+ * @ioc: per adapter object
+ * @sas_node: sas node object (either expander or sas host)
+ * @mpt2sas_phy: mpt2sas per phy object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
+{
+ struct _sas_port *mpt2sas_port, *next;
+ struct _sas_phy *phy_srch;
+
+ if (mpt2sas_phy->phy_belongs_to_port == 0)
return;
- dev_printk(KERN_ERR, &mpt2sas_port_duplicate->port->dev,
- "deleting duplicate device at sas_addr(0x%016llx), phy(%d)!!!!\n",
- (unsigned long long)
- mpt2sas_port_duplicate->remote_identify.sas_address, phy_num);
- ioc->logging_level |= MPT_DEBUG_TRANSPORT;
- mpt2sas_transport_port_remove(ioc,
- mpt2sas_port_duplicate->remote_identify.sas_address,
- sas_node->sas_address);
- ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
+ list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
+ port_list) {
+ list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
+ port_siblings) {
+ if (phy_srch != mpt2sas_phy)
+ continue;
+ if (mpt2sas_port->num_phys == 1)
+ _transport_delete_port(ioc, mpt2sas_port);
+ else
+ _transport_delete_phy(ioc, mpt2sas_port,
+ mpt2sas_phy);
+ return;
+ }
+ }
}
/**
@@ -537,11 +624,13 @@ _transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
{
int i;
- for (i = 0; i < sas_node->num_phys; i++)
- if (sas_node->phy[i].remote_identify.sas_address == sas_address)
- if (sas_node->phy[i].phy_belongs_to_port)
- _transport_delete_duplicate_port(ioc, sas_node,
- sas_address, i);
+ for (i = 0; i < sas_node->num_phys; i++) {
+ if (sas_node->phy[i].remote_identify.sas_address != sas_address)
+ continue;
+ if (sas_node->phy[i].phy_belongs_to_port == 1)
+ _transport_del_phy_from_an_existing_port(ioc, sas_node,
+ &sas_node->phy[i]);
+ }
}
/**
@@ -905,10 +994,12 @@ mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
mpt2sas_phy = &sas_node->phy[phy_number];
mpt2sas_phy->attached_handle = handle;
- if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
+ if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
_transport_set_identify(ioc, handle,
&mpt2sas_phy->remote_identify);
- else
+ _transport_add_phy_to_an_existing_port(ioc, sas_node,
+ mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
+ } else
memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
sas_identify));
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index bc8194f7462..44578b56ad0 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1309,6 +1309,31 @@ qla2x00_fabric_param_show(struct device *dev, struct device_attribute *attr,
}
static ssize_t
+qla2x00_thermal_temp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ int rval = QLA_FUNCTION_FAILED;
+ uint16_t temp, frac;
+
+ if (!vha->hw->flags.thermal_supported)
+ return snprintf(buf, PAGE_SIZE, "\n");
+
+ temp = frac = 0;
+ if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
+ test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
+ DEBUG2_3_11(printk(KERN_WARNING
+ "%s(%ld): isp reset in progress.\n",
+ __func__, vha->host_no));
+ else if (!vha->hw->flags.eeh_busy)
+ rval = qla2x00_get_thermal_temp(vha, &temp, &frac);
+ if (rval != QLA_SUCCESS)
+ temp = frac = 0;
+
+ return snprintf(buf, PAGE_SIZE, "%d.%02d\n", temp, frac);
+}
+
+static ssize_t
qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -1366,6 +1391,7 @@ static DEVICE_ATTR(vn_port_mac_address, S_IRUGO,
qla2x00_vn_port_mac_address_show, NULL);
static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL);
static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL);
+static DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
@@ -1394,6 +1420,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_fabric_param,
&dev_attr_fw_state,
&dev_attr_optrom_gold_fw_version,
+ &dev_attr_thermal_temp,
NULL,
};
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 31a4121a2be..903b0586ded 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -103,7 +103,7 @@ 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)) {
+ if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))) {
ret = -EINVAL;
goto exit_fcp_prio_cfg;
}
@@ -753,7 +753,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
command_sent = INT_DEF_LB_LOOPBACK_CMD;
rval = qla2x00_loopback_test(vha, &elreq, response);
- if (new_config[1]) {
+ if (new_config[0]) {
/* Revert back to original port config
* Also clear internal loopback
*/
@@ -1512,6 +1512,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
if (((sp_bsg->type == SRB_CT_CMD) ||
(sp_bsg->type == SRB_ELS_CMD_HST))
&& (sp_bsg->u.bsg_job == bsg_job)) {
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (ha->isp_ops->abort_command(sp)) {
DEBUG2(qla_printk(KERN_INFO, ha,
"scsi(%ld): mbx "
@@ -1527,6 +1528,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
bsg_job->req->errors =
bsg_job->reply->result = 0;
}
+ spin_lock_irqsave(&ha->hardware_lock, flags);
goto done;
}
}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 9ce539d4557..ccfc8e78be2 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2425,6 +2425,9 @@ struct qla_hw_data {
uint32_t disable_msix_handshake :1;
uint32_t fcp_prio_enabled :1;
uint32_t fw_hung :1;
+ uint32_t quiesce_owner:1;
+ uint32_t thermal_supported:1;
+ /* 26 bits */
} flags;
/* This spinlock is used to protect "io transactions", you must
@@ -2863,6 +2866,7 @@ typedef struct scsi_qla_host {
#define ISP_UNRECOVERABLE 17
#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */
#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */
+#define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */
uint32_t device_flags;
#define SWITCH_FOUND BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 9382a816c13..89e900adb67 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -36,6 +36,7 @@ extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *);
extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *);
+extern int qla2x00_perform_loop_resync(scsi_qla_host_t *);
extern int qla2x00_loop_resync(scsi_qla_host_t *);
extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
@@ -45,12 +46,15 @@ extern void qla2x00_update_fcports(scsi_qla_host_t *);
extern int qla2x00_abort_isp(scsi_qla_host_t *);
extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *);
+extern void qla82xx_quiescent_state_cleanup(scsi_qla_host_t *);
extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
+extern int qla2x00_get_thermal_temp(scsi_qla_host_t *, uint16_t *, uint16_t *);
+
extern void qla84xx_put_chip(struct scsi_qla_host *);
extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
@@ -68,6 +72,7 @@ extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *,
struct srb_iocb *);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
+extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
extern fc_port_t *
qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t );
@@ -90,7 +95,6 @@ extern int ql2xfwloadbin;
extern int ql2xetsenable;
extern int ql2xshiftctondsd;
extern int ql2xdbwr;
-extern int ql2xdontresethba;
extern int ql2xasynctmfenable;
extern int ql2xgffidenable;
extern int ql2xenabledif;
@@ -549,9 +553,11 @@ extern void qla82xx_rom_unlock(struct qla_hw_data *);
/* ISP 8021 IDC */
extern void qla82xx_clear_drv_active(struct qla_hw_data *);
+extern uint32_t qla82xx_wait_for_state_change(scsi_qla_host_t *, uint32_t);
extern int qla82xx_idc_lock(struct qla_hw_data *);
extern void qla82xx_idc_unlock(struct qla_hw_data *);
extern int qla82xx_device_state_handler(scsi_qla_host_t *);
+extern void qla82xx_clear_qsnt_ready(scsi_qla_host_t *);
extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *,
size_t, char *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 259f5113749..f948e1a73ae 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -498,6 +498,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
vha->flags.reset_active = 0;
ha->flags.pci_channel_io_perm_failure = 0;
ha->flags.eeh_busy = 0;
+ ha->flags.thermal_supported = 1;
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
atomic_set(&vha->loop_state, LOOP_DOWN);
vha->device_flags = DFLG_NO_CABLE;
@@ -2023,6 +2024,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
&loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
if (rval != QLA_SUCCESS) {
if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) ||
+ IS_QLA8XXX_TYPE(ha) ||
(rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
DEBUG2(printk("%s(%ld) Loop is in a transition state\n",
__func__, vha->host_no));
@@ -2928,6 +2930,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
qla2x00_iidma_fcport(vha, fcport);
+ qla24xx_update_fcport_fcp_prio(vha, fcport);
qla2x00_reg_remote_port(vha, fcport);
atomic_set(&fcport->state, FCS_ONLINE);
}
@@ -3844,6 +3847,37 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
return (rval);
}
+/*
+* qla2x00_perform_loop_resync
+* Description: This function will set the appropriate flags and call
+* qla2x00_loop_resync. If successful loop will be resynced
+* Arguments : scsi_qla_host_t pointer
+* returm : Success or Failure
+*/
+
+int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
+{
+ int32_t rval = 0;
+
+ if (!test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) {
+ /*Configure the flags so that resync happens properly*/
+ atomic_set(&ha->loop_down_timer, 0);
+ if (!(ha->device_flags & DFLG_NO_CABLE)) {
+ atomic_set(&ha->loop_state, LOOP_UP);
+ set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
+ set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+ set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+
+ rval = qla2x00_loop_resync(ha);
+ } else
+ atomic_set(&ha->loop_state, LOOP_DEAD);
+
+ clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
+ }
+
+ return rval;
+}
+
void
qla2x00_update_fcports(scsi_qla_host_t *base_vha)
{
@@ -3857,7 +3891,7 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
atomic_inc(&vha->vref_count);
list_for_each_entry(fcport, &vha->vp_fcports, list) {
- if (fcport && fcport->drport &&
+ if (fcport->drport &&
atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
spin_unlock_irqrestore(&ha->vport_slock, flags);
@@ -3871,11 +3905,43 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
spin_unlock_irqrestore(&ha->vport_slock, flags);
}
+/*
+* qla82xx_quiescent_state_cleanup
+* Description: This function will block the new I/Os
+* Its not aborting any I/Os as context
+* is not destroyed during quiescence
+* Arguments: scsi_qla_host_t
+* return : void
+*/
+void
+qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct scsi_qla_host *vp;
+
+ qla_printk(KERN_INFO, ha,
+ "Performing ISP error recovery - ha= %p.\n", ha);
+
+ atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
+ if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
+ atomic_set(&vha->loop_state, LOOP_DOWN);
+ qla2x00_mark_all_devices_lost(vha, 0);
+ list_for_each_entry(vp, &ha->vp_list, list)
+ qla2x00_mark_all_devices_lost(vha, 0);
+ } else {
+ if (!atomic_read(&vha->loop_down_timer))
+ atomic_set(&vha->loop_down_timer,
+ LOOP_DOWN_TIME);
+ }
+ /* Wait for pending cmds to complete */
+ qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
+}
+
void
qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
- struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
+ struct scsi_qla_host *vp;
unsigned long flags;
vha->flags.online = 0;
@@ -3896,7 +3962,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
qla2x00_mark_all_devices_lost(vha, 0);
spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &base_vha->hw->vp_list, list) {
+ list_for_each_entry(vp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
@@ -5410,7 +5476,7 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha)
* the tag (priority) value is returned.
*
* Input:
- * ha = adapter block po
+ * vha = scsi host structure pointer.
* fcport = port structure pointer.
*
* Return:
@@ -5504,7 +5570,7 @@ qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
* Activates fcp priority for the logged in fc port
*
* Input:
- * ha = adapter block pointer.
+ * vha = scsi host structure pointer.
* fcp = port structure pointer.
*
* Return:
@@ -5514,25 +5580,24 @@ qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
* Kernel context.
*/
int
-qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *ha, fc_port_t *fcport)
+qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
{
int ret;
uint8_t priority;
uint16_t mb[5];
- if (atomic_read(&fcport->state) == FCS_UNCONFIGURED ||
- fcport->port_type != FCT_TARGET ||
- fcport->loop_id == FC_NO_LOOP_ID)
+ if (fcport->port_type != FCT_TARGET ||
+ fcport->loop_id == FC_NO_LOOP_ID)
return QLA_FUNCTION_FAILED;
- priority = qla24xx_get_fcp_prio(ha, fcport);
- ret = qla24xx_set_fcp_prio(ha, fcport->loop_id, priority, mb);
+ priority = qla24xx_get_fcp_prio(vha, fcport);
+ ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb);
if (ret == QLA_SUCCESS)
fcport->fcp_prio = priority;
else
DEBUG2(printk(KERN_WARNING
"scsi(%ld): Unable to activate fcp priority, "
- " ret=0x%x\n", ha->host_no, ret));
+ " ret=0x%x\n", vha->host_no, ret));
return ret;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 7f77898486a..d17ed9a94a0 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -321,6 +321,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
struct qla_hw_data *ha = vha->hw;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
+ struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
uint32_t rscn_entry, host_pid;
uint8_t rscn_queue_index;
unsigned long flags;
@@ -498,6 +499,7 @@ skip_rio:
case MBA_LOOP_DOWN: /* Loop Down Event */
mbx = IS_QLA81XX(ha) ? RD_REG_WORD(&reg24->mailbox4) : 0;
+ mbx = IS_QLA82XX(ha) ? RD_REG_WORD(&reg82->mailbox_out[4]) : mbx;
DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
"(%x %x %x %x).\n", vha->host_no, mb[1], mb[2], mb[3],
mbx));
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index effd8a1403d..e473e9fb363 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -4125,7 +4125,7 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
return QLA_FUNCTION_FAILED;
DEBUG11(printk(KERN_INFO
- "%s(%ld): entered.\n", __func__, ha->host_no));
+ "%s(%ld): entered.\n", __func__, vha->host_no));
mcp->mb[0] = MBC_PORT_PARAMS;
mcp->mb[1] = loop_id;
@@ -4160,6 +4160,71 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
}
int
+qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac)
+{
+ 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__, ha->host_no));
+
+ /* High bits. */
+ mcp->mb[0] = MBC_READ_SFP;
+ mcp->mb[1] = 0x98;
+ mcp->mb[2] = 0;
+ mcp->mb[3] = 0;
+ mcp->mb[6] = 0;
+ mcp->mb[7] = 0;
+ mcp->mb[8] = 1;
+ mcp->mb[9] = 0x01;
+ mcp->mb[10] = BIT_13|BIT_0;
+ mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = 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]));
+ ha->flags.thermal_supported = 0;
+ goto fail;
+ }
+ *temp = mcp->mb[1] & 0xFF;
+
+ /* Low bits. */
+ mcp->mb[0] = MBC_READ_SFP;
+ mcp->mb[1] = 0x98;
+ mcp->mb[2] = 0;
+ mcp->mb[3] = 0;
+ mcp->mb[6] = 0;
+ mcp->mb[7] = 0;
+ mcp->mb[8] = 1;
+ mcp->mb[9] = 0x10;
+ mcp->mb[10] = BIT_13|BIT_0;
+ mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = 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]));
+ ha->flags.thermal_supported = 0;
+ goto fail;
+ }
+ *frac = ((mcp->mb[1] & 0xFF) >> 6) * 25;
+
+ if (rval == QLA_SUCCESS)
+ DEBUG11(printk(KERN_INFO
+ "%s(%ld): done.\n", __func__, ha->host_no));
+fail:
+ return rval;
+}
+
+int
qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
{
int rval;
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index ae2acacc000..fdb96a3584a 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -1079,11 +1079,55 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
/* Halt all the indiviual PEGs and other blocks of the ISP */
qla82xx_rom_lock(ha);
+
+ /* mask all niu interrupts */
+ qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff);
+ /* disable xge rx/tx */
+ qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00);
+ /* disable xg1 rx/tx */
+ qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00);
+
+ /* halt sre */
+ val = qla82xx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000);
+ qla82xx_wr_32(ha, QLA82XX_CRB_SRE + 0x1000, val & (~(0x1)));
+
+ /* halt epg */
+ qla82xx_wr_32(ha, QLA82XX_CRB_EPG + 0x1300, 0x1);
+
+ /* halt timers */
+ qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x0, 0x0);
+ qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x8, 0x0);
+ qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0);
+ qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0);
+ qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0);
+
+ /* halt pegs */
+ qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1);
+ qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c, 1);
+ qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1);
+ qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1);
+ qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1);
+
+ /* big hammer */
+ msleep(1000);
if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
/* don't reset CAM block on reset */
qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff);
else
qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff);
+
+ /* reset ms */
+ val = qla82xx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
+ val |= (1 << 1);
+ qla82xx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
+ msleep(20);
+
+ /* unreset ms */
+ val = qla82xx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
+ val &= ~(1 << 1);
+ qla82xx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
+ msleep(20);
+
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
/* Read the signature value from the flash.
@@ -1210,25 +1254,6 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
}
static int
-qla82xx_check_for_bad_spd(struct qla_hw_data *ha)
-{
- u32 val = 0;
- val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS);
- val &= QLA82XX_BOOT_LOADER_MN_ISSUE;
- if (val & QLA82XX_PEG_TUNE_MN_SPD_ZEROED) {
- qla_printk(KERN_INFO, ha,
- "Memory DIMM SPD not programmed. "
- " Assumed valid.\n");
- return 1;
- } else if (val) {
- qla_printk(KERN_INFO, ha,
- "Memory DIMM type incorrect.Info:%08X.\n", val);
- return 2;
- }
- return 0;
-}
-
-static int
qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
u64 off, void *data, int size)
{
@@ -1293,11 +1318,6 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
word[startword+1] |= tmpw >> (sz[0] * 8);
}
- /*
- * don't lock here - write_wx gets the lock if each time
- * write_lock_irqsave(&adapter->adapter_lock, flags);
- * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
- */
for (i = 0; i < loop; i++) {
temp = off8 + (i << shift_amount);
qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
@@ -1399,12 +1419,6 @@ qla82xx_pci_mem_read_2M(struct qla_hw_data *ha,
off0[1] = 0;
sz[1] = size - sz[0];
- /*
- * don't lock here - write_wx gets the lock if each time
- * write_lock_irqsave(&adapter->adapter_lock, flags);
- * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
- */
-
for (i = 0; i < loop; i++) {
temp = off8 + (i << shift_amount);
qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
@@ -1437,11 +1451,6 @@ qla82xx_pci_mem_read_2M(struct qla_hw_data *ha,
}
}
- /*
- * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
- * write_unlock_irqrestore(&adapter->adapter_lock, flags);
- */
-
if (j >= MAX_CTL_CHECK)
return -1;
@@ -1872,7 +1881,6 @@ qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
qla_printk(KERN_INFO, ha,
"Cmd Peg initialization failed: 0x%x.\n", val);
- qla82xx_check_for_bad_spd(ha);
val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_PEGTUNE_DONE);
read_lock(&ha->hw_lock);
qla82xx_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
@@ -2343,6 +2351,17 @@ qla82xx_set_qsnt_ready(struct qla_hw_data *ha)
qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
}
+void
+qla82xx_clear_qsnt_ready(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t qsnt_state;
+
+ qsnt_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+ qsnt_state &= ~(QLA82XX_DRVST_QSNT_RDY << (ha->portnum * 4));
+ qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
+}
+
static int
qla82xx_load_fw(scsi_qla_host_t *vha)
{
@@ -2542,7 +2561,7 @@ qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
*cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
- cur_seg++;
+ cur_seg = sg_next(cur_seg);
avail_dsds--;
}
}
@@ -3261,6 +3280,104 @@ dev_ready:
return QLA_SUCCESS;
}
+/*
+* qla82xx_need_qsnt_handler
+* Code to start quiescence sequence
+*
+* Note:
+* IDC lock must be held upon entry
+*
+* Return: void
+*/
+
+static void
+qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t dev_state, drv_state, drv_active;
+ unsigned long reset_timeout;
+
+ if (vha->flags.online) {
+ /*Block any further I/O and wait for pending cmnds to complete*/
+ qla82xx_quiescent_state_cleanup(vha);
+ }
+
+ /* Set the quiescence ready bit */
+ qla82xx_set_qsnt_ready(ha);
+
+ /*wait for 30 secs for other functions to ack */
+ reset_timeout = jiffies + (30 * HZ);
+
+ drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+ drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+ /* Its 2 that is written when qsnt is acked, moving one bit */
+ drv_active = drv_active << 0x01;
+
+ while (drv_state != drv_active) {
+
+ if (time_after_eq(jiffies, reset_timeout)) {
+ /* quiescence timeout, other functions didn't ack
+ * changing the state to DEV_READY
+ */
+ qla_printk(KERN_INFO, ha,
+ "%s: QUIESCENT TIMEOUT\n", QLA2XXX_DRIVER_NAME);
+ qla_printk(KERN_INFO, ha,
+ "DRV_ACTIVE:%d DRV_STATE:%d\n", drv_active,
+ drv_state);
+ qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+ QLA82XX_DEV_READY);
+ qla_printk(KERN_INFO, ha,
+ "HW State: DEV_READY\n");
+ qla82xx_idc_unlock(ha);
+ qla2x00_perform_loop_resync(vha);
+ qla82xx_idc_lock(ha);
+
+ qla82xx_clear_qsnt_ready(vha);
+ return;
+ }
+
+ qla82xx_idc_unlock(ha);
+ msleep(1000);
+ qla82xx_idc_lock(ha);
+
+ drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+ drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+ drv_active = drv_active << 0x01;
+ }
+ dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+ /* everyone acked so set the state to DEV_QUIESCENCE */
+ if (dev_state == QLA82XX_DEV_NEED_QUIESCENT) {
+ qla_printk(KERN_INFO, ha, "HW State: DEV_QUIESCENT\n");
+ qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_QUIESCENT);
+ }
+}
+
+/*
+* qla82xx_wait_for_state_change
+* Wait for device state to change from given current state
+*
+* Note:
+* IDC lock must not be held upon entry
+*
+* Return:
+* Changed device state.
+*/
+uint32_t
+qla82xx_wait_for_state_change(scsi_qla_host_t *vha, uint32_t curr_state)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t dev_state;
+
+ do {
+ msleep(1000);
+ qla82xx_idc_lock(ha);
+ dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+ qla82xx_idc_unlock(ha);
+ } while (dev_state == curr_state);
+
+ return dev_state;
+}
+
static void
qla82xx_dev_failed_handler(scsi_qla_host_t *vha)
{
@@ -3439,15 +3556,28 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
qla82xx_idc_lock(ha);
break;
case QLA82XX_DEV_NEED_RESET:
- if (!ql2xdontresethba)
- qla82xx_need_reset_handler(vha);
+ qla82xx_need_reset_handler(vha);
break;
case QLA82XX_DEV_NEED_QUIESCENT:
- qla82xx_set_qsnt_ready(ha);
+ qla82xx_need_qsnt_handler(vha);
+ /* Reset timeout value after quiescence handler */
+ dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\
+ * HZ);
+ break;
case QLA82XX_DEV_QUIESCENT:
+ /* Owner will exit and other will wait for the state
+ * to get changed
+ */
+ if (ha->flags.quiesce_owner)
+ goto exit;
+
qla82xx_idc_unlock(ha);
msleep(1000);
qla82xx_idc_lock(ha);
+
+ /* Reset timeout value after quiescence handler */
+ dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\
+ * HZ);
break;
case QLA82XX_DEV_FAILED:
qla82xx_dev_failed_handler(vha);
@@ -3490,6 +3620,13 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
&ha->mbx_cmd_flags))
complete(&ha->mbx_intr_comp);
}
+ } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
+ !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
+ DEBUG(qla_printk(KERN_INFO, ha,
+ "scsi(%ld) %s - detected quiescence needed\n",
+ vha->host_no, __func__));
+ set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
} else {
qla82xx_check_fw_alive(vha);
}
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 51ec0c5380e..ed5883f1778 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -523,8 +523,6 @@
# 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))
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2c0876c81a3..c194c23ca1f 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -37,12 +37,12 @@ static struct kmem_cache *srb_cachep;
static struct kmem_cache *ctx_cachep;
int ql2xlogintimeout = 20;
-module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
+module_param(ql2xlogintimeout, int, S_IRUGO);
MODULE_PARM_DESC(ql2xlogintimeout,
"Login timeout value in seconds.");
int qlport_down_retry;
-module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
+module_param(qlport_down_retry, int, S_IRUGO);
MODULE_PARM_DESC(qlport_down_retry,
"Maximum number of command retries to a port that returns "
"a PORT-DOWN status.");
@@ -55,12 +55,12 @@ MODULE_PARM_DESC(ql2xplogiabsentdevice,
"Default is 0 - no PLOGI. 1 - perfom PLOGI.");
int ql2xloginretrycount = 0;
-module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
+module_param(ql2xloginretrycount, int, S_IRUGO);
MODULE_PARM_DESC(ql2xloginretrycount,
"Specify an alternate value for the NVRAM login retry count.");
int ql2xallocfwdump = 1;
-module_param(ql2xallocfwdump, int, S_IRUGO|S_IRUSR);
+module_param(ql2xallocfwdump, int, S_IRUGO);
MODULE_PARM_DESC(ql2xallocfwdump,
"Option to enable allocation of memory for a firmware dump "
"during HBA initialization. Memory allocation requirements "
@@ -73,7 +73,7 @@ MODULE_PARM_DESC(ql2xextended_error_logging,
"Default is 0 - no logging. 1 - log errors.");
int ql2xshiftctondsd = 6;
-module_param(ql2xshiftctondsd, int, S_IRUGO|S_IRUSR);
+module_param(ql2xshiftctondsd, int, S_IRUGO);
MODULE_PARM_DESC(ql2xshiftctondsd,
"Set to control shifting of command type processing "
"based on total number of SG elements.");
@@ -81,7 +81,7 @@ MODULE_PARM_DESC(ql2xshiftctondsd,
static void qla2x00_free_device(scsi_qla_host_t *);
int ql2xfdmienable=1;
-module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xfdmienable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xfdmienable,
"Enables FDMI registrations. "
"0 - no FDMI. Default is 1 - perform FDMI.");
@@ -106,27 +106,27 @@ MODULE_PARM_DESC(ql2xenablehba_err_chk,
" Default is 0 - Error isolation disabled, 1 - Enable it");
int ql2xiidmaenable=1;
-module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xiidmaenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xiidmaenable,
"Enables iIDMA settings "
"Default is 1 - perform iIDMA. 0 - no iIDMA.");
int ql2xmaxqueues = 1;
-module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR);
+module_param(ql2xmaxqueues, int, S_IRUGO);
MODULE_PARM_DESC(ql2xmaxqueues,
"Enables MQ settings "
"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);
+module_param(ql2xmultique_tag, int, S_IRUGO);
MODULE_PARM_DESC(ql2xmultique_tag,
"Enables CPU affinity settings for the driver "
"Default is 0 for no affinity of request and response IO. "
"Set it to 1 to turn on the cpu affinity.");
int ql2xfwloadbin;
-module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
+module_param(ql2xfwloadbin, int, S_IRUGO);
MODULE_PARM_DESC(ql2xfwloadbin,
"Option to specify location from which to load ISP firmware:\n"
" 2 -- load firmware via the request_firmware() (hotplug)\n"
@@ -135,39 +135,32 @@ MODULE_PARM_DESC(ql2xfwloadbin,
" 0 -- use default semantics.\n");
int ql2xetsenable;
-module_param(ql2xetsenable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xetsenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xetsenable,
"Enables firmware ETS burst."
"Default is 0 - skip ETS enablement.");
int ql2xdbwr = 1;
-module_param(ql2xdbwr, int, S_IRUGO|S_IRUSR);
+module_param(ql2xdbwr, int, S_IRUGO);
MODULE_PARM_DESC(ql2xdbwr,
"Option to specify scheme for request queue posting\n"
" 0 -- Regular doorbell.\n"
" 1 -- CAMRAM doorbell (faster).\n");
-int ql2xdontresethba;
-module_param(ql2xdontresethba, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ql2xdontresethba,
- "Option to specify reset behaviour\n"
- " 0 (Default) -- Reset on failure.\n"
- " 1 -- Do not reset on failure.\n");
-
int ql2xtargetreset = 1;
-module_param(ql2xtargetreset, int, S_IRUGO|S_IRUSR);
+module_param(ql2xtargetreset, int, S_IRUGO);
MODULE_PARM_DESC(ql2xtargetreset,
"Enable target reset."
"Default is 1 - use hw defaults.");
int ql2xgffidenable;
-module_param(ql2xgffidenable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xgffidenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xgffidenable,
"Enables GFF_ID checks of port type. "
"Default is 0 - Do not use GFF_ID information.");
int ql2xasynctmfenable;
-module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xasynctmfenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xasynctmfenable,
"Enables issue of TM IOCBs asynchronously via IOCB mechanism"
"Default is 0 - Issue TM IOCBs via mailbox mechanism.");
@@ -2371,7 +2364,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
list_for_each_entry(vha, &ha->vp_list, list) {
atomic_inc(&vha->vref_count);
- if (vha && vha->fc_vport) {
+ if (vha->fc_vport) {
spin_unlock_irqrestore(&ha->vport_slock, flags);
fc_vport_terminate(vha->fc_vport);
@@ -3386,6 +3379,21 @@ qla2x00_do_dpc(void *data)
clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
}
+ if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
+ DEBUG(printk(KERN_INFO "scsi(%ld): dpc: sched "
+ "qla2x00_quiesce_needed ha = %p\n",
+ base_vha->host_no, ha));
+ qla82xx_device_state_handler(base_vha);
+ clear_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags);
+ if (!ha->flags.quiesce_owner) {
+ qla2x00_perform_loop_resync(base_vha);
+
+ qla82xx_idc_lock(ha);
+ qla82xx_clear_qsnt_ready(base_vha);
+ qla82xx_idc_unlock(ha);
+ }
+ }
+
if (test_and_clear_bit(RESET_MARKER_NEEDED,
&base_vha->dpc_flags) &&
(!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
@@ -3589,13 +3597,16 @@ qla2x00_timer(scsi_qla_host_t *vha)
return;
}
- if (IS_QLA82XX(ha))
- qla82xx_watchdog(vha);
-
/* Hardware read to raise pending EEH errors during mailbox waits. */
if (!pci_channel_offline(ha->pdev))
pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
+ if (IS_QLA82XX(ha)) {
+ if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags))
+ start_dpc++;
+ qla82xx_watchdog(vha);
+ }
+
/* Loop down handler. */
if (atomic_read(&vha->loop_down_timer) > 0 &&
!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 76de9574b38..22070621206 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -669,6 +669,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
def = 1;
else if (IS_QLA81XX(ha))
def = 2;
+
+ /* Assign FCP prio region since older adapters may not have FLT, or
+ FCP prio region in it's FLT.
+ */
+ ha->flt_region_fcp_prio = ha->flags.port0 ?
+ fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
+
ha->flt_region_flt = flt_addr;
wptr = (uint16_t *)req->ring;
flt = (struct qla_flt_header *)req->ring;
@@ -696,10 +703,6 @@ 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++) {
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c
index edcf048215d..af62c3cf875 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.c
+++ b/drivers/scsi/qla4xxx/ql4_dbg.c
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.h b/drivers/scsi/qla4xxx/ql4_dbg.h
index d861c3b411c..abd83602cdd 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.h
+++ b/drivers/scsi/qla4xxx/ql4_dbg.h
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 0f3bfc3da5c..2fc0045b1a5 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
@@ -175,7 +175,7 @@
struct srb {
struct list_head list; /* (8) */
struct scsi_qla_host *ha; /* HA the SP is queued on */
- struct ddb_entry *ddb;
+ struct ddb_entry *ddb;
uint16_t flags; /* (1) Status flags. */
#define SRB_DMA_VALID BIT_3 /* DMA Buffer mapped. */
@@ -191,7 +191,6 @@ struct srb {
struct scsi_cmnd *cmd; /* (4) SCSI command block */
dma_addr_t dma_handle; /* (4) for unmap of single transfers */
struct kref srb_ref; /* reference count for this srb */
- uint32_t fw_ddb_index;
uint8_t err_id; /* error id */
#define SRB_ERR_PORT 1 /* Request failed because "port down" */
#define SRB_ERR_LOOP 2 /* Request failed because "loop down" */
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 5e757d7fff7..c1985792f03 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 6575a47501e..8fad99b7eef 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index dc01fa3da5d..1629c48c35e 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h
index 9471ac75500..62f90bdec5d 100644
--- a/drivers/scsi/qla4xxx/ql4_inline.h
+++ b/drivers/scsi/qla4xxx/ql4_inline.h
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index 5ae49fd8784..75fcd82a8fc 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 7c33fd5943d..6ffbe9727df 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
@@ -554,7 +554,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
/* 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))
+ ((mbox_sts[2] == ACB_STATE_TENTATIVE) ||
+ (mbox_sts[2] == ACB_STATE_ACQUIRING)))
set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
(mbox_sts[2] == ACB_STATE_VALID))
@@ -1077,7 +1078,7 @@ try_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);
+ 0, DRIVER_NAME, ha);
if (!ret) {
DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
set_bit(AF_MSI_ENABLED, &ha->flags);
@@ -1095,7 +1096,7 @@ try_msi:
try_intx:
/* Trying INTx */
ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
- IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha);
+ IRQF_SHARED, DRIVER_NAME, ha);
if (!ret) {
DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n"));
set_bit(AF_INTx_ENABLED, &ha->flags);
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 2d2f9c879bf..f65626aec7c 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
@@ -81,23 +81,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
*/
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) {
- /* 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 {
+ if (!is_qla8022(ha)) {
intr_status = readl(&ha->reg->ctrl_status);
if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
/* Service existing interrupt */
@@ -934,7 +918,7 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
return status;
mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
- mbox_cmd[1] = srb->fw_ddb_index;
+ mbox_cmd[1] = srb->ddb->fw_ddb_index;
mbox_cmd[2] = index;
/* Immediate Command Enable */
mbox_cmd[5] = 0x01;
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
index f0d0fbf88aa..b4b859b2d47 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.c
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h
index 7a8fc66a760..b3831bd2947 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.h
+++ b/drivers/scsi/qla4xxx/ql4_nvram.h
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 474b10d7136..3d5ef2df413 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2009 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
@@ -942,12 +942,55 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose)
/* Halt all the indiviual PEGs and other blocks of the ISP */
qla4_8xxx_rom_lock(ha);
+
+ /* mask all niu interrupts */
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff);
+ /* disable xge rx/tx */
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00);
+ /* disable xg1 rx/tx */
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00);
+
+ /* halt sre */
+ val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_SRE + 0x1000, val & (~(0x1)));
+
+ /* halt epg */
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_EPG + 0x1300, 0x1);
+
+ /* halt timers */
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x0, 0x0);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x8, 0x0);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0);
+
+ /* halt pegs */
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c, 1);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1);
+
+ /* big hammer */
+ msleep(1000);
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);
+ /* reset ms */
+ val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
+ val |= (1 << 1);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
+
+ msleep(20);
+ /* unreset ms */
+ val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
+ val &= ~(1 << 1);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
+ msleep(20);
+
qla4_8xxx_rom_unlock(ha);
/* Read the signature value from the flash.
@@ -1084,14 +1127,14 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose)
static int
qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start)
{
- int i;
+ int i, rval = 0;
long size = 0;
long flashaddr, memaddr;
u64 data;
u32 high, low;
flashaddr = memaddr = ha->hw.flt_region_bootload;
- size = (image_start - flashaddr)/8;
+ 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));
@@ -1100,14 +1143,18 @@ qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start)
if ((qla4_8xxx_rom_fast_read(ha, flashaddr, (int *)&low)) ||
(qla4_8xxx_rom_fast_read(ha, flashaddr + 4,
(int *)&high))) {
- return -1;
+ rval = -1;
+ goto exit_load_from_flash;
}
data = ((u64)high << 32) | low ;
- qla4_8xxx_pci_mem_write_2M(ha, memaddr, &data, 8);
+ rval = qla4_8xxx_pci_mem_write_2M(ha, memaddr, &data, 8);
+ if (rval)
+ goto exit_load_from_flash;
+
flashaddr += 8;
memaddr += 8;
- if (i%0x1000 == 0)
+ if (i % 0x1000 == 0)
msleep(1);
}
@@ -1119,7 +1166,8 @@ qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start)
qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e);
read_unlock(&ha->hw_lock);
- return 0;
+exit_load_from_flash:
+ return rval;
}
static int qla4_8xxx_load_fw(struct scsi_qla_host *ha, uint32_t image_start)
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h
index ff689bf5300..35376a1c3f1 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.h
+++ b/drivers/scsi/qla4xxx/ql4_nx.h
@@ -1,8 +1,8 @@
/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c) 2003-2008 QLogic Corporation
+ * QLogic iSCSI HBA Driver
+ * Copyright (c) 2003-2010 QLogic Corporation
*
- * See LICENSE.qla2xxx for copyright and licensing details.
+ * See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef __QLA_NX_H
#define __QLA_NX_H
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 0d48fb4d104..3fc1d256636 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -1,6 +1,6 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
@@ -706,18 +706,22 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
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 (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
+ test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
+ 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);
- qla4xxx_mailbox_premature_completion(ha);
+ if (!ql4xdontresethba) {
+ ql4_printk(KERN_INFO, ha, "%s: HW State: "
+ "NEED RESET!\n", __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",
- ha->host_no, __func__);
+ ql4_printk(KERN_INFO, ha, "%s: HW State: NEED QUIES!\n",
+ __func__);
set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags);
qla4xxx_wake_dpc(ha);
} else {
@@ -1721,6 +1725,14 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
if (!test_bit(AF_ONLINE, &ha->flags)) {
ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n");
+ if (is_qla8022(ha) && ql4xdontresethba) {
+ /* Put the device in failed state. */
+ DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n"));
+ qla4_8xxx_idc_lock(ha);
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+ QLA82XX_DEV_FAILED);
+ qla4_8xxx_idc_unlock(ha);
+ }
ret = -ENODEV;
goto probe_failed;
}
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 9bfacf4ed13..8475b308e01 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -1,8 +1,8 @@
/*
* QLogic iSCSI HBA Driver
- * Copyright (c) 2003-2006 QLogic Corporation
+ * Copyright (c) 2003-2010 QLogic Corporation
*
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.02.00-k4"
+#define QLA4XXX_DRIVER_VERSION "5.02.00-k5"
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 2f1f9b079b1..7b310934efe 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1805,6 +1805,7 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
devip->sense_buff[5] = (ret >> 8) & 0xff;
devip->sense_buff[6] = ret & 0xff;
}
+ scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
return check_condition_result;
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 30ac116186f..45c75649b9e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1124,51 +1124,40 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
struct list_head *work_q,
struct list_head *done_q)
{
- struct scsi_cmnd *scmd, *tgtr_scmd, *next;
- unsigned int id = 0;
- int rtn;
+ LIST_HEAD(tmp_list);
- do {
- tgtr_scmd = NULL;
- list_for_each_entry(scmd, work_q, eh_entry) {
- if (id == scmd_id(scmd)) {
- tgtr_scmd = scmd;
- break;
- }
- }
- if (!tgtr_scmd) {
- /* not one exactly equal; find the next highest */
- list_for_each_entry(scmd, work_q, eh_entry) {
- if (scmd_id(scmd) > id &&
- (!tgtr_scmd ||
- scmd_id(tgtr_scmd) > scmd_id(scmd)))
- tgtr_scmd = scmd;
- }
- }
- if (!tgtr_scmd)
- /* no more commands, that's it */
- break;
+ list_splice_init(work_q, &tmp_list);
+
+ while (!list_empty(&tmp_list)) {
+ struct scsi_cmnd *next, *scmd;
+ int rtn;
+ unsigned int id;
+
+ scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry);
+ id = scmd_id(scmd);
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
"to target %d\n",
current->comm, id));
- rtn = scsi_try_target_reset(tgtr_scmd);
- if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
- list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
- if (id == scmd_id(scmd))
- if (!scsi_device_online(scmd->device) ||
- rtn == FAST_IO_FAIL ||
- !scsi_eh_tur(tgtr_scmd))
- scsi_eh_finish_cmd(scmd,
- done_q);
- }
- } else
+ rtn = scsi_try_target_reset(scmd);
+ if (rtn != SUCCESS && rtn != FAST_IO_FAIL)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset"
" failed target: "
"%d\n",
current->comm, id));
- id++;
- } while(id != 0);
+ list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) {
+ if (scmd_id(scmd) != id)
+ continue;
+
+ if ((rtn == SUCCESS || rtn == FAST_IO_FAIL)
+ && (!scsi_device_online(scmd->device) ||
+ rtn == FAST_IO_FAIL || !scsi_eh_tur(scmd)))
+ scsi_eh_finish_cmd(scmd, done_q);
+ else
+ /* push back on work queue for further processing */
+ list_move(&scmd->eh_entry, work_q);
+ }
+ }
return list_empty(work_q);
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 4a3842212c5..501f67bef71 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1278,11 +1278,10 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
}
if (scsi_target_is_busy(starget)) {
- if (list_empty(&sdev->starved_entry)) {
+ if (list_empty(&sdev->starved_entry))
list_add_tail(&sdev->starved_entry,
&shost->starved_list);
- return 0;
- }
+ return 0;
}
/* We're OK to process the command, so we can't be starved */
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 76ee2e784f7..4c68d36f9ac 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -993,16 +993,14 @@ static int __remove_child (struct device * dev, void * data)
*/
void scsi_remove_target(struct device *dev)
{
- struct device *rdev;
-
if (scsi_is_target_device(dev)) {
__scsi_remove_target(to_scsi_target(dev));
return;
}
- rdev = get_device(dev);
+ get_device(dev);
device_for_each_child(dev, NULL, __remove_child);
- put_device(rdev);
+ put_device(dev);
}
EXPORT_SYMBOL(scsi_remove_target);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 332387a6bc2..f905ecb5704 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -2200,3 +2200,4 @@ MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
MODULE_DESCRIPTION("iSCSI Transport Interface");
MODULE_LICENSE("GPL");
MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_ISCSI);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 956496182c8..365024b0c40 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -583,7 +583,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
* quietly refuse to do anything to a changed disc until
* the changed bit has been reset
*/
- /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
+ /* printk("SCSI disk has been changed or is not present. Prohibiting further I/O.\n"); */
goto out;
}
@@ -1023,7 +1023,6 @@ static int sd_media_changed(struct gendisk *disk)
*/
if (!scsi_device_online(sdp)) {
set_media_not_present(sdkp);
- retval = 1;
goto out;
}
@@ -1054,7 +1053,6 @@ static int sd_media_changed(struct gendisk *disk)
/* 0x3a is medium not present */
sshdr->asc == 0x3a)) {
set_media_not_present(sdkp);
- retval = 1;
goto out;
}
@@ -1065,12 +1063,27 @@ static int sd_media_changed(struct gendisk *disk)
*/
sdkp->media_present = 1;
- retval = sdp->changed;
- sdp->changed = 0;
out:
- if (retval != sdkp->previous_state)
+ /*
+ * Report a media change under the following conditions:
+ *
+ * Medium is present now and wasn't present before.
+ * Medium wasn't present before and is present now.
+ * Medium was present at all times, but it changed while
+ * we weren't looking (sdp->changed is set).
+ *
+ * If there was no medium before and there is no medium now then
+ * don't report a change, even if a medium was inserted and removed
+ * while we weren't looking.
+ */
+ retval = (sdkp->media_present != sdkp->previous_state ||
+ (sdkp->media_present && sdp->changed));
+ if (retval)
sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL);
- sdkp->previous_state = retval;
+ sdkp->previous_state = sdkp->media_present;
+
+ /* sdp->changed indicates medium was changed or is not present */
+ sdp->changed = !sdkp->media_present;
kfree(sshdr);
return retval;
}
@@ -1175,6 +1188,12 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512);
u64 bad_lba;
int info_valid;
+ /*
+ * resid is optional but mostly filled in. When it's unused,
+ * its value is zero, so we assume the whole buffer transferred
+ */
+ unsigned int transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd);
+ unsigned int good_bytes;
if (scmd->request->cmd_type != REQ_TYPE_FS)
return 0;
@@ -1208,7 +1227,8 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
/* This computation should always be done in terms of
* the resolution of the device's medium.
*/
- return (bad_lba - start_lba) * scmd->device->sector_size;
+ good_bytes = (bad_lba - start_lba) * scmd->device->sector_size;
+ return min(good_bytes, transferred);
}
/**
@@ -1902,10 +1922,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
int old_rcd = sdkp->RCD;
int old_dpofua = sdkp->DPOFUA;
- if (sdp->skip_ms_page_8)
- goto defaults;
-
- if (sdp->type == TYPE_RBC) {
+ if (sdp->skip_ms_page_8) {
+ if (sdp->type == TYPE_RBC)
+ goto defaults;
+ else {
+ modepage = 0x3F;
+ dbd = 0;
+ }
+ } else if (sdp->type == TYPE_RBC) {
modepage = 6;
dbd = 8;
} else {
@@ -1933,13 +1957,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
*/
if (len < 3)
goto bad_sense;
- if (len > 20)
- len = 20;
-
- /* Take headers and block descriptors into account */
- len += data.header_length + data.block_descriptor_length;
- if (len > SD_BUF_SIZE)
- goto bad_sense;
+ else if (len > SD_BUF_SIZE) {
+ sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
+ "data from %d to %d bytes\n", len, SD_BUF_SIZE);
+ len = SD_BUF_SIZE;
+ }
/* Get the data */
res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
@@ -1947,16 +1969,45 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
if (scsi_status_is_good(res)) {
int offset = data.header_length + data.block_descriptor_length;
- if (offset >= SD_BUF_SIZE - 2) {
- sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
- goto defaults;
+ while (offset < len) {
+ u8 page_code = buffer[offset] & 0x3F;
+ u8 spf = buffer[offset] & 0x40;
+
+ if (page_code == 8 || page_code == 6) {
+ /* We're interested only in the first 3 bytes.
+ */
+ if (len - offset <= 2) {
+ sd_printk(KERN_ERR, sdkp, "Incomplete "
+ "mode parameter data\n");
+ goto defaults;
+ } else {
+ modepage = page_code;
+ goto Page_found;
+ }
+ } else {
+ /* Go to the next page */
+ if (spf && len - offset > 3)
+ offset += 4 + (buffer[offset+2] << 8) +
+ buffer[offset+3];
+ else if (!spf && len - offset > 1)
+ offset += 2 + buffer[offset+1];
+ else {
+ sd_printk(KERN_ERR, sdkp, "Incomplete "
+ "mode parameter data\n");
+ goto defaults;
+ }
+ }
}
- if ((buffer[offset] & 0x3f) != modepage) {
+ if (modepage == 0x3F) {
+ sd_printk(KERN_ERR, sdkp, "No Caching mode page "
+ "present\n");
+ goto defaults;
+ } else if ((buffer[offset] & 0x3f) != modepage) {
sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
goto defaults;
}
-
+ Page_found:
if (modepage == 8) {
sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 5b7388f1c83..1871b8ae83a 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static const char *verstr = "20100829";
+static const char *verstr = "20101219";
#include <linux/module.h>
@@ -3729,9 +3729,11 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
b_size = PAGE_SIZE << order;
} else {
for (b_size = PAGE_SIZE, order = 0;
- order < ST_MAX_ORDER && b_size < new_size;
+ order < ST_MAX_ORDER &&
+ max_segs * (PAGE_SIZE << order) < new_size;
order++, b_size *= 2)
; /* empty */
+ STbuffer->reserved_page_order = order;
}
if (max_segs * (PAGE_SIZE << order) < new_size) {
if (order == ST_MAX_ORDER)
@@ -3758,7 +3760,6 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
segs++;
}
STbuffer->b_data = page_address(STbuffer->reserved_pages[0]);
- STbuffer->reserved_page_order = order;
return 1;
}