mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-30 16:13:54 +08:00
[SCSI] qla2xxx: Add LLD target-mode infrastructure for >= 24xx series
Add LLD target mode for >= 24xx series HW. This code was originally based on external qla2x00t module based on 8.02.01-k4, and has been refactored to push the bulk of code into mainline qla2xxx.ko LLD -> qla_target.c. The implementation uses internal workqueues for I/O context submission into tcm_qla2xxx code, and includes the struct qla_tgt_func_tmpl API for external interaction to allow qla2xxx LDD to function without direct target-core dependencies: It also enables qla_target.c usage within existing qla2xxx LLD code. This includes: *) Addition of target mode specific members to existing data structures in qla_def.h and struct qla_hw_data->tgt_ops using qla_target.h:struct qla_tgt_func_tmpl *) Addition of struct qla_tgt_func_tmpl and direct calls into qla_target.c logic w/ qlt_* prefixed functions. *) Addition of qla_iocb.c:qla2x00_req_pkt() for ring processing, and qla2x00_issue_marker() for handling request/response queue processing for target mode operation *) Addition of various qla_tgt_mode_enabled() logic checks in qla24xx_nvram_config(), qla2x00_initialize_adapter(), qla2x00_rff_id(), qla2x00_abort_isp(), qla24xx_modify_vp_config(), and qla2x00_vp_abort_isp(). By default the new qlini_mode module parameter is setting initiator-mode to 'enabled' in order for 'modprobe qla2xxx' to continue to function as expected in initiator only mode. Enabling target-mode operation will currently require a: modprobe qla2xxx qlini_mode="disabled" in order to explictly disabled initiator mode and allow target-mode to be enabled via tcm_qla2xxx configfs fabric callers. (nab: Convert to qlini_mode='enabled' by default in qla_target.c) (joern: Remove loop_id from qla_tgt_make_local_sess() arguments + Remove unused s_id + fix s_id endianness bug + simplify qla_tgt_abort_work) (gerard: fix section __exit mismatch in qla_tgt_exit) (arun: Capture ATIO queue during firmware dump + Send SCR in target mode + Target mode review comments) (roland: Don't create duplicate target sessions to address tearing down ACLs with IO in flight + Add missing call to qlt_fc_port_deleted call during qla2x00_schedule_rport_del timeout) Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org> Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
2c1391d395
commit
2d70c103fd
@ -1,5 +1,5 @@
|
||||
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
|
||||
qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \
|
||||
qla_nx.o
|
||||
qla_nx.o qla_target.o
|
||||
|
||||
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
|
||||
|
@ -5,6 +5,7 @@
|
||||
* See LICENSE.qla2xxx for copyright and licensing details.
|
||||
*/
|
||||
#include "qla_def.h"
|
||||
#include "qla_target.h"
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/vmalloc.h>
|
||||
@ -1737,6 +1738,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
|
||||
fc_host_supported_speeds(vha->host) =
|
||||
fc_host_supported_speeds(base_vha->host);
|
||||
|
||||
qlt_vport_create(vha, ha);
|
||||
qla24xx_vport_disable(fc_vport, disable);
|
||||
|
||||
if (ha->flags.cpu_affinity_enabled) {
|
||||
@ -1951,7 +1953,8 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
|
||||
fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
|
||||
fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
|
||||
fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
|
||||
fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
|
||||
fc_host_supported_classes(vha->host) = ha->tgt.enable_class_2 ?
|
||||
(FC_COS_CLASS2|FC_COS_CLASS3) : FC_COS_CLASS3;
|
||||
fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports;
|
||||
fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count;
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
* ----------------------------------------------------------------------
|
||||
* | Level | Last Value Used | Holes |
|
||||
* ----------------------------------------------------------------------
|
||||
* | Module Init and Probe | 0x0120 | 0x4b,0xba,0xfa |
|
||||
* | Mailbox commands | 0x113e | 0x111a-0x111b |
|
||||
* | Module Init and Probe | 0x0122 | 0x4b,0xba,0xfa |
|
||||
* | Mailbox commands | 0x1140 | 0x111a-0x111b |
|
||||
* | | | 0x112c-0x112e |
|
||||
* | | | 0x113a |
|
||||
* | Device Discovery | 0x2086 | 0x2020-0x2022 |
|
||||
@ -33,6 +33,9 @@
|
||||
* | ISP82XX Specific | 0xb054 | 0xb024 |
|
||||
* | MultiQ | 0xc00c | |
|
||||
* | Misc | 0xd010 | |
|
||||
* | Target Mode | 0xe06f | |
|
||||
* | Target Mode Management | 0xf071 | |
|
||||
* | Target Mode Task Management | 0x1000b | |
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -379,6 +382,54 @@ qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
|
||||
return (char *)iter_reg + ntohl(fcec->size);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr,
|
||||
uint32_t **last_chain)
|
||||
{
|
||||
struct qla2xxx_mqueue_chain *q;
|
||||
struct qla2xxx_mqueue_header *qh;
|
||||
uint32_t num_queues;
|
||||
int que;
|
||||
struct {
|
||||
int length;
|
||||
void *ring;
|
||||
} aq, *aqp;
|
||||
|
||||
if (!ha->tgt.atio_q_length)
|
||||
return ptr;
|
||||
|
||||
num_queues = 1;
|
||||
aqp = &aq;
|
||||
aqp->length = ha->tgt.atio_q_length;
|
||||
aqp->ring = ha->tgt.atio_ring;
|
||||
|
||||
for (que = 0; que < num_queues; que++) {
|
||||
/* aqp = ha->atio_q_map[que]; */
|
||||
q = ptr;
|
||||
*last_chain = &q->type;
|
||||
q->type = __constant_htonl(DUMP_CHAIN_QUEUE);
|
||||
q->chain_size = htonl(
|
||||
sizeof(struct qla2xxx_mqueue_chain) +
|
||||
sizeof(struct qla2xxx_mqueue_header) +
|
||||
(aqp->length * sizeof(request_t)));
|
||||
ptr += sizeof(struct qla2xxx_mqueue_chain);
|
||||
|
||||
/* Add header. */
|
||||
qh = ptr;
|
||||
qh->queue = __constant_htonl(TYPE_ATIO_QUEUE);
|
||||
qh->number = htonl(que);
|
||||
qh->size = htonl(aqp->length * sizeof(request_t));
|
||||
ptr += sizeof(struct qla2xxx_mqueue_header);
|
||||
|
||||
/* Add data. */
|
||||
memcpy(ptr, aqp->ring, aqp->length * sizeof(request_t));
|
||||
|
||||
ptr += aqp->length * sizeof(request_t);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
|
||||
{
|
||||
@ -874,6 +925,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
|
||||
struct qla24xx_fw_dump *fw;
|
||||
uint32_t ext_mem_cnt;
|
||||
void *nxt;
|
||||
void *nxt_chain;
|
||||
uint32_t *last_chain = NULL;
|
||||
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
|
||||
|
||||
if (IS_QLA82XX(ha))
|
||||
@ -1092,6 +1145,16 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
|
||||
|
||||
qla24xx_copy_eft(ha, nxt);
|
||||
|
||||
nxt_chain = (void *)ha->fw_dump + ha->chain_offset;
|
||||
nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain);
|
||||
if (last_chain) {
|
||||
ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
|
||||
*last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
|
||||
}
|
||||
|
||||
/* Adjust valid length. */
|
||||
ha->fw_dump_len = (nxt_chain - (void *)ha->fw_dump);
|
||||
|
||||
qla24xx_fw_dump_failed_0:
|
||||
qla2xxx_dump_post_process(base_vha, rval);
|
||||
|
||||
@ -1400,6 +1463,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
|
||||
/* Chain entries -- started with MQ. */
|
||||
nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
|
||||
nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
|
||||
nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain);
|
||||
if (last_chain) {
|
||||
ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
|
||||
*last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
|
||||
@ -1718,6 +1782,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
|
||||
/* Chain entries -- started with MQ. */
|
||||
nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
|
||||
nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
|
||||
nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain);
|
||||
if (last_chain) {
|
||||
ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
|
||||
*last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
|
||||
@ -2219,6 +2284,7 @@ copy_queue:
|
||||
/* Chain entries -- started with MQ. */
|
||||
nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
|
||||
nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
|
||||
nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain);
|
||||
if (last_chain) {
|
||||
ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
|
||||
*last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
|
||||
|
@ -244,6 +244,7 @@ struct qla2xxx_mqueue_header {
|
||||
uint32_t queue;
|
||||
#define TYPE_REQUEST_QUEUE 0x1
|
||||
#define TYPE_RESPONSE_QUEUE 0x2
|
||||
#define TYPE_ATIO_QUEUE 0x3
|
||||
uint32_t number;
|
||||
uint32_t size;
|
||||
};
|
||||
@ -344,3 +345,6 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
|
||||
* more verbosity is required. It might not
|
||||
* be applicable to all the levels.
|
||||
*/
|
||||
#define ql_dbg_tgt 0x00004000 /* Target mode */
|
||||
#define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */
|
||||
#define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */
|
||||
|
@ -186,6 +186,7 @@
|
||||
#define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/
|
||||
#define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/
|
||||
#define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/
|
||||
#define ATIO_ENTRY_CNT_24XX 4096 /* Number of ATIO entries. */
|
||||
|
||||
struct req_que;
|
||||
|
||||
@ -1234,11 +1235,27 @@ typedef struct {
|
||||
* ISP queue - response queue entry definition.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t data[60];
|
||||
uint8_t entry_type; /* Entry type. */
|
||||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t sys_define; /* System defined. */
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint32_t handle; /* System defined handle */
|
||||
uint8_t data[52];
|
||||
uint32_t signature;
|
||||
#define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */
|
||||
} response_t;
|
||||
|
||||
/*
|
||||
* ISP queue - ATIO queue entry definition.
|
||||
*/
|
||||
struct atio {
|
||||
uint8_t entry_type; /* Entry type. */
|
||||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t data[58];
|
||||
uint32_t signature;
|
||||
#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
|
||||
};
|
||||
|
||||
typedef union {
|
||||
uint16_t extended;
|
||||
struct {
|
||||
@ -1749,6 +1766,7 @@ static const char * const port_state_str[] = {
|
||||
#define FCF_LOGIN_NEEDED BIT_1
|
||||
#define FCF_FCP2_DEVICE BIT_2
|
||||
#define FCF_ASYNC_SENT BIT_3
|
||||
#define FCF_CONF_COMP_SUPPORTED BIT_4
|
||||
|
||||
/* No loop ID flag. */
|
||||
#define FC_NO_LOOP_ID 0x1000
|
||||
@ -2421,6 +2439,40 @@ struct qlfc_fw {
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
struct qlt_hw_data {
|
||||
/* Protected by hw lock */
|
||||
uint32_t enable_class_2:1;
|
||||
uint32_t enable_explicit_conf:1;
|
||||
uint32_t ini_mode_force_reverse:1;
|
||||
uint32_t node_name_set:1;
|
||||
|
||||
dma_addr_t atio_dma; /* Physical address. */
|
||||
struct atio *atio_ring; /* Base virtual address */
|
||||
struct atio *atio_ring_ptr; /* Current address. */
|
||||
uint16_t atio_ring_index; /* Current index. */
|
||||
uint16_t atio_q_length;
|
||||
|
||||
void *target_lport_ptr;
|
||||
struct qla_tgt_func_tmpl *tgt_ops;
|
||||
struct qla_tgt *qla_tgt;
|
||||
struct qla_tgt_cmd *cmds[MAX_OUTSTANDING_COMMANDS];
|
||||
uint16_t current_handle;
|
||||
|
||||
struct qla_tgt_vp_map *tgt_vp_map;
|
||||
struct mutex tgt_mutex;
|
||||
struct mutex tgt_host_action_mutex;
|
||||
|
||||
int saved_set;
|
||||
uint16_t saved_exchange_count;
|
||||
uint32_t saved_firmware_options_1;
|
||||
uint32_t saved_firmware_options_2;
|
||||
uint32_t saved_firmware_options_3;
|
||||
uint8_t saved_firmware_options[2];
|
||||
uint8_t saved_add_firmware_options[2];
|
||||
|
||||
uint8_t tgt_node_name[WWN_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* Qlogic host adapter specific data structure.
|
||||
*/
|
||||
@ -2463,7 +2515,8 @@ struct qla_hw_data {
|
||||
uint32_t isp82xx_reset_hdlr_active:1;
|
||||
uint32_t isp82xx_reset_owner:1;
|
||||
uint32_t isp82xx_no_md_cap:1;
|
||||
/* 28 bits */
|
||||
uint32_t host_shutting_down:1;
|
||||
/* 30 bits */
|
||||
} flags;
|
||||
|
||||
/* This spinlock is used to protect "io transactions", you must
|
||||
@ -2864,6 +2917,8 @@ struct qla_hw_data {
|
||||
dma_addr_t md_tmplt_hdr_dma;
|
||||
void *md_dump;
|
||||
uint32_t md_dump_size;
|
||||
|
||||
struct qlt_hw_data tgt;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2921,6 +2976,7 @@ typedef struct scsi_qla_host {
|
||||
#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */
|
||||
#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */
|
||||
#define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */
|
||||
#define SCR_PENDING 21 /* SCR in target mode */
|
||||
|
||||
uint32_t device_flags;
|
||||
#define SWITCH_FOUND BIT_0
|
||||
@ -2986,6 +3042,15 @@ typedef struct scsi_qla_host {
|
||||
atomic_t vref_count;
|
||||
} scsi_qla_host_t;
|
||||
|
||||
#define SET_VP_IDX 1
|
||||
#define SET_AL_PA 2
|
||||
#define RESET_VP_IDX 3
|
||||
#define RESET_AL_PA 4
|
||||
struct qla_tgt_vp_map {
|
||||
uint8_t idx;
|
||||
scsi_qla_host_t *vha;
|
||||
};
|
||||
|
||||
/*
|
||||
* Macros to help code, maintain, etc.
|
||||
*/
|
||||
|
@ -175,6 +175,7 @@ extern int qla2x00_vp_abort_isp(scsi_qla_host_t *);
|
||||
/*
|
||||
* Global Function Prototypes in qla_iocb.c source file.
|
||||
*/
|
||||
|
||||
extern uint16_t qla2x00_calc_iocbs_32(uint16_t);
|
||||
extern uint16_t qla2x00_calc_iocbs_64(uint16_t);
|
||||
extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t);
|
||||
@ -188,6 +189,8 @@ extern uint16_t qla24xx_calc_iocbs(scsi_qla_host_t *, uint16_t);
|
||||
extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t);
|
||||
extern int qla24xx_dif_start_scsi(srb_t *);
|
||||
|
||||
extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *);
|
||||
extern int qla2x00_issue_marker(scsi_qla_host_t *, int);
|
||||
|
||||
/*
|
||||
* Global Function Prototypes in qla_mbx.c source file.
|
||||
@ -238,6 +241,9 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *);
|
||||
extern int
|
||||
qla2x00_init_firmware(scsi_qla_host_t *, uint16_t);
|
||||
|
||||
extern int
|
||||
qla2x00_get_node_name_list(scsi_qla_host_t *, void **, int *);
|
||||
|
||||
extern int
|
||||
qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t);
|
||||
|
||||
@ -548,6 +554,7 @@ extern void qla2x00_sp_free(void *, void *);
|
||||
extern void qla2x00_sp_timeout(unsigned long);
|
||||
extern void qla2x00_bsg_job_done(void *, void *, int);
|
||||
extern void qla2x00_bsg_sp_free(void *, void *);
|
||||
extern void qla2x00_start_iocbs(struct scsi_qla_host *, struct req_que *);
|
||||
|
||||
/* Interrupt related */
|
||||
extern irqreturn_t qla82xx_intr_handler(int, void *);
|
||||
|
@ -5,6 +5,7 @@
|
||||
* See LICENSE.qla2xxx for copyright and licensing details.
|
||||
*/
|
||||
#include "qla_def.h"
|
||||
#include "qla_target.h"
|
||||
|
||||
static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
|
||||
static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
|
||||
@ -556,7 +557,8 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
|
||||
ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
|
||||
ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;
|
||||
|
||||
ct_req->req.rff_id.fc4_feature = BIT_1;
|
||||
qlt_rff_id(vha, ct_req);
|
||||
|
||||
ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */
|
||||
|
||||
/* Execute MS IOCB */
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <asm/prom.h>
|
||||
#endif
|
||||
|
||||
#include <target/target_core_base.h>
|
||||
#include "qla_target.h"
|
||||
|
||||
/*
|
||||
* QLogic ISP2x00 Hardware Support Function Prototypes.
|
||||
*/
|
||||
@ -518,7 +521,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
}
|
||||
rval = qla2x00_init_rings(vha);
|
||||
|
||||
if (qla_ini_mode_enabled(vha))
|
||||
rval = qla2x00_init_rings(vha);
|
||||
|
||||
ha->flags.chip_reset_done = 1;
|
||||
|
||||
if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
|
||||
@ -1233,6 +1239,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
|
||||
mq_size += ha->max_rsp_queues *
|
||||
(rsp->length * sizeof(response_t));
|
||||
}
|
||||
if (ha->tgt.atio_q_length)
|
||||
mq_size += ha->tgt.atio_q_length * sizeof(request_t);
|
||||
/* Allocate memory for Fibre Channel Event Buffer. */
|
||||
if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha))
|
||||
goto try_eft;
|
||||
@ -1696,6 +1704,12 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
|
||||
icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
|
||||
icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
|
||||
|
||||
/* Setup ATIO queue dma pointers for target mode */
|
||||
icb->atio_q_inpointer = __constant_cpu_to_le16(0);
|
||||
icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length);
|
||||
icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma));
|
||||
icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma));
|
||||
|
||||
if (ha->mqenable || IS_QLA83XX(ha)) {
|
||||
icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS);
|
||||
icb->rid = __constant_cpu_to_le16(rid);
|
||||
@ -1739,6 +1753,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
|
||||
WRT_REG_DWORD(®->isp24.rsp_q_in, 0);
|
||||
WRT_REG_DWORD(®->isp24.rsp_q_out, 0);
|
||||
}
|
||||
qlt_24xx_config_rings(vha, reg);
|
||||
|
||||
/* PCI posting */
|
||||
RD_REG_DWORD(&ioreg->hccr);
|
||||
}
|
||||
@ -1794,6 +1810,11 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
|
||||
|
||||
spin_unlock(&ha->vport_slock);
|
||||
|
||||
ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
|
||||
ha->tgt.atio_ring_index = 0;
|
||||
/* Initialize ATIO queue entries */
|
||||
qlt_init_atio_q_entries(vha);
|
||||
|
||||
ha->isp_ops->config_rings(vha);
|
||||
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
@ -2051,6 +2072,10 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
|
||||
vha->d_id.b.area = area;
|
||||
vha->d_id.b.al_pa = al_pa;
|
||||
|
||||
spin_lock(&ha->vport_slock);
|
||||
qlt_update_vp_map(vha, SET_AL_PA);
|
||||
spin_unlock(&ha->vport_slock);
|
||||
|
||||
if (!vha->flags.init_done)
|
||||
ql_log(ql_log_info, vha, 0x2010,
|
||||
"Topology - %s, Host Loop address 0x%x.\n",
|
||||
@ -2270,7 +2295,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
|
||||
if (IS_QLA23XX(ha)) {
|
||||
nv->firmware_options[0] |= BIT_2;
|
||||
nv->firmware_options[0] &= ~BIT_3;
|
||||
nv->firmware_options[0] &= ~BIT_6;
|
||||
nv->special_options[0] &= ~BIT_6;
|
||||
nv->add_firmware_options[1] |= BIT_5 | BIT_4;
|
||||
|
||||
if (IS_QLA2300(ha)) {
|
||||
@ -2467,14 +2492,21 @@ qla2x00_rport_del(void *data)
|
||||
{
|
||||
fc_port_t *fcport = data;
|
||||
struct fc_rport *rport;
|
||||
scsi_qla_host_t *vha = fcport->vha;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
|
||||
rport = fcport->drport ? fcport->drport: fcport->rport;
|
||||
fcport->drport = NULL;
|
||||
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
|
||||
if (rport)
|
||||
if (rport) {
|
||||
fc_remote_port_delete(rport);
|
||||
/*
|
||||
* Release the target mode FC NEXUS in qla_target.c code
|
||||
* if target mod is enabled.
|
||||
*/
|
||||
qlt_fc_port_deleted(vha, fcport);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2853,6 +2885,12 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
|
||||
"Unable to allocate fc remote port.\n");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Create target mode FC NEXUS in qla_target.c if target mode is
|
||||
* enabled..
|
||||
*/
|
||||
qlt_fc_port_added(vha, fcport);
|
||||
|
||||
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
|
||||
*((fc_port_t **)rport->dd_data) = fcport;
|
||||
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
|
||||
@ -3532,6 +3570,12 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
|
||||
if (mb[10] & BIT_1)
|
||||
fcport->supported_classes |= FC_COS_CLASS3;
|
||||
|
||||
if (IS_FWI2_CAPABLE(ha)) {
|
||||
if (mb[10] & BIT_7)
|
||||
fcport->flags |=
|
||||
FCF_CONF_COMP_SUPPORTED;
|
||||
}
|
||||
|
||||
rval = QLA_SUCCESS;
|
||||
break;
|
||||
} else if (mb[0] == MBS_LOOP_ID_USED) {
|
||||
@ -4003,6 +4047,7 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct req_que *req = ha->req_q_map[0];
|
||||
struct rsp_que *rsp = ha->rsp_q_map[0];
|
||||
unsigned long flags;
|
||||
|
||||
/* If firmware needs to be loaded */
|
||||
if (qla2x00_isp_firmware(vha)) {
|
||||
@ -4027,6 +4072,16 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
|
||||
qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
|
||||
|
||||
vha->flags.online = 1;
|
||||
|
||||
/*
|
||||
* Process any ATIO queue entries that came in
|
||||
* while we weren't online.
|
||||
*/
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
if (qla_tgt_mode_enabled(vha))
|
||||
qlt_24xx_process_atio_queue(vha);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
/* Wait at most MAX_TARGET RSCNs for a stable link. */
|
||||
wait_time = 256;
|
||||
do {
|
||||
@ -4267,6 +4322,15 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
if (!qla_ini_mode_enabled(vha)) {
|
||||
/* Don't enable full login after initial LIP */
|
||||
nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13);
|
||||
/* Don't enable LIP full login for initiator */
|
||||
nv->host_p &= __constant_cpu_to_le32(~BIT_10);
|
||||
}
|
||||
|
||||
qlt_24xx_config_nvram_stage1(vha, nv);
|
||||
|
||||
/* Reset Initialization control block */
|
||||
memset(icb, 0, ha->init_cb_size);
|
||||
|
||||
@ -4294,8 +4358,10 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
|
||||
qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
|
||||
"QLA2462");
|
||||
|
||||
/* Use alternate WWN? */
|
||||
qlt_24xx_config_nvram_stage2(vha, icb);
|
||||
|
||||
if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
|
||||
/* Use alternate WWN? */
|
||||
memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
|
||||
memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
* See LICENSE.qla2xxx for copyright and licensing details.
|
||||
*/
|
||||
#include "qla_def.h"
|
||||
#include "qla_target.h"
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/delay.h>
|
||||
@ -470,7 +471,7 @@ queuing_error:
|
||||
/**
|
||||
* qla2x00_start_iocbs() - Execute the IOCB command
|
||||
*/
|
||||
static void
|
||||
void
|
||||
qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
@ -571,6 +572,29 @@ qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* qla2x00_issue_marker
|
||||
*
|
||||
* Issue marker
|
||||
* Caller CAN have hardware lock held as specified by ha_locked parameter.
|
||||
* Might release it, then reaquire.
|
||||
*/
|
||||
int qla2x00_issue_marker(scsi_qla_host_t *vha, int ha_locked)
|
||||
{
|
||||
if (ha_locked) {
|
||||
if (__qla2x00_marker(vha, vha->req, vha->req->rsp, 0, 0,
|
||||
MK_SYNC_ALL) != QLA_SUCCESS)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
} else {
|
||||
if (qla2x00_marker(vha, vha->req, vha->req->rsp, 0, 0,
|
||||
MK_SYNC_ALL) != QLA_SUCCESS)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
vha->marker_needed = 0;
|
||||
|
||||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* qla24xx_calc_iocbs() - Determine number of Command Type 3 and
|
||||
* Continuation Type 1 IOCBs to allocate.
|
||||
|
@ -5,6 +5,7 @@
|
||||
* See LICENSE.qla2xxx for copyright and licensing details.
|
||||
*/
|
||||
#include "qla_def.h"
|
||||
#include "qla_target.h"
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
@ -473,8 +474,8 @@ skip_rio:
|
||||
case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
|
||||
ql_dbg(ql_dbg_async, vha, 0x5008,
|
||||
"Asynchronous WAKEUP_THRES.\n");
|
||||
break;
|
||||
|
||||
break;
|
||||
case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
|
||||
ql_dbg(ql_dbg_async, vha, 0x5009,
|
||||
"LIP occurred (%x).\n", mb[1]);
|
||||
@ -685,6 +686,8 @@ skip_rio:
|
||||
ql_dbg(ql_dbg_async, vha, 0x5011,
|
||||
"Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
|
||||
mb[1], mb[2], mb[3]);
|
||||
|
||||
qlt_async_event(mb[0], vha, mb);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -702,8 +705,13 @@ skip_rio:
|
||||
|
||||
qla2x00_mark_all_devices_lost(vha, 1);
|
||||
|
||||
if (vha->vp_idx == 0 && !qla_ini_mode_enabled(vha))
|
||||
set_bit(SCR_PENDING, &vha->dpc_flags);
|
||||
|
||||
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
|
||||
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
|
||||
|
||||
qlt_async_event(mb[0], vha, mb);
|
||||
break;
|
||||
|
||||
case MBA_RSCN_UPDATE: /* State Change Registration */
|
||||
@ -825,6 +833,8 @@ skip_rio:
|
||||
mb[0], mb[1], mb[2], mb[3]);
|
||||
}
|
||||
|
||||
qlt_async_event(mb[0], vha, mb);
|
||||
|
||||
if (!vha->vp_idx && ha->num_vhosts)
|
||||
qla2x00_alert_all_vps(rsp, mb);
|
||||
}
|
||||
@ -1190,6 +1200,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||
} else if (iop[0] & BIT_5)
|
||||
fcport->port_type = FCT_INITIATOR;
|
||||
|
||||
if (iop[0] & BIT_7)
|
||||
fcport->flags |= FCF_CONF_COMP_SUPPORTED;
|
||||
|
||||
if (logio->io_parameter[7] || logio->io_parameter[8])
|
||||
fcport->supported_classes |= FC_COS_CLASS2;
|
||||
if (logio->io_parameter[9] || logio->io_parameter[10])
|
||||
@ -2004,6 +2017,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||
|
||||
if (pkt->entry_status != 0) {
|
||||
qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt);
|
||||
|
||||
(void)qlt_24xx_process_response_error(vha, pkt);
|
||||
|
||||
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
|
||||
wmb();
|
||||
continue;
|
||||
@ -2034,6 +2050,14 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||
case ELS_IOCB_TYPE:
|
||||
qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
|
||||
break;
|
||||
case ABTS_RECV_24XX:
|
||||
/* ensure that the ATIO queue is empty */
|
||||
qlt_24xx_process_atio_queue(vha);
|
||||
case ABTS_RESP_24XX:
|
||||
case CTIO_TYPE7:
|
||||
case NOTIFY_ACK_TYPE:
|
||||
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
|
||||
break;
|
||||
case MARKER_TYPE:
|
||||
/* Do nothing in this case, this check is to prevent it
|
||||
* from falling into default case
|
||||
@ -2186,6 +2210,13 @@ qla24xx_intr_handler(int irq, void *dev_id)
|
||||
case 0x14:
|
||||
qla24xx_process_response_queue(vha, rsp);
|
||||
break;
|
||||
case 0x1C: /* ATIO queue updated */
|
||||
qlt_24xx_process_atio_queue(vha);
|
||||
break;
|
||||
case 0x1D: /* ATIO and response queues updated */
|
||||
qlt_24xx_process_atio_queue(vha);
|
||||
qla24xx_process_response_queue(vha, rsp);
|
||||
break;
|
||||
default:
|
||||
ql_dbg(ql_dbg_async, vha, 0x504f,
|
||||
"Unrecognized interrupt type (%d).\n", stat * 0xff);
|
||||
@ -2330,6 +2361,13 @@ qla24xx_msix_default(int irq, void *dev_id)
|
||||
case 0x14:
|
||||
qla24xx_process_response_queue(vha, rsp);
|
||||
break;
|
||||
case 0x1C: /* ATIO queue updated */
|
||||
qlt_24xx_process_atio_queue(vha);
|
||||
break;
|
||||
case 0x1D: /* ATIO and response queues updated */
|
||||
qlt_24xx_process_atio_queue(vha);
|
||||
qla24xx_process_response_queue(vha, rsp);
|
||||
break;
|
||||
default:
|
||||
ql_dbg(ql_dbg_async, vha, 0x5051,
|
||||
"Unrecognized interrupt type (%d).\n", stat & 0xff);
|
||||
|
@ -5,6 +5,7 @@
|
||||
* See LICENSE.qla2xxx for copyright and licensing details.
|
||||
*/
|
||||
#include "qla_def.h"
|
||||
#include "qla_target.h"
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gfp.h>
|
||||
@ -1244,6 +1245,96 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* qla2x00_get_node_name_list
|
||||
* Issue get node name list mailbox command, kmalloc()
|
||||
* and return the resulting list. Caller must kfree() it!
|
||||
*
|
||||
* Input:
|
||||
* ha = adapter state pointer.
|
||||
* out_data = resulting list
|
||||
* out_len = length of the resulting list
|
||||
*
|
||||
* Returns:
|
||||
* qla2x00 local function return status code.
|
||||
*
|
||||
* Context:
|
||||
* Kernel context.
|
||||
*/
|
||||
int
|
||||
qla2x00_get_node_name_list(scsi_qla_host_t *vha, void **out_data, int *out_len)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct qla_port_24xx_data *list = NULL;
|
||||
void *pmap;
|
||||
mbx_cmd_t mc;
|
||||
dma_addr_t pmap_dma;
|
||||
ulong dma_size;
|
||||
int rval, left;
|
||||
|
||||
left = 1;
|
||||
while (left > 0) {
|
||||
dma_size = left * sizeof(*list);
|
||||
pmap = dma_alloc_coherent(&ha->pdev->dev, dma_size,
|
||||
&pmap_dma, GFP_KERNEL);
|
||||
if (!pmap) {
|
||||
ql_log(ql_log_warn, vha, 0x113f,
|
||||
"%s(%ld): DMA Alloc failed of %ld\n",
|
||||
__func__, vha->host_no, dma_size);
|
||||
rval = QLA_MEMORY_ALLOC_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mc.mb[0] = MBC_PORT_NODE_NAME_LIST;
|
||||
mc.mb[1] = BIT_1 | BIT_3;
|
||||
mc.mb[2] = MSW(pmap_dma);
|
||||
mc.mb[3] = LSW(pmap_dma);
|
||||
mc.mb[6] = MSW(MSD(pmap_dma));
|
||||
mc.mb[7] = LSW(MSD(pmap_dma));
|
||||
mc.mb[8] = dma_size;
|
||||
mc.out_mb = MBX_0|MBX_1|MBX_2|MBX_3|MBX_6|MBX_7|MBX_8;
|
||||
mc.in_mb = MBX_0|MBX_1;
|
||||
mc.tov = 30;
|
||||
mc.flags = MBX_DMA_IN;
|
||||
|
||||
rval = qla2x00_mailbox_command(vha, &mc);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
if ((mc.mb[0] == MBS_COMMAND_ERROR) &&
|
||||
(mc.mb[1] == 0xA)) {
|
||||
left += le16_to_cpu(mc.mb[2]) /
|
||||
sizeof(struct qla_port_24xx_data);
|
||||
goto restart;
|
||||
}
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
left = 0;
|
||||
|
||||
list = kzalloc(dma_size, GFP_KERNEL);
|
||||
if (!list) {
|
||||
ql_log(ql_log_warn, vha, 0x1140,
|
||||
"%s(%ld): failed to allocate node names list "
|
||||
"structure.\n", __func__, vha->host_no);
|
||||
rval = QLA_MEMORY_ALLOC_FAILED;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
memcpy(list, pmap, dma_size);
|
||||
restart:
|
||||
dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
|
||||
}
|
||||
|
||||
*out_data = list;
|
||||
*out_len = dma_size;
|
||||
|
||||
out:
|
||||
return rval;
|
||||
|
||||
out_free:
|
||||
dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* qla2x00_get_port_database
|
||||
* Issue normal/enhanced get port database mailbox command
|
||||
@ -1352,6 +1443,13 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
|
||||
fcport->port_type = FCT_INITIATOR;
|
||||
else
|
||||
fcport->port_type = FCT_TARGET;
|
||||
|
||||
/* Passback COS information. */
|
||||
fcport->supported_classes = (pd24->flags & PDF_CLASS_2) ?
|
||||
FC_COS_CLASS2 : FC_COS_CLASS3;
|
||||
|
||||
if (pd24->prli_svc_param_word_3[0] & BIT_7)
|
||||
fcport->flags |= FCF_CONF_COMP_SUPPORTED;
|
||||
} else {
|
||||
uint64_t zero = 0;
|
||||
|
||||
@ -1770,6 +1868,10 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
|
||||
mb[10] |= BIT_0; /* Class 2. */
|
||||
if (lg->io_parameter[9] || lg->io_parameter[10])
|
||||
mb[10] |= BIT_1; /* Class 3. */
|
||||
if (lg->io_parameter[0] & __constant_cpu_to_le32(BIT_7))
|
||||
mb[10] |= BIT_7; /* Confirmed Completion
|
||||
* Allowed
|
||||
*/
|
||||
}
|
||||
|
||||
dma_pool_free(ha->s_dma_pool, lg, lg_dma);
|
||||
@ -3096,6 +3198,9 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha)
|
||||
vpmod->vp_count = 1;
|
||||
vpmod->vp_index1 = vha->vp_idx;
|
||||
vpmod->options_idx1 = BIT_3|BIT_4|BIT_5;
|
||||
|
||||
qlt_modify_vp_config(vha, vpmod);
|
||||
|
||||
memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE);
|
||||
memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE);
|
||||
vpmod->entry_count = 1;
|
||||
@ -3235,13 +3340,6 @@ qla2x00_send_change_request(scsi_qla_host_t *vha, uint16_t format,
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c7,
|
||||
"Entered %s.\n", __func__);
|
||||
|
||||
/*
|
||||
* This command is implicitly executed by firmware during login for the
|
||||
* physical hosts
|
||||
*/
|
||||
if (vp_idx == 0)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
|
||||
mcp->mb[1] = format;
|
||||
mcp->mb[9] = vp_idx;
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
#include "qla_def.h"
|
||||
#include "qla_gbl.h"
|
||||
#include "qla_target.h"
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/vmalloc.h>
|
||||
@ -49,6 +50,9 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
|
||||
|
||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||
list_add_tail(&vha->list, &ha->vp_list);
|
||||
|
||||
qlt_update_vp_map(vha, SET_VP_IDX);
|
||||
|
||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||
|
||||
mutex_unlock(&ha->vport_lock);
|
||||
@ -79,6 +83,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
|
||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||
}
|
||||
list_del(&vha->list);
|
||||
qlt_update_vp_map(vha, RESET_VP_IDX);
|
||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||
|
||||
vp_id = vha->vp_idx;
|
||||
@ -150,6 +155,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
|
||||
atomic_set(&vha->loop_state, LOOP_DOWN);
|
||||
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
|
||||
|
||||
/* Remove port id from vp target map */
|
||||
qlt_update_vp_map(vha, RESET_AL_PA);
|
||||
|
||||
qla2x00_mark_vp_devices_dead(vha);
|
||||
atomic_set(&vha->vp_state, VP_FAILED);
|
||||
vha->flags.management_server_logged_in = 0;
|
||||
|
@ -13,12 +13,13 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsicam.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "qla_target.h"
|
||||
|
||||
/*
|
||||
* Driver version
|
||||
*/
|
||||
@ -40,6 +41,12 @@ static struct kmem_cache *ctx_cachep;
|
||||
*/
|
||||
int ql_errlev = ql_log_all;
|
||||
|
||||
int ql2xenableclass2;
|
||||
module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR);
|
||||
MODULE_PARM_DESC(ql2xenableclass2,
|
||||
"Specify if Class 2 operations are supported from the very "
|
||||
"beginning. Default is 0 - class 2 not supported.");
|
||||
|
||||
int ql2xlogintimeout = 20;
|
||||
module_param(ql2xlogintimeout, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(ql2xlogintimeout,
|
||||
@ -255,6 +262,8 @@ struct scsi_host_template qla2xxx_driver_template = {
|
||||
|
||||
.max_sectors = 0xFFFF,
|
||||
.shost_attrs = qla2x00_host_attrs,
|
||||
|
||||
.supported_mode = MODE_INITIATOR,
|
||||
};
|
||||
|
||||
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
|
||||
@ -2187,6 +2196,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
ql_dbg_pci(ql_dbg_init, pdev, 0x000a,
|
||||
"Memory allocated for ha=%p.\n", ha);
|
||||
ha->pdev = pdev;
|
||||
ha->tgt.enable_class_2 = ql2xenableclass2;
|
||||
|
||||
/* Clear our data area */
|
||||
ha->bars = bars;
|
||||
@ -2250,6 +2260,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
ha->mbx_count = MAILBOX_REGISTER_COUNT;
|
||||
req_length = REQUEST_ENTRY_CNT_24XX;
|
||||
rsp_length = RESPONSE_ENTRY_CNT_2300;
|
||||
ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
|
||||
ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
|
||||
ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
|
||||
ha->gid_list_info_size = 8;
|
||||
@ -2265,6 +2276,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
ha->mbx_count = MAILBOX_REGISTER_COUNT;
|
||||
req_length = REQUEST_ENTRY_CNT_24XX;
|
||||
rsp_length = RESPONSE_ENTRY_CNT_2300;
|
||||
ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
|
||||
ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
|
||||
ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
|
||||
ha->gid_list_info_size = 8;
|
||||
@ -2433,6 +2445,7 @@ que_init:
|
||||
goto probe_init_failed;
|
||||
}
|
||||
|
||||
qlt_probe_one_stage1(base_vha, ha);
|
||||
|
||||
/* Set up the irqs */
|
||||
ret = qla2x00_request_irqs(ha, rsp);
|
||||
@ -2521,6 +2534,14 @@ que_init:
|
||||
ql_dbg(ql_dbg_init, base_vha, 0x00ee,
|
||||
"DPC thread started successfully.\n");
|
||||
|
||||
/*
|
||||
* If we're not coming up in initiator mode, we might sit for
|
||||
* a while without waking up the dpc thread, which leads to a
|
||||
* stuck process warning. So just kick the dpc once here and
|
||||
* let the kthread start (and go back to sleep in qla2x00_do_dpc).
|
||||
*/
|
||||
qla2xxx_wake_dpc(base_vha);
|
||||
|
||||
skip_dpc:
|
||||
list_add_tail(&base_vha->list, &ha->vp_list);
|
||||
base_vha->host->irq = ha->pdev->irq;
|
||||
@ -2566,7 +2587,11 @@ skip_dpc:
|
||||
ql_dbg(ql_dbg_init, base_vha, 0x00f2,
|
||||
"Init done and hba is online.\n");
|
||||
|
||||
scsi_scan_host(host);
|
||||
if (qla_ini_mode_enabled(base_vha))
|
||||
scsi_scan_host(host);
|
||||
else
|
||||
ql_dbg(ql_dbg_init, base_vha, 0x0122,
|
||||
"skipping scsi_scan_host() for non-initiator port\n");
|
||||
|
||||
qla2x00_alloc_sysfs_attr(base_vha);
|
||||
|
||||
@ -2584,6 +2609,8 @@ skip_dpc:
|
||||
base_vha->host_no,
|
||||
ha->isp_ops->fw_version_str(base_vha, fw_str));
|
||||
|
||||
qlt_add_target(ha, base_vha);
|
||||
|
||||
return 0;
|
||||
|
||||
probe_init_failed:
|
||||
@ -2631,6 +2658,22 @@ probe_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_stop_dpc_thread(scsi_qla_host_t *vha)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct task_struct *t = ha->dpc_thread;
|
||||
|
||||
if (ha->dpc_thread == NULL)
|
||||
return;
|
||||
/*
|
||||
* qla2xxx_wake_dpc checks for ->dpc_thread
|
||||
* so we need to zero it out.
|
||||
*/
|
||||
ha->dpc_thread = NULL;
|
||||
kthread_stop(t);
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
@ -2684,6 +2727,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
||||
base_vha = pci_get_drvdata(pdev);
|
||||
ha = base_vha->hw;
|
||||
|
||||
ha->flags.host_shutting_down = 1;
|
||||
|
||||
mutex_lock(&ha->vport_lock);
|
||||
while (ha->cur_vport_count) {
|
||||
struct Scsi_Host *scsi_host;
|
||||
@ -2737,6 +2782,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
||||
ha->dpc_thread = NULL;
|
||||
kthread_stop(t);
|
||||
}
|
||||
qlt_remove_target(ha, base_vha);
|
||||
|
||||
qla2x00_free_sysfs_attr(base_vha);
|
||||
|
||||
@ -2788,17 +2834,7 @@ qla2x00_free_device(scsi_qla_host_t *vha)
|
||||
if (vha->timer_active)
|
||||
qla2x00_stop_timer(vha);
|
||||
|
||||
/* Kill the kernel thread for this host */
|
||||
if (ha->dpc_thread) {
|
||||
struct task_struct *t = ha->dpc_thread;
|
||||
|
||||
/*
|
||||
* qla2xxx_wake_dpc checks for ->dpc_thread
|
||||
* so we need to zero it out.
|
||||
*/
|
||||
ha->dpc_thread = NULL;
|
||||
kthread_stop(t);
|
||||
}
|
||||
qla2x00_stop_dpc_thread(vha);
|
||||
|
||||
qla25xx_delete_queues(vha);
|
||||
|
||||
@ -2860,8 +2896,10 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
|
||||
spin_unlock_irqrestore(vha->host->host_lock, flags);
|
||||
set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(base_vha);
|
||||
} else
|
||||
} else {
|
||||
fc_remote_port_delete(rport);
|
||||
qlt_fc_port_deleted(vha, fcport);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2964,10 +3002,13 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
|
||||
if (!ha->init_cb)
|
||||
goto fail;
|
||||
|
||||
if (qlt_mem_alloc(ha) < 0)
|
||||
goto fail_free_init_cb;
|
||||
|
||||
ha->gid_list = dma_alloc_coherent(&ha->pdev->dev,
|
||||
qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL);
|
||||
if (!ha->gid_list)
|
||||
goto fail_free_init_cb;
|
||||
goto fail_free_tgt_mem;
|
||||
|
||||
ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
|
||||
if (!ha->srb_mempool)
|
||||
@ -3185,6 +3226,8 @@ fail_free_gid_list:
|
||||
ha->gid_list_dma);
|
||||
ha->gid_list = NULL;
|
||||
ha->gid_list_dma = 0;
|
||||
fail_free_tgt_mem:
|
||||
qlt_mem_free(ha);
|
||||
fail_free_init_cb:
|
||||
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb,
|
||||
ha->init_cb_dma);
|
||||
@ -3300,6 +3343,8 @@ qla2x00_mem_free(struct qla_hw_data *ha)
|
||||
if (ha->ctx_mempool)
|
||||
mempool_destroy(ha->ctx_mempool);
|
||||
|
||||
qlt_mem_free(ha);
|
||||
|
||||
if (ha->init_cb)
|
||||
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
|
||||
ha->init_cb, ha->init_cb_dma);
|
||||
@ -3329,6 +3374,10 @@ qla2x00_mem_free(struct qla_hw_data *ha)
|
||||
|
||||
ha->gid_list = NULL;
|
||||
ha->gid_list_dma = 0;
|
||||
|
||||
ha->tgt.atio_ring = NULL;
|
||||
ha->tgt.atio_dma = 0;
|
||||
ha->tgt.tgt_vp_map = NULL;
|
||||
}
|
||||
|
||||
struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
|
||||
@ -3757,6 +3806,16 @@ qla2x00_do_dpc(void *data)
|
||||
clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
|
||||
}
|
||||
|
||||
if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) {
|
||||
int ret;
|
||||
ret = qla2x00_send_change_request(base_vha, 0x3, 0);
|
||||
if (ret != QLA_SUCCESS)
|
||||
ql_log(ql_log_warn, base_vha, 0x121,
|
||||
"Failed to enable receiving of RSCN "
|
||||
"requests: 0x%x.\n", ret);
|
||||
clear_bit(SCR_PENDING, &base_vha->dpc_flags);
|
||||
}
|
||||
|
||||
if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
|
||||
ql_dbg(ql_dbg_dpc, base_vha, 0x4009,
|
||||
"Quiescence mode scheduled.\n");
|
||||
@ -4475,6 +4534,21 @@ qla2x00_module_init(void)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Initialize target kmem_cache and mem_pools */
|
||||
ret = qlt_init();
|
||||
if (ret < 0) {
|
||||
kmem_cache_destroy(srb_cachep);
|
||||
return ret;
|
||||
} else if (ret > 0) {
|
||||
/*
|
||||
* If initiator mode is explictly disabled by qlt_init(),
|
||||
* prevent scsi_transport_fc.c:fc_scsi_scan_rport() from
|
||||
* performing scsi_scan_target() during LOOP UP event.
|
||||
*/
|
||||
qla2xxx_transport_functions.disable_target_scan = 1;
|
||||
qla2xxx_transport_vport_functions.disable_target_scan = 1;
|
||||
}
|
||||
|
||||
/* Derive version string. */
|
||||
strcpy(qla2x00_version_str, QLA2XXX_VERSION);
|
||||
if (ql2xextended_error_logging)
|
||||
@ -4486,6 +4560,7 @@ qla2x00_module_init(void)
|
||||
kmem_cache_destroy(srb_cachep);
|
||||
ql_log(ql_log_fatal, NULL, 0x0002,
|
||||
"fc_attach_transport failed...Failing load!.\n");
|
||||
qlt_exit();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -4499,6 +4574,7 @@ qla2x00_module_init(void)
|
||||
fc_attach_transport(&qla2xxx_transport_vport_functions);
|
||||
if (!qla2xxx_transport_vport_template) {
|
||||
kmem_cache_destroy(srb_cachep);
|
||||
qlt_exit();
|
||||
fc_release_transport(qla2xxx_transport_template);
|
||||
ql_log(ql_log_fatal, NULL, 0x0004,
|
||||
"fc_attach_transport vport failed...Failing load!.\n");
|
||||
@ -4510,6 +4586,7 @@ qla2x00_module_init(void)
|
||||
ret = pci_register_driver(&qla2xxx_pci_driver);
|
||||
if (ret) {
|
||||
kmem_cache_destroy(srb_cachep);
|
||||
qlt_exit();
|
||||
fc_release_transport(qla2xxx_transport_template);
|
||||
fc_release_transport(qla2xxx_transport_vport_template);
|
||||
ql_log(ql_log_fatal, NULL, 0x0006,
|
||||
@ -4529,6 +4606,7 @@ qla2x00_module_exit(void)
|
||||
pci_unregister_driver(&qla2xxx_pci_driver);
|
||||
qla2x00_release_firmware();
|
||||
kmem_cache_destroy(srb_cachep);
|
||||
qlt_exit();
|
||||
if (ctx_cachep)
|
||||
kmem_cache_destroy(ctx_cachep);
|
||||
fc_release_transport(qla2xxx_transport_template);
|
||||
|
4973
drivers/scsi/qla2xxx/qla_target.c
Normal file
4973
drivers/scsi/qla2xxx/qla_target.c
Normal file
File diff suppressed because it is too large
Load Diff
1005
drivers/scsi/qla2xxx/qla_target.h
Normal file
1005
drivers/scsi/qla2xxx/qla_target.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user