Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (55 commits) [SCSI] tcm_loop: Add multi-fabric Linux/SCSI LLD fabric module [SCSI] qla4xxx: Use polling mode for disable interrupt mailbox completion [SCSI] Revert "[SCSI] Retrieve the Caching mode page" [SCSI] bnx2fc: IO completion not processed due to missed wakeup [SCSI] qla4xxx: Update driver version to 5.02.00-k6 [SCSI] qla4xxx: masking required bits of add_fw_options during initialization [SCSI] qla4xxx: added new function qla4xxx_relogin_all_devices [SCSI] qla4xxx: add support for ql4xsess_recovery_tmo cmd line param [SCSI] qla4xxx: Add support for ql4xmaxqdepth command line parameter [SCSI] qla4xxx: cleanup function qla4xxx_process_ddb_changed [SCSI] qla4xxx: Prevent other port reinitialization during remove_adapter [SCSI] qla4xxx: remove unused ddb flag DF_NO_RELOGIN [SCSI] qla4xxx: cleanup DDB relogin logic during initialization [SCSI] qla4xxx: Do not retry ISP82XX initialization if H/W state is failed [SCSI] qla4xxx: Do not send mbox command if FW is in failed state [SCSI] qla4xxx: cleanup qla4xxx_initialize_ddb_list() [SCSI] ses: add subenclosure support [SCSI] bnx2fc: Bump version to 1.0.1 [SCSI] bnx2fc: Remove unnecessary module state checks [SCSI] bnx2fc: Fix MTU issue by using static MTU ...
This commit is contained in:
commit
9f34217c84
@ -239,8 +239,8 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||||||
buf += "#include <target/target_core_configfs.h>\n"
|
buf += "#include <target/target_core_configfs.h>\n"
|
||||||
buf += "#include <target/target_core_base.h>\n"
|
buf += "#include <target/target_core_base.h>\n"
|
||||||
buf += "#include <target/configfs_macros.h>\n\n"
|
buf += "#include <target/configfs_macros.h>\n\n"
|
||||||
buf += "#include <" + fabric_mod_name + "_base.h>\n"
|
buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
|
||||||
buf += "#include <" + fabric_mod_name + "_fabric.h>\n\n"
|
buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
|
||||||
|
|
||||||
buf += "/* Local pointer to allocated TCM configfs fabric module */\n"
|
buf += "/* Local pointer to allocated TCM configfs fabric module */\n"
|
||||||
buf += "struct target_fabric_configfs *" + fabric_mod_name + "_fabric_configfs;\n\n"
|
buf += "struct target_fabric_configfs *" + fabric_mod_name + "_fabric_configfs;\n\n"
|
||||||
@ -289,6 +289,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||||||
buf += "{\n"
|
buf += "{\n"
|
||||||
buf += " struct " + fabric_mod_name + "_nacl *nacl = container_of(se_acl,\n"
|
buf += " struct " + fabric_mod_name + "_nacl *nacl = container_of(se_acl,\n"
|
||||||
buf += " struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
|
buf += " struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
|
||||||
|
buf += " core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);\n"
|
||||||
buf += " kfree(nacl);\n"
|
buf += " kfree(nacl);\n"
|
||||||
buf += "}\n\n"
|
buf += "}\n\n"
|
||||||
|
|
||||||
@ -583,9 +584,9 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||||||
buf += "#include <target/target_core_fabric_lib.h>\n"
|
buf += "#include <target/target_core_fabric_lib.h>\n"
|
||||||
buf += "#include <target/target_core_device.h>\n"
|
buf += "#include <target/target_core_device.h>\n"
|
||||||
buf += "#include <target/target_core_tpg.h>\n"
|
buf += "#include <target/target_core_tpg.h>\n"
|
||||||
buf += "#include <target/target_core_configfs.h>\n"
|
buf += "#include <target/target_core_configfs.h>\n\n"
|
||||||
buf += "#include <" + fabric_mod_name + "_base.h>\n"
|
buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
|
||||||
buf += "#include <" + fabric_mod_name + "_fabric.h>\n\n"
|
buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
|
||||||
|
|
||||||
buf += "int " + fabric_mod_name + "_check_true(struct se_portal_group *se_tpg)\n"
|
buf += "int " + fabric_mod_name + "_check_true(struct se_portal_group *se_tpg)\n"
|
||||||
buf += "{\n"
|
buf += "{\n"
|
||||||
@ -973,14 +974,13 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||||||
def tcm_mod_build_kbuild(fabric_mod_dir_var, fabric_mod_name):
|
def tcm_mod_build_kbuild(fabric_mod_dir_var, fabric_mod_name):
|
||||||
|
|
||||||
buf = ""
|
buf = ""
|
||||||
f = fabric_mod_dir_var + "/Kbuild"
|
f = fabric_mod_dir_var + "/Makefile"
|
||||||
print "Writing file: " + f
|
print "Writing file: " + f
|
||||||
|
|
||||||
p = open(f, 'w')
|
p = open(f, 'w')
|
||||||
if not p:
|
if not p:
|
||||||
tcm_mod_err("Unable to open file: " + f)
|
tcm_mod_err("Unable to open file: " + f)
|
||||||
|
|
||||||
buf = "EXTRA_CFLAGS += -I$(srctree)/drivers/target/ -I$(srctree)/include/ -I$(srctree)/drivers/scsi/ -I$(srctree)/include/scsi/ -I$(srctree)/drivers/target/" + fabric_mod_name + "\n\n"
|
|
||||||
buf += fabric_mod_name + "-objs := " + fabric_mod_name + "_fabric.o \\\n"
|
buf += fabric_mod_name + "-objs := " + fabric_mod_name + "_fabric.o \\\n"
|
||||||
buf += " " + fabric_mod_name + "_configfs.o\n"
|
buf += " " + fabric_mod_name + "_configfs.o\n"
|
||||||
buf += "obj-$(CONFIG_" + fabric_mod_name.upper() + ") += " + fabric_mod_name + ".o\n"
|
buf += "obj-$(CONFIG_" + fabric_mod_name.upper() + ") += " + fabric_mod_name + ".o\n"
|
||||||
@ -1018,7 +1018,7 @@ def tcm_mod_build_kconfig(fabric_mod_dir_var, fabric_mod_name):
|
|||||||
|
|
||||||
def tcm_mod_add_kbuild(tcm_dir, fabric_mod_name):
|
def tcm_mod_add_kbuild(tcm_dir, fabric_mod_name):
|
||||||
buf = "obj-$(CONFIG_" + fabric_mod_name.upper() + ") += " + fabric_mod_name.lower() + "/\n"
|
buf = "obj-$(CONFIG_" + fabric_mod_name.upper() + ") += " + fabric_mod_name.lower() + "/\n"
|
||||||
kbuild = tcm_dir + "/drivers/target/Kbuild"
|
kbuild = tcm_dir + "/drivers/target/Makefile"
|
||||||
|
|
||||||
f = open(kbuild, 'a')
|
f = open(kbuild, 'a')
|
||||||
f.write(buf)
|
f.write(buf)
|
||||||
@ -1064,7 +1064,7 @@ def main(modname, proto_ident):
|
|||||||
tcm_mod_build_kbuild(fabric_mod_dir, fabric_mod_name)
|
tcm_mod_build_kbuild(fabric_mod_dir, fabric_mod_name)
|
||||||
tcm_mod_build_kconfig(fabric_mod_dir, fabric_mod_name)
|
tcm_mod_build_kconfig(fabric_mod_dir, fabric_mod_name)
|
||||||
|
|
||||||
input = raw_input("Would you like to add " + fabric_mod_name + "to drivers/target/Kbuild..? [yes,no]: ")
|
input = raw_input("Would you like to add " + fabric_mod_name + "to drivers/target/Makefile..? [yes,no]: ")
|
||||||
if input == "yes" or input == "y":
|
if input == "yes" or input == "y":
|
||||||
tcm_mod_add_kbuild(tcm_dir, fabric_mod_name)
|
tcm_mod_add_kbuild(tcm_dir, fabric_mod_name)
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
|
obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
|
||||||
|
|
||||||
aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \
|
aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \
|
||||||
dpcsup.o rx.o sa.o rkt.o nark.o
|
dpcsup.o rx.o sa.o rkt.o nark.o src.o
|
||||||
|
|
||||||
ccflags-y := -Idrivers/scsi
|
ccflags-y := -Idrivers/scsi
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -1486,7 +1487,9 @@ int aac_get_adapter_info(struct aac_dev* dev)
|
|||||||
dev->a_ops.adapter_write = aac_write_block;
|
dev->a_ops.adapter_write = aac_write_block;
|
||||||
}
|
}
|
||||||
dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
|
dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
|
||||||
if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
|
if (dev->adapter_info.options & AAC_OPT_NEW_COMM_TYPE1)
|
||||||
|
dev->adapter_info.options |= AAC_OPT_NEW_COMM;
|
||||||
|
if (!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
|
||||||
/*
|
/*
|
||||||
* Worst case size that could cause sg overflow when
|
* Worst case size that could cause sg overflow when
|
||||||
* we break up SG elements that are larger than 64KB.
|
* we break up SG elements that are larger than 64KB.
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef AAC_DRIVER_BUILD
|
#ifndef AAC_DRIVER_BUILD
|
||||||
# define AAC_DRIVER_BUILD 26400
|
# define AAC_DRIVER_BUILD 28000
|
||||||
# define AAC_DRIVER_BRANCH "-ms"
|
# define AAC_DRIVER_BRANCH "-ms"
|
||||||
#endif
|
#endif
|
||||||
#define MAXIMUM_NUM_CONTAINERS 32
|
#define MAXIMUM_NUM_CONTAINERS 32
|
||||||
@ -277,6 +277,16 @@ enum aac_queue_types {
|
|||||||
|
|
||||||
#define FsaNormal 1
|
#define FsaNormal 1
|
||||||
|
|
||||||
|
/* transport FIB header (PMC) */
|
||||||
|
struct aac_fib_xporthdr {
|
||||||
|
u64 HostAddress; /* FIB host address w/o xport header */
|
||||||
|
u32 Size; /* FIB size excluding xport header */
|
||||||
|
u32 Handle; /* driver handle to reference the FIB */
|
||||||
|
u64 Reserved[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ALIGN32 32
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the FIB. The FIB is the where all the requested data and
|
* Define the FIB. The FIB is the where all the requested data and
|
||||||
* command information are put to the application on the FSA adapter.
|
* command information are put to the application on the FSA adapter.
|
||||||
@ -394,7 +404,9 @@ enum fib_xfer_state {
|
|||||||
AdapterMicroFib = (1<<17),
|
AdapterMicroFib = (1<<17),
|
||||||
BIOSFibPath = (1<<18),
|
BIOSFibPath = (1<<18),
|
||||||
FastResponseCapable = (1<<19),
|
FastResponseCapable = (1<<19),
|
||||||
ApiFib = (1<<20) // Its an API Fib.
|
ApiFib = (1<<20), /* Its an API Fib */
|
||||||
|
/* PMC NEW COMM: There is no more AIF data pending */
|
||||||
|
NoMoreAifDataAvailable = (1<<21)
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -404,6 +416,7 @@ enum fib_xfer_state {
|
|||||||
|
|
||||||
#define ADAPTER_INIT_STRUCT_REVISION 3
|
#define ADAPTER_INIT_STRUCT_REVISION 3
|
||||||
#define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science
|
#define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science
|
||||||
|
#define ADAPTER_INIT_STRUCT_REVISION_6 6 /* PMC src */
|
||||||
|
|
||||||
struct aac_init
|
struct aac_init
|
||||||
{
|
{
|
||||||
@ -428,9 +441,15 @@ struct aac_init
|
|||||||
#define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001
|
#define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001
|
||||||
#define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010
|
#define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010
|
||||||
#define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020
|
#define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020
|
||||||
|
#define INITFLAGS_NEW_COMM_TYPE1_SUPPORTED 0x00000041
|
||||||
__le32 MaxIoCommands; /* max outstanding commands */
|
__le32 MaxIoCommands; /* max outstanding commands */
|
||||||
__le32 MaxIoSize; /* largest I/O command */
|
__le32 MaxIoSize; /* largest I/O command */
|
||||||
__le32 MaxFibSize; /* largest FIB to adapter */
|
__le32 MaxFibSize; /* largest FIB to adapter */
|
||||||
|
/* ADAPTER_INIT_STRUCT_REVISION_5 begins here */
|
||||||
|
__le32 MaxNumAif; /* max number of aif */
|
||||||
|
/* ADAPTER_INIT_STRUCT_REVISION_6 begins here */
|
||||||
|
__le32 HostRRQ_AddrLow;
|
||||||
|
__le32 HostRRQ_AddrHigh; /* Host RRQ (response queue) for SRC */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum aac_log_level {
|
enum aac_log_level {
|
||||||
@ -685,7 +704,7 @@ struct rx_inbound {
|
|||||||
#define OutboundDoorbellReg MUnit.ODR
|
#define OutboundDoorbellReg MUnit.ODR
|
||||||
|
|
||||||
struct rx_registers {
|
struct rx_registers {
|
||||||
struct rx_mu_registers MUnit; /* 1300h - 1344h */
|
struct rx_mu_registers MUnit; /* 1300h - 1347h */
|
||||||
__le32 reserved1[2]; /* 1348h - 134ch */
|
__le32 reserved1[2]; /* 1348h - 134ch */
|
||||||
struct rx_inbound IndexRegs;
|
struct rx_inbound IndexRegs;
|
||||||
};
|
};
|
||||||
@ -703,7 +722,7 @@ struct rx_registers {
|
|||||||
#define rkt_inbound rx_inbound
|
#define rkt_inbound rx_inbound
|
||||||
|
|
||||||
struct rkt_registers {
|
struct rkt_registers {
|
||||||
struct rkt_mu_registers MUnit; /* 1300h - 1344h */
|
struct rkt_mu_registers MUnit; /* 1300h - 1347h */
|
||||||
__le32 reserved1[1006]; /* 1348h - 22fch */
|
__le32 reserved1[1006]; /* 1348h - 22fch */
|
||||||
struct rkt_inbound IndexRegs; /* 2300h - */
|
struct rkt_inbound IndexRegs; /* 2300h - */
|
||||||
};
|
};
|
||||||
@ -713,6 +732,44 @@ struct rkt_registers {
|
|||||||
#define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR))
|
#define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR))
|
||||||
#define rkt_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rkt->CSR))
|
#define rkt_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rkt->CSR))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PMC SRC message unit registers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define src_inbound rx_inbound
|
||||||
|
|
||||||
|
struct src_mu_registers {
|
||||||
|
/* PCI*| Name */
|
||||||
|
__le32 reserved0[8]; /* 00h | Reserved */
|
||||||
|
__le32 IDR; /* 20h | Inbound Doorbell Register */
|
||||||
|
__le32 IISR; /* 24h | Inbound Int. Status Register */
|
||||||
|
__le32 reserved1[3]; /* 28h | Reserved */
|
||||||
|
__le32 OIMR; /* 34h | Outbound Int. Mask Register */
|
||||||
|
__le32 reserved2[25]; /* 38h | Reserved */
|
||||||
|
__le32 ODR_R; /* 9ch | Outbound Doorbell Read */
|
||||||
|
__le32 ODR_C; /* a0h | Outbound Doorbell Clear */
|
||||||
|
__le32 reserved3[6]; /* a4h | Reserved */
|
||||||
|
__le32 OMR; /* bch | Outbound Message Register */
|
||||||
|
__le32 IQ_L; /* c0h | Inbound Queue (Low address) */
|
||||||
|
__le32 IQ_H; /* c4h | Inbound Queue (High address) */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct src_registers {
|
||||||
|
struct src_mu_registers MUnit; /* 00h - c7h */
|
||||||
|
__le32 reserved1[130790]; /* c8h - 7fc5fh */
|
||||||
|
struct src_inbound IndexRegs; /* 7fc60h */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define src_readb(AEP, CSR) readb(&((AEP)->regs.src.bar0->CSR))
|
||||||
|
#define src_readl(AEP, CSR) readl(&((AEP)->regs.src.bar0->CSR))
|
||||||
|
#define src_writeb(AEP, CSR, value) writeb(value, \
|
||||||
|
&((AEP)->regs.src.bar0->CSR))
|
||||||
|
#define src_writel(AEP, CSR, value) writel(value, \
|
||||||
|
&((AEP)->regs.src.bar0->CSR))
|
||||||
|
|
||||||
|
#define SRC_ODR_SHIFT 12
|
||||||
|
#define SRC_IDR_SHIFT 9
|
||||||
|
|
||||||
typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
|
typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
|
||||||
|
|
||||||
struct aac_fib_context {
|
struct aac_fib_context {
|
||||||
@ -879,6 +936,7 @@ struct aac_supplement_adapter_info
|
|||||||
#define AAC_OPTION_MU_RESET cpu_to_le32(0x00000001)
|
#define AAC_OPTION_MU_RESET cpu_to_le32(0x00000001)
|
||||||
#define AAC_OPTION_IGNORE_RESET cpu_to_le32(0x00000002)
|
#define AAC_OPTION_IGNORE_RESET cpu_to_le32(0x00000002)
|
||||||
#define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004)
|
#define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004)
|
||||||
|
#define AAC_OPTION_DOORBELL_RESET cpu_to_le32(0x00004000)
|
||||||
#define AAC_SIS_VERSION_V3 3
|
#define AAC_SIS_VERSION_V3 3
|
||||||
#define AAC_SIS_SLOT_UNKNOWN 0xFF
|
#define AAC_SIS_SLOT_UNKNOWN 0xFF
|
||||||
|
|
||||||
@ -940,6 +998,7 @@ struct aac_bus_info_response {
|
|||||||
#define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16)
|
#define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16)
|
||||||
#define AAC_OPT_NEW_COMM cpu_to_le32(1<<17)
|
#define AAC_OPT_NEW_COMM cpu_to_le32(1<<17)
|
||||||
#define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18)
|
#define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18)
|
||||||
|
#define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28)
|
||||||
|
|
||||||
struct aac_dev
|
struct aac_dev
|
||||||
{
|
{
|
||||||
@ -952,6 +1011,7 @@ struct aac_dev
|
|||||||
*/
|
*/
|
||||||
unsigned max_fib_size;
|
unsigned max_fib_size;
|
||||||
unsigned sg_tablesize;
|
unsigned sg_tablesize;
|
||||||
|
unsigned max_num_aif;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map for 128 fib objects (64k)
|
* Map for 128 fib objects (64k)
|
||||||
@ -980,10 +1040,21 @@ struct aac_dev
|
|||||||
struct adapter_ops a_ops;
|
struct adapter_ops a_ops;
|
||||||
unsigned long fsrev; /* Main driver's revision number */
|
unsigned long fsrev; /* Main driver's revision number */
|
||||||
|
|
||||||
unsigned base_size; /* Size of mapped in region */
|
unsigned long dbg_base; /* address of UART
|
||||||
|
* debug buffer */
|
||||||
|
|
||||||
|
unsigned base_size, dbg_size; /* Size of
|
||||||
|
* mapped in region */
|
||||||
|
|
||||||
struct aac_init *init; /* Holds initialization info to communicate with adapter */
|
struct aac_init *init; /* Holds initialization info to communicate with adapter */
|
||||||
dma_addr_t init_pa; /* Holds physical address of the init struct */
|
dma_addr_t init_pa; /* Holds physical address of the init struct */
|
||||||
|
|
||||||
|
u32 *host_rrq; /* response queue
|
||||||
|
* if AAC_COMM_MESSAGE_TYPE1 */
|
||||||
|
|
||||||
|
dma_addr_t host_rrq_pa; /* phys. address */
|
||||||
|
u32 host_rrq_idx; /* index into rrq buffer */
|
||||||
|
|
||||||
struct pci_dev *pdev; /* Our PCI interface */
|
struct pci_dev *pdev; /* Our PCI interface */
|
||||||
void * printfbuf; /* pointer to buffer used for printf's from the adapter */
|
void * printfbuf; /* pointer to buffer used for printf's from the adapter */
|
||||||
void * comm_addr; /* Base address of Comm area */
|
void * comm_addr; /* Base address of Comm area */
|
||||||
@ -1003,14 +1074,20 @@ struct aac_dev
|
|||||||
*/
|
*/
|
||||||
#ifndef AAC_MIN_FOOTPRINT_SIZE
|
#ifndef AAC_MIN_FOOTPRINT_SIZE
|
||||||
# define AAC_MIN_FOOTPRINT_SIZE 8192
|
# define AAC_MIN_FOOTPRINT_SIZE 8192
|
||||||
|
# define AAC_MIN_SRC_BAR0_SIZE 0x400000
|
||||||
|
# define AAC_MIN_SRC_BAR1_SIZE 0x800
|
||||||
#endif
|
#endif
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct sa_registers __iomem *sa;
|
struct sa_registers __iomem *sa;
|
||||||
struct rx_registers __iomem *rx;
|
struct rx_registers __iomem *rx;
|
||||||
struct rkt_registers __iomem *rkt;
|
struct rkt_registers __iomem *rkt;
|
||||||
|
struct {
|
||||||
|
struct src_registers __iomem *bar0;
|
||||||
|
char __iomem *bar1;
|
||||||
|
} src;
|
||||||
} regs;
|
} regs;
|
||||||
volatile void __iomem *base;
|
volatile void __iomem *base, *dbg_base_mapped;
|
||||||
volatile struct rx_inbound __iomem *IndexRegs;
|
volatile struct rx_inbound __iomem *IndexRegs;
|
||||||
u32 OIMR; /* Mask Register Cache */
|
u32 OIMR; /* Mask Register Cache */
|
||||||
/*
|
/*
|
||||||
@ -1031,9 +1108,8 @@ struct aac_dev
|
|||||||
u8 comm_interface;
|
u8 comm_interface;
|
||||||
# define AAC_COMM_PRODUCER 0
|
# define AAC_COMM_PRODUCER 0
|
||||||
# define AAC_COMM_MESSAGE 1
|
# define AAC_COMM_MESSAGE 1
|
||||||
/* macro side-effects BEWARE */
|
# define AAC_COMM_MESSAGE_TYPE1 3
|
||||||
# define raw_io_interface \
|
u8 raw_io_interface;
|
||||||
init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
|
|
||||||
u8 raw_io_64;
|
u8 raw_io_64;
|
||||||
u8 printf_enabled;
|
u8 printf_enabled;
|
||||||
u8 in_reset;
|
u8 in_reset;
|
||||||
@ -1789,6 +1865,10 @@ extern struct aac_common aac_config;
|
|||||||
#define DoorBellAdapterNormCmdNotFull (1<<3) /* Adapter -> Host */
|
#define DoorBellAdapterNormCmdNotFull (1<<3) /* Adapter -> Host */
|
||||||
#define DoorBellAdapterNormRespNotFull (1<<4) /* Adapter -> Host */
|
#define DoorBellAdapterNormRespNotFull (1<<4) /* Adapter -> Host */
|
||||||
#define DoorBellPrintfReady (1<<5) /* Adapter -> Host */
|
#define DoorBellPrintfReady (1<<5) /* Adapter -> Host */
|
||||||
|
#define DoorBellAifPending (1<<6) /* Adapter -> Host */
|
||||||
|
|
||||||
|
/* PMC specific outbound doorbell bits */
|
||||||
|
#define PmDoorBellResponseSent (1<<1) /* Adapter -> Host */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For FIB communication, we need all of the following things
|
* For FIB communication, we need all of the following things
|
||||||
@ -1831,6 +1911,9 @@ extern struct aac_common aac_config;
|
|||||||
#define AifReqAPIJobUpdate 109 /* Update a job report from the API */
|
#define AifReqAPIJobUpdate 109 /* Update a job report from the API */
|
||||||
#define AifReqAPIJobFinish 110 /* Finish a job from the API */
|
#define AifReqAPIJobFinish 110 /* Finish a job from the API */
|
||||||
|
|
||||||
|
/* PMC NEW COMM: Request the event data */
|
||||||
|
#define AifReqEvent 200
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adapter Initiated FIB command structures. Start with the adapter
|
* Adapter Initiated FIB command structures. Start with the adapter
|
||||||
* initiated FIBs that really come from the adapter, and get responded
|
* initiated FIBs that really come from the adapter, and get responded
|
||||||
@ -1886,10 +1969,13 @@ int aac_rx_init(struct aac_dev *dev);
|
|||||||
int aac_rkt_init(struct aac_dev *dev);
|
int aac_rkt_init(struct aac_dev *dev);
|
||||||
int aac_nark_init(struct aac_dev *dev);
|
int aac_nark_init(struct aac_dev *dev);
|
||||||
int aac_sa_init(struct aac_dev *dev);
|
int aac_sa_init(struct aac_dev *dev);
|
||||||
|
int aac_src_init(struct aac_dev *dev);
|
||||||
int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
|
int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
|
||||||
unsigned int aac_response_normal(struct aac_queue * q);
|
unsigned int aac_response_normal(struct aac_queue * q);
|
||||||
unsigned int aac_command_normal(struct aac_queue * q);
|
unsigned int aac_command_normal(struct aac_queue * q);
|
||||||
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
|
unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index,
|
||||||
|
int isAif, int isFastResponse,
|
||||||
|
struct hw_fib *aif_fib);
|
||||||
int aac_reset_adapter(struct aac_dev * dev, int forced);
|
int aac_reset_adapter(struct aac_dev * dev, int forced);
|
||||||
int aac_check_health(struct aac_dev * dev);
|
int aac_check_health(struct aac_dev * dev);
|
||||||
int aac_command_thread(void *data);
|
int aac_command_thread(void *data);
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -52,12 +53,16 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
|
|||||||
unsigned long size, align;
|
unsigned long size, align;
|
||||||
const unsigned long fibsize = 4096;
|
const unsigned long fibsize = 4096;
|
||||||
const unsigned long printfbufsiz = 256;
|
const unsigned long printfbufsiz = 256;
|
||||||
|
unsigned long host_rrq_size = 0;
|
||||||
struct aac_init *init;
|
struct aac_init *init;
|
||||||
dma_addr_t phys;
|
dma_addr_t phys;
|
||||||
unsigned long aac_max_hostphysmempages;
|
unsigned long aac_max_hostphysmempages;
|
||||||
|
|
||||||
size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz;
|
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1)
|
||||||
|
host_rrq_size = (dev->scsi_host_ptr->can_queue
|
||||||
|
+ AAC_NUM_MGT_FIB) * sizeof(u32);
|
||||||
|
size = fibsize + sizeof(struct aac_init) + commsize +
|
||||||
|
commalign + printfbufsiz + host_rrq_size;
|
||||||
|
|
||||||
base = pci_alloc_consistent(dev->pdev, size, &phys);
|
base = pci_alloc_consistent(dev->pdev, size, &phys);
|
||||||
|
|
||||||
@ -70,8 +75,14 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
|
|||||||
dev->comm_phys = phys;
|
dev->comm_phys = phys;
|
||||||
dev->comm_size = size;
|
dev->comm_size = size;
|
||||||
|
|
||||||
dev->init = (struct aac_init *)(base + fibsize);
|
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
|
||||||
dev->init_pa = phys + fibsize;
|
dev->host_rrq = (u32 *)(base + fibsize);
|
||||||
|
dev->host_rrq_pa = phys + fibsize;
|
||||||
|
memset(dev->host_rrq, 0, host_rrq_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->init = (struct aac_init *)(base + fibsize + host_rrq_size);
|
||||||
|
dev->init_pa = phys + fibsize + host_rrq_size;
|
||||||
|
|
||||||
init = dev->init;
|
init = dev->init;
|
||||||
|
|
||||||
@ -106,8 +117,13 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
|
|||||||
|
|
||||||
init->InitFlags = 0;
|
init->InitFlags = 0;
|
||||||
if (dev->comm_interface == AAC_COMM_MESSAGE) {
|
if (dev->comm_interface == AAC_COMM_MESSAGE) {
|
||||||
init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
|
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
|
||||||
dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
|
dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
|
||||||
|
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
|
||||||
|
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6);
|
||||||
|
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_TYPE1_SUPPORTED);
|
||||||
|
dprintk((KERN_WARNING
|
||||||
|
"aacraid: New Comm Interface type1 enabled\n"));
|
||||||
}
|
}
|
||||||
init->InitFlags |= cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME |
|
init->InitFlags |= cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME |
|
||||||
INITFLAGS_DRIVER_SUPPORTS_PM);
|
INITFLAGS_DRIVER_SUPPORTS_PM);
|
||||||
@ -115,11 +131,18 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
|
|||||||
init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
|
init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
|
||||||
init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
|
init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
|
||||||
|
|
||||||
|
init->MaxNumAif = cpu_to_le32(dev->max_num_aif);
|
||||||
|
init->HostRRQ_AddrHigh = (u32)((u64)dev->host_rrq_pa >> 32);
|
||||||
|
init->HostRRQ_AddrLow = (u32)(dev->host_rrq_pa & 0xffffffff);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Increment the base address by the amount already used
|
* Increment the base address by the amount already used
|
||||||
*/
|
*/
|
||||||
base = base + fibsize + sizeof(struct aac_init);
|
base = base + fibsize + host_rrq_size + sizeof(struct aac_init);
|
||||||
phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init));
|
phys = (dma_addr_t)((ulong)phys + fibsize + host_rrq_size +
|
||||||
|
sizeof(struct aac_init));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Align the beginning of Headers to commalign
|
* Align the beginning of Headers to commalign
|
||||||
*/
|
*/
|
||||||
@ -314,15 +337,22 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
|||||||
- sizeof(struct aac_write) + sizeof(struct sgentry))
|
- sizeof(struct aac_write) + sizeof(struct sgentry))
|
||||||
/ sizeof(struct sgentry);
|
/ sizeof(struct sgentry);
|
||||||
dev->comm_interface = AAC_COMM_PRODUCER;
|
dev->comm_interface = AAC_COMM_PRODUCER;
|
||||||
dev->raw_io_64 = 0;
|
dev->raw_io_interface = dev->raw_io_64 = 0;
|
||||||
|
|
||||||
if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
|
if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
|
||||||
0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
|
0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
|
||||||
(status[0] == 0x00000001)) {
|
(status[0] == 0x00000001)) {
|
||||||
if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64))
|
if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64))
|
||||||
dev->raw_io_64 = 1;
|
dev->raw_io_64 = 1;
|
||||||
if (dev->a_ops.adapter_comm &&
|
if (dev->a_ops.adapter_comm) {
|
||||||
(status[1] & le32_to_cpu(AAC_OPT_NEW_COMM)))
|
if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1)) {
|
||||||
dev->comm_interface = AAC_COMM_MESSAGE;
|
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
|
||||||
|
dev->raw_io_interface = 1;
|
||||||
|
} else if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM)) {
|
||||||
|
dev->comm_interface = AAC_COMM_MESSAGE;
|
||||||
|
dev->raw_io_interface = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
|
if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
|
||||||
(status[2] > dev->base_size)) {
|
(status[2] > dev->base_size)) {
|
||||||
aac_adapter_ioremap(dev, 0);
|
aac_adapter_ioremap(dev, 0);
|
||||||
@ -350,10 +380,12 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
|||||||
* status[3] & 0xFFFF maximum number FIBs outstanding
|
* status[3] & 0xFFFF maximum number FIBs outstanding
|
||||||
*/
|
*/
|
||||||
host->max_sectors = (status[1] >> 16) << 1;
|
host->max_sectors = (status[1] >> 16) << 1;
|
||||||
dev->max_fib_size = status[1] & 0xFFFF;
|
/* Multiple of 32 for PMC */
|
||||||
|
dev->max_fib_size = status[1] & 0xFFE0;
|
||||||
host->sg_tablesize = status[2] >> 16;
|
host->sg_tablesize = status[2] >> 16;
|
||||||
dev->sg_tablesize = status[2] & 0xFFFF;
|
dev->sg_tablesize = status[2] & 0xFFFF;
|
||||||
host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
|
host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
|
||||||
|
dev->max_num_aif = status[4] & 0xFFFF;
|
||||||
/*
|
/*
|
||||||
* NOTE:
|
* NOTE:
|
||||||
* All these overrides are based on a fixed internal
|
* All these overrides are based on a fixed internal
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -63,9 +64,11 @@ static int fib_map_alloc(struct aac_dev *dev)
|
|||||||
"allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
|
"allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
|
||||||
dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue,
|
dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue,
|
||||||
AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
|
AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
|
||||||
if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, dev->max_fib_size
|
dev->hw_fib_va = pci_alloc_consistent(dev->pdev,
|
||||||
* (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
|
(dev->max_fib_size + sizeof(struct aac_fib_xporthdr))
|
||||||
&dev->hw_fib_pa))==NULL)
|
* (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) + (ALIGN32 - 1),
|
||||||
|
&dev->hw_fib_pa);
|
||||||
|
if (dev->hw_fib_va == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -110,9 +113,22 @@ int aac_fib_setup(struct aac_dev * dev)
|
|||||||
if (i<0)
|
if (i<0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* 32 byte alignment for PMC */
|
||||||
|
hw_fib_pa = (dev->hw_fib_pa + (ALIGN32 - 1)) & ~(ALIGN32 - 1);
|
||||||
|
dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va +
|
||||||
|
(hw_fib_pa - dev->hw_fib_pa));
|
||||||
|
dev->hw_fib_pa = hw_fib_pa;
|
||||||
|
memset(dev->hw_fib_va, 0,
|
||||||
|
(dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) *
|
||||||
|
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
|
||||||
|
|
||||||
|
/* add Xport header */
|
||||||
|
dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va +
|
||||||
|
sizeof(struct aac_fib_xporthdr));
|
||||||
|
dev->hw_fib_pa += sizeof(struct aac_fib_xporthdr);
|
||||||
|
|
||||||
hw_fib = dev->hw_fib_va;
|
hw_fib = dev->hw_fib_va;
|
||||||
hw_fib_pa = dev->hw_fib_pa;
|
hw_fib_pa = dev->hw_fib_pa;
|
||||||
memset(hw_fib, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
|
|
||||||
/*
|
/*
|
||||||
* Initialise the fibs
|
* Initialise the fibs
|
||||||
*/
|
*/
|
||||||
@ -129,8 +145,10 @@ int aac_fib_setup(struct aac_dev * dev)
|
|||||||
hw_fib->header.XferState = cpu_to_le32(0xffffffff);
|
hw_fib->header.XferState = cpu_to_le32(0xffffffff);
|
||||||
hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
|
hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
|
||||||
fibptr->hw_fib_pa = hw_fib_pa;
|
fibptr->hw_fib_pa = hw_fib_pa;
|
||||||
hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size);
|
hw_fib = (struct hw_fib *)((unsigned char *)hw_fib +
|
||||||
hw_fib_pa = hw_fib_pa + dev->max_fib_size;
|
dev->max_fib_size + sizeof(struct aac_fib_xporthdr));
|
||||||
|
hw_fib_pa = hw_fib_pa +
|
||||||
|
dev->max_fib_size + sizeof(struct aac_fib_xporthdr);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Add the fib chain to the free list
|
* Add the fib chain to the free list
|
||||||
@ -664,9 +682,14 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
|
|||||||
unsigned long nointr = 0;
|
unsigned long nointr = 0;
|
||||||
unsigned long qflags;
|
unsigned long qflags;
|
||||||
|
|
||||||
|
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
|
||||||
|
kfree(hw_fib);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (hw_fib->header.XferState == 0) {
|
if (hw_fib->header.XferState == 0) {
|
||||||
if (dev->comm_interface == AAC_COMM_MESSAGE)
|
if (dev->comm_interface == AAC_COMM_MESSAGE)
|
||||||
kfree (hw_fib);
|
kfree(hw_fib);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -674,7 +697,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
|
|||||||
*/
|
*/
|
||||||
if (hw_fib->header.StructType != FIB_MAGIC) {
|
if (hw_fib->header.StructType != FIB_MAGIC) {
|
||||||
if (dev->comm_interface == AAC_COMM_MESSAGE)
|
if (dev->comm_interface == AAC_COMM_MESSAGE)
|
||||||
kfree (hw_fib);
|
kfree(hw_fib);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -228,6 +229,48 @@ unsigned int aac_command_normal(struct aac_queue *q)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* aac_aif_callback
|
||||||
|
* @context: the context set in the fib - here it is scsi cmd
|
||||||
|
* @fibptr: pointer to the fib
|
||||||
|
*
|
||||||
|
* Handles the AIFs - new method (SRC)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void aac_aif_callback(void *context, struct fib * fibptr)
|
||||||
|
{
|
||||||
|
struct fib *fibctx;
|
||||||
|
struct aac_dev *dev;
|
||||||
|
struct aac_aifcmd *cmd;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
fibctx = (struct fib *)context;
|
||||||
|
BUG_ON(fibptr == NULL);
|
||||||
|
dev = fibptr->dev;
|
||||||
|
|
||||||
|
if (fibptr->hw_fib_va->header.XferState &
|
||||||
|
cpu_to_le32(NoMoreAifDataAvailable)) {
|
||||||
|
aac_fib_complete(fibptr);
|
||||||
|
aac_fib_free(fibptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aac_intr_normal(dev, 0, 1, 0, fibptr->hw_fib_va);
|
||||||
|
|
||||||
|
aac_fib_init(fibctx);
|
||||||
|
cmd = (struct aac_aifcmd *) fib_data(fibctx);
|
||||||
|
cmd->command = cpu_to_le32(AifReqEvent);
|
||||||
|
|
||||||
|
status = aac_fib_send(AifRequest,
|
||||||
|
fibctx,
|
||||||
|
sizeof(struct hw_fib)-sizeof(struct aac_fibhdr),
|
||||||
|
FsaNormal,
|
||||||
|
0, 1,
|
||||||
|
(fib_callback)aac_aif_callback, fibctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aac_intr_normal - Handle command replies
|
* aac_intr_normal - Handle command replies
|
||||||
@ -238,19 +281,17 @@ unsigned int aac_command_normal(struct aac_queue *q)
|
|||||||
* know there is a response on our normal priority queue. We will pull off
|
* know there is a response on our normal priority queue. We will pull off
|
||||||
* all QE there are and wake up all the waiters before exiting.
|
* all QE there are and wake up all the waiters before exiting.
|
||||||
*/
|
*/
|
||||||
|
unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
|
||||||
unsigned int aac_intr_normal(struct aac_dev * dev, u32 index)
|
int isAif, int isFastResponse, struct hw_fib *aif_fib)
|
||||||
{
|
{
|
||||||
unsigned long mflags;
|
unsigned long mflags;
|
||||||
dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index));
|
dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index));
|
||||||
if ((index & 0x00000002L)) {
|
if (isAif == 1) { /* AIF - common */
|
||||||
struct hw_fib * hw_fib;
|
struct hw_fib * hw_fib;
|
||||||
struct fib * fib;
|
struct fib * fib;
|
||||||
struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue];
|
struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue];
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (index == 0xFFFFFFFEL) /* Special Case */
|
|
||||||
return 0; /* Do nothing */
|
|
||||||
/*
|
/*
|
||||||
* Allocate a FIB. For non queued stuff we can just use
|
* Allocate a FIB. For non queued stuff we can just use
|
||||||
* the stack so we are happy. We need a fib object in order to
|
* the stack so we are happy. We need a fib object in order to
|
||||||
@ -263,8 +304,13 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 index)
|
|||||||
kfree (fib);
|
kfree (fib);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memcpy(hw_fib, (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) +
|
if (aif_fib != NULL) {
|
||||||
(index & ~0x00000002L)), sizeof(struct hw_fib));
|
memcpy(hw_fib, aif_fib, sizeof(struct hw_fib));
|
||||||
|
} else {
|
||||||
|
memcpy(hw_fib,
|
||||||
|
(struct hw_fib *)(((uintptr_t)(dev->regs.sa)) +
|
||||||
|
index), sizeof(struct hw_fib));
|
||||||
|
}
|
||||||
INIT_LIST_HEAD(&fib->fiblink);
|
INIT_LIST_HEAD(&fib->fiblink);
|
||||||
fib->type = FSAFS_NTC_FIB_CONTEXT;
|
fib->type = FSAFS_NTC_FIB_CONTEXT;
|
||||||
fib->size = sizeof(struct fib);
|
fib->size = sizeof(struct fib);
|
||||||
@ -277,9 +323,26 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 index)
|
|||||||
wake_up_interruptible(&q->cmdready);
|
wake_up_interruptible(&q->cmdready);
|
||||||
spin_unlock_irqrestore(q->lock, flags);
|
spin_unlock_irqrestore(q->lock, flags);
|
||||||
return 1;
|
return 1;
|
||||||
|
} else if (isAif == 2) { /* AIF - new (SRC) */
|
||||||
|
struct fib *fibctx;
|
||||||
|
struct aac_aifcmd *cmd;
|
||||||
|
|
||||||
|
fibctx = aac_fib_alloc(dev);
|
||||||
|
if (!fibctx)
|
||||||
|
return 1;
|
||||||
|
aac_fib_init(fibctx);
|
||||||
|
|
||||||
|
cmd = (struct aac_aifcmd *) fib_data(fibctx);
|
||||||
|
cmd->command = cpu_to_le32(AifReqEvent);
|
||||||
|
|
||||||
|
return aac_fib_send(AifRequest,
|
||||||
|
fibctx,
|
||||||
|
sizeof(struct hw_fib)-sizeof(struct aac_fibhdr),
|
||||||
|
FsaNormal,
|
||||||
|
0, 1,
|
||||||
|
(fib_callback)aac_aif_callback, fibctx);
|
||||||
} else {
|
} else {
|
||||||
int fast = index & 0x01;
|
struct fib *fib = &dev->fibs[index];
|
||||||
struct fib * fib = &dev->fibs[index >> 2];
|
|
||||||
struct hw_fib * hwfib = fib->hw_fib_va;
|
struct hw_fib * hwfib = fib->hw_fib_va;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -298,7 +361,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 index)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fast) {
|
if (isFastResponse) {
|
||||||
/*
|
/*
|
||||||
* Doctor the fib
|
* Doctor the fib
|
||||||
*/
|
*/
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -54,7 +55,7 @@
|
|||||||
|
|
||||||
#include "aacraid.h"
|
#include "aacraid.h"
|
||||||
|
|
||||||
#define AAC_DRIVER_VERSION "1.1-5"
|
#define AAC_DRIVER_VERSION "1.1-7"
|
||||||
#ifndef AAC_DRIVER_BRANCH
|
#ifndef AAC_DRIVER_BRANCH
|
||||||
#define AAC_DRIVER_BRANCH ""
|
#define AAC_DRIVER_BRANCH ""
|
||||||
#endif
|
#endif
|
||||||
@ -161,6 +162,7 @@ static const struct pci_device_id aac_pci_tbl[] __devinitdata = {
|
|||||||
{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
|
{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
|
||||||
{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
|
{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
|
||||||
{ 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */
|
{ 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */
|
||||||
|
{ 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Catch All */
|
||||||
{ 0,}
|
{ 0,}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
|
MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
|
||||||
@ -235,7 +237,8 @@ static struct aac_driver_ident aac_drivers[] = {
|
|||||||
{ aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend Catchall */
|
{ aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend Catchall */
|
||||||
{ aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */
|
{ aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */
|
||||||
{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */
|
{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */
|
||||||
{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec NEMER/ARK Catch All */
|
{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec NEMER/ARK Catch All */
|
||||||
|
{ aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Catch All */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -653,8 +656,10 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
|
|||||||
* This adapter needs a blind reset, only do so for Adapters that
|
* This adapter needs a blind reset, only do so for Adapters that
|
||||||
* support a register, instead of a commanded, reset.
|
* support a register, instead of a commanded, reset.
|
||||||
*/
|
*/
|
||||||
if ((aac->supplement_adapter_info.SupportedOptions2 &
|
if (((aac->supplement_adapter_info.SupportedOptions2 &
|
||||||
AAC_OPTION_MU_RESET) &&
|
AAC_OPTION_MU_RESET) ||
|
||||||
|
(aac->supplement_adapter_info.SupportedOptions2 &
|
||||||
|
AAC_OPTION_DOORBELL_RESET)) &&
|
||||||
aac_check_reset &&
|
aac_check_reset &&
|
||||||
((aac_check_reset != 1) ||
|
((aac_check_reset != 1) ||
|
||||||
!(aac->supplement_adapter_info.SupportedOptions2 &
|
!(aac->supplement_adapter_info.SupportedOptions2 &
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2006-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -84,15 +85,35 @@ static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id)
|
|||||||
|
|
||||||
static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
|
static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
|
int isAif, isFastResponse, isSpecial;
|
||||||
struct aac_dev *dev = dev_id;
|
struct aac_dev *dev = dev_id;
|
||||||
u32 Index = rx_readl(dev, MUnit.OutboundQueue);
|
u32 Index = rx_readl(dev, MUnit.OutboundQueue);
|
||||||
if (unlikely(Index == 0xFFFFFFFFL))
|
if (unlikely(Index == 0xFFFFFFFFL))
|
||||||
Index = rx_readl(dev, MUnit.OutboundQueue);
|
Index = rx_readl(dev, MUnit.OutboundQueue);
|
||||||
if (likely(Index != 0xFFFFFFFFL)) {
|
if (likely(Index != 0xFFFFFFFFL)) {
|
||||||
do {
|
do {
|
||||||
if (unlikely(aac_intr_normal(dev, Index))) {
|
isAif = isFastResponse = isSpecial = 0;
|
||||||
rx_writel(dev, MUnit.OutboundQueue, Index);
|
if (Index & 0x00000002L) {
|
||||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
|
isAif = 1;
|
||||||
|
if (Index == 0xFFFFFFFEL)
|
||||||
|
isSpecial = 1;
|
||||||
|
Index &= ~0x00000002L;
|
||||||
|
} else {
|
||||||
|
if (Index & 0x00000001L)
|
||||||
|
isFastResponse = 1;
|
||||||
|
Index >>= 2;
|
||||||
|
}
|
||||||
|
if (!isSpecial) {
|
||||||
|
if (unlikely(aac_intr_normal(dev,
|
||||||
|
Index, isAif,
|
||||||
|
isFastResponse, NULL))) {
|
||||||
|
rx_writel(dev,
|
||||||
|
MUnit.OutboundQueue,
|
||||||
|
Index);
|
||||||
|
rx_writel(dev,
|
||||||
|
MUnit.ODR,
|
||||||
|
DoorBellAdapterNormRespReady);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Index = rx_readl(dev, MUnit.OutboundQueue);
|
Index = rx_readl(dev, MUnit.OutboundQueue);
|
||||||
} while (Index != 0xFFFFFFFFL);
|
} while (Index != 0xFFFFFFFFL);
|
||||||
@ -631,6 +652,10 @@ int _aac_rx_init(struct aac_dev *dev)
|
|||||||
name, instance);
|
name, instance);
|
||||||
goto error_iounmap;
|
goto error_iounmap;
|
||||||
}
|
}
|
||||||
|
dev->dbg_base = dev->scsi_host_ptr->base;
|
||||||
|
dev->dbg_base_mapped = dev->base;
|
||||||
|
dev->dbg_size = dev->base_size;
|
||||||
|
|
||||||
aac_adapter_enable_int(dev);
|
aac_adapter_enable_int(dev);
|
||||||
/*
|
/*
|
||||||
* Tell the adapter that all is configured, and it can
|
* Tell the adapter that all is configured, and it can
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
* based on the old aacraid driver that is..
|
* based on the old aacraid driver that is..
|
||||||
* Adaptec aacraid device driver for Linux.
|
* Adaptec aacraid device driver for Linux.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -391,6 +392,10 @@ int aac_sa_init(struct aac_dev *dev)
|
|||||||
name, instance);
|
name, instance);
|
||||||
goto error_iounmap;
|
goto error_iounmap;
|
||||||
}
|
}
|
||||||
|
dev->dbg_base = dev->scsi_host_ptr->base;
|
||||||
|
dev->dbg_base_mapped = dev->base;
|
||||||
|
dev->dbg_size = dev->base_size;
|
||||||
|
|
||||||
aac_adapter_enable_int(dev);
|
aac_adapter_enable_int(dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
594
drivers/scsi/aacraid/src.c
Normal file
594
drivers/scsi/aacraid/src.c
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
/*
|
||||||
|
* Adaptec AAC series RAID controller driver
|
||||||
|
* (c) Copyright 2001 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* based on the old aacraid driver that is..
|
||||||
|
* Adaptec aacraid device driver for Linux.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2000-2010 Adaptec, Inc.
|
||||||
|
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.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, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
* Module Name:
|
||||||
|
* src.c
|
||||||
|
*
|
||||||
|
* Abstract: Hardware Device Interface for PMC SRC based controllers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <linux/time.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <scsi/scsi_host.h>
|
||||||
|
|
||||||
|
#include "aacraid.h"
|
||||||
|
|
||||||
|
static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct aac_dev *dev = dev_id;
|
||||||
|
unsigned long bellbits, bellbits_shifted;
|
||||||
|
int our_interrupt = 0;
|
||||||
|
int isFastResponse;
|
||||||
|
u32 index, handle;
|
||||||
|
|
||||||
|
bellbits = src_readl(dev, MUnit.ODR_R);
|
||||||
|
if (bellbits & PmDoorBellResponseSent) {
|
||||||
|
bellbits = PmDoorBellResponseSent;
|
||||||
|
/* handle async. status */
|
||||||
|
our_interrupt = 1;
|
||||||
|
index = dev->host_rrq_idx;
|
||||||
|
if (dev->host_rrq[index] == 0) {
|
||||||
|
u32 old_index = index;
|
||||||
|
/* adjust index */
|
||||||
|
do {
|
||||||
|
index++;
|
||||||
|
if (index == dev->scsi_host_ptr->can_queue +
|
||||||
|
AAC_NUM_MGT_FIB)
|
||||||
|
index = 0;
|
||||||
|
if (dev->host_rrq[index] != 0)
|
||||||
|
break;
|
||||||
|
} while (index != old_index);
|
||||||
|
dev->host_rrq_idx = index;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
isFastResponse = 0;
|
||||||
|
/* remove toggle bit (31) */
|
||||||
|
handle = (dev->host_rrq[index] & 0x7fffffff);
|
||||||
|
/* check fast response bit (30) */
|
||||||
|
if (handle & 0x40000000)
|
||||||
|
isFastResponse = 1;
|
||||||
|
handle &= 0x0000ffff;
|
||||||
|
if (handle == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
|
||||||
|
|
||||||
|
dev->host_rrq[index++] = 0;
|
||||||
|
if (index == dev->scsi_host_ptr->can_queue +
|
||||||
|
AAC_NUM_MGT_FIB)
|
||||||
|
index = 0;
|
||||||
|
dev->host_rrq_idx = index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
|
||||||
|
if (bellbits_shifted & DoorBellAifPending) {
|
||||||
|
our_interrupt = 1;
|
||||||
|
/* handle AIF */
|
||||||
|
aac_intr_normal(dev, 0, 2, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (our_interrupt) {
|
||||||
|
src_writel(dev, MUnit.ODR_C, bellbits);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_disable_interrupt - Disable interrupts
|
||||||
|
* @dev: Adapter
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void aac_src_disable_interrupt(struct aac_dev *dev)
|
||||||
|
{
|
||||||
|
src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_enable_interrupt_message - Enable interrupts
|
||||||
|
* @dev: Adapter
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void aac_src_enable_interrupt_message(struct aac_dev *dev)
|
||||||
|
{
|
||||||
|
src_writel(dev, MUnit.OIMR, dev->OIMR = 0xfffffff8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* src_sync_cmd - send a command and wait
|
||||||
|
* @dev: Adapter
|
||||||
|
* @command: Command to execute
|
||||||
|
* @p1: first parameter
|
||||||
|
* @ret: adapter status
|
||||||
|
*
|
||||||
|
* This routine will send a synchronous command to the adapter and wait
|
||||||
|
* for its completion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int src_sync_cmd(struct aac_dev *dev, u32 command,
|
||||||
|
u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
|
||||||
|
u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
|
||||||
|
{
|
||||||
|
unsigned long start;
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the command into Mailbox 0
|
||||||
|
*/
|
||||||
|
writel(command, &dev->IndexRegs->Mailbox[0]);
|
||||||
|
/*
|
||||||
|
* Write the parameters into Mailboxes 1 - 6
|
||||||
|
*/
|
||||||
|
writel(p1, &dev->IndexRegs->Mailbox[1]);
|
||||||
|
writel(p2, &dev->IndexRegs->Mailbox[2]);
|
||||||
|
writel(p3, &dev->IndexRegs->Mailbox[3]);
|
||||||
|
writel(p4, &dev->IndexRegs->Mailbox[4]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the synch command doorbell to start on a clean slate.
|
||||||
|
*/
|
||||||
|
src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable doorbell interrupts
|
||||||
|
*/
|
||||||
|
src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force the completion of the mask register write before issuing
|
||||||
|
* the interrupt.
|
||||||
|
*/
|
||||||
|
src_readl(dev, MUnit.OIMR);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal that there is a new synch command
|
||||||
|
*/
|
||||||
|
src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
|
||||||
|
|
||||||
|
ok = 0;
|
||||||
|
start = jiffies;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait up to 30 seconds
|
||||||
|
*/
|
||||||
|
while (time_before(jiffies, start+30*HZ)) {
|
||||||
|
/* Delay 5 microseconds to let Mon960 get info. */
|
||||||
|
udelay(5);
|
||||||
|
|
||||||
|
/* Mon960 will set doorbell0 bit
|
||||||
|
* when it has completed the command
|
||||||
|
*/
|
||||||
|
if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) {
|
||||||
|
/* Clear the doorbell */
|
||||||
|
src_writel(dev,
|
||||||
|
MUnit.ODR_C,
|
||||||
|
OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
|
||||||
|
ok = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yield the processor in case we are slow */
|
||||||
|
msleep(1);
|
||||||
|
}
|
||||||
|
if (unlikely(ok != 1)) {
|
||||||
|
/* Restore interrupt mask even though we timed out */
|
||||||
|
aac_adapter_enable_int(dev);
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pull the synch status from Mailbox 0 */
|
||||||
|
if (status)
|
||||||
|
*status = readl(&dev->IndexRegs->Mailbox[0]);
|
||||||
|
if (r1)
|
||||||
|
*r1 = readl(&dev->IndexRegs->Mailbox[1]);
|
||||||
|
if (r2)
|
||||||
|
*r2 = readl(&dev->IndexRegs->Mailbox[2]);
|
||||||
|
if (r3)
|
||||||
|
*r3 = readl(&dev->IndexRegs->Mailbox[3]);
|
||||||
|
if (r4)
|
||||||
|
*r4 = readl(&dev->IndexRegs->Mailbox[4]);
|
||||||
|
|
||||||
|
/* Clear the synch command doorbell */
|
||||||
|
src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
|
||||||
|
|
||||||
|
/* Restore interrupt mask */
|
||||||
|
aac_adapter_enable_int(dev);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_interrupt_adapter - interrupt adapter
|
||||||
|
* @dev: Adapter
|
||||||
|
*
|
||||||
|
* Send an interrupt to the i960 and breakpoint it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void aac_src_interrupt_adapter(struct aac_dev *dev)
|
||||||
|
{
|
||||||
|
src_sync_cmd(dev, BREAKPOINT_REQUEST,
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
NULL, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_notify_adapter - send an event to the adapter
|
||||||
|
* @dev: Adapter
|
||||||
|
* @event: Event to send
|
||||||
|
*
|
||||||
|
* Notify the i960 that something it probably cares about has
|
||||||
|
* happened.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void aac_src_notify_adapter(struct aac_dev *dev, u32 event)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
|
||||||
|
case AdapNormCmdQue:
|
||||||
|
src_writel(dev, MUnit.ODR_C,
|
||||||
|
INBOUNDDOORBELL_1 << SRC_ODR_SHIFT);
|
||||||
|
break;
|
||||||
|
case HostNormRespNotFull:
|
||||||
|
src_writel(dev, MUnit.ODR_C,
|
||||||
|
INBOUNDDOORBELL_4 << SRC_ODR_SHIFT);
|
||||||
|
break;
|
||||||
|
case AdapNormRespQue:
|
||||||
|
src_writel(dev, MUnit.ODR_C,
|
||||||
|
INBOUNDDOORBELL_2 << SRC_ODR_SHIFT);
|
||||||
|
break;
|
||||||
|
case HostNormCmdNotFull:
|
||||||
|
src_writel(dev, MUnit.ODR_C,
|
||||||
|
INBOUNDDOORBELL_3 << SRC_ODR_SHIFT);
|
||||||
|
break;
|
||||||
|
case FastIo:
|
||||||
|
src_writel(dev, MUnit.ODR_C,
|
||||||
|
INBOUNDDOORBELL_6 << SRC_ODR_SHIFT);
|
||||||
|
break;
|
||||||
|
case AdapPrintfDone:
|
||||||
|
src_writel(dev, MUnit.ODR_C,
|
||||||
|
INBOUNDDOORBELL_5 << SRC_ODR_SHIFT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_start_adapter - activate adapter
|
||||||
|
* @dev: Adapter
|
||||||
|
*
|
||||||
|
* Start up processing on an i960 based AAC adapter
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void aac_src_start_adapter(struct aac_dev *dev)
|
||||||
|
{
|
||||||
|
struct aac_init *init;
|
||||||
|
|
||||||
|
init = dev->init;
|
||||||
|
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
|
||||||
|
|
||||||
|
/* We can only use a 32 bit address here */
|
||||||
|
src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
|
||||||
|
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_check_health
|
||||||
|
* @dev: device to check if healthy
|
||||||
|
*
|
||||||
|
* Will attempt to determine if the specified adapter is alive and
|
||||||
|
* capable of handling requests, returning 0 if alive.
|
||||||
|
*/
|
||||||
|
static int aac_src_check_health(struct aac_dev *dev)
|
||||||
|
{
|
||||||
|
u32 status = src_readl(dev, MUnit.OMR);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if the board failed any self tests.
|
||||||
|
*/
|
||||||
|
if (unlikely(status & SELF_TEST_FAILED))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if the board panic'd.
|
||||||
|
*/
|
||||||
|
if (unlikely(status & KERNEL_PANIC))
|
||||||
|
return (status >> 16) & 0xFF;
|
||||||
|
/*
|
||||||
|
* Wait for the adapter to be up and running.
|
||||||
|
*/
|
||||||
|
if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
|
||||||
|
return -3;
|
||||||
|
/*
|
||||||
|
* Everything is OK
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_deliver_message
|
||||||
|
* @fib: fib to issue
|
||||||
|
*
|
||||||
|
* Will send a fib, returning 0 if successful.
|
||||||
|
*/
|
||||||
|
static int aac_src_deliver_message(struct fib *fib)
|
||||||
|
{
|
||||||
|
struct aac_dev *dev = fib->dev;
|
||||||
|
struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
|
||||||
|
unsigned long qflags;
|
||||||
|
u32 fibsize;
|
||||||
|
u64 address;
|
||||||
|
struct aac_fib_xporthdr *pFibX;
|
||||||
|
|
||||||
|
spin_lock_irqsave(q->lock, qflags);
|
||||||
|
q->numpending++;
|
||||||
|
spin_unlock_irqrestore(q->lock, qflags);
|
||||||
|
|
||||||
|
/* Calculate the amount to the fibsize bits */
|
||||||
|
fibsize = (sizeof(struct aac_fib_xporthdr) +
|
||||||
|
fib->hw_fib_va->header.Size + 127) / 128 - 1;
|
||||||
|
if (fibsize > (ALIGN32 - 1))
|
||||||
|
fibsize = ALIGN32 - 1;
|
||||||
|
|
||||||
|
/* Fill XPORT header */
|
||||||
|
pFibX = (struct aac_fib_xporthdr *)
|
||||||
|
((unsigned char *)fib->hw_fib_va -
|
||||||
|
sizeof(struct aac_fib_xporthdr));
|
||||||
|
pFibX->Handle = fib->hw_fib_va->header.SenderData + 1;
|
||||||
|
pFibX->HostAddress = fib->hw_fib_pa;
|
||||||
|
pFibX->Size = fib->hw_fib_va->header.Size;
|
||||||
|
address = fib->hw_fib_pa - (u64)sizeof(struct aac_fib_xporthdr);
|
||||||
|
|
||||||
|
src_writel(dev, MUnit.IQ_H, (u32)(address >> 32));
|
||||||
|
src_writel(dev, MUnit.IQ_L, (u32)(address & 0xffffffff) + fibsize);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_ioremap
|
||||||
|
* @size: mapping resize request
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int aac_src_ioremap(struct aac_dev *dev, u32 size)
|
||||||
|
{
|
||||||
|
if (!size) {
|
||||||
|
iounmap(dev->regs.src.bar0);
|
||||||
|
dev->regs.src.bar0 = NULL;
|
||||||
|
iounmap(dev->base);
|
||||||
|
dev->base = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2),
|
||||||
|
AAC_MIN_SRC_BAR1_SIZE);
|
||||||
|
dev->base = NULL;
|
||||||
|
if (dev->regs.src.bar1 == NULL)
|
||||||
|
return -1;
|
||||||
|
dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base,
|
||||||
|
size);
|
||||||
|
if (dev->base == NULL) {
|
||||||
|
iounmap(dev->regs.src.bar1);
|
||||||
|
dev->regs.src.bar1 = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dev->IndexRegs = &((struct src_registers __iomem *)
|
||||||
|
dev->base)->IndexRegs;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int aac_src_restart_adapter(struct aac_dev *dev, int bled)
|
||||||
|
{
|
||||||
|
u32 var, reset_mask;
|
||||||
|
|
||||||
|
if (bled >= 0) {
|
||||||
|
if (bled)
|
||||||
|
printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
|
||||||
|
dev->name, dev->id, bled);
|
||||||
|
bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
|
||||||
|
0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL);
|
||||||
|
if (bled || (var != 0x00000001))
|
||||||
|
bled = -EINVAL;
|
||||||
|
if (dev->supplement_adapter_info.SupportedOptions2 &
|
||||||
|
AAC_OPTION_DOORBELL_RESET) {
|
||||||
|
src_writel(dev, MUnit.IDR, reset_mask);
|
||||||
|
msleep(5000); /* Delay 5 seconds */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (startup_timeout < 300)
|
||||||
|
startup_timeout = 300;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_select_comm - Select communications method
|
||||||
|
* @dev: Adapter
|
||||||
|
* @comm: communications method
|
||||||
|
*/
|
||||||
|
int aac_src_select_comm(struct aac_dev *dev, int comm)
|
||||||
|
{
|
||||||
|
switch (comm) {
|
||||||
|
case AAC_COMM_MESSAGE:
|
||||||
|
dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
|
||||||
|
dev->a_ops.adapter_intr = aac_src_intr_message;
|
||||||
|
dev->a_ops.adapter_deliver = aac_src_deliver_message;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac_src_init - initialize an Cardinal Frey Bar card
|
||||||
|
* @dev: device to configure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int aac_src_init(struct aac_dev *dev)
|
||||||
|
{
|
||||||
|
unsigned long start;
|
||||||
|
unsigned long status;
|
||||||
|
int restart = 0;
|
||||||
|
int instance = dev->id;
|
||||||
|
const char *name = dev->name;
|
||||||
|
|
||||||
|
dev->a_ops.adapter_ioremap = aac_src_ioremap;
|
||||||
|
dev->a_ops.adapter_comm = aac_src_select_comm;
|
||||||
|
|
||||||
|
dev->base_size = AAC_MIN_SRC_BAR0_SIZE;
|
||||||
|
if (aac_adapter_ioremap(dev, dev->base_size)) {
|
||||||
|
printk(KERN_WARNING "%s: unable to map adapter.\n", name);
|
||||||
|
goto error_iounmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failure to reset here is an option ... */
|
||||||
|
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
|
||||||
|
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
|
||||||
|
if ((aac_reset_devices || reset_devices) &&
|
||||||
|
!aac_src_restart_adapter(dev, 0))
|
||||||
|
++restart;
|
||||||
|
/*
|
||||||
|
* Check to see if the board panic'd while booting.
|
||||||
|
*/
|
||||||
|
status = src_readl(dev, MUnit.OMR);
|
||||||
|
if (status & KERNEL_PANIC) {
|
||||||
|
if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
|
||||||
|
goto error_iounmap;
|
||||||
|
++restart;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Check to see if the board failed any self tests.
|
||||||
|
*/
|
||||||
|
status = src_readl(dev, MUnit.OMR);
|
||||||
|
if (status & SELF_TEST_FAILED) {
|
||||||
|
printk(KERN_ERR "%s%d: adapter self-test failed.\n",
|
||||||
|
dev->name, instance);
|
||||||
|
goto error_iounmap;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Check to see if the monitor panic'd while booting.
|
||||||
|
*/
|
||||||
|
if (status & MONITOR_PANIC) {
|
||||||
|
printk(KERN_ERR "%s%d: adapter monitor panic.\n",
|
||||||
|
dev->name, instance);
|
||||||
|
goto error_iounmap;
|
||||||
|
}
|
||||||
|
start = jiffies;
|
||||||
|
/*
|
||||||
|
* Wait for the adapter to be up and running. Wait up to 3 minutes
|
||||||
|
*/
|
||||||
|
while (!((status = src_readl(dev, MUnit.OMR)) &
|
||||||
|
KERNEL_UP_AND_RUNNING)) {
|
||||||
|
if ((restart &&
|
||||||
|
(status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
|
||||||
|
time_after(jiffies, start+HZ*startup_timeout)) {
|
||||||
|
printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
|
||||||
|
dev->name, instance, status);
|
||||||
|
goto error_iounmap;
|
||||||
|
}
|
||||||
|
if (!restart &&
|
||||||
|
((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
|
||||||
|
time_after(jiffies, start + HZ *
|
||||||
|
((startup_timeout > 60)
|
||||||
|
? (startup_timeout - 60)
|
||||||
|
: (startup_timeout / 2))))) {
|
||||||
|
if (likely(!aac_src_restart_adapter(dev,
|
||||||
|
aac_src_check_health(dev))))
|
||||||
|
start = jiffies;
|
||||||
|
++restart;
|
||||||
|
}
|
||||||
|
msleep(1);
|
||||||
|
}
|
||||||
|
if (restart && aac_commit)
|
||||||
|
aac_commit = 1;
|
||||||
|
/*
|
||||||
|
* Fill in the common function dispatch table.
|
||||||
|
*/
|
||||||
|
dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
|
||||||
|
dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
|
||||||
|
dev->a_ops.adapter_notify = aac_src_notify_adapter;
|
||||||
|
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
|
||||||
|
dev->a_ops.adapter_check_health = aac_src_check_health;
|
||||||
|
dev->a_ops.adapter_restart = aac_src_restart_adapter;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First clear out all interrupts. Then enable the one's that we
|
||||||
|
* can handle.
|
||||||
|
*/
|
||||||
|
aac_adapter_comm(dev, AAC_COMM_MESSAGE);
|
||||||
|
aac_adapter_disable_int(dev);
|
||||||
|
src_writel(dev, MUnit.ODR_C, 0xffffffff);
|
||||||
|
aac_adapter_enable_int(dev);
|
||||||
|
|
||||||
|
if (aac_init_adapter(dev) == NULL)
|
||||||
|
goto error_iounmap;
|
||||||
|
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
|
||||||
|
goto error_iounmap;
|
||||||
|
|
||||||
|
dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
|
||||||
|
|
||||||
|
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
|
||||||
|
IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
|
||||||
|
|
||||||
|
if (dev->msi)
|
||||||
|
pci_disable_msi(dev->pdev);
|
||||||
|
|
||||||
|
printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
|
||||||
|
name, instance);
|
||||||
|
goto error_iounmap;
|
||||||
|
}
|
||||||
|
dev->dbg_base = pci_resource_start(dev->pdev, 2);
|
||||||
|
dev->dbg_base_mapped = dev->regs.src.bar1;
|
||||||
|
dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE;
|
||||||
|
|
||||||
|
aac_adapter_enable_int(dev);
|
||||||
|
/*
|
||||||
|
* Tell the adapter that all is configured, and it can
|
||||||
|
* start accepting requests
|
||||||
|
*/
|
||||||
|
aac_src_start_adapter(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_iounmap:
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
@ -62,7 +62,7 @@
|
|||||||
#include "bnx2fc_constants.h"
|
#include "bnx2fc_constants.h"
|
||||||
|
|
||||||
#define BNX2FC_NAME "bnx2fc"
|
#define BNX2FC_NAME "bnx2fc"
|
||||||
#define BNX2FC_VERSION "1.0.0"
|
#define BNX2FC_VERSION "1.0.1"
|
||||||
|
|
||||||
#define PFX "bnx2fc: "
|
#define PFX "bnx2fc: "
|
||||||
|
|
||||||
@ -84,9 +84,15 @@
|
|||||||
#define BNX2FC_NUM_MAX_SESS 128
|
#define BNX2FC_NUM_MAX_SESS 128
|
||||||
#define BNX2FC_NUM_MAX_SESS_LOG (ilog2(BNX2FC_NUM_MAX_SESS))
|
#define BNX2FC_NUM_MAX_SESS_LOG (ilog2(BNX2FC_NUM_MAX_SESS))
|
||||||
|
|
||||||
#define BNX2FC_MAX_OUTSTANDING_CMNDS 4096
|
#define BNX2FC_MAX_OUTSTANDING_CMNDS 2048
|
||||||
|
#define BNX2FC_CAN_QUEUE BNX2FC_MAX_OUTSTANDING_CMNDS
|
||||||
|
#define BNX2FC_ELSTM_XIDS BNX2FC_CAN_QUEUE
|
||||||
#define BNX2FC_MIN_PAYLOAD 256
|
#define BNX2FC_MIN_PAYLOAD 256
|
||||||
#define BNX2FC_MAX_PAYLOAD 2048
|
#define BNX2FC_MAX_PAYLOAD 2048
|
||||||
|
#define BNX2FC_MFS \
|
||||||
|
(BNX2FC_MAX_PAYLOAD + sizeof(struct fc_frame_header))
|
||||||
|
#define BNX2FC_MINI_JUMBO_MTU 2500
|
||||||
|
|
||||||
|
|
||||||
#define BNX2FC_RQ_BUF_SZ 256
|
#define BNX2FC_RQ_BUF_SZ 256
|
||||||
#define BNX2FC_RQ_BUF_LOG_SZ (ilog2(BNX2FC_RQ_BUF_SZ))
|
#define BNX2FC_RQ_BUF_LOG_SZ (ilog2(BNX2FC_RQ_BUF_SZ))
|
||||||
@ -98,7 +104,8 @@
|
|||||||
#define BNX2FC_CONFQ_WQE_SIZE (sizeof(struct fcoe_confqe))
|
#define BNX2FC_CONFQ_WQE_SIZE (sizeof(struct fcoe_confqe))
|
||||||
#define BNX2FC_5771X_DB_PAGE_SIZE 128
|
#define BNX2FC_5771X_DB_PAGE_SIZE 128
|
||||||
|
|
||||||
#define BNX2FC_MAX_TASKS BNX2FC_MAX_OUTSTANDING_CMNDS
|
#define BNX2FC_MAX_TASKS \
|
||||||
|
(BNX2FC_MAX_OUTSTANDING_CMNDS + BNX2FC_ELSTM_XIDS)
|
||||||
#define BNX2FC_TASK_SIZE 128
|
#define BNX2FC_TASK_SIZE 128
|
||||||
#define BNX2FC_TASKS_PER_PAGE (PAGE_SIZE/BNX2FC_TASK_SIZE)
|
#define BNX2FC_TASKS_PER_PAGE (PAGE_SIZE/BNX2FC_TASK_SIZE)
|
||||||
#define BNX2FC_TASK_CTX_ARR_SZ (BNX2FC_MAX_TASKS/BNX2FC_TASKS_PER_PAGE)
|
#define BNX2FC_TASK_CTX_ARR_SZ (BNX2FC_MAX_TASKS/BNX2FC_TASKS_PER_PAGE)
|
||||||
@ -112,10 +119,10 @@
|
|||||||
#define BNX2FC_WRITE (1 << 0)
|
#define BNX2FC_WRITE (1 << 0)
|
||||||
|
|
||||||
#define BNX2FC_MIN_XID 0
|
#define BNX2FC_MIN_XID 0
|
||||||
#define BNX2FC_MAX_XID (BNX2FC_MAX_OUTSTANDING_CMNDS - 1)
|
#define BNX2FC_MAX_XID \
|
||||||
#define FCOE_MIN_XID (BNX2FC_MAX_OUTSTANDING_CMNDS)
|
(BNX2FC_MAX_OUTSTANDING_CMNDS + BNX2FC_ELSTM_XIDS - 1)
|
||||||
#define FCOE_MAX_XID \
|
#define FCOE_MIN_XID (BNX2FC_MAX_XID + 1)
|
||||||
(BNX2FC_MAX_OUTSTANDING_CMNDS + (nr_cpu_ids * 256))
|
#define FCOE_MAX_XID (FCOE_MIN_XID + 4095)
|
||||||
#define BNX2FC_MAX_LUN 0xFFFF
|
#define BNX2FC_MAX_LUN 0xFFFF
|
||||||
#define BNX2FC_MAX_FCP_TGT 256
|
#define BNX2FC_MAX_FCP_TGT 256
|
||||||
#define BNX2FC_MAX_CMD_LEN 16
|
#define BNX2FC_MAX_CMD_LEN 16
|
||||||
@ -125,7 +132,6 @@
|
|||||||
|
|
||||||
#define BNX2FC_WAIT_CNT 120
|
#define BNX2FC_WAIT_CNT 120
|
||||||
#define BNX2FC_FW_TIMEOUT (3 * HZ)
|
#define BNX2FC_FW_TIMEOUT (3 * HZ)
|
||||||
|
|
||||||
#define PORT_MAX 2
|
#define PORT_MAX 2
|
||||||
|
|
||||||
#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status)
|
#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status)
|
||||||
|
@ -21,7 +21,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
|
|||||||
|
|
||||||
#define DRV_MODULE_NAME "bnx2fc"
|
#define DRV_MODULE_NAME "bnx2fc"
|
||||||
#define DRV_MODULE_VERSION BNX2FC_VERSION
|
#define DRV_MODULE_VERSION BNX2FC_VERSION
|
||||||
#define DRV_MODULE_RELDATE "Jan 25, 2011"
|
#define DRV_MODULE_RELDATE "Mar 17, 2011"
|
||||||
|
|
||||||
|
|
||||||
static char version[] __devinitdata =
|
static char version[] __devinitdata =
|
||||||
@ -437,17 +437,16 @@ static int bnx2fc_l2_rcv_thread(void *arg)
|
|||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
schedule();
|
schedule();
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
spin_lock_bh(&bg->fcoe_rx_list.lock);
|
spin_lock_bh(&bg->fcoe_rx_list.lock);
|
||||||
while ((skb = __skb_dequeue(&bg->fcoe_rx_list)) != NULL) {
|
while ((skb = __skb_dequeue(&bg->fcoe_rx_list)) != NULL) {
|
||||||
spin_unlock_bh(&bg->fcoe_rx_list.lock);
|
spin_unlock_bh(&bg->fcoe_rx_list.lock);
|
||||||
bnx2fc_recv_frame(skb);
|
bnx2fc_recv_frame(skb);
|
||||||
spin_lock_bh(&bg->fcoe_rx_list.lock);
|
spin_lock_bh(&bg->fcoe_rx_list.lock);
|
||||||
}
|
}
|
||||||
|
__set_current_state(TASK_INTERRUPTIBLE);
|
||||||
spin_unlock_bh(&bg->fcoe_rx_list.lock);
|
spin_unlock_bh(&bg->fcoe_rx_list.lock);
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
}
|
}
|
||||||
set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +568,6 @@ int bnx2fc_percpu_io_thread(void *arg)
|
|||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
schedule();
|
schedule();
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
spin_lock_bh(&p->fp_work_lock);
|
spin_lock_bh(&p->fp_work_lock);
|
||||||
while (!list_empty(&p->work_list)) {
|
while (!list_empty(&p->work_list)) {
|
||||||
list_splice_init(&p->work_list, &work_list);
|
list_splice_init(&p->work_list, &work_list);
|
||||||
@ -583,10 +581,10 @@ int bnx2fc_percpu_io_thread(void *arg)
|
|||||||
|
|
||||||
spin_lock_bh(&p->fp_work_lock);
|
spin_lock_bh(&p->fp_work_lock);
|
||||||
}
|
}
|
||||||
|
__set_current_state(TASK_INTERRUPTIBLE);
|
||||||
spin_unlock_bh(&p->fp_work_lock);
|
spin_unlock_bh(&p->fp_work_lock);
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
}
|
}
|
||||||
set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -661,31 +659,6 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bnx2fc_mfs_update(struct fc_lport *lport)
|
|
||||||
{
|
|
||||||
struct fcoe_port *port = lport_priv(lport);
|
|
||||||
struct bnx2fc_hba *hba = port->priv;
|
|
||||||
struct net_device *netdev = hba->netdev;
|
|
||||||
u32 mfs;
|
|
||||||
u32 max_mfs;
|
|
||||||
|
|
||||||
mfs = netdev->mtu - (sizeof(struct fcoe_hdr) +
|
|
||||||
sizeof(struct fcoe_crc_eof));
|
|
||||||
max_mfs = BNX2FC_MAX_PAYLOAD + sizeof(struct fc_frame_header);
|
|
||||||
BNX2FC_HBA_DBG(lport, "mfs = %d, max_mfs = %d\n", mfs, max_mfs);
|
|
||||||
if (mfs > max_mfs)
|
|
||||||
mfs = max_mfs;
|
|
||||||
|
|
||||||
/* Adjust mfs to be a multiple of 256 bytes */
|
|
||||||
mfs = (((mfs - sizeof(struct fc_frame_header)) / BNX2FC_MIN_PAYLOAD) *
|
|
||||||
BNX2FC_MIN_PAYLOAD);
|
|
||||||
mfs = mfs + sizeof(struct fc_frame_header);
|
|
||||||
|
|
||||||
BNX2FC_HBA_DBG(lport, "Set MFS = %d\n", mfs);
|
|
||||||
if (fc_set_mfs(lport, mfs))
|
|
||||||
return -EINVAL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static void bnx2fc_link_speed_update(struct fc_lport *lport)
|
static void bnx2fc_link_speed_update(struct fc_lport *lport)
|
||||||
{
|
{
|
||||||
struct fcoe_port *port = lport_priv(lport);
|
struct fcoe_port *port = lport_priv(lport);
|
||||||
@ -754,7 +727,7 @@ static int bnx2fc_net_config(struct fc_lport *lport)
|
|||||||
!hba->phys_dev->ethtool_ops->get_pauseparam)
|
!hba->phys_dev->ethtool_ops->get_pauseparam)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (bnx2fc_mfs_update(lport))
|
if (fc_set_mfs(lport, BNX2FC_MFS))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
skb_queue_head_init(&port->fcoe_pending_queue);
|
skb_queue_head_init(&port->fcoe_pending_queue);
|
||||||
@ -825,14 +798,6 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event)
|
|||||||
if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
|
if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
|
||||||
printk(KERN_ERR "indicate_netevent: "\
|
printk(KERN_ERR "indicate_netevent: "\
|
||||||
"adapter is not UP!!\n");
|
"adapter is not UP!!\n");
|
||||||
/* fall thru to update mfs if MTU has changed */
|
|
||||||
case NETDEV_CHANGEMTU:
|
|
||||||
BNX2FC_HBA_DBG(lport, "NETDEV_CHANGEMTU event\n");
|
|
||||||
bnx2fc_mfs_update(lport);
|
|
||||||
mutex_lock(&lport->lp_mutex);
|
|
||||||
list_for_each_entry(vport, &lport->vports, list)
|
|
||||||
bnx2fc_mfs_update(vport);
|
|
||||||
mutex_unlock(&lport->lp_mutex);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NETDEV_DOWN:
|
case NETDEV_DOWN:
|
||||||
@ -1095,13 +1060,6 @@ static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
|
|||||||
struct netdev_hw_addr *ha;
|
struct netdev_hw_addr *ha;
|
||||||
int sel_san_mac = 0;
|
int sel_san_mac = 0;
|
||||||
|
|
||||||
/* Do not support for bonding device */
|
|
||||||
if ((netdev->priv_flags & IFF_MASTER_ALB) ||
|
|
||||||
(netdev->priv_flags & IFF_SLAVE_INACTIVE) ||
|
|
||||||
(netdev->priv_flags & IFF_MASTER_8023AD)) {
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup Source MAC Address */
|
/* setup Source MAC Address */
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for_each_dev_addr(physdev, ha) {
|
for_each_dev_addr(physdev, ha) {
|
||||||
@ -1432,16 +1390,9 @@ static int bnx2fc_destroy(struct net_device *netdev)
|
|||||||
struct net_device *phys_dev;
|
struct net_device *phys_dev;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!rtnl_trylock())
|
rtnl_lock();
|
||||||
return restart_syscall();
|
|
||||||
|
|
||||||
mutex_lock(&bnx2fc_dev_lock);
|
mutex_lock(&bnx2fc_dev_lock);
|
||||||
#ifdef CONFIG_SCSI_BNX2X_FCOE_MODULE
|
|
||||||
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
|
|
||||||
rc = -ENODEV;
|
|
||||||
goto netdev_err;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* obtain physical netdev */
|
/* obtain physical netdev */
|
||||||
if (netdev->priv_flags & IFF_802_1Q_VLAN)
|
if (netdev->priv_flags & IFF_802_1Q_VLAN)
|
||||||
phys_dev = vlan_dev_real_dev(netdev);
|
phys_dev = vlan_dev_real_dev(netdev);
|
||||||
@ -1805,18 +1756,10 @@ static int bnx2fc_disable(struct net_device *netdev)
|
|||||||
struct ethtool_drvinfo drvinfo;
|
struct ethtool_drvinfo drvinfo;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!rtnl_trylock()) {
|
rtnl_lock();
|
||||||
printk(KERN_ERR PFX "retrying for rtnl_lock\n");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(&bnx2fc_dev_lock);
|
mutex_lock(&bnx2fc_dev_lock);
|
||||||
|
|
||||||
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
|
|
||||||
rc = -ENODEV;
|
|
||||||
goto nodev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* obtain physical netdev */
|
/* obtain physical netdev */
|
||||||
if (netdev->priv_flags & IFF_802_1Q_VLAN)
|
if (netdev->priv_flags & IFF_802_1Q_VLAN)
|
||||||
phys_dev = vlan_dev_real_dev(netdev);
|
phys_dev = vlan_dev_real_dev(netdev);
|
||||||
@ -1867,19 +1810,11 @@ static int bnx2fc_enable(struct net_device *netdev)
|
|||||||
struct ethtool_drvinfo drvinfo;
|
struct ethtool_drvinfo drvinfo;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!rtnl_trylock()) {
|
rtnl_lock();
|
||||||
printk(KERN_ERR PFX "retrying for rtnl_lock\n");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
BNX2FC_MISC_DBG("Entered %s\n", __func__);
|
BNX2FC_MISC_DBG("Entered %s\n", __func__);
|
||||||
mutex_lock(&bnx2fc_dev_lock);
|
mutex_lock(&bnx2fc_dev_lock);
|
||||||
|
|
||||||
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
|
|
||||||
rc = -ENODEV;
|
|
||||||
goto nodev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* obtain physical netdev */
|
/* obtain physical netdev */
|
||||||
if (netdev->priv_flags & IFF_802_1Q_VLAN)
|
if (netdev->priv_flags & IFF_802_1Q_VLAN)
|
||||||
phys_dev = vlan_dev_real_dev(netdev);
|
phys_dev = vlan_dev_real_dev(netdev);
|
||||||
@ -1942,18 +1877,9 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rtnl_trylock()) {
|
rtnl_lock();
|
||||||
printk(KERN_ERR "trying for rtnl_lock\n");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
mutex_lock(&bnx2fc_dev_lock);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SCSI_BNX2X_FCOE_MODULE
|
mutex_lock(&bnx2fc_dev_lock);
|
||||||
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
|
|
||||||
rc = -ENODEV;
|
|
||||||
goto mod_err;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!try_module_get(THIS_MODULE)) {
|
if (!try_module_get(THIS_MODULE)) {
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
@ -2506,7 +2432,7 @@ static struct scsi_host_template bnx2fc_shost_template = {
|
|||||||
.change_queue_type = fc_change_queue_type,
|
.change_queue_type = fc_change_queue_type,
|
||||||
.this_id = -1,
|
.this_id = -1,
|
||||||
.cmd_per_lun = 3,
|
.cmd_per_lun = 3,
|
||||||
.can_queue = (BNX2FC_MAX_OUTSTANDING_CMNDS/2),
|
.can_queue = BNX2FC_CAN_QUEUE,
|
||||||
.use_clustering = ENABLE_CLUSTERING,
|
.use_clustering = ENABLE_CLUSTERING,
|
||||||
.sg_tablesize = BNX2FC_MAX_BDS_PER_CMD,
|
.sg_tablesize = BNX2FC_MAX_BDS_PER_CMD,
|
||||||
.max_sectors = 512,
|
.max_sectors = 512,
|
||||||
|
@ -87,7 +87,7 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
|
|||||||
fcoe_init1.task_list_pbl_addr_lo = (u32) hba->task_ctx_bd_dma;
|
fcoe_init1.task_list_pbl_addr_lo = (u32) hba->task_ctx_bd_dma;
|
||||||
fcoe_init1.task_list_pbl_addr_hi =
|
fcoe_init1.task_list_pbl_addr_hi =
|
||||||
(u32) ((u64) hba->task_ctx_bd_dma >> 32);
|
(u32) ((u64) hba->task_ctx_bd_dma >> 32);
|
||||||
fcoe_init1.mtu = hba->netdev->mtu;
|
fcoe_init1.mtu = BNX2FC_MINI_JUMBO_MTU;
|
||||||
|
|
||||||
fcoe_init1.flags = (PAGE_SHIFT <<
|
fcoe_init1.flags = (PAGE_SHIFT <<
|
||||||
FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT);
|
FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT);
|
||||||
@ -590,7 +590,10 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
|
|||||||
|
|
||||||
num_rq = (frame_len + BNX2FC_RQ_BUF_SZ - 1) / BNX2FC_RQ_BUF_SZ;
|
num_rq = (frame_len + BNX2FC_RQ_BUF_SZ - 1) / BNX2FC_RQ_BUF_SZ;
|
||||||
|
|
||||||
|
spin_lock_bh(&tgt->tgt_lock);
|
||||||
rq_data = (unsigned char *)bnx2fc_get_next_rqe(tgt, num_rq);
|
rq_data = (unsigned char *)bnx2fc_get_next_rqe(tgt, num_rq);
|
||||||
|
spin_unlock_bh(&tgt->tgt_lock);
|
||||||
|
|
||||||
if (rq_data) {
|
if (rq_data) {
|
||||||
buf = rq_data;
|
buf = rq_data;
|
||||||
} else {
|
} else {
|
||||||
@ -603,8 +606,10 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_rq; i++) {
|
for (i = 0; i < num_rq; i++) {
|
||||||
|
spin_lock_bh(&tgt->tgt_lock);
|
||||||
rq_data = (unsigned char *)
|
rq_data = (unsigned char *)
|
||||||
bnx2fc_get_next_rqe(tgt, 1);
|
bnx2fc_get_next_rqe(tgt, 1);
|
||||||
|
spin_unlock_bh(&tgt->tgt_lock);
|
||||||
len = BNX2FC_RQ_BUF_SZ;
|
len = BNX2FC_RQ_BUF_SZ;
|
||||||
memcpy(buf1, rq_data, len);
|
memcpy(buf1, rq_data, len);
|
||||||
buf1 += len;
|
buf1 += len;
|
||||||
@ -615,13 +620,15 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
|
|||||||
|
|
||||||
if (buf != rq_data)
|
if (buf != rq_data)
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
spin_lock_bh(&tgt->tgt_lock);
|
||||||
bnx2fc_return_rqe(tgt, num_rq);
|
bnx2fc_return_rqe(tgt, num_rq);
|
||||||
|
spin_unlock_bh(&tgt->tgt_lock);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FCOE_ERROR_DETECTION_CQE_TYPE:
|
case FCOE_ERROR_DETECTION_CQE_TYPE:
|
||||||
/*
|
/*
|
||||||
*In case of error reporting CQE a single RQ entry
|
* In case of error reporting CQE a single RQ entry
|
||||||
* is consumes.
|
* is consumed.
|
||||||
*/
|
*/
|
||||||
spin_lock_bh(&tgt->tgt_lock);
|
spin_lock_bh(&tgt->tgt_lock);
|
||||||
num_rq = 1;
|
num_rq = 1;
|
||||||
@ -705,6 +712,7 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
|
|||||||
*In case of warning reporting CQE a single RQ entry
|
*In case of warning reporting CQE a single RQ entry
|
||||||
* is consumes.
|
* is consumes.
|
||||||
*/
|
*/
|
||||||
|
spin_lock_bh(&tgt->tgt_lock);
|
||||||
num_rq = 1;
|
num_rq = 1;
|
||||||
err_entry = (struct fcoe_err_report_entry *)
|
err_entry = (struct fcoe_err_report_entry *)
|
||||||
bnx2fc_get_next_rqe(tgt, 1);
|
bnx2fc_get_next_rqe(tgt, 1);
|
||||||
@ -717,6 +725,7 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
|
|||||||
err_entry->tx_buf_off, err_entry->rx_buf_off);
|
err_entry->tx_buf_off, err_entry->rx_buf_off);
|
||||||
|
|
||||||
bnx2fc_return_rqe(tgt, 1);
|
bnx2fc_return_rqe(tgt, 1);
|
||||||
|
spin_unlock_bh(&tgt->tgt_lock);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "bnx2fc.h"
|
#include "bnx2fc.h"
|
||||||
|
|
||||||
|
#define RESERVE_FREE_LIST_INDEX num_possible_cpus()
|
||||||
|
|
||||||
static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
|
static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
|
||||||
int bd_index);
|
int bd_index);
|
||||||
static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req);
|
static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req);
|
||||||
@ -242,8 +245,9 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
|
|||||||
u32 mem_size;
|
u32 mem_size;
|
||||||
u16 xid;
|
u16 xid;
|
||||||
int i;
|
int i;
|
||||||
int num_ios;
|
int num_ios, num_pri_ios;
|
||||||
size_t bd_tbl_sz;
|
size_t bd_tbl_sz;
|
||||||
|
int arr_sz = num_possible_cpus() + 1;
|
||||||
|
|
||||||
if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
|
if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
|
||||||
printk(KERN_ERR PFX "cmd_mgr_alloc: Invalid min_xid 0x%x \
|
printk(KERN_ERR PFX "cmd_mgr_alloc: Invalid min_xid 0x%x \
|
||||||
@ -263,14 +267,14 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmgr->free_list = kzalloc(sizeof(*cmgr->free_list) *
|
cmgr->free_list = kzalloc(sizeof(*cmgr->free_list) *
|
||||||
num_possible_cpus(), GFP_KERNEL);
|
arr_sz, GFP_KERNEL);
|
||||||
if (!cmgr->free_list) {
|
if (!cmgr->free_list) {
|
||||||
printk(KERN_ERR PFX "failed to alloc free_list\n");
|
printk(KERN_ERR PFX "failed to alloc free_list\n");
|
||||||
goto mem_err;
|
goto mem_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmgr->free_list_lock = kzalloc(sizeof(*cmgr->free_list_lock) *
|
cmgr->free_list_lock = kzalloc(sizeof(*cmgr->free_list_lock) *
|
||||||
num_possible_cpus(), GFP_KERNEL);
|
arr_sz, GFP_KERNEL);
|
||||||
if (!cmgr->free_list_lock) {
|
if (!cmgr->free_list_lock) {
|
||||||
printk(KERN_ERR PFX "failed to alloc free_list_lock\n");
|
printk(KERN_ERR PFX "failed to alloc free_list_lock\n");
|
||||||
goto mem_err;
|
goto mem_err;
|
||||||
@ -279,13 +283,18 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
|
|||||||
cmgr->hba = hba;
|
cmgr->hba = hba;
|
||||||
cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1);
|
cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1);
|
||||||
|
|
||||||
for (i = 0; i < num_possible_cpus(); i++) {
|
for (i = 0; i < arr_sz; i++) {
|
||||||
INIT_LIST_HEAD(&cmgr->free_list[i]);
|
INIT_LIST_HEAD(&cmgr->free_list[i]);
|
||||||
spin_lock_init(&cmgr->free_list_lock[i]);
|
spin_lock_init(&cmgr->free_list_lock[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pre-allocated pool of bnx2fc_cmds */
|
/*
|
||||||
|
* Pre-allocated pool of bnx2fc_cmds.
|
||||||
|
* Last entry in the free list array is the free list
|
||||||
|
* of slow path requests.
|
||||||
|
*/
|
||||||
xid = BNX2FC_MIN_XID;
|
xid = BNX2FC_MIN_XID;
|
||||||
|
num_pri_ios = num_ios - BNX2FC_ELSTM_XIDS;
|
||||||
for (i = 0; i < num_ios; i++) {
|
for (i = 0; i < num_ios; i++) {
|
||||||
io_req = kzalloc(sizeof(*io_req), GFP_KERNEL);
|
io_req = kzalloc(sizeof(*io_req), GFP_KERNEL);
|
||||||
|
|
||||||
@ -298,11 +307,13 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
|
|||||||
INIT_DELAYED_WORK(&io_req->timeout_work, bnx2fc_cmd_timeout);
|
INIT_DELAYED_WORK(&io_req->timeout_work, bnx2fc_cmd_timeout);
|
||||||
|
|
||||||
io_req->xid = xid++;
|
io_req->xid = xid++;
|
||||||
if (io_req->xid >= BNX2FC_MAX_OUTSTANDING_CMNDS)
|
if (i < num_pri_ios)
|
||||||
printk(KERN_ERR PFX "ERROR allocating xids - 0x%x\n",
|
list_add_tail(&io_req->link,
|
||||||
io_req->xid);
|
&cmgr->free_list[io_req->xid %
|
||||||
list_add_tail(&io_req->link,
|
num_possible_cpus()]);
|
||||||
&cmgr->free_list[io_req->xid % num_possible_cpus()]);
|
else
|
||||||
|
list_add_tail(&io_req->link,
|
||||||
|
&cmgr->free_list[num_possible_cpus()]);
|
||||||
io_req++;
|
io_req++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +400,7 @@ free_cmd_pool:
|
|||||||
if (!cmgr->free_list)
|
if (!cmgr->free_list)
|
||||||
goto free_cmgr;
|
goto free_cmgr;
|
||||||
|
|
||||||
for (i = 0; i < num_possible_cpus(); i++) {
|
for (i = 0; i < num_possible_cpus() + 1; i++) {
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
|
|
||||||
@ -413,6 +424,7 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
|
|||||||
struct bnx2fc_cmd *io_req;
|
struct bnx2fc_cmd *io_req;
|
||||||
struct list_head *listp;
|
struct list_head *listp;
|
||||||
struct io_bdt *bd_tbl;
|
struct io_bdt *bd_tbl;
|
||||||
|
int index = RESERVE_FREE_LIST_INDEX;
|
||||||
u32 max_sqes;
|
u32 max_sqes;
|
||||||
u16 xid;
|
u16 xid;
|
||||||
|
|
||||||
@ -432,26 +444,26 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
|
|||||||
* NOTE: Free list insertions and deletions are protected with
|
* NOTE: Free list insertions and deletions are protected with
|
||||||
* cmgr lock
|
* cmgr lock
|
||||||
*/
|
*/
|
||||||
spin_lock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
|
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
|
||||||
if ((list_empty(&(cmd_mgr->free_list[smp_processor_id()]))) ||
|
if ((list_empty(&(cmd_mgr->free_list[index]))) ||
|
||||||
(tgt->num_active_ios.counter >= max_sqes)) {
|
(tgt->num_active_ios.counter >= max_sqes)) {
|
||||||
BNX2FC_TGT_DBG(tgt, "No free els_tm cmds available "
|
BNX2FC_TGT_DBG(tgt, "No free els_tm cmds available "
|
||||||
"ios(%d):sqes(%d)\n",
|
"ios(%d):sqes(%d)\n",
|
||||||
tgt->num_active_ios.counter, tgt->max_sqes);
|
tgt->num_active_ios.counter, tgt->max_sqes);
|
||||||
if (list_empty(&(cmd_mgr->free_list[smp_processor_id()])))
|
if (list_empty(&(cmd_mgr->free_list[index])))
|
||||||
printk(KERN_ERR PFX "elstm_alloc: list_empty\n");
|
printk(KERN_ERR PFX "elstm_alloc: list_empty\n");
|
||||||
spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
|
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
listp = (struct list_head *)
|
listp = (struct list_head *)
|
||||||
cmd_mgr->free_list[smp_processor_id()].next;
|
cmd_mgr->free_list[index].next;
|
||||||
list_del_init(listp);
|
list_del_init(listp);
|
||||||
io_req = (struct bnx2fc_cmd *) listp;
|
io_req = (struct bnx2fc_cmd *) listp;
|
||||||
xid = io_req->xid;
|
xid = io_req->xid;
|
||||||
cmd_mgr->cmds[xid] = io_req;
|
cmd_mgr->cmds[xid] = io_req;
|
||||||
atomic_inc(&tgt->num_active_ios);
|
atomic_inc(&tgt->num_active_ios);
|
||||||
spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
|
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&io_req->link);
|
INIT_LIST_HEAD(&io_req->link);
|
||||||
|
|
||||||
@ -479,27 +491,30 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
|
|||||||
struct io_bdt *bd_tbl;
|
struct io_bdt *bd_tbl;
|
||||||
u32 max_sqes;
|
u32 max_sqes;
|
||||||
u16 xid;
|
u16 xid;
|
||||||
|
int index = get_cpu();
|
||||||
|
|
||||||
max_sqes = BNX2FC_SCSI_MAX_SQES;
|
max_sqes = BNX2FC_SCSI_MAX_SQES;
|
||||||
/*
|
/*
|
||||||
* NOTE: Free list insertions and deletions are protected with
|
* NOTE: Free list insertions and deletions are protected with
|
||||||
* cmgr lock
|
* cmgr lock
|
||||||
*/
|
*/
|
||||||
spin_lock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
|
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
|
||||||
if ((list_empty(&cmd_mgr->free_list[smp_processor_id()])) ||
|
if ((list_empty(&cmd_mgr->free_list[index])) ||
|
||||||
(tgt->num_active_ios.counter >= max_sqes)) {
|
(tgt->num_active_ios.counter >= max_sqes)) {
|
||||||
spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
|
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
|
||||||
|
put_cpu();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
listp = (struct list_head *)
|
listp = (struct list_head *)
|
||||||
cmd_mgr->free_list[smp_processor_id()].next;
|
cmd_mgr->free_list[index].next;
|
||||||
list_del_init(listp);
|
list_del_init(listp);
|
||||||
io_req = (struct bnx2fc_cmd *) listp;
|
io_req = (struct bnx2fc_cmd *) listp;
|
||||||
xid = io_req->xid;
|
xid = io_req->xid;
|
||||||
cmd_mgr->cmds[xid] = io_req;
|
cmd_mgr->cmds[xid] = io_req;
|
||||||
atomic_inc(&tgt->num_active_ios);
|
atomic_inc(&tgt->num_active_ios);
|
||||||
spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
|
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
|
||||||
|
put_cpu();
|
||||||
|
|
||||||
INIT_LIST_HEAD(&io_req->link);
|
INIT_LIST_HEAD(&io_req->link);
|
||||||
|
|
||||||
@ -522,8 +537,15 @@ void bnx2fc_cmd_release(struct kref *ref)
|
|||||||
struct bnx2fc_cmd *io_req = container_of(ref,
|
struct bnx2fc_cmd *io_req = container_of(ref,
|
||||||
struct bnx2fc_cmd, refcount);
|
struct bnx2fc_cmd, refcount);
|
||||||
struct bnx2fc_cmd_mgr *cmd_mgr = io_req->cmd_mgr;
|
struct bnx2fc_cmd_mgr *cmd_mgr = io_req->cmd_mgr;
|
||||||
|
int index;
|
||||||
|
|
||||||
spin_lock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
|
if (io_req->cmd_type == BNX2FC_SCSI_CMD)
|
||||||
|
index = io_req->xid % num_possible_cpus();
|
||||||
|
else
|
||||||
|
index = RESERVE_FREE_LIST_INDEX;
|
||||||
|
|
||||||
|
|
||||||
|
spin_lock_bh(&cmd_mgr->free_list_lock[index]);
|
||||||
if (io_req->cmd_type != BNX2FC_SCSI_CMD)
|
if (io_req->cmd_type != BNX2FC_SCSI_CMD)
|
||||||
bnx2fc_free_mp_resc(io_req);
|
bnx2fc_free_mp_resc(io_req);
|
||||||
cmd_mgr->cmds[io_req->xid] = NULL;
|
cmd_mgr->cmds[io_req->xid] = NULL;
|
||||||
@ -531,9 +553,10 @@ void bnx2fc_cmd_release(struct kref *ref)
|
|||||||
list_del_init(&io_req->link);
|
list_del_init(&io_req->link);
|
||||||
/* Add it to the free list */
|
/* Add it to the free list */
|
||||||
list_add(&io_req->link,
|
list_add(&io_req->link,
|
||||||
&cmd_mgr->free_list[smp_processor_id()]);
|
&cmd_mgr->free_list[index]);
|
||||||
atomic_dec(&io_req->tgt->num_active_ios);
|
atomic_dec(&io_req->tgt->num_active_ios);
|
||||||
spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
|
spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req)
|
static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req)
|
||||||
|
@ -304,10 +304,8 @@ static void bnx2fc_upload_session(struct fcoe_port *port,
|
|||||||
" not sent to FW\n");
|
" not sent to FW\n");
|
||||||
|
|
||||||
/* Free session resources */
|
/* Free session resources */
|
||||||
spin_lock_bh(&tgt->cq_lock);
|
|
||||||
bnx2fc_free_session_resc(hba, tgt);
|
bnx2fc_free_session_resc(hba, tgt);
|
||||||
bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
|
bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
|
||||||
spin_unlock_bh(&tgt->cq_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
|
static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
|
||||||
@ -830,11 +828,13 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
|
|||||||
tgt->rq = NULL;
|
tgt->rq = NULL;
|
||||||
}
|
}
|
||||||
/* Free CQ */
|
/* Free CQ */
|
||||||
|
spin_lock_bh(&tgt->cq_lock);
|
||||||
if (tgt->cq) {
|
if (tgt->cq) {
|
||||||
dma_free_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
|
dma_free_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
|
||||||
tgt->cq, tgt->cq_dma);
|
tgt->cq, tgt->cq_dma);
|
||||||
tgt->cq = NULL;
|
tgt->cq = NULL;
|
||||||
}
|
}
|
||||||
|
spin_unlock_bh(&tgt->cq_lock);
|
||||||
/* Free SQ */
|
/* Free SQ */
|
||||||
if (tgt->sq) {
|
if (tgt->sq) {
|
||||||
dma_free_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
|
dma_free_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
|
||||||
|
@ -132,14 +132,25 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
|
|||||||
if (page_count(sg_page(sg)) >= 1 && !recv)
|
if (page_count(sg_page(sg)) >= 1 && !recv)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
|
if (recv) {
|
||||||
|
segment->atomic_mapped = true;
|
||||||
|
segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
|
||||||
|
} else {
|
||||||
|
segment->atomic_mapped = false;
|
||||||
|
/* the xmit path can sleep with the page mapped so use kmap */
|
||||||
|
segment->sg_mapped = kmap(sg_page(sg));
|
||||||
|
}
|
||||||
|
|
||||||
segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
|
segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
|
void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
|
||||||
{
|
{
|
||||||
if (segment->sg_mapped) {
|
if (segment->sg_mapped) {
|
||||||
kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
|
if (segment->atomic_mapped)
|
||||||
|
kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
|
||||||
|
else
|
||||||
|
kunmap(sg_page(segment->sg));
|
||||||
segment->sg_mapped = NULL;
|
segment->sg_mapped = NULL;
|
||||||
segment->data = NULL;
|
segment->data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#/*******************************************************************
|
#/*******************************************************************
|
||||||
# * This file is part of the Emulex Linux Device Driver for *
|
# * This file is part of the Emulex Linux Device Driver for *
|
||||||
# * Fibre Channel Host Bus Adapters. *
|
# * Fibre Channel Host Bus Adapters. *
|
||||||
# * Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
# * Copyright (C) 2004-2011 Emulex. All rights reserved. *
|
||||||
# * EMULEX and SLI are trademarks of Emulex. *
|
# * EMULEX and SLI are trademarks of Emulex. *
|
||||||
# * www.emulex.com *
|
# * www.emulex.com *
|
||||||
# * *
|
# * *
|
||||||
|
@ -539,6 +539,8 @@ struct lpfc_hba {
|
|||||||
(struct lpfc_hba *, uint32_t);
|
(struct lpfc_hba *, uint32_t);
|
||||||
int (*lpfc_hba_down_link)
|
int (*lpfc_hba_down_link)
|
||||||
(struct lpfc_hba *, uint32_t);
|
(struct lpfc_hba *, uint32_t);
|
||||||
|
int (*lpfc_selective_reset)
|
||||||
|
(struct lpfc_hba *);
|
||||||
|
|
||||||
/* SLI4 specific HBA data structure */
|
/* SLI4 specific HBA data structure */
|
||||||
struct lpfc_sli4_hba sli4_hba;
|
struct lpfc_sli4_hba sli4_hba;
|
||||||
@ -895,7 +897,18 @@ lpfc_worker_wake_up(struct lpfc_hba *phba)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline int
|
||||||
|
lpfc_readl(void __iomem *addr, uint32_t *data)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
temp = readl(addr);
|
||||||
|
if (temp == 0xffffffff)
|
||||||
|
return -EIO;
|
||||||
|
*data = temp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
lpfc_sli_read_hs(struct lpfc_hba *phba)
|
lpfc_sli_read_hs(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -904,15 +917,17 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
|
|||||||
*/
|
*/
|
||||||
phba->sli.slistat.err_attn_event++;
|
phba->sli.slistat.err_attn_event++;
|
||||||
|
|
||||||
/* Save status info */
|
/* Save status info and check for unplug error */
|
||||||
phba->work_hs = readl(phba->HSregaddr);
|
if (lpfc_readl(phba->HSregaddr, &phba->work_hs) ||
|
||||||
phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
|
lpfc_readl(phba->MBslimaddr + 0xa8, &phba->work_status[0]) ||
|
||||||
phba->work_status[1] = readl(phba->MBslimaddr + 0xac);
|
lpfc_readl(phba->MBslimaddr + 0xac, &phba->work_status[1])) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
/* Clear chip Host Attention error bit */
|
/* Clear chip Host Attention error bit */
|
||||||
writel(HA_ERATT, phba->HAregaddr);
|
writel(HA_ERATT, phba->HAregaddr);
|
||||||
readl(phba->HAregaddr); /* flush */
|
readl(phba->HAregaddr); /* flush */
|
||||||
phba->pport->stopped = 1;
|
phba->pport->stopped = 1;
|
||||||
|
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -685,7 +685,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
|
|||||||
* -EIO reset not configured or error posting the event
|
* -EIO reset not configured or error posting the event
|
||||||
* zero for success
|
* zero for success
|
||||||
**/
|
**/
|
||||||
static int
|
int
|
||||||
lpfc_selective_reset(struct lpfc_hba *phba)
|
lpfc_selective_reset(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
struct completion online_compl;
|
struct completion online_compl;
|
||||||
@ -746,7 +746,7 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
|
|||||||
int status = -EINVAL;
|
int status = -EINVAL;
|
||||||
|
|
||||||
if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
|
if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
|
||||||
status = lpfc_selective_reset(phba);
|
status = phba->lpfc_selective_reset(phba);
|
||||||
|
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
return strlen(buf);
|
return strlen(buf);
|
||||||
@ -1224,7 +1224,10 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,
|
|||||||
if (val & ENABLE_FCP_RING_POLLING) {
|
if (val & ENABLE_FCP_RING_POLLING) {
|
||||||
if ((val & DISABLE_FCP_RING_INT) &&
|
if ((val & DISABLE_FCP_RING_INT) &&
|
||||||
!(old_val & DISABLE_FCP_RING_INT)) {
|
!(old_val & DISABLE_FCP_RING_INT)) {
|
||||||
creg_val = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &creg_val)) {
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
|
creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
|
||||||
writel(creg_val, phba->HCregaddr);
|
writel(creg_val, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
@ -1242,7 +1245,10 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,
|
|||||||
spin_unlock_irq(&phba->hbalock);
|
spin_unlock_irq(&phba->hbalock);
|
||||||
del_timer(&phba->fcp_poll_timer);
|
del_timer(&phba->fcp_poll_timer);
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
creg_val = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &creg_val)) {
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
||||||
writel(creg_val, phba->HCregaddr);
|
writel(creg_val, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* This file is part of the Emulex Linux Device Driver for *
|
* This file is part of the Emulex Linux Device Driver for *
|
||||||
* Fibre Channel Host Bus Adapters. *
|
* Fibre Channel Host Bus Adapters. *
|
||||||
* Copyright (C) 2009-2010 Emulex. All rights reserved. *
|
* Copyright (C) 2009-2011 Emulex. All rights reserved. *
|
||||||
* EMULEX and SLI are trademarks of Emulex. *
|
* EMULEX and SLI are trademarks of Emulex. *
|
||||||
* www.emulex.com *
|
* www.emulex.com *
|
||||||
* *
|
* *
|
||||||
@ -348,7 +348,10 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
|
|||||||
dd_data->context_un.iocb.bmp = bmp;
|
dd_data->context_un.iocb.bmp = bmp;
|
||||||
|
|
||||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||||
creg_val = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &creg_val)) {
|
||||||
|
rc = -EIO ;
|
||||||
|
goto free_cmdiocbq;
|
||||||
|
}
|
||||||
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
||||||
writel(creg_val, phba->HCregaddr);
|
writel(creg_val, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
@ -599,7 +602,10 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
|
|||||||
dd_data->context_un.iocb.ndlp = ndlp;
|
dd_data->context_un.iocb.ndlp = ndlp;
|
||||||
|
|
||||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||||
creg_val = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &creg_val)) {
|
||||||
|
rc = -EIO;
|
||||||
|
goto linkdown_err;
|
||||||
|
}
|
||||||
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
||||||
writel(creg_val, phba->HCregaddr);
|
writel(creg_val, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
@ -613,6 +619,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
|
|||||||
else
|
else
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
|
|
||||||
|
linkdown_err:
|
||||||
pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
|
pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
|
||||||
job->request_payload.sg_cnt, DMA_TO_DEVICE);
|
job->request_payload.sg_cnt, DMA_TO_DEVICE);
|
||||||
pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
|
pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
|
||||||
@ -1357,7 +1364,10 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
|
|||||||
dd_data->context_un.iocb.ndlp = ndlp;
|
dd_data->context_un.iocb.ndlp = ndlp;
|
||||||
|
|
||||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||||
creg_val = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &creg_val)) {
|
||||||
|
rc = -IOCB_ERROR;
|
||||||
|
goto issue_ct_rsp_exit;
|
||||||
|
}
|
||||||
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
||||||
writel(creg_val, phba->HCregaddr);
|
writel(creg_val, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
@ -2479,16 +2489,18 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
|
|||||||
|
|
||||||
from = (uint8_t *)dd_data->context_un.mbox.mb;
|
from = (uint8_t *)dd_data->context_un.mbox.mb;
|
||||||
job = dd_data->context_un.mbox.set_job;
|
job = dd_data->context_un.mbox.set_job;
|
||||||
size = job->reply_payload.payload_len;
|
if (job) {
|
||||||
job->reply->reply_payload_rcv_len =
|
size = job->reply_payload.payload_len;
|
||||||
sg_copy_from_buffer(job->reply_payload.sg_list,
|
job->reply->reply_payload_rcv_len =
|
||||||
job->reply_payload.sg_cnt,
|
sg_copy_from_buffer(job->reply_payload.sg_list,
|
||||||
from, size);
|
job->reply_payload.sg_cnt,
|
||||||
job->reply->result = 0;
|
from, size);
|
||||||
|
job->reply->result = 0;
|
||||||
|
|
||||||
|
job->dd_data = NULL;
|
||||||
|
job->job_done(job);
|
||||||
|
}
|
||||||
dd_data->context_un.mbox.set_job = NULL;
|
dd_data->context_un.mbox.set_job = NULL;
|
||||||
job->dd_data = NULL;
|
|
||||||
job->job_done(job);
|
|
||||||
/* need to hold the lock until we call job done to hold off
|
/* need to hold the lock until we call job done to hold off
|
||||||
* the timeout handler returning to the midlayer while
|
* the timeout handler returning to the midlayer while
|
||||||
* we are stillprocessing the job
|
* we are stillprocessing the job
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* This file is part of the Emulex Linux Device Driver for *
|
* This file is part of the Emulex Linux Device Driver for *
|
||||||
* Fibre Channel Host Bus Adapters. *
|
* Fibre Channel Host Bus Adapters. *
|
||||||
* Copyright (C) 2004-2010 Emulex. All rights reserved. *
|
* Copyright (C) 2004-2011 Emulex. All rights reserved. *
|
||||||
* EMULEX and SLI are trademarks of Emulex. *
|
* EMULEX and SLI are trademarks of Emulex. *
|
||||||
* www.emulex.com *
|
* www.emulex.com *
|
||||||
* *
|
* *
|
||||||
@ -254,8 +254,8 @@ uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
|
|||||||
void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
|
void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
|
||||||
uint32_t);
|
uint32_t);
|
||||||
void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||||
|
int lpfc_selective_reset(struct lpfc_hba *);
|
||||||
void lpfc_reset_barrier(struct lpfc_hba * phba);
|
void lpfc_reset_barrier(struct lpfc_hba *);
|
||||||
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
|
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
|
||||||
int lpfc_sli_brdkill(struct lpfc_hba *);
|
int lpfc_sli_brdkill(struct lpfc_hba *);
|
||||||
int lpfc_sli_brdreset(struct lpfc_hba *);
|
int lpfc_sli_brdreset(struct lpfc_hba *);
|
||||||
|
@ -89,7 +89,8 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Read the HBA Host Attention Register */
|
/* Read the HBA Host Attention Register */
|
||||||
ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy))
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (!(ha_copy & HA_LATT))
|
if (!(ha_copy & HA_LATT))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1344,7 +1344,7 @@ typedef struct { /* FireFly BIU registers */
|
|||||||
#define HS_FFER1 0x80000000 /* Bit 31 */
|
#define HS_FFER1 0x80000000 /* Bit 31 */
|
||||||
#define HS_CRIT_TEMP 0x00000100 /* Bit 8 */
|
#define HS_CRIT_TEMP 0x00000100 /* Bit 8 */
|
||||||
#define HS_FFERM 0xFF000100 /* Mask for error bits 31:24 and 8 */
|
#define HS_FFERM 0xFF000100 /* Mask for error bits 31:24 and 8 */
|
||||||
|
#define UNPLUG_ERR 0x00000001 /* Indicate pci hot unplug */
|
||||||
/* Host Control Register */
|
/* Host Control Register */
|
||||||
|
|
||||||
#define HC_REG_OFFSET 12 /* Byte offset from register base address */
|
#define HC_REG_OFFSET 12 /* Byte offset from register base address */
|
||||||
@ -1713,6 +1713,17 @@ struct lpfc_pde6 {
|
|||||||
#define pde6_apptagval_WORD word2
|
#define pde6_apptagval_WORD word2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct lpfc_pde7 {
|
||||||
|
uint32_t word0;
|
||||||
|
#define pde7_type_SHIFT 24
|
||||||
|
#define pde7_type_MASK 0x000000ff
|
||||||
|
#define pde7_type_WORD word0
|
||||||
|
#define pde7_rsvd0_SHIFT 0
|
||||||
|
#define pde7_rsvd0_MASK 0x00ffffff
|
||||||
|
#define pde7_rsvd0_WORD word0
|
||||||
|
uint32_t addrHigh;
|
||||||
|
uint32_t addrLow;
|
||||||
|
};
|
||||||
|
|
||||||
/* Structure for MB Command LOAD_SM and DOWN_LOAD */
|
/* Structure for MB Command LOAD_SM and DOWN_LOAD */
|
||||||
|
|
||||||
@ -3621,7 +3632,7 @@ typedef struct _IOCB { /* IOCB structure */
|
|||||||
ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */
|
ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */
|
||||||
QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */
|
QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */
|
||||||
struct rcv_seq64 rcvseq64; /* RCV_SEQ64 and RCV_CONT64 */
|
struct rcv_seq64 rcvseq64; /* RCV_SEQ64 and RCV_CONT64 */
|
||||||
struct sli4_bls_acc bls_acc; /* UNSOL ABTS BLS_ACC params */
|
struct sli4_bls_rsp bls_rsp; /* UNSOL ABTS BLS_RSP params */
|
||||||
uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */
|
uint32_t ulpWord[IOCB_WORD_SZ - 2]; /* generic 6 'words' */
|
||||||
} un;
|
} un;
|
||||||
union {
|
union {
|
||||||
|
@ -215,7 +215,7 @@ struct lpfc_sli4_flags {
|
|||||||
#define lpfc_fip_flag_WORD word0
|
#define lpfc_fip_flag_WORD word0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sli4_bls_acc {
|
struct sli4_bls_rsp {
|
||||||
uint32_t word0_rsvd; /* Word0 must be reserved */
|
uint32_t word0_rsvd; /* Word0 must be reserved */
|
||||||
uint32_t word1;
|
uint32_t word1;
|
||||||
#define lpfc_abts_orig_SHIFT 0
|
#define lpfc_abts_orig_SHIFT 0
|
||||||
@ -231,6 +231,16 @@ struct sli4_bls_acc {
|
|||||||
#define lpfc_abts_oxid_MASK 0x0000FFFF
|
#define lpfc_abts_oxid_MASK 0x0000FFFF
|
||||||
#define lpfc_abts_oxid_WORD word2
|
#define lpfc_abts_oxid_WORD word2
|
||||||
uint32_t word3;
|
uint32_t word3;
|
||||||
|
#define lpfc_vndr_code_SHIFT 0
|
||||||
|
#define lpfc_vndr_code_MASK 0x000000FF
|
||||||
|
#define lpfc_vndr_code_WORD word3
|
||||||
|
#define lpfc_rsn_expln_SHIFT 8
|
||||||
|
#define lpfc_rsn_expln_MASK 0x000000FF
|
||||||
|
#define lpfc_rsn_expln_WORD word3
|
||||||
|
#define lpfc_rsn_code_SHIFT 16
|
||||||
|
#define lpfc_rsn_code_MASK 0x000000FF
|
||||||
|
#define lpfc_rsn_code_WORD word3
|
||||||
|
|
||||||
uint32_t word4;
|
uint32_t word4;
|
||||||
uint32_t word5_rsvd; /* Word5 must be reserved */
|
uint32_t word5_rsvd; /* Word5 must be reserved */
|
||||||
};
|
};
|
||||||
@ -711,21 +721,27 @@ struct lpfc_sli4_cfg_mhdr {
|
|||||||
union lpfc_sli4_cfg_shdr {
|
union lpfc_sli4_cfg_shdr {
|
||||||
struct {
|
struct {
|
||||||
uint32_t word6;
|
uint32_t word6;
|
||||||
#define lpfc_mbox_hdr_opcode_SHIFT 0
|
#define lpfc_mbox_hdr_opcode_SHIFT 0
|
||||||
#define lpfc_mbox_hdr_opcode_MASK 0x000000FF
|
#define lpfc_mbox_hdr_opcode_MASK 0x000000FF
|
||||||
#define lpfc_mbox_hdr_opcode_WORD word6
|
#define lpfc_mbox_hdr_opcode_WORD word6
|
||||||
#define lpfc_mbox_hdr_subsystem_SHIFT 8
|
#define lpfc_mbox_hdr_subsystem_SHIFT 8
|
||||||
#define lpfc_mbox_hdr_subsystem_MASK 0x000000FF
|
#define lpfc_mbox_hdr_subsystem_MASK 0x000000FF
|
||||||
#define lpfc_mbox_hdr_subsystem_WORD word6
|
#define lpfc_mbox_hdr_subsystem_WORD word6
|
||||||
#define lpfc_mbox_hdr_port_number_SHIFT 16
|
#define lpfc_mbox_hdr_port_number_SHIFT 16
|
||||||
#define lpfc_mbox_hdr_port_number_MASK 0x000000FF
|
#define lpfc_mbox_hdr_port_number_MASK 0x000000FF
|
||||||
#define lpfc_mbox_hdr_port_number_WORD word6
|
#define lpfc_mbox_hdr_port_number_WORD word6
|
||||||
#define lpfc_mbox_hdr_domain_SHIFT 24
|
#define lpfc_mbox_hdr_domain_SHIFT 24
|
||||||
#define lpfc_mbox_hdr_domain_MASK 0x000000FF
|
#define lpfc_mbox_hdr_domain_MASK 0x000000FF
|
||||||
#define lpfc_mbox_hdr_domain_WORD word6
|
#define lpfc_mbox_hdr_domain_WORD word6
|
||||||
uint32_t timeout;
|
uint32_t timeout;
|
||||||
uint32_t request_length;
|
uint32_t request_length;
|
||||||
uint32_t reserved9;
|
uint32_t word9;
|
||||||
|
#define lpfc_mbox_hdr_version_SHIFT 0
|
||||||
|
#define lpfc_mbox_hdr_version_MASK 0x000000FF
|
||||||
|
#define lpfc_mbox_hdr_version_WORD word9
|
||||||
|
#define LPFC_Q_CREATE_VERSION_2 2
|
||||||
|
#define LPFC_Q_CREATE_VERSION_1 1
|
||||||
|
#define LPFC_Q_CREATE_VERSION_0 0
|
||||||
} request;
|
} request;
|
||||||
struct {
|
struct {
|
||||||
uint32_t word6;
|
uint32_t word6;
|
||||||
@ -917,9 +933,12 @@ struct cq_context {
|
|||||||
#define LPFC_CQ_CNT_512 0x1
|
#define LPFC_CQ_CNT_512 0x1
|
||||||
#define LPFC_CQ_CNT_1024 0x2
|
#define LPFC_CQ_CNT_1024 0x2
|
||||||
uint32_t word1;
|
uint32_t word1;
|
||||||
#define lpfc_cq_eq_id_SHIFT 22
|
#define lpfc_cq_eq_id_SHIFT 22 /* Version 0 Only */
|
||||||
#define lpfc_cq_eq_id_MASK 0x000000FF
|
#define lpfc_cq_eq_id_MASK 0x000000FF
|
||||||
#define lpfc_cq_eq_id_WORD word1
|
#define lpfc_cq_eq_id_WORD word1
|
||||||
|
#define lpfc_cq_eq_id_2_SHIFT 0 /* Version 2 Only */
|
||||||
|
#define lpfc_cq_eq_id_2_MASK 0x0000FFFF
|
||||||
|
#define lpfc_cq_eq_id_2_WORD word1
|
||||||
uint32_t reserved0;
|
uint32_t reserved0;
|
||||||
uint32_t reserved1;
|
uint32_t reserved1;
|
||||||
};
|
};
|
||||||
@ -929,6 +948,9 @@ struct lpfc_mbx_cq_create {
|
|||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t word0;
|
uint32_t word0;
|
||||||
|
#define lpfc_mbx_cq_create_page_size_SHIFT 16 /* Version 2 Only */
|
||||||
|
#define lpfc_mbx_cq_create_page_size_MASK 0x000000FF
|
||||||
|
#define lpfc_mbx_cq_create_page_size_WORD word0
|
||||||
#define lpfc_mbx_cq_create_num_pages_SHIFT 0
|
#define lpfc_mbx_cq_create_num_pages_SHIFT 0
|
||||||
#define lpfc_mbx_cq_create_num_pages_MASK 0x0000FFFF
|
#define lpfc_mbx_cq_create_num_pages_MASK 0x0000FFFF
|
||||||
#define lpfc_mbx_cq_create_num_pages_WORD word0
|
#define lpfc_mbx_cq_create_num_pages_WORD word0
|
||||||
@ -969,7 +991,7 @@ struct wq_context {
|
|||||||
struct lpfc_mbx_wq_create {
|
struct lpfc_mbx_wq_create {
|
||||||
struct mbox_header header;
|
struct mbox_header header;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct { /* Version 0 Request */
|
||||||
uint32_t word0;
|
uint32_t word0;
|
||||||
#define lpfc_mbx_wq_create_num_pages_SHIFT 0
|
#define lpfc_mbx_wq_create_num_pages_SHIFT 0
|
||||||
#define lpfc_mbx_wq_create_num_pages_MASK 0x0000FFFF
|
#define lpfc_mbx_wq_create_num_pages_MASK 0x0000FFFF
|
||||||
@ -979,6 +1001,23 @@ struct lpfc_mbx_wq_create {
|
|||||||
#define lpfc_mbx_wq_create_cq_id_WORD word0
|
#define lpfc_mbx_wq_create_cq_id_WORD word0
|
||||||
struct dma_address page[LPFC_MAX_WQ_PAGE];
|
struct dma_address page[LPFC_MAX_WQ_PAGE];
|
||||||
} request;
|
} request;
|
||||||
|
struct { /* Version 1 Request */
|
||||||
|
uint32_t word0; /* Word 0 is the same as in v0 */
|
||||||
|
uint32_t word1;
|
||||||
|
#define lpfc_mbx_wq_create_page_size_SHIFT 0
|
||||||
|
#define lpfc_mbx_wq_create_page_size_MASK 0x000000FF
|
||||||
|
#define lpfc_mbx_wq_create_page_size_WORD word1
|
||||||
|
#define lpfc_mbx_wq_create_wqe_size_SHIFT 8
|
||||||
|
#define lpfc_mbx_wq_create_wqe_size_MASK 0x0000000F
|
||||||
|
#define lpfc_mbx_wq_create_wqe_size_WORD word1
|
||||||
|
#define LPFC_WQ_WQE_SIZE_64 0x5
|
||||||
|
#define LPFC_WQ_WQE_SIZE_128 0x6
|
||||||
|
#define lpfc_mbx_wq_create_wqe_count_SHIFT 16
|
||||||
|
#define lpfc_mbx_wq_create_wqe_count_MASK 0x0000FFFF
|
||||||
|
#define lpfc_mbx_wq_create_wqe_count_WORD word1
|
||||||
|
uint32_t word2;
|
||||||
|
struct dma_address page[LPFC_MAX_WQ_PAGE-1];
|
||||||
|
} request_1;
|
||||||
struct {
|
struct {
|
||||||
uint32_t word0;
|
uint32_t word0;
|
||||||
#define lpfc_mbx_wq_create_q_id_SHIFT 0
|
#define lpfc_mbx_wq_create_q_id_SHIFT 0
|
||||||
@ -1007,13 +1046,22 @@ struct lpfc_mbx_wq_destroy {
|
|||||||
#define LPFC_DATA_BUF_SIZE 2048
|
#define LPFC_DATA_BUF_SIZE 2048
|
||||||
struct rq_context {
|
struct rq_context {
|
||||||
uint32_t word0;
|
uint32_t word0;
|
||||||
#define lpfc_rq_context_rq_size_SHIFT 16
|
#define lpfc_rq_context_rqe_count_SHIFT 16 /* Version 0 Only */
|
||||||
#define lpfc_rq_context_rq_size_MASK 0x0000000F
|
#define lpfc_rq_context_rqe_count_MASK 0x0000000F
|
||||||
#define lpfc_rq_context_rq_size_WORD word0
|
#define lpfc_rq_context_rqe_count_WORD word0
|
||||||
#define LPFC_RQ_RING_SIZE_512 9 /* 512 entries */
|
#define LPFC_RQ_RING_SIZE_512 9 /* 512 entries */
|
||||||
#define LPFC_RQ_RING_SIZE_1024 10 /* 1024 entries */
|
#define LPFC_RQ_RING_SIZE_1024 10 /* 1024 entries */
|
||||||
#define LPFC_RQ_RING_SIZE_2048 11 /* 2048 entries */
|
#define LPFC_RQ_RING_SIZE_2048 11 /* 2048 entries */
|
||||||
#define LPFC_RQ_RING_SIZE_4096 12 /* 4096 entries */
|
#define LPFC_RQ_RING_SIZE_4096 12 /* 4096 entries */
|
||||||
|
#define lpfc_rq_context_rqe_count_1_SHIFT 16 /* Version 1 Only */
|
||||||
|
#define lpfc_rq_context_rqe_count_1_MASK 0x0000FFFF
|
||||||
|
#define lpfc_rq_context_rqe_count_1_WORD word0
|
||||||
|
#define lpfc_rq_context_rqe_size_SHIFT 8 /* Version 1 Only */
|
||||||
|
#define lpfc_rq_context_rqe_size_MASK 0x0000000F
|
||||||
|
#define lpfc_rq_context_rqe_size_WORD word0
|
||||||
|
#define lpfc_rq_context_page_size_SHIFT 0 /* Version 1 Only */
|
||||||
|
#define lpfc_rq_context_page_size_MASK 0x000000FF
|
||||||
|
#define lpfc_rq_context_page_size_WORD word0
|
||||||
uint32_t reserved1;
|
uint32_t reserved1;
|
||||||
uint32_t word2;
|
uint32_t word2;
|
||||||
#define lpfc_rq_context_cq_id_SHIFT 16
|
#define lpfc_rq_context_cq_id_SHIFT 16
|
||||||
@ -1022,7 +1070,7 @@ struct rq_context {
|
|||||||
#define lpfc_rq_context_buf_size_SHIFT 0
|
#define lpfc_rq_context_buf_size_SHIFT 0
|
||||||
#define lpfc_rq_context_buf_size_MASK 0x0000FFFF
|
#define lpfc_rq_context_buf_size_MASK 0x0000FFFF
|
||||||
#define lpfc_rq_context_buf_size_WORD word2
|
#define lpfc_rq_context_buf_size_WORD word2
|
||||||
uint32_t reserved3;
|
uint32_t buffer_size; /* Version 1 Only */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lpfc_mbx_rq_create {
|
struct lpfc_mbx_rq_create {
|
||||||
@ -1062,16 +1110,16 @@ struct lpfc_mbx_rq_destroy {
|
|||||||
|
|
||||||
struct mq_context {
|
struct mq_context {
|
||||||
uint32_t word0;
|
uint32_t word0;
|
||||||
#define lpfc_mq_context_cq_id_SHIFT 22
|
#define lpfc_mq_context_cq_id_SHIFT 22 /* Version 0 Only */
|
||||||
#define lpfc_mq_context_cq_id_MASK 0x000003FF
|
#define lpfc_mq_context_cq_id_MASK 0x000003FF
|
||||||
#define lpfc_mq_context_cq_id_WORD word0
|
#define lpfc_mq_context_cq_id_WORD word0
|
||||||
#define lpfc_mq_context_count_SHIFT 16
|
#define lpfc_mq_context_ring_size_SHIFT 16
|
||||||
#define lpfc_mq_context_count_MASK 0x0000000F
|
#define lpfc_mq_context_ring_size_MASK 0x0000000F
|
||||||
#define lpfc_mq_context_count_WORD word0
|
#define lpfc_mq_context_ring_size_WORD word0
|
||||||
#define LPFC_MQ_CNT_16 0x5
|
#define LPFC_MQ_RING_SIZE_16 0x5
|
||||||
#define LPFC_MQ_CNT_32 0x6
|
#define LPFC_MQ_RING_SIZE_32 0x6
|
||||||
#define LPFC_MQ_CNT_64 0x7
|
#define LPFC_MQ_RING_SIZE_64 0x7
|
||||||
#define LPFC_MQ_CNT_128 0x8
|
#define LPFC_MQ_RING_SIZE_128 0x8
|
||||||
uint32_t word1;
|
uint32_t word1;
|
||||||
#define lpfc_mq_context_valid_SHIFT 31
|
#define lpfc_mq_context_valid_SHIFT 31
|
||||||
#define lpfc_mq_context_valid_MASK 0x00000001
|
#define lpfc_mq_context_valid_MASK 0x00000001
|
||||||
@ -1105,9 +1153,12 @@ struct lpfc_mbx_mq_create_ext {
|
|||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t word0;
|
uint32_t word0;
|
||||||
#define lpfc_mbx_mq_create_ext_num_pages_SHIFT 0
|
#define lpfc_mbx_mq_create_ext_num_pages_SHIFT 0
|
||||||
#define lpfc_mbx_mq_create_ext_num_pages_MASK 0x0000FFFF
|
#define lpfc_mbx_mq_create_ext_num_pages_MASK 0x0000FFFF
|
||||||
#define lpfc_mbx_mq_create_ext_num_pages_WORD word0
|
#define lpfc_mbx_mq_create_ext_num_pages_WORD word0
|
||||||
|
#define lpfc_mbx_mq_create_ext_cq_id_SHIFT 16 /* Version 1 Only */
|
||||||
|
#define lpfc_mbx_mq_create_ext_cq_id_MASK 0x0000FFFF
|
||||||
|
#define lpfc_mbx_mq_create_ext_cq_id_WORD word0
|
||||||
uint32_t async_evt_bmap;
|
uint32_t async_evt_bmap;
|
||||||
#define lpfc_mbx_mq_create_ext_async_evt_link_SHIFT LPFC_TRAILER_CODE_LINK
|
#define lpfc_mbx_mq_create_ext_async_evt_link_SHIFT LPFC_TRAILER_CODE_LINK
|
||||||
#define lpfc_mbx_mq_create_ext_async_evt_link_MASK 0x00000001
|
#define lpfc_mbx_mq_create_ext_async_evt_link_MASK 0x00000001
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* This file is part of the Emulex Linux Device Driver for *
|
* This file is part of the Emulex Linux Device Driver for *
|
||||||
* Fibre Channel Host Bus Adapters. *
|
* Fibre Channel Host Bus Adapters. *
|
||||||
* Copyright (C) 2004-2010 Emulex. All rights reserved. *
|
* Copyright (C) 2004-2011 Emulex. All rights reserved. *
|
||||||
* EMULEX and SLI are trademarks of Emulex. *
|
* EMULEX and SLI are trademarks of Emulex. *
|
||||||
* www.emulex.com *
|
* www.emulex.com *
|
||||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||||
@ -507,7 +507,10 @@ lpfc_config_port_post(struct lpfc_hba *phba)
|
|||||||
phba->hba_flag &= ~HBA_ERATT_HANDLED;
|
phba->hba_flag &= ~HBA_ERATT_HANDLED;
|
||||||
|
|
||||||
/* Enable appropriate host interrupts */
|
/* Enable appropriate host interrupts */
|
||||||
status = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &status)) {
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
status |= HC_MBINT_ENA | HC_ERINT_ENA | HC_LAINT_ENA;
|
status |= HC_MBINT_ENA | HC_ERINT_ENA | HC_LAINT_ENA;
|
||||||
if (psli->num_rings > 0)
|
if (psli->num_rings > 0)
|
||||||
status |= HC_R0INT_ENA;
|
status |= HC_R0INT_ENA;
|
||||||
@ -1222,7 +1225,10 @@ lpfc_handle_deferred_eratt(struct lpfc_hba *phba)
|
|||||||
/* Wait for the ER1 bit to clear.*/
|
/* Wait for the ER1 bit to clear.*/
|
||||||
while (phba->work_hs & HS_FFER1) {
|
while (phba->work_hs & HS_FFER1) {
|
||||||
msleep(100);
|
msleep(100);
|
||||||
phba->work_hs = readl(phba->HSregaddr);
|
if (lpfc_readl(phba->HSregaddr, &phba->work_hs)) {
|
||||||
|
phba->work_hs = UNPLUG_ERR ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* If driver is unloading let the worker thread continue */
|
/* If driver is unloading let the worker thread continue */
|
||||||
if (phba->pport->load_flag & FC_UNLOADING) {
|
if (phba->pport->load_flag & FC_UNLOADING) {
|
||||||
phba->work_hs = 0;
|
phba->work_hs = 0;
|
||||||
@ -4474,6 +4480,7 @@ lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
|
|||||||
{
|
{
|
||||||
phba->lpfc_hba_init_link = lpfc_hba_init_link;
|
phba->lpfc_hba_init_link = lpfc_hba_init_link;
|
||||||
phba->lpfc_hba_down_link = lpfc_hba_down_link;
|
phba->lpfc_hba_down_link = lpfc_hba_down_link;
|
||||||
|
phba->lpfc_selective_reset = lpfc_selective_reset;
|
||||||
switch (dev_grp) {
|
switch (dev_grp) {
|
||||||
case LPFC_PCI_DEV_LP:
|
case LPFC_PCI_DEV_LP:
|
||||||
phba->lpfc_hba_down_post = lpfc_hba_down_post_s3;
|
phba->lpfc_hba_down_post = lpfc_hba_down_post_s3;
|
||||||
@ -5385,13 +5392,16 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba)
|
|||||||
int i, port_error = 0;
|
int i, port_error = 0;
|
||||||
uint32_t if_type;
|
uint32_t if_type;
|
||||||
|
|
||||||
|
memset(&portsmphr_reg, 0, sizeof(portsmphr_reg));
|
||||||
|
memset(®_data, 0, sizeof(reg_data));
|
||||||
if (!phba->sli4_hba.PSMPHRregaddr)
|
if (!phba->sli4_hba.PSMPHRregaddr)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Wait up to 30 seconds for the SLI Port POST done and ready */
|
/* Wait up to 30 seconds for the SLI Port POST done and ready */
|
||||||
for (i = 0; i < 3000; i++) {
|
for (i = 0; i < 3000; i++) {
|
||||||
portsmphr_reg.word0 = readl(phba->sli4_hba.PSMPHRregaddr);
|
if (lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
|
||||||
if (bf_get(lpfc_port_smphr_perr, &portsmphr_reg)) {
|
&portsmphr_reg.word0) ||
|
||||||
|
(bf_get(lpfc_port_smphr_perr, &portsmphr_reg))) {
|
||||||
/* Port has a fatal POST error, break out */
|
/* Port has a fatal POST error, break out */
|
||||||
port_error = -ENODEV;
|
port_error = -ENODEV;
|
||||||
break;
|
break;
|
||||||
@ -5472,9 +5482,9 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba)
|
|||||||
break;
|
break;
|
||||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||||
/* Final checks. The port status should be clean. */
|
/* Final checks. The port status should be clean. */
|
||||||
reg_data.word0 =
|
if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
|
||||||
readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
|
®_data.word0) ||
|
||||||
if (bf_get(lpfc_sliport_status_err, ®_data)) {
|
bf_get(lpfc_sliport_status_err, ®_data)) {
|
||||||
phba->work_status[0] =
|
phba->work_status[0] =
|
||||||
readl(phba->sli4_hba.u.if_type2.
|
readl(phba->sli4_hba.u.if_type2.
|
||||||
ERR1regaddr);
|
ERR1regaddr);
|
||||||
@ -6760,9 +6770,11 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
|
|||||||
* the loop again.
|
* the loop again.
|
||||||
*/
|
*/
|
||||||
for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) {
|
for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) {
|
||||||
reg_data.word0 =
|
if (lpfc_readl(phba->sli4_hba.u.if_type2.
|
||||||
readl(phba->sli4_hba.u.if_type2.
|
STATUSregaddr, ®_data.word0)) {
|
||||||
STATUSregaddr);
|
rc = -ENODEV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (bf_get(lpfc_sliport_status_rdy, ®_data))
|
if (bf_get(lpfc_sliport_status_rdy, ®_data))
|
||||||
break;
|
break;
|
||||||
if (bf_get(lpfc_sliport_status_rn, ®_data)) {
|
if (bf_get(lpfc_sliport_status_rn, ®_data)) {
|
||||||
@ -6783,8 +6795,11 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Detect any port errors. */
|
/* Detect any port errors. */
|
||||||
reg_data.word0 = readl(phba->sli4_hba.u.if_type2.
|
if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
|
||||||
STATUSregaddr);
|
®_data.word0)) {
|
||||||
|
rc = -ENODEV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if ((bf_get(lpfc_sliport_status_err, ®_data)) ||
|
if ((bf_get(lpfc_sliport_status_err, ®_data)) ||
|
||||||
(rdy_chk >= 1000)) {
|
(rdy_chk >= 1000)) {
|
||||||
phba->work_status[0] = readl(
|
phba->work_status[0] = readl(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* This file is part of the Emulex Linux Device Driver for *
|
* This file is part of the Emulex Linux Device Driver for *
|
||||||
* Fibre Channel Host Bus Adapters. *
|
* Fibre Channel Host Bus Adapters. *
|
||||||
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
|
* Copyright (C) 2004-2011 Emulex. All rights reserved. *
|
||||||
* EMULEX and SLI are trademarks of Emulex. *
|
* EMULEX and SLI are trademarks of Emulex. *
|
||||||
* www.emulex.com *
|
* www.emulex.com *
|
||||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||||
@ -1514,10 +1514,11 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
|||||||
struct scatterlist *sgpe = NULL; /* s/g prot entry */
|
struct scatterlist *sgpe = NULL; /* s/g prot entry */
|
||||||
struct lpfc_pde5 *pde5 = NULL;
|
struct lpfc_pde5 *pde5 = NULL;
|
||||||
struct lpfc_pde6 *pde6 = NULL;
|
struct lpfc_pde6 *pde6 = NULL;
|
||||||
struct ulp_bde64 *prot_bde = NULL;
|
struct lpfc_pde7 *pde7 = NULL;
|
||||||
dma_addr_t dataphysaddr, protphysaddr;
|
dma_addr_t dataphysaddr, protphysaddr;
|
||||||
unsigned short curr_data = 0, curr_prot = 0;
|
unsigned short curr_data = 0, curr_prot = 0;
|
||||||
unsigned int split_offset, protgroup_len;
|
unsigned int split_offset;
|
||||||
|
unsigned int protgroup_len, protgroup_offset = 0, protgroup_remainder;
|
||||||
unsigned int protgrp_blks, protgrp_bytes;
|
unsigned int protgrp_blks, protgrp_bytes;
|
||||||
unsigned int remainder, subtotal;
|
unsigned int remainder, subtotal;
|
||||||
int status;
|
int status;
|
||||||
@ -1585,23 +1586,33 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
|||||||
bpl++;
|
bpl++;
|
||||||
|
|
||||||
/* setup the first BDE that points to protection buffer */
|
/* setup the first BDE that points to protection buffer */
|
||||||
prot_bde = (struct ulp_bde64 *) bpl;
|
protphysaddr = sg_dma_address(sgpe) + protgroup_offset;
|
||||||
protphysaddr = sg_dma_address(sgpe);
|
protgroup_len = sg_dma_len(sgpe) - protgroup_offset;
|
||||||
prot_bde->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
|
|
||||||
prot_bde->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
|
|
||||||
protgroup_len = sg_dma_len(sgpe);
|
|
||||||
|
|
||||||
/* must be integer multiple of the DIF block length */
|
/* must be integer multiple of the DIF block length */
|
||||||
BUG_ON(protgroup_len % 8);
|
BUG_ON(protgroup_len % 8);
|
||||||
|
|
||||||
|
pde7 = (struct lpfc_pde7 *) bpl;
|
||||||
|
memset(pde7, 0, sizeof(struct lpfc_pde7));
|
||||||
|
bf_set(pde7_type, pde7, LPFC_PDE7_DESCRIPTOR);
|
||||||
|
|
||||||
|
pde7->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
|
||||||
|
pde7->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
|
||||||
|
|
||||||
protgrp_blks = protgroup_len / 8;
|
protgrp_blks = protgroup_len / 8;
|
||||||
protgrp_bytes = protgrp_blks * blksize;
|
protgrp_bytes = protgrp_blks * blksize;
|
||||||
|
|
||||||
prot_bde->tus.f.bdeSize = protgroup_len;
|
/* check if this pde is crossing the 4K boundary; if so split */
|
||||||
prot_bde->tus.f.bdeFlags = LPFC_PDE7_DESCRIPTOR;
|
if ((pde7->addrLow & 0xfff) + protgroup_len > 0x1000) {
|
||||||
prot_bde->tus.w = le32_to_cpu(bpl->tus.w);
|
protgroup_remainder = 0x1000 - (pde7->addrLow & 0xfff);
|
||||||
|
protgroup_offset += protgroup_remainder;
|
||||||
|
protgrp_blks = protgroup_remainder / 8;
|
||||||
|
protgrp_bytes = protgroup_remainder * blksize;
|
||||||
|
} else {
|
||||||
|
protgroup_offset = 0;
|
||||||
|
curr_prot++;
|
||||||
|
}
|
||||||
|
|
||||||
curr_prot++;
|
|
||||||
num_bde++;
|
num_bde++;
|
||||||
|
|
||||||
/* setup BDE's for data blocks associated with DIF data */
|
/* setup BDE's for data blocks associated with DIF data */
|
||||||
@ -1653,6 +1664,13 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (protgroup_offset) {
|
||||||
|
/* update the reference tag */
|
||||||
|
reftag += protgrp_blks;
|
||||||
|
bpl++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* are we done ? */
|
/* are we done ? */
|
||||||
if (curr_prot == protcnt) {
|
if (curr_prot == protcnt) {
|
||||||
alldone = 1;
|
alldone = 1;
|
||||||
@ -1675,6 +1693,7 @@ out:
|
|||||||
|
|
||||||
return num_bde;
|
return num_bde;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a SCSI command that supports DIF, determine composition of protection
|
* Given a SCSI command that supports DIF, determine composition of protection
|
||||||
* groups involved in setting up buffer lists
|
* groups involved in setting up buffer lists
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* This file is part of the Emulex Linux Device Driver for *
|
* This file is part of the Emulex Linux Device Driver for *
|
||||||
* Fibre Channel Host Bus Adapters. *
|
* Fibre Channel Host Bus Adapters. *
|
||||||
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
|
* Copyright (C) 2004-2011 Emulex. All rights reserved. *
|
||||||
* EMULEX and SLI are trademarks of Emulex. *
|
* EMULEX and SLI are trademarks of Emulex. *
|
||||||
* www.emulex.com *
|
* www.emulex.com *
|
||||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||||
@ -3477,7 +3477,8 @@ lpfc_sli_brdready_s3(struct lpfc_hba *phba, uint32_t mask)
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
/* Read the HBA Host Status Register */
|
/* Read the HBA Host Status Register */
|
||||||
status = readl(phba->HSregaddr);
|
if (lpfc_readl(phba->HSregaddr, &status))
|
||||||
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check status register every 100ms for 5 retries, then every
|
* Check status register every 100ms for 5 retries, then every
|
||||||
@ -3502,7 +3503,10 @@ lpfc_sli_brdready_s3(struct lpfc_hba *phba, uint32_t mask)
|
|||||||
lpfc_sli_brdrestart(phba);
|
lpfc_sli_brdrestart(phba);
|
||||||
}
|
}
|
||||||
/* Read the HBA Host Status Register */
|
/* Read the HBA Host Status Register */
|
||||||
status = readl(phba->HSregaddr);
|
if (lpfc_readl(phba->HSregaddr, &status)) {
|
||||||
|
retval = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check to see if any errors occurred during init */
|
/* Check to see if any errors occurred during init */
|
||||||
@ -3584,7 +3588,7 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
|
|||||||
uint32_t __iomem *resp_buf;
|
uint32_t __iomem *resp_buf;
|
||||||
uint32_t __iomem *mbox_buf;
|
uint32_t __iomem *mbox_buf;
|
||||||
volatile uint32_t mbox;
|
volatile uint32_t mbox;
|
||||||
uint32_t hc_copy;
|
uint32_t hc_copy, ha_copy, resp_data;
|
||||||
int i;
|
int i;
|
||||||
uint8_t hdrtype;
|
uint8_t hdrtype;
|
||||||
|
|
||||||
@ -3601,12 +3605,15 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
|
|||||||
resp_buf = phba->MBslimaddr;
|
resp_buf = phba->MBslimaddr;
|
||||||
|
|
||||||
/* Disable the error attention */
|
/* Disable the error attention */
|
||||||
hc_copy = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &hc_copy))
|
||||||
|
return;
|
||||||
writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
|
writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
phba->link_flag |= LS_IGNORE_ERATT;
|
phba->link_flag |= LS_IGNORE_ERATT;
|
||||||
|
|
||||||
if (readl(phba->HAregaddr) & HA_ERATT) {
|
if (lpfc_readl(phba->HAregaddr, &ha_copy))
|
||||||
|
return;
|
||||||
|
if (ha_copy & HA_ERATT) {
|
||||||
/* Clear Chip error bit */
|
/* Clear Chip error bit */
|
||||||
writel(HA_ERATT, phba->HAregaddr);
|
writel(HA_ERATT, phba->HAregaddr);
|
||||||
phba->pport->stopped = 1;
|
phba->pport->stopped = 1;
|
||||||
@ -3620,11 +3627,18 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
|
|||||||
mbox_buf = phba->MBslimaddr;
|
mbox_buf = phba->MBslimaddr;
|
||||||
writel(mbox, mbox_buf);
|
writel(mbox, mbox_buf);
|
||||||
|
|
||||||
for (i = 0;
|
for (i = 0; i < 50; i++) {
|
||||||
readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN) && i < 50; i++)
|
if (lpfc_readl((resp_buf + 1), &resp_data))
|
||||||
mdelay(1);
|
return;
|
||||||
|
if (resp_data != ~(BARRIER_TEST_PATTERN))
|
||||||
if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
|
mdelay(1);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resp_data = 0;
|
||||||
|
if (lpfc_readl((resp_buf + 1), &resp_data))
|
||||||
|
return;
|
||||||
|
if (resp_data != ~(BARRIER_TEST_PATTERN)) {
|
||||||
if (phba->sli.sli_flag & LPFC_SLI_ACTIVE ||
|
if (phba->sli.sli_flag & LPFC_SLI_ACTIVE ||
|
||||||
phba->pport->stopped)
|
phba->pport->stopped)
|
||||||
goto restore_hc;
|
goto restore_hc;
|
||||||
@ -3633,13 +3647,26 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
|
|||||||
}
|
}
|
||||||
|
|
||||||
((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST;
|
((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST;
|
||||||
for (i = 0; readl(resp_buf) != mbox && i < 500; i++)
|
resp_data = 0;
|
||||||
mdelay(1);
|
for (i = 0; i < 500; i++) {
|
||||||
|
if (lpfc_readl(resp_buf, &resp_data))
|
||||||
|
return;
|
||||||
|
if (resp_data != mbox)
|
||||||
|
mdelay(1);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
clear_errat:
|
clear_errat:
|
||||||
|
|
||||||
while (!(readl(phba->HAregaddr) & HA_ERATT) && ++i < 500)
|
while (++i < 500) {
|
||||||
mdelay(1);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy))
|
||||||
|
return;
|
||||||
|
if (!(ha_copy & HA_ERATT))
|
||||||
|
mdelay(1);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (readl(phba->HAregaddr) & HA_ERATT) {
|
if (readl(phba->HAregaddr) & HA_ERATT) {
|
||||||
writel(HA_ERATT, phba->HAregaddr);
|
writel(HA_ERATT, phba->HAregaddr);
|
||||||
@ -3686,7 +3713,11 @@ lpfc_sli_brdkill(struct lpfc_hba *phba)
|
|||||||
|
|
||||||
/* Disable the error attention */
|
/* Disable the error attention */
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
status = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &status)) {
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
mempool_free(pmb, phba->mbox_mem_pool);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
status &= ~HC_ERINT_ENA;
|
status &= ~HC_ERINT_ENA;
|
||||||
writel(status, phba->HCregaddr);
|
writel(status, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
@ -3720,11 +3751,12 @@ lpfc_sli_brdkill(struct lpfc_hba *phba)
|
|||||||
* 3 seconds we still set HBA_ERROR state because the status of the
|
* 3 seconds we still set HBA_ERROR state because the status of the
|
||||||
* board is now undefined.
|
* board is now undefined.
|
||||||
*/
|
*/
|
||||||
ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy))
|
||||||
|
return 1;
|
||||||
while ((i++ < 30) && !(ha_copy & HA_ERATT)) {
|
while ((i++ < 30) && !(ha_copy & HA_ERATT)) {
|
||||||
mdelay(100);
|
mdelay(100);
|
||||||
ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy))
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
del_timer_sync(&psli->mbox_tmo);
|
del_timer_sync(&psli->mbox_tmo);
|
||||||
@ -4018,7 +4050,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
|
|||||||
uint32_t status, i = 0;
|
uint32_t status, i = 0;
|
||||||
|
|
||||||
/* Read the HBA Host Status Register */
|
/* Read the HBA Host Status Register */
|
||||||
status = readl(phba->HSregaddr);
|
if (lpfc_readl(phba->HSregaddr, &status))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
/* Check status register to see what current state is */
|
/* Check status register to see what current state is */
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -4073,7 +4106,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
|
|||||||
lpfc_sli_brdrestart(phba);
|
lpfc_sli_brdrestart(phba);
|
||||||
}
|
}
|
||||||
/* Read the HBA Host Status Register */
|
/* Read the HBA Host Status Register */
|
||||||
status = readl(phba->HSregaddr);
|
if (lpfc_readl(phba->HSregaddr, &status))
|
||||||
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check to see if any errors occurred during init */
|
/* Check to see if any errors occurred during init */
|
||||||
@ -5136,7 +5170,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
|
|||||||
MAILBOX_t *mb;
|
MAILBOX_t *mb;
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
uint32_t status, evtctr;
|
uint32_t status, evtctr;
|
||||||
uint32_t ha_copy;
|
uint32_t ha_copy, hc_copy;
|
||||||
int i;
|
int i;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
unsigned long drvr_flag = 0;
|
unsigned long drvr_flag = 0;
|
||||||
@ -5202,15 +5236,17 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
|
|||||||
goto out_not_finished;
|
goto out_not_finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
|
if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT) {
|
||||||
!(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
|
if (lpfc_readl(phba->HCregaddr, &hc_copy) ||
|
||||||
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
|
!(hc_copy & HC_MBINT_ENA)) {
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
|
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
|
||||||
"(%d):2528 Mailbox command x%x cannot "
|
"(%d):2528 Mailbox command x%x cannot "
|
||||||
"issue Data: x%x x%x\n",
|
"issue Data: x%x x%x\n",
|
||||||
pmbox->vport ? pmbox->vport->vpi : 0,
|
pmbox->vport ? pmbox->vport->vpi : 0,
|
||||||
pmbox->u.mb.mbxCommand, psli->sli_flag, flag);
|
pmbox->u.mb.mbxCommand, psli->sli_flag, flag);
|
||||||
goto out_not_finished;
|
goto out_not_finished;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
|
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
|
||||||
@ -5408,11 +5444,19 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
|
|||||||
word0 = le32_to_cpu(word0);
|
word0 = le32_to_cpu(word0);
|
||||||
} else {
|
} else {
|
||||||
/* First read mbox status word */
|
/* First read mbox status word */
|
||||||
word0 = readl(phba->MBslimaddr);
|
if (lpfc_readl(phba->MBslimaddr, &word0)) {
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock,
|
||||||
|
drvr_flag);
|
||||||
|
goto out_not_finished;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the HBA Host Attention Register */
|
/* Read the HBA Host Attention Register */
|
||||||
ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy)) {
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock,
|
||||||
|
drvr_flag);
|
||||||
|
goto out_not_finished;
|
||||||
|
}
|
||||||
timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
|
timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
|
||||||
mb->mbxCommand) *
|
mb->mbxCommand) *
|
||||||
1000) + jiffies;
|
1000) + jiffies;
|
||||||
@ -5463,7 +5507,11 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
|
|||||||
word0 = readl(phba->MBslimaddr);
|
word0 = readl(phba->MBslimaddr);
|
||||||
}
|
}
|
||||||
/* Read the HBA Host Attention Register */
|
/* Read the HBA Host Attention Register */
|
||||||
ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy)) {
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock,
|
||||||
|
drvr_flag);
|
||||||
|
goto out_not_finished;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psli->sli_flag & LPFC_SLI_ACTIVE) {
|
if (psli->sli_flag & LPFC_SLI_ACTIVE) {
|
||||||
@ -6263,7 +6311,6 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
|
|||||||
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
||||||
else
|
else
|
||||||
bf_set(lpfc_sli4_sge_last, sgl, 0);
|
bf_set(lpfc_sli4_sge_last, sgl, 0);
|
||||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
|
||||||
/* swap the size field back to the cpu so we
|
/* swap the size field back to the cpu so we
|
||||||
* can assign it to the sgl.
|
* can assign it to the sgl.
|
||||||
*/
|
*/
|
||||||
@ -6283,6 +6330,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
|
|||||||
bf_set(lpfc_sli4_sge_offset, sgl, offset);
|
bf_set(lpfc_sli4_sge_offset, sgl, offset);
|
||||||
offset += bde.tus.f.bdeSize;
|
offset += bde.tus.f.bdeSize;
|
||||||
}
|
}
|
||||||
|
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||||
bpl++;
|
bpl++;
|
||||||
sgl++;
|
sgl++;
|
||||||
}
|
}
|
||||||
@ -6528,9 +6576,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||||||
numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize /
|
numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize /
|
||||||
sizeof(struct ulp_bde64);
|
sizeof(struct ulp_bde64);
|
||||||
for (i = 0; i < numBdes; i++) {
|
for (i = 0; i < numBdes; i++) {
|
||||||
if (bpl[i].tus.f.bdeFlags != BUFF_TYPE_BDE_64)
|
|
||||||
break;
|
|
||||||
bde.tus.w = le32_to_cpu(bpl[i].tus.w);
|
bde.tus.w = le32_to_cpu(bpl[i].tus.w);
|
||||||
|
if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64)
|
||||||
|
break;
|
||||||
xmit_len += bde.tus.f.bdeSize;
|
xmit_len += bde.tus.f.bdeSize;
|
||||||
}
|
}
|
||||||
/* word3 iocb=IO_TAG wqe=request_payload_len */
|
/* word3 iocb=IO_TAG wqe=request_payload_len */
|
||||||
@ -6620,15 +6668,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||||||
xritag = 0;
|
xritag = 0;
|
||||||
break;
|
break;
|
||||||
case CMD_XMIT_BLS_RSP64_CX:
|
case CMD_XMIT_BLS_RSP64_CX:
|
||||||
/* As BLS ABTS-ACC WQE is very different from other WQEs,
|
/* As BLS ABTS RSP WQE is very different from other WQEs,
|
||||||
* we re-construct this WQE here based on information in
|
* we re-construct this WQE here based on information in
|
||||||
* iocbq from scratch.
|
* iocbq from scratch.
|
||||||
*/
|
*/
|
||||||
memset(wqe, 0, sizeof(union lpfc_wqe));
|
memset(wqe, 0, sizeof(union lpfc_wqe));
|
||||||
/* OX_ID is invariable to who sent ABTS to CT exchange */
|
/* OX_ID is invariable to who sent ABTS to CT exchange */
|
||||||
bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp,
|
bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp,
|
||||||
bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_acc));
|
bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_rsp));
|
||||||
if (bf_get(lpfc_abts_orig, &iocbq->iocb.un.bls_acc) ==
|
if (bf_get(lpfc_abts_orig, &iocbq->iocb.un.bls_rsp) ==
|
||||||
LPFC_ABTS_UNSOL_INT) {
|
LPFC_ABTS_UNSOL_INT) {
|
||||||
/* ABTS sent by initiator to CT exchange, the
|
/* ABTS sent by initiator to CT exchange, the
|
||||||
* RX_ID field will be filled with the newly
|
* RX_ID field will be filled with the newly
|
||||||
@ -6642,7 +6690,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||||||
* RX_ID from ABTS.
|
* RX_ID from ABTS.
|
||||||
*/
|
*/
|
||||||
bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp,
|
bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp,
|
||||||
bf_get(lpfc_abts_rxid, &iocbq->iocb.un.bls_acc));
|
bf_get(lpfc_abts_rxid, &iocbq->iocb.un.bls_rsp));
|
||||||
}
|
}
|
||||||
bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff);
|
bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff);
|
||||||
bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1);
|
bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1);
|
||||||
@ -6653,6 +6701,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||||||
LPFC_WQE_LENLOC_NONE);
|
LPFC_WQE_LENLOC_NONE);
|
||||||
/* Overwrite the pre-set comnd type with OTHER_COMMAND */
|
/* Overwrite the pre-set comnd type with OTHER_COMMAND */
|
||||||
command_type = OTHER_COMMAND;
|
command_type = OTHER_COMMAND;
|
||||||
|
if (iocbq->iocb.un.xseq64.w5.hcsw.Rctl == FC_RCTL_BA_RJT) {
|
||||||
|
bf_set(xmit_bls_rsp64_rjt_vspec, &wqe->xmit_bls_rsp,
|
||||||
|
bf_get(lpfc_vndr_code, &iocbq->iocb.un.bls_rsp));
|
||||||
|
bf_set(xmit_bls_rsp64_rjt_expc, &wqe->xmit_bls_rsp,
|
||||||
|
bf_get(lpfc_rsn_expln, &iocbq->iocb.un.bls_rsp));
|
||||||
|
bf_set(xmit_bls_rsp64_rjt_rsnc, &wqe->xmit_bls_rsp,
|
||||||
|
bf_get(lpfc_rsn_code, &iocbq->iocb.un.bls_rsp));
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CMD_XRI_ABORTED_CX:
|
case CMD_XRI_ABORTED_CX:
|
||||||
case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
|
case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
|
||||||
@ -6701,7 +6758,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
|
|||||||
|
|
||||||
if (piocb->sli4_xritag == NO_XRI) {
|
if (piocb->sli4_xritag == NO_XRI) {
|
||||||
if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
|
if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
|
||||||
piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
|
piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN ||
|
||||||
|
piocb->iocb.ulpCommand == CMD_XMIT_BLS_RSP64_CX)
|
||||||
sglq = NULL;
|
sglq = NULL;
|
||||||
else {
|
else {
|
||||||
if (pring->txq_cnt) {
|
if (pring->txq_cnt) {
|
||||||
@ -8194,7 +8252,8 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
|
|||||||
piocb->iocb_flag &= ~LPFC_IO_WAKE;
|
piocb->iocb_flag &= ~LPFC_IO_WAKE;
|
||||||
|
|
||||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||||
creg_val = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &creg_val))
|
||||||
|
return IOCB_ERROR;
|
||||||
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
|
||||||
writel(creg_val, phba->HCregaddr);
|
writel(creg_val, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
@ -8236,7 +8295,8 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||||
creg_val = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &creg_val))
|
||||||
|
return IOCB_ERROR;
|
||||||
creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
|
creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
|
||||||
writel(creg_val, phba->HCregaddr);
|
writel(creg_val, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
@ -8387,10 +8447,13 @@ lpfc_sli_eratt_read(struct lpfc_hba *phba)
|
|||||||
uint32_t ha_copy;
|
uint32_t ha_copy;
|
||||||
|
|
||||||
/* Read chip Host Attention (HA) register */
|
/* Read chip Host Attention (HA) register */
|
||||||
ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy))
|
||||||
|
goto unplug_err;
|
||||||
|
|
||||||
if (ha_copy & HA_ERATT) {
|
if (ha_copy & HA_ERATT) {
|
||||||
/* Read host status register to retrieve error event */
|
/* Read host status register to retrieve error event */
|
||||||
lpfc_sli_read_hs(phba);
|
if (lpfc_sli_read_hs(phba))
|
||||||
|
goto unplug_err;
|
||||||
|
|
||||||
/* Check if there is a deferred error condition is active */
|
/* Check if there is a deferred error condition is active */
|
||||||
if ((HS_FFER1 & phba->work_hs) &&
|
if ((HS_FFER1 & phba->work_hs) &&
|
||||||
@ -8409,6 +8472,15 @@ lpfc_sli_eratt_read(struct lpfc_hba *phba)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
unplug_err:
|
||||||
|
/* Set the driver HS work bitmap */
|
||||||
|
phba->work_hs |= UNPLUG_ERR;
|
||||||
|
/* Set the driver HA work bitmap */
|
||||||
|
phba->work_ha |= HA_ERATT;
|
||||||
|
/* Indicate polling handles this ERATT */
|
||||||
|
phba->hba_flag |= HBA_ERATT_HANDLED;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8436,8 +8508,15 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba)
|
|||||||
if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
|
if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
|
||||||
switch (if_type) {
|
switch (if_type) {
|
||||||
case LPFC_SLI_INTF_IF_TYPE_0:
|
case LPFC_SLI_INTF_IF_TYPE_0:
|
||||||
uerr_sta_lo = readl(phba->sli4_hba.u.if_type0.UERRLOregaddr);
|
if (lpfc_readl(phba->sli4_hba.u.if_type0.UERRLOregaddr,
|
||||||
uerr_sta_hi = readl(phba->sli4_hba.u.if_type0.UERRHIregaddr);
|
&uerr_sta_lo) ||
|
||||||
|
lpfc_readl(phba->sli4_hba.u.if_type0.UERRHIregaddr,
|
||||||
|
&uerr_sta_hi)) {
|
||||||
|
phba->work_hs |= UNPLUG_ERR;
|
||||||
|
phba->work_ha |= HA_ERATT;
|
||||||
|
phba->hba_flag |= HBA_ERATT_HANDLED;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
|
if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
|
||||||
(~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
|
(~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||||
@ -8456,9 +8535,15 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||||
portstat_reg.word0 =
|
if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
|
||||||
readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
|
&portstat_reg.word0) ||
|
||||||
portsmphr = readl(phba->sli4_hba.PSMPHRregaddr);
|
lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
|
||||||
|
&portsmphr)){
|
||||||
|
phba->work_hs |= UNPLUG_ERR;
|
||||||
|
phba->work_ha |= HA_ERATT;
|
||||||
|
phba->hba_flag |= HBA_ERATT_HANDLED;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (bf_get(lpfc_sliport_status_err, &portstat_reg)) {
|
if (bf_get(lpfc_sliport_status_err, &portstat_reg)) {
|
||||||
phba->work_status[0] =
|
phba->work_status[0] =
|
||||||
readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
|
readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
|
||||||
@ -8639,7 +8724,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
|
|||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
/* Need to read HA REG for slow-path events */
|
/* Need to read HA REG for slow-path events */
|
||||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||||
ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy))
|
||||||
|
goto unplug_error;
|
||||||
/* If somebody is waiting to handle an eratt don't process it
|
/* If somebody is waiting to handle an eratt don't process it
|
||||||
* here. The brdkill function will do this.
|
* here. The brdkill function will do this.
|
||||||
*/
|
*/
|
||||||
@ -8665,7 +8751,9 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Clear up only attention source related to slow-path */
|
/* Clear up only attention source related to slow-path */
|
||||||
hc_copy = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &hc_copy))
|
||||||
|
goto unplug_error;
|
||||||
|
|
||||||
writel(hc_copy & ~(HC_MBINT_ENA | HC_R2INT_ENA |
|
writel(hc_copy & ~(HC_MBINT_ENA | HC_R2INT_ENA |
|
||||||
HC_LAINT_ENA | HC_ERINT_ENA),
|
HC_LAINT_ENA | HC_ERINT_ENA),
|
||||||
phba->HCregaddr);
|
phba->HCregaddr);
|
||||||
@ -8688,7 +8776,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
|
|||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||||
phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
|
phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
|
||||||
control = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &control))
|
||||||
|
goto unplug_error;
|
||||||
control &= ~HC_LAINT_ENA;
|
control &= ~HC_LAINT_ENA;
|
||||||
writel(control, phba->HCregaddr);
|
writel(control, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
@ -8708,7 +8797,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
|
|||||||
status >>= (4*LPFC_ELS_RING);
|
status >>= (4*LPFC_ELS_RING);
|
||||||
if (status & HA_RXMASK) {
|
if (status & HA_RXMASK) {
|
||||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||||
control = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &control))
|
||||||
|
goto unplug_error;
|
||||||
|
|
||||||
lpfc_debugfs_slow_ring_trc(phba,
|
lpfc_debugfs_slow_ring_trc(phba,
|
||||||
"ISR slow ring: ctl:x%x stat:x%x isrcnt:x%x",
|
"ISR slow ring: ctl:x%x stat:x%x isrcnt:x%x",
|
||||||
@ -8741,7 +8831,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
|
|||||||
}
|
}
|
||||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||||
if (work_ha_copy & HA_ERATT) {
|
if (work_ha_copy & HA_ERATT) {
|
||||||
lpfc_sli_read_hs(phba);
|
if (lpfc_sli_read_hs(phba))
|
||||||
|
goto unplug_error;
|
||||||
/*
|
/*
|
||||||
* Check if there is a deferred error condition
|
* Check if there is a deferred error condition
|
||||||
* is active
|
* is active
|
||||||
@ -8872,6 +8963,9 @@ send_current_mbox:
|
|||||||
lpfc_worker_wake_up(phba);
|
lpfc_worker_wake_up(phba);
|
||||||
}
|
}
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
unplug_error:
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock, iflag);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
} /* lpfc_sli_sp_intr_handler */
|
} /* lpfc_sli_sp_intr_handler */
|
||||||
|
|
||||||
@ -8919,7 +9013,8 @@ lpfc_sli_fp_intr_handler(int irq, void *dev_id)
|
|||||||
if (lpfc_intr_state_check(phba))
|
if (lpfc_intr_state_check(phba))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
/* Need to read HA REG for FCP ring and other ring events */
|
/* Need to read HA REG for FCP ring and other ring events */
|
||||||
ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &ha_copy))
|
||||||
|
return IRQ_HANDLED;
|
||||||
/* Clear up only attention source related to fast-path */
|
/* Clear up only attention source related to fast-path */
|
||||||
spin_lock_irqsave(&phba->hbalock, iflag);
|
spin_lock_irqsave(&phba->hbalock, iflag);
|
||||||
/*
|
/*
|
||||||
@ -9004,7 +9099,11 @@ lpfc_sli_intr_handler(int irq, void *dev_id)
|
|||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
spin_lock(&phba->hbalock);
|
spin_lock(&phba->hbalock);
|
||||||
phba->ha_copy = readl(phba->HAregaddr);
|
if (lpfc_readl(phba->HAregaddr, &phba->ha_copy)) {
|
||||||
|
spin_unlock(&phba->hbalock);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely(!phba->ha_copy)) {
|
if (unlikely(!phba->ha_copy)) {
|
||||||
spin_unlock(&phba->hbalock);
|
spin_unlock(&phba->hbalock);
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
@ -9026,7 +9125,10 @@ lpfc_sli_intr_handler(int irq, void *dev_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Clear attention sources except link and error attentions */
|
/* Clear attention sources except link and error attentions */
|
||||||
hc_copy = readl(phba->HCregaddr);
|
if (lpfc_readl(phba->HCregaddr, &hc_copy)) {
|
||||||
|
spin_unlock(&phba->hbalock);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
writel(hc_copy & ~(HC_MBINT_ENA | HC_R0INT_ENA | HC_R1INT_ENA
|
writel(hc_copy & ~(HC_MBINT_ENA | HC_R0INT_ENA | HC_R1INT_ENA
|
||||||
| HC_R2INT_ENA | HC_LAINT_ENA | HC_ERINT_ENA),
|
| HC_R2INT_ENA | HC_LAINT_ENA | HC_ERINT_ENA),
|
||||||
phba->HCregaddr);
|
phba->HCregaddr);
|
||||||
@ -10403,7 +10505,6 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
|
|||||||
if (!phba->sli4_hba.pc_sli4_params.supported)
|
if (!phba->sli4_hba.pc_sli4_params.supported)
|
||||||
hw_page_size = SLI4_PAGE_SIZE;
|
hw_page_size = SLI4_PAGE_SIZE;
|
||||||
|
|
||||||
|
|
||||||
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||||
if (!mbox)
|
if (!mbox)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -10413,11 +10514,22 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
|
|||||||
LPFC_MBOX_OPCODE_CQ_CREATE,
|
LPFC_MBOX_OPCODE_CQ_CREATE,
|
||||||
length, LPFC_SLI4_MBX_EMBED);
|
length, LPFC_SLI4_MBX_EMBED);
|
||||||
cq_create = &mbox->u.mqe.un.cq_create;
|
cq_create = &mbox->u.mqe.un.cq_create;
|
||||||
|
shdr = (union lpfc_sli4_cfg_shdr *) &cq_create->header.cfg_shdr;
|
||||||
bf_set(lpfc_mbx_cq_create_num_pages, &cq_create->u.request,
|
bf_set(lpfc_mbx_cq_create_num_pages, &cq_create->u.request,
|
||||||
cq->page_count);
|
cq->page_count);
|
||||||
bf_set(lpfc_cq_context_event, &cq_create->u.request.context, 1);
|
bf_set(lpfc_cq_context_event, &cq_create->u.request.context, 1);
|
||||||
bf_set(lpfc_cq_context_valid, &cq_create->u.request.context, 1);
|
bf_set(lpfc_cq_context_valid, &cq_create->u.request.context, 1);
|
||||||
bf_set(lpfc_cq_eq_id, &cq_create->u.request.context, eq->queue_id);
|
bf_set(lpfc_mbox_hdr_version, &shdr->request,
|
||||||
|
phba->sli4_hba.pc_sli4_params.cqv);
|
||||||
|
if (phba->sli4_hba.pc_sli4_params.cqv == LPFC_Q_CREATE_VERSION_2) {
|
||||||
|
bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request,
|
||||||
|
(PAGE_SIZE/SLI4_PAGE_SIZE));
|
||||||
|
bf_set(lpfc_cq_eq_id_2, &cq_create->u.request.context,
|
||||||
|
eq->queue_id);
|
||||||
|
} else {
|
||||||
|
bf_set(lpfc_cq_eq_id, &cq_create->u.request.context,
|
||||||
|
eq->queue_id);
|
||||||
|
}
|
||||||
switch (cq->entry_count) {
|
switch (cq->entry_count) {
|
||||||
default:
|
default:
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||||
@ -10449,7 +10561,6 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
|
|||||||
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
|
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
|
||||||
|
|
||||||
/* The IOCTL status is embedded in the mailbox subheader. */
|
/* The IOCTL status is embedded in the mailbox subheader. */
|
||||||
shdr = (union lpfc_sli4_cfg_shdr *) &cq_create->header.cfg_shdr;
|
|
||||||
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
|
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
|
||||||
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
|
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
|
||||||
if (shdr_status || shdr_add_status || rc) {
|
if (shdr_status || shdr_add_status || rc) {
|
||||||
@ -10515,20 +10626,20 @@ lpfc_mq_create_fb_init(struct lpfc_hba *phba, struct lpfc_queue *mq,
|
|||||||
bf_set(lpfc_mq_context_valid, &mq_create->u.request.context, 1);
|
bf_set(lpfc_mq_context_valid, &mq_create->u.request.context, 1);
|
||||||
switch (mq->entry_count) {
|
switch (mq->entry_count) {
|
||||||
case 16:
|
case 16:
|
||||||
bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
|
bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
|
||||||
LPFC_MQ_CNT_16);
|
LPFC_MQ_RING_SIZE_16);
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
|
bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
|
||||||
LPFC_MQ_CNT_32);
|
LPFC_MQ_RING_SIZE_32);
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
|
bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
|
||||||
LPFC_MQ_CNT_64);
|
LPFC_MQ_RING_SIZE_64);
|
||||||
break;
|
break;
|
||||||
case 128:
|
case 128:
|
||||||
bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
|
bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
|
||||||
LPFC_MQ_CNT_128);
|
LPFC_MQ_RING_SIZE_128);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list_for_each_entry(dmabuf, &mq->page_list, list) {
|
list_for_each_entry(dmabuf, &mq->page_list, list) {
|
||||||
@ -10586,6 +10697,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
|
|||||||
length, LPFC_SLI4_MBX_EMBED);
|
length, LPFC_SLI4_MBX_EMBED);
|
||||||
|
|
||||||
mq_create_ext = &mbox->u.mqe.un.mq_create_ext;
|
mq_create_ext = &mbox->u.mqe.un.mq_create_ext;
|
||||||
|
shdr = (union lpfc_sli4_cfg_shdr *) &mq_create_ext->header.cfg_shdr;
|
||||||
bf_set(lpfc_mbx_mq_create_ext_num_pages,
|
bf_set(lpfc_mbx_mq_create_ext_num_pages,
|
||||||
&mq_create_ext->u.request, mq->page_count);
|
&mq_create_ext->u.request, mq->page_count);
|
||||||
bf_set(lpfc_mbx_mq_create_ext_async_evt_link,
|
bf_set(lpfc_mbx_mq_create_ext_async_evt_link,
|
||||||
@ -10598,9 +10710,15 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
|
|||||||
&mq_create_ext->u.request, 1);
|
&mq_create_ext->u.request, 1);
|
||||||
bf_set(lpfc_mbx_mq_create_ext_async_evt_sli,
|
bf_set(lpfc_mbx_mq_create_ext_async_evt_sli,
|
||||||
&mq_create_ext->u.request, 1);
|
&mq_create_ext->u.request, 1);
|
||||||
bf_set(lpfc_mq_context_cq_id,
|
|
||||||
&mq_create_ext->u.request.context, cq->queue_id);
|
|
||||||
bf_set(lpfc_mq_context_valid, &mq_create_ext->u.request.context, 1);
|
bf_set(lpfc_mq_context_valid, &mq_create_ext->u.request.context, 1);
|
||||||
|
bf_set(lpfc_mbox_hdr_version, &shdr->request,
|
||||||
|
phba->sli4_hba.pc_sli4_params.mqv);
|
||||||
|
if (phba->sli4_hba.pc_sli4_params.mqv == LPFC_Q_CREATE_VERSION_1)
|
||||||
|
bf_set(lpfc_mbx_mq_create_ext_cq_id, &mq_create_ext->u.request,
|
||||||
|
cq->queue_id);
|
||||||
|
else
|
||||||
|
bf_set(lpfc_mq_context_cq_id, &mq_create_ext->u.request.context,
|
||||||
|
cq->queue_id);
|
||||||
switch (mq->entry_count) {
|
switch (mq->entry_count) {
|
||||||
default:
|
default:
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||||
@ -10610,20 +10728,24 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
/* otherwise default to smallest count (drop through) */
|
/* otherwise default to smallest count (drop through) */
|
||||||
case 16:
|
case 16:
|
||||||
bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
|
bf_set(lpfc_mq_context_ring_size,
|
||||||
LPFC_MQ_CNT_16);
|
&mq_create_ext->u.request.context,
|
||||||
|
LPFC_MQ_RING_SIZE_16);
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
|
bf_set(lpfc_mq_context_ring_size,
|
||||||
LPFC_MQ_CNT_32);
|
&mq_create_ext->u.request.context,
|
||||||
|
LPFC_MQ_RING_SIZE_32);
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
|
bf_set(lpfc_mq_context_ring_size,
|
||||||
LPFC_MQ_CNT_64);
|
&mq_create_ext->u.request.context,
|
||||||
|
LPFC_MQ_RING_SIZE_64);
|
||||||
break;
|
break;
|
||||||
case 128:
|
case 128:
|
||||||
bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
|
bf_set(lpfc_mq_context_ring_size,
|
||||||
LPFC_MQ_CNT_128);
|
&mq_create_ext->u.request.context,
|
||||||
|
LPFC_MQ_RING_SIZE_128);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list_for_each_entry(dmabuf, &mq->page_list, list) {
|
list_for_each_entry(dmabuf, &mq->page_list, list) {
|
||||||
@ -10634,7 +10756,6 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
|
|||||||
putPaddrHigh(dmabuf->phys);
|
putPaddrHigh(dmabuf->phys);
|
||||||
}
|
}
|
||||||
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
|
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
|
||||||
shdr = (union lpfc_sli4_cfg_shdr *) &mq_create_ext->header.cfg_shdr;
|
|
||||||
mq->queue_id = bf_get(lpfc_mbx_mq_create_q_id,
|
mq->queue_id = bf_get(lpfc_mbx_mq_create_q_id,
|
||||||
&mq_create_ext->u.response);
|
&mq_create_ext->u.response);
|
||||||
if (rc != MBX_SUCCESS) {
|
if (rc != MBX_SUCCESS) {
|
||||||
@ -10711,6 +10832,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
|
|||||||
uint32_t shdr_status, shdr_add_status;
|
uint32_t shdr_status, shdr_add_status;
|
||||||
union lpfc_sli4_cfg_shdr *shdr;
|
union lpfc_sli4_cfg_shdr *shdr;
|
||||||
uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
|
uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
|
||||||
|
struct dma_address *page;
|
||||||
|
|
||||||
if (!phba->sli4_hba.pc_sli4_params.supported)
|
if (!phba->sli4_hba.pc_sli4_params.supported)
|
||||||
hw_page_size = SLI4_PAGE_SIZE;
|
hw_page_size = SLI4_PAGE_SIZE;
|
||||||
@ -10724,20 +10846,42 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
|
|||||||
LPFC_MBOX_OPCODE_FCOE_WQ_CREATE,
|
LPFC_MBOX_OPCODE_FCOE_WQ_CREATE,
|
||||||
length, LPFC_SLI4_MBX_EMBED);
|
length, LPFC_SLI4_MBX_EMBED);
|
||||||
wq_create = &mbox->u.mqe.un.wq_create;
|
wq_create = &mbox->u.mqe.un.wq_create;
|
||||||
|
shdr = (union lpfc_sli4_cfg_shdr *) &wq_create->header.cfg_shdr;
|
||||||
bf_set(lpfc_mbx_wq_create_num_pages, &wq_create->u.request,
|
bf_set(lpfc_mbx_wq_create_num_pages, &wq_create->u.request,
|
||||||
wq->page_count);
|
wq->page_count);
|
||||||
bf_set(lpfc_mbx_wq_create_cq_id, &wq_create->u.request,
|
bf_set(lpfc_mbx_wq_create_cq_id, &wq_create->u.request,
|
||||||
cq->queue_id);
|
cq->queue_id);
|
||||||
|
bf_set(lpfc_mbox_hdr_version, &shdr->request,
|
||||||
|
phba->sli4_hba.pc_sli4_params.wqv);
|
||||||
|
if (phba->sli4_hba.pc_sli4_params.wqv == LPFC_Q_CREATE_VERSION_1) {
|
||||||
|
bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1,
|
||||||
|
wq->entry_count);
|
||||||
|
switch (wq->entry_size) {
|
||||||
|
default:
|
||||||
|
case 64:
|
||||||
|
bf_set(lpfc_mbx_wq_create_wqe_size,
|
||||||
|
&wq_create->u.request_1,
|
||||||
|
LPFC_WQ_WQE_SIZE_64);
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
bf_set(lpfc_mbx_wq_create_wqe_size,
|
||||||
|
&wq_create->u.request_1,
|
||||||
|
LPFC_WQ_WQE_SIZE_128);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bf_set(lpfc_mbx_wq_create_page_size, &wq_create->u.request_1,
|
||||||
|
(PAGE_SIZE/SLI4_PAGE_SIZE));
|
||||||
|
page = wq_create->u.request_1.page;
|
||||||
|
} else {
|
||||||
|
page = wq_create->u.request.page;
|
||||||
|
}
|
||||||
list_for_each_entry(dmabuf, &wq->page_list, list) {
|
list_for_each_entry(dmabuf, &wq->page_list, list) {
|
||||||
memset(dmabuf->virt, 0, hw_page_size);
|
memset(dmabuf->virt, 0, hw_page_size);
|
||||||
wq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
|
page[dmabuf->buffer_tag].addr_lo = putPaddrLow(dmabuf->phys);
|
||||||
putPaddrLow(dmabuf->phys);
|
page[dmabuf->buffer_tag].addr_hi = putPaddrHigh(dmabuf->phys);
|
||||||
wq_create->u.request.page[dmabuf->buffer_tag].addr_hi =
|
|
||||||
putPaddrHigh(dmabuf->phys);
|
|
||||||
}
|
}
|
||||||
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
|
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
|
||||||
/* The IOCTL status is embedded in the mailbox subheader. */
|
/* The IOCTL status is embedded in the mailbox subheader. */
|
||||||
shdr = (union lpfc_sli4_cfg_shdr *) &wq_create->header.cfg_shdr;
|
|
||||||
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
|
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
|
||||||
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
|
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
|
||||||
if (shdr_status || shdr_add_status || rc) {
|
if (shdr_status || shdr_add_status || rc) {
|
||||||
@ -10815,37 +10959,51 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
|
|||||||
LPFC_MBOX_OPCODE_FCOE_RQ_CREATE,
|
LPFC_MBOX_OPCODE_FCOE_RQ_CREATE,
|
||||||
length, LPFC_SLI4_MBX_EMBED);
|
length, LPFC_SLI4_MBX_EMBED);
|
||||||
rq_create = &mbox->u.mqe.un.rq_create;
|
rq_create = &mbox->u.mqe.un.rq_create;
|
||||||
switch (hrq->entry_count) {
|
shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr;
|
||||||
default:
|
bf_set(lpfc_mbox_hdr_version, &shdr->request,
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
phba->sli4_hba.pc_sli4_params.rqv);
|
||||||
"2535 Unsupported RQ count. (%d)\n",
|
if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
|
||||||
hrq->entry_count);
|
bf_set(lpfc_rq_context_rqe_count_1,
|
||||||
if (hrq->entry_count < 512)
|
&rq_create->u.request.context,
|
||||||
return -EINVAL;
|
hrq->entry_count);
|
||||||
/* otherwise default to smallest count (drop through) */
|
rq_create->u.request.context.buffer_size = LPFC_HDR_BUF_SIZE;
|
||||||
case 512:
|
} else {
|
||||||
bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
|
switch (hrq->entry_count) {
|
||||||
LPFC_RQ_RING_SIZE_512);
|
default:
|
||||||
break;
|
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||||
case 1024:
|
"2535 Unsupported RQ count. (%d)\n",
|
||||||
bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
|
hrq->entry_count);
|
||||||
LPFC_RQ_RING_SIZE_1024);
|
if (hrq->entry_count < 512)
|
||||||
break;
|
return -EINVAL;
|
||||||
case 2048:
|
/* otherwise default to smallest count (drop through) */
|
||||||
bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
|
case 512:
|
||||||
LPFC_RQ_RING_SIZE_2048);
|
bf_set(lpfc_rq_context_rqe_count,
|
||||||
break;
|
&rq_create->u.request.context,
|
||||||
case 4096:
|
LPFC_RQ_RING_SIZE_512);
|
||||||
bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
|
break;
|
||||||
LPFC_RQ_RING_SIZE_4096);
|
case 1024:
|
||||||
break;
|
bf_set(lpfc_rq_context_rqe_count,
|
||||||
|
&rq_create->u.request.context,
|
||||||
|
LPFC_RQ_RING_SIZE_1024);
|
||||||
|
break;
|
||||||
|
case 2048:
|
||||||
|
bf_set(lpfc_rq_context_rqe_count,
|
||||||
|
&rq_create->u.request.context,
|
||||||
|
LPFC_RQ_RING_SIZE_2048);
|
||||||
|
break;
|
||||||
|
case 4096:
|
||||||
|
bf_set(lpfc_rq_context_rqe_count,
|
||||||
|
&rq_create->u.request.context,
|
||||||
|
LPFC_RQ_RING_SIZE_4096);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
|
||||||
|
LPFC_HDR_BUF_SIZE);
|
||||||
}
|
}
|
||||||
bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
|
bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
|
||||||
cq->queue_id);
|
cq->queue_id);
|
||||||
bf_set(lpfc_mbx_rq_create_num_pages, &rq_create->u.request,
|
bf_set(lpfc_mbx_rq_create_num_pages, &rq_create->u.request,
|
||||||
hrq->page_count);
|
hrq->page_count);
|
||||||
bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
|
|
||||||
LPFC_HDR_BUF_SIZE);
|
|
||||||
list_for_each_entry(dmabuf, &hrq->page_list, list) {
|
list_for_each_entry(dmabuf, &hrq->page_list, list) {
|
||||||
memset(dmabuf->virt, 0, hw_page_size);
|
memset(dmabuf->virt, 0, hw_page_size);
|
||||||
rq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
|
rq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
|
||||||
@ -10855,7 +11013,6 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
|
|||||||
}
|
}
|
||||||
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
|
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
|
||||||
/* The IOCTL status is embedded in the mailbox subheader. */
|
/* The IOCTL status is embedded in the mailbox subheader. */
|
||||||
shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr;
|
|
||||||
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
|
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
|
||||||
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
|
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
|
||||||
if (shdr_status || shdr_add_status || rc) {
|
if (shdr_status || shdr_add_status || rc) {
|
||||||
@ -10881,37 +11038,50 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
|
|||||||
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
|
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
|
||||||
LPFC_MBOX_OPCODE_FCOE_RQ_CREATE,
|
LPFC_MBOX_OPCODE_FCOE_RQ_CREATE,
|
||||||
length, LPFC_SLI4_MBX_EMBED);
|
length, LPFC_SLI4_MBX_EMBED);
|
||||||
switch (drq->entry_count) {
|
bf_set(lpfc_mbox_hdr_version, &shdr->request,
|
||||||
default:
|
phba->sli4_hba.pc_sli4_params.rqv);
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
|
||||||
"2536 Unsupported RQ count. (%d)\n",
|
bf_set(lpfc_rq_context_rqe_count_1,
|
||||||
drq->entry_count);
|
&rq_create->u.request.context,
|
||||||
if (drq->entry_count < 512)
|
hrq->entry_count);
|
||||||
return -EINVAL;
|
rq_create->u.request.context.buffer_size = LPFC_DATA_BUF_SIZE;
|
||||||
/* otherwise default to smallest count (drop through) */
|
} else {
|
||||||
case 512:
|
switch (drq->entry_count) {
|
||||||
bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
|
default:
|
||||||
LPFC_RQ_RING_SIZE_512);
|
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||||
break;
|
"2536 Unsupported RQ count. (%d)\n",
|
||||||
case 1024:
|
drq->entry_count);
|
||||||
bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
|
if (drq->entry_count < 512)
|
||||||
LPFC_RQ_RING_SIZE_1024);
|
return -EINVAL;
|
||||||
break;
|
/* otherwise default to smallest count (drop through) */
|
||||||
case 2048:
|
case 512:
|
||||||
bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
|
bf_set(lpfc_rq_context_rqe_count,
|
||||||
LPFC_RQ_RING_SIZE_2048);
|
&rq_create->u.request.context,
|
||||||
break;
|
LPFC_RQ_RING_SIZE_512);
|
||||||
case 4096:
|
break;
|
||||||
bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
|
case 1024:
|
||||||
LPFC_RQ_RING_SIZE_4096);
|
bf_set(lpfc_rq_context_rqe_count,
|
||||||
break;
|
&rq_create->u.request.context,
|
||||||
|
LPFC_RQ_RING_SIZE_1024);
|
||||||
|
break;
|
||||||
|
case 2048:
|
||||||
|
bf_set(lpfc_rq_context_rqe_count,
|
||||||
|
&rq_create->u.request.context,
|
||||||
|
LPFC_RQ_RING_SIZE_2048);
|
||||||
|
break;
|
||||||
|
case 4096:
|
||||||
|
bf_set(lpfc_rq_context_rqe_count,
|
||||||
|
&rq_create->u.request.context,
|
||||||
|
LPFC_RQ_RING_SIZE_4096);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
|
||||||
|
LPFC_DATA_BUF_SIZE);
|
||||||
}
|
}
|
||||||
bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
|
bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
|
||||||
cq->queue_id);
|
cq->queue_id);
|
||||||
bf_set(lpfc_mbx_rq_create_num_pages, &rq_create->u.request,
|
bf_set(lpfc_mbx_rq_create_num_pages, &rq_create->u.request,
|
||||||
drq->page_count);
|
drq->page_count);
|
||||||
bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
|
|
||||||
LPFC_DATA_BUF_SIZE);
|
|
||||||
list_for_each_entry(dmabuf, &drq->page_list, list) {
|
list_for_each_entry(dmabuf, &drq->page_list, list) {
|
||||||
rq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
|
rq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
|
||||||
putPaddrLow(dmabuf->phys);
|
putPaddrLow(dmabuf->phys);
|
||||||
@ -11580,6 +11750,7 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
|
|||||||
static char *rctl_names[] = FC_RCTL_NAMES_INIT;
|
static char *rctl_names[] = FC_RCTL_NAMES_INIT;
|
||||||
char *type_names[] = FC_TYPE_NAMES_INIT;
|
char *type_names[] = FC_TYPE_NAMES_INIT;
|
||||||
struct fc_vft_header *fc_vft_hdr;
|
struct fc_vft_header *fc_vft_hdr;
|
||||||
|
uint32_t *header = (uint32_t *) fc_hdr;
|
||||||
|
|
||||||
switch (fc_hdr->fh_r_ctl) {
|
switch (fc_hdr->fh_r_ctl) {
|
||||||
case FC_RCTL_DD_UNCAT: /* uncategorized information */
|
case FC_RCTL_DD_UNCAT: /* uncategorized information */
|
||||||
@ -11628,10 +11799,15 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
|
|||||||
default:
|
default:
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||||
"2538 Received frame rctl:%s type:%s\n",
|
"2538 Received frame rctl:%s type:%s "
|
||||||
|
"Frame Data:%08x %08x %08x %08x %08x %08x\n",
|
||||||
rctl_names[fc_hdr->fh_r_ctl],
|
rctl_names[fc_hdr->fh_r_ctl],
|
||||||
type_names[fc_hdr->fh_type]);
|
type_names[fc_hdr->fh_type],
|
||||||
|
be32_to_cpu(header[0]), be32_to_cpu(header[1]),
|
||||||
|
be32_to_cpu(header[2]), be32_to_cpu(header[3]),
|
||||||
|
be32_to_cpu(header[4]), be32_to_cpu(header[5]));
|
||||||
return 0;
|
return 0;
|
||||||
drop:
|
drop:
|
||||||
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
|
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
|
||||||
@ -11928,17 +12104,17 @@ lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lpfc_sli4_seq_abort_acc_cmpl - Accept seq abort iocb complete handler
|
* lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler
|
||||||
* @phba: Pointer to HBA context object.
|
* @phba: Pointer to HBA context object.
|
||||||
* @cmd_iocbq: pointer to the command iocbq structure.
|
* @cmd_iocbq: pointer to the command iocbq structure.
|
||||||
* @rsp_iocbq: pointer to the response iocbq structure.
|
* @rsp_iocbq: pointer to the response iocbq structure.
|
||||||
*
|
*
|
||||||
* This function handles the sequence abort accept iocb command complete
|
* This function handles the sequence abort response iocb command complete
|
||||||
* event. It properly releases the memory allocated to the sequence abort
|
* event. It properly releases the memory allocated to the sequence abort
|
||||||
* accept iocb.
|
* accept iocb.
|
||||||
**/
|
**/
|
||||||
static void
|
static void
|
||||||
lpfc_sli4_seq_abort_acc_cmpl(struct lpfc_hba *phba,
|
lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba,
|
||||||
struct lpfc_iocbq *cmd_iocbq,
|
struct lpfc_iocbq *cmd_iocbq,
|
||||||
struct lpfc_iocbq *rsp_iocbq)
|
struct lpfc_iocbq *rsp_iocbq)
|
||||||
{
|
{
|
||||||
@ -11947,15 +12123,15 @@ lpfc_sli4_seq_abort_acc_cmpl(struct lpfc_hba *phba,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lpfc_sli4_seq_abort_acc - Accept sequence abort
|
* lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort
|
||||||
* @phba: Pointer to HBA context object.
|
* @phba: Pointer to HBA context object.
|
||||||
* @fc_hdr: pointer to a FC frame header.
|
* @fc_hdr: pointer to a FC frame header.
|
||||||
*
|
*
|
||||||
* This function sends a basic accept to a previous unsol sequence abort
|
* This function sends a basic response to a previous unsol sequence abort
|
||||||
* event after aborting the sequence handling.
|
* event after aborting the sequence handling.
|
||||||
**/
|
**/
|
||||||
static void
|
static void
|
||||||
lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
|
lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
|
||||||
struct fc_frame_header *fc_hdr)
|
struct fc_frame_header *fc_hdr)
|
||||||
{
|
{
|
||||||
struct lpfc_iocbq *ctiocb = NULL;
|
struct lpfc_iocbq *ctiocb = NULL;
|
||||||
@ -11963,6 +12139,7 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
|
|||||||
uint16_t oxid, rxid;
|
uint16_t oxid, rxid;
|
||||||
uint32_t sid, fctl;
|
uint32_t sid, fctl;
|
||||||
IOCB_t *icmd;
|
IOCB_t *icmd;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!lpfc_is_link_up(phba))
|
if (!lpfc_is_link_up(phba))
|
||||||
return;
|
return;
|
||||||
@ -11983,7 +12160,7 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
|
|||||||
+ phba->sli4_hba.max_cfg_param.xri_base))
|
+ phba->sli4_hba.max_cfg_param.xri_base))
|
||||||
lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0);
|
lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0);
|
||||||
|
|
||||||
/* Allocate buffer for acc iocb */
|
/* Allocate buffer for rsp iocb */
|
||||||
ctiocb = lpfc_sli_get_iocbq(phba);
|
ctiocb = lpfc_sli_get_iocbq(phba);
|
||||||
if (!ctiocb)
|
if (!ctiocb)
|
||||||
return;
|
return;
|
||||||
@ -12008,32 +12185,54 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
|
|||||||
|
|
||||||
ctiocb->iocb_cmpl = NULL;
|
ctiocb->iocb_cmpl = NULL;
|
||||||
ctiocb->vport = phba->pport;
|
ctiocb->vport = phba->pport;
|
||||||
ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_acc_cmpl;
|
ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl;
|
||||||
|
ctiocb->sli4_xritag = NO_XRI;
|
||||||
|
|
||||||
|
/* If the oxid maps to the FCP XRI range or if it is out of range,
|
||||||
|
* send a BLS_RJT. The driver no longer has that exchange.
|
||||||
|
* Override the IOCB for a BA_RJT.
|
||||||
|
*/
|
||||||
|
if (oxid > (phba->sli4_hba.max_cfg_param.max_xri +
|
||||||
|
phba->sli4_hba.max_cfg_param.xri_base) ||
|
||||||
|
oxid > (lpfc_sli4_get_els_iocb_cnt(phba) +
|
||||||
|
phba->sli4_hba.max_cfg_param.xri_base)) {
|
||||||
|
icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT;
|
||||||
|
bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0);
|
||||||
|
bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID);
|
||||||
|
bf_set(lpfc_rsn_code, &icmd->un.bls_rsp, FC_BA_RJT_UNABLE);
|
||||||
|
}
|
||||||
|
|
||||||
if (fctl & FC_FC_EX_CTX) {
|
if (fctl & FC_FC_EX_CTX) {
|
||||||
/* ABTS sent by responder to CT exchange, construction
|
/* ABTS sent by responder to CT exchange, construction
|
||||||
* of BA_ACC will use OX_ID from ABTS for the XRI_TAG
|
* of BA_ACC will use OX_ID from ABTS for the XRI_TAG
|
||||||
* field and RX_ID from ABTS for RX_ID field.
|
* field and RX_ID from ABTS for RX_ID field.
|
||||||
*/
|
*/
|
||||||
bf_set(lpfc_abts_orig, &icmd->un.bls_acc, LPFC_ABTS_UNSOL_RSP);
|
bf_set(lpfc_abts_orig, &icmd->un.bls_rsp, LPFC_ABTS_UNSOL_RSP);
|
||||||
bf_set(lpfc_abts_rxid, &icmd->un.bls_acc, rxid);
|
bf_set(lpfc_abts_rxid, &icmd->un.bls_rsp, rxid);
|
||||||
ctiocb->sli4_xritag = oxid;
|
|
||||||
} else {
|
} else {
|
||||||
/* ABTS sent by initiator to CT exchange, construction
|
/* ABTS sent by initiator to CT exchange, construction
|
||||||
* of BA_ACC will need to allocate a new XRI as for the
|
* of BA_ACC will need to allocate a new XRI as for the
|
||||||
* XRI_TAG and RX_ID fields.
|
* XRI_TAG and RX_ID fields.
|
||||||
*/
|
*/
|
||||||
bf_set(lpfc_abts_orig, &icmd->un.bls_acc, LPFC_ABTS_UNSOL_INT);
|
bf_set(lpfc_abts_orig, &icmd->un.bls_rsp, LPFC_ABTS_UNSOL_INT);
|
||||||
bf_set(lpfc_abts_rxid, &icmd->un.bls_acc, NO_XRI);
|
bf_set(lpfc_abts_rxid, &icmd->un.bls_rsp, NO_XRI);
|
||||||
ctiocb->sli4_xritag = NO_XRI;
|
|
||||||
}
|
}
|
||||||
bf_set(lpfc_abts_oxid, &icmd->un.bls_acc, oxid);
|
bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid);
|
||||||
|
|
||||||
/* Xmit CT abts accept on exchange <xid> */
|
/* Xmit CT abts response on exchange <xid> */
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||||
"1200 Xmit CT ABTS ACC on exchange x%x Data: x%x\n",
|
"1200 Send BLS cmd x%x on oxid x%x Data: x%x\n",
|
||||||
CMD_XMIT_BLS_RSP64_CX, phba->link_state);
|
icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state);
|
||||||
lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
|
|
||||||
|
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
|
||||||
|
if (rc == IOCB_ERROR) {
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
||||||
|
"2925 Failed to issue CT ABTS RSP x%x on "
|
||||||
|
"xri x%x, Data x%x\n",
|
||||||
|
icmd->un.xseq64.w5.hcsw.Rctl, oxid,
|
||||||
|
phba->link_state);
|
||||||
|
lpfc_sli_release_iocbq(phba, ctiocb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12081,7 +12280,7 @@ lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport,
|
|||||||
lpfc_in_buf_free(phba, &dmabuf->dbuf);
|
lpfc_in_buf_free(phba, &dmabuf->dbuf);
|
||||||
}
|
}
|
||||||
/* Send basic accept (BA_ACC) to the abort requester */
|
/* Send basic accept (BA_ACC) to the abort requester */
|
||||||
lpfc_sli4_seq_abort_acc(phba, &fc_hdr);
|
lpfc_sli4_seq_abort_rsp(phba, &fc_hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* This file is part of the Emulex Linux Device Driver for *
|
* This file is part of the Emulex Linux Device Driver for *
|
||||||
* Fibre Channel Host Bus Adapters. *
|
* Fibre Channel Host Bus Adapters. *
|
||||||
* Copyright (C) 2009 Emulex. All rights reserved. *
|
* Copyright (C) 2009-2011 Emulex. All rights reserved. *
|
||||||
* EMULEX and SLI are trademarks of Emulex. *
|
* EMULEX and SLI are trademarks of Emulex. *
|
||||||
* www.emulex.com *
|
* www.emulex.com *
|
||||||
* *
|
* *
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* included with this package. *
|
* included with this package. *
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
||||||
#define LPFC_DRIVER_VERSION "8.3.21"
|
#define LPFC_DRIVER_VERSION "8.3.22"
|
||||||
#define LPFC_DRIVER_NAME "lpfc"
|
#define LPFC_DRIVER_NAME "lpfc"
|
||||||
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
|
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
|
||||||
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
|
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
|
||||||
|
@ -1747,6 +1747,54 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _base_display_hp_branding - Display branding string
|
||||||
|
* @ioc: per adapter object
|
||||||
|
*
|
||||||
|
* Return nothing.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
_base_display_hp_branding(struct MPT2SAS_ADAPTER *ioc)
|
||||||
|
{
|
||||||
|
if (ioc->pdev->subsystem_vendor != MPT2SAS_HP_3PAR_SSVID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (ioc->pdev->device) {
|
||||||
|
case MPI2_MFGPAGE_DEVID_SAS2004:
|
||||||
|
switch (ioc->pdev->subsystem_device) {
|
||||||
|
case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID:
|
||||||
|
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
||||||
|
MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MPI2_MFGPAGE_DEVID_SAS2308_2:
|
||||||
|
switch (ioc->pdev->subsystem_device) {
|
||||||
|
case MPT2SAS_HP_2_4_INTERNAL_SSDID:
|
||||||
|
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
||||||
|
MPT2SAS_HP_2_4_INTERNAL_BRANDING);
|
||||||
|
break;
|
||||||
|
case MPT2SAS_HP_2_4_EXTERNAL_SSDID:
|
||||||
|
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
||||||
|
MPT2SAS_HP_2_4_EXTERNAL_BRANDING);
|
||||||
|
break;
|
||||||
|
case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID:
|
||||||
|
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
||||||
|
MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING);
|
||||||
|
break;
|
||||||
|
case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID:
|
||||||
|
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
||||||
|
MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _base_display_ioc_capabilities - Disply IOC's capabilities.
|
* _base_display_ioc_capabilities - Disply IOC's capabilities.
|
||||||
* @ioc: per adapter object
|
* @ioc: per adapter object
|
||||||
@ -1778,6 +1826,7 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
|
|||||||
|
|
||||||
_base_display_dell_branding(ioc);
|
_base_display_dell_branding(ioc);
|
||||||
_base_display_intel_branding(ioc);
|
_base_display_intel_branding(ioc);
|
||||||
|
_base_display_hp_branding(ioc);
|
||||||
|
|
||||||
printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
|
printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
|
||||||
|
|
||||||
|
@ -168,6 +168,26 @@
|
|||||||
#define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E
|
#define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E
|
||||||
#define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F
|
#define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HP HBA branding
|
||||||
|
*/
|
||||||
|
#define MPT2SAS_HP_3PAR_SSVID 0x1590
|
||||||
|
#define MPT2SAS_HP_2_4_INTERNAL_BRANDING "HP H220 Host Bus Adapter"
|
||||||
|
#define MPT2SAS_HP_2_4_EXTERNAL_BRANDING "HP H221 Host Bus Adapter"
|
||||||
|
#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING "HP H222 Host Bus Adapter"
|
||||||
|
#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING "HP H220i Host Bus Adapter"
|
||||||
|
#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING "HP H210i Host Bus Adapter"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HO HBA SSDIDs
|
||||||
|
*/
|
||||||
|
#define MPT2SAS_HP_2_4_INTERNAL_SSDID 0x0041
|
||||||
|
#define MPT2SAS_HP_2_4_EXTERNAL_SSDID 0x0042
|
||||||
|
#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID 0x0043
|
||||||
|
#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID 0x0044
|
||||||
|
#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID 0x0046
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* per target private data
|
* per target private data
|
||||||
*/
|
*/
|
||||||
|
@ -663,6 +663,13 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
|
|||||||
{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
|
{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
|
||||||
{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
|
{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
|
||||||
{ PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
|
{ PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
|
||||||
|
{ PCI_VDEVICE(TTI, 0x2710), chip_9480 },
|
||||||
|
{ PCI_VDEVICE(TTI, 0x2720), chip_9480 },
|
||||||
|
{ PCI_VDEVICE(TTI, 0x2721), chip_9480 },
|
||||||
|
{ PCI_VDEVICE(TTI, 0x2722), chip_9480 },
|
||||||
|
{ PCI_VDEVICE(TTI, 0x2740), chip_9480 },
|
||||||
|
{ PCI_VDEVICE(TTI, 0x2744), chip_9480 },
|
||||||
|
{ PCI_VDEVICE(TTI, 0x2760), chip_9480 },
|
||||||
|
|
||||||
{ } /* terminate list */
|
{ } /* terminate list */
|
||||||
};
|
};
|
||||||
|
@ -53,6 +53,9 @@
|
|||||||
#define PCI_DEVICE_ID_QLOGIC_ISP8022 0x8022
|
#define PCI_DEVICE_ID_QLOGIC_ISP8022 0x8022
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ISP4XXX_PCI_FN_1 0x1
|
||||||
|
#define ISP4XXX_PCI_FN_2 0x3
|
||||||
|
|
||||||
#define QLA_SUCCESS 0
|
#define QLA_SUCCESS 0
|
||||||
#define QLA_ERROR 1
|
#define QLA_ERROR 1
|
||||||
|
|
||||||
@ -233,9 +236,6 @@ struct ddb_entry {
|
|||||||
|
|
||||||
unsigned long flags; /* DDB Flags */
|
unsigned long flags; /* DDB Flags */
|
||||||
|
|
||||||
unsigned long dev_scan_wait_to_start_relogin;
|
|
||||||
unsigned long dev_scan_wait_to_complete_relogin;
|
|
||||||
|
|
||||||
uint16_t fw_ddb_index; /* DDB firmware index */
|
uint16_t fw_ddb_index; /* DDB firmware index */
|
||||||
uint16_t options;
|
uint16_t options;
|
||||||
uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */
|
uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */
|
||||||
@ -289,8 +289,6 @@ struct ddb_entry {
|
|||||||
* DDB flags.
|
* DDB flags.
|
||||||
*/
|
*/
|
||||||
#define DF_RELOGIN 0 /* Relogin to device */
|
#define DF_RELOGIN 0 /* Relogin to device */
|
||||||
#define DF_NO_RELOGIN 1 /* Do not relogin if IOCTL
|
|
||||||
* logged it out */
|
|
||||||
#define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */
|
#define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */
|
||||||
#define DF_FO_MASKED 3
|
#define DF_FO_MASKED 3
|
||||||
|
|
||||||
@ -376,7 +374,7 @@ struct scsi_qla_host {
|
|||||||
#define AF_LINK_UP 8 /* 0x00000100 */
|
#define AF_LINK_UP 8 /* 0x00000100 */
|
||||||
#define AF_IRQ_ATTACHED 10 /* 0x00000400 */
|
#define AF_IRQ_ATTACHED 10 /* 0x00000400 */
|
||||||
#define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */
|
#define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */
|
||||||
#define AF_HBA_GOING_AWAY 12 /* 0x00001000 */
|
#define AF_HA_REMOVAL 12 /* 0x00001000 */
|
||||||
#define AF_INTx_ENABLED 15 /* 0x00008000 */
|
#define AF_INTx_ENABLED 15 /* 0x00008000 */
|
||||||
#define AF_MSI_ENABLED 16 /* 0x00010000 */
|
#define AF_MSI_ENABLED 16 /* 0x00010000 */
|
||||||
#define AF_MSIX_ENABLED 17 /* 0x00020000 */
|
#define AF_MSIX_ENABLED 17 /* 0x00020000 */
|
||||||
@ -479,7 +477,6 @@ struct scsi_qla_host {
|
|||||||
uint32_t timer_active;
|
uint32_t timer_active;
|
||||||
|
|
||||||
/* Recovery Timers */
|
/* Recovery Timers */
|
||||||
uint32_t discovery_wait;
|
|
||||||
atomic_t check_relogin_timeouts;
|
atomic_t check_relogin_timeouts;
|
||||||
uint32_t retry_reset_ha_cnt;
|
uint32_t retry_reset_ha_cnt;
|
||||||
uint32_t isp_reset_timer; /* reset test timer */
|
uint32_t isp_reset_timer; /* reset test timer */
|
||||||
@ -765,6 +762,5 @@ static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a)
|
|||||||
/* Defines for process_aen() */
|
/* Defines for process_aen() */
|
||||||
#define PROCESS_ALL_AENS 0
|
#define PROCESS_ALL_AENS 0
|
||||||
#define FLUSH_DDB_CHANGED_AENS 1
|
#define FLUSH_DDB_CHANGED_AENS 1
|
||||||
#define RELOGIN_DDB_CHANGED_AENS 2
|
|
||||||
|
|
||||||
#endif /*_QLA4XXX_H */
|
#endif /*_QLA4XXX_H */
|
||||||
|
@ -455,6 +455,7 @@ struct addr_ctrl_blk {
|
|||||||
uint8_t res0; /* 07 */
|
uint8_t res0; /* 07 */
|
||||||
uint16_t eth_mtu_size; /* 08-09 */
|
uint16_t eth_mtu_size; /* 08-09 */
|
||||||
uint16_t add_fw_options; /* 0A-0B */
|
uint16_t add_fw_options; /* 0A-0B */
|
||||||
|
#define SERIALIZE_TASK_MGMT 0x0400
|
||||||
|
|
||||||
uint8_t hb_interval; /* 0C */
|
uint8_t hb_interval; /* 0C */
|
||||||
uint8_t inst_num; /* 0D */
|
uint8_t inst_num; /* 0D */
|
||||||
|
@ -136,7 +136,6 @@ void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha);
|
|||||||
void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha);
|
void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha);
|
||||||
|
|
||||||
extern int ql4xextended_error_logging;
|
extern int ql4xextended_error_logging;
|
||||||
extern int ql4xdiscoverywait;
|
|
||||||
extern int ql4xdontresethba;
|
extern int ql4xdontresethba;
|
||||||
extern int ql4xenablemsix;
|
extern int ql4xenablemsix;
|
||||||
|
|
||||||
|
@ -723,13 +723,38 @@ int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err)
|
|||||||
return relogin;
|
return relogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qla4xxx_flush_AENS(struct scsi_qla_host *ha)
|
||||||
|
{
|
||||||
|
unsigned long wtime;
|
||||||
|
|
||||||
|
/* Flush the 0x8014 AEN from the firmware as a result of
|
||||||
|
* Auto connect. We are basically doing get_firmware_ddb()
|
||||||
|
* to determine whether we need to log back in or not.
|
||||||
|
* Trying to do a set ddb before we have processed 0x8014
|
||||||
|
* will result in another set_ddb() for the same ddb. In other
|
||||||
|
* words there will be stale entries in the aen_q.
|
||||||
|
*/
|
||||||
|
wtime = jiffies + (2 * HZ);
|
||||||
|
do {
|
||||||
|
if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS)
|
||||||
|
if (ha->firmware_state & (BIT_2 | BIT_0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
|
||||||
|
qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
|
||||||
|
|
||||||
|
msleep(1000);
|
||||||
|
} while (!time_after_eq(jiffies, wtime));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qla4xxx_configure_ddbs - builds driver ddb list
|
* qla4xxx_build_ddb_list - builds driver ddb list
|
||||||
* @ha: Pointer to host adapter structure.
|
* @ha: Pointer to host adapter structure.
|
||||||
*
|
*
|
||||||
* This routine searches for all valid firmware ddb entries and builds
|
* This routine searches for all valid firmware ddb entries and builds
|
||||||
* an internal ddb list. Ddbs that are considered valid are those with
|
* an internal ddb list. Ddbs that are considered valid are those with
|
||||||
* a device state of SESSION_ACTIVE.
|
* a device state of SESSION_ACTIVE.
|
||||||
|
* A relogin (set_ddb) is issued for DDBs that are not online.
|
||||||
**/
|
**/
|
||||||
static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
|
static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
|
||||||
{
|
{
|
||||||
@ -744,6 +769,8 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
|
|||||||
uint32_t ipv6_device;
|
uint32_t ipv6_device;
|
||||||
uint32_t new_tgt;
|
uint32_t new_tgt;
|
||||||
|
|
||||||
|
qla4xxx_flush_AENS(ha);
|
||||||
|
|
||||||
fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
|
fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
|
||||||
&fw_ddb_entry_dma, GFP_KERNEL);
|
&fw_ddb_entry_dma, GFP_KERNEL);
|
||||||
if (fw_ddb_entry == NULL) {
|
if (fw_ddb_entry == NULL) {
|
||||||
@ -847,144 +874,6 @@ exit_build_ddb_list_no_free:
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct qla4_relog_scan {
|
|
||||||
int halt_wait;
|
|
||||||
uint32_t conn_err;
|
|
||||||
uint32_t fw_ddb_index;
|
|
||||||
uint32_t next_fw_ddb_index;
|
|
||||||
uint32_t fw_ddb_device_state;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int qla4_test_rdy(struct scsi_qla_host *ha, struct qla4_relog_scan *rs)
|
|
||||||
{
|
|
||||||
struct ddb_entry *ddb_entry;
|
|
||||||
|
|
||||||
if (qla4_is_relogin_allowed(ha, rs->conn_err)) {
|
|
||||||
/* We either have a device that is in
|
|
||||||
* the process of relogging in or a
|
|
||||||
* device that is waiting to be
|
|
||||||
* relogged in */
|
|
||||||
rs->halt_wait = 0;
|
|
||||||
|
|
||||||
ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha,
|
|
||||||
rs->fw_ddb_index);
|
|
||||||
if (ddb_entry == NULL)
|
|
||||||
return QLA_ERROR;
|
|
||||||
|
|
||||||
if (ddb_entry->dev_scan_wait_to_start_relogin != 0
|
|
||||||
&& time_after_eq(jiffies,
|
|
||||||
ddb_entry->
|
|
||||||
dev_scan_wait_to_start_relogin))
|
|
||||||
{
|
|
||||||
ddb_entry->dev_scan_wait_to_start_relogin = 0;
|
|
||||||
qla4xxx_set_ddb_entry(ha, rs->fw_ddb_index, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QLA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int qla4_scan_for_relogin(struct scsi_qla_host *ha,
|
|
||||||
struct qla4_relog_scan *rs)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
/* scan for relogins
|
|
||||||
* ----------------- */
|
|
||||||
for (rs->fw_ddb_index = 0; rs->fw_ddb_index < MAX_DDB_ENTRIES;
|
|
||||||
rs->fw_ddb_index = rs->next_fw_ddb_index) {
|
|
||||||
if (qla4xxx_get_fwddb_entry(ha, rs->fw_ddb_index, NULL, 0,
|
|
||||||
NULL, &rs->next_fw_ddb_index,
|
|
||||||
&rs->fw_ddb_device_state,
|
|
||||||
&rs->conn_err, NULL, NULL)
|
|
||||||
== QLA_ERROR)
|
|
||||||
return QLA_ERROR;
|
|
||||||
|
|
||||||
if (rs->fw_ddb_device_state == DDB_DS_LOGIN_IN_PROCESS)
|
|
||||||
rs->halt_wait = 0;
|
|
||||||
|
|
||||||
if (rs->fw_ddb_device_state == DDB_DS_SESSION_FAILED ||
|
|
||||||
rs->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE) {
|
|
||||||
error = qla4_test_rdy(ha, rs);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We know we've reached the last device when
|
|
||||||
* next_fw_ddb_index is 0 */
|
|
||||||
if (rs->next_fw_ddb_index == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return QLA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* qla4xxx_devices_ready - wait for target devices to be logged in
|
|
||||||
* @ha: pointer to adapter structure
|
|
||||||
*
|
|
||||||
* This routine waits up to ql4xdiscoverywait seconds
|
|
||||||
* F/W database during driver load time.
|
|
||||||
**/
|
|
||||||
static int qla4xxx_devices_ready(struct scsi_qla_host *ha)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
unsigned long discovery_wtime;
|
|
||||||
struct qla4_relog_scan rs;
|
|
||||||
|
|
||||||
discovery_wtime = jiffies + (ql4xdiscoverywait * HZ);
|
|
||||||
|
|
||||||
DEBUG(printk("Waiting (%d) for devices ...\n", ql4xdiscoverywait));
|
|
||||||
do {
|
|
||||||
/* poll for AEN. */
|
|
||||||
qla4xxx_get_firmware_state(ha);
|
|
||||||
if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) {
|
|
||||||
/* Set time-between-relogin timer */
|
|
||||||
qla4xxx_process_aen(ha, RELOGIN_DDB_CHANGED_AENS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if no relogins active or needed, halt discvery wait */
|
|
||||||
rs.halt_wait = 1;
|
|
||||||
|
|
||||||
error = qla4_scan_for_relogin(ha, &rs);
|
|
||||||
|
|
||||||
if (rs.halt_wait) {
|
|
||||||
DEBUG2(printk("scsi%ld: %s: Delay halted. Devices "
|
|
||||||
"Ready.\n", ha->host_no, __func__));
|
|
||||||
return QLA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
msleep(2000);
|
|
||||||
} while (!time_after_eq(jiffies, discovery_wtime));
|
|
||||||
|
|
||||||
DEBUG3(qla4xxx_get_conn_event_log(ha));
|
|
||||||
|
|
||||||
return QLA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void qla4xxx_flush_AENS(struct scsi_qla_host *ha)
|
|
||||||
{
|
|
||||||
unsigned long wtime;
|
|
||||||
|
|
||||||
/* Flush the 0x8014 AEN from the firmware as a result of
|
|
||||||
* Auto connect. We are basically doing get_firmware_ddb()
|
|
||||||
* to determine whether we need to log back in or not.
|
|
||||||
* Trying to do a set ddb before we have processed 0x8014
|
|
||||||
* will result in another set_ddb() for the same ddb. In other
|
|
||||||
* words there will be stale entries in the aen_q.
|
|
||||||
*/
|
|
||||||
wtime = jiffies + (2 * HZ);
|
|
||||||
do {
|
|
||||||
if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS)
|
|
||||||
if (ha->firmware_state & (BIT_2 | BIT_0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
|
|
||||||
qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
|
|
||||||
|
|
||||||
msleep(1000);
|
|
||||||
} while (!time_after_eq(jiffies, wtime));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
|
static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
|
||||||
{
|
{
|
||||||
uint16_t fw_ddb_index;
|
uint16_t fw_ddb_index;
|
||||||
@ -996,29 +885,12 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
|
|||||||
|
|
||||||
for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++)
|
for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++)
|
||||||
ha->fw_ddb_index_map[fw_ddb_index] =
|
ha->fw_ddb_index_map[fw_ddb_index] =
|
||||||
(struct ddb_entry *)INVALID_ENTRY;
|
(struct ddb_entry *)INVALID_ENTRY;
|
||||||
|
|
||||||
ha->tot_ddbs = 0;
|
ha->tot_ddbs = 0;
|
||||||
|
|
||||||
qla4xxx_flush_AENS(ha);
|
/* Perform device discovery and build ddb list. */
|
||||||
|
status = qla4xxx_build_ddb_list(ha);
|
||||||
/* Wait for an AEN */
|
|
||||||
qla4xxx_devices_ready(ha);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First perform device discovery for active
|
|
||||||
* fw ddb indexes and build
|
|
||||||
* ddb list.
|
|
||||||
*/
|
|
||||||
if ((status = qla4xxx_build_ddb_list(ha)) == QLA_ERROR)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Targets can come online after the inital discovery, so processing
|
|
||||||
* the aens here will catch them.
|
|
||||||
*/
|
|
||||||
if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
|
|
||||||
qla4xxx_process_aen(ha, PROCESS_ALL_AENS);
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -1537,7 +1409,6 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
|
|||||||
uint32_t state, uint32_t conn_err)
|
uint32_t state, uint32_t conn_err)
|
||||||
{
|
{
|
||||||
struct ddb_entry * ddb_entry;
|
struct ddb_entry * ddb_entry;
|
||||||
uint32_t old_fw_ddb_device_state;
|
|
||||||
|
|
||||||
/* check for out of range index */
|
/* check for out of range index */
|
||||||
if (fw_ddb_index >= MAX_DDB_ENTRIES)
|
if (fw_ddb_index >= MAX_DDB_ENTRIES)
|
||||||
@ -1553,27 +1424,18 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Device already exists in our database. */
|
/* Device already exists in our database. */
|
||||||
old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
|
|
||||||
DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for "
|
DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for "
|
||||||
"index [%d]\n", ha->host_no, __func__,
|
"index [%d]\n", ha->host_no, __func__,
|
||||||
ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
|
ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
|
||||||
if (old_fw_ddb_device_state == state &&
|
|
||||||
state == DDB_DS_SESSION_ACTIVE) {
|
|
||||||
if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
|
|
||||||
atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
|
|
||||||
iscsi_unblock_session(ddb_entry->sess);
|
|
||||||
}
|
|
||||||
return QLA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
ddb_entry->fw_ddb_device_state = state;
|
ddb_entry->fw_ddb_device_state = state;
|
||||||
/* Device is back online. */
|
/* Device is back online. */
|
||||||
if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
|
if ((ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) &&
|
||||||
|
(atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)) {
|
||||||
atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
|
atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
|
||||||
atomic_set(&ddb_entry->relogin_retry_count, 0);
|
atomic_set(&ddb_entry->relogin_retry_count, 0);
|
||||||
atomic_set(&ddb_entry->relogin_timer, 0);
|
atomic_set(&ddb_entry->relogin_timer, 0);
|
||||||
clear_bit(DF_RELOGIN, &ddb_entry->flags);
|
clear_bit(DF_RELOGIN, &ddb_entry->flags);
|
||||||
clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
|
|
||||||
iscsi_unblock_session(ddb_entry->sess);
|
iscsi_unblock_session(ddb_entry->sess);
|
||||||
iscsi_session_event(ddb_entry->sess,
|
iscsi_session_event(ddb_entry->sess,
|
||||||
ISCSI_KEVENT_CREATE_SESSION);
|
ISCSI_KEVENT_CREATE_SESSION);
|
||||||
@ -1581,7 +1443,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
|
|||||||
* Change the lun state to READY in case the lun TIMEOUT before
|
* Change the lun state to READY in case the lun TIMEOUT before
|
||||||
* the device came back.
|
* the device came back.
|
||||||
*/
|
*/
|
||||||
} else {
|
} else if (ddb_entry->fw_ddb_device_state != DDB_DS_SESSION_ACTIVE) {
|
||||||
/* Device went away, mark device missing */
|
/* Device went away, mark device missing */
|
||||||
if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
|
if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
|
||||||
DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing "
|
DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing "
|
||||||
@ -1598,7 +1460,6 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
|
|||||||
*/
|
*/
|
||||||
if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
|
if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
|
||||||
!test_bit(DF_RELOGIN, &ddb_entry->flags) &&
|
!test_bit(DF_RELOGIN, &ddb_entry->flags) &&
|
||||||
!test_bit(DF_NO_RELOGIN, &ddb_entry->flags) &&
|
|
||||||
qla4_is_relogin_allowed(ha, conn_err)) {
|
qla4_is_relogin_allowed(ha, conn_err)) {
|
||||||
/*
|
/*
|
||||||
* This triggers a relogin. After the relogin_timer
|
* This triggers a relogin. After the relogin_timer
|
||||||
|
@ -801,7 +801,7 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
|
|||||||
&ha->reg->ctrl_status);
|
&ha->reg->ctrl_status);
|
||||||
readl(&ha->reg->ctrl_status);
|
readl(&ha->reg->ctrl_status);
|
||||||
|
|
||||||
if (!test_bit(AF_HBA_GOING_AWAY, &ha->flags))
|
if (!test_bit(AF_HA_REMOVAL, &ha->flags))
|
||||||
set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
|
set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1008,34 +1008,9 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
|
|||||||
mbox_sts[0], mbox_sts[2],
|
mbox_sts[0], mbox_sts[2],
|
||||||
mbox_sts[3]));
|
mbox_sts[3]));
|
||||||
break;
|
break;
|
||||||
} else if (process_aen == RELOGIN_DDB_CHANGED_AENS) {
|
|
||||||
/* for use during init time, we only want to
|
|
||||||
* relogin non-active ddbs */
|
|
||||||
struct ddb_entry *ddb_entry;
|
|
||||||
|
|
||||||
ddb_entry =
|
|
||||||
/* FIXME: name length? */
|
|
||||||
qla4xxx_lookup_ddb_by_fw_index(ha,
|
|
||||||
mbox_sts[2]);
|
|
||||||
if (!ddb_entry)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ddb_entry->dev_scan_wait_to_complete_relogin =
|
|
||||||
0;
|
|
||||||
ddb_entry->dev_scan_wait_to_start_relogin =
|
|
||||||
jiffies +
|
|
||||||
((ddb_entry->default_time2wait +
|
|
||||||
4) * HZ);
|
|
||||||
|
|
||||||
DEBUG2(printk("scsi%ld: ddb [%d] initiate"
|
|
||||||
" RELOGIN after %d seconds\n",
|
|
||||||
ha->host_no,
|
|
||||||
ddb_entry->fw_ddb_index,
|
|
||||||
ddb_entry->default_time2wait +
|
|
||||||
4));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
case PROCESS_ALL_AENS:
|
||||||
|
default:
|
||||||
if (mbox_sts[1] == 0) { /* Global DB change. */
|
if (mbox_sts[1] == 0) { /* Global DB change. */
|
||||||
qla4xxx_reinitialize_ddb_list(ha);
|
qla4xxx_reinitialize_ddb_list(ha);
|
||||||
} else if (mbox_sts[1] == 1) { /* Specific device. */
|
} else if (mbox_sts[1] == 1) { /* Specific device. */
|
||||||
|
@ -32,6 +32,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
|||||||
u_long wait_count;
|
u_long wait_count;
|
||||||
uint32_t intr_status;
|
uint32_t intr_status;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
|
uint32_t dev_state;
|
||||||
|
|
||||||
/* Make sure that pointers are valid */
|
/* Make sure that pointers are valid */
|
||||||
if (!mbx_cmd || !mbx_sts) {
|
if (!mbx_cmd || !mbx_sts) {
|
||||||
@ -40,12 +41,23 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_qla8022(ha) &&
|
if (is_qla8022(ha)) {
|
||||||
test_bit(AF_FW_RECOVERY, &ha->flags)) {
|
if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
|
||||||
DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: prematurely "
|
DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
|
||||||
"completing mbx cmd as firmware recovery detected\n",
|
"prematurely completing mbx cmd as firmware "
|
||||||
ha->host_no, __func__));
|
"recovery detected\n", ha->host_no, __func__));
|
||||||
return status;
|
return status;
|
||||||
|
}
|
||||||
|
/* Do not send any mbx cmd if h/w is in failed state*/
|
||||||
|
qla4_8xxx_idc_lock(ha);
|
||||||
|
dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
|
||||||
|
qla4_8xxx_idc_unlock(ha);
|
||||||
|
if (dev_state == QLA82XX_DEV_FAILED) {
|
||||||
|
ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: H/W is in "
|
||||||
|
"failed state, do not send any mailbox commands\n",
|
||||||
|
ha->host_no, __func__);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((is_aer_supported(ha)) &&
|
if ((is_aer_supported(ha)) &&
|
||||||
@ -139,7 +151,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
|||||||
if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
|
if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
|
||||||
test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
|
test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
|
||||||
test_bit(AF_ONLINE, &ha->flags) &&
|
test_bit(AF_ONLINE, &ha->flags) &&
|
||||||
!test_bit(AF_HBA_GOING_AWAY, &ha->flags)) {
|
!test_bit(AF_HA_REMOVAL, &ha->flags)) {
|
||||||
/* Do not poll for completion. Use completion queue */
|
/* Do not poll for completion. Use completion queue */
|
||||||
set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
|
set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
|
||||||
wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
|
wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
|
||||||
@ -395,9 +407,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
|
|||||||
/*memcpy(ha->alias, init_fw_cb->Alias,
|
/*memcpy(ha->alias, init_fw_cb->Alias,
|
||||||
min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
|
min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
|
||||||
|
|
||||||
/* Save Command Line Paramater info */
|
|
||||||
ha->discovery_wait = ql4xdiscoverywait;
|
|
||||||
|
|
||||||
if (ha->acb_version == ACB_SUPPORTED) {
|
if (ha->acb_version == ACB_SUPPORTED) {
|
||||||
ha->ipv6_options = init_fw_cb->ipv6_opts;
|
ha->ipv6_options = init_fw_cb->ipv6_opts;
|
||||||
ha->ipv6_addl_options = init_fw_cb->ipv6_addtl_opts;
|
ha->ipv6_addl_options = init_fw_cb->ipv6_addtl_opts;
|
||||||
@ -467,6 +476,11 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
|
|||||||
|
|
||||||
init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
|
init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
|
||||||
|
|
||||||
|
/* Set bit for "serialize task mgmt" all other bits need to be zero */
|
||||||
|
init_fw_cb->add_fw_options = 0;
|
||||||
|
init_fw_cb->add_fw_options |=
|
||||||
|
__constant_cpu_to_le16(SERIALIZE_TASK_MGMT);
|
||||||
|
|
||||||
if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
|
if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
|
||||||
!= QLA_SUCCESS) {
|
!= QLA_SUCCESS) {
|
||||||
DEBUG2(printk(KERN_WARNING
|
DEBUG2(printk(KERN_WARNING
|
||||||
|
@ -2304,14 +2304,13 @@ qla4_8xxx_enable_intrs(struct scsi_qla_host *ha)
|
|||||||
void
|
void
|
||||||
qla4_8xxx_disable_intrs(struct scsi_qla_host *ha)
|
qla4_8xxx_disable_intrs(struct scsi_qla_host *ha)
|
||||||
{
|
{
|
||||||
if (test_bit(AF_INTERRUPTS_ON, &ha->flags))
|
if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags))
|
||||||
qla4_8xxx_mbx_intr_disable(ha);
|
qla4_8xxx_mbx_intr_disable(ha);
|
||||||
|
|
||||||
spin_lock_irq(&ha->hardware_lock);
|
spin_lock_irq(&ha->hardware_lock);
|
||||||
/* BIT 10 - set */
|
/* BIT 10 - set */
|
||||||
qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);
|
qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);
|
||||||
spin_unlock_irq(&ha->hardware_lock);
|
spin_unlock_irq(&ha->hardware_lock);
|
||||||
clear_bit(AF_INTERRUPTS_ON, &ha->flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ql4_init_msix_entry {
|
struct ql4_init_msix_entry {
|
||||||
|
@ -29,10 +29,6 @@ static struct kmem_cache *srb_cachep;
|
|||||||
/*
|
/*
|
||||||
* Module parameter information and variables
|
* Module parameter information and variables
|
||||||
*/
|
*/
|
||||||
int ql4xdiscoverywait = 60;
|
|
||||||
module_param(ql4xdiscoverywait, int, S_IRUGO | S_IWUSR);
|
|
||||||
MODULE_PARM_DESC(ql4xdiscoverywait, "Discovery wait time");
|
|
||||||
|
|
||||||
int ql4xdontresethba = 0;
|
int ql4xdontresethba = 0;
|
||||||
module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
|
module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
|
||||||
MODULE_PARM_DESC(ql4xdontresethba,
|
MODULE_PARM_DESC(ql4xdontresethba,
|
||||||
@ -55,6 +51,17 @@ MODULE_PARM_DESC(ql4xenablemsix,
|
|||||||
" 2 = enable MSI interrupt mechanism.");
|
" 2 = enable MSI interrupt mechanism.");
|
||||||
|
|
||||||
#define QL4_DEF_QDEPTH 32
|
#define QL4_DEF_QDEPTH 32
|
||||||
|
static int ql4xmaxqdepth = QL4_DEF_QDEPTH;
|
||||||
|
module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);
|
||||||
|
MODULE_PARM_DESC(ql4xmaxqdepth,
|
||||||
|
"Maximum queue depth to report for target devices.\n"
|
||||||
|
" Default: 32.");
|
||||||
|
|
||||||
|
static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
|
||||||
|
module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
|
||||||
|
MODULE_PARM_DESC(ql4xsess_recovery_tmo,
|
||||||
|
"Target Session Recovery Timeout.\n"
|
||||||
|
" Default: 30 sec.");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SCSI host template entry points
|
* SCSI host template entry points
|
||||||
@ -165,7 +172,7 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
|
|||||||
DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout "
|
DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout "
|
||||||
"of (%d) secs exhausted, marking device DEAD.\n",
|
"of (%d) secs exhausted, marking device DEAD.\n",
|
||||||
ha->host_no, __func__, ddb_entry->fw_ddb_index,
|
ha->host_no, __func__, ddb_entry->fw_ddb_index,
|
||||||
QL4_SESS_RECOVERY_TMO));
|
ddb_entry->sess->recovery_tmo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +302,7 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
ddb_entry->sess->recovery_tmo = QL4_SESS_RECOVERY_TMO;
|
ddb_entry->sess->recovery_tmo = ql4xsess_recovery_tmo;
|
||||||
|
|
||||||
err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
|
err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -753,12 +760,6 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
|
|||||||
if (!pci_channel_offline(ha->pdev))
|
if (!pci_channel_offline(ha->pdev))
|
||||||
pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
|
pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
|
||||||
|
|
||||||
if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) {
|
|
||||||
DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n",
|
|
||||||
__func__));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_qla8022(ha)) {
|
if (is_qla8022(ha)) {
|
||||||
qla4_8xxx_watchdog(ha);
|
qla4_8xxx_watchdog(ha);
|
||||||
}
|
}
|
||||||
@ -1067,7 +1068,6 @@ void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha)
|
|||||||
|
|
||||||
/* Disable the board */
|
/* Disable the board */
|
||||||
ql4_printk(KERN_INFO, ha, "Disabling the board\n");
|
ql4_printk(KERN_INFO, ha, "Disabling the board\n");
|
||||||
set_bit(AF_HBA_GOING_AWAY, &ha->flags);
|
|
||||||
|
|
||||||
qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
|
qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
|
||||||
qla4xxx_mark_all_devices_missing(ha);
|
qla4xxx_mark_all_devices_missing(ha);
|
||||||
@ -1218,6 +1218,27 @@ recover_ha_init_adapter:
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
|
||||||
|
{
|
||||||
|
struct ddb_entry *ddb_entry, *dtemp;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
|
||||||
|
if ((atomic_read(&ddb_entry->state) == DDB_STATE_MISSING) ||
|
||||||
|
(atomic_read(&ddb_entry->state) == DDB_STATE_DEAD)) {
|
||||||
|
if (ddb_entry->fw_ddb_device_state ==
|
||||||
|
DDB_DS_SESSION_ACTIVE) {
|
||||||
|
atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
|
||||||
|
ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
|
||||||
|
" marked ONLINE\n", ha->host_no, __func__,
|
||||||
|
ddb_entry->fw_ddb_index);
|
||||||
|
|
||||||
|
iscsi_unblock_session(ddb_entry->sess);
|
||||||
|
} else
|
||||||
|
qla4xxx_relogin_device(ha, ddb_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
|
void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
|
||||||
{
|
{
|
||||||
if (ha->dpc_thread &&
|
if (ha->dpc_thread &&
|
||||||
@ -1259,11 +1280,6 @@ static void qla4xxx_do_dpc(struct work_struct *work)
|
|||||||
goto do_dpc_exit;
|
goto do_dpc_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HBA is in the process of being permanently disabled.
|
|
||||||
* Don't process anything */
|
|
||||||
if (test_bit(AF_HBA_GOING_AWAY, &ha->flags))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (is_qla8022(ha)) {
|
if (is_qla8022(ha)) {
|
||||||
if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
|
if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
|
||||||
qla4_8xxx_idc_lock(ha);
|
qla4_8xxx_idc_lock(ha);
|
||||||
@ -1331,13 +1347,7 @@ dpc_post_reset_ha:
|
|||||||
if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
|
if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
|
||||||
if (!test_bit(AF_LINK_UP, &ha->flags)) {
|
if (!test_bit(AF_LINK_UP, &ha->flags)) {
|
||||||
/* ---- link down? --- */
|
/* ---- link down? --- */
|
||||||
list_for_each_entry_safe(ddb_entry, dtemp,
|
qla4xxx_mark_all_devices_missing(ha);
|
||||||
&ha->ddb_list, list) {
|
|
||||||
if (atomic_read(&ddb_entry->state) ==
|
|
||||||
DDB_STATE_ONLINE)
|
|
||||||
qla4xxx_mark_device_missing(ha,
|
|
||||||
ddb_entry);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* ---- link up? --- *
|
/* ---- link up? --- *
|
||||||
* F/W will auto login to all devices ONLY ONCE after
|
* F/W will auto login to all devices ONLY ONCE after
|
||||||
@ -1346,30 +1356,7 @@ dpc_post_reset_ha:
|
|||||||
* manually relogin to devices when recovering from
|
* manually relogin to devices when recovering from
|
||||||
* connection failures, logouts, expired KATO, etc. */
|
* connection failures, logouts, expired KATO, etc. */
|
||||||
|
|
||||||
list_for_each_entry_safe(ddb_entry, dtemp,
|
qla4xxx_relogin_all_devices(ha);
|
||||||
&ha->ddb_list, list) {
|
|
||||||
if ((atomic_read(&ddb_entry->state) ==
|
|
||||||
DDB_STATE_MISSING) ||
|
|
||||||
(atomic_read(&ddb_entry->state) ==
|
|
||||||
DDB_STATE_DEAD)) {
|
|
||||||
if (ddb_entry->fw_ddb_device_state ==
|
|
||||||
DDB_DS_SESSION_ACTIVE) {
|
|
||||||
atomic_set(&ddb_entry->state,
|
|
||||||
DDB_STATE_ONLINE);
|
|
||||||
ql4_printk(KERN_INFO, ha,
|
|
||||||
"scsi%ld: %s: ddb[%d]"
|
|
||||||
" marked ONLINE\n",
|
|
||||||
ha->host_no, __func__,
|
|
||||||
ddb_entry->fw_ddb_index);
|
|
||||||
|
|
||||||
iscsi_unblock_session(
|
|
||||||
ddb_entry->sess);
|
|
||||||
} else
|
|
||||||
qla4xxx_relogin_device(
|
|
||||||
ha, ddb_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1630,6 +1617,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||||||
uint8_t init_retry_count = 0;
|
uint8_t init_retry_count = 0;
|
||||||
char buf[34];
|
char buf[34];
|
||||||
struct qla4_8xxx_legacy_intr_set *nx_legacy_intr;
|
struct qla4_8xxx_legacy_intr_set *nx_legacy_intr;
|
||||||
|
uint32_t dev_state;
|
||||||
|
|
||||||
if (pci_enable_device(pdev))
|
if (pci_enable_device(pdev))
|
||||||
return -1;
|
return -1;
|
||||||
@ -1713,6 +1701,18 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||||||
status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
|
status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
|
||||||
while ((!test_bit(AF_ONLINE, &ha->flags)) &&
|
while ((!test_bit(AF_ONLINE, &ha->flags)) &&
|
||||||
init_retry_count++ < MAX_INIT_RETRIES) {
|
init_retry_count++ < MAX_INIT_RETRIES) {
|
||||||
|
|
||||||
|
if (is_qla8022(ha)) {
|
||||||
|
qla4_8xxx_idc_lock(ha);
|
||||||
|
dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
|
||||||
|
qla4_8xxx_idc_unlock(ha);
|
||||||
|
if (dev_state == QLA82XX_DEV_FAILED) {
|
||||||
|
ql4_printk(KERN_WARNING, ha, "%s: don't retry "
|
||||||
|
"initialize adapter. H/W is in failed state\n",
|
||||||
|
__func__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
DEBUG2(printk("scsi: %s: retrying adapter initialization "
|
DEBUG2(printk("scsi: %s: retrying adapter initialization "
|
||||||
"(%d)\n", __func__, init_retry_count));
|
"(%d)\n", __func__, init_retry_count));
|
||||||
|
|
||||||
@ -1814,6 +1814,44 @@ probe_disable_device:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qla4xxx_prevent_other_port_reinit - prevent other port from re-initialize
|
||||||
|
* @ha: pointer to adapter structure
|
||||||
|
*
|
||||||
|
* Mark the other ISP-4xxx port to indicate that the driver is being removed,
|
||||||
|
* so that the other port will not re-initialize while in the process of
|
||||||
|
* removing the ha due to driver unload or hba hotplug.
|
||||||
|
**/
|
||||||
|
static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha)
|
||||||
|
{
|
||||||
|
struct scsi_qla_host *other_ha = NULL;
|
||||||
|
struct pci_dev *other_pdev = NULL;
|
||||||
|
int fn = ISP4XXX_PCI_FN_2;
|
||||||
|
|
||||||
|
/*iscsi function numbers for ISP4xxx is 1 and 3*/
|
||||||
|
if (PCI_FUNC(ha->pdev->devfn) & BIT_1)
|
||||||
|
fn = ISP4XXX_PCI_FN_1;
|
||||||
|
|
||||||
|
other_pdev =
|
||||||
|
pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
|
||||||
|
ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
|
||||||
|
fn));
|
||||||
|
|
||||||
|
/* Get other_ha if other_pdev is valid and state is enable*/
|
||||||
|
if (other_pdev) {
|
||||||
|
if (atomic_read(&other_pdev->enable_cnt)) {
|
||||||
|
other_ha = pci_get_drvdata(other_pdev);
|
||||||
|
if (other_ha) {
|
||||||
|
set_bit(AF_HA_REMOVAL, &other_ha->flags);
|
||||||
|
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: "
|
||||||
|
"Prevent %s reinit\n", __func__,
|
||||||
|
dev_name(&other_ha->pdev->dev)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pci_dev_put(other_pdev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qla4xxx_remove_adapter - calback function to remove adapter.
|
* qla4xxx_remove_adapter - calback function to remove adapter.
|
||||||
* @pci_dev: PCI device pointer
|
* @pci_dev: PCI device pointer
|
||||||
@ -1824,7 +1862,8 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
|
|||||||
|
|
||||||
ha = pci_get_drvdata(pdev);
|
ha = pci_get_drvdata(pdev);
|
||||||
|
|
||||||
set_bit(AF_HBA_GOING_AWAY, &ha->flags);
|
if (!is_qla8022(ha))
|
||||||
|
qla4xxx_prevent_other_port_reinit(ha);
|
||||||
|
|
||||||
/* remove devs from iscsi_sessions to scsi_devices */
|
/* remove devs from iscsi_sessions to scsi_devices */
|
||||||
qla4xxx_free_ddb_list(ha);
|
qla4xxx_free_ddb_list(ha);
|
||||||
@ -1868,10 +1907,15 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev)
|
|||||||
{
|
{
|
||||||
struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target);
|
struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target);
|
||||||
struct ddb_entry *ddb = sess->dd_data;
|
struct ddb_entry *ddb = sess->dd_data;
|
||||||
|
int queue_depth = QL4_DEF_QDEPTH;
|
||||||
|
|
||||||
sdev->hostdata = ddb;
|
sdev->hostdata = ddb;
|
||||||
sdev->tagged_supported = 1;
|
sdev->tagged_supported = 1;
|
||||||
scsi_activate_tcq(sdev, QL4_DEF_QDEPTH);
|
|
||||||
|
if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU)
|
||||||
|
queue_depth = ql4xmaxqdepth;
|
||||||
|
|
||||||
|
scsi_activate_tcq(sdev, queue_depth);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,4 +5,4 @@
|
|||||||
* See LICENSE.qla4xxx for copyright and licensing details.
|
* See LICENSE.qla4xxx for copyright and licensing details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define QLA4XXX_DRIVER_VERSION "5.02.00-k5"
|
#define QLA4XXX_DRIVER_VERSION "5.02.00-k6"
|
||||||
|
@ -1917,7 +1917,7 @@ store_priv_session_##field(struct device *dev, \
|
|||||||
#define iscsi_priv_session_rw_attr(field, format) \
|
#define iscsi_priv_session_rw_attr(field, format) \
|
||||||
iscsi_priv_session_attr_show(field, format) \
|
iscsi_priv_session_attr_show(field, format) \
|
||||||
iscsi_priv_session_attr_store(field) \
|
iscsi_priv_session_attr_store(field) \
|
||||||
static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUGO, \
|
static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR, \
|
||||||
show_priv_session_##field, \
|
show_priv_session_##field, \
|
||||||
store_priv_session_##field)
|
store_priv_session_##field)
|
||||||
iscsi_priv_session_rw_attr(recovery_tmo, "%d");
|
iscsi_priv_session_rw_attr(recovery_tmo, "%d");
|
||||||
|
@ -2027,14 +2027,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
|
|||||||
int old_rcd = sdkp->RCD;
|
int old_rcd = sdkp->RCD;
|
||||||
int old_dpofua = sdkp->DPOFUA;
|
int old_dpofua = sdkp->DPOFUA;
|
||||||
|
|
||||||
if (sdp->skip_ms_page_8) {
|
if (sdp->skip_ms_page_8)
|
||||||
if (sdp->type == TYPE_RBC)
|
goto defaults;
|
||||||
goto defaults;
|
|
||||||
else {
|
if (sdp->type == TYPE_RBC) {
|
||||||
modepage = 0x3F;
|
|
||||||
dbd = 0;
|
|
||||||
}
|
|
||||||
} else if (sdp->type == TYPE_RBC) {
|
|
||||||
modepage = 6;
|
modepage = 6;
|
||||||
dbd = 8;
|
dbd = 8;
|
||||||
} else {
|
} else {
|
||||||
@ -2062,11 +2058,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
|
|||||||
*/
|
*/
|
||||||
if (len < 3)
|
if (len < 3)
|
||||||
goto bad_sense;
|
goto bad_sense;
|
||||||
else if (len > SD_BUF_SIZE) {
|
if (len > 20)
|
||||||
sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
|
len = 20;
|
||||||
"data from %d to %d bytes\n", len, SD_BUF_SIZE);
|
|
||||||
len = SD_BUF_SIZE;
|
/* Take headers and block descriptors into account */
|
||||||
}
|
len += data.header_length + data.block_descriptor_length;
|
||||||
|
if (len > SD_BUF_SIZE)
|
||||||
|
goto bad_sense;
|
||||||
|
|
||||||
/* Get the data */
|
/* Get the data */
|
||||||
res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
|
res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
|
||||||
@ -2074,45 +2072,16 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
|
|||||||
if (scsi_status_is_good(res)) {
|
if (scsi_status_is_good(res)) {
|
||||||
int offset = data.header_length + data.block_descriptor_length;
|
int offset = data.header_length + data.block_descriptor_length;
|
||||||
|
|
||||||
while (offset < len) {
|
if (offset >= SD_BUF_SIZE - 2) {
|
||||||
u8 page_code = buffer[offset] & 0x3F;
|
sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
|
||||||
u8 spf = buffer[offset] & 0x40;
|
goto defaults;
|
||||||
|
|
||||||
if (page_code == 8 || page_code == 6) {
|
|
||||||
/* We're interested only in the first 3 bytes.
|
|
||||||
*/
|
|
||||||
if (len - offset <= 2) {
|
|
||||||
sd_printk(KERN_ERR, sdkp, "Incomplete "
|
|
||||||
"mode parameter data\n");
|
|
||||||
goto defaults;
|
|
||||||
} else {
|
|
||||||
modepage = page_code;
|
|
||||||
goto Page_found;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Go to the next page */
|
|
||||||
if (spf && len - offset > 3)
|
|
||||||
offset += 4 + (buffer[offset+2] << 8) +
|
|
||||||
buffer[offset+3];
|
|
||||||
else if (!spf && len - offset > 1)
|
|
||||||
offset += 2 + buffer[offset+1];
|
|
||||||
else {
|
|
||||||
sd_printk(KERN_ERR, sdkp, "Incomplete "
|
|
||||||
"mode parameter data\n");
|
|
||||||
goto defaults;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modepage == 0x3F) {
|
if ((buffer[offset] & 0x3f) != modepage) {
|
||||||
sd_printk(KERN_ERR, sdkp, "No Caching mode page "
|
|
||||||
"present\n");
|
|
||||||
goto defaults;
|
|
||||||
} else if ((buffer[offset] & 0x3f) != modepage) {
|
|
||||||
sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
|
sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
|
||||||
goto defaults;
|
goto defaults;
|
||||||
}
|
}
|
||||||
Page_found:
|
|
||||||
if (modepage == 8) {
|
if (modepage == 8) {
|
||||||
sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
|
sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
|
||||||
sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
|
sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
|
||||||
|
@ -35,9 +35,11 @@
|
|||||||
|
|
||||||
struct ses_device {
|
struct ses_device {
|
||||||
unsigned char *page1;
|
unsigned char *page1;
|
||||||
|
unsigned char *page1_types;
|
||||||
unsigned char *page2;
|
unsigned char *page2;
|
||||||
unsigned char *page10;
|
unsigned char *page10;
|
||||||
short page1_len;
|
short page1_len;
|
||||||
|
short page1_num_types;
|
||||||
short page2_len;
|
short page2_len;
|
||||||
short page10_len;
|
short page10_len;
|
||||||
};
|
};
|
||||||
@ -110,12 +112,12 @@ static int ses_set_page2_descriptor(struct enclosure_device *edev,
|
|||||||
int i, j, count = 0, descriptor = ecomp->number;
|
int i, j, count = 0, descriptor = ecomp->number;
|
||||||
struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
|
struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
|
||||||
struct ses_device *ses_dev = edev->scratch;
|
struct ses_device *ses_dev = edev->scratch;
|
||||||
unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
|
unsigned char *type_ptr = ses_dev->page1_types;
|
||||||
unsigned char *desc_ptr = ses_dev->page2 + 8;
|
unsigned char *desc_ptr = ses_dev->page2 + 8;
|
||||||
|
|
||||||
/* Clear everything */
|
/* Clear everything */
|
||||||
memset(desc_ptr, 0, ses_dev->page2_len - 8);
|
memset(desc_ptr, 0, ses_dev->page2_len - 8);
|
||||||
for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) {
|
for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) {
|
||||||
for (j = 0; j < type_ptr[1]; j++) {
|
for (j = 0; j < type_ptr[1]; j++) {
|
||||||
desc_ptr += 4;
|
desc_ptr += 4;
|
||||||
if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
|
if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
|
||||||
@ -140,12 +142,12 @@ static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev,
|
|||||||
int i, j, count = 0, descriptor = ecomp->number;
|
int i, j, count = 0, descriptor = ecomp->number;
|
||||||
struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
|
struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
|
||||||
struct ses_device *ses_dev = edev->scratch;
|
struct ses_device *ses_dev = edev->scratch;
|
||||||
unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
|
unsigned char *type_ptr = ses_dev->page1_types;
|
||||||
unsigned char *desc_ptr = ses_dev->page2 + 8;
|
unsigned char *desc_ptr = ses_dev->page2 + 8;
|
||||||
|
|
||||||
ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len);
|
ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len);
|
||||||
|
|
||||||
for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) {
|
for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) {
|
||||||
for (j = 0; j < type_ptr[1]; j++) {
|
for (j = 0; j < type_ptr[1]; j++) {
|
||||||
desc_ptr += 4;
|
desc_ptr += 4;
|
||||||
if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
|
if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
|
||||||
@ -358,7 +360,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
|
|||||||
unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL;
|
unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL;
|
||||||
int i, j, page7_len, len, components;
|
int i, j, page7_len, len, components;
|
||||||
struct ses_device *ses_dev = edev->scratch;
|
struct ses_device *ses_dev = edev->scratch;
|
||||||
int types = ses_dev->page1[10];
|
int types = ses_dev->page1_num_types;
|
||||||
unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL);
|
unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL);
|
||||||
|
|
||||||
if (!hdr_buf)
|
if (!hdr_buf)
|
||||||
@ -390,10 +392,10 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
|
|||||||
len = (desc_ptr[2] << 8) + desc_ptr[3];
|
len = (desc_ptr[2] << 8) + desc_ptr[3];
|
||||||
/* skip past overall descriptor */
|
/* skip past overall descriptor */
|
||||||
desc_ptr += len + 4;
|
desc_ptr += len + 4;
|
||||||
if (ses_dev->page10)
|
|
||||||
addl_desc_ptr = ses_dev->page10 + 8;
|
|
||||||
}
|
}
|
||||||
type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
|
if (ses_dev->page10)
|
||||||
|
addl_desc_ptr = ses_dev->page10 + 8;
|
||||||
|
type_ptr = ses_dev->page1_types;
|
||||||
components = 0;
|
components = 0;
|
||||||
for (i = 0; i < types; i++, type_ptr += 4) {
|
for (i = 0; i < types; i++, type_ptr += 4) {
|
||||||
for (j = 0; j < type_ptr[1]; j++) {
|
for (j = 0; j < type_ptr[1]; j++) {
|
||||||
@ -503,6 +505,7 @@ static int ses_intf_add(struct device *cdev,
|
|||||||
u32 result;
|
u32 result;
|
||||||
int i, types, len, components = 0;
|
int i, types, len, components = 0;
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
|
int num_enclosures;
|
||||||
struct enclosure_device *edev;
|
struct enclosure_device *edev;
|
||||||
struct ses_component *scomp = NULL;
|
struct ses_component *scomp = NULL;
|
||||||
|
|
||||||
@ -530,16 +533,6 @@ static int ses_intf_add(struct device *cdev,
|
|||||||
if (result)
|
if (result)
|
||||||
goto recv_failed;
|
goto recv_failed;
|
||||||
|
|
||||||
if (hdr_buf[1] != 0) {
|
|
||||||
/* FIXME: need subenclosure support; I've just never
|
|
||||||
* seen a device with subenclosures and it makes the
|
|
||||||
* traversal routines more complex */
|
|
||||||
sdev_printk(KERN_ERR, sdev,
|
|
||||||
"FIXME driver has no support for subenclosures (%d)\n",
|
|
||||||
hdr_buf[1]);
|
|
||||||
goto err_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
|
len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
|
||||||
buf = kzalloc(len, GFP_KERNEL);
|
buf = kzalloc(len, GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
@ -549,11 +542,24 @@ static int ses_intf_add(struct device *cdev,
|
|||||||
if (result)
|
if (result)
|
||||||
goto recv_failed;
|
goto recv_failed;
|
||||||
|
|
||||||
types = buf[10];
|
types = 0;
|
||||||
|
|
||||||
type_ptr = buf + 12 + buf[11];
|
/* we always have one main enclosure and the rest are referred
|
||||||
|
* to as secondary subenclosures */
|
||||||
|
num_enclosures = buf[1] + 1;
|
||||||
|
|
||||||
for (i = 0; i < types; i++, type_ptr += 4) {
|
/* begin at the enclosure descriptor */
|
||||||
|
type_ptr = buf + 8;
|
||||||
|
/* skip all the enclosure descriptors */
|
||||||
|
for (i = 0; i < num_enclosures && type_ptr < buf + len; i++) {
|
||||||
|
types += type_ptr[2];
|
||||||
|
type_ptr += type_ptr[3] + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
ses_dev->page1_types = type_ptr;
|
||||||
|
ses_dev->page1_num_types = types;
|
||||||
|
|
||||||
|
for (i = 0; i < types && type_ptr < buf + len; i++, type_ptr += 4) {
|
||||||
if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
|
if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
|
||||||
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE)
|
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE)
|
||||||
components += type_ptr[1];
|
components += type_ptr[1];
|
||||||
|
@ -29,4 +29,6 @@ config TCM_PSCSI
|
|||||||
Say Y here to enable the TCM/pSCSI subsystem plugin for non-buffered
|
Say Y here to enable the TCM/pSCSI subsystem plugin for non-buffered
|
||||||
passthrough access to Linux/SCSI device
|
passthrough access to Linux/SCSI device
|
||||||
|
|
||||||
|
source "drivers/target/loopback/Kconfig"
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
EXTRA_CFLAGS += -I$(srctree)/drivers/target/ -I$(srctree)/drivers/scsi/
|
|
||||||
|
|
||||||
target_core_mod-y := target_core_configfs.o \
|
target_core_mod-y := target_core_configfs.o \
|
||||||
target_core_device.o \
|
target_core_device.o \
|
||||||
@ -13,7 +12,8 @@ target_core_mod-y := target_core_configfs.o \
|
|||||||
target_core_transport.o \
|
target_core_transport.o \
|
||||||
target_core_cdb.o \
|
target_core_cdb.o \
|
||||||
target_core_ua.o \
|
target_core_ua.o \
|
||||||
target_core_rd.o
|
target_core_rd.o \
|
||||||
|
target_core_stat.o
|
||||||
|
|
||||||
obj-$(CONFIG_TARGET_CORE) += target_core_mod.o
|
obj-$(CONFIG_TARGET_CORE) += target_core_mod.o
|
||||||
|
|
||||||
@ -21,3 +21,6 @@ obj-$(CONFIG_TARGET_CORE) += target_core_mod.o
|
|||||||
obj-$(CONFIG_TCM_IBLOCK) += target_core_iblock.o
|
obj-$(CONFIG_TCM_IBLOCK) += target_core_iblock.o
|
||||||
obj-$(CONFIG_TCM_FILEIO) += target_core_file.o
|
obj-$(CONFIG_TCM_FILEIO) += target_core_file.o
|
||||||
obj-$(CONFIG_TCM_PSCSI) += target_core_pscsi.o
|
obj-$(CONFIG_TCM_PSCSI) += target_core_pscsi.o
|
||||||
|
|
||||||
|
# Fabric modules
|
||||||
|
obj-$(CONFIG_LOOPBACK_TARGET) += loopback/
|
||||||
|
11
drivers/target/loopback/Kconfig
Normal file
11
drivers/target/loopback/Kconfig
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
config LOOPBACK_TARGET
|
||||||
|
tristate "TCM Virtual SAS target and Linux/SCSI LDD fabric loopback module"
|
||||||
|
help
|
||||||
|
Say Y here to enable the TCM Virtual SAS target and Linux/SCSI LLD
|
||||||
|
fabric loopback module.
|
||||||
|
|
||||||
|
config LOOPBACK_TARGET_CDB_DEBUG
|
||||||
|
bool "TCM loopback fabric module CDB debug code"
|
||||||
|
depends on LOOPBACK_TARGET
|
||||||
|
help
|
||||||
|
Say Y here to enable the TCM loopback fabric module CDB debug code
|
1
drivers/target/loopback/Makefile
Normal file
1
drivers/target/loopback/Makefile
Normal file
@ -0,0 +1 @@
|
|||||||
|
obj-$(CONFIG_LOOPBACK_TARGET) += tcm_loop.o
|
1579
drivers/target/loopback/tcm_loop.c
Normal file
1579
drivers/target/loopback/tcm_loop.c
Normal file
File diff suppressed because it is too large
Load Diff
77
drivers/target/loopback/tcm_loop.h
Normal file
77
drivers/target/loopback/tcm_loop.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#define TCM_LOOP_VERSION "v2.1-rc1"
|
||||||
|
#define TL_WWN_ADDR_LEN 256
|
||||||
|
#define TL_TPGS_PER_HBA 32
|
||||||
|
/*
|
||||||
|
* Defaults for struct scsi_host_template tcm_loop_driver_template
|
||||||
|
*
|
||||||
|
* We use large can_queue and cmd_per_lun here and let TCM enforce
|
||||||
|
* the underlying se_device_t->queue_depth.
|
||||||
|
*/
|
||||||
|
#define TL_SCSI_CAN_QUEUE 1024
|
||||||
|
#define TL_SCSI_CMD_PER_LUN 1024
|
||||||
|
#define TL_SCSI_MAX_SECTORS 1024
|
||||||
|
#define TL_SCSI_SG_TABLESIZE 256
|
||||||
|
/*
|
||||||
|
* Used in tcm_loop_driver_probe() for struct Scsi_Host->max_cmd_len
|
||||||
|
*/
|
||||||
|
#define TL_SCSI_MAX_CMD_LEN 32
|
||||||
|
|
||||||
|
#ifdef CONFIG_LOOPBACK_TARGET_CDB_DEBUG
|
||||||
|
# define TL_CDB_DEBUG(x...) printk(KERN_INFO x)
|
||||||
|
#else
|
||||||
|
# define TL_CDB_DEBUG(x...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct tcm_loop_cmd {
|
||||||
|
/* State of Linux/SCSI CDB+Data descriptor */
|
||||||
|
u32 sc_cmd_state;
|
||||||
|
/* Pointer to the CDB+Data descriptor from Linux/SCSI subsystem */
|
||||||
|
struct scsi_cmnd *sc;
|
||||||
|
struct list_head *tl_cmd_list;
|
||||||
|
/* The TCM I/O descriptor that is accessed via container_of() */
|
||||||
|
struct se_cmd tl_se_cmd;
|
||||||
|
/* Sense buffer that will be mapped into outgoing status */
|
||||||
|
unsigned char tl_sense_buf[TRANSPORT_SENSE_BUFFER];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcm_loop_tmr {
|
||||||
|
atomic_t tmr_complete;
|
||||||
|
wait_queue_head_t tl_tmr_wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcm_loop_nexus {
|
||||||
|
int it_nexus_active;
|
||||||
|
/*
|
||||||
|
* Pointer to Linux/SCSI HBA from linux/include/scsi_host.h
|
||||||
|
*/
|
||||||
|
struct scsi_host *sh;
|
||||||
|
/*
|
||||||
|
* Pointer to TCM session for I_T Nexus
|
||||||
|
*/
|
||||||
|
struct se_session *se_sess;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcm_loop_nacl {
|
||||||
|
struct se_node_acl se_node_acl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcm_loop_tpg {
|
||||||
|
unsigned short tl_tpgt;
|
||||||
|
atomic_t tl_tpg_port_count;
|
||||||
|
struct se_portal_group tl_se_tpg;
|
||||||
|
struct tcm_loop_hba *tl_hba;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcm_loop_hba {
|
||||||
|
u8 tl_proto_id;
|
||||||
|
unsigned char tl_wwn_address[TL_WWN_ADDR_LEN];
|
||||||
|
struct se_hba_s *se_hba;
|
||||||
|
struct se_lun *tl_hba_lun;
|
||||||
|
struct se_port *tl_hba_lun_sep;
|
||||||
|
struct se_device_s *se_dev_hba_ptr;
|
||||||
|
struct tcm_loop_nexus *tl_nexus;
|
||||||
|
struct device dev;
|
||||||
|
struct Scsi_Host *sh;
|
||||||
|
struct tcm_loop_tpg tl_hba_tpgs[TL_TPGS_PER_HBA];
|
||||||
|
struct se_wwn tl_hba_wwn;
|
||||||
|
};
|
@ -3,8 +3,8 @@
|
|||||||
*
|
*
|
||||||
* This file contains ConfigFS logic for the Generic Target Engine project.
|
* This file contains ConfigFS logic for the Generic Target Engine project.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008-2010 Rising Tide Systems
|
* Copyright (c) 2008-2011 Rising Tide Systems
|
||||||
* Copyright (c) 2008-2010 Linux-iSCSI.org
|
* Copyright (c) 2008-2011 Linux-iSCSI.org
|
||||||
*
|
*
|
||||||
* Nicholas A. Bellinger <nab@kernel.org>
|
* Nicholas A. Bellinger <nab@kernel.org>
|
||||||
*
|
*
|
||||||
@ -50,6 +50,7 @@
|
|||||||
#include "target_core_hba.h"
|
#include "target_core_hba.h"
|
||||||
#include "target_core_pr.h"
|
#include "target_core_pr.h"
|
||||||
#include "target_core_rd.h"
|
#include "target_core_rd.h"
|
||||||
|
#include "target_core_stat.h"
|
||||||
|
|
||||||
static struct list_head g_tf_list;
|
static struct list_head g_tf_list;
|
||||||
static struct mutex g_tf_lock;
|
static struct mutex g_tf_lock;
|
||||||
@ -1451,8 +1452,8 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
struct se_device *dev;
|
struct se_device *dev;
|
||||||
unsigned char *i_fabric, *t_fabric, *i_port = NULL, *t_port = NULL;
|
unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL;
|
||||||
unsigned char *isid = NULL;
|
unsigned char *t_fabric = NULL, *t_port = NULL;
|
||||||
char *orig, *ptr, *arg_p, *opts;
|
char *orig, *ptr, *arg_p, *opts;
|
||||||
substring_t args[MAX_OPT_ARGS];
|
substring_t args[MAX_OPT_ARGS];
|
||||||
unsigned long long tmp_ll;
|
unsigned long long tmp_ll;
|
||||||
@ -1488,9 +1489,17 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||||||
switch (token) {
|
switch (token) {
|
||||||
case Opt_initiator_fabric:
|
case Opt_initiator_fabric:
|
||||||
i_fabric = match_strdup(&args[0]);
|
i_fabric = match_strdup(&args[0]);
|
||||||
|
if (!i_fabric) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Opt_initiator_node:
|
case Opt_initiator_node:
|
||||||
i_port = match_strdup(&args[0]);
|
i_port = match_strdup(&args[0]);
|
||||||
|
if (!i_port) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) {
|
if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) {
|
||||||
printk(KERN_ERR "APTPL metadata initiator_node="
|
printk(KERN_ERR "APTPL metadata initiator_node="
|
||||||
" exceeds PR_APTPL_MAX_IPORT_LEN: %d\n",
|
" exceeds PR_APTPL_MAX_IPORT_LEN: %d\n",
|
||||||
@ -1501,6 +1510,10 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||||||
break;
|
break;
|
||||||
case Opt_initiator_sid:
|
case Opt_initiator_sid:
|
||||||
isid = match_strdup(&args[0]);
|
isid = match_strdup(&args[0]);
|
||||||
|
if (!isid) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (strlen(isid) > PR_REG_ISID_LEN) {
|
if (strlen(isid) > PR_REG_ISID_LEN) {
|
||||||
printk(KERN_ERR "APTPL metadata initiator_isid"
|
printk(KERN_ERR "APTPL metadata initiator_isid"
|
||||||
"= exceeds PR_REG_ISID_LEN: %d\n",
|
"= exceeds PR_REG_ISID_LEN: %d\n",
|
||||||
@ -1511,6 +1524,10 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||||||
break;
|
break;
|
||||||
case Opt_sa_res_key:
|
case Opt_sa_res_key:
|
||||||
arg_p = match_strdup(&args[0]);
|
arg_p = match_strdup(&args[0]);
|
||||||
|
if (!arg_p) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
ret = strict_strtoull(arg_p, 0, &tmp_ll);
|
ret = strict_strtoull(arg_p, 0, &tmp_ll);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "strict_strtoull() failed for"
|
printk(KERN_ERR "strict_strtoull() failed for"
|
||||||
@ -1547,9 +1564,17 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||||||
*/
|
*/
|
||||||
case Opt_target_fabric:
|
case Opt_target_fabric:
|
||||||
t_fabric = match_strdup(&args[0]);
|
t_fabric = match_strdup(&args[0]);
|
||||||
|
if (!t_fabric) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Opt_target_node:
|
case Opt_target_node:
|
||||||
t_port = match_strdup(&args[0]);
|
t_port = match_strdup(&args[0]);
|
||||||
|
if (!t_port) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) {
|
if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) {
|
||||||
printk(KERN_ERR "APTPL metadata target_node="
|
printk(KERN_ERR "APTPL metadata target_node="
|
||||||
" exceeds PR_APTPL_MAX_TPORT_LEN: %d\n",
|
" exceeds PR_APTPL_MAX_TPORT_LEN: %d\n",
|
||||||
@ -1592,6 +1617,11 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||||||
i_port, isid, mapped_lun, t_port, tpgt, target_lun,
|
i_port, isid, mapped_lun, t_port, tpgt, target_lun,
|
||||||
res_holder, all_tg_pt, type);
|
res_holder, all_tg_pt, type);
|
||||||
out:
|
out:
|
||||||
|
kfree(i_fabric);
|
||||||
|
kfree(i_port);
|
||||||
|
kfree(isid);
|
||||||
|
kfree(t_fabric);
|
||||||
|
kfree(t_port);
|
||||||
kfree(orig);
|
kfree(orig);
|
||||||
return (ret == 0) ? count : ret;
|
return (ret == 0) ? count : ret;
|
||||||
}
|
}
|
||||||
@ -1798,7 +1828,9 @@ static ssize_t target_core_store_dev_enable(
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr);
|
dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr);
|
||||||
if (!(dev) || IS_ERR(dev))
|
if (IS_ERR(dev))
|
||||||
|
return PTR_ERR(dev);
|
||||||
|
else if (!dev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
se_dev->se_dev_ptr = dev;
|
se_dev->se_dev_ptr = dev;
|
||||||
@ -2678,6 +2710,34 @@ static struct config_item_type target_core_alua_cit = {
|
|||||||
|
|
||||||
/* End functions for struct config_item_type target_core_alua_cit */
|
/* End functions for struct config_item_type target_core_alua_cit */
|
||||||
|
|
||||||
|
/* Start functions for struct config_item_type target_core_stat_cit */
|
||||||
|
|
||||||
|
static struct config_group *target_core_stat_mkdir(
|
||||||
|
struct config_group *group,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void target_core_stat_rmdir(
|
||||||
|
struct config_group *group,
|
||||||
|
struct config_item *item)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_group_operations target_core_stat_group_ops = {
|
||||||
|
.make_group = &target_core_stat_mkdir,
|
||||||
|
.drop_item = &target_core_stat_rmdir,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type target_core_stat_cit = {
|
||||||
|
.ct_group_ops = &target_core_stat_group_ops,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* End functions for struct config_item_type target_core_stat_cit */
|
||||||
|
|
||||||
/* Start functions for struct config_item_type target_core_hba_cit */
|
/* Start functions for struct config_item_type target_core_hba_cit */
|
||||||
|
|
||||||
static struct config_group *target_core_make_subdev(
|
static struct config_group *target_core_make_subdev(
|
||||||
@ -2690,10 +2750,12 @@ static struct config_group *target_core_make_subdev(
|
|||||||
struct config_item *hba_ci = &group->cg_item;
|
struct config_item *hba_ci = &group->cg_item;
|
||||||
struct se_hba *hba = item_to_hba(hba_ci);
|
struct se_hba *hba = item_to_hba(hba_ci);
|
||||||
struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL;
|
struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL;
|
||||||
|
struct config_group *dev_stat_grp = NULL;
|
||||||
|
int errno = -ENOMEM, ret;
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&hba->hba_access_mutex))
|
ret = mutex_lock_interruptible(&hba->hba_access_mutex);
|
||||||
return NULL;
|
if (ret)
|
||||||
|
return ERR_PTR(ret);
|
||||||
/*
|
/*
|
||||||
* Locate the struct se_subsystem_api from parent's struct se_hba.
|
* Locate the struct se_subsystem_api from parent's struct se_hba.
|
||||||
*/
|
*/
|
||||||
@ -2723,7 +2785,7 @@ static struct config_group *target_core_make_subdev(
|
|||||||
se_dev->se_dev_hba = hba;
|
se_dev->se_dev_hba = hba;
|
||||||
dev_cg = &se_dev->se_dev_group;
|
dev_cg = &se_dev->se_dev_group;
|
||||||
|
|
||||||
dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 6,
|
dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!(dev_cg->default_groups))
|
if (!(dev_cg->default_groups))
|
||||||
goto out;
|
goto out;
|
||||||
@ -2755,13 +2817,17 @@ static struct config_group *target_core_make_subdev(
|
|||||||
&target_core_dev_wwn_cit);
|
&target_core_dev_wwn_cit);
|
||||||
config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group,
|
config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group,
|
||||||
"alua", &target_core_alua_tg_pt_gps_cit);
|
"alua", &target_core_alua_tg_pt_gps_cit);
|
||||||
|
config_group_init_type_name(&se_dev->dev_stat_grps.stat_group,
|
||||||
|
"statistics", &target_core_stat_cit);
|
||||||
|
|
||||||
dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group;
|
dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group;
|
||||||
dev_cg->default_groups[1] = &se_dev->se_dev_pr_group;
|
dev_cg->default_groups[1] = &se_dev->se_dev_pr_group;
|
||||||
dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group;
|
dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group;
|
||||||
dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group;
|
dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group;
|
||||||
dev_cg->default_groups[4] = NULL;
|
dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group;
|
||||||
|
dev_cg->default_groups[5] = NULL;
|
||||||
/*
|
/*
|
||||||
* Add core/$HBA/$DEV/alua/tg_pt_gps/default_tg_pt_gp
|
* Add core/$HBA/$DEV/alua/default_tg_pt_gp
|
||||||
*/
|
*/
|
||||||
tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1);
|
tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1);
|
||||||
if (!(tg_pt_gp))
|
if (!(tg_pt_gp))
|
||||||
@ -2781,6 +2847,17 @@ static struct config_group *target_core_make_subdev(
|
|||||||
tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group;
|
tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group;
|
||||||
tg_pt_gp_cg->default_groups[1] = NULL;
|
tg_pt_gp_cg->default_groups[1] = NULL;
|
||||||
T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp;
|
T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp;
|
||||||
|
/*
|
||||||
|
* Add core/$HBA/$DEV/statistics/ default groups
|
||||||
|
*/
|
||||||
|
dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group;
|
||||||
|
dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!dev_stat_grp->default_groups) {
|
||||||
|
printk(KERN_ERR "Unable to allocate dev_stat_grp->default_groups\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
target_stat_setup_dev_default_groups(se_dev);
|
||||||
|
|
||||||
printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:"
|
printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:"
|
||||||
" %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr);
|
" %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr);
|
||||||
@ -2792,6 +2869,8 @@ out:
|
|||||||
core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp);
|
core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp);
|
||||||
T10_ALUA(se_dev)->default_tg_pt_gp = NULL;
|
T10_ALUA(se_dev)->default_tg_pt_gp = NULL;
|
||||||
}
|
}
|
||||||
|
if (dev_stat_grp)
|
||||||
|
kfree(dev_stat_grp->default_groups);
|
||||||
if (tg_pt_gp_cg)
|
if (tg_pt_gp_cg)
|
||||||
kfree(tg_pt_gp_cg->default_groups);
|
kfree(tg_pt_gp_cg->default_groups);
|
||||||
if (dev_cg)
|
if (dev_cg)
|
||||||
@ -2801,7 +2880,7 @@ out:
|
|||||||
kfree(se_dev);
|
kfree(se_dev);
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&hba->hba_access_mutex);
|
mutex_unlock(&hba->hba_access_mutex);
|
||||||
return NULL;
|
return ERR_PTR(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void target_core_drop_subdev(
|
static void target_core_drop_subdev(
|
||||||
@ -2813,7 +2892,7 @@ static void target_core_drop_subdev(
|
|||||||
struct se_hba *hba;
|
struct se_hba *hba;
|
||||||
struct se_subsystem_api *t;
|
struct se_subsystem_api *t;
|
||||||
struct config_item *df_item;
|
struct config_item *df_item;
|
||||||
struct config_group *dev_cg, *tg_pt_gp_cg;
|
struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item);
|
hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item);
|
||||||
@ -2825,6 +2904,14 @@ static void target_core_drop_subdev(
|
|||||||
list_del(&se_dev->g_se_dev_list);
|
list_del(&se_dev->g_se_dev_list);
|
||||||
spin_unlock(&se_global->g_device_lock);
|
spin_unlock(&se_global->g_device_lock);
|
||||||
|
|
||||||
|
dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group;
|
||||||
|
for (i = 0; dev_stat_grp->default_groups[i]; i++) {
|
||||||
|
df_item = &dev_stat_grp->default_groups[i]->cg_item;
|
||||||
|
dev_stat_grp->default_groups[i] = NULL;
|
||||||
|
config_item_put(df_item);
|
||||||
|
}
|
||||||
|
kfree(dev_stat_grp->default_groups);
|
||||||
|
|
||||||
tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group;
|
tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group;
|
||||||
for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) {
|
for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) {
|
||||||
df_item = &tg_pt_gp_cg->default_groups[i]->cg_item;
|
df_item = &tg_pt_gp_cg->default_groups[i]->cg_item;
|
||||||
@ -3044,7 +3131,7 @@ static struct config_item_type target_core_cit = {
|
|||||||
|
|
||||||
/* Stop functions for struct config_item_type target_core_hba_cit */
|
/* Stop functions for struct config_item_type target_core_hba_cit */
|
||||||
|
|
||||||
static int target_core_init_configfs(void)
|
static int __init target_core_init_configfs(void)
|
||||||
{
|
{
|
||||||
struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL;
|
struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL;
|
||||||
struct config_group *lu_gp_cg = NULL;
|
struct config_group *lu_gp_cg = NULL;
|
||||||
@ -3176,7 +3263,7 @@ out_global:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void target_core_exit_configfs(void)
|
static void __exit target_core_exit_configfs(void)
|
||||||
{
|
{
|
||||||
struct configfs_subsystem *subsys;
|
struct configfs_subsystem *subsys;
|
||||||
struct config_group *hba_cg, *alua_cg, *lu_gp_cg;
|
struct config_group *hba_cg, *alua_cg, *lu_gp_cg;
|
||||||
|
@ -589,6 +589,7 @@ static void core_export_port(
|
|||||||
* Called with struct se_device->se_port_lock spinlock held.
|
* Called with struct se_device->se_port_lock spinlock held.
|
||||||
*/
|
*/
|
||||||
static void core_release_port(struct se_device *dev, struct se_port *port)
|
static void core_release_port(struct se_device *dev, struct se_port *port)
|
||||||
|
__releases(&dev->se_port_lock) __acquires(&dev->se_port_lock)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Wait for any port reference for PR ALL_TG_PT=1 operation
|
* Wait for any port reference for PR ALL_TG_PT=1 operation
|
||||||
@ -779,49 +780,14 @@ void se_release_vpd_for_dev(struct se_device *dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Called with struct se_hba->device_lock held.
|
|
||||||
*/
|
|
||||||
void se_clear_dev_ports(struct se_device *dev)
|
|
||||||
{
|
|
||||||
struct se_hba *hba = dev->se_hba;
|
|
||||||
struct se_lun *lun;
|
|
||||||
struct se_portal_group *tpg;
|
|
||||||
struct se_port *sep, *sep_tmp;
|
|
||||||
|
|
||||||
spin_lock(&dev->se_port_lock);
|
|
||||||
list_for_each_entry_safe(sep, sep_tmp, &dev->dev_sep_list, sep_list) {
|
|
||||||
spin_unlock(&dev->se_port_lock);
|
|
||||||
spin_unlock(&hba->device_lock);
|
|
||||||
|
|
||||||
lun = sep->sep_lun;
|
|
||||||
tpg = sep->sep_tpg;
|
|
||||||
spin_lock(&lun->lun_sep_lock);
|
|
||||||
if (lun->lun_se_dev == NULL) {
|
|
||||||
spin_unlock(&lun->lun_sep_lock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
spin_unlock(&lun->lun_sep_lock);
|
|
||||||
|
|
||||||
core_dev_del_lun(tpg, lun->unpacked_lun);
|
|
||||||
|
|
||||||
spin_lock(&hba->device_lock);
|
|
||||||
spin_lock(&dev->se_port_lock);
|
|
||||||
}
|
|
||||||
spin_unlock(&dev->se_port_lock);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* se_free_virtual_device():
|
/* se_free_virtual_device():
|
||||||
*
|
*
|
||||||
* Used for IBLOCK, RAMDISK, and FILEIO Transport Drivers.
|
* Used for IBLOCK, RAMDISK, and FILEIO Transport Drivers.
|
||||||
*/
|
*/
|
||||||
int se_free_virtual_device(struct se_device *dev, struct se_hba *hba)
|
int se_free_virtual_device(struct se_device *dev, struct se_hba *hba)
|
||||||
{
|
{
|
||||||
spin_lock(&hba->device_lock);
|
if (!list_empty(&dev->dev_sep_list))
|
||||||
se_clear_dev_ports(dev);
|
dump_stack();
|
||||||
spin_unlock(&hba->device_lock);
|
|
||||||
|
|
||||||
core_alua_free_lu_gp_mem(dev);
|
core_alua_free_lu_gp_mem(dev);
|
||||||
se_release_device_for_hba(dev);
|
se_release_device_for_hba(dev);
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
* This file contains generic fabric module configfs infrastructure for
|
* This file contains generic fabric module configfs infrastructure for
|
||||||
* TCM v4.x code
|
* TCM v4.x code
|
||||||
*
|
*
|
||||||
* Copyright (c) 2010 Rising Tide Systems
|
* Copyright (c) 2010,2011 Rising Tide Systems
|
||||||
* Copyright (c) 2010 Linux-iSCSI.org
|
* Copyright (c) 2010,2011 Linux-iSCSI.org
|
||||||
*
|
*
|
||||||
* Copyright (c) 2010 Nicholas A. Bellinger <nab@linux-iscsi.org>
|
* Copyright (c) Nicholas A. Bellinger <nab@linux-iscsi.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -48,6 +48,7 @@
|
|||||||
#include "target_core_alua.h"
|
#include "target_core_alua.h"
|
||||||
#include "target_core_hba.h"
|
#include "target_core_hba.h"
|
||||||
#include "target_core_pr.h"
|
#include "target_core_pr.h"
|
||||||
|
#include "target_core_stat.h"
|
||||||
|
|
||||||
#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \
|
#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \
|
||||||
static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
|
static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
|
||||||
@ -241,6 +242,32 @@ TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL,
|
|||||||
|
|
||||||
/* End of tfc_tpg_mappedlun_cit */
|
/* End of tfc_tpg_mappedlun_cit */
|
||||||
|
|
||||||
|
/* Start of tfc_tpg_mappedlun_port_cit */
|
||||||
|
|
||||||
|
static struct config_group *target_core_mappedlun_stat_mkdir(
|
||||||
|
struct config_group *group,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void target_core_mappedlun_stat_rmdir(
|
||||||
|
struct config_group *group,
|
||||||
|
struct config_item *item)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = {
|
||||||
|
.make_group = target_core_mappedlun_stat_mkdir,
|
||||||
|
.drop_item = target_core_mappedlun_stat_rmdir,
|
||||||
|
};
|
||||||
|
|
||||||
|
TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* End of tfc_tpg_mappedlun_port_cit */
|
||||||
|
|
||||||
/* Start of tfc_tpg_nacl_attrib_cit */
|
/* Start of tfc_tpg_nacl_attrib_cit */
|
||||||
|
|
||||||
CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group);
|
CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group);
|
||||||
@ -294,6 +321,7 @@ static struct config_group *target_fabric_make_mappedlun(
|
|||||||
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
|
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
|
||||||
struct se_lun_acl *lacl;
|
struct se_lun_acl *lacl;
|
||||||
struct config_item *acl_ci;
|
struct config_item *acl_ci;
|
||||||
|
struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
|
||||||
char *buf;
|
char *buf;
|
||||||
unsigned long mapped_lun;
|
unsigned long mapped_lun;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -330,15 +358,42 @@ static struct config_group *target_fabric_make_mappedlun(
|
|||||||
|
|
||||||
lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun,
|
lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun,
|
||||||
config_item_name(acl_ci), &ret);
|
config_item_name(acl_ci), &ret);
|
||||||
if (!(lacl))
|
if (!(lacl)) {
|
||||||
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lacl_cg = &lacl->se_lun_group;
|
||||||
|
lacl_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!lacl_cg->default_groups) {
|
||||||
|
printk(KERN_ERR "Unable to allocate lacl_cg->default_groups\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
config_group_init_type_name(&lacl->se_lun_group, name,
|
config_group_init_type_name(&lacl->se_lun_group, name,
|
||||||
&TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit);
|
&TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit);
|
||||||
|
config_group_init_type_name(&lacl->ml_stat_grps.stat_group,
|
||||||
|
"statistics", &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_stat_cit);
|
||||||
|
lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group;
|
||||||
|
lacl_cg->default_groups[1] = NULL;
|
||||||
|
|
||||||
|
ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group;
|
||||||
|
ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!ml_stat_grp->default_groups) {
|
||||||
|
printk(KERN_ERR "Unable to allocate ml_stat_grp->default_groups\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
target_stat_setup_mappedlun_default_groups(lacl);
|
||||||
|
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return &lacl->se_lun_group;
|
return &lacl->se_lun_group;
|
||||||
out:
|
out:
|
||||||
|
if (lacl_cg)
|
||||||
|
kfree(lacl_cg->default_groups);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
@ -347,6 +402,28 @@ static void target_fabric_drop_mappedlun(
|
|||||||
struct config_group *group,
|
struct config_group *group,
|
||||||
struct config_item *item)
|
struct config_item *item)
|
||||||
{
|
{
|
||||||
|
struct se_lun_acl *lacl = container_of(to_config_group(item),
|
||||||
|
struct se_lun_acl, se_lun_group);
|
||||||
|
struct config_item *df_item;
|
||||||
|
struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group;
|
||||||
|
for (i = 0; ml_stat_grp->default_groups[i]; i++) {
|
||||||
|
df_item = &ml_stat_grp->default_groups[i]->cg_item;
|
||||||
|
ml_stat_grp->default_groups[i] = NULL;
|
||||||
|
config_item_put(df_item);
|
||||||
|
}
|
||||||
|
kfree(ml_stat_grp->default_groups);
|
||||||
|
|
||||||
|
lacl_cg = &lacl->se_lun_group;
|
||||||
|
for (i = 0; lacl_cg->default_groups[i]; i++) {
|
||||||
|
df_item = &lacl_cg->default_groups[i]->cg_item;
|
||||||
|
lacl_cg->default_groups[i] = NULL;
|
||||||
|
config_item_put(df_item);
|
||||||
|
}
|
||||||
|
kfree(lacl_cg->default_groups);
|
||||||
|
|
||||||
config_item_put(item);
|
config_item_put(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,6 +453,15 @@ TF_CIT_SETUP(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
|
|||||||
|
|
||||||
/* End of tfc_tpg_nacl_base_cit */
|
/* End of tfc_tpg_nacl_base_cit */
|
||||||
|
|
||||||
|
/* Start of tfc_node_fabric_stats_cit */
|
||||||
|
/*
|
||||||
|
* This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group
|
||||||
|
* to allow fabrics access to ->acl_fabric_stat_group->default_groups[]
|
||||||
|
*/
|
||||||
|
TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* End of tfc_wwn_fabric_stats_cit */
|
||||||
|
|
||||||
/* Start of tfc_tpg_nacl_cit */
|
/* Start of tfc_tpg_nacl_cit */
|
||||||
|
|
||||||
static struct config_group *target_fabric_make_nodeacl(
|
static struct config_group *target_fabric_make_nodeacl(
|
||||||
@ -402,7 +488,8 @@ static struct config_group *target_fabric_make_nodeacl(
|
|||||||
nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group;
|
nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group;
|
||||||
nacl_cg->default_groups[1] = &se_nacl->acl_auth_group;
|
nacl_cg->default_groups[1] = &se_nacl->acl_auth_group;
|
||||||
nacl_cg->default_groups[2] = &se_nacl->acl_param_group;
|
nacl_cg->default_groups[2] = &se_nacl->acl_param_group;
|
||||||
nacl_cg->default_groups[3] = NULL;
|
nacl_cg->default_groups[3] = &se_nacl->acl_fabric_stat_group;
|
||||||
|
nacl_cg->default_groups[4] = NULL;
|
||||||
|
|
||||||
config_group_init_type_name(&se_nacl->acl_group, name,
|
config_group_init_type_name(&se_nacl->acl_group, name,
|
||||||
&TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit);
|
&TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit);
|
||||||
@ -412,6 +499,9 @@ static struct config_group *target_fabric_make_nodeacl(
|
|||||||
&TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit);
|
&TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit);
|
||||||
config_group_init_type_name(&se_nacl->acl_param_group, "param",
|
config_group_init_type_name(&se_nacl->acl_param_group, "param",
|
||||||
&TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit);
|
&TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit);
|
||||||
|
config_group_init_type_name(&se_nacl->acl_fabric_stat_group,
|
||||||
|
"fabric_statistics",
|
||||||
|
&TF_CIT_TMPL(tf)->tfc_tpg_nacl_stat_cit);
|
||||||
|
|
||||||
return &se_nacl->acl_group;
|
return &se_nacl->acl_group;
|
||||||
}
|
}
|
||||||
@ -758,6 +848,31 @@ TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_at
|
|||||||
|
|
||||||
/* End of tfc_tpg_port_cit */
|
/* End of tfc_tpg_port_cit */
|
||||||
|
|
||||||
|
/* Start of tfc_tpg_port_stat_cit */
|
||||||
|
|
||||||
|
static struct config_group *target_core_port_stat_mkdir(
|
||||||
|
struct config_group *group,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void target_core_port_stat_rmdir(
|
||||||
|
struct config_group *group,
|
||||||
|
struct config_item *item)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_group_operations target_fabric_port_stat_group_ops = {
|
||||||
|
.make_group = target_core_port_stat_mkdir,
|
||||||
|
.drop_item = target_core_port_stat_rmdir,
|
||||||
|
};
|
||||||
|
|
||||||
|
TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL);
|
||||||
|
|
||||||
|
/* End of tfc_tpg_port_stat_cit */
|
||||||
|
|
||||||
/* Start of tfc_tpg_lun_cit */
|
/* Start of tfc_tpg_lun_cit */
|
||||||
|
|
||||||
static struct config_group *target_fabric_make_lun(
|
static struct config_group *target_fabric_make_lun(
|
||||||
@ -768,7 +883,9 @@ static struct config_group *target_fabric_make_lun(
|
|||||||
struct se_portal_group *se_tpg = container_of(group,
|
struct se_portal_group *se_tpg = container_of(group,
|
||||||
struct se_portal_group, tpg_lun_group);
|
struct se_portal_group, tpg_lun_group);
|
||||||
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
|
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
|
||||||
|
struct config_group *lun_cg = NULL, *port_stat_grp = NULL;
|
||||||
unsigned long unpacked_lun;
|
unsigned long unpacked_lun;
|
||||||
|
int errno;
|
||||||
|
|
||||||
if (strstr(name, "lun_") != name) {
|
if (strstr(name, "lun_") != name) {
|
||||||
printk(KERN_ERR "Unable to locate \'_\" in"
|
printk(KERN_ERR "Unable to locate \'_\" in"
|
||||||
@ -782,16 +899,64 @@ static struct config_group *target_fabric_make_lun(
|
|||||||
if (!(lun))
|
if (!(lun))
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
lun_cg = &lun->lun_group;
|
||||||
|
lun_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!lun_cg->default_groups) {
|
||||||
|
printk(KERN_ERR "Unable to allocate lun_cg->default_groups\n");
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
config_group_init_type_name(&lun->lun_group, name,
|
config_group_init_type_name(&lun->lun_group, name,
|
||||||
&TF_CIT_TMPL(tf)->tfc_tpg_port_cit);
|
&TF_CIT_TMPL(tf)->tfc_tpg_port_cit);
|
||||||
|
config_group_init_type_name(&lun->port_stat_grps.stat_group,
|
||||||
|
"statistics", &TF_CIT_TMPL(tf)->tfc_tpg_port_stat_cit);
|
||||||
|
lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group;
|
||||||
|
lun_cg->default_groups[1] = NULL;
|
||||||
|
|
||||||
|
port_stat_grp = &PORT_STAT_GRP(lun)->stat_group;
|
||||||
|
port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!port_stat_grp->default_groups) {
|
||||||
|
printk(KERN_ERR "Unable to allocate port_stat_grp->default_groups\n");
|
||||||
|
errno = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
target_stat_setup_port_default_groups(lun);
|
||||||
|
|
||||||
return &lun->lun_group;
|
return &lun->lun_group;
|
||||||
|
out:
|
||||||
|
if (lun_cg)
|
||||||
|
kfree(lun_cg->default_groups);
|
||||||
|
return ERR_PTR(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void target_fabric_drop_lun(
|
static void target_fabric_drop_lun(
|
||||||
struct config_group *group,
|
struct config_group *group,
|
||||||
struct config_item *item)
|
struct config_item *item)
|
||||||
{
|
{
|
||||||
|
struct se_lun *lun = container_of(to_config_group(item),
|
||||||
|
struct se_lun, lun_group);
|
||||||
|
struct config_item *df_item;
|
||||||
|
struct config_group *lun_cg, *port_stat_grp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
port_stat_grp = &PORT_STAT_GRP(lun)->stat_group;
|
||||||
|
for (i = 0; port_stat_grp->default_groups[i]; i++) {
|
||||||
|
df_item = &port_stat_grp->default_groups[i]->cg_item;
|
||||||
|
port_stat_grp->default_groups[i] = NULL;
|
||||||
|
config_item_put(df_item);
|
||||||
|
}
|
||||||
|
kfree(port_stat_grp->default_groups);
|
||||||
|
|
||||||
|
lun_cg = &lun->lun_group;
|
||||||
|
for (i = 0; lun_cg->default_groups[i]; i++) {
|
||||||
|
df_item = &lun_cg->default_groups[i]->cg_item;
|
||||||
|
lun_cg->default_groups[i] = NULL;
|
||||||
|
config_item_put(df_item);
|
||||||
|
}
|
||||||
|
kfree(lun_cg->default_groups);
|
||||||
|
|
||||||
config_item_put(item);
|
config_item_put(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,6 +1111,15 @@ TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops,
|
|||||||
|
|
||||||
/* End of tfc_tpg_cit */
|
/* End of tfc_tpg_cit */
|
||||||
|
|
||||||
|
/* Start of tfc_wwn_fabric_stats_cit */
|
||||||
|
/*
|
||||||
|
* This is used as a placeholder for struct se_wwn->fabric_stat_group
|
||||||
|
* to allow fabrics access to ->fabric_stat_group->default_groups[]
|
||||||
|
*/
|
||||||
|
TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* End of tfc_wwn_fabric_stats_cit */
|
||||||
|
|
||||||
/* Start of tfc_wwn_cit */
|
/* Start of tfc_wwn_cit */
|
||||||
|
|
||||||
static struct config_group *target_fabric_make_wwn(
|
static struct config_group *target_fabric_make_wwn(
|
||||||
@ -966,8 +1140,17 @@ static struct config_group *target_fabric_make_wwn(
|
|||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
wwn->wwn_tf = tf;
|
wwn->wwn_tf = tf;
|
||||||
|
/*
|
||||||
|
* Setup default groups from pre-allocated wwn->wwn_default_groups
|
||||||
|
*/
|
||||||
|
wwn->wwn_group.default_groups = wwn->wwn_default_groups;
|
||||||
|
wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group;
|
||||||
|
wwn->wwn_group.default_groups[1] = NULL;
|
||||||
|
|
||||||
config_group_init_type_name(&wwn->wwn_group, name,
|
config_group_init_type_name(&wwn->wwn_group, name,
|
||||||
&TF_CIT_TMPL(tf)->tfc_tpg_cit);
|
&TF_CIT_TMPL(tf)->tfc_tpg_cit);
|
||||||
|
config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics",
|
||||||
|
&TF_CIT_TMPL(tf)->tfc_wwn_fabric_stats_cit);
|
||||||
|
|
||||||
return &wwn->wwn_group;
|
return &wwn->wwn_group;
|
||||||
}
|
}
|
||||||
@ -976,6 +1159,18 @@ static void target_fabric_drop_wwn(
|
|||||||
struct config_group *group,
|
struct config_group *group,
|
||||||
struct config_item *item)
|
struct config_item *item)
|
||||||
{
|
{
|
||||||
|
struct se_wwn *wwn = container_of(to_config_group(item),
|
||||||
|
struct se_wwn, wwn_group);
|
||||||
|
struct config_item *df_item;
|
||||||
|
struct config_group *cg = &wwn->wwn_group;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; cg->default_groups[i]; i++) {
|
||||||
|
df_item = &cg->default_groups[i]->cg_item;
|
||||||
|
cg->default_groups[i] = NULL;
|
||||||
|
config_item_put(df_item);
|
||||||
|
}
|
||||||
|
|
||||||
config_item_put(item);
|
config_item_put(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1015,9 +1210,11 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf)
|
|||||||
{
|
{
|
||||||
target_fabric_setup_discovery_cit(tf);
|
target_fabric_setup_discovery_cit(tf);
|
||||||
target_fabric_setup_wwn_cit(tf);
|
target_fabric_setup_wwn_cit(tf);
|
||||||
|
target_fabric_setup_wwn_fabric_stats_cit(tf);
|
||||||
target_fabric_setup_tpg_cit(tf);
|
target_fabric_setup_tpg_cit(tf);
|
||||||
target_fabric_setup_tpg_base_cit(tf);
|
target_fabric_setup_tpg_base_cit(tf);
|
||||||
target_fabric_setup_tpg_port_cit(tf);
|
target_fabric_setup_tpg_port_cit(tf);
|
||||||
|
target_fabric_setup_tpg_port_stat_cit(tf);
|
||||||
target_fabric_setup_tpg_lun_cit(tf);
|
target_fabric_setup_tpg_lun_cit(tf);
|
||||||
target_fabric_setup_tpg_np_cit(tf);
|
target_fabric_setup_tpg_np_cit(tf);
|
||||||
target_fabric_setup_tpg_np_base_cit(tf);
|
target_fabric_setup_tpg_np_base_cit(tf);
|
||||||
@ -1028,7 +1225,9 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf)
|
|||||||
target_fabric_setup_tpg_nacl_attrib_cit(tf);
|
target_fabric_setup_tpg_nacl_attrib_cit(tf);
|
||||||
target_fabric_setup_tpg_nacl_auth_cit(tf);
|
target_fabric_setup_tpg_nacl_auth_cit(tf);
|
||||||
target_fabric_setup_tpg_nacl_param_cit(tf);
|
target_fabric_setup_tpg_nacl_param_cit(tf);
|
||||||
|
target_fabric_setup_tpg_nacl_stat_cit(tf);
|
||||||
target_fabric_setup_tpg_mappedlun_cit(tf);
|
target_fabric_setup_tpg_mappedlun_cit(tf);
|
||||||
|
target_fabric_setup_tpg_mappedlun_stat_cit(tf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <target/target_core_base.h>
|
#include <target/target_core_base.h>
|
||||||
#include <target/target_core_device.h>
|
#include <target/target_core_device.h>
|
||||||
#include <target/target_core_transport.h>
|
#include <target/target_core_transport.h>
|
||||||
|
#include <target/target_core_fabric_lib.h>
|
||||||
#include <target/target_core_fabric_ops.h>
|
#include <target/target_core_fabric_ops.h>
|
||||||
#include <target/target_core_configfs.h>
|
#include <target/target_core_configfs.h>
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ static struct se_device *fd_create_virtdevice(
|
|||||||
mm_segment_t old_fs;
|
mm_segment_t old_fs;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
int dev_flags = 0, flags;
|
int dev_flags = 0, flags, ret = -EINVAL;
|
||||||
|
|
||||||
memset(&dev_limits, 0, sizeof(struct se_dev_limits));
|
memset(&dev_limits, 0, sizeof(struct se_dev_limits));
|
||||||
|
|
||||||
@ -146,6 +146,7 @@ static struct se_device *fd_create_virtdevice(
|
|||||||
if (IS_ERR(dev_p)) {
|
if (IS_ERR(dev_p)) {
|
||||||
printk(KERN_ERR "getname(%s) failed: %lu\n",
|
printk(KERN_ERR "getname(%s) failed: %lu\n",
|
||||||
fd_dev->fd_dev_name, IS_ERR(dev_p));
|
fd_dev->fd_dev_name, IS_ERR(dev_p));
|
||||||
|
ret = PTR_ERR(dev_p);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
@ -165,8 +166,12 @@ static struct se_device *fd_create_virtdevice(
|
|||||||
flags |= O_SYNC;
|
flags |= O_SYNC;
|
||||||
|
|
||||||
file = filp_open(dev_p, flags, 0600);
|
file = filp_open(dev_p, flags, 0600);
|
||||||
|
if (IS_ERR(file)) {
|
||||||
if (IS_ERR(file) || !file || !file->f_dentry) {
|
printk(KERN_ERR "filp_open(%s) failed\n", dev_p);
|
||||||
|
ret = PTR_ERR(file);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!file || !file->f_dentry) {
|
||||||
printk(KERN_ERR "filp_open(%s) failed\n", dev_p);
|
printk(KERN_ERR "filp_open(%s) failed\n", dev_p);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -241,7 +246,7 @@ fail:
|
|||||||
fd_dev->fd_file = NULL;
|
fd_dev->fd_file = NULL;
|
||||||
}
|
}
|
||||||
putname(dev_p);
|
putname(dev_p);
|
||||||
return NULL;
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fd_free_device(): (Part of se_subsystem_api_t template)
|
/* fd_free_device(): (Part of se_subsystem_api_t template)
|
||||||
@ -509,7 +514,7 @@ enum {
|
|||||||
static match_table_t tokens = {
|
static match_table_t tokens = {
|
||||||
{Opt_fd_dev_name, "fd_dev_name=%s"},
|
{Opt_fd_dev_name, "fd_dev_name=%s"},
|
||||||
{Opt_fd_dev_size, "fd_dev_size=%s"},
|
{Opt_fd_dev_size, "fd_dev_size=%s"},
|
||||||
{Opt_fd_buffered_io, "fd_buffered_id=%d"},
|
{Opt_fd_buffered_io, "fd_buffered_io=%d"},
|
||||||
{Opt_err, NULL}
|
{Opt_err, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -536,15 +541,26 @@ static ssize_t fd_set_configfs_dev_params(
|
|||||||
token = match_token(ptr, tokens, args);
|
token = match_token(ptr, tokens, args);
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case Opt_fd_dev_name:
|
case Opt_fd_dev_name:
|
||||||
|
arg_p = match_strdup(&args[0]);
|
||||||
|
if (!arg_p) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
snprintf(fd_dev->fd_dev_name, FD_MAX_DEV_NAME,
|
snprintf(fd_dev->fd_dev_name, FD_MAX_DEV_NAME,
|
||||||
"%s", match_strdup(&args[0]));
|
"%s", arg_p);
|
||||||
|
kfree(arg_p);
|
||||||
printk(KERN_INFO "FILEIO: Referencing Path: %s\n",
|
printk(KERN_INFO "FILEIO: Referencing Path: %s\n",
|
||||||
fd_dev->fd_dev_name);
|
fd_dev->fd_dev_name);
|
||||||
fd_dev->fbd_flags |= FBDF_HAS_PATH;
|
fd_dev->fbd_flags |= FBDF_HAS_PATH;
|
||||||
break;
|
break;
|
||||||
case Opt_fd_dev_size:
|
case Opt_fd_dev_size:
|
||||||
arg_p = match_strdup(&args[0]);
|
arg_p = match_strdup(&args[0]);
|
||||||
|
if (!arg_p) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
ret = strict_strtoull(arg_p, 0, &fd_dev->fd_dev_size);
|
ret = strict_strtoull(arg_p, 0, &fd_dev->fd_dev_size);
|
||||||
|
kfree(arg_p);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "strict_strtoull() failed for"
|
printk(KERN_ERR "strict_strtoull() failed for"
|
||||||
" fd_dev_size=\n");
|
" fd_dev_size=\n");
|
||||||
|
@ -151,19 +151,8 @@ out_free_hba:
|
|||||||
int
|
int
|
||||||
core_delete_hba(struct se_hba *hba)
|
core_delete_hba(struct se_hba *hba)
|
||||||
{
|
{
|
||||||
struct se_device *dev, *dev_tmp;
|
if (!list_empty(&hba->hba_dev_list))
|
||||||
|
dump_stack();
|
||||||
spin_lock(&hba->device_lock);
|
|
||||||
list_for_each_entry_safe(dev, dev_tmp, &hba->hba_dev_list, dev_list) {
|
|
||||||
|
|
||||||
se_clear_dev_ports(dev);
|
|
||||||
spin_unlock(&hba->device_lock);
|
|
||||||
|
|
||||||
se_release_device_for_hba(dev);
|
|
||||||
|
|
||||||
spin_lock(&hba->device_lock);
|
|
||||||
}
|
|
||||||
spin_unlock(&hba->device_lock);
|
|
||||||
|
|
||||||
hba->transport->detach_hba(hba);
|
hba->transport->detach_hba(hba);
|
||||||
|
|
||||||
|
@ -129,10 +129,11 @@ static struct se_device *iblock_create_virtdevice(
|
|||||||
struct request_queue *q;
|
struct request_queue *q;
|
||||||
struct queue_limits *limits;
|
struct queue_limits *limits;
|
||||||
u32 dev_flags = 0;
|
u32 dev_flags = 0;
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
if (!(ib_dev)) {
|
if (!(ib_dev)) {
|
||||||
printk(KERN_ERR "Unable to locate struct iblock_dev parameter\n");
|
printk(KERN_ERR "Unable to locate struct iblock_dev parameter\n");
|
||||||
return 0;
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
memset(&dev_limits, 0, sizeof(struct se_dev_limits));
|
memset(&dev_limits, 0, sizeof(struct se_dev_limits));
|
||||||
/*
|
/*
|
||||||
@ -141,7 +142,7 @@ static struct se_device *iblock_create_virtdevice(
|
|||||||
ib_dev->ibd_bio_set = bioset_create(32, 64);
|
ib_dev->ibd_bio_set = bioset_create(32, 64);
|
||||||
if (!(ib_dev->ibd_bio_set)) {
|
if (!(ib_dev->ibd_bio_set)) {
|
||||||
printk(KERN_ERR "IBLOCK: Unable to create bioset()\n");
|
printk(KERN_ERR "IBLOCK: Unable to create bioset()\n");
|
||||||
return 0;
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
printk(KERN_INFO "IBLOCK: Created bio_set()\n");
|
printk(KERN_INFO "IBLOCK: Created bio_set()\n");
|
||||||
/*
|
/*
|
||||||
@ -153,8 +154,10 @@ static struct se_device *iblock_create_virtdevice(
|
|||||||
|
|
||||||
bd = blkdev_get_by_path(ib_dev->ibd_udev_path,
|
bd = blkdev_get_by_path(ib_dev->ibd_udev_path,
|
||||||
FMODE_WRITE|FMODE_READ|FMODE_EXCL, ib_dev);
|
FMODE_WRITE|FMODE_READ|FMODE_EXCL, ib_dev);
|
||||||
if (IS_ERR(bd))
|
if (IS_ERR(bd)) {
|
||||||
|
ret = PTR_ERR(bd);
|
||||||
goto failed;
|
goto failed;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Setup the local scope queue_limits from struct request_queue->limits
|
* Setup the local scope queue_limits from struct request_queue->limits
|
||||||
* to pass into transport_add_device_to_core_hba() as struct se_dev_limits.
|
* to pass into transport_add_device_to_core_hba() as struct se_dev_limits.
|
||||||
@ -184,9 +187,7 @@ static struct se_device *iblock_create_virtdevice(
|
|||||||
* the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
|
* the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
|
||||||
* in ATA and we need to set TPE=1
|
* in ATA and we need to set TPE=1
|
||||||
*/
|
*/
|
||||||
if (blk_queue_discard(bdev_get_queue(bd))) {
|
if (blk_queue_discard(q)) {
|
||||||
struct request_queue *q = bdev_get_queue(bd);
|
|
||||||
|
|
||||||
DEV_ATTRIB(dev)->max_unmap_lba_count =
|
DEV_ATTRIB(dev)->max_unmap_lba_count =
|
||||||
q->limits.max_discard_sectors;
|
q->limits.max_discard_sectors;
|
||||||
/*
|
/*
|
||||||
@ -212,7 +213,7 @@ failed:
|
|||||||
ib_dev->ibd_bd = NULL;
|
ib_dev->ibd_bd = NULL;
|
||||||
ib_dev->ibd_major = 0;
|
ib_dev->ibd_major = 0;
|
||||||
ib_dev->ibd_minor = 0;
|
ib_dev->ibd_minor = 0;
|
||||||
return NULL;
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iblock_free_device(void *p)
|
static void iblock_free_device(void *p)
|
||||||
@ -467,7 +468,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
|
|||||||
const char *page, ssize_t count)
|
const char *page, ssize_t count)
|
||||||
{
|
{
|
||||||
struct iblock_dev *ib_dev = se_dev->se_dev_su_ptr;
|
struct iblock_dev *ib_dev = se_dev->se_dev_su_ptr;
|
||||||
char *orig, *ptr, *opts;
|
char *orig, *ptr, *arg_p, *opts;
|
||||||
substring_t args[MAX_OPT_ARGS];
|
substring_t args[MAX_OPT_ARGS];
|
||||||
int ret = 0, arg, token;
|
int ret = 0, arg, token;
|
||||||
|
|
||||||
@ -490,9 +491,14 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
|
|||||||
ret = -EEXIST;
|
ret = -EEXIST;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
arg_p = match_strdup(&args[0]);
|
||||||
ret = snprintf(ib_dev->ibd_udev_path, SE_UDEV_PATH_LEN,
|
if (!arg_p) {
|
||||||
"%s", match_strdup(&args[0]));
|
ret = -ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
snprintf(ib_dev->ibd_udev_path, SE_UDEV_PATH_LEN,
|
||||||
|
"%s", arg_p);
|
||||||
|
kfree(arg_p);
|
||||||
printk(KERN_INFO "IBLOCK: Referencing UDEV path: %s\n",
|
printk(KERN_INFO "IBLOCK: Referencing UDEV path: %s\n",
|
||||||
ib_dev->ibd_udev_path);
|
ib_dev->ibd_udev_path);
|
||||||
ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH;
|
ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH;
|
||||||
|
@ -441,6 +441,7 @@ static struct se_device *pscsi_create_type_disk(
|
|||||||
struct pscsi_dev_virt *pdv,
|
struct pscsi_dev_virt *pdv,
|
||||||
struct se_subsystem_dev *se_dev,
|
struct se_subsystem_dev *se_dev,
|
||||||
struct se_hba *hba)
|
struct se_hba *hba)
|
||||||
|
__releases(sh->host_lock)
|
||||||
{
|
{
|
||||||
struct se_device *dev;
|
struct se_device *dev;
|
||||||
struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
|
struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
|
||||||
@ -488,6 +489,7 @@ static struct se_device *pscsi_create_type_rom(
|
|||||||
struct pscsi_dev_virt *pdv,
|
struct pscsi_dev_virt *pdv,
|
||||||
struct se_subsystem_dev *se_dev,
|
struct se_subsystem_dev *se_dev,
|
||||||
struct se_hba *hba)
|
struct se_hba *hba)
|
||||||
|
__releases(sh->host_lock)
|
||||||
{
|
{
|
||||||
struct se_device *dev;
|
struct se_device *dev;
|
||||||
struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
|
struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
|
||||||
@ -522,6 +524,7 @@ static struct se_device *pscsi_create_type_other(
|
|||||||
struct pscsi_dev_virt *pdv,
|
struct pscsi_dev_virt *pdv,
|
||||||
struct se_subsystem_dev *se_dev,
|
struct se_subsystem_dev *se_dev,
|
||||||
struct se_hba *hba)
|
struct se_hba *hba)
|
||||||
|
__releases(sh->host_lock)
|
||||||
{
|
{
|
||||||
struct se_device *dev;
|
struct se_device *dev;
|
||||||
struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
|
struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
|
||||||
@ -555,7 +558,7 @@ static struct se_device *pscsi_create_virtdevice(
|
|||||||
if (!(pdv)) {
|
if (!(pdv)) {
|
||||||
printk(KERN_ERR "Unable to locate struct pscsi_dev_virt"
|
printk(KERN_ERR "Unable to locate struct pscsi_dev_virt"
|
||||||
" parameter\n");
|
" parameter\n");
|
||||||
return NULL;
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If not running in PHV_LLD_SCSI_HOST_NO mode, locate the
|
* If not running in PHV_LLD_SCSI_HOST_NO mode, locate the
|
||||||
@ -565,7 +568,7 @@ static struct se_device *pscsi_create_virtdevice(
|
|||||||
if (phv->phv_mode == PHV_LLD_SCSI_HOST_NO) {
|
if (phv->phv_mode == PHV_LLD_SCSI_HOST_NO) {
|
||||||
printk(KERN_ERR "pSCSI: Unable to locate struct"
|
printk(KERN_ERR "pSCSI: Unable to locate struct"
|
||||||
" Scsi_Host for PHV_LLD_SCSI_HOST_NO\n");
|
" Scsi_Host for PHV_LLD_SCSI_HOST_NO\n");
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* For the newer PHV_VIRUTAL_HOST_ID struct scsi_device
|
* For the newer PHV_VIRUTAL_HOST_ID struct scsi_device
|
||||||
@ -574,7 +577,7 @@ static struct se_device *pscsi_create_virtdevice(
|
|||||||
if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) {
|
if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) {
|
||||||
printk(KERN_ERR "pSCSI: udev_path attribute has not"
|
printk(KERN_ERR "pSCSI: udev_path attribute has not"
|
||||||
" been set before ENABLE=1\n");
|
" been set before ENABLE=1\n");
|
||||||
return NULL;
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If no scsi_host_id= was passed for PHV_VIRUTAL_HOST_ID,
|
* If no scsi_host_id= was passed for PHV_VIRUTAL_HOST_ID,
|
||||||
@ -587,12 +590,12 @@ static struct se_device *pscsi_create_virtdevice(
|
|||||||
printk(KERN_ERR "pSCSI: Unable to set hba_mode"
|
printk(KERN_ERR "pSCSI: Unable to set hba_mode"
|
||||||
" with active devices\n");
|
" with active devices\n");
|
||||||
spin_unlock(&hba->device_lock);
|
spin_unlock(&hba->device_lock);
|
||||||
return NULL;
|
return ERR_PTR(-EEXIST);
|
||||||
}
|
}
|
||||||
spin_unlock(&hba->device_lock);
|
spin_unlock(&hba->device_lock);
|
||||||
|
|
||||||
if (pscsi_pmode_enable_hba(hba, 1) != 1)
|
if (pscsi_pmode_enable_hba(hba, 1) != 1)
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
legacy_mode_enable = 1;
|
legacy_mode_enable = 1;
|
||||||
hba->hba_flags |= HBA_FLAGS_PSCSI_MODE;
|
hba->hba_flags |= HBA_FLAGS_PSCSI_MODE;
|
||||||
@ -602,14 +605,14 @@ static struct se_device *pscsi_create_virtdevice(
|
|||||||
if (!(sh)) {
|
if (!(sh)) {
|
||||||
printk(KERN_ERR "pSCSI: Unable to locate"
|
printk(KERN_ERR "pSCSI: Unable to locate"
|
||||||
" pdv_host_id: %d\n", pdv->pdv_host_id);
|
" pdv_host_id: %d\n", pdv->pdv_host_id);
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (phv->phv_mode == PHV_VIRUTAL_HOST_ID) {
|
if (phv->phv_mode == PHV_VIRUTAL_HOST_ID) {
|
||||||
printk(KERN_ERR "pSCSI: PHV_VIRUTAL_HOST_ID set while"
|
printk(KERN_ERR "pSCSI: PHV_VIRUTAL_HOST_ID set while"
|
||||||
" struct Scsi_Host exists\n");
|
" struct Scsi_Host exists\n");
|
||||||
return NULL;
|
return ERR_PTR(-EEXIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,7 +647,7 @@ static struct se_device *pscsi_create_virtdevice(
|
|||||||
hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE;
|
hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE;
|
||||||
}
|
}
|
||||||
pdv->pdv_sd = NULL;
|
pdv->pdv_sd = NULL;
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
@ -660,7 +663,7 @@ static struct se_device *pscsi_create_virtdevice(
|
|||||||
hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE;
|
hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pscsi_free_device(): (Part of se_subsystem_api_t template)
|
/* pscsi_free_device(): (Part of se_subsystem_api_t template)
|
||||||
@ -816,6 +819,7 @@ pscsi_alloc_task(struct se_cmd *cmd)
|
|||||||
if (!(pt->pscsi_cdb)) {
|
if (!(pt->pscsi_cdb)) {
|
||||||
printk(KERN_ERR "pSCSI: Unable to allocate extended"
|
printk(KERN_ERR "pSCSI: Unable to allocate extended"
|
||||||
" pt->pscsi_cdb\n");
|
" pt->pscsi_cdb\n");
|
||||||
|
kfree(pt);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -150,7 +150,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
|
|||||||
if (rd_dev->rd_page_count <= 0) {
|
if (rd_dev->rd_page_count <= 0) {
|
||||||
printk(KERN_ERR "Illegal page count: %u for Ramdisk device\n",
|
printk(KERN_ERR "Illegal page count: %u for Ramdisk device\n",
|
||||||
rd_dev->rd_page_count);
|
rd_dev->rd_page_count);
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
total_sg_needed = rd_dev->rd_page_count;
|
total_sg_needed = rd_dev->rd_page_count;
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
|
|||||||
if (!(sg_table)) {
|
if (!(sg_table)) {
|
||||||
printk(KERN_ERR "Unable to allocate memory for Ramdisk"
|
printk(KERN_ERR "Unable to allocate memory for Ramdisk"
|
||||||
" scatterlist tables\n");
|
" scatterlist tables\n");
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
rd_dev->sg_table_array = sg_table;
|
rd_dev->sg_table_array = sg_table;
|
||||||
@ -175,7 +175,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
|
|||||||
if (!(sg)) {
|
if (!(sg)) {
|
||||||
printk(KERN_ERR "Unable to allocate scatterlist array"
|
printk(KERN_ERR "Unable to allocate scatterlist array"
|
||||||
" for struct rd_dev\n");
|
" for struct rd_dev\n");
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
sg_init_table((struct scatterlist *)&sg[0], sg_per_table);
|
sg_init_table((struct scatterlist *)&sg[0], sg_per_table);
|
||||||
@ -191,7 +191,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
|
|||||||
if (!(pg)) {
|
if (!(pg)) {
|
||||||
printk(KERN_ERR "Unable to allocate scatterlist"
|
printk(KERN_ERR "Unable to allocate scatterlist"
|
||||||
" pages for struct rd_dev_sg_table\n");
|
" pages for struct rd_dev_sg_table\n");
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
sg_assign_page(&sg[j], pg);
|
sg_assign_page(&sg[j], pg);
|
||||||
sg[j].length = PAGE_SIZE;
|
sg[j].length = PAGE_SIZE;
|
||||||
@ -253,12 +253,13 @@ static struct se_device *rd_create_virtdevice(
|
|||||||
struct se_dev_limits dev_limits;
|
struct se_dev_limits dev_limits;
|
||||||
struct rd_dev *rd_dev = p;
|
struct rd_dev *rd_dev = p;
|
||||||
struct rd_host *rd_host = hba->hba_ptr;
|
struct rd_host *rd_host = hba->hba_ptr;
|
||||||
int dev_flags = 0;
|
int dev_flags = 0, ret;
|
||||||
char prod[16], rev[4];
|
char prod[16], rev[4];
|
||||||
|
|
||||||
memset(&dev_limits, 0, sizeof(struct se_dev_limits));
|
memset(&dev_limits, 0, sizeof(struct se_dev_limits));
|
||||||
|
|
||||||
if (rd_build_device_space(rd_dev) < 0)
|
ret = rd_build_device_space(rd_dev);
|
||||||
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
snprintf(prod, 16, "RAMDISK-%s", (rd_dev->rd_direct) ? "DR" : "MCP");
|
snprintf(prod, 16, "RAMDISK-%s", (rd_dev->rd_direct) ? "DR" : "MCP");
|
||||||
@ -292,7 +293,7 @@ static struct se_device *rd_create_virtdevice(
|
|||||||
|
|
||||||
fail:
|
fail:
|
||||||
rd_release_device_space(rd_dev);
|
rd_release_device_space(rd_dev);
|
||||||
return NULL;
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct se_device *rd_DIRECT_create_virtdevice(
|
static struct se_device *rd_DIRECT_create_virtdevice(
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
#define RD_BLOCKSIZE 512
|
#define RD_BLOCKSIZE 512
|
||||||
#define RD_MAX_SECTORS 1024
|
#define RD_MAX_SECTORS 1024
|
||||||
|
|
||||||
extern struct kmem_cache *se_mem_cache;
|
|
||||||
|
|
||||||
/* Used in target_core_init_configfs() for virtual LUN 0 access */
|
/* Used in target_core_init_configfs() for virtual LUN 0 access */
|
||||||
int __init rd_module_init(void);
|
int __init rd_module_init(void);
|
||||||
void rd_module_exit(void);
|
void rd_module_exit(void);
|
||||||
|
1810
drivers/target/target_core_stat.c
Normal file
1810
drivers/target/target_core_stat.c
Normal file
File diff suppressed because it is too large
Load Diff
8
drivers/target/target_core_stat.h
Normal file
8
drivers/target/target_core_stat.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef TARGET_CORE_STAT_H
|
||||||
|
#define TARGET_CORE_STAT_H
|
||||||
|
|
||||||
|
extern void target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
|
||||||
|
extern void target_stat_setup_port_default_groups(struct se_lun *);
|
||||||
|
extern void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
|
||||||
|
|
||||||
|
#endif /*** TARGET_CORE_STAT_H ***/
|
@ -227,8 +227,6 @@ static void transport_remove_cmd_from_queue(struct se_cmd *cmd,
|
|||||||
static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq);
|
static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq);
|
||||||
static void transport_stop_all_task_timers(struct se_cmd *cmd);
|
static void transport_stop_all_task_timers(struct se_cmd *cmd);
|
||||||
|
|
||||||
int transport_emulate_control_cdb(struct se_task *task);
|
|
||||||
|
|
||||||
int init_se_global(void)
|
int init_se_global(void)
|
||||||
{
|
{
|
||||||
struct se_global *global;
|
struct se_global *global;
|
||||||
@ -1622,7 +1620,7 @@ struct se_device *transport_add_device_to_core_hba(
|
|||||||
const char *inquiry_prod,
|
const char *inquiry_prod,
|
||||||
const char *inquiry_rev)
|
const char *inquiry_rev)
|
||||||
{
|
{
|
||||||
int ret = 0, force_pt;
|
int force_pt;
|
||||||
struct se_device *dev;
|
struct se_device *dev;
|
||||||
|
|
||||||
dev = kzalloc(sizeof(struct se_device), GFP_KERNEL);
|
dev = kzalloc(sizeof(struct se_device), GFP_KERNEL);
|
||||||
@ -1739,9 +1737,8 @@ struct se_device *transport_add_device_to_core_hba(
|
|||||||
}
|
}
|
||||||
scsi_dump_inquiry(dev);
|
scsi_dump_inquiry(dev);
|
||||||
|
|
||||||
|
return dev;
|
||||||
out:
|
out:
|
||||||
if (!ret)
|
|
||||||
return dev;
|
|
||||||
kthread_stop(dev->process_thread);
|
kthread_stop(dev->process_thread);
|
||||||
|
|
||||||
spin_lock(&hba->device_lock);
|
spin_lock(&hba->device_lock);
|
||||||
@ -4359,11 +4356,9 @@ transport_generic_get_mem(struct se_cmd *cmd, u32 length, u32 dma_size)
|
|||||||
printk(KERN_ERR "Unable to allocate struct se_mem\n");
|
printk(KERN_ERR "Unable to allocate struct se_mem\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
INIT_LIST_HEAD(&se_mem->se_list);
|
|
||||||
se_mem->se_len = (length > dma_size) ? dma_size : length;
|
|
||||||
|
|
||||||
/* #warning FIXME Allocate contigous pages for struct se_mem elements */
|
/* #warning FIXME Allocate contigous pages for struct se_mem elements */
|
||||||
se_mem->se_page = (struct page *) alloc_pages(GFP_KERNEL, 0);
|
se_mem->se_page = alloc_pages(GFP_KERNEL, 0);
|
||||||
if (!(se_mem->se_page)) {
|
if (!(se_mem->se_page)) {
|
||||||
printk(KERN_ERR "alloc_pages() failed\n");
|
printk(KERN_ERR "alloc_pages() failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
@ -4374,6 +4369,8 @@ transport_generic_get_mem(struct se_cmd *cmd, u32 length, u32 dma_size)
|
|||||||
printk(KERN_ERR "kmap_atomic() failed\n");
|
printk(KERN_ERR "kmap_atomic() failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
INIT_LIST_HEAD(&se_mem->se_list);
|
||||||
|
se_mem->se_len = (length > dma_size) ? dma_size : length;
|
||||||
memset(buf, 0, se_mem->se_len);
|
memset(buf, 0, se_mem->se_len);
|
||||||
kunmap_atomic(buf, KM_IRQ0);
|
kunmap_atomic(buf, KM_IRQ0);
|
||||||
|
|
||||||
@ -4392,10 +4389,13 @@ transport_generic_get_mem(struct se_cmd *cmd, u32 length, u32 dma_size)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
out:
|
out:
|
||||||
|
if (se_mem)
|
||||||
|
__free_pages(se_mem->se_page, 0);
|
||||||
|
kmem_cache_free(se_mem_cache, se_mem);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern u32 transport_calc_sg_num(
|
u32 transport_calc_sg_num(
|
||||||
struct se_task *task,
|
struct se_task *task,
|
||||||
struct se_mem *in_se_mem,
|
struct se_mem *in_se_mem,
|
||||||
u32 task_offset)
|
u32 task_offset)
|
||||||
@ -5834,31 +5834,26 @@ int transport_generic_do_tmr(struct se_cmd *cmd)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (tmr->function) {
|
switch (tmr->function) {
|
||||||
case ABORT_TASK:
|
case TMR_ABORT_TASK:
|
||||||
ref_cmd = tmr->ref_cmd;
|
ref_cmd = tmr->ref_cmd;
|
||||||
tmr->response = TMR_FUNCTION_REJECTED;
|
tmr->response = TMR_FUNCTION_REJECTED;
|
||||||
break;
|
break;
|
||||||
case ABORT_TASK_SET:
|
case TMR_ABORT_TASK_SET:
|
||||||
case CLEAR_ACA:
|
case TMR_CLEAR_ACA:
|
||||||
case CLEAR_TASK_SET:
|
case TMR_CLEAR_TASK_SET:
|
||||||
tmr->response = TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
|
tmr->response = TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
|
||||||
break;
|
break;
|
||||||
case LUN_RESET:
|
case TMR_LUN_RESET:
|
||||||
ret = core_tmr_lun_reset(dev, tmr, NULL, NULL);
|
ret = core_tmr_lun_reset(dev, tmr, NULL, NULL);
|
||||||
tmr->response = (!ret) ? TMR_FUNCTION_COMPLETE :
|
tmr->response = (!ret) ? TMR_FUNCTION_COMPLETE :
|
||||||
TMR_FUNCTION_REJECTED;
|
TMR_FUNCTION_REJECTED;
|
||||||
break;
|
break;
|
||||||
#if 0
|
case TMR_TARGET_WARM_RESET:
|
||||||
case TARGET_WARM_RESET:
|
|
||||||
transport_generic_host_reset(dev->se_hba);
|
|
||||||
tmr->response = TMR_FUNCTION_REJECTED;
|
tmr->response = TMR_FUNCTION_REJECTED;
|
||||||
break;
|
break;
|
||||||
case TARGET_COLD_RESET:
|
case TMR_TARGET_COLD_RESET:
|
||||||
transport_generic_host_reset(dev->se_hba);
|
|
||||||
transport_generic_cold_reset(dev->se_hba);
|
|
||||||
tmr->response = TMR_FUNCTION_REJECTED;
|
tmr->response = TMR_FUNCTION_REJECTED;
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "Uknown TMR function: 0x%02x.\n",
|
printk(KERN_ERR "Uknown TMR function: 0x%02x.\n",
|
||||||
tmr->function);
|
tmr->function);
|
||||||
|
@ -47,6 +47,7 @@ struct iscsi_segment {
|
|||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
void *sg_mapped;
|
void *sg_mapped;
|
||||||
unsigned int sg_offset;
|
unsigned int sg_offset;
|
||||||
|
bool atomic_mapped;
|
||||||
|
|
||||||
iscsi_segment_done_fn_t *done;
|
iscsi_segment_done_fn_t *done;
|
||||||
};
|
};
|
||||||
|
@ -462,7 +462,7 @@ static inline int scsi_device_qas(struct scsi_device *sdev)
|
|||||||
}
|
}
|
||||||
static inline int scsi_device_enclosure(struct scsi_device *sdev)
|
static inline int scsi_device_enclosure(struct scsi_device *sdev)
|
||||||
{
|
{
|
||||||
return sdev->inquiry[6] & (1<<6);
|
return sdev->inquiry ? (sdev->inquiry[6] & (1<<6)) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int scsi_device_protection(struct scsi_device *sdev)
|
static inline int scsi_device_protection(struct scsi_device *sdev)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
#include <net/tcp.h>
|
#include <net/tcp.h>
|
||||||
|
|
||||||
#define TARGET_CORE_MOD_VERSION "v4.0.0-rc6"
|
#define TARGET_CORE_MOD_VERSION "v4.0.0-rc7-ml"
|
||||||
#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGABRT))
|
#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGABRT))
|
||||||
|
|
||||||
/* Used by transport_generic_allocate_iovecs() */
|
/* Used by transport_generic_allocate_iovecs() */
|
||||||
@ -239,7 +239,7 @@ struct t10_alua_lu_gp {
|
|||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
struct t10_alua_lu_gp_member {
|
struct t10_alua_lu_gp_member {
|
||||||
int lu_gp_assoc:1;
|
bool lu_gp_assoc;
|
||||||
atomic_t lu_gp_mem_ref_cnt;
|
atomic_t lu_gp_mem_ref_cnt;
|
||||||
spinlock_t lu_gp_mem_lock;
|
spinlock_t lu_gp_mem_lock;
|
||||||
struct t10_alua_lu_gp *lu_gp;
|
struct t10_alua_lu_gp *lu_gp;
|
||||||
@ -271,7 +271,7 @@ struct t10_alua_tg_pt_gp {
|
|||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
struct t10_alua_tg_pt_gp_member {
|
struct t10_alua_tg_pt_gp_member {
|
||||||
int tg_pt_gp_assoc:1;
|
bool tg_pt_gp_assoc;
|
||||||
atomic_t tg_pt_gp_mem_ref_cnt;
|
atomic_t tg_pt_gp_mem_ref_cnt;
|
||||||
spinlock_t tg_pt_gp_mem_lock;
|
spinlock_t tg_pt_gp_mem_lock;
|
||||||
struct t10_alua_tg_pt_gp *tg_pt_gp;
|
struct t10_alua_tg_pt_gp *tg_pt_gp;
|
||||||
@ -336,7 +336,7 @@ struct t10_pr_registration {
|
|||||||
int pr_res_type;
|
int pr_res_type;
|
||||||
int pr_res_scope;
|
int pr_res_scope;
|
||||||
/* Used for fabric initiator WWPNs using a ISID */
|
/* Used for fabric initiator WWPNs using a ISID */
|
||||||
int isid_present_at_reg:1;
|
bool isid_present_at_reg;
|
||||||
u32 pr_res_mapped_lun;
|
u32 pr_res_mapped_lun;
|
||||||
u32 pr_aptpl_target_lun;
|
u32 pr_aptpl_target_lun;
|
||||||
u32 pr_res_generation;
|
u32 pr_res_generation;
|
||||||
@ -418,7 +418,7 @@ struct se_transport_task {
|
|||||||
unsigned long long t_task_lba;
|
unsigned long long t_task_lba;
|
||||||
int t_tasks_failed;
|
int t_tasks_failed;
|
||||||
int t_tasks_fua;
|
int t_tasks_fua;
|
||||||
int t_tasks_bidi:1;
|
bool t_tasks_bidi;
|
||||||
u32 t_task_cdbs;
|
u32 t_task_cdbs;
|
||||||
u32 t_tasks_check;
|
u32 t_tasks_check;
|
||||||
u32 t_tasks_no;
|
u32 t_tasks_no;
|
||||||
@ -470,7 +470,7 @@ struct se_task {
|
|||||||
u8 task_flags;
|
u8 task_flags;
|
||||||
int task_error_status;
|
int task_error_status;
|
||||||
int task_state_flags;
|
int task_state_flags;
|
||||||
int task_padded_sg:1;
|
bool task_padded_sg;
|
||||||
unsigned long long task_lba;
|
unsigned long long task_lba;
|
||||||
u32 task_no;
|
u32 task_no;
|
||||||
u32 task_sectors;
|
u32 task_sectors;
|
||||||
@ -494,8 +494,8 @@ struct se_task {
|
|||||||
struct list_head t_state_list;
|
struct list_head t_state_list;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
#define TASK_CMD(task) ((struct se_cmd *)task->task_se_cmd)
|
#define TASK_CMD(task) ((task)->task_se_cmd)
|
||||||
#define TASK_DEV(task) ((struct se_device *)task->se_dev)
|
#define TASK_DEV(task) ((task)->se_dev)
|
||||||
|
|
||||||
struct se_cmd {
|
struct se_cmd {
|
||||||
/* SAM response code being sent to initiator */
|
/* SAM response code being sent to initiator */
|
||||||
@ -551,8 +551,8 @@ struct se_cmd {
|
|||||||
void (*transport_complete_callback)(struct se_cmd *);
|
void (*transport_complete_callback)(struct se_cmd *);
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
#define T_TASK(cmd) ((struct se_transport_task *)(cmd->t_task))
|
#define T_TASK(cmd) ((cmd)->t_task)
|
||||||
#define CMD_TFO(cmd) ((struct target_core_fabric_ops *)cmd->se_tfo)
|
#define CMD_TFO(cmd) ((cmd)->se_tfo)
|
||||||
|
|
||||||
struct se_tmr_req {
|
struct se_tmr_req {
|
||||||
/* Task Management function to be preformed */
|
/* Task Management function to be preformed */
|
||||||
@ -583,7 +583,7 @@ struct se_ua {
|
|||||||
struct se_node_acl {
|
struct se_node_acl {
|
||||||
char initiatorname[TRANSPORT_IQN_LEN];
|
char initiatorname[TRANSPORT_IQN_LEN];
|
||||||
/* Used to signal demo mode created ACL, disabled by default */
|
/* Used to signal demo mode created ACL, disabled by default */
|
||||||
int dynamic_node_acl:1;
|
bool dynamic_node_acl;
|
||||||
u32 queue_depth;
|
u32 queue_depth;
|
||||||
u32 acl_index;
|
u32 acl_index;
|
||||||
u64 num_cmds;
|
u64 num_cmds;
|
||||||
@ -601,7 +601,8 @@ struct se_node_acl {
|
|||||||
struct config_group acl_attrib_group;
|
struct config_group acl_attrib_group;
|
||||||
struct config_group acl_auth_group;
|
struct config_group acl_auth_group;
|
||||||
struct config_group acl_param_group;
|
struct config_group acl_param_group;
|
||||||
struct config_group *acl_default_groups[4];
|
struct config_group acl_fabric_stat_group;
|
||||||
|
struct config_group *acl_default_groups[5];
|
||||||
struct list_head acl_list;
|
struct list_head acl_list;
|
||||||
struct list_head acl_sess_list;
|
struct list_head acl_sess_list;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
@ -615,13 +616,19 @@ struct se_session {
|
|||||||
struct list_head sess_acl_list;
|
struct list_head sess_acl_list;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
#define SE_SESS(cmd) ((struct se_session *)(cmd)->se_sess)
|
#define SE_SESS(cmd) ((cmd)->se_sess)
|
||||||
#define SE_NODE_ACL(sess) ((struct se_node_acl *)(sess)->se_node_acl)
|
#define SE_NODE_ACL(sess) ((sess)->se_node_acl)
|
||||||
|
|
||||||
struct se_device;
|
struct se_device;
|
||||||
struct se_transform_info;
|
struct se_transform_info;
|
||||||
struct scatterlist;
|
struct scatterlist;
|
||||||
|
|
||||||
|
struct se_ml_stat_grps {
|
||||||
|
struct config_group stat_group;
|
||||||
|
struct config_group scsi_auth_intr_group;
|
||||||
|
struct config_group scsi_att_intr_port_group;
|
||||||
|
};
|
||||||
|
|
||||||
struct se_lun_acl {
|
struct se_lun_acl {
|
||||||
char initiatorname[TRANSPORT_IQN_LEN];
|
char initiatorname[TRANSPORT_IQN_LEN];
|
||||||
u32 mapped_lun;
|
u32 mapped_lun;
|
||||||
@ -629,10 +636,13 @@ struct se_lun_acl {
|
|||||||
struct se_lun *se_lun;
|
struct se_lun *se_lun;
|
||||||
struct list_head lacl_list;
|
struct list_head lacl_list;
|
||||||
struct config_group se_lun_group;
|
struct config_group se_lun_group;
|
||||||
|
struct se_ml_stat_grps ml_stat_grps;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
|
#define ML_STAT_GRPS(lacl) (&(lacl)->ml_stat_grps)
|
||||||
|
|
||||||
struct se_dev_entry {
|
struct se_dev_entry {
|
||||||
int def_pr_registered:1;
|
bool def_pr_registered;
|
||||||
/* See transport_lunflags_table */
|
/* See transport_lunflags_table */
|
||||||
u32 lun_flags;
|
u32 lun_flags;
|
||||||
u32 deve_cmds;
|
u32 deve_cmds;
|
||||||
@ -693,6 +703,13 @@ struct se_dev_attrib {
|
|||||||
struct config_group da_group;
|
struct config_group da_group;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
|
struct se_dev_stat_grps {
|
||||||
|
struct config_group stat_group;
|
||||||
|
struct config_group scsi_dev_group;
|
||||||
|
struct config_group scsi_tgt_dev_group;
|
||||||
|
struct config_group scsi_lu_group;
|
||||||
|
};
|
||||||
|
|
||||||
struct se_subsystem_dev {
|
struct se_subsystem_dev {
|
||||||
/* Used for struct se_subsystem_dev-->se_dev_alias, must be less than PAGE_SIZE */
|
/* Used for struct se_subsystem_dev-->se_dev_alias, must be less than PAGE_SIZE */
|
||||||
#define SE_DEV_ALIAS_LEN 512
|
#define SE_DEV_ALIAS_LEN 512
|
||||||
@ -716,11 +733,14 @@ struct se_subsystem_dev {
|
|||||||
struct config_group se_dev_group;
|
struct config_group se_dev_group;
|
||||||
/* For T10 Reservations */
|
/* For T10 Reservations */
|
||||||
struct config_group se_dev_pr_group;
|
struct config_group se_dev_pr_group;
|
||||||
|
/* For target_core_stat.c groups */
|
||||||
|
struct se_dev_stat_grps dev_stat_grps;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
#define T10_ALUA(su_dev) (&(su_dev)->t10_alua)
|
#define T10_ALUA(su_dev) (&(su_dev)->t10_alua)
|
||||||
#define T10_RES(su_dev) (&(su_dev)->t10_reservation)
|
#define T10_RES(su_dev) (&(su_dev)->t10_reservation)
|
||||||
#define T10_PR_OPS(su_dev) (&(su_dev)->t10_reservation.pr_ops)
|
#define T10_PR_OPS(su_dev) (&(su_dev)->t10_reservation.pr_ops)
|
||||||
|
#define DEV_STAT_GRP(dev) (&(dev)->dev_stat_grps)
|
||||||
|
|
||||||
struct se_device {
|
struct se_device {
|
||||||
/* Set to 1 if thread is NOT sleeping on thread_sem */
|
/* Set to 1 if thread is NOT sleeping on thread_sem */
|
||||||
@ -803,8 +823,8 @@ struct se_device {
|
|||||||
struct list_head g_se_dev_list;
|
struct list_head g_se_dev_list;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
#define SE_DEV(cmd) ((struct se_device *)(cmd)->se_lun->lun_se_dev)
|
#define SE_DEV(cmd) ((cmd)->se_lun->lun_se_dev)
|
||||||
#define SU_DEV(dev) ((struct se_subsystem_dev *)(dev)->se_sub_dev)
|
#define SU_DEV(dev) ((dev)->se_sub_dev)
|
||||||
#define DEV_ATTRIB(dev) (&(dev)->se_sub_dev->se_dev_attrib)
|
#define DEV_ATTRIB(dev) (&(dev)->se_sub_dev->se_dev_attrib)
|
||||||
#define DEV_T10_WWN(dev) (&(dev)->se_sub_dev->t10_wwn)
|
#define DEV_T10_WWN(dev) (&(dev)->se_sub_dev->t10_wwn)
|
||||||
|
|
||||||
@ -832,7 +852,14 @@ struct se_hba {
|
|||||||
struct se_subsystem_api *transport;
|
struct se_subsystem_api *transport;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
#define SE_HBA(d) ((struct se_hba *)(d)->se_hba)
|
#define SE_HBA(dev) ((dev)->se_hba)
|
||||||
|
|
||||||
|
struct se_port_stat_grps {
|
||||||
|
struct config_group stat_group;
|
||||||
|
struct config_group scsi_port_group;
|
||||||
|
struct config_group scsi_tgt_port_group;
|
||||||
|
struct config_group scsi_transport_group;
|
||||||
|
};
|
||||||
|
|
||||||
struct se_lun {
|
struct se_lun {
|
||||||
/* See transport_lun_status_table */
|
/* See transport_lun_status_table */
|
||||||
@ -848,11 +875,13 @@ struct se_lun {
|
|||||||
struct list_head lun_cmd_list;
|
struct list_head lun_cmd_list;
|
||||||
struct list_head lun_acl_list;
|
struct list_head lun_acl_list;
|
||||||
struct se_device *lun_se_dev;
|
struct se_device *lun_se_dev;
|
||||||
|
struct se_port *lun_sep;
|
||||||
struct config_group lun_group;
|
struct config_group lun_group;
|
||||||
struct se_port *lun_sep;
|
struct se_port_stat_grps port_stat_grps;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
#define SE_LUN(c) ((struct se_lun *)(c)->se_lun)
|
#define SE_LUN(cmd) ((cmd)->se_lun)
|
||||||
|
#define PORT_STAT_GRP(lun) (&(lun)->port_stat_grps)
|
||||||
|
|
||||||
struct scsi_port_stats {
|
struct scsi_port_stats {
|
||||||
u64 cmd_pdus;
|
u64 cmd_pdus;
|
||||||
@ -919,11 +948,13 @@ struct se_portal_group {
|
|||||||
struct config_group tpg_param_group;
|
struct config_group tpg_param_group;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
#define TPG_TFO(se_tpg) ((struct target_core_fabric_ops *)(se_tpg)->se_tpg_tfo)
|
#define TPG_TFO(se_tpg) ((se_tpg)->se_tpg_tfo)
|
||||||
|
|
||||||
struct se_wwn {
|
struct se_wwn {
|
||||||
struct target_fabric_configfs *wwn_tf;
|
struct target_fabric_configfs *wwn_tf;
|
||||||
struct config_group wwn_group;
|
struct config_group wwn_group;
|
||||||
|
struct config_group *wwn_default_groups[2];
|
||||||
|
struct config_group fabric_stat_group;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
|
||||||
struct se_global {
|
struct se_global {
|
||||||
|
@ -14,10 +14,12 @@ extern void target_fabric_configfs_deregister(struct target_fabric_configfs *);
|
|||||||
struct target_fabric_configfs_template {
|
struct target_fabric_configfs_template {
|
||||||
struct config_item_type tfc_discovery_cit;
|
struct config_item_type tfc_discovery_cit;
|
||||||
struct config_item_type tfc_wwn_cit;
|
struct config_item_type tfc_wwn_cit;
|
||||||
|
struct config_item_type tfc_wwn_fabric_stats_cit;
|
||||||
struct config_item_type tfc_tpg_cit;
|
struct config_item_type tfc_tpg_cit;
|
||||||
struct config_item_type tfc_tpg_base_cit;
|
struct config_item_type tfc_tpg_base_cit;
|
||||||
struct config_item_type tfc_tpg_lun_cit;
|
struct config_item_type tfc_tpg_lun_cit;
|
||||||
struct config_item_type tfc_tpg_port_cit;
|
struct config_item_type tfc_tpg_port_cit;
|
||||||
|
struct config_item_type tfc_tpg_port_stat_cit;
|
||||||
struct config_item_type tfc_tpg_np_cit;
|
struct config_item_type tfc_tpg_np_cit;
|
||||||
struct config_item_type tfc_tpg_np_base_cit;
|
struct config_item_type tfc_tpg_np_base_cit;
|
||||||
struct config_item_type tfc_tpg_attrib_cit;
|
struct config_item_type tfc_tpg_attrib_cit;
|
||||||
@ -27,7 +29,9 @@ struct target_fabric_configfs_template {
|
|||||||
struct config_item_type tfc_tpg_nacl_attrib_cit;
|
struct config_item_type tfc_tpg_nacl_attrib_cit;
|
||||||
struct config_item_type tfc_tpg_nacl_auth_cit;
|
struct config_item_type tfc_tpg_nacl_auth_cit;
|
||||||
struct config_item_type tfc_tpg_nacl_param_cit;
|
struct config_item_type tfc_tpg_nacl_param_cit;
|
||||||
|
struct config_item_type tfc_tpg_nacl_stat_cit;
|
||||||
struct config_item_type tfc_tpg_mappedlun_cit;
|
struct config_item_type tfc_tpg_mappedlun_cit;
|
||||||
|
struct config_item_type tfc_tpg_mappedlun_stat_cit;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct target_fabric_configfs {
|
struct target_fabric_configfs {
|
||||||
|
@ -8,7 +8,7 @@ struct target_core_fabric_ops {
|
|||||||
* for scatterlist chaining using transport_do_task_sg_link(),
|
* for scatterlist chaining using transport_do_task_sg_link(),
|
||||||
* disabled by default
|
* disabled by default
|
||||||
*/
|
*/
|
||||||
int task_sg_chaining:1;
|
bool task_sg_chaining;
|
||||||
char *(*get_fabric_name)(void);
|
char *(*get_fabric_name)(void);
|
||||||
u8 (*get_fabric_proto_ident)(struct se_portal_group *);
|
u8 (*get_fabric_proto_ident)(struct se_portal_group *);
|
||||||
char *(*tpg_get_wwn)(struct se_portal_group *);
|
char *(*tpg_get_wwn)(struct se_portal_group *);
|
||||||
|
@ -1,37 +1,29 @@
|
|||||||
#ifndef TARGET_CORE_TMR_H
|
#ifndef TARGET_CORE_TMR_H
|
||||||
#define TARGET_CORE_TMR_H
|
#define TARGET_CORE_TMR_H
|
||||||
|
|
||||||
/* task management function values */
|
/* fabric independent task management function values */
|
||||||
#ifdef ABORT_TASK
|
enum tcm_tmreq_table {
|
||||||
#undef ABORT_TASK
|
TMR_ABORT_TASK = 1,
|
||||||
#endif /* ABORT_TASK */
|
TMR_ABORT_TASK_SET = 2,
|
||||||
#define ABORT_TASK 1
|
TMR_CLEAR_ACA = 3,
|
||||||
#ifdef ABORT_TASK_SET
|
TMR_CLEAR_TASK_SET = 4,
|
||||||
#undef ABORT_TASK_SET
|
TMR_LUN_RESET = 5,
|
||||||
#endif /* ABORT_TASK_SET */
|
TMR_TARGET_WARM_RESET = 6,
|
||||||
#define ABORT_TASK_SET 2
|
TMR_TARGET_COLD_RESET = 7,
|
||||||
#ifdef CLEAR_ACA
|
TMR_FABRIC_TMR = 255,
|
||||||
#undef CLEAR_ACA
|
};
|
||||||
#endif /* CLEAR_ACA */
|
|
||||||
#define CLEAR_ACA 3
|
|
||||||
#ifdef CLEAR_TASK_SET
|
|
||||||
#undef CLEAR_TASK_SET
|
|
||||||
#endif /* CLEAR_TASK_SET */
|
|
||||||
#define CLEAR_TASK_SET 4
|
|
||||||
#define LUN_RESET 5
|
|
||||||
#define TARGET_WARM_RESET 6
|
|
||||||
#define TARGET_COLD_RESET 7
|
|
||||||
#define TASK_REASSIGN 8
|
|
||||||
|
|
||||||
/* task management response values */
|
/* fabric independent task management response values */
|
||||||
#define TMR_FUNCTION_COMPLETE 0
|
enum tcm_tmrsp_table {
|
||||||
#define TMR_TASK_DOES_NOT_EXIST 1
|
TMR_FUNCTION_COMPLETE = 0,
|
||||||
#define TMR_LUN_DOES_NOT_EXIST 2
|
TMR_TASK_DOES_NOT_EXIST = 1,
|
||||||
#define TMR_TASK_STILL_ALLEGIANT 3
|
TMR_LUN_DOES_NOT_EXIST = 2,
|
||||||
#define TMR_TASK_FAILOVER_NOT_SUPPORTED 4
|
TMR_TASK_STILL_ALLEGIANT = 3,
|
||||||
#define TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED 5
|
TMR_TASK_FAILOVER_NOT_SUPPORTED = 4,
|
||||||
#define TMR_FUNCTION_AUTHORIZATION_FAILED 6
|
TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED = 5,
|
||||||
#define TMR_FUNCTION_REJECTED 255
|
TMR_FUNCTION_AUTHORIZATION_FAILED = 6,
|
||||||
|
TMR_FUNCTION_REJECTED = 255,
|
||||||
|
};
|
||||||
|
|
||||||
extern struct kmem_cache *se_tmr_req_cache;
|
extern struct kmem_cache *se_tmr_req_cache;
|
||||||
|
|
||||||
|
@ -109,6 +109,8 @@
|
|||||||
struct se_mem;
|
struct se_mem;
|
||||||
struct se_subsystem_api;
|
struct se_subsystem_api;
|
||||||
|
|
||||||
|
extern struct kmem_cache *se_mem_cache;
|
||||||
|
|
||||||
extern int init_se_global(void);
|
extern int init_se_global(void);
|
||||||
extern void release_se_global(void);
|
extern void release_se_global(void);
|
||||||
extern void init_scsi_index_table(void);
|
extern void init_scsi_index_table(void);
|
||||||
@ -190,6 +192,8 @@ extern void transport_generic_process_write(struct se_cmd *);
|
|||||||
extern int transport_generic_do_tmr(struct se_cmd *);
|
extern int transport_generic_do_tmr(struct se_cmd *);
|
||||||
/* From target_core_alua.c */
|
/* From target_core_alua.c */
|
||||||
extern int core_alua_check_nonop_delay(struct se_cmd *);
|
extern int core_alua_check_nonop_delay(struct se_cmd *);
|
||||||
|
/* From target_core_cdb.c */
|
||||||
|
extern int transport_emulate_control_cdb(struct se_task *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each se_transport_task_t can have N number of possible struct se_task's
|
* Each se_transport_task_t can have N number of possible struct se_task's
|
||||||
|
Loading…
x
Reference in New Issue
Block a user