lpfc: add Emulex FC driver version 8.0.28
From: James.Smart@Emulex.Com Modified for kernel import and Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
8e8790415e
commit
dea3101e0a
1865
Documentation/scsi/ChangeLog.lpfc
Normal file
1865
Documentation/scsi/ChangeLog.lpfc
Normal file
File diff suppressed because it is too large
Load Diff
83
Documentation/scsi/lpfc.txt
Normal file
83
Documentation/scsi/lpfc.txt
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
LPFC Driver Release Notes:
|
||||
|
||||
=============================================================================
|
||||
|
||||
|
||||
IMPORTANT:
|
||||
|
||||
Starting in the 8.0.17 release, the driver began to be targeted strictly
|
||||
toward the upstream kernel. As such, we removed #ifdefs for older kernels
|
||||
(pre 2.6.10). The 8.0.16 release should be used if the driver is to be
|
||||
run on one of the older kernels.
|
||||
|
||||
The proposed modifications to the transport layer for FC remote ports
|
||||
and extended attribute support is now part of the upstream kernel
|
||||
as of 2.6.12. We no longer need to provide patches for this support,
|
||||
nor a *full* version which has old an new kernel support.
|
||||
|
||||
The driver now requires a 2.6.12 (if pre-release, 2.6.12-rc1) or later
|
||||
kernel.
|
||||
|
||||
Please heed these dependencies....
|
||||
|
||||
|
||||
********************************************************************
|
||||
|
||||
|
||||
The following information is provided for additional background on the
|
||||
history of the driver as we push for upstream acceptance.
|
||||
|
||||
Cable pull and temporary device Loss:
|
||||
|
||||
In older revisions of the lpfc driver, the driver internally queued i/o
|
||||
received from the midlayer. In the cases where a cable was pulled, link
|
||||
jitter, or a device temporarily loses connectivity (due to its cable
|
||||
being removed, a switch rebooting, or a device reboot), the driver could
|
||||
hide the disappearance of the device from the midlayer. I/O's issued to
|
||||
the LLDD would simply be queued for a short duration, allowing the device
|
||||
to reappear or link come back alive, with no inadvertant side effects
|
||||
to the system. If the driver did not hide these conditions, i/o would be
|
||||
errored by the driver, the mid-layer would exhaust its retries, and the
|
||||
device would be taken offline. Manual intervention would be required to
|
||||
re-enable the device.
|
||||
|
||||
The community supporting kernel.org has driven an effort to remove
|
||||
internal queuing from all LLDDs. The philosophy is that internal
|
||||
queuing is unnecessary as the block layer already performs the
|
||||
queuing. Removing the queues from the LLDD makes a more predictable
|
||||
and more simple LLDD.
|
||||
|
||||
As a potential new addition to kernel.org, the 8.x driver was asked to
|
||||
have all internal queuing removed. Emulex complied with this request.
|
||||
In explaining the impacts of this change, Emulex has worked with the
|
||||
community in modifying the behavior of the SCSI midlayer so that SCSI
|
||||
devices can be temporarily suspended while transport events (such as
|
||||
those described) can occur.
|
||||
|
||||
The proposed patch was posted to the linux-scsi mailing list. The patch
|
||||
is contained in the 2.6.10-rc2 (and later) patch kits. As such, this
|
||||
patch is part of the standard 2.6.10 kernel.
|
||||
|
||||
By default, the driver expects the patches for block/unblock interfaces
|
||||
to be present in the kernel. No #define needs to be set to enable support.
|
||||
|
||||
|
||||
Kernel Support
|
||||
|
||||
This source package is targeted for the upstream kernel only. (See notes
|
||||
at the top of this file). It relies on interfaces that are slowing
|
||||
migrating into the kernel.org kernel.
|
||||
|
||||
At this time, the driver requires the 2.6.12 (if pre-release, 2.6.12-rc1)
|
||||
kernel.
|
||||
|
||||
If a driver is needed for older kernels please utilize the 8.0.16
|
||||
driver sources.
|
||||
|
||||
|
||||
Patches
|
||||
|
||||
Thankfully, at this time, patches are not needed.
|
||||
|
||||
|
|
@ -1314,6 +1314,14 @@ config SCSI_QLOGICPTI
|
|||
|
||||
source "drivers/scsi/qla2xxx/Kconfig"
|
||||
|
||||
config SCSI_LPFC
|
||||
tristate "Emulex LightPulse Fibre Channel Support"
|
||||
depends on PCI && SCSI
|
||||
select SCSI_FC_ATTRS
|
||||
help
|
||||
This lpfc driver supports the Emulex LightPulse
|
||||
Family of Fibre Channel PCI host adapters.
|
||||
|
||||
config SCSI_SEAGATE
|
||||
tristate "Seagate ST-02 and Future Domain TMC-8xx SCSI support"
|
||||
depends on X86 && ISA && SCSI && BROKEN
|
||||
|
|
|
@ -80,6 +80,7 @@ obj-$(CONFIG_SCSI_QLOGIC_ISP) += qlogicisp.o
|
|||
obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o
|
||||
obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
|
||||
obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx/
|
||||
obj-$(CONFIG_SCSI_LPFC) += lpfc/
|
||||
obj-$(CONFIG_SCSI_PAS16) += pas16.o
|
||||
obj-$(CONFIG_SCSI_SEAGATE) += seagate.o
|
||||
obj-$(CONFIG_SCSI_FD_8xx) += seagate.o
|
||||
|
|
32
drivers/scsi/lpfc/Makefile
Normal file
32
drivers/scsi/lpfc/Makefile
Normal file
|
@ -0,0 +1,32 @@
|
|||
#/*******************************************************************
|
||||
# * This file is part of the Emulex Linux Device Driver for *
|
||||
# * Enterprise Fibre Channel Host Bus Adapters. *
|
||||
# * Refer to the README file included with this package for *
|
||||
# * driver version and adapter support. *
|
||||
# * Copyright (C) 2004 Emulex Corporation. *
|
||||
# * www.emulex.com *
|
||||
# * *
|
||||
# * 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, a copy of which *
|
||||
# * can be found in the file COPYING included with this package. *
|
||||
# *******************************************************************/
|
||||
######################################################################
|
||||
|
||||
#$Id: Makefile 1.58 2005/01/23 19:00:32EST sf_support Exp $
|
||||
|
||||
ifneq ($(GCOV),)
|
||||
EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
EXTRA_CFLAGS += -O0
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_SCSI_LPFC) := lpfc.o
|
||||
|
||||
lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o \
|
||||
lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o
|
384
drivers/scsi/lpfc/lpfc.h
Normal file
384
drivers/scsi/lpfc/lpfc.h
Normal file
|
@ -0,0 +1,384 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc.h 1.167 2005/04/07 08:47:05EDT sf_support Exp $
|
||||
*/
|
||||
|
||||
struct lpfc_sli2_slim;
|
||||
|
||||
#define LPFC_MAX_TARGET 256 /* max targets supported */
|
||||
#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els req */
|
||||
#define LPFC_MAX_NS_RETRY 3 /* max NameServer retries */
|
||||
|
||||
#define LPFC_DFT_HBA_Q_DEPTH 2048 /* max cmds per hba */
|
||||
#define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */
|
||||
#define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */
|
||||
|
||||
#define LPFC_CMD_PER_LUN 30 /* max outstanding cmds per lun */
|
||||
#define LPFC_SG_SEG_CNT 64 /* sg element count per scsi cmnd */
|
||||
#define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */
|
||||
|
||||
/* Define macros for 64 bit support */
|
||||
#define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr)))
|
||||
#define putPaddrHigh(addr) ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
|
||||
#define getPaddr(high, low) ((dma_addr_t)( \
|
||||
(( (u64)(high)<<16 ) << 16)|( (u64)(low))))
|
||||
/* Provide maximum configuration definitions. */
|
||||
#define LPFC_DRVR_TIMEOUT 16 /* driver iocb timeout value in sec */
|
||||
#define MAX_FCP_TARGET 256 /* max num of FCP targets supported */
|
||||
#define FC_MAX_ADPTMSG 64
|
||||
|
||||
#define MAX_HBAEVT 32
|
||||
|
||||
/* Provide DMA memory definitions the driver uses per port instance. */
|
||||
struct lpfc_dmabuf {
|
||||
struct list_head list;
|
||||
void *virt; /* virtual address ptr */
|
||||
dma_addr_t phys; /* mapped address */
|
||||
};
|
||||
|
||||
struct lpfc_dma_pool {
|
||||
struct lpfc_dmabuf *elements;
|
||||
uint32_t max_count;
|
||||
uint32_t current_count;
|
||||
};
|
||||
|
||||
/* Priority bit. Set value to exceed low water mark in lpfc_mem. */
|
||||
#define MEM_PRI 0x100
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Device VPD save area */
|
||||
/****************************************************************************/
|
||||
typedef struct lpfc_vpd {
|
||||
uint32_t status; /* vpd status value */
|
||||
uint32_t length; /* number of bytes actually returned */
|
||||
struct {
|
||||
uint32_t rsvd1; /* Revision numbers */
|
||||
uint32_t biuRev;
|
||||
uint32_t smRev;
|
||||
uint32_t smFwRev;
|
||||
uint32_t endecRev;
|
||||
uint16_t rBit;
|
||||
uint8_t fcphHigh;
|
||||
uint8_t fcphLow;
|
||||
uint8_t feaLevelHigh;
|
||||
uint8_t feaLevelLow;
|
||||
uint32_t postKernRev;
|
||||
uint32_t opFwRev;
|
||||
uint8_t opFwName[16];
|
||||
uint32_t sli1FwRev;
|
||||
uint8_t sli1FwName[16];
|
||||
uint32_t sli2FwRev;
|
||||
uint8_t sli2FwName[16];
|
||||
} rev;
|
||||
} lpfc_vpd_t;
|
||||
|
||||
struct lpfc_scsi_buf;
|
||||
|
||||
|
||||
/*
|
||||
* lpfc stat counters
|
||||
*/
|
||||
struct lpfc_stats {
|
||||
/* Statistics for ELS commands */
|
||||
uint32_t elsLogiCol;
|
||||
uint32_t elsRetryExceeded;
|
||||
uint32_t elsXmitRetry;
|
||||
uint32_t elsDelayRetry;
|
||||
uint32_t elsRcvDrop;
|
||||
uint32_t elsRcvFrame;
|
||||
uint32_t elsRcvRSCN;
|
||||
uint32_t elsRcvRNID;
|
||||
uint32_t elsRcvFARP;
|
||||
uint32_t elsRcvFARPR;
|
||||
uint32_t elsRcvFLOGI;
|
||||
uint32_t elsRcvPLOGI;
|
||||
uint32_t elsRcvADISC;
|
||||
uint32_t elsRcvPDISC;
|
||||
uint32_t elsRcvFAN;
|
||||
uint32_t elsRcvLOGO;
|
||||
uint32_t elsRcvPRLO;
|
||||
uint32_t elsRcvPRLI;
|
||||
uint32_t elsRcvRRQ;
|
||||
uint32_t elsXmitFLOGI;
|
||||
uint32_t elsXmitPLOGI;
|
||||
uint32_t elsXmitPRLI;
|
||||
uint32_t elsXmitADISC;
|
||||
uint32_t elsXmitLOGO;
|
||||
uint32_t elsXmitSCR;
|
||||
uint32_t elsXmitRNID;
|
||||
uint32_t elsXmitFARP;
|
||||
uint32_t elsXmitFARPR;
|
||||
uint32_t elsXmitACC;
|
||||
uint32_t elsXmitLSRJT;
|
||||
|
||||
uint32_t frameRcvBcast;
|
||||
uint32_t frameRcvMulti;
|
||||
uint32_t strayXmitCmpl;
|
||||
uint32_t frameXmitDelay;
|
||||
uint32_t xriCmdCmpl;
|
||||
uint32_t xriStatErr;
|
||||
uint32_t LinkUp;
|
||||
uint32_t LinkDown;
|
||||
uint32_t LinkMultiEvent;
|
||||
uint32_t NoRcvBuf;
|
||||
uint32_t fcpCmd;
|
||||
uint32_t fcpCmpl;
|
||||
uint32_t fcpRspErr;
|
||||
uint32_t fcpRemoteStop;
|
||||
uint32_t fcpPortRjt;
|
||||
uint32_t fcpPortBusy;
|
||||
uint32_t fcpError;
|
||||
uint32_t fcpLocalErr;
|
||||
};
|
||||
|
||||
enum sysfs_mbox_state {
|
||||
SMBOX_IDLE,
|
||||
SMBOX_WRITING,
|
||||
SMBOX_READING
|
||||
};
|
||||
|
||||
struct lpfc_sysfs_mbox {
|
||||
enum sysfs_mbox_state state;
|
||||
size_t offset;
|
||||
struct lpfcMboxq * mbox;
|
||||
};
|
||||
|
||||
struct lpfc_hba {
|
||||
struct list_head hba_list; /* List of hbas/ports */
|
||||
struct lpfc_sli sli;
|
||||
struct lpfc_sli2_slim *slim2p;
|
||||
dma_addr_t slim2p_mapping;
|
||||
uint16_t pci_cfg_value;
|
||||
|
||||
uint32_t hba_state;
|
||||
|
||||
#define LPFC_INIT_START 1 /* Initial state after board reset */
|
||||
#define LPFC_INIT_MBX_CMDS 2 /* Initialize HBA with mbox commands */
|
||||
#define LPFC_LINK_DOWN 3 /* HBA initialized, link is down */
|
||||
#define LPFC_LINK_UP 4 /* Link is up - issue READ_LA */
|
||||
#define LPFC_LOCAL_CFG_LINK 5 /* local NPORT Id configured */
|
||||
#define LPFC_FLOGI 6 /* FLOGI sent to Fabric */
|
||||
#define LPFC_FABRIC_CFG_LINK 7 /* Fabric assigned NPORT Id
|
||||
configured */
|
||||
#define LPFC_NS_REG 8 /* Register with NameServer */
|
||||
#define LPFC_NS_QRY 9 /* Query NameServer for NPort ID list */
|
||||
#define LPFC_BUILD_DISC_LIST 10 /* Build ADISC and PLOGI lists for
|
||||
* device authentication / discovery */
|
||||
#define LPFC_DISC_AUTH 11 /* Processing ADISC list */
|
||||
#define LPFC_CLEAR_LA 12 /* authentication cmplt - issue
|
||||
CLEAR_LA */
|
||||
#define LPFC_HBA_READY 32
|
||||
#define LPFC_HBA_ERROR 0xff
|
||||
|
||||
uint8_t fc_linkspeed; /* Link speed after last READ_LA */
|
||||
|
||||
uint32_t fc_eventTag; /* event tag for link attention */
|
||||
uint32_t fc_prli_sent; /* cntr for outstanding PRLIs */
|
||||
|
||||
uint32_t num_disc_nodes; /*in addition to hba_state */
|
||||
|
||||
struct timer_list fc_estabtmo; /* link establishment timer */
|
||||
struct timer_list fc_disctmo; /* Discovery rescue timer */
|
||||
struct timer_list fc_fdmitmo; /* fdmi timer */
|
||||
/* These fields used to be binfo */
|
||||
struct lpfc_name fc_nodename; /* fc nodename */
|
||||
struct lpfc_name fc_portname; /* fc portname */
|
||||
uint32_t fc_pref_DID; /* preferred D_ID */
|
||||
uint8_t fc_pref_ALPA; /* preferred AL_PA */
|
||||
uint32_t fc_edtov; /* E_D_TOV timer value */
|
||||
uint32_t fc_arbtov; /* ARB_TOV timer value */
|
||||
uint32_t fc_ratov; /* R_A_TOV timer value */
|
||||
uint32_t fc_rttov; /* R_T_TOV timer value */
|
||||
uint32_t fc_altov; /* AL_TOV timer value */
|
||||
uint32_t fc_crtov; /* C_R_TOV timer value */
|
||||
uint32_t fc_citov; /* C_I_TOV timer value */
|
||||
uint32_t fc_myDID; /* fibre channel S_ID */
|
||||
uint32_t fc_prevDID; /* previous fibre channel S_ID */
|
||||
|
||||
struct serv_parm fc_sparam; /* buffer for our service parameters */
|
||||
struct serv_parm fc_fabparam; /* fabric service parameters buffer */
|
||||
uint8_t alpa_map[128]; /* AL_PA map from READ_LA */
|
||||
|
||||
uint8_t fc_ns_retry; /* retries for fabric nameserver */
|
||||
uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */
|
||||
uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */
|
||||
struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
|
||||
uint32_t lmt;
|
||||
uint32_t fc_flag; /* FC flags */
|
||||
#define FC_PT2PT 0x1 /* pt2pt with no fabric */
|
||||
#define FC_PT2PT_PLOGI 0x2 /* pt2pt initiate PLOGI */
|
||||
#define FC_DISC_TMO 0x4 /* Discovery timer running */
|
||||
#define FC_PUBLIC_LOOP 0x8 /* Public loop */
|
||||
#define FC_LBIT 0x10 /* LOGIN bit in loopinit set */
|
||||
#define FC_RSCN_MODE 0x20 /* RSCN cmd rcv'ed */
|
||||
#define FC_NLP_MORE 0x40 /* More node to process in node tbl */
|
||||
#define FC_OFFLINE_MODE 0x80 /* Interface is offline for diag */
|
||||
#define FC_FABRIC 0x100 /* We are fabric attached */
|
||||
#define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */
|
||||
#define FC_RSCN_DISCOVERY 0x400 /* Authenticate all devices after RSCN*/
|
||||
#define FC_LOADING 0x1000 /* HBA in process of loading drvr */
|
||||
#define FC_UNLOADING 0x2000 /* HBA in process of unloading drvr */
|
||||
#define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
|
||||
#define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
|
||||
#define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */
|
||||
|
||||
uint32_t fc_topology; /* link topology, from LINK INIT */
|
||||
|
||||
struct lpfc_stats fc_stat;
|
||||
|
||||
/* These are the head/tail pointers for the bind, plogi, adisc, unmap,
|
||||
* and map lists. Their counters are immediately following.
|
||||
*/
|
||||
struct list_head fc_plogi_list;
|
||||
struct list_head fc_adisc_list;
|
||||
struct list_head fc_reglogin_list;
|
||||
struct list_head fc_prli_list;
|
||||
struct list_head fc_nlpunmap_list;
|
||||
struct list_head fc_nlpmap_list;
|
||||
struct list_head fc_npr_list;
|
||||
struct list_head fc_unused_list;
|
||||
|
||||
/* Keep counters for the number of entries in each list. */
|
||||
uint16_t fc_plogi_cnt;
|
||||
uint16_t fc_adisc_cnt;
|
||||
uint16_t fc_reglogin_cnt;
|
||||
uint16_t fc_prli_cnt;
|
||||
uint16_t fc_unmap_cnt;
|
||||
uint16_t fc_map_cnt;
|
||||
uint16_t fc_npr_cnt;
|
||||
uint16_t fc_unused_cnt;
|
||||
struct lpfc_nodelist fc_fcpnodev; /* nodelist entry for no device */
|
||||
uint32_t nport_event_cnt; /* timestamp for nlplist entry */
|
||||
|
||||
#define LPFC_RPI_HASH_SIZE 64
|
||||
#define LPFC_RPI_HASH_FUNC(x) ((x) & (0x3f))
|
||||
/* ptr to active D_ID / RPIs */
|
||||
struct lpfc_nodelist *fc_nlplookup[LPFC_RPI_HASH_SIZE];
|
||||
uint32_t wwnn[2];
|
||||
uint32_t RandomData[7];
|
||||
|
||||
uint32_t cfg_log_verbose;
|
||||
uint32_t cfg_lun_queue_depth;
|
||||
uint32_t cfg_nodev_tmo;
|
||||
uint32_t cfg_hba_queue_depth;
|
||||
uint32_t cfg_fcp_class;
|
||||
uint32_t cfg_use_adisc;
|
||||
uint32_t cfg_ack0;
|
||||
uint32_t cfg_topology;
|
||||
uint32_t cfg_scan_down;
|
||||
uint32_t cfg_link_speed;
|
||||
uint32_t cfg_cr_delay;
|
||||
uint32_t cfg_cr_count;
|
||||
uint32_t cfg_fdmi_on;
|
||||
uint32_t cfg_fcp_bind_method;
|
||||
uint32_t cfg_discovery_threads;
|
||||
uint32_t cfg_max_luns;
|
||||
uint32_t cfg_sg_seg_cnt;
|
||||
uint32_t cfg_sg_dma_buf_size;
|
||||
|
||||
lpfc_vpd_t vpd; /* vital product data */
|
||||
|
||||
struct Scsi_Host *host;
|
||||
struct pci_dev *pcidev;
|
||||
struct list_head work_list;
|
||||
uint32_t work_ha; /* Host Attention Bits for WT */
|
||||
uint32_t work_ha_mask; /* HA Bits owned by WT */
|
||||
uint32_t work_hs; /* HS stored in case of ERRAT */
|
||||
uint32_t work_status[2]; /* Extra status from SLIM */
|
||||
uint32_t work_hba_events; /* Timeout to be handled */
|
||||
#define WORKER_DISC_TMO 0x1 /* Discovery timeout */
|
||||
#define WORKER_ELS_TMO 0x2 /* ELS timeout */
|
||||
#define WORKER_MBOX_TMO 0x4 /* MBOX timeout */
|
||||
#define WORKER_FDMI_TMO 0x8 /* FDMI timeout */
|
||||
|
||||
wait_queue_head_t *work_wait;
|
||||
struct task_struct *worker_thread;
|
||||
|
||||
unsigned long pci_bar0_map; /* Physical address for PCI BAR0 */
|
||||
unsigned long pci_bar2_map; /* Physical address for PCI BAR2 */
|
||||
void __iomem *slim_memmap_p; /* Kernel memory mapped address for
|
||||
PCI BAR0 */
|
||||
void __iomem *ctrl_regs_memmap_p;/* Kernel memory mapped address for
|
||||
PCI BAR2 */
|
||||
|
||||
void __iomem *MBslimaddr; /* virtual address for mbox cmds */
|
||||
void __iomem *HAregaddr; /* virtual address for host attn reg */
|
||||
void __iomem *CAregaddr; /* virtual address for chip attn reg */
|
||||
void __iomem *HSregaddr; /* virtual address for host status
|
||||
reg */
|
||||
void __iomem *HCregaddr; /* virtual address for host ctl reg */
|
||||
|
||||
int brd_no; /* FC board number */
|
||||
|
||||
char SerialNumber[32]; /* adapter Serial Number */
|
||||
char OptionROMVersion[32]; /* adapter BIOS / Fcode version */
|
||||
char ModelDesc[256]; /* Model Description */
|
||||
char ModelName[80]; /* Model Name */
|
||||
char ProgramType[256]; /* Program Type */
|
||||
char Port[20]; /* Port No */
|
||||
uint8_t vpd_flag; /* VPD data flag */
|
||||
|
||||
#define VPD_MODEL_DESC 0x1 /* valid vpd model description */
|
||||
#define VPD_MODEL_NAME 0x2 /* valid vpd model name */
|
||||
#define VPD_PROGRAM_TYPE 0x4 /* valid vpd program type */
|
||||
#define VPD_PORT 0x8 /* valid vpd port data */
|
||||
#define VPD_MASK 0xf /* mask for any vpd data */
|
||||
|
||||
struct timer_list els_tmofunc;
|
||||
|
||||
void *link_stats;
|
||||
|
||||
/*
|
||||
* stat counters
|
||||
*/
|
||||
uint64_t fc4InputRequests;
|
||||
uint64_t fc4OutputRequests;
|
||||
uint64_t fc4ControlRequests;
|
||||
|
||||
struct lpfc_sysfs_mbox sysfs_mbox;
|
||||
|
||||
/* fastpath list. */
|
||||
struct list_head lpfc_scsi_buf_list;
|
||||
uint32_t total_scsi_bufs;
|
||||
struct list_head lpfc_iocb_list;
|
||||
uint32_t total_iocbq_bufs;
|
||||
|
||||
/* pci_mem_pools */
|
||||
struct pci_pool *lpfc_scsi_dma_buf_pool;
|
||||
struct pci_pool *lpfc_mbuf_pool;
|
||||
struct lpfc_dma_pool lpfc_mbuf_safety_pool;
|
||||
|
||||
mempool_t *mbox_mem_pool;
|
||||
mempool_t *nlp_mem_pool;
|
||||
struct list_head freebufList;
|
||||
struct list_head ctrspbuflist;
|
||||
struct list_head rnidrspbuflist;
|
||||
};
|
||||
|
||||
|
||||
struct rnidrsp {
|
||||
void *buf;
|
||||
uint32_t uniqueid;
|
||||
struct list_head list;
|
||||
uint32_t data;
|
||||
};
|
1291
drivers/scsi/lpfc/lpfc_attr.c
Normal file
1291
drivers/scsi/lpfc/lpfc_attr.c
Normal file
File diff suppressed because it is too large
Load Diff
97
drivers/scsi/lpfc/lpfc_compat.h
Normal file
97
drivers/scsi/lpfc/lpfc_compat.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_compat.h 1.32 2005/01/25 17:51:45EST sf_support Exp $
|
||||
*
|
||||
* This file provides macros to aid compilation in the Linux 2.4 kernel
|
||||
* over various platform architectures.
|
||||
*/
|
||||
|
||||
/*******************************************************************
|
||||
Note: HBA's SLI memory contains little-endian LW.
|
||||
Thus to access it from a little-endian host,
|
||||
memcpy_toio() and memcpy_fromio() can be used.
|
||||
However on a big-endian host, copy 4 bytes at a time,
|
||||
using writel() and readl().
|
||||
*******************************************************************/
|
||||
|
||||
#if __BIG_ENDIAN
|
||||
|
||||
static inline void
|
||||
lpfc_memcpy_to_slim(void __iomem *dest, void *src, unsigned int bytes)
|
||||
{
|
||||
uint32_t __iomem *dest32;
|
||||
uint32_t *src32;
|
||||
unsigned int four_bytes;
|
||||
|
||||
|
||||
dest32 = (uint32_t __iomem *) dest;
|
||||
src32 = (uint32_t *) src;
|
||||
|
||||
/* write input bytes, 4 bytes at a time */
|
||||
for (four_bytes = bytes /4; four_bytes > 0; four_bytes--) {
|
||||
writel( *src32, dest32);
|
||||
readl(dest32); /* flush */
|
||||
dest32++;
|
||||
src32++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void
|
||||
lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes)
|
||||
{
|
||||
uint32_t *dest32;
|
||||
uint32_t __iomem *src32;
|
||||
unsigned int four_bytes;
|
||||
|
||||
|
||||
dest32 = (uint32_t *) dest;
|
||||
src32 = (uint32_t __iomem *) src;
|
||||
|
||||
/* read input bytes, 4 bytes at a time */
|
||||
for (four_bytes = bytes /4; four_bytes > 0; four_bytes--) {
|
||||
*dest32 = readl( src32);
|
||||
dest32++;
|
||||
src32++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes)
|
||||
{
|
||||
/* actually returns 1 byte past dest */
|
||||
memcpy_toio( dest, src, bytes);
|
||||
}
|
||||
|
||||
static inline void
|
||||
lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes)
|
||||
{
|
||||
/* actually returns 1 byte past dest */
|
||||
memcpy_fromio( dest, src, bytes);
|
||||
}
|
||||
|
||||
#endif /* __BIG_ENDIAN */
|
216
drivers/scsi/lpfc/lpfc_crtn.h
Normal file
216
drivers/scsi/lpfc/lpfc_crtn.h
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_crtn.h 1.166 2005/04/07 08:46:47EDT sf_support Exp $
|
||||
*/
|
||||
|
||||
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
|
||||
void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
|
||||
struct lpfc_dmabuf *mp);
|
||||
void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
|
||||
int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *,
|
||||
uint32_t);
|
||||
void lpfc_unreg_login(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
|
||||
void lpfc_unreg_did(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
|
||||
void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
|
||||
|
||||
|
||||
int lpfc_linkdown(struct lpfc_hba *);
|
||||
void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
|
||||
void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_nlp_plogi(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
int lpfc_nlp_adisc(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
int lpfc_nlp_unmapped(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
int lpfc_nlp_list(struct lpfc_hba *, struct lpfc_nodelist *, int);
|
||||
void lpfc_set_disctmo(struct lpfc_hba *);
|
||||
int lpfc_can_disctmo(struct lpfc_hba *);
|
||||
int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *, struct lpfc_nodelist *);
|
||||
int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t);
|
||||
struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t);
|
||||
struct lpfc_nodelist *lpfc_setup_rscn_node(struct lpfc_hba *, uint32_t);
|
||||
void lpfc_disc_list_loopmap(struct lpfc_hba *);
|
||||
void lpfc_disc_start(struct lpfc_hba *);
|
||||
void lpfc_disc_flush_list(struct lpfc_hba *);
|
||||
void lpfc_disc_timeout(unsigned long);
|
||||
void lpfc_scan_timeout(unsigned long);
|
||||
|
||||
struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
|
||||
struct lpfc_nodelist *lpfc_findnode_remove_rpi(struct lpfc_hba * phba,
|
||||
uint16_t rpi);
|
||||
void lpfc_addnode_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
|
||||
uint16_t rpi);
|
||||
|
||||
int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
|
||||
int lpfc_do_work(void *);
|
||||
int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
|
||||
uint32_t);
|
||||
|
||||
uint32_t lpfc_cmpl_prli_reglogin_issue(struct lpfc_hba *,
|
||||
struct lpfc_nodelist *, void *,
|
||||
uint32_t);
|
||||
uint32_t lpfc_cmpl_plogi_prli_issue(struct lpfc_hba *, struct lpfc_nodelist *,
|
||||
void *, uint32_t);
|
||||
|
||||
int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
|
||||
struct serv_parm *, uint32_t);
|
||||
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp,
|
||||
int);
|
||||
int lpfc_els_abort_flogi(struct lpfc_hba *);
|
||||
int lpfc_initial_flogi(struct lpfc_hba *);
|
||||
int lpfc_issue_els_plogi(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
|
||||
int lpfc_issue_els_prli(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
|
||||
int lpfc_issue_els_adisc(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
|
||||
int lpfc_issue_els_logo(struct lpfc_hba *, struct lpfc_nodelist *, uint8_t);
|
||||
int lpfc_issue_els_scr(struct lpfc_hba *, uint32_t, uint8_t);
|
||||
int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
|
||||
int lpfc_els_rsp_acc(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
|
||||
struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t);
|
||||
int lpfc_els_rsp_reject(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *,
|
||||
struct lpfc_nodelist *);
|
||||
int lpfc_els_rsp_adisc_acc(struct lpfc_hba *, struct lpfc_iocbq *,
|
||||
struct lpfc_nodelist *);
|
||||
int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *,
|
||||
struct lpfc_nodelist *);
|
||||
void lpfc_els_retry_delay(unsigned long);
|
||||
void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
|
||||
void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *);
|
||||
int lpfc_els_handle_rscn(struct lpfc_hba *);
|
||||
int lpfc_els_flush_rscn(struct lpfc_hba *);
|
||||
int lpfc_rscn_payload_check(struct lpfc_hba *, uint32_t);
|
||||
void lpfc_els_flush_cmd(struct lpfc_hba *);
|
||||
int lpfc_els_disc_adisc(struct lpfc_hba *);
|
||||
int lpfc_els_disc_plogi(struct lpfc_hba *);
|
||||
void lpfc_els_timeout(unsigned long);
|
||||
void lpfc_els_timeout_handler(struct lpfc_hba *);
|
||||
|
||||
void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *);
|
||||
int lpfc_ns_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
|
||||
int lpfc_fdmi_cmd(struct lpfc_hba *, struct lpfc_nodelist *, int);
|
||||
void lpfc_fdmi_tmo(unsigned long);
|
||||
void lpfc_fdmi_tmo_handler(struct lpfc_hba *);
|
||||
|
||||
int lpfc_config_port_prep(struct lpfc_hba *);
|
||||
int lpfc_config_port_post(struct lpfc_hba *);
|
||||
int lpfc_hba_down_prep(struct lpfc_hba *);
|
||||
void lpfc_hba_init(struct lpfc_hba *, uint32_t *);
|
||||
int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int);
|
||||
void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
|
||||
uint8_t *lpfc_get_lpfchba_info(struct lpfc_hba *, uint8_t *);
|
||||
int lpfc_fcp_abort(struct lpfc_hba *, int, int, int);
|
||||
int lpfc_online(struct lpfc_hba *);
|
||||
int lpfc_offline(struct lpfc_hba *);
|
||||
|
||||
|
||||
int lpfc_sli_setup(struct lpfc_hba *);
|
||||
int lpfc_sli_queue_setup(struct lpfc_hba *);
|
||||
void lpfc_slim_access(struct lpfc_hba *);
|
||||
|
||||
void lpfc_handle_eratt(struct lpfc_hba *);
|
||||
void lpfc_handle_latt(struct lpfc_hba *);
|
||||
irqreturn_t lpfc_intr_handler(int, void *, struct pt_regs *);
|
||||
|
||||
void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
|
||||
void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
|
||||
|
||||
int lpfc_mem_alloc(struct lpfc_hba *);
|
||||
void lpfc_mem_free(struct lpfc_hba *);
|
||||
|
||||
int lpfc_sli_hba_setup(struct lpfc_hba *);
|
||||
int lpfc_sli_hba_down(struct lpfc_hba *);
|
||||
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
|
||||
int lpfc_sli_handle_mb_event(struct lpfc_hba *);
|
||||
int lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
|
||||
struct lpfc_sli_ring *, uint32_t);
|
||||
void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *, uint32_t);
|
||||
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
|
||||
int lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
|
||||
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_dmabuf *);
|
||||
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
|
||||
struct lpfc_sli_ring *,
|
||||
dma_addr_t);
|
||||
int lpfc_sli_issue_abort_iotag32(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *);
|
||||
int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
|
||||
uint64_t, lpfc_ctx_cmd);
|
||||
int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
|
||||
uint64_t, uint32_t, lpfc_ctx_cmd);
|
||||
|
||||
void lpfc_mbox_timeout(unsigned long);
|
||||
void lpfc_mbox_timeout_handler(struct lpfc_hba *);
|
||||
void lpfc_map_fcp_cmnd_to_bpl(struct lpfc_hba *, struct lpfc_scsi_buf *);
|
||||
void lpfc_free_scsi_cmd(struct lpfc_scsi_buf *);
|
||||
uint32_t lpfc_os_timeout_transform(struct lpfc_hba *, uint32_t);
|
||||
|
||||
struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order,
|
||||
uint32_t did);
|
||||
|
||||
int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
|
||||
uint32_t timeout);
|
||||
|
||||
int lpfc_sli_issue_iocb_wait_high_priority(struct lpfc_hba * phba,
|
||||
struct lpfc_sli_ring * pring,
|
||||
struct lpfc_iocbq * piocb,
|
||||
uint32_t flag,
|
||||
struct lpfc_iocbq * prspiocbq,
|
||||
uint32_t timeout);
|
||||
void lpfc_sli_wake_iocb_high_priority(struct lpfc_hba * phba,
|
||||
struct lpfc_iocbq * queue1,
|
||||
struct lpfc_iocbq * queue2);
|
||||
|
||||
void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
|
||||
void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
|
||||
|
||||
/* Function prototypes. */
|
||||
const char* lpfc_info(struct Scsi_Host *);
|
||||
void lpfc_get_cfgparam(struct lpfc_hba *);
|
||||
int lpfc_alloc_sysfs_attr(struct lpfc_hba *);
|
||||
void lpfc_free_sysfs_attr(struct lpfc_hba *);
|
||||
extern struct class_device_attribute *lpfc_host_attrs[];
|
||||
extern struct scsi_host_template lpfc_template;
|
||||
extern struct fc_function_template lpfc_transport_functions;
|
||||
|
||||
void lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp);
|
||||
|
||||
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
|
||||
#define HBA_EVENT_RSCN 5
|
||||
#define HBA_EVENT_LINK_UP 2
|
||||
#define HBA_EVENT_LINK_DOWN 3
|
1237
drivers/scsi/lpfc/lpfc_ct.c
Normal file
1237
drivers/scsi/lpfc/lpfc_ct.c
Normal file
File diff suppressed because it is too large
Load Diff
206
drivers/scsi/lpfc/lpfc_disc.h
Normal file
206
drivers/scsi/lpfc/lpfc_disc.h
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_disc.h 1.61 2005/04/07 08:46:52EDT sf_support Exp $
|
||||
*/
|
||||
|
||||
#define FC_MAX_HOLD_RSCN 32 /* max number of deferred RSCNs */
|
||||
#define FC_MAX_NS_RSP 65536 /* max size NameServer rsp */
|
||||
#define FC_MAXLOOP 126 /* max devices supported on a fc loop */
|
||||
#define LPFC_DISC_FLOGI_TMO 10 /* Discovery FLOGI ratov */
|
||||
|
||||
|
||||
/* This is the protocol dependent definition for a Node List Entry.
|
||||
* This is used by Fibre Channel protocol to support FCP.
|
||||
*/
|
||||
|
||||
/* structure used to queue event to the discovery tasklet */
|
||||
struct lpfc_work_evt {
|
||||
struct list_head evt_listp;
|
||||
void * evt_arg1;
|
||||
void * evt_arg2;
|
||||
uint32_t evt;
|
||||
};
|
||||
|
||||
#define LPFC_EVT_NODEV_TMO 0x1
|
||||
#define LPFC_EVT_ONLINE 0x2
|
||||
#define LPFC_EVT_OFFLINE 0x3
|
||||
#define LPFC_EVT_ELS_RETRY 0x4
|
||||
|
||||
struct lpfc_nodelist {
|
||||
struct list_head nlp_listp;
|
||||
struct lpfc_name nlp_portname; /* port name */
|
||||
struct lpfc_name nlp_nodename; /* node name */
|
||||
uint32_t nlp_flag; /* entry flags */
|
||||
uint32_t nlp_DID; /* FC D_ID of entry */
|
||||
uint32_t nlp_last_elscmd; /* Last ELS cmd sent */
|
||||
uint16_t nlp_type;
|
||||
#define NLP_FC_NODE 0x1 /* entry is an FC node */
|
||||
#define NLP_FABRIC 0x4 /* entry rep a Fabric entity */
|
||||
#define NLP_FCP_TARGET 0x8 /* entry is an FCP target */
|
||||
#define NLP_FCP_INITIATOR 0x10 /* entry is an FCP Initiator */
|
||||
|
||||
uint16_t nlp_rpi;
|
||||
uint16_t nlp_state; /* state transition indicator */
|
||||
uint16_t nlp_xri; /* output exchange id for RPI */
|
||||
uint16_t nlp_sid; /* scsi id */
|
||||
#define NLP_NO_SID 0xffff
|
||||
uint16_t nlp_maxframe; /* Max RCV frame size */
|
||||
uint8_t nlp_class_sup; /* Supported Classes */
|
||||
uint8_t nlp_retry; /* used for ELS retries */
|
||||
uint8_t nlp_disc_refcnt; /* used for DSM */
|
||||
uint8_t nlp_fcp_info; /* class info, bits 0-3 */
|
||||
#define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */
|
||||
|
||||
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
|
||||
struct timer_list nlp_tmofunc; /* Used for nodev tmo */
|
||||
struct fc_rport *rport; /* Corresponding FC transport
|
||||
port structure */
|
||||
struct lpfc_nodelist *nlp_rpi_hash_next;
|
||||
struct lpfc_hba *nlp_phba;
|
||||
struct lpfc_work_evt nodev_timeout_evt;
|
||||
struct lpfc_work_evt els_retry_evt;
|
||||
};
|
||||
|
||||
/* Defines for nlp_flag (uint32) */
|
||||
#define NLP_NO_LIST 0x0 /* Indicates immediately free node */
|
||||
#define NLP_UNUSED_LIST 0x1 /* Flg to indicate node will be freed */
|
||||
#define NLP_PLOGI_LIST 0x2 /* Flg to indicate sent PLOGI */
|
||||
#define NLP_ADISC_LIST 0x3 /* Flg to indicate sent ADISC */
|
||||
#define NLP_REGLOGIN_LIST 0x4 /* Flg to indicate sent REG_LOGIN */
|
||||
#define NLP_PRLI_LIST 0x5 /* Flg to indicate sent PRLI */
|
||||
#define NLP_UNMAPPED_LIST 0x6 /* Node is now unmapped */
|
||||
#define NLP_MAPPED_LIST 0x7 /* Node is now mapped */
|
||||
#define NLP_NPR_LIST 0x8 /* Node is in NPort Recovery state */
|
||||
#define NLP_JUST_DQ 0x9 /* just deque ndlp in lpfc_nlp_list */
|
||||
#define NLP_LIST_MASK 0xf /* mask to see what list node is on */
|
||||
#define NLP_PLOGI_SND 0x20 /* sent PLOGI request for this entry */
|
||||
#define NLP_PRLI_SND 0x40 /* sent PRLI request for this entry */
|
||||
#define NLP_ADISC_SND 0x80 /* sent ADISC request for this entry */
|
||||
#define NLP_LOGO_SND 0x100 /* sent LOGO request for this entry */
|
||||
#define NLP_RNID_SND 0x400 /* sent RNID request for this entry */
|
||||
#define NLP_ELS_SND_MASK 0x7e0 /* sent ELS request for this entry */
|
||||
#define NLP_NODEV_TMO 0x10000 /* nodev timeout is running for node */
|
||||
#define NLP_DELAY_TMO 0x20000 /* delay timeout is running for node */
|
||||
#define NLP_NPR_2B_DISC 0x40000 /* node is included in num_disc_nodes */
|
||||
#define NLP_RCV_PLOGI 0x80000 /* Rcv'ed PLOGI from remote system */
|
||||
#define NLP_LOGO_ACC 0x100000 /* Process LOGO after ACC completes */
|
||||
#define NLP_TGT_NO_SCSIID 0x200000 /* good PRLI but no binding for scsid */
|
||||
#define NLP_ACC_REGLOGIN 0x1000000 /* Issue Reg Login after successful
|
||||
ACC */
|
||||
#define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from
|
||||
NPR list */
|
||||
#define NLP_DELAY_REMOVE 0x4000000 /* Defer removal till end of DSM */
|
||||
|
||||
/* Defines for list searchs */
|
||||
#define NLP_SEARCH_MAPPED 0x1 /* search mapped */
|
||||
#define NLP_SEARCH_UNMAPPED 0x2 /* search unmapped */
|
||||
#define NLP_SEARCH_PLOGI 0x4 /* search plogi */
|
||||
#define NLP_SEARCH_ADISC 0x8 /* search adisc */
|
||||
#define NLP_SEARCH_REGLOGIN 0x10 /* search reglogin */
|
||||
#define NLP_SEARCH_PRLI 0x20 /* search prli */
|
||||
#define NLP_SEARCH_NPR 0x40 /* search npr */
|
||||
#define NLP_SEARCH_UNUSED 0x80 /* search mapped */
|
||||
#define NLP_SEARCH_ALL 0xff /* search all lists */
|
||||
|
||||
/* There are 4 different double linked lists nodelist entries can reside on.
|
||||
* The Port Login (PLOGI) list and Address Discovery (ADISC) list are used
|
||||
* when Link Up discovery or Registered State Change Notification (RSCN)
|
||||
* processing is needed. Each list holds the nodes that require a PLOGI or
|
||||
* ADISC Extended Link Service (ELS) request. These lists keep track of the
|
||||
* nodes affected by an RSCN, or a Link Up (Typically, all nodes are effected
|
||||
* by Link Up) event. The unmapped_list contains all nodes that have
|
||||
* successfully logged into at the Fibre Channel level. The
|
||||
* mapped_list will contain all nodes that are mapped FCP targets.
|
||||
*
|
||||
* The bind list is a list of undiscovered (potentially non-existent) nodes
|
||||
* that we have saved binding information on. This information is used when
|
||||
* nodes transition from the unmapped to the mapped list.
|
||||
*/
|
||||
|
||||
/* Defines for nlp_state */
|
||||
#define NLP_STE_UNUSED_NODE 0x0 /* node is just allocated */
|
||||
#define NLP_STE_PLOGI_ISSUE 0x1 /* PLOGI was sent to NL_PORT */
|
||||
#define NLP_STE_ADISC_ISSUE 0x2 /* ADISC was sent to NL_PORT */
|
||||
#define NLP_STE_REG_LOGIN_ISSUE 0x3 /* REG_LOGIN was issued for NL_PORT */
|
||||
#define NLP_STE_PRLI_ISSUE 0x4 /* PRLI was sent to NL_PORT */
|
||||
#define NLP_STE_UNMAPPED_NODE 0x5 /* PRLI completed from NL_PORT */
|
||||
#define NLP_STE_MAPPED_NODE 0x6 /* Identified as a FCP Target */
|
||||
#define NLP_STE_NPR_NODE 0x7 /* NPort disappeared */
|
||||
#define NLP_STE_MAX_STATE 0x8
|
||||
#define NLP_STE_FREED_NODE 0xff /* node entry was freed to MEM_NLP */
|
||||
|
||||
/* For UNUSED_NODE state, the node has just been allocated.
|
||||
* For PLOGI_ISSUE and REG_LOGIN_ISSUE, the node is on
|
||||
* the PLOGI list. For REG_LOGIN_COMPL, the node is taken off the PLOGI list
|
||||
* and put on the unmapped list. For ADISC processing, the node is taken off
|
||||
* the ADISC list and placed on either the mapped or unmapped list (depending
|
||||
* on its previous state). Once on the unmapped list, a PRLI is issued and the
|
||||
* state changed to PRLI_ISSUE. When the PRLI completion occurs, the state is
|
||||
* changed to PRLI_COMPL. If the completion indicates a mapped
|
||||
* node, the node is taken off the unmapped list. The binding list is checked
|
||||
* for a valid binding, or a binding is automatically assigned. If binding
|
||||
* assignment is unsuccessful, the node is left on the unmapped list. If
|
||||
* binding assignment is successful, the associated binding list entry (if
|
||||
* any) is removed, and the node is placed on the mapped list.
|
||||
*/
|
||||
/*
|
||||
* For a Link Down, all nodes on the ADISC, PLOGI, unmapped or mapped
|
||||
* lists will receive a DEVICE_RECOVERY event. If the linkdown or nodev timers
|
||||
* expire, all effected nodes will receive a DEVICE_RM event.
|
||||
*/
|
||||
/*
|
||||
* For a Link Up or RSCN, all nodes will move from the mapped / unmapped lists
|
||||
* to either the ADISC or PLOGI list. After a Nameserver query or ALPA loopmap
|
||||
* check, additional nodes may be added (DEVICE_ADD) or removed (DEVICE_RM) to /
|
||||
* from the PLOGI or ADISC lists. Once the PLOGI and ADISC lists are populated,
|
||||
* we will first process the ADISC list. 32 entries are processed initially and
|
||||
* ADISC is initited for each one. Completions / Events for each node are
|
||||
* funnelled thru the state machine. As each node finishes ADISC processing, it
|
||||
* starts ADISC for any nodes waiting for ADISC processing. If no nodes are
|
||||
* waiting, and the ADISC list count is identically 0, then we are done. For
|
||||
* Link Up discovery, since all nodes on the PLOGI list are UNREG_LOGIN'ed, we
|
||||
* can issue a CLEAR_LA and reenable Link Events. Next we will process the PLOGI
|
||||
* list. 32 entries are processed initially and PLOGI is initited for each one.
|
||||
* Completions / Events for each node are funnelled thru the state machine. As
|
||||
* each node finishes PLOGI processing, it starts PLOGI for any nodes waiting
|
||||
* for PLOGI processing. If no nodes are waiting, and the PLOGI list count is
|
||||
* identically 0, then we are done. We have now completed discovery / RSCN
|
||||
* handling. Upon completion, ALL nodes should be on either the mapped or
|
||||
* unmapped lists.
|
||||
*/
|
||||
|
||||
/* Defines for Node List Entry Events that could happen */
|
||||
#define NLP_EVT_RCV_PLOGI 0x0 /* Rcv'd an ELS PLOGI command */
|
||||
#define NLP_EVT_RCV_PRLI 0x1 /* Rcv'd an ELS PRLI command */
|
||||
#define NLP_EVT_RCV_LOGO 0x2 /* Rcv'd an ELS LOGO command */
|
||||
#define NLP_EVT_RCV_ADISC 0x3 /* Rcv'd an ELS ADISC command */
|
||||
#define NLP_EVT_RCV_PDISC 0x4 /* Rcv'd an ELS PDISC command */
|
||||
#define NLP_EVT_RCV_PRLO 0x5 /* Rcv'd an ELS PRLO command */
|
||||
#define NLP_EVT_CMPL_PLOGI 0x6 /* Sent an ELS PLOGI command */
|
||||
#define NLP_EVT_CMPL_PRLI 0x7 /* Sent an ELS PRLI command */
|
||||
#define NLP_EVT_CMPL_LOGO 0x8 /* Sent an ELS LOGO command */
|
||||
#define NLP_EVT_CMPL_ADISC 0x9 /* Sent an ELS ADISC command */
|
||||
#define NLP_EVT_CMPL_REG_LOGIN 0xa /* REG_LOGIN mbox cmd completed */
|
||||
#define NLP_EVT_DEVICE_RM 0xb /* Device not found in NS / ALPAmap */
|
||||
#define NLP_EVT_DEVICE_RECOVERY 0xc /* Device existence unknown */
|
||||
#define NLP_EVT_MAX_EVENT 0xd
|
||||
|
3258
drivers/scsi/lpfc/lpfc_els.c
Normal file
3258
drivers/scsi/lpfc/lpfc_els.c
Normal file
File diff suppressed because it is too large
Load Diff
2537
drivers/scsi/lpfc/lpfc_hbadisc.c
Normal file
2537
drivers/scsi/lpfc/lpfc_hbadisc.c
Normal file
File diff suppressed because it is too large
Load Diff
2687
drivers/scsi/lpfc/lpfc_hw.h
Normal file
2687
drivers/scsi/lpfc/lpfc_hw.h
Normal file
File diff suppressed because it is too large
Load Diff
1739
drivers/scsi/lpfc/lpfc_init.c
Normal file
1739
drivers/scsi/lpfc/lpfc_init.c
Normal file
File diff suppressed because it is too large
Load Diff
41
drivers/scsi/lpfc/lpfc_logmsg.h
Normal file
41
drivers/scsi/lpfc/lpfc_logmsg.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_logmsg.h 1.32 2005/01/25 17:52:01EST sf_support Exp $
|
||||
*/
|
||||
|
||||
#define LOG_ELS 0x1 /* ELS events */
|
||||
#define LOG_DISCOVERY 0x2 /* Link discovery events */
|
||||
#define LOG_MBOX 0x4 /* Mailbox events */
|
||||
#define LOG_INIT 0x8 /* Initialization events */
|
||||
#define LOG_LINK_EVENT 0x10 /* Link events */
|
||||
#define LOG_IP 0x20 /* IP traffic history */
|
||||
#define LOG_FCP 0x40 /* FCP traffic history */
|
||||
#define LOG_NODE 0x80 /* Node table events */
|
||||
#define LOG_MISC 0x400 /* Miscellaneous events */
|
||||
#define LOG_SLI 0x800 /* SLI events */
|
||||
#define LOG_CHK_COND 0x1000 /* FCP Check condition flag */
|
||||
#define LOG_LIBDFC 0x2000 /* Libdfc events */
|
||||
#define LOG_ALL_MSG 0xffff /* LOG all messages */
|
||||
|
||||
#define lpfc_printf_log(phba, level, mask, fmt, arg...) \
|
||||
{ if (((mask) &(phba)->cfg_log_verbose) || (level[1] <= '3')) \
|
||||
dev_printk(level, &((phba)->pcidev)->dev, fmt, ##arg); }
|
646
drivers/scsi/lpfc/lpfc_mbox.c
Normal file
646
drivers/scsi/lpfc/lpfc_mbox.c
Normal file
|
@ -0,0 +1,646 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_mbox.c 1.85 2005/04/13 11:59:11EDT sf_support Exp $
|
||||
*/
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
#include "lpfc.h"
|
||||
#include "lpfc_logmsg.h"
|
||||
#include "lpfc_crtn.h"
|
||||
#include "lpfc_compat.h"
|
||||
|
||||
/**********************************************/
|
||||
|
||||
/* mailbox command */
|
||||
/**********************************************/
|
||||
void
|
||||
lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
void *ctx;
|
||||
|
||||
mb = &pmb->mb;
|
||||
ctx = pmb->context2;
|
||||
|
||||
/* Setup to dump VPD region */
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
mb->mbxCommand = MBX_DUMP_MEMORY;
|
||||
mb->un.varDmp.cv = 1;
|
||||
mb->un.varDmp.type = DMP_NV_PARAMS;
|
||||
mb->un.varDmp.entry_index = offset;
|
||||
mb->un.varDmp.region_id = DMP_REGION_VPD;
|
||||
mb->un.varDmp.word_cnt = (DMP_RSP_SIZE / sizeof (uint32_t));
|
||||
mb->un.varDmp.co = 0;
|
||||
mb->un.varDmp.resp_offset = 0;
|
||||
pmb->context2 = ctx;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* lpfc_read_nv Issue a READ NVPARAM */
|
||||
/* mailbox command */
|
||||
/**********************************************/
|
||||
void
|
||||
lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
mb->mbxCommand = MBX_READ_NV;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* lpfc_read_la Issue a READ LA */
|
||||
/* mailbox command */
|
||||
/**********************************************/
|
||||
int
|
||||
lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
struct lpfc_sli *psli;
|
||||
|
||||
psli = &phba->sli;
|
||||
mb = &pmb->mb;
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* lpfc_clear_la Issue a CLEAR LA */
|
||||
/* mailbox command */
|
||||
/**********************************************/
|
||||
void
|
||||
lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
mb->un.varClearLA.eventTag = phba->fc_eventTag;
|
||||
mb->mbxCommand = MBX_CLEAR_LA;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* lpfc_config_link Issue a CONFIG LINK */
|
||||
/* mailbox command */
|
||||
/**************************************************/
|
||||
void
|
||||
lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
MAILBOX_t *mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
/* NEW_FEATURE
|
||||
* SLI-2, Coalescing Response Feature.
|
||||
*/
|
||||
if (phba->cfg_cr_delay) {
|
||||
mb->un.varCfgLnk.cr = 1;
|
||||
mb->un.varCfgLnk.ci = 1;
|
||||
mb->un.varCfgLnk.cr_delay = phba->cfg_cr_delay;
|
||||
mb->un.varCfgLnk.cr_count = phba->cfg_cr_count;
|
||||
}
|
||||
|
||||
mb->un.varCfgLnk.myId = phba->fc_myDID;
|
||||
mb->un.varCfgLnk.edtov = phba->fc_edtov;
|
||||
mb->un.varCfgLnk.arbtov = phba->fc_arbtov;
|
||||
mb->un.varCfgLnk.ratov = phba->fc_ratov;
|
||||
mb->un.varCfgLnk.rttov = phba->fc_rttov;
|
||||
mb->un.varCfgLnk.altov = phba->fc_altov;
|
||||
mb->un.varCfgLnk.crtov = phba->fc_crtov;
|
||||
mb->un.varCfgLnk.citov = phba->fc_citov;
|
||||
|
||||
if (phba->cfg_ack0)
|
||||
mb->un.varCfgLnk.ack0_enable = 1;
|
||||
|
||||
mb->mbxCommand = MBX_CONFIG_LINK;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* lpfc_init_link Issue an INIT LINK */
|
||||
/* mailbox command */
|
||||
/**********************************************/
|
||||
void
|
||||
lpfc_init_link(struct lpfc_hba * phba,
|
||||
LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed)
|
||||
{
|
||||
lpfc_vpd_t *vpd;
|
||||
struct lpfc_sli *psli;
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
psli = &phba->sli;
|
||||
switch (topology) {
|
||||
case FLAGS_TOPOLOGY_MODE_LOOP_PT:
|
||||
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
|
||||
mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
|
||||
break;
|
||||
case FLAGS_TOPOLOGY_MODE_PT_PT:
|
||||
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
|
||||
break;
|
||||
case FLAGS_TOPOLOGY_MODE_LOOP:
|
||||
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
|
||||
break;
|
||||
case FLAGS_TOPOLOGY_MODE_PT_LOOP:
|
||||
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
|
||||
mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
|
||||
break;
|
||||
}
|
||||
|
||||
/* NEW_FEATURE
|
||||
* Setting up the link speed
|
||||
*/
|
||||
vpd = &phba->vpd;
|
||||
if (vpd->rev.feaLevelHigh >= 0x02){
|
||||
switch(linkspeed){
|
||||
case LINK_SPEED_1G:
|
||||
case LINK_SPEED_2G:
|
||||
case LINK_SPEED_4G:
|
||||
mb->un.varInitLnk.link_flags |=
|
||||
FLAGS_LINK_SPEED;
|
||||
mb->un.varInitLnk.link_speed = linkspeed;
|
||||
break;
|
||||
case LINK_SPEED_AUTO:
|
||||
default:
|
||||
mb->un.varInitLnk.link_speed =
|
||||
LINK_SPEED_AUTO;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
|
||||
|
||||
mb->mbxCommand = (volatile uint8_t)MBX_INIT_LINK;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
mb->un.varInitLnk.fabric_AL_PA = phba->fc_pref_ALPA;
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* lpfc_read_sparam Issue a READ SPARAM */
|
||||
/* mailbox command */
|
||||
/**********************************************/
|
||||
int
|
||||
lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
struct lpfc_dmabuf *mp;
|
||||
MAILBOX_t *mb;
|
||||
struct lpfc_sli *psli;
|
||||
|
||||
psli = &phba->sli;
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
|
||||
/* Get a buffer to hold the HBAs Service Parameters */
|
||||
|
||||
if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
|
||||
((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
|
||||
if (mp)
|
||||
kfree(mp);
|
||||
mb->mbxCommand = MBX_READ_SPARM64;
|
||||
/* READ_SPARAM: no buffers */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_WARNING,
|
||||
LOG_MBOX,
|
||||
"%d:0301 READ_SPARAM: no buffers\n",
|
||||
phba->brd_no);
|
||||
return (1);
|
||||
}
|
||||
INIT_LIST_HEAD(&mp->list);
|
||||
mb->mbxCommand = MBX_READ_SPARM64;
|
||||
mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
|
||||
mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
|
||||
mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
|
||||
|
||||
/* save address for completion */
|
||||
pmb->context1 = mp;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* lpfc_unreg_did Issue a UNREG_DID */
|
||||
/* mailbox command */
|
||||
/********************************************/
|
||||
void
|
||||
lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
mb->un.varUnregDID.did = did;
|
||||
|
||||
mb->mbxCommand = MBX_UNREG_D_ID;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
|
||||
/* command to write slim */
|
||||
/***********************************************/
|
||||
void
|
||||
lpfc_set_slim(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint32_t addr,
|
||||
uint32_t value)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
/* addr = 0x090597 is AUTO ABTS disable for ELS commands */
|
||||
/* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
|
||||
|
||||
/*
|
||||
* Always turn on DELAYED ABTS for ELS timeouts
|
||||
*/
|
||||
if ((addr == 0x052198) && (value == 0))
|
||||
value = 1;
|
||||
|
||||
mb->un.varWords[0] = addr;
|
||||
mb->un.varWords[1] = value;
|
||||
|
||||
mb->mbxCommand = MBX_SET_SLIM;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* lpfc_read_nv Issue a READ CONFIG */
|
||||
/* mailbox command */
|
||||
/**********************************************/
|
||||
void
|
||||
lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
mb->mbxCommand = MBX_READ_CONFIG;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* lpfc_reg_login Issue a REG_LOGIN */
|
||||
/* mailbox command */
|
||||
/********************************************/
|
||||
int
|
||||
lpfc_reg_login(struct lpfc_hba * phba,
|
||||
uint32_t did, uint8_t * param, LPFC_MBOXQ_t * pmb, uint32_t flag)
|
||||
{
|
||||
uint8_t *sparam;
|
||||
struct lpfc_dmabuf *mp;
|
||||
MAILBOX_t *mb;
|
||||
struct lpfc_sli *psli;
|
||||
|
||||
psli = &phba->sli;
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
mb->un.varRegLogin.rpi = 0;
|
||||
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 */
|
||||
if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == NULL) ||
|
||||
((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
|
||||
if (mp)
|
||||
kfree(mp);
|
||||
|
||||
mb->mbxCommand = MBX_REG_LOGIN64;
|
||||
/* REG_LOGIN: no buffers */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_WARNING,
|
||||
LOG_MBOX,
|
||||
"%d:0302 REG_LOGIN: no buffers Data x%x x%x\n",
|
||||
phba->brd_no,
|
||||
(uint32_t) did, (uint32_t) flag);
|
||||
return (1);
|
||||
}
|
||||
INIT_LIST_HEAD(&mp->list);
|
||||
sparam = mp->virt;
|
||||
|
||||
/* Copy param's into a new buffer */
|
||||
memcpy(sparam, param, sizeof (struct serv_parm));
|
||||
|
||||
/* save address for completion */
|
||||
pmb->context1 = (uint8_t *) mp;
|
||||
|
||||
mb->mbxCommand = MBX_REG_LOGIN64;
|
||||
mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
|
||||
mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys);
|
||||
mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* lpfc_unreg_login Issue a UNREG_LOGIN */
|
||||
/* mailbox command */
|
||||
/**********************************************/
|
||||
void
|
||||
lpfc_unreg_login(struct lpfc_hba * phba, uint32_t rpi, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
mb->un.varUnregLogin.rpi = (uint16_t) rpi;
|
||||
mb->un.varUnregLogin.rsvd1 = 0;
|
||||
|
||||
mb->mbxCommand = MBX_UNREG_LOGIN;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_config_pcb_setup(struct lpfc_hba * phba)
|
||||
{
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct lpfc_sli_ring *pring;
|
||||
PCB_t *pcbp = &phba->slim2p->pcb;
|
||||
dma_addr_t pdma_addr;
|
||||
uint32_t offset;
|
||||
uint32_t iocbCnt;
|
||||
int i;
|
||||
|
||||
psli->MBhostaddr = (uint32_t *)&phba->slim2p->mbx;
|
||||
pcbp->maxRing = (psli->num_rings - 1);
|
||||
|
||||
iocbCnt = 0;
|
||||
for (i = 0; i < psli->num_rings; i++) {
|
||||
pring = &psli->ring[i];
|
||||
/* A ring MUST have both cmd and rsp entries defined to be
|
||||
valid */
|
||||
if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
|
||||
pcbp->rdsc[i].cmdEntries = 0;
|
||||
pcbp->rdsc[i].rspEntries = 0;
|
||||
pcbp->rdsc[i].cmdAddrHigh = 0;
|
||||
pcbp->rdsc[i].rspAddrHigh = 0;
|
||||
pcbp->rdsc[i].cmdAddrLow = 0;
|
||||
pcbp->rdsc[i].rspAddrLow = 0;
|
||||
pring->cmdringaddr = NULL;
|
||||
pring->rspringaddr = NULL;
|
||||
continue;
|
||||
}
|
||||
/* Command ring setup for ring */
|
||||
pring->cmdringaddr =
|
||||
(void *)&phba->slim2p->IOCBs[iocbCnt];
|
||||
pcbp->rdsc[i].cmdEntries = pring->numCiocb;
|
||||
|
||||
offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
|
||||
(uint8_t *)phba->slim2p;
|
||||
pdma_addr = phba->slim2p_mapping + offset;
|
||||
pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr);
|
||||
pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr);
|
||||
iocbCnt += pring->numCiocb;
|
||||
|
||||
/* Response ring setup for ring */
|
||||
pring->rspringaddr =
|
||||
(void *)&phba->slim2p->IOCBs[iocbCnt];
|
||||
|
||||
pcbp->rdsc[i].rspEntries = pring->numRiocb;
|
||||
offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
|
||||
(uint8_t *)phba->slim2p;
|
||||
pdma_addr = phba->slim2p_mapping + offset;
|
||||
pcbp->rdsc[i].rspAddrHigh = putPaddrHigh(pdma_addr);
|
||||
pcbp->rdsc[i].rspAddrLow = putPaddrLow(pdma_addr);
|
||||
iocbCnt += pring->numRiocb;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
|
||||
mb = &pmb->mb;
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
mb->un.varRdRev.cv = 1;
|
||||
mb->mbxCommand = MBX_READ_REV;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
int i;
|
||||
MAILBOX_t *mb = &pmb->mb;
|
||||
struct lpfc_sli *psli;
|
||||
struct lpfc_sli_ring *pring;
|
||||
|
||||
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||
|
||||
mb->un.varCfgRing.ring = ring;
|
||||
mb->un.varCfgRing.maxOrigXchg = 0;
|
||||
mb->un.varCfgRing.maxRespXchg = 0;
|
||||
mb->un.varCfgRing.recvNotify = 1;
|
||||
|
||||
psli = &phba->sli;
|
||||
pring = &psli->ring[ring];
|
||||
mb->un.varCfgRing.numMask = pring->num_mask;
|
||||
mb->mbxCommand = MBX_CONFIG_RING;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
|
||||
/* Is this ring configured for a specific profile */
|
||||
if (pring->prt[0].profile) {
|
||||
mb->un.varCfgRing.profile = pring->prt[0].profile;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise we setup specific rctl / type masks for this ring */
|
||||
for (i = 0; i < pring->num_mask; i++) {
|
||||
mb->un.varCfgRing.rrRegs[i].rval = pring->prt[i].rctl;
|
||||
if (mb->un.varCfgRing.rrRegs[i].rval != FC_ELS_REQ)
|
||||
mb->un.varCfgRing.rrRegs[i].rmask = 0xff;
|
||||
else
|
||||
mb->un.varCfgRing.rrRegs[i].rmask = 0xfe;
|
||||
mb->un.varCfgRing.rrRegs[i].tval = pring->prt[i].type;
|
||||
mb->un.varCfgRing.rrRegs[i].tmask = 0xff;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
MAILBOX_t *mb = &pmb->mb;
|
||||
dma_addr_t pdma_addr;
|
||||
uint32_t bar_low, bar_high;
|
||||
size_t offset;
|
||||
HGP hgp;
|
||||
void __iomem *to_slim;
|
||||
|
||||
memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
|
||||
mb->mbxCommand = MBX_CONFIG_PORT;
|
||||
mb->mbxOwner = OWN_HOST;
|
||||
|
||||
mb->un.varCfgPort.pcbLen = sizeof(PCB_t);
|
||||
|
||||
offset = (uint8_t *)&phba->slim2p->pcb - (uint8_t *)phba->slim2p;
|
||||
pdma_addr = phba->slim2p_mapping + offset;
|
||||
mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
|
||||
mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
|
||||
|
||||
/* Now setup pcb */
|
||||
phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
|
||||
phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
|
||||
|
||||
/* Setup Mailbox pointers */
|
||||
phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t);
|
||||
offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
|
||||
pdma_addr = phba->slim2p_mapping + offset;
|
||||
phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
|
||||
phba->slim2p->pcb.mbAddrLow = putPaddrLow(pdma_addr);
|
||||
|
||||
/*
|
||||
* Setup Host Group ring pointer.
|
||||
*
|
||||
* For efficiency reasons, the ring get/put pointers can be
|
||||
* placed in adapter memory (SLIM) rather than in host memory.
|
||||
* This allows firmware to avoid PCI reads/writes when updating
|
||||
* and checking pointers.
|
||||
*
|
||||
* The firmware recognizes the use of SLIM memory by comparing
|
||||
* the address of the get/put pointers structure with that of
|
||||
* the SLIM BAR (BAR0).
|
||||
*
|
||||
* Caution: be sure to use the PCI config space value of BAR0/BAR1
|
||||
* (the hardware's view of the base address), not the OS's
|
||||
* value of pci_resource_start() as the OS value may be a cookie
|
||||
* for ioremap/iomap.
|
||||
*/
|
||||
|
||||
|
||||
pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
|
||||
pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
|
||||
|
||||
|
||||
/* mask off BAR0's flag bits 0 - 3 */
|
||||
phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
|
||||
(SLIMOFF*sizeof(uint32_t));
|
||||
if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
|
||||
phba->slim2p->pcb.hgpAddrHigh = bar_high;
|
||||
else
|
||||
phba->slim2p->pcb.hgpAddrHigh = 0;
|
||||
/* write HGP data to SLIM at the required longword offset */
|
||||
memset(&hgp, 0, sizeof(HGP));
|
||||
to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
|
||||
lpfc_memcpy_to_slim(to_slim, &hgp, sizeof (HGP));
|
||||
|
||||
/* Setup Port Group ring pointer */
|
||||
offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
|
||||
(uint8_t *)phba->slim2p;
|
||||
pdma_addr = phba->slim2p_mapping + offset;
|
||||
phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
|
||||
phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
|
||||
|
||||
/* Use callback routine to setp rings in the pcb */
|
||||
lpfc_config_pcb_setup(phba);
|
||||
|
||||
/* special handling for LC HBAs */
|
||||
if (lpfc_is_LC_HBA(phba->pcidev->device)) {
|
||||
uint32_t hbainit[5];
|
||||
|
||||
lpfc_hba_init(phba, hbainit);
|
||||
|
||||
memcpy(&mb->un.varCfgPort.hbainit, hbainit, 20);
|
||||
}
|
||||
|
||||
/* Swap PCB if needed */
|
||||
lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
|
||||
sizeof (PCB_t));
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
||||
"%d:0405 Service Level Interface (SLI) 2 selected\n",
|
||||
phba->brd_no);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
|
||||
{
|
||||
struct lpfc_sli *psli;
|
||||
|
||||
psli = &phba->sli;
|
||||
|
||||
list_add_tail(&mbq->list, &psli->mboxq);
|
||||
|
||||
psli->mboxq_cnt++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LPFC_MBOXQ_t *
|
||||
lpfc_mbox_get(struct lpfc_hba * phba)
|
||||
{
|
||||
LPFC_MBOXQ_t *mbq = NULL;
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
|
||||
list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t,
|
||||
list);
|
||||
if (mbq) {
|
||||
psli->mboxq_cnt--;
|
||||
}
|
||||
|
||||
return mbq;
|
||||
}
|
179
drivers/scsi/lpfc/lpfc_mem.c
Normal file
179
drivers/scsi/lpfc/lpfc_mem.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_mem.c 1.79 2005/04/13 14:25:50EDT sf_support Exp $
|
||||
*/
|
||||
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
#include "lpfc.h"
|
||||
#include "lpfc_crtn.h"
|
||||
|
||||
#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */
|
||||
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
|
||||
|
||||
static void *
|
||||
lpfc_pool_kmalloc(unsigned int gfp_flags, void *data)
|
||||
{
|
||||
return kmalloc((unsigned long)data, gfp_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_pool_kfree(void *obj, void *data)
|
||||
{
|
||||
kfree(obj);
|
||||
}
|
||||
|
||||
int
|
||||
lpfc_mem_alloc(struct lpfc_hba * phba)
|
||||
{
|
||||
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
|
||||
int i;
|
||||
|
||||
phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool",
|
||||
phba->pcidev, phba->cfg_sg_dma_buf_size, 8, 0);
|
||||
if (!phba->lpfc_scsi_dma_buf_pool)
|
||||
goto fail;
|
||||
|
||||
phba->lpfc_mbuf_pool = pci_pool_create("lpfc_mbuf_pool", phba->pcidev,
|
||||
LPFC_BPL_SIZE, 8,0);
|
||||
if (!phba->lpfc_mbuf_pool)
|
||||
goto fail_free_dma_buf_pool;
|
||||
|
||||
pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) *
|
||||
LPFC_MBUF_POOL_SIZE, GFP_KERNEL);
|
||||
pool->max_count = 0;
|
||||
pool->current_count = 0;
|
||||
for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) {
|
||||
pool->elements[i].virt = pci_pool_alloc(phba->lpfc_mbuf_pool,
|
||||
GFP_KERNEL, &pool->elements[i].phys);
|
||||
if (!pool->elements[i].virt)
|
||||
goto fail_free_mbuf_pool;
|
||||
pool->max_count++;
|
||||
pool->current_count++;
|
||||
}
|
||||
|
||||
phba->mbox_mem_pool = mempool_create(LPFC_MEM_POOL_SIZE,
|
||||
lpfc_pool_kmalloc, lpfc_pool_kfree,
|
||||
(void *)(unsigned long)sizeof(LPFC_MBOXQ_t));
|
||||
if (!phba->mbox_mem_pool)
|
||||
goto fail_free_mbuf_pool;
|
||||
|
||||
phba->nlp_mem_pool = mempool_create(LPFC_MEM_POOL_SIZE,
|
||||
lpfc_pool_kmalloc, lpfc_pool_kfree,
|
||||
(void *)(unsigned long)sizeof(struct lpfc_nodelist));
|
||||
if (!phba->nlp_mem_pool)
|
||||
goto fail_free_mbox_pool;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_mbox_pool:
|
||||
mempool_destroy(phba->mbox_mem_pool);
|
||||
fail_free_mbuf_pool:
|
||||
while (--i)
|
||||
pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
|
||||
pool->elements[i].phys);
|
||||
kfree(pool->elements);
|
||||
pci_pool_destroy(phba->lpfc_mbuf_pool);
|
||||
fail_free_dma_buf_pool:
|
||||
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
|
||||
fail:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_mem_free(struct lpfc_hba * phba)
|
||||
{
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
|
||||
LPFC_MBOXQ_t *mbox, *next_mbox;
|
||||
struct lpfc_dmabuf *mp;
|
||||
int i;
|
||||
|
||||
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
|
||||
mp = (struct lpfc_dmabuf *) (mbox->context1);
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
list_del(&mbox->list);
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
}
|
||||
|
||||
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
||||
if (psli->mbox_active) {
|
||||
mbox = psli->mbox_active;
|
||||
mp = (struct lpfc_dmabuf *) (mbox->context1);
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
psli->mbox_active = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->current_count; i++)
|
||||
pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
|
||||
pool->elements[i].phys);
|
||||
kfree(pool->elements);
|
||||
mempool_destroy(phba->nlp_mem_pool);
|
||||
mempool_destroy(phba->mbox_mem_pool);
|
||||
|
||||
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
|
||||
pci_pool_destroy(phba->lpfc_mbuf_pool);
|
||||
}
|
||||
|
||||
void *
|
||||
lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
|
||||
{
|
||||
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
|
||||
void *ret;
|
||||
|
||||
ret = pci_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle);
|
||||
|
||||
if (!ret && ( mem_flags & MEM_PRI) && pool->current_count) {
|
||||
pool->current_count--;
|
||||
ret = pool->elements[pool->current_count].virt;
|
||||
*handle = pool->elements[pool->current_count].phys;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
|
||||
{
|
||||
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
|
||||
|
||||
if (pool->current_count < pool->max_count) {
|
||||
pool->elements[pool->current_count].virt = virt;
|
||||
pool->elements[pool->current_count].phys = dma;
|
||||
pool->current_count++;
|
||||
} else {
|
||||
pci_pool_free(phba->lpfc_mbuf_pool, virt, dma);
|
||||
}
|
||||
return;
|
||||
}
|
1842
drivers/scsi/lpfc/lpfc_nportdisc.c
Normal file
1842
drivers/scsi/lpfc/lpfc_nportdisc.c
Normal file
File diff suppressed because it is too large
Load Diff
1246
drivers/scsi/lpfc/lpfc_scsi.c
Normal file
1246
drivers/scsi/lpfc/lpfc_scsi.c
Normal file
File diff suppressed because it is too large
Load Diff
157
drivers/scsi/lpfc/lpfc_scsi.h
Normal file
157
drivers/scsi/lpfc/lpfc_scsi.h
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_scsi.h 1.83 2005/04/07 08:47:43EDT sf_support Exp $
|
||||
*/
|
||||
|
||||
struct lpfc_hba;
|
||||
|
||||
#define list_remove_head(list, entry, type, member) \
|
||||
if (!list_empty(list)) { \
|
||||
entry = list_entry((list)->next, type, member); \
|
||||
list_del_init(&entry->member); \
|
||||
}
|
||||
|
||||
#define list_get_first(list, type, member) \
|
||||
(list_empty(list)) ? NULL : \
|
||||
list_entry((list)->next, type, member)
|
||||
|
||||
/* per-port data that is allocated in the FC transport for us */
|
||||
struct lpfc_rport_data {
|
||||
struct lpfc_nodelist *pnode; /* Pointer to the node structure. */
|
||||
};
|
||||
|
||||
struct fcp_rsp {
|
||||
uint32_t rspRsvd1; /* FC Word 0, byte 0:3 */
|
||||
uint32_t rspRsvd2; /* FC Word 1, byte 0:3 */
|
||||
|
||||
uint8_t rspStatus0; /* FCP_STATUS byte 0 (reserved) */
|
||||
uint8_t rspStatus1; /* FCP_STATUS byte 1 (reserved) */
|
||||
uint8_t rspStatus2; /* FCP_STATUS byte 2 field validity */
|
||||
#define RSP_LEN_VALID 0x01 /* bit 0 */
|
||||
#define SNS_LEN_VALID 0x02 /* bit 1 */
|
||||
#define RESID_OVER 0x04 /* bit 2 */
|
||||
#define RESID_UNDER 0x08 /* bit 3 */
|
||||
uint8_t rspStatus3; /* FCP_STATUS byte 3 SCSI status byte */
|
||||
|
||||
uint32_t rspResId; /* Residual xfer if residual count field set in
|
||||
fcpStatus2 */
|
||||
/* Received in Big Endian format */
|
||||
uint32_t rspSnsLen; /* Length of sense data in fcpSnsInfo */
|
||||
/* Received in Big Endian format */
|
||||
uint32_t rspRspLen; /* Length of FCP response data in fcpRspInfo */
|
||||
/* Received in Big Endian format */
|
||||
|
||||
uint8_t rspInfo0; /* FCP_RSP_INFO byte 0 (reserved) */
|
||||
uint8_t rspInfo1; /* FCP_RSP_INFO byte 1 (reserved) */
|
||||
uint8_t rspInfo2; /* FCP_RSP_INFO byte 2 (reserved) */
|
||||
uint8_t rspInfo3; /* FCP_RSP_INFO RSP_CODE byte 3 */
|
||||
|
||||
#define RSP_NO_FAILURE 0x00
|
||||
#define RSP_DATA_BURST_ERR 0x01
|
||||
#define RSP_CMD_FIELD_ERR 0x02
|
||||
#define RSP_RO_MISMATCH_ERR 0x03
|
||||
#define RSP_TM_NOT_SUPPORTED 0x04 /* Task mgmt function not supported */
|
||||
#define RSP_TM_NOT_COMPLETED 0x05 /* Task mgmt function not performed */
|
||||
|
||||
uint32_t rspInfoRsvd; /* FCP_RSP_INFO bytes 4-7 (reserved) */
|
||||
|
||||
uint8_t rspSnsInfo[128];
|
||||
#define SNS_ILLEGAL_REQ 0x05 /* sense key is byte 3 ([2]) */
|
||||
#define SNSCOD_BADCMD 0x20 /* sense code is byte 13 ([12]) */
|
||||
};
|
||||
|
||||
struct fcp_cmnd {
|
||||
uint32_t fcpLunMsl; /* most significant lun word (32 bits) */
|
||||
uint32_t fcpLunLsl; /* least significant lun word (32 bits) */
|
||||
/* # of bits to shift lun id to end up in right
|
||||
* payload word, little endian = 8, big = 16.
|
||||
*/
|
||||
#if __BIG_ENDIAN
|
||||
#define FC_LUN_SHIFT 16
|
||||
#define FC_ADDR_MODE_SHIFT 24
|
||||
#else /* __LITTLE_ENDIAN */
|
||||
#define FC_LUN_SHIFT 8
|
||||
#define FC_ADDR_MODE_SHIFT 0
|
||||
#endif
|
||||
|
||||
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
|
||||
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
|
||||
#define SIMPLE_Q 0x00
|
||||
#define HEAD_OF_Q 0x01
|
||||
#define ORDERED_Q 0x02
|
||||
#define ACA_Q 0x04
|
||||
#define UNTAGGED 0x05
|
||||
uint8_t fcpCntl2; /* FCP_CTL byte 2 task management codes */
|
||||
#define FCP_ABORT_TASK_SET 0x02 /* Bit 1 */
|
||||
#define FCP_CLEAR_TASK_SET 0x04 /* bit 2 */
|
||||
#define FCP_BUS_RESET 0x08 /* bit 3 */
|
||||
#define FCP_LUN_RESET 0x10 /* bit 4 */
|
||||
#define FCP_TARGET_RESET 0x20 /* bit 5 */
|
||||
#define FCP_CLEAR_ACA 0x40 /* bit 6 */
|
||||
#define FCP_TERMINATE_TASK 0x80 /* bit 7 */
|
||||
uint8_t fcpCntl3;
|
||||
#define WRITE_DATA 0x01 /* Bit 0 */
|
||||
#define READ_DATA 0x02 /* Bit 1 */
|
||||
|
||||
uint8_t fcpCdb[16]; /* SRB cdb field is copied here */
|
||||
uint32_t fcpDl; /* Total transfer length */
|
||||
|
||||
};
|
||||
|
||||
struct lpfc_scsi_buf {
|
||||
struct list_head list;
|
||||
struct scsi_cmnd *pCmd;
|
||||
struct lpfc_hba *scsi_hba;
|
||||
struct lpfc_rport_data *rdata;
|
||||
|
||||
uint32_t timeout;
|
||||
|
||||
uint16_t status; /* From IOCB Word 7- ulpStatus */
|
||||
uint32_t result; /* From IOCB Word 4. */
|
||||
|
||||
uint32_t seg_cnt; /* Number of scatter-gather segments returned by
|
||||
* dma_map_sg. The driver needs this for calls
|
||||
* to dma_unmap_sg. */
|
||||
dma_addr_t nonsg_phys; /* Non scatter-gather physical address. */
|
||||
|
||||
/*
|
||||
* data and dma_handle are the kernel virutal and bus address of the
|
||||
* dma-able buffer containing the fcp_cmd, fcp_rsp and a scatter
|
||||
* gather bde list that supports the sg_tablesize value.
|
||||
*/
|
||||
void *data;
|
||||
dma_addr_t dma_handle;
|
||||
|
||||
struct fcp_cmnd *fcp_cmnd;
|
||||
struct fcp_rsp *fcp_rsp;
|
||||
struct ulp_bde64 *fcp_bpl;
|
||||
|
||||
/* cur_iocbq has phys of the dma-able buffer.
|
||||
* Iotag is in here
|
||||
*/
|
||||
struct lpfc_iocbq cur_iocbq;
|
||||
};
|
||||
|
||||
#define LPFC_SCSI_DMA_EXT_SIZE 264
|
||||
#define LPFC_BPL_SIZE 1024
|
||||
|
||||
#define MDAC_DIRECT_CMD 0x22
|
2885
drivers/scsi/lpfc/lpfc_sli.c
Normal file
2885
drivers/scsi/lpfc/lpfc_sli.c
Normal file
File diff suppressed because it is too large
Load Diff
216
drivers/scsi/lpfc/lpfc_sli.h
Normal file
216
drivers/scsi/lpfc/lpfc_sli.h
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_sli.h 1.42 2005/03/21 02:01:28EST sf_support Exp $
|
||||
*/
|
||||
|
||||
/* forward declaration for LPFC_IOCB_t's use */
|
||||
struct lpfc_hba;
|
||||
|
||||
/* Define the context types that SLI handles for abort and sums. */
|
||||
typedef enum _lpfc_ctx_cmd {
|
||||
LPFC_CTX_LUN,
|
||||
LPFC_CTX_TGT,
|
||||
LPFC_CTX_CTX,
|
||||
LPFC_CTX_HOST
|
||||
} lpfc_ctx_cmd;
|
||||
|
||||
/* This structure is used to handle IOCB requests / responses */
|
||||
struct lpfc_iocbq {
|
||||
/* lpfc_iocbqs are used in double linked lists */
|
||||
struct list_head list;
|
||||
IOCB_t iocb; /* IOCB cmd */
|
||||
uint8_t retry; /* retry counter for IOCB cmd - if needed */
|
||||
uint8_t iocb_flag;
|
||||
#define LPFC_IO_POLL 1 /* Polling mode iocb */
|
||||
#define LPFC_IO_LIBDFC 2 /* libdfc iocb */
|
||||
#define LPFC_IO_WAIT 4
|
||||
#define LPFC_IO_HIPRI 8 /* High Priority Queue signal flag */
|
||||
|
||||
uint8_t abort_count;
|
||||
uint8_t rsvd2;
|
||||
uint32_t drvrTimeout; /* driver timeout in seconds */
|
||||
void *context1; /* caller context information */
|
||||
void *context2; /* caller context information */
|
||||
void *context3; /* caller context information */
|
||||
union {
|
||||
wait_queue_head_t *hipri_wait_queue; /* High Priority Queue wait
|
||||
queue */
|
||||
struct lpfc_iocbq *rsp_iocb;
|
||||
struct lpfcMboxq *mbox;
|
||||
} context_un;
|
||||
|
||||
void (*iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
|
||||
struct lpfc_iocbq *);
|
||||
|
||||
};
|
||||
|
||||
#define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */
|
||||
#define SLI_IOCB_HIGH_PRIORITY 2 /* High priority command */
|
||||
|
||||
#define IOCB_SUCCESS 0
|
||||
#define IOCB_BUSY 1
|
||||
#define IOCB_ERROR 2
|
||||
#define IOCB_TIMEDOUT 3
|
||||
|
||||
typedef struct lpfcMboxq {
|
||||
/* MBOXQs are used in single linked lists */
|
||||
struct list_head list; /* ptr to next mailbox command */
|
||||
MAILBOX_t mb; /* Mailbox cmd */
|
||||
void *context1; /* caller context information */
|
||||
void *context2; /* caller context information */
|
||||
|
||||
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
|
||||
|
||||
} LPFC_MBOXQ_t;
|
||||
|
||||
#define MBX_POLL 1 /* poll mailbox till command done, then
|
||||
return */
|
||||
#define MBX_NOWAIT 2 /* issue command then return immediately */
|
||||
#define MBX_STOP_IOCB 4 /* Stop iocb processing till mbox cmds
|
||||
complete */
|
||||
|
||||
#define LPFC_MAX_RING_MASK 4 /* max num of rctl/type masks allowed per
|
||||
ring */
|
||||
#define LPFC_MAX_RING 4 /* max num of SLI rings used by driver */
|
||||
|
||||
struct lpfc_sli_ring;
|
||||
|
||||
struct lpfc_sli_ring_mask {
|
||||
uint8_t profile; /* profile associated with ring */
|
||||
uint8_t rctl; /* rctl / type pair configured for ring */
|
||||
uint8_t type; /* rctl / type pair configured for ring */
|
||||
uint8_t rsvd;
|
||||
/* rcv'd unsol event */
|
||||
void (*lpfc_sli_rcv_unsol_event) (struct lpfc_hba *,
|
||||
struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *);
|
||||
};
|
||||
|
||||
|
||||
/* Structure used to hold SLI statistical counters and info */
|
||||
struct lpfc_sli_ring_stat {
|
||||
uint64_t iocb_event; /* IOCB event counters */
|
||||
uint64_t iocb_cmd; /* IOCB cmd issued */
|
||||
uint64_t iocb_rsp; /* IOCB rsp received */
|
||||
uint64_t iocb_cmd_delay; /* IOCB cmd ring delay */
|
||||
uint64_t iocb_cmd_full; /* IOCB cmd ring full */
|
||||
uint64_t iocb_cmd_empty; /* IOCB cmd ring is now empty */
|
||||
uint64_t iocb_rsp_full; /* IOCB rsp ring full */
|
||||
};
|
||||
|
||||
/* Structure used to hold SLI ring information */
|
||||
struct lpfc_sli_ring {
|
||||
uint16_t flag; /* ring flags */
|
||||
#define LPFC_DEFERRED_RING_EVENT 0x001 /* Deferred processing a ring event */
|
||||
#define LPFC_CALL_RING_AVAILABLE 0x002 /* indicates cmd was full */
|
||||
#define LPFC_STOP_IOCB_MBX 0x010 /* Stop processing IOCB cmds mbox */
|
||||
#define LPFC_STOP_IOCB_EVENT 0x020 /* Stop processing IOCB cmds event */
|
||||
#define LPFC_STOP_IOCB_MASK 0x030 /* Stop processing IOCB cmds mask */
|
||||
uint16_t abtsiotag; /* tracks next iotag to use for ABTS */
|
||||
|
||||
uint32_t local_getidx; /* last available cmd index (from cmdGetInx) */
|
||||
uint32_t next_cmdidx; /* next_cmd index */
|
||||
uint8_t rsvd;
|
||||
uint8_t ringno; /* ring number */
|
||||
uint8_t rspidx; /* current index in response ring */
|
||||
uint8_t cmdidx; /* current index in command ring */
|
||||
uint16_t numCiocb; /* number of command iocb's per ring */
|
||||
uint16_t numRiocb; /* number of rsp iocb's per ring */
|
||||
|
||||
uint32_t fast_iotag; /* max fastlookup based iotag */
|
||||
uint32_t iotag_ctr; /* keeps track of the next iotag to use */
|
||||
uint32_t iotag_max; /* max iotag value to use */
|
||||
struct lpfc_iocbq ** fast_lookup; /* array of IOCB ptrs indexed by
|
||||
iotag */
|
||||
struct list_head txq;
|
||||
uint16_t txq_cnt; /* current length of queue */
|
||||
uint16_t txq_max; /* max length */
|
||||
struct list_head txcmplq;
|
||||
uint16_t txcmplq_cnt; /* current length of queue */
|
||||
uint16_t txcmplq_max; /* max length */
|
||||
uint32_t *cmdringaddr; /* virtual address for cmd rings */
|
||||
uint32_t *rspringaddr; /* virtual address for rsp rings */
|
||||
uint32_t missbufcnt; /* keep track of buffers to post */
|
||||
struct list_head postbufq;
|
||||
uint16_t postbufq_cnt; /* current length of queue */
|
||||
uint16_t postbufq_max; /* max length */
|
||||
struct list_head iocb_continueq;
|
||||
uint16_t iocb_continueq_cnt; /* current length of queue */
|
||||
uint16_t iocb_continueq_max; /* max length */
|
||||
|
||||
struct lpfc_sli_ring_mask prt[LPFC_MAX_RING_MASK];
|
||||
uint32_t num_mask; /* number of mask entries in prt array */
|
||||
|
||||
struct lpfc_sli_ring_stat stats; /* SLI statistical info */
|
||||
|
||||
/* cmd ring available */
|
||||
void (*lpfc_sli_cmd_available) (struct lpfc_hba *,
|
||||
struct lpfc_sli_ring *);
|
||||
};
|
||||
|
||||
/* Structure used to hold SLI statistical counters and info */
|
||||
struct lpfc_sli_stat {
|
||||
uint64_t mbox_stat_err; /* Mbox cmds completed status error */
|
||||
uint64_t mbox_cmd; /* Mailbox commands issued */
|
||||
uint64_t sli_intr; /* Count of Host Attention interrupts */
|
||||
uint32_t err_attn_event; /* Error Attn event counters */
|
||||
uint32_t link_event; /* Link event counters */
|
||||
uint32_t mbox_event; /* Mailbox event counters */
|
||||
uint32_t mbox_busy; /* Mailbox cmd busy */
|
||||
};
|
||||
|
||||
/* Structure used to hold SLI information */
|
||||
struct lpfc_sli {
|
||||
uint32_t num_rings;
|
||||
uint32_t sli_flag;
|
||||
|
||||
/* Additional sli_flags */
|
||||
#define LPFC_SLI_MBOX_ACTIVE 0x100 /* HBA mailbox is currently active */
|
||||
#define LPFC_SLI2_ACTIVE 0x200 /* SLI2 overlay in firmware is active */
|
||||
#define LPFC_PROCESS_LA 0x400 /* Able to process link attention */
|
||||
|
||||
struct lpfc_sli_ring ring[LPFC_MAX_RING];
|
||||
int fcp_ring; /* ring used for FCP initiator commands */
|
||||
int next_ring;
|
||||
|
||||
int ip_ring; /* ring used for IP network drv cmds */
|
||||
|
||||
struct lpfc_sli_stat slistat; /* SLI statistical info */
|
||||
struct list_head mboxq;
|
||||
uint16_t mboxq_cnt; /* current length of queue */
|
||||
uint16_t mboxq_max; /* max length */
|
||||
LPFC_MBOXQ_t *mbox_active; /* active mboxq information */
|
||||
|
||||
struct timer_list mbox_tmo; /* Hold clk to timeout active mbox
|
||||
cmd */
|
||||
|
||||
uint32_t *MBhostaddr; /* virtual address for mbox cmds */
|
||||
};
|
||||
|
||||
/* Given a pointer to the start of the ring, and the slot number of
|
||||
* the desired iocb entry, calc a pointer to that entry.
|
||||
* (assume iocb entry size is 32 bytes, or 8 words)
|
||||
*/
|
||||
#define IOCB_ENTRY(ring,slot) ((IOCB_t *)(((char *)(ring)) + ((slot) * 32)))
|
||||
|
||||
#define LPFC_MBOX_TMO 30 /* Sec tmo for outstanding mbox
|
||||
command */
|
32
drivers/scsi/lpfc/lpfc_version.h
Normal file
32
drivers/scsi/lpfc/lpfc_version.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Enterprise Fibre Channel Host Bus Adapters. *
|
||||
* Refer to the README file included with this package for *
|
||||
* driver version and adapter support. *
|
||||
* Copyright (C) 2004 Emulex Corporation. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
* 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, a copy of which *
|
||||
* can be found in the file COPYING included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
/*
|
||||
* $Id: lpfc_version.h 1.49 2005/04/13 15:07:19EDT sf_support Exp $
|
||||
*/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "8.0.28"
|
||||
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
|
||||
LPFC_DRIVER_VERSION
|
||||
|
||||
#define DFC_API_VERSION "0.0.0"
|
Loading…
Reference in New Issue
Block a user