Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger: "The highlights this round include: - enable dual mode (initiator + target) qla2xxx operation. (Quinn + Himanshu) - add a framework for qla2xxx async fabric discovery. (Quinn + Himanshu) - enable iscsi PDU DDP completion offload in cxgbit/T6 NICs. (Varun) - fix target-core handling of aborted failed commands. (Bart) - fix a long standing target-core issue NULL pointer dereference with active I/O LUN shutdown. (Rob Millner + Bryant + nab)" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (44 commits) target: Add counters for ABORT_TASK success + failure iscsi-target: Fix early login failure statistics misses target: Fix NULL dereference during LUN lookup + active I/O shutdown target: Delete tmr from list before processing target: Fix handling of aborted failed commands uapi: fix linux/target_core_user.h userspace compilation errors target: export protocol identifier qla2xxx: Fix a warning reported by the "smatch" static checker target/iscsi: Fix unsolicited data seq_end_offset calculation target/cxgbit: add T6 iSCSI DDP completion feature target/cxgbit: Enable DDP for T6 only if data sequence and pdu are in order target/cxgbit: Use T6 specific macros to get ETH/IP hdr len target/cxgbit: use cxgb4_tp_smt_idx() to get smt idx target/iscsi: split iscsit_check_dataout_hdr() target: Remove command flag CMD_T_DEV_ACTIVE target: Remove command flag CMD_T_BUSY target: Move session check from target_put_sess_cmd() into target_release_cmd_kref() target: Inline transport_cmd_check_stop() target: Remove an overly chatty debug message target: Stop execution if CMD_T_STOP has been set ...
This commit is contained in:
commit
821fd6f6cb
|
@ -1364,6 +1364,10 @@ struct cpl_tx_data {
|
|||
#define TX_FORCE_S 13
|
||||
#define TX_FORCE_V(x) ((x) << TX_FORCE_S)
|
||||
|
||||
#define T6_TX_FORCE_S 20
|
||||
#define T6_TX_FORCE_V(x) ((x) << T6_TX_FORCE_S)
|
||||
#define T6_TX_FORCE_F T6_TX_FORCE_V(1U)
|
||||
|
||||
enum {
|
||||
ULP_TX_MEM_READ = 2,
|
||||
ULP_TX_MEM_WRITE = 3,
|
||||
|
|
|
@ -59,7 +59,7 @@ struct cxgbi_pagepod_hdr {
|
|||
#define PPOD_PAGES_MAX 4
|
||||
struct cxgbi_pagepod {
|
||||
struct cxgbi_pagepod_hdr hdr;
|
||||
u64 addr[PPOD_PAGES_MAX + 1];
|
||||
__be64 addr[PPOD_PAGES_MAX + 1];
|
||||
};
|
||||
|
||||
/* ddp tag format
|
||||
|
|
|
@ -2163,6 +2163,9 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
|
|||
clear_bit(vha->vp_idx, ha->vp_idx_map);
|
||||
mutex_unlock(&ha->vport_lock);
|
||||
|
||||
dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
|
||||
vha->gnl.ldma);
|
||||
|
||||
if (vha->qpair->vp_idx == vha->vp_idx) {
|
||||
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
|
||||
ql_log(ql_log_warn, vha, 0x7087,
|
||||
|
|
|
@ -13,28 +13,25 @@
|
|||
|
||||
/* BSG support for ELS/CT pass through */
|
||||
void
|
||||
qla2x00_bsg_job_done(void *data, void *ptr, int res)
|
||||
qla2x00_bsg_job_done(void *ptr, int res)
|
||||
{
|
||||
srb_t *sp = (srb_t *)ptr;
|
||||
struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
|
||||
srb_t *sp = ptr;
|
||||
struct bsg_job *bsg_job = sp->u.bsg_job;
|
||||
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
|
||||
|
||||
bsg_reply->result = res;
|
||||
bsg_job_done(bsg_job, bsg_reply->result,
|
||||
bsg_reply->reply_payload_rcv_len);
|
||||
sp->free(vha, sp);
|
||||
sp->free(sp);
|
||||
}
|
||||
|
||||
void
|
||||
qla2x00_bsg_sp_free(void *data, void *ptr)
|
||||
qla2x00_bsg_sp_free(void *ptr)
|
||||
{
|
||||
srb_t *sp = (srb_t *)ptr;
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
srb_t *sp = ptr;
|
||||
struct qla_hw_data *ha = sp->vha->hw;
|
||||
struct bsg_job *bsg_job = sp->u.bsg_job;
|
||||
struct fc_bsg_request *bsg_request = bsg_job->request;
|
||||
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
|
||||
|
||||
if (sp->type == SRB_FXIOCB_BCMD) {
|
||||
|
@ -62,7 +59,7 @@ qla2x00_bsg_sp_free(void *data, void *ptr)
|
|||
sp->type == SRB_FXIOCB_BCMD ||
|
||||
sp->type == SRB_ELS_CMD_HST)
|
||||
kfree(sp->fcport);
|
||||
qla2x00_rel_sp(vha, sp);
|
||||
qla2x00_rel_sp(sp);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -394,7 +391,7 @@ qla2x00_process_els(struct bsg_job *bsg_job)
|
|||
if (rval != QLA_SUCCESS) {
|
||||
ql_log(ql_log_warn, vha, 0x700e,
|
||||
"qla2x00_start_sp failed = %d\n", rval);
|
||||
qla2x00_rel_sp(vha, sp);
|
||||
qla2x00_rel_sp(sp);
|
||||
rval = -EIO;
|
||||
goto done_unmap_sg;
|
||||
}
|
||||
|
@ -542,7 +539,7 @@ qla2x00_process_ct(struct bsg_job *bsg_job)
|
|||
if (rval != QLA_SUCCESS) {
|
||||
ql_log(ql_log_warn, vha, 0x7017,
|
||||
"qla2x00_start_sp failed=%d.\n", rval);
|
||||
qla2x00_rel_sp(vha, sp);
|
||||
qla2x00_rel_sp(sp);
|
||||
rval = -EIO;
|
||||
goto done_free_fcport;
|
||||
}
|
||||
|
@ -2578,6 +2575,6 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
|
|||
|
||||
done:
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
sp->free(vha, sp);
|
||||
sp->free(sp);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@
|
|||
|
||||
#include "qla_settings.h"
|
||||
|
||||
#define MODE_DUAL (MODE_TARGET | MODE_INITIATOR)
|
||||
|
||||
/*
|
||||
* Data bit definitions
|
||||
*/
|
||||
|
@ -251,6 +253,14 @@
|
|||
|
||||
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
|
||||
#include "qla_fw.h"
|
||||
|
||||
struct name_list_extended {
|
||||
struct get_name_list_extended *l;
|
||||
dma_addr_t ldma;
|
||||
struct list_head fcports; /* protect by sess_list */
|
||||
u32 size;
|
||||
u8 sent;
|
||||
};
|
||||
/*
|
||||
* Timeout timer counts in seconds
|
||||
*/
|
||||
|
@ -309,6 +319,17 @@ struct els_logo_payload {
|
|||
uint8_t wwpn[WWN_SIZE];
|
||||
};
|
||||
|
||||
struct ct_arg {
|
||||
void *iocb;
|
||||
u16 nport_handle;
|
||||
dma_addr_t req_dma;
|
||||
dma_addr_t rsp_dma;
|
||||
u32 req_size;
|
||||
u32 rsp_size;
|
||||
void *req;
|
||||
void *rsp;
|
||||
};
|
||||
|
||||
/*
|
||||
* SRB extensions.
|
||||
*/
|
||||
|
@ -320,6 +341,7 @@ struct srb_iocb {
|
|||
#define SRB_LOGIN_COND_PLOGI BIT_1
|
||||
#define SRB_LOGIN_SKIP_PRLI BIT_2
|
||||
uint16_t data[2];
|
||||
u32 iop[2];
|
||||
} logio;
|
||||
struct {
|
||||
#define ELS_DCMD_TIMEOUT 20
|
||||
|
@ -372,6 +394,16 @@ struct srb_iocb {
|
|||
__le16 comp_status;
|
||||
struct completion comp;
|
||||
} abt;
|
||||
struct ct_arg ctarg;
|
||||
struct {
|
||||
__le16 in_mb[28]; /* fr fw */
|
||||
__le16 out_mb[28]; /* to fw */
|
||||
void *out, *in;
|
||||
dma_addr_t out_dma, in_dma;
|
||||
} mbx;
|
||||
struct {
|
||||
struct imm_ntfy_from_isp *ntfy;
|
||||
} nack;
|
||||
} u;
|
||||
|
||||
struct timer_list timer;
|
||||
|
@ -392,23 +424,31 @@ struct srb_iocb {
|
|||
#define SRB_FXIOCB_BCMD 11
|
||||
#define SRB_ABT_CMD 12
|
||||
#define SRB_ELS_DCMD 13
|
||||
#define SRB_MB_IOCB 14
|
||||
#define SRB_CT_PTHRU_CMD 15
|
||||
#define SRB_NACK_PLOGI 16
|
||||
#define SRB_NACK_PRLI 17
|
||||
#define SRB_NACK_LOGO 18
|
||||
|
||||
typedef struct srb {
|
||||
atomic_t ref_count;
|
||||
struct fc_port *fcport;
|
||||
struct scsi_qla_host *vha;
|
||||
uint32_t handle;
|
||||
uint16_t flags;
|
||||
uint16_t type;
|
||||
char *name;
|
||||
int iocbs;
|
||||
struct qla_qpair *qpair;
|
||||
u32 gen1; /* scratch */
|
||||
u32 gen2; /* scratch */
|
||||
union {
|
||||
struct srb_iocb iocb_cmd;
|
||||
struct bsg_job *bsg_job;
|
||||
struct srb_cmd scmd;
|
||||
} u;
|
||||
void (*done)(void *, void *, int);
|
||||
void (*free)(void *, void *);
|
||||
void (*done)(void *, int);
|
||||
void (*free)(void *);
|
||||
} srb_t;
|
||||
|
||||
#define GET_CMD_SP(sp) (sp->u.scmd.cmd)
|
||||
|
@ -1794,6 +1834,7 @@ typedef struct {
|
|||
#define SS_RESIDUAL_OVER BIT_10
|
||||
#define SS_SENSE_LEN_VALID BIT_9
|
||||
#define SS_RESPONSE_INFO_LEN_VALID BIT_8
|
||||
#define SS_SCSI_STATUS_BYTE 0xff
|
||||
|
||||
#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3)
|
||||
#define SS_BUSY_CONDITION BIT_3
|
||||
|
@ -1975,6 +2016,84 @@ struct mbx_entry {
|
|||
uint8_t port_name[WWN_SIZE];
|
||||
};
|
||||
|
||||
#ifndef IMMED_NOTIFY_TYPE
|
||||
#define IMMED_NOTIFY_TYPE 0x0D /* Immediate notify entry. */
|
||||
/*
|
||||
* ISP queue - immediate notify entry structure definition.
|
||||
* This is sent by the ISP to the Target driver.
|
||||
* This IOCB would have report of events sent by the
|
||||
* initiator, that needs to be handled by the target
|
||||
* driver immediately.
|
||||
*/
|
||||
struct imm_ntfy_from_isp {
|
||||
uint8_t entry_type; /* Entry type. */
|
||||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t sys_define; /* System defined. */
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
union {
|
||||
struct {
|
||||
uint32_t sys_define_2; /* System defined. */
|
||||
target_id_t target;
|
||||
uint16_t lun;
|
||||
uint8_t target_id;
|
||||
uint8_t reserved_1;
|
||||
uint16_t status_modifier;
|
||||
uint16_t status;
|
||||
uint16_t task_flags;
|
||||
uint16_t seq_id;
|
||||
uint16_t srr_rx_id;
|
||||
uint32_t srr_rel_offs;
|
||||
uint16_t srr_ui;
|
||||
#define SRR_IU_DATA_IN 0x1
|
||||
#define SRR_IU_DATA_OUT 0x5
|
||||
#define SRR_IU_STATUS 0x7
|
||||
uint16_t srr_ox_id;
|
||||
uint8_t reserved_2[28];
|
||||
} isp2x;
|
||||
struct {
|
||||
uint32_t reserved;
|
||||
uint16_t nport_handle;
|
||||
uint16_t reserved_2;
|
||||
uint16_t flags;
|
||||
#define NOTIFY24XX_FLAGS_GLOBAL_TPRLO BIT_1
|
||||
#define NOTIFY24XX_FLAGS_PUREX_IOCB BIT_0
|
||||
uint16_t srr_rx_id;
|
||||
uint16_t status;
|
||||
uint8_t status_subcode;
|
||||
uint8_t fw_handle;
|
||||
uint32_t exchange_address;
|
||||
uint32_t srr_rel_offs;
|
||||
uint16_t srr_ui;
|
||||
uint16_t srr_ox_id;
|
||||
union {
|
||||
struct {
|
||||
uint8_t node_name[8];
|
||||
} plogi; /* PLOGI/ADISC/PDISC */
|
||||
struct {
|
||||
/* PRLI word 3 bit 0-15 */
|
||||
uint16_t wd3_lo;
|
||||
uint8_t resv0[6];
|
||||
} prli;
|
||||
struct {
|
||||
uint8_t port_id[3];
|
||||
uint8_t resv1;
|
||||
uint16_t nport_handle;
|
||||
uint16_t resv2;
|
||||
} req_els;
|
||||
} u;
|
||||
uint8_t port_name[8];
|
||||
uint8_t resv3[3];
|
||||
uint8_t vp_index;
|
||||
uint32_t reserved_5;
|
||||
uint8_t port_id[3];
|
||||
uint8_t reserved_6;
|
||||
} isp24;
|
||||
} u;
|
||||
uint16_t reserved_7;
|
||||
uint16_t ox_id;
|
||||
} __packed;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ISP request and response queue entry sizes
|
||||
*/
|
||||
|
@ -2022,6 +2141,18 @@ typedef struct {
|
|||
#define FC4_TYPE_OTHER 0x0
|
||||
#define FC4_TYPE_UNKNOWN 0xff
|
||||
|
||||
/* mailbox command 4G & above */
|
||||
struct mbx_24xx_entry {
|
||||
uint8_t entry_type;
|
||||
uint8_t entry_count;
|
||||
uint8_t sys_define1;
|
||||
uint8_t entry_status;
|
||||
uint32_t handle;
|
||||
uint16_t mb[28];
|
||||
};
|
||||
|
||||
#define IOCB_SIZE 64
|
||||
|
||||
/*
|
||||
* Fibre channel port type.
|
||||
*/
|
||||
|
@ -2034,6 +2165,74 @@ typedef struct {
|
|||
FCT_TARGET
|
||||
} fc_port_type_t;
|
||||
|
||||
enum qla_sess_deletion {
|
||||
QLA_SESS_DELETION_NONE = 0,
|
||||
QLA_SESS_DELETION_IN_PROGRESS,
|
||||
QLA_SESS_DELETED,
|
||||
};
|
||||
|
||||
enum qlt_plogi_link_t {
|
||||
QLT_PLOGI_LINK_SAME_WWN,
|
||||
QLT_PLOGI_LINK_CONFLICT,
|
||||
QLT_PLOGI_LINK_MAX
|
||||
};
|
||||
|
||||
struct qlt_plogi_ack_t {
|
||||
struct list_head list;
|
||||
struct imm_ntfy_from_isp iocb;
|
||||
port_id_t id;
|
||||
int ref_count;
|
||||
void *fcport;
|
||||
};
|
||||
|
||||
struct ct_sns_desc {
|
||||
struct ct_sns_pkt *ct_sns;
|
||||
dma_addr_t ct_sns_dma;
|
||||
};
|
||||
|
||||
enum discovery_state {
|
||||
DSC_DELETED,
|
||||
DSC_GID_PN,
|
||||
DSC_GNL,
|
||||
DSC_LOGIN_PEND,
|
||||
DSC_LOGIN_FAILED,
|
||||
DSC_GPDB,
|
||||
DSC_GPSC,
|
||||
DSC_UPD_FCPORT,
|
||||
DSC_LOGIN_COMPLETE,
|
||||
DSC_DELETE_PEND,
|
||||
};
|
||||
|
||||
enum login_state { /* FW control Target side */
|
||||
DSC_LS_LLIOCB_SENT = 2,
|
||||
DSC_LS_PLOGI_PEND,
|
||||
DSC_LS_PLOGI_COMP,
|
||||
DSC_LS_PRLI_PEND,
|
||||
DSC_LS_PRLI_COMP,
|
||||
DSC_LS_PORT_UNAVAIL,
|
||||
DSC_LS_PRLO_PEND = 9,
|
||||
DSC_LS_LOGO_PEND,
|
||||
};
|
||||
|
||||
enum fcport_mgt_event {
|
||||
FCME_RELOGIN = 1,
|
||||
FCME_RSCN,
|
||||
FCME_GIDPN_DONE,
|
||||
FCME_PLOGI_DONE, /* Initiator side sent LLIOCB */
|
||||
FCME_GNL_DONE,
|
||||
FCME_GPSC_DONE,
|
||||
FCME_GPDB_DONE,
|
||||
FCME_GPNID_DONE,
|
||||
FCME_DELETE_DONE,
|
||||
};
|
||||
|
||||
enum rscn_addr_format {
|
||||
RSCN_PORT_ADDR,
|
||||
RSCN_AREA_ADDR,
|
||||
RSCN_DOM_ADDR,
|
||||
RSCN_FAB_ADDR,
|
||||
};
|
||||
|
||||
/*
|
||||
* Fibre channel port structure.
|
||||
*/
|
||||
|
@ -2047,6 +2246,29 @@ typedef struct fc_port {
|
|||
uint16_t loop_id;
|
||||
uint16_t old_loop_id;
|
||||
|
||||
unsigned int conf_compl_supported:1;
|
||||
unsigned int deleted:2;
|
||||
unsigned int local:1;
|
||||
unsigned int logout_on_delete:1;
|
||||
unsigned int logo_ack_needed:1;
|
||||
unsigned int keep_nport_handle:1;
|
||||
unsigned int send_els_logo:1;
|
||||
unsigned int login_pause:1;
|
||||
unsigned int login_succ:1;
|
||||
|
||||
struct fc_port *conflict;
|
||||
unsigned char logout_completed;
|
||||
int generation;
|
||||
|
||||
struct se_session *se_sess;
|
||||
struct kref sess_kref;
|
||||
struct qla_tgt *tgt;
|
||||
unsigned long expires;
|
||||
struct list_head del_list_entry;
|
||||
struct work_struct free_work;
|
||||
|
||||
struct qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX];
|
||||
|
||||
uint16_t tgt_id;
|
||||
uint16_t old_tgt_id;
|
||||
|
||||
|
@ -2075,8 +2297,30 @@ typedef struct fc_port {
|
|||
|
||||
unsigned long retry_delay_timestamp;
|
||||
struct qla_tgt_sess *tgt_session;
|
||||
struct ct_sns_desc ct_desc;
|
||||
enum discovery_state disc_state;
|
||||
enum login_state fw_login_state;
|
||||
u32 login_gen, last_login_gen;
|
||||
u32 rscn_gen, last_rscn_gen;
|
||||
u32 chip_reset;
|
||||
struct list_head gnl_entry;
|
||||
struct work_struct del_work;
|
||||
u8 iocb[IOCB_SIZE];
|
||||
} fc_port_t;
|
||||
|
||||
#define QLA_FCPORT_SCAN 1
|
||||
#define QLA_FCPORT_FOUND 2
|
||||
|
||||
struct event_arg {
|
||||
enum fcport_mgt_event event;
|
||||
fc_port_t *fcport;
|
||||
srb_t *sp;
|
||||
port_id_t id;
|
||||
u16 data[2], rc;
|
||||
u8 port_name[WWN_SIZE];
|
||||
u32 iop[2];
|
||||
};
|
||||
|
||||
#include "qla_mr.h"
|
||||
|
||||
/*
|
||||
|
@ -2154,6 +2398,10 @@ static const char * const port_state_str[] = {
|
|||
#define GFT_ID_REQ_SIZE (16 + 4)
|
||||
#define GFT_ID_RSP_SIZE (16 + 32)
|
||||
|
||||
#define GID_PN_CMD 0x121
|
||||
#define GID_PN_REQ_SIZE (16 + 8)
|
||||
#define GID_PN_RSP_SIZE (16 + 4)
|
||||
|
||||
#define RFT_ID_CMD 0x217
|
||||
#define RFT_ID_REQ_SIZE (16 + 4 + 32)
|
||||
#define RFT_ID_RSP_SIZE 16
|
||||
|
@ -2479,6 +2727,10 @@ struct ct_sns_req {
|
|||
uint8_t reserved;
|
||||
uint8_t port_name[3];
|
||||
} gff_id;
|
||||
|
||||
struct {
|
||||
uint8_t port_name[8];
|
||||
} gid_pn;
|
||||
} req;
|
||||
};
|
||||
|
||||
|
@ -2558,6 +2810,10 @@ struct ct_sns_rsp {
|
|||
struct {
|
||||
uint8_t fc4_features[128];
|
||||
} gff_id;
|
||||
struct {
|
||||
uint8_t reserved;
|
||||
uint8_t port_id[3];
|
||||
} gid_pn;
|
||||
} rsp;
|
||||
};
|
||||
|
||||
|
@ -2699,7 +2955,7 @@ struct isp_operations {
|
|||
|
||||
uint16_t (*calc_req_entries) (uint16_t);
|
||||
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
|
||||
void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
|
||||
void *(*prep_ms_iocb) (struct scsi_qla_host *, struct ct_arg *);
|
||||
void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
|
||||
uint32_t);
|
||||
|
||||
|
@ -2765,13 +3021,21 @@ enum qla_work_type {
|
|||
QLA_EVT_AEN,
|
||||
QLA_EVT_IDC_ACK,
|
||||
QLA_EVT_ASYNC_LOGIN,
|
||||
QLA_EVT_ASYNC_LOGIN_DONE,
|
||||
QLA_EVT_ASYNC_LOGOUT,
|
||||
QLA_EVT_ASYNC_LOGOUT_DONE,
|
||||
QLA_EVT_ASYNC_ADISC,
|
||||
QLA_EVT_ASYNC_ADISC_DONE,
|
||||
QLA_EVT_UEVENT,
|
||||
QLA_EVT_AENFX,
|
||||
QLA_EVT_GIDPN,
|
||||
QLA_EVT_GPNID,
|
||||
QLA_EVT_GPNID_DONE,
|
||||
QLA_EVT_NEW_SESS,
|
||||
QLA_EVT_GPDB,
|
||||
QLA_EVT_GPSC,
|
||||
QLA_EVT_UPD_FCPORT,
|
||||
QLA_EVT_GNL,
|
||||
QLA_EVT_NACK,
|
||||
};
|
||||
|
||||
|
||||
|
@ -2807,6 +3071,23 @@ struct qla_work_evt {
|
|||
struct {
|
||||
srb_t *sp;
|
||||
} iosb;
|
||||
struct {
|
||||
port_id_t id;
|
||||
} gpnid;
|
||||
struct {
|
||||
port_id_t id;
|
||||
u8 port_name[8];
|
||||
void *pla;
|
||||
} new_sess;
|
||||
struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
|
||||
fc_port_t *fcport;
|
||||
u8 opt;
|
||||
} fcport;
|
||||
struct {
|
||||
fc_port_t *fcport;
|
||||
u8 iocb[IOCB_SIZE];
|
||||
int type;
|
||||
} nack;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -2943,6 +3224,7 @@ struct qla_qpair {
|
|||
struct qla_hw_data *hw;
|
||||
struct work_struct q_work;
|
||||
struct list_head qp_list_elem; /* vha->qp_list */
|
||||
struct scsi_qla_host *vha;
|
||||
};
|
||||
|
||||
/* Place holder for FW buffer parameters */
|
||||
|
@ -2963,7 +3245,6 @@ 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. */
|
||||
|
@ -3115,6 +3396,7 @@ struct qla_hw_data {
|
|||
#define FLOGI_SP_SUPPORT BIT_13
|
||||
|
||||
uint8_t port_no; /* Physical port of adapter */
|
||||
uint8_t exch_starvation;
|
||||
|
||||
/* Timeout timers. */
|
||||
uint8_t loop_down_abort_time; /* port down timer */
|
||||
|
@ -3682,7 +3964,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 */
|
||||
#define FREE_BIT 21
|
||||
#define PORT_UPDATE_NEEDED 22
|
||||
#define FX00_RESET_RECOVERY 23
|
||||
#define FX00_TARGET_SCAN 24
|
||||
|
@ -3736,7 +4018,9 @@ typedef struct scsi_qla_host {
|
|||
/* list of commands waiting on workqueue */
|
||||
struct list_head qla_cmd_list;
|
||||
struct list_head qla_sess_op_cmd_list;
|
||||
struct list_head unknown_atio_list;
|
||||
spinlock_t cmd_list_lock;
|
||||
struct delayed_work unknown_atio_work;
|
||||
|
||||
/* Counter to detect races between ELS and RSCN events */
|
||||
atomic_t generation_tick;
|
||||
|
@ -3788,6 +4072,10 @@ typedef struct scsi_qla_host {
|
|||
struct qla8044_reset_template reset_tmplt;
|
||||
struct qla_tgt_counters tgt_counters;
|
||||
uint16_t bbcr;
|
||||
struct name_list_extended gnl;
|
||||
/* Count of active session/fcport */
|
||||
int fcport_count;
|
||||
wait_queue_head_t fcport_waitQ;
|
||||
} scsi_qla_host_t;
|
||||
|
||||
struct qla27xx_image_status {
|
||||
|
|
|
@ -18,7 +18,7 @@ qla2x00_dfs_tgt_sess_show(struct seq_file *s, void *unused)
|
|||
scsi_qla_host_t *vha = s->private;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
unsigned long flags;
|
||||
struct qla_tgt_sess *sess = NULL;
|
||||
struct fc_port *sess = NULL;
|
||||
struct qla_tgt *tgt= vha->vha_tgt.qla_tgt;
|
||||
|
||||
seq_printf(s, "%s\n",vha->host_str);
|
||||
|
@ -26,12 +26,11 @@ qla2x00_dfs_tgt_sess_show(struct seq_file *s, void *unused)
|
|||
seq_printf(s, "Port ID Port Name Handle\n");
|
||||
|
||||
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||
list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
|
||||
list_for_each_entry(sess, &vha->vp_fcports, list)
|
||||
seq_printf(s, "%02x:%02x:%02x %8phC %d\n",
|
||||
sess->s_id.b.domain,sess->s_id.b.area,
|
||||
sess->s_id.b.al_pa, sess->port_name,
|
||||
sess->d_id.b.domain, sess->d_id.b.area,
|
||||
sess->d_id.b.al_pa, sess->port_name,
|
||||
sess->loop_id);
|
||||
}
|
||||
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,37 @@ struct port_database_24xx {
|
|||
uint8_t reserved_3[24];
|
||||
};
|
||||
|
||||
/*
|
||||
* MB 75h returns a list of DB entries similar to port_database_24xx(64B).
|
||||
* However, in this case it returns 1st 40 bytes.
|
||||
*/
|
||||
struct get_name_list_extended {
|
||||
__le16 flags;
|
||||
u8 current_login_state;
|
||||
u8 last_login_state;
|
||||
u8 hard_address[3];
|
||||
u8 reserved_1;
|
||||
u8 port_id[3];
|
||||
u8 sequence_id;
|
||||
__le16 port_timer;
|
||||
__le16 nport_handle; /* N_PORT handle. */
|
||||
__le16 receive_data_size;
|
||||
__le16 reserved_2;
|
||||
|
||||
/* PRLI SVC Param are Big endian */
|
||||
u8 prli_svc_param_word_0[2]; /* Bits 15-0 of word 0 */
|
||||
u8 prli_svc_param_word_3[2]; /* Bits 15-0 of word 3 */
|
||||
u8 port_name[WWN_SIZE];
|
||||
u8 node_name[WWN_SIZE];
|
||||
};
|
||||
|
||||
/* MB 75h: This is the short version of the database */
|
||||
struct get_name_list {
|
||||
u8 port_node_name[WWN_SIZE]; /* B7 most sig, B0 least sig */
|
||||
__le16 nport_handle;
|
||||
u8 reserved;
|
||||
};
|
||||
|
||||
struct vp_database_24xx {
|
||||
uint16_t vp_status;
|
||||
uint8_t options;
|
||||
|
@ -1270,27 +1301,76 @@ struct vp_config_entry_24xx {
|
|||
};
|
||||
|
||||
#define VP_RPT_ID_IOCB_TYPE 0x32 /* Report ID Acquisition entry. */
|
||||
enum VP_STATUS {
|
||||
VP_STAT_COMPL,
|
||||
VP_STAT_FAIL,
|
||||
VP_STAT_ID_CHG,
|
||||
VP_STAT_SNS_TO, /* timeout */
|
||||
VP_STAT_SNS_RJT,
|
||||
VP_STAT_SCR_TO, /* timeout */
|
||||
VP_STAT_SCR_RJT,
|
||||
};
|
||||
|
||||
enum VP_FLAGS {
|
||||
VP_FLAGS_CON_FLOOP = 1,
|
||||
VP_FLAGS_CON_P2P = 2,
|
||||
VP_FLAGS_CON_FABRIC = 3,
|
||||
VP_FLAGS_NAME_VALID = BIT_5,
|
||||
};
|
||||
|
||||
struct vp_rpt_id_entry_24xx {
|
||||
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 handle. */
|
||||
|
||||
uint16_t vp_count; /* Format 0 -- | VP setup | VP acq |. */
|
||||
/* Format 1 -- | VP count |. */
|
||||
uint16_t vp_idx; /* Format 0 -- Reserved. */
|
||||
/* Format 1 -- VP status and index. */
|
||||
uint32_t resv1;
|
||||
uint8_t vp_acquired;
|
||||
uint8_t vp_setup;
|
||||
uint8_t vp_idx; /* Format 0=reserved */
|
||||
uint8_t vp_status; /* Format 0=reserved */
|
||||
|
||||
uint8_t port_id[3];
|
||||
uint8_t format;
|
||||
|
||||
union {
|
||||
struct {
|
||||
/* format 0 loop */
|
||||
uint8_t vp_idx_map[16];
|
||||
uint8_t reserved_4[32];
|
||||
} f0;
|
||||
struct {
|
||||
/* format 1 fabric */
|
||||
uint8_t vpstat1_subcode; /* vp_status=1 subcode */
|
||||
uint8_t flags;
|
||||
uint16_t fip_flags;
|
||||
uint8_t rsv2[12];
|
||||
|
||||
uint8_t reserved_4[24];
|
||||
uint8_t ls_rjt_vendor;
|
||||
uint8_t ls_rjt_explanation;
|
||||
uint8_t ls_rjt_reason;
|
||||
uint8_t rsv3[5];
|
||||
|
||||
uint8_t port_name[8];
|
||||
uint8_t node_name[8];
|
||||
uint16_t bbcr;
|
||||
uint8_t reserved_5[6];
|
||||
} f1;
|
||||
struct { /* format 2: N2N direct connect */
|
||||
uint8_t vpstat1_subcode;
|
||||
uint8_t flags;
|
||||
uint16_t rsv6;
|
||||
uint8_t rsv2[12];
|
||||
|
||||
uint8_t ls_rjt_vendor;
|
||||
uint8_t ls_rjt_explanation;
|
||||
uint8_t ls_rjt_reason;
|
||||
uint8_t rsv3[5];
|
||||
|
||||
uint8_t port_name[8];
|
||||
uint8_t node_name[8];
|
||||
uint32_t remote_nport_id;
|
||||
uint32_t reserved_5;
|
||||
} f2;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define VF_EVFP_IOCB_TYPE 0x26 /* Exchange Virtual Fabric Parameters entry. */
|
||||
|
|
|
@ -73,6 +73,10 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
|
|||
uint16_t *);
|
||||
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
|
||||
uint16_t *);
|
||||
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
|
||||
enum qla_work_type);
|
||||
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
|
||||
int qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e);
|
||||
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
|
||||
extern void *qla2x00_alloc_iocbs_ready(struct scsi_qla_host *, srb_t *);
|
||||
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
|
||||
|
@ -94,6 +98,13 @@ extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
|
|||
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
|
||||
int, int);
|
||||
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
|
||||
void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *);
|
||||
int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
|
||||
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
|
||||
struct imm_ntfy_from_isp *, int);
|
||||
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
|
||||
void *);
|
||||
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
|
||||
|
||||
/*
|
||||
* Global Data in qla_os.c source file.
|
||||
|
@ -127,6 +138,7 @@ extern int ql2xmdenable;
|
|||
extern int ql2xexlogins;
|
||||
extern int ql2xexchoffld;
|
||||
extern int ql2xfwholdabts;
|
||||
extern int ql2xmvasynctoatio;
|
||||
|
||||
extern int qla2x00_loop_reset(scsi_qla_host_t *);
|
||||
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
|
||||
|
@ -135,8 +147,6 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
|
|||
extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
|
||||
extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *,
|
||||
uint16_t *);
|
||||
extern int qla2x00_post_async_login_done_work(struct scsi_qla_host *,
|
||||
fc_port_t *, uint16_t *);
|
||||
extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
|
||||
uint16_t *);
|
||||
extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
|
||||
|
@ -176,9 +186,13 @@ extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
|
|||
|
||||
extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
|
||||
extern void qla2x00_disable_board_on_pci_error(struct work_struct *);
|
||||
extern void qla2x00_sp_compl(void *, void *, int);
|
||||
extern void qla2xxx_qpair_sp_free_dma(void *, void *);
|
||||
extern void qla2xxx_qpair_sp_compl(void *, void *, int);
|
||||
extern void qla2x00_sp_compl(void *, int);
|
||||
extern void qla2xxx_qpair_sp_free_dma(void *);
|
||||
extern void qla2xxx_qpair_sp_compl(void *, int);
|
||||
extern int qla24xx_post_upd_fcport_work(struct scsi_qla_host *, fc_port_t *);
|
||||
void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
|
||||
uint16_t *);
|
||||
int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
|
||||
|
||||
/*
|
||||
* Global Functions in qla_mid.c source file.
|
||||
|
@ -201,7 +215,7 @@ extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *);
|
|||
extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *);
|
||||
extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *);
|
||||
|
||||
extern void qla2x00_sp_free_dma(void *, void *);
|
||||
extern void qla2x00_sp_free_dma(void *);
|
||||
extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
|
||||
|
||||
extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
|
||||
|
@ -301,9 +315,6 @@ 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);
|
||||
|
||||
|
@ -483,6 +494,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *,
|
|||
uint32_t);
|
||||
extern irqreturn_t
|
||||
qla2xxx_msix_rsp_q(int irq, void *dev_id);
|
||||
fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
|
||||
fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
|
||||
fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
|
||||
|
||||
/*
|
||||
* Global Function Prototypes in qla_sup.c source file.
|
||||
|
@ -574,8 +588,8 @@ extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int);
|
|||
/*
|
||||
* Global Function Prototypes in qla_gs.c source file.
|
||||
*/
|
||||
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
|
||||
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
|
||||
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
|
||||
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
|
||||
extern int qla2x00_ga_nxt(scsi_qla_host_t *, fc_port_t *);
|
||||
extern int qla2x00_gid_pt(scsi_qla_host_t *, sw_info_t *);
|
||||
extern int qla2x00_gpn_id(scsi_qla_host_t *, sw_info_t *);
|
||||
|
@ -591,6 +605,23 @@ extern int qla2x00_fdmi_register(scsi_qla_host_t *);
|
|||
extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
|
||||
extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
|
||||
extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t);
|
||||
extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *,
|
||||
struct ct_sns_rsp *, const char *);
|
||||
extern void qla2x00_async_iocb_timeout(void *data);
|
||||
extern int qla24xx_async_gidpn(scsi_qla_host_t *, fc_port_t *);
|
||||
int qla24xx_post_gidpn_work(struct scsi_qla_host *, fc_port_t *);
|
||||
void qla24xx_handle_gidpn_event(scsi_qla_host_t *, struct event_arg *);
|
||||
|
||||
extern void qla2x00_free_fcport(fc_port_t *);
|
||||
|
||||
extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
|
||||
extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
|
||||
void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*);
|
||||
void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
|
||||
|
||||
int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
|
||||
int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
|
||||
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
|
||||
|
||||
/*
|
||||
* Global Function Prototypes in qla_attr.c source file.
|
||||
|
@ -702,10 +733,10 @@ extern int qla82xx_restart_isp(scsi_qla_host_t *);
|
|||
|
||||
/* IOCB related functions */
|
||||
extern int qla82xx_start_scsi(srb_t *);
|
||||
extern void qla2x00_sp_free(void *, void *);
|
||||
extern void qla2x00_sp_free(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_bsg_job_done(void *, int);
|
||||
extern void qla2x00_bsg_sp_free(void *);
|
||||
extern void qla2x00_start_iocbs(struct scsi_qla_host *, struct req_que *);
|
||||
|
||||
/* Interrupt related */
|
||||
|
@ -803,4 +834,17 @@ extern int qla_get_exchoffld_status(scsi_qla_host_t *, uint16_t *, uint16_t *);
|
|||
extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *, dma_addr_t);
|
||||
extern void qlt_handle_abts_recv(struct scsi_qla_host *, response_t *);
|
||||
|
||||
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
|
||||
struct imm_ntfy_from_isp *, int);
|
||||
void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
|
||||
void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *,
|
||||
struct fc_port *, enum qlt_plogi_link_t);
|
||||
void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *);
|
||||
extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool);
|
||||
extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
|
||||
extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
|
||||
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
|
||||
void qla24xx_delete_sess_fn(struct work_struct *);
|
||||
void qlt_unknown_atio_work_fn(struct work_struct *);
|
||||
|
||||
#endif /* _QLA_GBL_H */
|
||||
|
|
|
@ -24,12 +24,12 @@ static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
|
|||
* Returns a pointer to the @ha's ms_iocb.
|
||||
*/
|
||||
void *
|
||||
qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
|
||||
qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
ms_iocb_entry_t *ms_pkt;
|
||||
|
||||
ms_pkt = ha->ms_iocb;
|
||||
ms_pkt = (ms_iocb_entry_t *)arg->iocb;
|
||||
memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
|
||||
|
||||
ms_pkt->entry_type = MS_IOCB_TYPE;
|
||||
|
@ -39,15 +39,15 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
|
|||
ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
|
||||
ms_pkt->cmd_dsd_count = cpu_to_le16(1);
|
||||
ms_pkt->total_dsd_count = cpu_to_le16(2);
|
||||
ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
|
||||
ms_pkt->req_bytecount = cpu_to_le32(req_size);
|
||||
ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
|
||||
ms_pkt->req_bytecount = cpu_to_le32(arg->req_size);
|
||||
|
||||
ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
|
||||
ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
|
||||
ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(arg->req_dma));
|
||||
ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(arg->req_dma));
|
||||
ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
|
||||
|
||||
ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
|
||||
ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
|
||||
ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
|
||||
ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
|
||||
ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
|
||||
|
||||
vha->qla_stats.control_requests++;
|
||||
|
@ -64,29 +64,29 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
|
|||
* Returns a pointer to the @ha's ms_iocb.
|
||||
*/
|
||||
void *
|
||||
qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
|
||||
qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct ct_entry_24xx *ct_pkt;
|
||||
|
||||
ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
|
||||
ct_pkt = (struct ct_entry_24xx *)arg->iocb;
|
||||
memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
|
||||
|
||||
ct_pkt->entry_type = CT_IOCB_TYPE;
|
||||
ct_pkt->entry_count = 1;
|
||||
ct_pkt->nport_handle = cpu_to_le16(NPH_SNS);
|
||||
ct_pkt->nport_handle = cpu_to_le16(arg->nport_handle);
|
||||
ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
|
||||
ct_pkt->cmd_dsd_count = cpu_to_le16(1);
|
||||
ct_pkt->rsp_dsd_count = cpu_to_le16(1);
|
||||
ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
|
||||
ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
|
||||
ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);
|
||||
ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);
|
||||
|
||||
ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
|
||||
ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
|
||||
ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(arg->req_dma));
|
||||
ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(arg->req_dma));
|
||||
ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
|
||||
|
||||
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
|
||||
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
|
||||
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
|
||||
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
|
||||
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
|
||||
ct_pkt->vp_index = vha->vp_idx;
|
||||
|
||||
|
@ -117,7 +117,7 @@ qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)
|
|||
return &p->p.req;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
|
||||
struct ct_sns_rsp *ct_rsp, const char *routine)
|
||||
{
|
||||
|
@ -183,14 +183,21 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||
return qla2x00_sns_ga_nxt(vha, fcport);
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = GA_NXT_REQ_SIZE;
|
||||
arg.rsp_size = GA_NXT_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
/* Issue GA_NXT */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
|
||||
GA_NXT_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
|
||||
|
@ -269,16 +276,24 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
struct ct_sns_gid_pt_data *gid_data;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
uint16_t gid_pt_rsp_size;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||
return qla2x00_sns_gid_pt(vha, list);
|
||||
|
||||
gid_data = NULL;
|
||||
gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = GID_PT_REQ_SIZE;
|
||||
arg.rsp_size = gid_pt_rsp_size;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
/* Issue GID_PT */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
|
||||
gid_pt_rsp_size);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
|
||||
|
@ -344,15 +359,22 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||
return qla2x00_sns_gpn_id(vha, list);
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = GPN_ID_REQ_SIZE;
|
||||
arg.rsp_size = GPN_ID_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||
/* Issue GPN_ID */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
|
||||
GPN_ID_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
|
||||
|
@ -406,15 +428,22 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
ms_iocb_entry_t *ms_pkt;
|
||||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||
return qla2x00_sns_gnn_id(vha, list);
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = GNN_ID_REQ_SIZE;
|
||||
arg.rsp_size = GNN_ID_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||
/* Issue GNN_ID */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
|
||||
GNN_ID_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
|
||||
|
@ -473,14 +502,21 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
|
|||
ms_iocb_entry_t *ms_pkt;
|
||||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||
return qla2x00_sns_rft_id(vha);
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = RFT_ID_REQ_SIZE;
|
||||
arg.rsp_size = RFT_ID_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
/* Issue RFT_ID */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
|
||||
RFT_ID_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
|
||||
|
@ -526,6 +562,7 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
|
|||
ms_iocb_entry_t *ms_pkt;
|
||||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0x2046,
|
||||
|
@ -533,10 +570,16 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
|
|||
return (QLA_SUCCESS);
|
||||
}
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = RFF_ID_REQ_SIZE;
|
||||
arg.rsp_size = RFF_ID_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
/* Issue RFF_ID */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
|
||||
RFF_ID_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
|
||||
|
@ -584,14 +627,21 @@ qla2x00_rnn_id(scsi_qla_host_t *vha)
|
|||
ms_iocb_entry_t *ms_pkt;
|
||||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||
return qla2x00_sns_rnn_id(vha);
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = RNN_ID_REQ_SIZE;
|
||||
arg.rsp_size = RNN_ID_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
/* Issue RNN_ID */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
|
||||
RNN_ID_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
|
||||
|
@ -651,6 +701,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
|
|||
ms_iocb_entry_t *ms_pkt;
|
||||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0x2050,
|
||||
|
@ -658,10 +709,17 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
|
|||
return (QLA_SUCCESS);
|
||||
}
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = 0;
|
||||
arg.rsp_size = RSNN_NN_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
/* Issue RSNN_NN */
|
||||
/* Prepare common MS IOCB */
|
||||
/* Request size adjusted after CT preparation */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
|
||||
|
@ -1103,7 +1161,7 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
|
|||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
|
||||
{
|
||||
int ret, rval;
|
||||
|
@ -2425,15 +2483,22 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
ms_iocb_entry_t *ms_pkt;
|
||||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (!IS_IIDMA_CAPABLE(ha))
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = GFPN_ID_REQ_SIZE;
|
||||
arg.rsp_size = GFPN_ID_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||
/* Issue GFPN_ID */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
|
||||
GFPN_ID_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
|
||||
|
@ -2471,36 +2536,6 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
return (rval);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
|
||||
uint32_t rsp_size)
|
||||
{
|
||||
struct ct_entry_24xx *ct_pkt;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
|
||||
memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
|
||||
|
||||
ct_pkt->entry_type = CT_IOCB_TYPE;
|
||||
ct_pkt->entry_count = 1;
|
||||
ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
|
||||
ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
|
||||
ct_pkt->cmd_dsd_count = cpu_to_le16(1);
|
||||
ct_pkt->rsp_dsd_count = cpu_to_le16(1);
|
||||
ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
|
||||
ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
|
||||
|
||||
ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
|
||||
ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
|
||||
ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
|
||||
|
||||
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
|
||||
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
|
||||
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
|
||||
ct_pkt->vp_index = vha->vp_idx;
|
||||
|
||||
return ct_pkt;
|
||||
}
|
||||
|
||||
|
||||
static inline struct ct_sns_req *
|
||||
qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
|
||||
|
@ -2533,6 +2568,7 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
ms_iocb_entry_t *ms_pkt;
|
||||
struct ct_sns_req *ct_req;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct ct_arg arg;
|
||||
|
||||
if (!IS_IIDMA_CAPABLE(ha))
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
@ -2543,11 +2579,17 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
if (rval)
|
||||
return rval;
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = GPSC_REQ_SIZE;
|
||||
arg.rsp_size = GPSC_RSP_SIZE;
|
||||
arg.nport_handle = vha->mgmt_svr_loop_id;
|
||||
|
||||
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||
/* Issue GFPN_ID */
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
|
||||
GPSC_RSP_SIZE);
|
||||
ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
|
||||
|
@ -2641,6 +2683,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
struct ct_sns_rsp *ct_rsp;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
uint8_t fcp_scsi_features = 0;
|
||||
struct ct_arg arg;
|
||||
|
||||
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||
/* Set default FC4 Type as UNKNOWN so the default is to
|
||||
|
@ -2651,9 +2694,15 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
if (!IS_FWI2_CAPABLE(ha))
|
||||
continue;
|
||||
|
||||
arg.iocb = ha->ms_iocb;
|
||||
arg.req_dma = ha->ct_sns_dma;
|
||||
arg.rsp_dma = ha->ct_sns_dma;
|
||||
arg.req_size = GFF_ID_REQ_SIZE;
|
||||
arg.rsp_size = GFF_ID_RSP_SIZE;
|
||||
arg.nport_handle = NPH_SNS;
|
||||
|
||||
/* Prepare common MS IOCB */
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
|
||||
GFF_ID_RSP_SIZE);
|
||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||
|
||||
/* Prepare CT request */
|
||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
|
||||
|
@ -2692,3 +2741,538 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* GID_PN completion processing. */
|
||||
void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
|
||||
{
|
||||
fc_port_t *fcport = ea->fcport;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %8phC login state %d \n",
|
||||
__func__, fcport->port_name, fcport->fw_login_state);
|
||||
|
||||
if (ea->sp->gen2 != fcport->login_gen) {
|
||||
/* PLOGI/PRLI/LOGO came in while cmd was out.*/
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %8phC generation changed rscn %d|%d login %d|%d \n",
|
||||
__func__, fcport->port_name, fcport->last_rscn_gen,
|
||||
fcport->rscn_gen, fcport->last_login_gen, fcport->login_gen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ea->rc) {
|
||||
if (ea->sp->gen1 == fcport->rscn_gen) {
|
||||
fcport->scan_state = QLA_FCPORT_FOUND;
|
||||
fcport->flags |= FCF_FABRIC_DEVICE;
|
||||
|
||||
if (fcport->d_id.b24 == ea->id.b24) {
|
||||
/* cable plugged into the same place */
|
||||
switch (vha->host->active_mode) {
|
||||
case MODE_TARGET:
|
||||
/* NOOP. let the other guy login to us.*/
|
||||
break;
|
||||
case MODE_INITIATOR:
|
||||
case MODE_DUAL:
|
||||
default:
|
||||
if (atomic_read(&fcport->state) ==
|
||||
FCS_ONLINE)
|
||||
break;
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %d %8phC post gnl\n",
|
||||
__func__, __LINE__, fcport->port_name);
|
||||
qla24xx_post_gnl_work(vha, fcport);
|
||||
break;
|
||||
}
|
||||
} else { /* fcport->d_id.b24 != ea->id.b24 */
|
||||
fcport->d_id.b24 = ea->id.b24;
|
||||
if (fcport->deleted == QLA_SESS_DELETED) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %d %8phC post del sess\n",
|
||||
__func__, __LINE__, fcport->port_name);
|
||||
qlt_schedule_sess_for_deletion_lock(fcport);
|
||||
}
|
||||
}
|
||||
} else { /* ea->sp->gen1 != fcport->rscn_gen */
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %d %8phC post gidpn\n",
|
||||
__func__, __LINE__, fcport->port_name);
|
||||
/* rscn came in while cmd was out */
|
||||
qla24xx_post_gidpn_work(vha, fcport);
|
||||
}
|
||||
} else { /* ea->rc */
|
||||
/* cable pulled */
|
||||
if (ea->sp->gen1 == fcport->rscn_gen) {
|
||||
if (ea->sp->gen2 == fcport->login_gen) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %d %8phC post del sess\n", __func__,
|
||||
__LINE__, fcport->port_name);
|
||||
qlt_schedule_sess_for_deletion_lock(fcport);
|
||||
} else {
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %d %8phC login\n", __func__, __LINE__,
|
||||
fcport->port_name);
|
||||
qla24xx_fcport_handle_login(vha, fcport);
|
||||
}
|
||||
} else {
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %d %8phC post gidpn\n", __func__, __LINE__,
|
||||
fcport->port_name);
|
||||
qla24xx_post_gidpn_work(vha, fcport);
|
||||
}
|
||||
}
|
||||
} /* gidpn_event */
|
||||
|
||||
static void qla2x00_async_gidpn_sp_done(void *s, int res)
|
||||
{
|
||||
struct srb *sp = s;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
fc_port_t *fcport = sp->fcport;
|
||||
u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id;
|
||||
struct event_arg ea;
|
||||
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.fcport = fcport;
|
||||
ea.id.b.domain = id[0];
|
||||
ea.id.b.area = id[1];
|
||||
ea.id.b.al_pa = id[2];
|
||||
ea.sp = sp;
|
||||
ea.rc = res;
|
||||
ea.event = FCME_GIDPN_DONE;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"Async done-%s res %x, WWPN %8phC ID %3phC \n",
|
||||
sp->name, res, fcport->port_name, id);
|
||||
|
||||
qla2x00_fcport_event_handler(vha, &ea);
|
||||
|
||||
sp->free(sp);
|
||||
}
|
||||
|
||||
int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
|
||||
{
|
||||
int rval = QLA_FUNCTION_FAILED;
|
||||
struct ct_sns_req *ct_req;
|
||||
srb_t *sp;
|
||||
|
||||
if (!vha->flags.online)
|
||||
goto done;
|
||||
|
||||
fcport->flags |= FCF_ASYNC_SENT;
|
||||
fcport->disc_state = DSC_GID_PN;
|
||||
fcport->scan_state = QLA_FCPORT_SCAN;
|
||||
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
|
||||
if (!sp)
|
||||
goto done;
|
||||
|
||||
sp->type = SRB_CT_PTHRU_CMD;
|
||||
sp->name = "gidpn";
|
||||
sp->gen1 = fcport->rscn_gen;
|
||||
sp->gen2 = fcport->login_gen;
|
||||
|
||||
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
|
||||
|
||||
/* CT_IU preamble */
|
||||
ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GID_PN_CMD,
|
||||
GID_PN_RSP_SIZE);
|
||||
|
||||
/* GIDPN req */
|
||||
memcpy(ct_req->req.gid_pn.port_name, fcport->port_name,
|
||||
WWN_SIZE);
|
||||
|
||||
/* req & rsp use the same buffer */
|
||||
sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
|
||||
sp->u.iocb_cmd.u.ctarg.req_size = GID_PN_REQ_SIZE;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_size = GID_PN_RSP_SIZE;
|
||||
sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
|
||||
|
||||
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
|
||||
sp->done = qla2x00_async_gidpn_sp_done;
|
||||
|
||||
rval = qla2x00_start_sp(sp);
|
||||
if (rval != QLA_SUCCESS)
|
||||
goto done_free_sp;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0x206f,
|
||||
"Async-%s - %8phC hdl=%x loopid=%x portid %02x%02x%02x.\n",
|
||||
sp->name, fcport->port_name,
|
||||
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
|
||||
fcport->d_id.b.area, fcport->d_id.b.al_pa);
|
||||
return rval;
|
||||
|
||||
done_free_sp:
|
||||
sp->free(sp);
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
return rval;
|
||||
}
|
||||
|
||||
int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
{
|
||||
struct qla_work_evt *e;
|
||||
int ls;
|
||||
|
||||
ls = atomic_read(&vha->loop_state);
|
||||
if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
|
||||
test_bit(UNLOADING, &vha->dpc_flags))
|
||||
return 0;
|
||||
|
||||
e = qla2x00_alloc_work(vha, QLA_EVT_GIDPN);
|
||||
if (!e)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
e->u.fcport.fcport = fcport;
|
||||
return qla2x00_post_work(vha, e);
|
||||
}
|
||||
|
||||
int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
{
|
||||
struct qla_work_evt *e;
|
||||
|
||||
e = qla2x00_alloc_work(vha, QLA_EVT_GPSC);
|
||||
if (!e)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
e->u.fcport.fcport = fcport;
|
||||
return qla2x00_post_work(vha, e);
|
||||
}
|
||||
|
||||
static void qla24xx_async_gpsc_sp_done(void *s, int res)
|
||||
{
|
||||
struct srb *sp = s;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
fc_port_t *fcport = sp->fcport;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct event_arg ea;
|
||||
|
||||
ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"Async done-%s res %x, WWPN %8phC \n",
|
||||
sp->name, res, fcport->port_name);
|
||||
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
|
||||
if (res == (DID_ERROR << 16)) {
|
||||
/* entry status error */
|
||||
goto done;
|
||||
} else if (res) {
|
||||
if ((ct_rsp->header.reason_code ==
|
||||
CT_REASON_INVALID_COMMAND_CODE) ||
|
||||
(ct_rsp->header.reason_code ==
|
||||
CT_REASON_COMMAND_UNSUPPORTED)) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0x205a,
|
||||
"GPSC command unsupported, disabling "
|
||||
"query.\n");
|
||||
ha->flags.gpsc_supported = 0;
|
||||
res = QLA_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
|
||||
case BIT_15:
|
||||
fcport->fp_speed = PORT_SPEED_1GB;
|
||||
break;
|
||||
case BIT_14:
|
||||
fcport->fp_speed = PORT_SPEED_2GB;
|
||||
break;
|
||||
case BIT_13:
|
||||
fcport->fp_speed = PORT_SPEED_4GB;
|
||||
break;
|
||||
case BIT_12:
|
||||
fcport->fp_speed = PORT_SPEED_10GB;
|
||||
break;
|
||||
case BIT_11:
|
||||
fcport->fp_speed = PORT_SPEED_8GB;
|
||||
break;
|
||||
case BIT_10:
|
||||
fcport->fp_speed = PORT_SPEED_16GB;
|
||||
break;
|
||||
case BIT_8:
|
||||
fcport->fp_speed = PORT_SPEED_32GB;
|
||||
break;
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
|
||||
sp->name,
|
||||
fcport->fabric_port_name,
|
||||
be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
|
||||
be16_to_cpu(ct_rsp->rsp.gpsc.speed));
|
||||
}
|
||||
done:
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.event = FCME_GPSC_DONE;
|
||||
ea.rc = res;
|
||||
ea.fcport = fcport;
|
||||
qla2x00_fcport_event_handler(vha, &ea);
|
||||
|
||||
sp->free(sp);
|
||||
}
|
||||
|
||||
int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
|
||||
{
|
||||
int rval = QLA_FUNCTION_FAILED;
|
||||
struct ct_sns_req *ct_req;
|
||||
srb_t *sp;
|
||||
|
||||
if (!vha->flags.online)
|
||||
goto done;
|
||||
|
||||
fcport->flags |= FCF_ASYNC_SENT;
|
||||
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
|
||||
if (!sp)
|
||||
goto done;
|
||||
|
||||
sp->type = SRB_CT_PTHRU_CMD;
|
||||
sp->name = "gpsc";
|
||||
sp->gen1 = fcport->rscn_gen;
|
||||
sp->gen2 = fcport->login_gen;
|
||||
|
||||
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
|
||||
|
||||
/* CT_IU preamble */
|
||||
ct_req = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
|
||||
GPSC_RSP_SIZE);
|
||||
|
||||
/* GPSC req */
|
||||
memcpy(ct_req->req.gpsc.port_name, fcport->port_name,
|
||||
WWN_SIZE);
|
||||
|
||||
sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
|
||||
sp->u.iocb_cmd.u.ctarg.req_size = GPSC_REQ_SIZE;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
|
||||
sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
|
||||
|
||||
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
|
||||
sp->done = qla24xx_async_gpsc_sp_done;
|
||||
|
||||
rval = qla2x00_start_sp(sp);
|
||||
if (rval != QLA_SUCCESS)
|
||||
goto done_free_sp;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
|
||||
sp->name, fcport->port_name, sp->handle,
|
||||
fcport->loop_id, fcport->d_id.b.domain,
|
||||
fcport->d_id.b.area, fcport->d_id.b.al_pa);
|
||||
return rval;
|
||||
|
||||
done_free_sp:
|
||||
sp->free(sp);
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
return rval;
|
||||
}
|
||||
|
||||
int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
|
||||
{
|
||||
struct qla_work_evt *e;
|
||||
|
||||
if (test_bit(UNLOADING, &vha->dpc_flags))
|
||||
return 0;
|
||||
|
||||
e = qla2x00_alloc_work(vha, QLA_EVT_GPNID);
|
||||
if (!e)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
e->u.gpnid.id = *id;
|
||||
return qla2x00_post_work(vha, e);
|
||||
}
|
||||
|
||||
void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp)
|
||||
{
|
||||
if (sp->u.iocb_cmd.u.ctarg.req) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sizeof(struct ct_sns_pkt),
|
||||
sp->u.iocb_cmd.u.ctarg.req,
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.req = NULL;
|
||||
}
|
||||
if (sp->u.iocb_cmd.u.ctarg.rsp) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sizeof(struct ct_sns_pkt),
|
||||
sp->u.iocb_cmd.u.ctarg.rsp,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
|
||||
}
|
||||
|
||||
sp->free(sp);
|
||||
}
|
||||
|
||||
void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
|
||||
{
|
||||
fc_port_t *fcport;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
||||
fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1);
|
||||
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
|
||||
|
||||
if (fcport) {
|
||||
/* cable moved. just plugged in */
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %d %8phC post del sess\n",
|
||||
__func__, __LINE__, fcport->port_name);
|
||||
|
||||
fcport->rscn_gen++;
|
||||
fcport->d_id = ea->id;
|
||||
fcport->scan_state = QLA_FCPORT_FOUND;
|
||||
fcport->flags |= FCF_FABRIC_DEVICE;
|
||||
|
||||
qlt_schedule_sess_for_deletion_lock(fcport);
|
||||
} else {
|
||||
/* create new fcport */
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"%s %d %8phC post new sess\n",
|
||||
__func__, __LINE__, ea->port_name);
|
||||
|
||||
qla24xx_post_newsess_work(vha, &ea->id, ea->port_name, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void qla2x00_async_gpnid_sp_done(void *s, int res)
|
||||
{
|
||||
struct srb *sp = s;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct ct_sns_req *ct_req =
|
||||
(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
|
||||
struct ct_sns_rsp *ct_rsp =
|
||||
(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
|
||||
struct event_arg ea;
|
||||
struct qla_work_evt *e;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"Async done-%s res %x ID %3phC. %8phC\n",
|
||||
sp->name, res, ct_req->req.port_id.port_id,
|
||||
ct_rsp->rsp.gpn_id.port_name);
|
||||
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
|
||||
ea.sp = sp;
|
||||
ea.id.b.domain = ct_req->req.port_id.port_id[0];
|
||||
ea.id.b.area = ct_req->req.port_id.port_id[1];
|
||||
ea.id.b.al_pa = ct_req->req.port_id.port_id[2];
|
||||
ea.rc = res;
|
||||
ea.event = FCME_GPNID_DONE;
|
||||
|
||||
qla2x00_fcport_event_handler(vha, &ea);
|
||||
|
||||
e = qla2x00_alloc_work(vha, QLA_EVT_GPNID_DONE);
|
||||
if (!e) {
|
||||
/* please ignore kernel warning. otherwise, we have mem leak. */
|
||||
if (sp->u.iocb_cmd.u.ctarg.req) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sizeof(struct ct_sns_pkt),
|
||||
sp->u.iocb_cmd.u.ctarg.req,
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.req = NULL;
|
||||
}
|
||||
if (sp->u.iocb_cmd.u.ctarg.rsp) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sizeof(struct ct_sns_pkt),
|
||||
sp->u.iocb_cmd.u.ctarg.rsp,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
|
||||
}
|
||||
|
||||
sp->free(sp);
|
||||
return;
|
||||
}
|
||||
|
||||
e->u.iosb.sp = sp;
|
||||
qla2x00_post_work(vha, e);
|
||||
}
|
||||
|
||||
/* Get WWPN with Nport ID. */
|
||||
int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
|
||||
{
|
||||
int rval = QLA_FUNCTION_FAILED;
|
||||
struct ct_sns_req *ct_req;
|
||||
srb_t *sp;
|
||||
struct ct_sns_pkt *ct_sns;
|
||||
|
||||
if (!vha->flags.online)
|
||||
goto done;
|
||||
|
||||
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
|
||||
if (!sp)
|
||||
goto done;
|
||||
|
||||
sp->type = SRB_CT_PTHRU_CMD;
|
||||
sp->name = "gpnid";
|
||||
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
|
||||
|
||||
sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
|
||||
sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
|
||||
GFP_KERNEL);
|
||||
if (!sp->u.iocb_cmd.u.ctarg.req) {
|
||||
ql_log(ql_log_warn, vha, 0xffff,
|
||||
"Failed to allocate ct_sns request.\n");
|
||||
goto done_free_sp;
|
||||
}
|
||||
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
|
||||
sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
|
||||
GFP_KERNEL);
|
||||
if (!sp->u.iocb_cmd.u.ctarg.rsp) {
|
||||
ql_log(ql_log_warn, vha, 0xffff,
|
||||
"Failed to allocate ct_sns request.\n");
|
||||
goto done_free_sp;
|
||||
}
|
||||
|
||||
ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
|
||||
memset(ct_sns, 0, sizeof(*ct_sns));
|
||||
|
||||
ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
|
||||
/* CT_IU preamble */
|
||||
ct_req = qla2x00_prep_ct_req(ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE);
|
||||
|
||||
/* GPN_ID req */
|
||||
ct_req->req.port_id.port_id[0] = id->b.domain;
|
||||
ct_req->req.port_id.port_id[1] = id->b.area;
|
||||
ct_req->req.port_id.port_id[2] = id->b.al_pa;
|
||||
|
||||
sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE;
|
||||
sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
|
||||
|
||||
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
|
||||
sp->done = qla2x00_async_gpnid_sp_done;
|
||||
|
||||
rval = qla2x00_start_sp(sp);
|
||||
if (rval != QLA_SUCCESS)
|
||||
goto done_free_sp;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"Async-%s hdl=%x ID %3phC.\n", sp->name,
|
||||
sp->handle, ct_req->req.port_id.port_id);
|
||||
return rval;
|
||||
|
||||
done_free_sp:
|
||||
if (sp->u.iocb_cmd.u.ctarg.req) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sizeof(struct ct_sns_pkt),
|
||||
sp->u.iocb_cmd.u.ctarg.req,
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.req = NULL;
|
||||
}
|
||||
if (sp->u.iocb_cmd.u.ctarg.rsp) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sizeof(struct ct_sns_pkt),
|
||||
sp->u.iocb_cmd.u.ctarg.rsp,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
|
||||
}
|
||||
|
||||
sp->free(sp);
|
||||
done:
|
||||
return rval;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -166,8 +166,8 @@ qla2x00_set_fcport_state(fc_port_t *fcport, int state)
|
|||
/* Don't print state transitions during initial allocation of fcport */
|
||||
if (old_state && old_state != state) {
|
||||
ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
|
||||
"FCPort state transitioned from %s to %s - "
|
||||
"portid=%02x%02x%02x.\n",
|
||||
"FCPort %8phC state transitioned from %s to %s - "
|
||||
"portid=%02x%02x%02x.\n", fcport->port_name,
|
||||
port_state_str[old_state], port_state_str[state],
|
||||
fcport->d_id.b.domain, fcport->d_id.b.area,
|
||||
fcport->d_id.b.al_pa);
|
||||
|
@ -232,6 +232,7 @@ qla2xxx_get_qpair_sp(struct qla_qpair *qpair, fc_port_t *fcport, gfp_t flag)
|
|||
memset(sp, 0, sizeof(*sp));
|
||||
sp->fcport = fcport;
|
||||
sp->iocbs = 1;
|
||||
sp->vha = qpair->vha;
|
||||
done:
|
||||
if (!sp)
|
||||
QLA_QPAIR_MARK_NOT_BUSY(qpair);
|
||||
|
@ -249,20 +250,20 @@ static inline srb_t *
|
|||
qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
|
||||
{
|
||||
srb_t *sp = NULL;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
uint8_t bail;
|
||||
|
||||
QLA_VHA_MARK_BUSY(vha, bail);
|
||||
if (unlikely(bail))
|
||||
return NULL;
|
||||
|
||||
sp = mempool_alloc(ha->srb_mempool, flag);
|
||||
sp = mempool_alloc(vha->hw->srb_mempool, flag);
|
||||
if (!sp)
|
||||
goto done;
|
||||
|
||||
memset(sp, 0, sizeof(*sp));
|
||||
sp->fcport = fcport;
|
||||
sp->iocbs = 1;
|
||||
sp->vha = vha;
|
||||
done:
|
||||
if (!sp)
|
||||
QLA_VHA_MARK_NOT_BUSY(vha);
|
||||
|
@ -270,10 +271,10 @@ done:
|
|||
}
|
||||
|
||||
static inline void
|
||||
qla2x00_rel_sp(scsi_qla_host_t *vha, srb_t *sp)
|
||||
qla2x00_rel_sp(srb_t *sp)
|
||||
{
|
||||
mempool_free(sp, vha->hw->srb_mempool);
|
||||
QLA_VHA_MARK_NOT_BUSY(vha);
|
||||
QLA_VHA_MARK_NOT_BUSY(sp->vha);
|
||||
mempool_free(sp, sp->vha->hw->srb_mempool);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -285,8 +286,7 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo)
|
|||
sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
|
||||
add_timer(&sp->u.iocb_cmd.timer);
|
||||
sp->free = qla2x00_sp_free;
|
||||
if ((IS_QLAFX00(sp->fcport->vha->hw)) &&
|
||||
(sp->type == SRB_FXIOCB_DCMD))
|
||||
if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD))
|
||||
init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
|
||||
if (sp->type == SRB_ELS_DCMD)
|
||||
init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
|
||||
|
|
|
@ -23,7 +23,7 @@ qla2x00_get_cmd_direction(srb_t *sp)
|
|||
{
|
||||
uint16_t cflags;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
|
||||
cflags = 0;
|
||||
|
||||
|
@ -210,7 +210,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
|
|||
return;
|
||||
}
|
||||
|
||||
vha = sp->fcport->vha;
|
||||
vha = sp->vha;
|
||||
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
|
||||
|
||||
/* Three DSDs are available in the Command Type 2 IOCB */
|
||||
|
@ -267,7 +267,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
|
|||
return;
|
||||
}
|
||||
|
||||
vha = sp->fcport->vha;
|
||||
vha = sp->vha;
|
||||
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
|
||||
|
||||
/* Two DSDs are available in the Command Type 3 IOCB */
|
||||
|
@ -324,7 +324,7 @@ qla2x00_start_scsi(srb_t *sp)
|
|||
struct rsp_que *rsp;
|
||||
|
||||
/* Setup device pointers. */
|
||||
vha = sp->fcport->vha;
|
||||
vha = sp->vha;
|
||||
ha = vha->hw;
|
||||
reg = &ha->iobase->isp;
|
||||
cmd = GET_CMD_SP(sp);
|
||||
|
@ -601,7 +601,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
vha = sp->fcport->vha;
|
||||
vha = sp->vha;
|
||||
ha = vha->hw;
|
||||
|
||||
/* Set transfer direction */
|
||||
|
@ -716,7 +716,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
|
|||
return;
|
||||
}
|
||||
|
||||
vha = sp->fcport->vha;
|
||||
vha = sp->vha;
|
||||
|
||||
/* Set transfer direction */
|
||||
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
|
||||
|
@ -1108,7 +1108,7 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
|
|||
if (sp) {
|
||||
cmd = GET_CMD_SP(sp);
|
||||
sgl = scsi_prot_sglist(cmd);
|
||||
vha = sp->fcport->vha;
|
||||
vha = sp->vha;
|
||||
} else if (tc) {
|
||||
vha = tc->vha;
|
||||
sgl = tc->prot_sg;
|
||||
|
@ -1215,7 +1215,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
|
|||
/* Update entry type to indicate Command Type CRC_2 IOCB */
|
||||
*((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_CRC_2);
|
||||
|
||||
vha = sp->fcport->vha;
|
||||
vha = sp->vha;
|
||||
ha = vha->hw;
|
||||
|
||||
/* No data transfer */
|
||||
|
@ -1225,7 +1225,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
|
|||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
|
||||
cmd_pkt->vp_index = sp->vha->vp_idx;
|
||||
|
||||
/* Set transfer direction */
|
||||
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
|
||||
|
@ -1415,7 +1415,7 @@ qla24xx_start_scsi(srb_t *sp)
|
|||
struct req_que *req = NULL;
|
||||
struct rsp_que *rsp = NULL;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
/* Setup device pointers. */
|
||||
|
@ -1492,7 +1492,7 @@ qla24xx_start_scsi(srb_t *sp)
|
|||
cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
|
||||
cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
|
||||
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
|
||||
cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
|
||||
cmd_pkt->vp_index = sp->vha->vp_idx;
|
||||
|
||||
int_to_scsilun(cmd->device->lun, &cmd_pkt->lun);
|
||||
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
|
||||
|
@ -1564,7 +1564,7 @@ qla24xx_dif_start_scsi(srb_t *sp)
|
|||
struct req_que *req = NULL;
|
||||
struct rsp_que *rsp = NULL;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct cmd_type_crc_2 *cmd_pkt;
|
||||
uint32_t status = 0;
|
||||
|
@ -2214,13 +2214,13 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio)
|
|||
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
|
||||
logio->port_id[1] = sp->fcport->d_id.b.area;
|
||||
logio->port_id[2] = sp->fcport->d_id.b.domain;
|
||||
logio->vp_index = sp->fcport->vha->vp_idx;
|
||||
logio->vp_index = sp->vha->vp_idx;
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx)
|
||||
{
|
||||
struct qla_hw_data *ha = sp->fcport->vha->hw;
|
||||
struct qla_hw_data *ha = sp->vha->hw;
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
uint16_t opts;
|
||||
|
||||
|
@ -2238,7 +2238,7 @@ qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx)
|
|||
mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain);
|
||||
mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 |
|
||||
sp->fcport->d_id.b.al_pa);
|
||||
mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx);
|
||||
mbx->mb9 = cpu_to_le16(sp->vha->vp_idx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2247,20 +2247,20 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
|
|||
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
|
||||
logio->control_flags =
|
||||
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
|
||||
if (!sp->fcport->tgt_session ||
|
||||
!sp->fcport->tgt_session->keep_nport_handle)
|
||||
if (!sp->fcport->se_sess ||
|
||||
!sp->fcport->keep_nport_handle)
|
||||
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
|
||||
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
|
||||
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
|
||||
logio->port_id[1] = sp->fcport->d_id.b.area;
|
||||
logio->port_id[2] = sp->fcport->d_id.b.domain;
|
||||
logio->vp_index = sp->fcport->vha->vp_idx;
|
||||
logio->vp_index = sp->vha->vp_idx;
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx)
|
||||
{
|
||||
struct qla_hw_data *ha = sp->fcport->vha->hw;
|
||||
struct qla_hw_data *ha = sp->vha->hw;
|
||||
|
||||
mbx->entry_type = MBX_IOCB_TYPE;
|
||||
SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
|
||||
|
@ -2271,7 +2271,7 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx)
|
|||
mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain);
|
||||
mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 |
|
||||
sp->fcport->d_id.b.al_pa);
|
||||
mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx);
|
||||
mbx->mb9 = cpu_to_le16(sp->vha->vp_idx);
|
||||
/* Implicit: mbx->mbx10 = 0. */
|
||||
}
|
||||
|
||||
|
@ -2281,13 +2281,13 @@ qla24xx_adisc_iocb(srb_t *sp, struct logio_entry_24xx *logio)
|
|||
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
|
||||
logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC);
|
||||
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
|
||||
logio->vp_index = sp->fcport->vha->vp_idx;
|
||||
logio->vp_index = sp->vha->vp_idx;
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
|
||||
{
|
||||
struct qla_hw_data *ha = sp->fcport->vha->hw;
|
||||
struct qla_hw_data *ha = sp->vha->hw;
|
||||
|
||||
mbx->entry_type = MBX_IOCB_TYPE;
|
||||
SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
|
||||
|
@ -2302,7 +2302,7 @@ qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
|
|||
mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma));
|
||||
mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma)));
|
||||
mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma)));
|
||||
mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx);
|
||||
mbx->mb9 = cpu_to_le16(sp->vha->vp_idx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2338,32 +2338,30 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
|
|||
}
|
||||
|
||||
static void
|
||||
qla2x00_els_dcmd_sp_free(void *ptr, void *data)
|
||||
qla2x00_els_dcmd_sp_free(void *data)
|
||||
{
|
||||
struct scsi_qla_host *vha = (scsi_qla_host_t *)ptr;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
srb_t *sp = (srb_t *)data;
|
||||
srb_t *sp = data;
|
||||
struct srb_iocb *elsio = &sp->u.iocb_cmd;
|
||||
|
||||
kfree(sp->fcport);
|
||||
|
||||
if (elsio->u.els_logo.els_logo_pyld)
|
||||
dma_free_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
|
||||
dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
|
||||
elsio->u.els_logo.els_logo_pyld,
|
||||
elsio->u.els_logo.els_logo_pyld_dma);
|
||||
|
||||
del_timer(&elsio->timer);
|
||||
qla2x00_rel_sp(vha, sp);
|
||||
qla2x00_rel_sp(sp);
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_els_dcmd_iocb_timeout(void *data)
|
||||
{
|
||||
srb_t *sp = (srb_t *)data;
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
srb_t *sp = data;
|
||||
fc_port_t *fcport = sp->fcport;
|
||||
struct scsi_qla_host *vha = fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
unsigned long flags = 0;
|
||||
|
||||
ql_dbg(ql_dbg_io, vha, 0x3069,
|
||||
|
@ -2386,12 +2384,12 @@ qla2x00_els_dcmd_iocb_timeout(void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
qla2x00_els_dcmd_sp_done(void *data, void *ptr, int res)
|
||||
qla2x00_els_dcmd_sp_done(void *ptr, int res)
|
||||
{
|
||||
srb_t *sp = (srb_t *)ptr;
|
||||
srb_t *sp = ptr;
|
||||
fc_port_t *fcport = sp->fcport;
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
struct scsi_qla_host *vha = fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
|
||||
ql_dbg(ql_dbg_io, vha, 0x3072,
|
||||
"%s hdl=%x, portid=%02x%02x%02x done\n",
|
||||
|
@ -2449,7 +2447,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
|
|||
GFP_KERNEL);
|
||||
|
||||
if (!elsio->u.els_logo.els_logo_pyld) {
|
||||
sp->free(vha, sp);
|
||||
sp->free(sp);
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -2468,7 +2466,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
|
|||
|
||||
rval = qla2x00_start_sp(sp);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
sp->free(vha, sp);
|
||||
sp->free(sp);
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -2479,14 +2477,14 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
|
|||
|
||||
wait_for_completion(&elsio->u.els_logo.comp);
|
||||
|
||||
sp->free(vha, sp);
|
||||
sp->free(sp);
|
||||
return rval;
|
||||
}
|
||||
|
||||
static void
|
||||
qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
|
||||
{
|
||||
scsi_qla_host_t *vha = sp->fcport->vha;
|
||||
scsi_qla_host_t *vha = sp->vha;
|
||||
struct srb_iocb *elsio = &sp->u.iocb_cmd;
|
||||
|
||||
els_iocb->entry_type = ELS_IOCB_TYPE;
|
||||
|
@ -2518,7 +2516,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
|
|||
els_iocb->rx_address[1] = 0;
|
||||
els_iocb->rx_len = 0;
|
||||
|
||||
sp->fcport->vha->qla_stats.control_requests++;
|
||||
sp->vha->qla_stats.control_requests++;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2534,7 +2532,7 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
|
|||
els_iocb->handle = sp->handle;
|
||||
els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
|
||||
els_iocb->tx_dsd_count = cpu_to_le16(bsg_job->request_payload.sg_cnt);
|
||||
els_iocb->vp_index = sp->fcport->vha->vp_idx;
|
||||
els_iocb->vp_index = sp->vha->vp_idx;
|
||||
els_iocb->sof_type = EST_SOFI3;
|
||||
els_iocb->rx_dsd_count = cpu_to_le16(bsg_job->reply_payload.sg_cnt);
|
||||
|
||||
|
@ -2565,7 +2563,7 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
|
|||
els_iocb->rx_len = cpu_to_le32(sg_dma_len
|
||||
(bsg_job->reply_payload.sg_list));
|
||||
|
||||
sp->fcport->vha->qla_stats.control_requests++;
|
||||
sp->vha->qla_stats.control_requests++;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2576,7 +2574,7 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb)
|
|||
struct scatterlist *sg;
|
||||
int index;
|
||||
uint16_t tot_dsds;
|
||||
scsi_qla_host_t *vha = sp->fcport->vha;
|
||||
scsi_qla_host_t *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct bsg_job *bsg_job = sp->u.bsg_job;
|
||||
int loop_iterartion = 0;
|
||||
|
@ -2642,7 +2640,7 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb)
|
|||
}
|
||||
ct_iocb->entry_count = entry_count;
|
||||
|
||||
sp->fcport->vha->qla_stats.control_requests++;
|
||||
sp->vha->qla_stats.control_requests++;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2653,7 +2651,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
|
|||
struct scatterlist *sg;
|
||||
int index;
|
||||
uint16_t tot_dsds;
|
||||
scsi_qla_host_t *vha = sp->fcport->vha;
|
||||
scsi_qla_host_t *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct bsg_job *bsg_job = sp->u.bsg_job;
|
||||
int loop_iterartion = 0;
|
||||
|
@ -2665,7 +2663,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
|
|||
ct_iocb->handle = sp->handle;
|
||||
|
||||
ct_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
|
||||
ct_iocb->vp_index = sp->fcport->vha->vp_idx;
|
||||
ct_iocb->vp_index = sp->vha->vp_idx;
|
||||
ct_iocb->comp_status = cpu_to_le16(0);
|
||||
|
||||
ct_iocb->cmd_dsd_count =
|
||||
|
@ -2739,7 +2737,7 @@ qla82xx_start_scsi(srb_t *sp)
|
|||
uint32_t *fcp_dl;
|
||||
uint8_t additional_cdb_len;
|
||||
struct ct6_dsd *ctx;
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct req_que *req = NULL;
|
||||
struct rsp_que *rsp = NULL;
|
||||
|
@ -2901,7 +2899,7 @@ sufficient_dsds:
|
|||
cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
|
||||
cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
|
||||
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
|
||||
cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
|
||||
cmd_pkt->vp_index = sp->vha->vp_idx;
|
||||
|
||||
/* Build IOCB segments */
|
||||
if (qla24xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds))
|
||||
|
@ -2974,7 +2972,7 @@ sufficient_dsds:
|
|||
cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
|
||||
cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
|
||||
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
|
||||
cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
|
||||
cmd_pkt->vp_index = sp->vha->vp_idx;
|
||||
|
||||
int_to_scsilun(cmd->device->lun, &cmd_pkt->lun);
|
||||
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun,
|
||||
|
@ -3060,7 +3058,7 @@ static void
|
|||
qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
|
||||
{
|
||||
struct srb_iocb *aio = &sp->u.iocb_cmd;
|
||||
scsi_qla_host_t *vha = sp->fcport->vha;
|
||||
scsi_qla_host_t *vha = sp->vha;
|
||||
struct req_que *req = vha->req;
|
||||
|
||||
memset(abt_iocb, 0, sizeof(struct abort_entry_24xx));
|
||||
|
@ -3079,19 +3077,69 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
|
|||
wmb();
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_mb_iocb(srb_t *sp, struct mbx_24xx_entry *mbx)
|
||||
{
|
||||
int i, sz;
|
||||
|
||||
mbx->entry_type = MBX_IOCB_TYPE;
|
||||
mbx->handle = sp->handle;
|
||||
sz = min(ARRAY_SIZE(mbx->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.out_mb));
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
mbx->mb[i] = cpu_to_le16(sp->u.iocb_cmd.u.mbx.out_mb[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_ctpthru_cmd_iocb(srb_t *sp, struct ct_entry_24xx *ct_pkt)
|
||||
{
|
||||
sp->u.iocb_cmd.u.ctarg.iocb = ct_pkt;
|
||||
qla24xx_prep_ms_iocb(sp->vha, &sp->u.iocb_cmd.u.ctarg);
|
||||
ct_pkt->handle = sp->handle;
|
||||
}
|
||||
|
||||
static void qla2x00_send_notify_ack_iocb(srb_t *sp,
|
||||
struct nack_to_isp *nack)
|
||||
{
|
||||
struct imm_ntfy_from_isp *ntfy = sp->u.iocb_cmd.u.nack.ntfy;
|
||||
|
||||
nack->entry_type = NOTIFY_ACK_TYPE;
|
||||
nack->entry_count = 1;
|
||||
nack->ox_id = ntfy->ox_id;
|
||||
|
||||
nack->u.isp24.handle = sp->handle;
|
||||
nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
|
||||
if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
|
||||
nack->u.isp24.flags = ntfy->u.isp24.flags &
|
||||
cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
|
||||
}
|
||||
nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
|
||||
nack->u.isp24.status = ntfy->u.isp24.status;
|
||||
nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
|
||||
nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
|
||||
nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
|
||||
nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
|
||||
nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
|
||||
nack->u.isp24.srr_flags = 0;
|
||||
nack->u.isp24.srr_reject_code = 0;
|
||||
nack->u.isp24.srr_reject_code_expl = 0;
|
||||
nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
|
||||
}
|
||||
|
||||
int
|
||||
qla2x00_start_sp(srb_t *sp)
|
||||
{
|
||||
int rval;
|
||||
struct qla_hw_data *ha = sp->fcport->vha->hw;
|
||||
scsi_qla_host_t *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
void *pkt;
|
||||
unsigned long flags;
|
||||
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp);
|
||||
pkt = qla2x00_alloc_iocbs(vha, sp);
|
||||
if (!pkt) {
|
||||
ql_log(ql_log_warn, sp->fcport->vha, 0x700c,
|
||||
ql_log(ql_log_warn, vha, 0x700c,
|
||||
"qla2x00_alloc_iocbs failed.\n");
|
||||
goto done;
|
||||
}
|
||||
|
@ -3139,12 +3187,23 @@ qla2x00_start_sp(srb_t *sp)
|
|||
case SRB_ELS_DCMD:
|
||||
qla24xx_els_logo_iocb(sp, pkt);
|
||||
break;
|
||||
case SRB_CT_PTHRU_CMD:
|
||||
qla2x00_ctpthru_cmd_iocb(sp, pkt);
|
||||
break;
|
||||
case SRB_MB_IOCB:
|
||||
qla2x00_mb_iocb(sp, pkt);
|
||||
break;
|
||||
case SRB_NACK_PLOGI:
|
||||
case SRB_NACK_PRLI:
|
||||
case SRB_NACK_LOGO:
|
||||
qla2x00_send_notify_ack_iocb(sp, pkt);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
wmb();
|
||||
qla2x00_start_iocbs(sp->fcport->vha, ha->req_q_map[0]);
|
||||
qla2x00_start_iocbs(vha, ha->req_q_map[0]);
|
||||
done:
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
return rval;
|
||||
|
|
|
@ -561,14 +561,50 @@ qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline fc_port_t *
|
||||
fc_port_t *
|
||||
qla2x00_find_fcport_by_loopid(scsi_qla_host_t *vha, uint16_t loop_id)
|
||||
{
|
||||
fc_port_t *fcport;
|
||||
fc_port_t *f, *tf;
|
||||
|
||||
list_for_each_entry(fcport, &vha->vp_fcports, list)
|
||||
if (fcport->loop_id == loop_id)
|
||||
return fcport;
|
||||
f = tf = NULL;
|
||||
list_for_each_entry_safe(f, tf, &vha->vp_fcports, list)
|
||||
if (f->loop_id == loop_id)
|
||||
return f;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fc_port_t *
|
||||
qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *vha, u8 *wwpn, u8 incl_deleted)
|
||||
{
|
||||
fc_port_t *f, *tf;
|
||||
|
||||
f = tf = NULL;
|
||||
list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
|
||||
if (memcmp(f->port_name, wwpn, WWN_SIZE) == 0) {
|
||||
if (incl_deleted)
|
||||
return f;
|
||||
else if (f->deleted == 0)
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fc_port_t *
|
||||
qla2x00_find_fcport_by_nportid(scsi_qla_host_t *vha, port_id_t *id,
|
||||
u8 incl_deleted)
|
||||
{
|
||||
fc_port_t *f, *tf;
|
||||
|
||||
f = tf = NULL;
|
||||
list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
|
||||
if (f->d_id.b24 == id->b24) {
|
||||
if (incl_deleted)
|
||||
return f;
|
||||
else if (f->deleted == 0)
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -934,7 +970,11 @@ skip_rio:
|
|||
ql_dbg(ql_dbg_async, vha, 0x508a,
|
||||
"Marking port lost loopid=%04x portid=%06x.\n",
|
||||
fcport->loop_id, fcport->d_id.b24);
|
||||
if (qla_ini_mode_enabled(vha)) {
|
||||
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
|
||||
fcport->logout_on_delete = 0;
|
||||
qlt_schedule_sess_for_deletion_lock(fcport);
|
||||
}
|
||||
break;
|
||||
|
||||
global_port_update:
|
||||
|
@ -985,9 +1025,6 @@ global_port_update:
|
|||
|
||||
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);
|
||||
set_bit(VP_CONFIG_OK, &vha->vp_flags);
|
||||
|
@ -1024,27 +1061,19 @@ global_port_update:
|
|||
if (qla2x00_is_a_vp_did(vha, rscn_entry))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Search for the rport related to this RSCN entry and mark it
|
||||
* as lost.
|
||||
*/
|
||||
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
||||
if (atomic_read(&fcport->state) != FCS_ONLINE)
|
||||
continue;
|
||||
if (fcport->d_id.b24 == rscn_entry) {
|
||||
qla2x00_mark_device_lost(vha, fcport, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
atomic_set(&vha->loop_down_timer, 0);
|
||||
vha->flags.management_server_logged_in = 0;
|
||||
{
|
||||
struct event_arg ea;
|
||||
|
||||
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
|
||||
set_bit(RSCN_UPDATE, &vha->dpc_flags);
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.event = FCME_RSCN;
|
||||
ea.id.b24 = rscn_entry;
|
||||
ea.id.b.rsvd_1 = rscn_entry >> 24;
|
||||
qla2x00_fcport_event_handler(vha, &ea);
|
||||
qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
|
||||
}
|
||||
break;
|
||||
|
||||
/* case MBA_RIO_RESPONSE: */
|
||||
case MBA_ZIO_RESPONSE:
|
||||
ql_dbg(ql_dbg_async, vha, 0x5015,
|
||||
|
@ -1212,7 +1241,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
|
|||
req->outstanding_cmds[index] = NULL;
|
||||
|
||||
/* Save ISP completion status */
|
||||
sp->done(ha, sp, DID_OK << 16);
|
||||
sp->done(sp, DID_OK << 16);
|
||||
} else {
|
||||
ql_log(ql_log_warn, vha, 0x3016, "Invalid SCSI SRB.\n");
|
||||
|
||||
|
@ -1235,7 +1264,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
|
|||
index = LSW(pkt->handle);
|
||||
if (index >= req->num_outstanding_cmds) {
|
||||
ql_log(ql_log_warn, vha, 0x5031,
|
||||
"Invalid command index (%x).\n", index);
|
||||
"Invalid command index (%x) type %8ph.\n",
|
||||
index, iocb);
|
||||
if (IS_P3P_TYPE(ha))
|
||||
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
|
||||
else
|
||||
|
@ -1343,7 +1373,50 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
le16_to_cpu(mbx->mb7));
|
||||
|
||||
logio_done:
|
||||
sp->done(vha, sp, 0);
|
||||
sp->done(sp, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
qla24xx_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||
struct mbx_24xx_entry *pkt)
|
||||
{
|
||||
const char func[] = "MBX-IOCB2";
|
||||
srb_t *sp;
|
||||
struct srb_iocb *si;
|
||||
u16 sz, i;
|
||||
int res;
|
||||
|
||||
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
|
||||
if (!sp)
|
||||
return;
|
||||
|
||||
si = &sp->u.iocb_cmd;
|
||||
sz = min(ARRAY_SIZE(pkt->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.in_mb));
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
si->u.mbx.in_mb[i] = le16_to_cpu(pkt->mb[i]);
|
||||
|
||||
res = (si->u.mbx.in_mb[0] & MBS_MASK);
|
||||
|
||||
sp->done(sp, res);
|
||||
}
|
||||
|
||||
static void
|
||||
qla24xxx_nack_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||
struct nack_to_isp *pkt)
|
||||
{
|
||||
const char func[] = "nack";
|
||||
srb_t *sp;
|
||||
int res = 0;
|
||||
|
||||
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
|
||||
if (!sp)
|
||||
return;
|
||||
|
||||
if (pkt->u.isp2x.status != cpu_to_le16(NOTIFY_ACK_SUCCESS))
|
||||
res = QLA_FUNCTION_FAILED;
|
||||
|
||||
sp->done(sp, res);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1356,12 +1429,14 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
struct bsg_job *bsg_job;
|
||||
struct fc_bsg_reply *bsg_reply;
|
||||
uint16_t comp_status;
|
||||
int res;
|
||||
int res = 0;
|
||||
|
||||
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
|
||||
if (!sp)
|
||||
return;
|
||||
|
||||
switch (sp->type) {
|
||||
case SRB_CT_CMD:
|
||||
bsg_job = sp->u.bsg_job;
|
||||
bsg_reply = bsg_job->reply;
|
||||
|
||||
|
@ -1369,7 +1444,8 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
|
||||
comp_status = le16_to_cpu(pkt->comp_status);
|
||||
|
||||
/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
|
||||
/*
|
||||
* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
|
||||
* fc payload to the caller
|
||||
*/
|
||||
bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
|
||||
|
@ -1382,14 +1458,13 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
|
||||
|
||||
ql_log(ql_log_warn, vha, 0x5048,
|
||||
"CT pass-through-%s error "
|
||||
"comp_status-status=0x%x total_byte = 0x%x.\n",
|
||||
"CT pass-through-%s error comp_status=0x%x total_byte=0x%x.\n",
|
||||
type, comp_status,
|
||||
bsg_reply->reply_payload_rcv_len);
|
||||
} else {
|
||||
ql_log(ql_log_warn, vha, 0x5049,
|
||||
"CT pass-through-%s error "
|
||||
"comp_status-status=0x%x.\n", type, comp_status);
|
||||
"CT pass-through-%s error comp_status=0x%x.\n",
|
||||
type, comp_status);
|
||||
res = DID_ERROR << 16;
|
||||
bsg_reply->reply_payload_rcv_len = 0;
|
||||
}
|
||||
|
@ -1401,8 +1476,19 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
bsg_job->reply_payload.payload_len;
|
||||
bsg_job->reply_len = 0;
|
||||
}
|
||||
break;
|
||||
case SRB_CT_PTHRU_CMD:
|
||||
/*
|
||||
* borrowing sts_entry_24xx.comp_status.
|
||||
* same location as ct_entry_24xx.comp_status
|
||||
*/
|
||||
res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
|
||||
(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
|
||||
sp->name);
|
||||
break;
|
||||
}
|
||||
|
||||
sp->done(vha, sp, res);
|
||||
sp->done(sp, res);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1438,7 +1524,16 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
type = "Driver ELS logo";
|
||||
ql_dbg(ql_dbg_user, vha, 0x5047,
|
||||
"Completing %s: (%p) type=%d.\n", type, sp, sp->type);
|
||||
sp->done(vha, sp, 0);
|
||||
sp->done(sp, 0);
|
||||
return;
|
||||
case SRB_CT_PTHRU_CMD:
|
||||
/* borrowing sts_entry_24xx.comp_status.
|
||||
same location as ct_entry_24xx.comp_status
|
||||
*/
|
||||
res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
|
||||
(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
|
||||
sp->name);
|
||||
sp->done(sp, res);
|
||||
return;
|
||||
default:
|
||||
ql_dbg(ql_dbg_user, vha, 0x503e,
|
||||
|
@ -1496,7 +1591,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
bsg_job->reply_len = 0;
|
||||
}
|
||||
|
||||
sp->done(vha, sp, res);
|
||||
sp->done(sp, res);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1543,6 +1638,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
fcport->d_id.b.area, fcport->d_id.b.al_pa,
|
||||
le32_to_cpu(logio->io_parameter[0]));
|
||||
|
||||
vha->hw->exch_starvation = 0;
|
||||
data[0] = MBS_COMMAND_COMPLETE;
|
||||
if (sp->type != SRB_LOGIN_CMD)
|
||||
goto logio_done;
|
||||
|
@ -1568,6 +1664,8 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
|
||||
iop[0] = le32_to_cpu(logio->io_parameter[0]);
|
||||
iop[1] = le32_to_cpu(logio->io_parameter[1]);
|
||||
lio->u.logio.iop[0] = iop[0];
|
||||
lio->u.logio.iop[1] = iop[1];
|
||||
switch (iop[0]) {
|
||||
case LSC_SCODE_PORTID_USED:
|
||||
data[0] = MBS_PORT_ID_USED;
|
||||
|
@ -1576,6 +1674,21 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
case LSC_SCODE_NPORT_USED:
|
||||
data[0] = MBS_LOOP_ID_USED;
|
||||
break;
|
||||
case LSC_SCODE_NOXCB:
|
||||
vha->hw->exch_starvation++;
|
||||
if (vha->hw->exch_starvation > 5) {
|
||||
ql_log(ql_log_warn, vha, 0xffff,
|
||||
"Exchange starvation. Resetting RISC\n");
|
||||
|
||||
vha->hw->exch_starvation = 0;
|
||||
|
||||
if (IS_P3P_TYPE(vha->hw))
|
||||
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
|
||||
else
|
||||
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(vha);
|
||||
}
|
||||
/* drop through */
|
||||
default:
|
||||
data[0] = MBS_COMMAND_ERROR;
|
||||
break;
|
||||
|
@ -1590,7 +1703,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
le32_to_cpu(logio->io_parameter[1]));
|
||||
|
||||
logio_done:
|
||||
sp->done(vha, sp, 0);
|
||||
sp->done(sp, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1640,7 +1753,7 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
|
|||
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055,
|
||||
(uint8_t *)sts, sizeof(*sts));
|
||||
|
||||
sp->done(vha, sp, 0);
|
||||
sp->done(sp, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1728,7 +1841,7 @@ static inline void
|
|||
qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
|
||||
uint32_t sense_len, struct rsp_que *rsp, int res)
|
||||
{
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct scsi_cmnd *cp = GET_CMD_SP(sp);
|
||||
uint32_t track_sense_len;
|
||||
|
||||
|
@ -1756,7 +1869,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
|
|||
if (sense_len) {
|
||||
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x301c,
|
||||
"Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
|
||||
sp->fcport->vha->host_no, cp->device->id, cp->device->lun,
|
||||
sp->vha->host_no, cp->device->id, cp->device->lun,
|
||||
cp);
|
||||
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b,
|
||||
cp->sense_buffer, sense_len);
|
||||
|
@ -1778,7 +1891,7 @@ struct scsi_dif_tuple {
|
|||
static inline int
|
||||
qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
|
||||
{
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
uint8_t *ap = &sts24->data[12];
|
||||
uint8_t *ep = &sts24->data[20];
|
||||
|
@ -2043,7 +2156,7 @@ done:
|
|||
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
|
||||
/* Always return DID_OK, bsg will send the vendor specific response
|
||||
* in this case only */
|
||||
sp->done(vha, sp, (DID_OK << 6));
|
||||
sp->done(sp, DID_OK << 6);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2076,6 +2189,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
|
|||
int res = 0;
|
||||
uint16_t state_flags = 0;
|
||||
uint16_t retry_delay = 0;
|
||||
uint8_t no_logout = 0;
|
||||
|
||||
sts = (sts_entry_t *) pkt;
|
||||
sts24 = (struct sts_entry_24xx *) pkt;
|
||||
|
@ -2336,6 +2450,7 @@ check_scsi_status:
|
|||
break;
|
||||
|
||||
case CS_PORT_LOGGED_OUT:
|
||||
no_logout = 1;
|
||||
case CS_PORT_CONFIG_CHG:
|
||||
case CS_PORT_BUSY:
|
||||
case CS_INCOMPLETE:
|
||||
|
@ -2358,14 +2473,21 @@ check_scsi_status:
|
|||
break;
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_io, fcport->vha, 0x3021,
|
||||
if (atomic_read(&fcport->state) == FCS_ONLINE) {
|
||||
ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
|
||||
"Port to be marked lost on fcport=%02x%02x%02x, current "
|
||||
"port state= %s.\n", fcport->d_id.b.domain,
|
||||
"port state= %s comp_status %x.\n", fcport->d_id.b.domain,
|
||||
fcport->d_id.b.area, fcport->d_id.b.al_pa,
|
||||
port_state_str[atomic_read(&fcport->state)]);
|
||||
port_state_str[atomic_read(&fcport->state)],
|
||||
comp_status);
|
||||
|
||||
if (no_logout)
|
||||
fcport->logout_on_delete = 0;
|
||||
|
||||
if (atomic_read(&fcport->state) == FCS_ONLINE)
|
||||
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
|
||||
qlt_schedule_sess_for_deletion_lock(fcport);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CS_ABORTED:
|
||||
|
@ -2407,7 +2529,7 @@ out:
|
|||
resid_len, fw_resid_len, sp, cp);
|
||||
|
||||
if (rsp->status_srb == NULL)
|
||||
sp->done(ha, sp, res);
|
||||
sp->done(sp, res);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2464,7 +2586,7 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
|
|||
/* Place command on done queue. */
|
||||
if (sense_len == 0) {
|
||||
rsp->status_srb = NULL;
|
||||
sp->done(ha, sp, cp->result);
|
||||
sp->done(sp, cp->result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2500,7 +2622,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
|
|||
|
||||
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
|
||||
if (sp) {
|
||||
sp->done(ha, sp, res);
|
||||
sp->done(sp, res);
|
||||
return;
|
||||
}
|
||||
fatal:
|
||||
|
@ -2558,7 +2680,7 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
|
||||
abt = &sp->u.iocb_cmd;
|
||||
abt->u.abt.comp_status = le32_to_cpu(pkt->nport_handle);
|
||||
sp->done(vha, sp, 0);
|
||||
sp->done(sp, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2629,10 +2751,16 @@ process_err:
|
|||
}
|
||||
case ABTS_RESP_24XX:
|
||||
case CTIO_TYPE7:
|
||||
case NOTIFY_ACK_TYPE:
|
||||
case CTIO_CRC2:
|
||||
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
|
||||
break;
|
||||
case NOTIFY_ACK_TYPE:
|
||||
if (pkt->handle == QLA_TGT_SKIP_HANDLE)
|
||||
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
|
||||
else
|
||||
qla24xxx_nack_iocb_entry(vha, rsp->req,
|
||||
(struct nack_to_isp *)pkt);
|
||||
break;
|
||||
case MARKER_TYPE:
|
||||
/* Do nothing in this case, this check is to prevent it
|
||||
* from falling into default case
|
||||
|
@ -2642,6 +2770,10 @@ process_err:
|
|||
qla24xx_abort_iocb_entry(vha, rsp->req,
|
||||
(struct abort_entry_24xx *)pkt);
|
||||
break;
|
||||
case MBX_IOCB_TYPE:
|
||||
qla24xx_mbx_iocb_entry(vha, rsp->req,
|
||||
(struct mbx_24xx_entry *)pkt);
|
||||
break;
|
||||
default:
|
||||
/* Type Not Supported. */
|
||||
ql_dbg(ql_dbg_async, vha, 0x5042,
|
||||
|
@ -2658,9 +2790,10 @@ process_err:
|
|||
if (IS_P3P_TYPE(ha)) {
|
||||
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
|
||||
WRT_REG_DWORD(®->rsp_q_out[0], rsp->ring_index);
|
||||
} else
|
||||
} else {
|
||||
WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
qla2xxx_check_risc_status(scsi_qla_host_t *vha)
|
||||
|
|
|
@ -1637,94 +1637,6 @@ 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 = kmemdup(pmap, 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;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -3687,10 +3599,8 @@ void
|
|||
qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
|
||||
struct vp_rpt_id_entry_24xx *rptid_entry)
|
||||
{
|
||||
uint8_t vp_idx;
|
||||
uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
scsi_qla_host_t *vp;
|
||||
scsi_qla_host_t *vp = NULL;
|
||||
unsigned long flags;
|
||||
int found;
|
||||
|
||||
|
@ -3701,56 +3611,80 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
|
|||
return;
|
||||
|
||||
if (rptid_entry->format == 0) {
|
||||
/* loop */
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7,
|
||||
"Format 0 : Number of VPs setup %d, number of "
|
||||
"VPs acquired %d.\n",
|
||||
MSB(le16_to_cpu(rptid_entry->vp_count)),
|
||||
LSB(le16_to_cpu(rptid_entry->vp_count)));
|
||||
"VPs acquired %d.\n", rptid_entry->vp_setup,
|
||||
rptid_entry->vp_acquired);
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b8,
|
||||
"Primary port id %02x%02x%02x.\n",
|
||||
rptid_entry->port_id[2], rptid_entry->port_id[1],
|
||||
rptid_entry->port_id[0]);
|
||||
|
||||
vha->d_id.b.domain = rptid_entry->port_id[2];
|
||||
vha->d_id.b.area = rptid_entry->port_id[1];
|
||||
vha->d_id.b.al_pa = rptid_entry->port_id[0];
|
||||
|
||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||
qlt_update_vp_map(vha, SET_AL_PA);
|
||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||
|
||||
} else if (rptid_entry->format == 1) {
|
||||
vp_idx = LSB(stat);
|
||||
/* fabric */
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b9,
|
||||
"Format 1: VP[%d] enabled - status %d - with "
|
||||
"port id %02x%02x%02x.\n", vp_idx, MSB(stat),
|
||||
"port id %02x%02x%02x.\n", rptid_entry->vp_idx,
|
||||
rptid_entry->vp_status,
|
||||
rptid_entry->port_id[2], rptid_entry->port_id[1],
|
||||
rptid_entry->port_id[0]);
|
||||
|
||||
/* buffer to buffer credit flag */
|
||||
vha->flags.bbcr_enable = (rptid_entry->bbcr & 0xf) != 0;
|
||||
vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
|
||||
|
||||
if (rptid_entry->vp_idx == 0) {
|
||||
if (rptid_entry->vp_status == VP_STAT_COMPL) {
|
||||
/* FA-WWN is only for physical port */
|
||||
if (!vp_idx) {
|
||||
void *wwpn = ha->init_cb->port_name;
|
||||
|
||||
if (!MSB(stat)) {
|
||||
if (rptid_entry->vp_idx_map[1] & BIT_6)
|
||||
wwpn = rptid_entry->reserved_4 + 8;
|
||||
if (qla_ini_mode_enabled(vha) &&
|
||||
ha->flags.fawwpn_enabled &&
|
||||
(rptid_entry->u.f1.flags &
|
||||
VP_FLAGS_NAME_VALID)) {
|
||||
memcpy(vha->port_name,
|
||||
rptid_entry->u.f1.port_name,
|
||||
WWN_SIZE);
|
||||
}
|
||||
memcpy(vha->port_name, wwpn, WWN_SIZE);
|
||||
|
||||
vha->d_id.b.domain = rptid_entry->port_id[2];
|
||||
vha->d_id.b.area = rptid_entry->port_id[1];
|
||||
vha->d_id.b.al_pa = rptid_entry->port_id[0];
|
||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||
qlt_update_vp_map(vha, SET_AL_PA);
|
||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||
}
|
||||
|
||||
fc_host_port_name(vha->host) =
|
||||
wwn_to_u64(vha->port_name);
|
||||
|
||||
if (qla_ini_mode_enabled(vha))
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x1018,
|
||||
"FA-WWN portname %016llx (%x)\n",
|
||||
fc_host_port_name(vha->host), MSB(stat));
|
||||
}
|
||||
fc_host_port_name(vha->host),
|
||||
rptid_entry->vp_status);
|
||||
|
||||
vp = vha;
|
||||
if (vp_idx == 0)
|
||||
goto reg_needed;
|
||||
|
||||
if (MSB(stat) != 0 && MSB(stat) != 2) {
|
||||
set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
|
||||
set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
|
||||
} else {
|
||||
if (rptid_entry->vp_status != VP_STAT_COMPL &&
|
||||
rptid_entry->vp_status != VP_STAT_ID_CHG) {
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x10ba,
|
||||
"Could not acquire ID for VP[%d].\n", vp_idx);
|
||||
"Could not acquire ID for VP[%d].\n",
|
||||
rptid_entry->vp_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
found = 0;
|
||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||
list_for_each_entry(vp, &ha->vp_list, list) {
|
||||
if (vp_idx == vp->vp_idx) {
|
||||
if (rptid_entry->vp_idx == vp->vp_idx) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -3763,18 +3697,38 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
|
|||
vp->d_id.b.domain = rptid_entry->port_id[2];
|
||||
vp->d_id.b.area = rptid_entry->port_id[1];
|
||||
vp->d_id.b.al_pa = rptid_entry->port_id[0];
|
||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||
qlt_update_vp_map(vp, SET_AL_PA);
|
||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||
|
||||
/*
|
||||
* Cannot configure here as we are still sitting on the
|
||||
* response queue. Handle it in dpc context.
|
||||
*/
|
||||
set_bit(VP_IDX_ACQUIRED, &vp->vp_flags);
|
||||
|
||||
reg_needed:
|
||||
set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags);
|
||||
set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags);
|
||||
}
|
||||
set_bit(VP_DPC_NEEDED, &vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(vha);
|
||||
} else if (rptid_entry->format == 2) {
|
||||
ql_dbg(ql_dbg_async, vha, 0xffff,
|
||||
"RIDA: format 2/N2N Primary port id %02x%02x%02x.\n",
|
||||
rptid_entry->port_id[2], rptid_entry->port_id[1],
|
||||
rptid_entry->port_id[0]);
|
||||
|
||||
ql_dbg(ql_dbg_async, vha, 0xffff,
|
||||
"N2N: Remote WWPN %8phC.\n",
|
||||
rptid_entry->u.f2.port_name);
|
||||
|
||||
/* N2N. direct connect */
|
||||
vha->d_id.b.domain = rptid_entry->port_id[2];
|
||||
vha->d_id.b.area = rptid_entry->port_id[1];
|
||||
vha->d_id.b.al_pa = rptid_entry->port_id[0];
|
||||
|
||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||
qlt_update_vp_map(vha, SET_AL_PA);
|
||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1789,16 +1789,16 @@ qlafx00_update_host_attr(scsi_qla_host_t *vha, struct port_info_data *pinfo)
|
|||
static void
|
||||
qla2x00_fxdisc_iocb_timeout(void *data)
|
||||
{
|
||||
srb_t *sp = (srb_t *)data;
|
||||
srb_t *sp = data;
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
|
||||
complete(&lio->u.fxiocb.fxiocb_comp);
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_fxdisc_sp_done(void *data, void *ptr, int res)
|
||||
qla2x00_fxdisc_sp_done(void *ptr, int res)
|
||||
{
|
||||
srb_t *sp = (srb_t *)ptr;
|
||||
srb_t *sp = ptr;
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
|
||||
complete(&lio->u.fxiocb.fxiocb_comp);
|
||||
|
@ -1999,7 +1999,7 @@ done_unmap_req:
|
|||
dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
|
||||
fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
|
||||
done_free_sp:
|
||||
sp->free(vha, sp);
|
||||
sp->free(sp);
|
||||
done:
|
||||
return rval;
|
||||
}
|
||||
|
@ -2127,7 +2127,7 @@ static inline void
|
|||
qlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
|
||||
uint32_t sense_len, struct rsp_que *rsp, int res)
|
||||
{
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct scsi_cmnd *cp = GET_CMD_SP(sp);
|
||||
uint32_t track_sense_len;
|
||||
|
||||
|
@ -2162,7 +2162,7 @@ qlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
|
|||
if (sense_len) {
|
||||
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3039,
|
||||
"Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
|
||||
sp->fcport->vha->host_no, cp->device->id, cp->device->lun,
|
||||
sp->vha->host_no, cp->device->id, cp->device->lun,
|
||||
cp);
|
||||
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3049,
|
||||
cp->sense_buffer, sense_len);
|
||||
|
@ -2181,7 +2181,7 @@ qlafx00_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
(sstatus & cpu_to_le16((uint16_t)SS_RESPONSE_INFO_LEN_VALID)))
|
||||
cpstatus = cpu_to_le16((uint16_t)CS_INCOMPLETE);
|
||||
tmf->u.tmf.comp_status = cpstatus;
|
||||
sp->done(vha, sp, 0);
|
||||
sp->done(sp, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2198,7 +2198,7 @@ qlafx00_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
|
||||
abt = &sp->u.iocb_cmd;
|
||||
abt->u.abt.comp_status = pkt->tgt_id_sts;
|
||||
sp->done(vha, sp, 0);
|
||||
sp->done(sp, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2264,7 +2264,7 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
bsg_reply->reply_payload_rcv_len =
|
||||
bsg_job->reply_payload.payload_len;
|
||||
}
|
||||
sp->done(vha, sp, res);
|
||||
sp->done(sp, res);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2537,7 +2537,7 @@ check_scsi_status:
|
|||
par_sense_len, rsp_info_len);
|
||||
|
||||
if (rsp->status_srb == NULL)
|
||||
sp->done(ha, sp, res);
|
||||
sp->done(sp, res);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2614,7 +2614,7 @@ qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
|
|||
/* Place command on done queue. */
|
||||
if (sense_len == 0) {
|
||||
rsp->status_srb = NULL;
|
||||
sp->done(ha, sp, cp->result);
|
||||
sp->done(sp, cp->result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2695,7 +2695,7 @@ qlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp,
|
|||
|
||||
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
|
||||
if (sp) {
|
||||
sp->done(ha, sp, res);
|
||||
sp->done(sp, res);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2997,7 +2997,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt,
|
|||
cont_a64_entry_t lcont_pkt;
|
||||
cont_a64_entry_t *cont_pkt;
|
||||
|
||||
vha = sp->fcport->vha;
|
||||
vha = sp->vha;
|
||||
req = vha->req;
|
||||
|
||||
cmd = GET_CMD_SP(sp);
|
||||
|
@ -3081,7 +3081,7 @@ qlafx00_start_scsi(srb_t *sp)
|
|||
struct req_que *req = NULL;
|
||||
struct rsp_que *rsp = NULL;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
struct scsi_qla_host *vha = sp->fcport->vha;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct cmd_type_7_fx00 *cmd_pkt;
|
||||
struct cmd_type_7_fx00 lcmd_pkt;
|
||||
|
@ -3205,7 +3205,7 @@ void
|
|||
qlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb)
|
||||
{
|
||||
struct srb_iocb *fxio = &sp->u.iocb_cmd;
|
||||
scsi_qla_host_t *vha = sp->fcport->vha;
|
||||
scsi_qla_host_t *vha = sp->vha;
|
||||
struct req_que *req = vha->req;
|
||||
struct tsk_mgmt_entry_fx00 tm_iocb;
|
||||
struct scsi_lun llun;
|
||||
|
@ -3232,7 +3232,7 @@ void
|
|||
qlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb)
|
||||
{
|
||||
struct srb_iocb *fxio = &sp->u.iocb_cmd;
|
||||
scsi_qla_host_t *vha = sp->fcport->vha;
|
||||
scsi_qla_host_t *vha = sp->vha;
|
||||
struct req_que *req = vha->req;
|
||||
struct abort_iocb_entry_fx00 abt_iocb;
|
||||
|
||||
|
@ -3346,8 +3346,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
|
|||
REQUEST_ENTRY_SIZE);
|
||||
cont_pkt =
|
||||
qlafx00_prep_cont_type1_iocb(
|
||||
sp->fcport->vha->req,
|
||||
&lcont_pkt);
|
||||
sp->vha->req, &lcont_pkt);
|
||||
cur_dsd = (__le32 *)
|
||||
lcont_pkt.dseg_0_address;
|
||||
avail_dsds = 5;
|
||||
|
@ -3368,7 +3367,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
|
|||
&lcont_pkt, REQUEST_ENTRY_SIZE);
|
||||
ql_dump_buffer(
|
||||
ql_dbg_user + ql_dbg_verbose,
|
||||
sp->fcport->vha, 0x3042,
|
||||
sp->vha, 0x3042,
|
||||
(uint8_t *)&lcont_pkt,
|
||||
REQUEST_ENTRY_SIZE);
|
||||
}
|
||||
|
@ -3377,7 +3376,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
|
|||
memcpy_toio((void __iomem *)cont_pkt,
|
||||
&lcont_pkt, REQUEST_ENTRY_SIZE);
|
||||
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
|
||||
sp->fcport->vha, 0x3043,
|
||||
sp->vha, 0x3043,
|
||||
(uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE);
|
||||
}
|
||||
}
|
||||
|
@ -3409,8 +3408,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
|
|||
REQUEST_ENTRY_SIZE);
|
||||
cont_pkt =
|
||||
qlafx00_prep_cont_type1_iocb(
|
||||
sp->fcport->vha->req,
|
||||
&lcont_pkt);
|
||||
sp->vha->req, &lcont_pkt);
|
||||
cur_dsd = (__le32 *)
|
||||
lcont_pkt.dseg_0_address;
|
||||
avail_dsds = 5;
|
||||
|
@ -3431,7 +3429,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
|
|||
REQUEST_ENTRY_SIZE);
|
||||
ql_dump_buffer(
|
||||
ql_dbg_user + ql_dbg_verbose,
|
||||
sp->fcport->vha, 0x3045,
|
||||
sp->vha, 0x3045,
|
||||
(uint8_t *)&lcont_pkt,
|
||||
REQUEST_ENTRY_SIZE);
|
||||
}
|
||||
|
@ -3440,7 +3438,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
|
|||
memcpy_toio((void __iomem *)cont_pkt,
|
||||
&lcont_pkt, REQUEST_ENTRY_SIZE);
|
||||
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
|
||||
sp->fcport->vha, 0x3046,
|
||||
sp->vha, 0x3046,
|
||||
(uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE);
|
||||
}
|
||||
}
|
||||
|
@ -3452,7 +3450,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
|
|||
}
|
||||
|
||||
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
|
||||
sp->fcport->vha, 0x3047,
|
||||
sp->vha, 0x3047,
|
||||
(uint8_t *)&fx_iocb, sizeof(struct fxdisc_entry_fx00));
|
||||
|
||||
memcpy_toio((void __iomem *)pfxiocb, &fx_iocb,
|
||||
|
|
|
@ -237,6 +237,13 @@ MODULE_PARM_DESC(ql2xfwholdabts,
|
|||
"0 (Default) Do not set fw option. "
|
||||
"1 - Set fw option to hold ABTS.");
|
||||
|
||||
int ql2xmvasynctoatio = 1;
|
||||
module_param(ql2xmvasynctoatio, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(ql2xmvasynctoatio,
|
||||
"Move PUREX, ABTS RX and RIDA IOCBs to ATIOQ"
|
||||
"0 (Default). Do not move IOCBs"
|
||||
"1 - Move IOCBs.");
|
||||
|
||||
/*
|
||||
* SCSI host template entry points
|
||||
*/
|
||||
|
@ -607,11 +614,11 @@ qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size)
|
|||
}
|
||||
|
||||
void
|
||||
qla2x00_sp_free_dma(void *vha, void *ptr)
|
||||
qla2x00_sp_free_dma(void *ptr)
|
||||
{
|
||||
srb_t *sp = (srb_t *)ptr;
|
||||
srb_t *sp = ptr;
|
||||
struct qla_hw_data *ha = sp->vha->hw;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
struct qla_hw_data *ha = sp->fcport->vha->hw;
|
||||
void *ctx = GET_CMD_CTX_SP(sp);
|
||||
|
||||
if (sp->flags & SRB_DMA_VALID) {
|
||||
|
@ -650,20 +657,19 @@ qla2x00_sp_free_dma(void *vha, void *ptr)
|
|||
}
|
||||
|
||||
CMD_SP(cmd) = NULL;
|
||||
qla2x00_rel_sp(sp->fcport->vha, sp);
|
||||
qla2x00_rel_sp(sp);
|
||||
}
|
||||
|
||||
void
|
||||
qla2x00_sp_compl(void *data, void *ptr, int res)
|
||||
qla2x00_sp_compl(void *ptr, int res)
|
||||
{
|
||||
struct qla_hw_data *ha = (struct qla_hw_data *)data;
|
||||
srb_t *sp = (srb_t *)ptr;
|
||||
srb_t *sp = ptr;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
|
||||
cmd->result = res;
|
||||
|
||||
if (atomic_read(&sp->ref_count) == 0) {
|
||||
ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015,
|
||||
ql_dbg(ql_dbg_io, sp->vha, 0x3015,
|
||||
"SP reference-count to ZERO -- sp=%p cmd=%p.\n",
|
||||
sp, GET_CMD_SP(sp));
|
||||
if (ql2xextended_error_logging & ql_dbg_io)
|
||||
|
@ -673,12 +679,12 @@ qla2x00_sp_compl(void *data, void *ptr, int res)
|
|||
if (!atomic_dec_and_test(&sp->ref_count))
|
||||
return;
|
||||
|
||||
qla2x00_sp_free_dma(ha, sp);
|
||||
qla2x00_sp_free_dma(sp);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
void
|
||||
qla2xxx_qpair_sp_free_dma(void *vha, void *ptr)
|
||||
qla2xxx_qpair_sp_free_dma(void *ptr)
|
||||
{
|
||||
srb_t *sp = (srb_t *)ptr;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
|
@ -724,9 +730,9 @@ qla2xxx_qpair_sp_free_dma(void *vha, void *ptr)
|
|||
}
|
||||
|
||||
void
|
||||
qla2xxx_qpair_sp_compl(void *data, void *ptr, int res)
|
||||
qla2xxx_qpair_sp_compl(void *ptr, int res)
|
||||
{
|
||||
srb_t *sp = (srb_t *)ptr;
|
||||
srb_t *sp = ptr;
|
||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||
|
||||
cmd->result = res;
|
||||
|
@ -742,7 +748,7 @@ qla2xxx_qpair_sp_compl(void *data, void *ptr, int res)
|
|||
if (!atomic_dec_and_test(&sp->ref_count))
|
||||
return;
|
||||
|
||||
qla2xxx_qpair_sp_free_dma(sp->fcport->vha, sp);
|
||||
qla2xxx_qpair_sp_free_dma(sp);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
|
@ -863,7 +869,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
|||
return 0;
|
||||
|
||||
qc24_host_busy_free_sp:
|
||||
qla2x00_sp_free_dma(ha, sp);
|
||||
qla2x00_sp_free_dma(sp);
|
||||
|
||||
qc24_host_busy:
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
@ -952,7 +958,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
|
|||
return 0;
|
||||
|
||||
qc24_host_busy_free_sp:
|
||||
qla2xxx_qpair_sp_free_dma(vha, sp);
|
||||
qla2xxx_qpair_sp_free_dma(sp);
|
||||
|
||||
qc24_host_busy:
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
@ -1044,6 +1050,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
|
|||
return (return_status);
|
||||
}
|
||||
|
||||
static inline int test_fcport_count(scsi_qla_host_t *vha)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
unsigned long flags;
|
||||
int res;
|
||||
|
||||
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||
ql_dbg(ql_dbg_init, vha, 0xffff,
|
||||
"tgt %p, fcport_count=%d\n",
|
||||
vha, vha->fcport_count);
|
||||
res = (vha->fcport_count == 0);
|
||||
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* qla2x00_wait_for_sess_deletion can only be called from remove_one.
|
||||
* it has dependency on UNLOADING flag to stop device discovery
|
||||
*/
|
||||
static void
|
||||
qla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha)
|
||||
{
|
||||
qla2x00_mark_all_devices_lost(vha, 0);
|
||||
|
||||
wait_event(vha->fcport_waitQ, test_fcport_count(vha));
|
||||
}
|
||||
|
||||
/*
|
||||
* qla2x00_wait_for_hba_ready
|
||||
* Wait till the HBA is ready before doing driver unload
|
||||
|
@ -1204,7 +1238,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|||
}
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
sp->done(ha, sp, 0);
|
||||
sp->done(sp, 0);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
/* Did the command return during mailbox execution? */
|
||||
|
@ -1249,7 +1283,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
|
|||
continue;
|
||||
if (sp->type != SRB_SCSI_CMD)
|
||||
continue;
|
||||
if (vha->vp_idx != sp->fcport->vha->vp_idx)
|
||||
if (vha->vp_idx != sp->vha->vp_idx)
|
||||
continue;
|
||||
match = 0;
|
||||
cmd = GET_CMD_SP(sp);
|
||||
|
@ -1629,7 +1663,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
|
|||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
}
|
||||
req->outstanding_cmds[cnt] = NULL;
|
||||
sp->done(vha, sp, res);
|
||||
sp->done(sp, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3124,7 +3158,8 @@ skip_dpc:
|
|||
ql_dbg(ql_dbg_init, base_vha, 0x00f2,
|
||||
"Init done and hba is online.\n");
|
||||
|
||||
if (qla_ini_mode_enabled(base_vha))
|
||||
if (qla_ini_mode_enabled(base_vha) ||
|
||||
qla_dual_mode_enabled(base_vha))
|
||||
scsi_scan_host(host);
|
||||
else
|
||||
ql_dbg(ql_dbg_init, base_vha, 0x0122,
|
||||
|
@ -3373,21 +3408,26 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
|||
* resources.
|
||||
*/
|
||||
if (!atomic_read(&pdev->enable_cnt)) {
|
||||
dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
|
||||
base_vha->gnl.l, base_vha->gnl.ldma);
|
||||
|
||||
scsi_host_put(base_vha->host);
|
||||
kfree(ha);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
qla2x00_wait_for_hba_ready(base_vha);
|
||||
|
||||
/* if UNLOAD flag is already set, then continue unload,
|
||||
/*
|
||||
* if UNLOAD flag is already set, then continue unload,
|
||||
* where it was set first.
|
||||
*/
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
return;
|
||||
|
||||
set_bit(UNLOADING, &base_vha->dpc_flags);
|
||||
dma_free_coherent(&ha->pdev->dev,
|
||||
base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
|
||||
|
||||
if (IS_QLAFX00(ha))
|
||||
qlafx00_driver_shutdown(base_vha, 20);
|
||||
|
@ -3536,10 +3576,14 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
|
|||
qla2xxx_wake_dpc(base_vha);
|
||||
} else {
|
||||
int now;
|
||||
if (rport)
|
||||
if (rport) {
|
||||
ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
|
||||
"%s %8phN. rport %p roles %x \n",
|
||||
__func__, fcport->port_name, rport,
|
||||
rport->roles);
|
||||
fc_remote_port_delete(rport);
|
||||
}
|
||||
qlt_do_generation_tick(vha, &now);
|
||||
qlt_fc_port_deleted(vha, fcport, now);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3582,7 +3626,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
|
|||
fcport->login_retry = vha->hw->login_retry_count;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0x2067,
|
||||
"Port login retry %8phN, id = 0x%04x retry cnt=%d.\n",
|
||||
"Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",
|
||||
fcport->port_name, fcport->loop_id, fcport->login_retry);
|
||||
}
|
||||
}
|
||||
|
@ -3605,7 +3649,13 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
|
|||
{
|
||||
fc_port_t *fcport;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xffff,
|
||||
"Mark all dev lost\n");
|
||||
|
||||
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
||||
fcport->scan_state = 0;
|
||||
qlt_schedule_sess_for_deletion_lock(fcport);
|
||||
|
||||
if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
|
||||
continue;
|
||||
|
||||
|
@ -4195,10 +4245,10 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
|
|||
struct scsi_qla_host *vha = NULL;
|
||||
|
||||
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
|
||||
if (host == NULL) {
|
||||
if (!host) {
|
||||
ql_log_pci(ql_log_fatal, ha->pdev, 0x0107,
|
||||
"Failed to allocate host from the scsi layer, aborting.\n");
|
||||
goto fail;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Clear our data area */
|
||||
|
@ -4217,9 +4267,22 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
|
|||
INIT_LIST_HEAD(&vha->logo_list);
|
||||
INIT_LIST_HEAD(&vha->plogi_ack_list);
|
||||
INIT_LIST_HEAD(&vha->qp_list);
|
||||
INIT_LIST_HEAD(&vha->gnl.fcports);
|
||||
|
||||
spin_lock_init(&vha->work_lock);
|
||||
spin_lock_init(&vha->cmd_list_lock);
|
||||
init_waitqueue_head(&vha->fcport_waitQ);
|
||||
|
||||
vha->gnl.size = sizeof(struct get_name_list_extended) *
|
||||
(ha->max_loop_id + 1);
|
||||
vha->gnl.l = dma_alloc_coherent(&ha->pdev->dev,
|
||||
vha->gnl.size, &vha->gnl.ldma, GFP_KERNEL);
|
||||
if (!vha->gnl.l) {
|
||||
ql_log(ql_log_fatal, vha, 0xffff,
|
||||
"Alloc failed for name list.\n");
|
||||
scsi_remove_host(vha->host);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
|
||||
ql_dbg(ql_dbg_init, vha, 0x0041,
|
||||
|
@ -4228,12 +4291,9 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
|
|||
dev_name(&(ha->pdev->dev)));
|
||||
|
||||
return vha;
|
||||
|
||||
fail:
|
||||
return vha;
|
||||
}
|
||||
|
||||
static struct qla_work_evt *
|
||||
struct qla_work_evt *
|
||||
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
|
||||
{
|
||||
struct qla_work_evt *e;
|
||||
|
@ -4255,7 +4315,7 @@ qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
|
|||
return e;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -4316,7 +4376,6 @@ int qla2x00_post_async_##name##_work( \
|
|||
}
|
||||
|
||||
qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN);
|
||||
qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE);
|
||||
qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
|
||||
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
|
||||
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
|
||||
|
@ -4369,6 +4428,67 @@ qlafx00_post_aenfx_work(struct scsi_qla_host *vha, uint32_t evtcode,
|
|||
return qla2x00_post_work(vha, e);
|
||||
}
|
||||
|
||||
int qla24xx_post_upd_fcport_work(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
{
|
||||
struct qla_work_evt *e;
|
||||
|
||||
e = qla2x00_alloc_work(vha, QLA_EVT_UPD_FCPORT);
|
||||
if (!e)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
e->u.fcport.fcport = fcport;
|
||||
return qla2x00_post_work(vha, e);
|
||||
}
|
||||
|
||||
static
|
||||
void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
|
||||
{
|
||||
unsigned long flags;
|
||||
fc_port_t *fcport = NULL;
|
||||
struct qlt_plogi_ack_t *pla =
|
||||
(struct qlt_plogi_ack_t *)e->u.new_sess.pla;
|
||||
|
||||
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
||||
fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1);
|
||||
if (fcport) {
|
||||
fcport->d_id = e->u.new_sess.id;
|
||||
if (pla) {
|
||||
fcport->fw_login_state = DSC_LS_PLOGI_PEND;
|
||||
qlt_plogi_ack_link(vha, pla, fcport, QLT_PLOGI_LINK_SAME_WWN);
|
||||
/* we took an extra ref_count to prevent PLOGI ACK when
|
||||
* fcport/sess has not been created.
|
||||
*/
|
||||
pla->ref_count--;
|
||||
}
|
||||
} else {
|
||||
fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
|
||||
if (fcport) {
|
||||
fcport->d_id = e->u.new_sess.id;
|
||||
fcport->scan_state = QLA_FCPORT_FOUND;
|
||||
fcport->flags |= FCF_FABRIC_DEVICE;
|
||||
fcport->fw_login_state = DSC_LS_PLOGI_PEND;
|
||||
|
||||
memcpy(fcport->port_name, e->u.new_sess.port_name,
|
||||
WWN_SIZE);
|
||||
list_add_tail(&fcport->list, &vha->vp_fcports);
|
||||
|
||||
if (pla) {
|
||||
qlt_plogi_ack_link(vha, pla, fcport,
|
||||
QLT_PLOGI_LINK_SAME_WWN);
|
||||
pla->ref_count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
|
||||
|
||||
if (fcport) {
|
||||
if (pla)
|
||||
qlt_plogi_ack_unref(vha, pla);
|
||||
else
|
||||
qla24xx_async_gnl(vha, fcport);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qla2x00_do_work(struct scsi_qla_host *vha)
|
||||
{
|
||||
|
@ -4395,10 +4515,6 @@ qla2x00_do_work(struct scsi_qla_host *vha)
|
|||
qla2x00_async_login(vha, e->u.logio.fcport,
|
||||
e->u.logio.data);
|
||||
break;
|
||||
case QLA_EVT_ASYNC_LOGIN_DONE:
|
||||
qla2x00_async_login_done(vha, e->u.logio.fcport,
|
||||
e->u.logio.data);
|
||||
break;
|
||||
case QLA_EVT_ASYNC_LOGOUT:
|
||||
qla2x00_async_logout(vha, e->u.logio.fcport);
|
||||
break;
|
||||
|
@ -4420,6 +4536,34 @@ qla2x00_do_work(struct scsi_qla_host *vha)
|
|||
case QLA_EVT_AENFX:
|
||||
qlafx00_process_aen(vha, e);
|
||||
break;
|
||||
case QLA_EVT_GIDPN:
|
||||
qla24xx_async_gidpn(vha, e->u.fcport.fcport);
|
||||
break;
|
||||
case QLA_EVT_GPNID:
|
||||
qla24xx_async_gpnid(vha, &e->u.gpnid.id);
|
||||
break;
|
||||
case QLA_EVT_GPNID_DONE:
|
||||
qla24xx_async_gpnid_done(vha, e->u.iosb.sp);
|
||||
break;
|
||||
case QLA_EVT_NEW_SESS:
|
||||
qla24xx_create_new_sess(vha, e);
|
||||
break;
|
||||
case QLA_EVT_GPDB:
|
||||
qla24xx_async_gpdb(vha, e->u.fcport.fcport,
|
||||
e->u.fcport.opt);
|
||||
break;
|
||||
case QLA_EVT_GPSC:
|
||||
qla24xx_async_gpsc(vha, e->u.fcport.fcport);
|
||||
break;
|
||||
case QLA_EVT_UPD_FCPORT:
|
||||
qla2x00_update_fcport(vha, e->u.fcport.fcport);
|
||||
break;
|
||||
case QLA_EVT_GNL:
|
||||
qla24xx_async_gnl(vha, e->u.fcport.fcport);
|
||||
break;
|
||||
case QLA_EVT_NACK:
|
||||
qla24xx_do_nack_work(vha, e);
|
||||
break;
|
||||
}
|
||||
if (e->flags & QLA_EVT_FLAG_FREE)
|
||||
kfree(e);
|
||||
|
@ -4436,9 +4580,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
|
|||
{
|
||||
fc_port_t *fcport;
|
||||
int status;
|
||||
uint16_t next_loopid = 0;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
uint16_t data[2];
|
||||
struct event_arg ea;
|
||||
|
||||
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
||||
/*
|
||||
|
@ -4449,78 +4591,39 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
|
|||
fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
|
||||
fcport->login_retry--;
|
||||
if (fcport->flags & FCF_FABRIC_DEVICE) {
|
||||
if (fcport->flags & FCF_FCP2_DEVICE)
|
||||
ha->isp_ops->fabric_logout(vha,
|
||||
fcport->loop_id,
|
||||
fcport->d_id.b.domain,
|
||||
fcport->d_id.b.area,
|
||||
fcport->d_id.b.al_pa);
|
||||
|
||||
if (fcport->loop_id == FC_NO_LOOP_ID) {
|
||||
fcport->loop_id = next_loopid =
|
||||
ha->min_external_loopid;
|
||||
status = qla2x00_find_new_loop_id(
|
||||
vha, fcport);
|
||||
if (status != QLA_SUCCESS) {
|
||||
/* Ran out of IDs to use */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ALOGIO_CAPABLE(ha)) {
|
||||
fcport->flags |= FCF_ASYNC_SENT;
|
||||
data[0] = 0;
|
||||
data[1] = QLA_LOGIO_LOGIN_RETRIED;
|
||||
status = qla2x00_post_async_login_work(
|
||||
vha, fcport, data);
|
||||
if (status == QLA_SUCCESS)
|
||||
continue;
|
||||
/* Attempt a retry. */
|
||||
status = 1;
|
||||
ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
|
||||
"%s %8phC DS %d LS %d\n", __func__,
|
||||
fcport->port_name, fcport->disc_state,
|
||||
fcport->fw_login_state);
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.event = FCME_RELOGIN;
|
||||
ea.fcport = fcport;
|
||||
qla2x00_fcport_event_handler(vha, &ea);
|
||||
} else {
|
||||
status = qla2x00_fabric_login(vha,
|
||||
fcport, &next_loopid);
|
||||
if (status == QLA_SUCCESS) {
|
||||
int status2;
|
||||
uint8_t opts;
|
||||
|
||||
opts = 0;
|
||||
if (fcport->flags &
|
||||
FCF_FCP2_DEVICE)
|
||||
opts |= BIT_1;
|
||||
status2 =
|
||||
qla2x00_get_port_database(
|
||||
vha, fcport, opts);
|
||||
if (status2 != QLA_SUCCESS)
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
} else
|
||||
status = qla2x00_local_device_login(vha,
|
||||
fcport);
|
||||
|
||||
if (status == QLA_SUCCESS) {
|
||||
fcport->old_loop_id = fcport->loop_id;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0x2003,
|
||||
"Port login OK: logged in ID 0x%x.\n",
|
||||
fcport->loop_id);
|
||||
|
||||
qla2x00_update_fcport(vha, fcport);
|
||||
|
||||
} else if (status == 1) {
|
||||
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
|
||||
/* retry the login again */
|
||||
ql_dbg(ql_dbg_disc, vha, 0x2007,
|
||||
"Retrying %d login again loop_id 0x%x.\n",
|
||||
fcport->login_retry, fcport->loop_id);
|
||||
fcport->login_retry,
|
||||
fcport->loop_id);
|
||||
} else {
|
||||
fcport->login_retry = 0;
|
||||
}
|
||||
|
||||
if (fcport->login_retry == 0 && status != QLA_SUCCESS)
|
||||
if (fcport->login_retry == 0 &&
|
||||
status != QLA_SUCCESS)
|
||||
qla2x00_clear_loop_id(fcport);
|
||||
}
|
||||
}
|
||||
if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
|
||||
break;
|
||||
}
|
||||
|
@ -5183,7 +5286,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
|
|||
struct pci_dev *pdev = ha->pdev;
|
||||
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
||||
|
||||
/* if UNLOAD flag is already set, then continue unload,
|
||||
/*
|
||||
* if UNLOAD flag is already set, then continue unload,
|
||||
* where it was set first.
|
||||
*/
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
|
@ -5192,6 +5296,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
|
|||
ql_log(ql_log_warn, base_vha, 0x015b,
|
||||
"Disabling adapter.\n");
|
||||
|
||||
qla2x00_wait_for_sess_deletion(base_vha);
|
||||
|
||||
set_bit(UNLOADING, &base_vha->dpc_flags);
|
||||
|
||||
qla2x00_delete_all_vps(ha, base_vha);
|
||||
|
@ -5410,16 +5516,6 @@ qla2x00_do_dpc(void *data)
|
|||
qla2x00_update_fcports(base_vha);
|
||||
}
|
||||
|
||||
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 (IS_QLAFX00(ha))
|
||||
goto loop_resync_check;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -45,10 +45,12 @@
|
|||
#define QLA2XXX_INI_MODE_STR_EXCLUSIVE "exclusive"
|
||||
#define QLA2XXX_INI_MODE_STR_DISABLED "disabled"
|
||||
#define QLA2XXX_INI_MODE_STR_ENABLED "enabled"
|
||||
#define QLA2XXX_INI_MODE_STR_DUAL "dual"
|
||||
|
||||
#define QLA2XXX_INI_MODE_EXCLUSIVE 0
|
||||
#define QLA2XXX_INI_MODE_DISABLED 1
|
||||
#define QLA2XXX_INI_MODE_ENABLED 2
|
||||
#define QLA2XXX_INI_MODE_DUAL 3
|
||||
|
||||
#define QLA2XXX_COMMAND_COUNT_INIT 250
|
||||
#define QLA2XXX_IMMED_NOTIFY_COUNT_INIT 250
|
||||
|
@ -118,84 +120,6 @@
|
|||
? le16_to_cpu((iocb)->u.isp2x.target.extended) \
|
||||
: (uint16_t)(iocb)->u.isp2x.target.id.standard)
|
||||
|
||||
#ifndef IMMED_NOTIFY_TYPE
|
||||
#define IMMED_NOTIFY_TYPE 0x0D /* Immediate notify entry. */
|
||||
/*
|
||||
* ISP queue - immediate notify entry structure definition.
|
||||
* This is sent by the ISP to the Target driver.
|
||||
* This IOCB would have report of events sent by the
|
||||
* initiator, that needs to be handled by the target
|
||||
* driver immediately.
|
||||
*/
|
||||
struct imm_ntfy_from_isp {
|
||||
uint8_t entry_type; /* Entry type. */
|
||||
uint8_t entry_count; /* Entry count. */
|
||||
uint8_t sys_define; /* System defined. */
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
union {
|
||||
struct {
|
||||
uint32_t sys_define_2; /* System defined. */
|
||||
target_id_t target;
|
||||
uint16_t lun;
|
||||
uint8_t target_id;
|
||||
uint8_t reserved_1;
|
||||
uint16_t status_modifier;
|
||||
uint16_t status;
|
||||
uint16_t task_flags;
|
||||
uint16_t seq_id;
|
||||
uint16_t srr_rx_id;
|
||||
uint32_t srr_rel_offs;
|
||||
uint16_t srr_ui;
|
||||
#define SRR_IU_DATA_IN 0x1
|
||||
#define SRR_IU_DATA_OUT 0x5
|
||||
#define SRR_IU_STATUS 0x7
|
||||
uint16_t srr_ox_id;
|
||||
uint8_t reserved_2[28];
|
||||
} isp2x;
|
||||
struct {
|
||||
uint32_t reserved;
|
||||
uint16_t nport_handle;
|
||||
uint16_t reserved_2;
|
||||
uint16_t flags;
|
||||
#define NOTIFY24XX_FLAGS_GLOBAL_TPRLO BIT_1
|
||||
#define NOTIFY24XX_FLAGS_PUREX_IOCB BIT_0
|
||||
uint16_t srr_rx_id;
|
||||
uint16_t status;
|
||||
uint8_t status_subcode;
|
||||
uint8_t fw_handle;
|
||||
uint32_t exchange_address;
|
||||
uint32_t srr_rel_offs;
|
||||
uint16_t srr_ui;
|
||||
uint16_t srr_ox_id;
|
||||
union {
|
||||
struct {
|
||||
uint8_t node_name[8];
|
||||
} plogi; /* PLOGI/ADISC/PDISC */
|
||||
struct {
|
||||
/* PRLI word 3 bit 0-15 */
|
||||
uint16_t wd3_lo;
|
||||
uint8_t resv0[6];
|
||||
} prli;
|
||||
struct {
|
||||
uint8_t port_id[3];
|
||||
uint8_t resv1;
|
||||
uint16_t nport_handle;
|
||||
uint16_t resv2;
|
||||
} req_els;
|
||||
} u;
|
||||
uint8_t port_name[8];
|
||||
uint8_t resv3[3];
|
||||
uint8_t vp_index;
|
||||
uint32_t reserved_5;
|
||||
uint8_t port_id[3];
|
||||
uint8_t reserved_6;
|
||||
} isp24;
|
||||
} u;
|
||||
uint16_t reserved_7;
|
||||
uint16_t ox_id;
|
||||
} __packed;
|
||||
#endif
|
||||
|
||||
#ifndef NOTIFY_ACK_TYPE
|
||||
#define NOTIFY_ACK_TYPE 0x0E /* Notify acknowledge entry. */
|
||||
/*
|
||||
|
@ -731,7 +655,7 @@ struct abts_resp_from_24xx_fw {
|
|||
\********************************************************************/
|
||||
|
||||
struct qla_tgt_mgmt_cmd;
|
||||
struct qla_tgt_sess;
|
||||
struct fc_port;
|
||||
|
||||
/*
|
||||
* This structure provides a template of function calls that the
|
||||
|
@ -744,21 +668,22 @@ struct qla_tgt_func_tmpl {
|
|||
unsigned char *, uint32_t, int, int, int);
|
||||
void (*handle_data)(struct qla_tgt_cmd *);
|
||||
void (*handle_dif_err)(struct qla_tgt_cmd *);
|
||||
int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_t,
|
||||
int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint16_t,
|
||||
uint32_t);
|
||||
void (*free_cmd)(struct qla_tgt_cmd *);
|
||||
void (*free_mcmd)(struct qla_tgt_mgmt_cmd *);
|
||||
void (*free_session)(struct qla_tgt_sess *);
|
||||
void (*free_session)(struct fc_port *);
|
||||
|
||||
int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
|
||||
struct qla_tgt_sess *);
|
||||
void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
|
||||
struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
|
||||
struct fc_port *);
|
||||
void (*update_sess)(struct fc_port *, port_id_t, uint16_t, bool);
|
||||
struct fc_port *(*find_sess_by_loop_id)(struct scsi_qla_host *,
|
||||
const uint16_t);
|
||||
struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
|
||||
struct fc_port *(*find_sess_by_s_id)(struct scsi_qla_host *,
|
||||
const uint8_t *);
|
||||
void (*clear_nacl_from_fcport_map)(struct qla_tgt_sess *);
|
||||
void (*shutdown_sess)(struct qla_tgt_sess *);
|
||||
void (*clear_nacl_from_fcport_map)(struct fc_port *);
|
||||
void (*put_sess)(struct fc_port *);
|
||||
void (*shutdown_sess)(struct fc_port *);
|
||||
};
|
||||
|
||||
int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
|
||||
|
@ -795,6 +720,8 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
|
|||
#define QLA_TGT_ABORT_ALL 0xFFFE
|
||||
#define QLA_TGT_NEXUS_LOSS_SESS 0xFFFD
|
||||
#define QLA_TGT_NEXUS_LOSS 0xFFFC
|
||||
#define QLA_TGT_ABTS 0xFFFB
|
||||
#define QLA_TGT_2G_ABORT_TASK 0xFFFA
|
||||
|
||||
/* Notify Acknowledge flags */
|
||||
#define NOTIFY_ACK_RES_COUNT BIT_8
|
||||
|
@ -872,12 +799,8 @@ struct qla_tgt {
|
|||
/* Count of sessions refering qla_tgt. Protected by hardware_lock. */
|
||||
int sess_count;
|
||||
|
||||
/* Protected by hardware_lock. Addition also protected by tgt_mutex. */
|
||||
struct list_head sess_list;
|
||||
|
||||
/* Protected by hardware_lock */
|
||||
struct list_head del_sess_list;
|
||||
struct delayed_work sess_del_work;
|
||||
|
||||
spinlock_t sess_work_lock;
|
||||
struct list_head sess_works_list;
|
||||
|
@ -888,16 +811,7 @@ struct qla_tgt {
|
|||
int notify_ack_expected;
|
||||
int abts_resp_expected;
|
||||
int modify_lun_expected;
|
||||
|
||||
int ctio_srr_id;
|
||||
int imm_srr_id;
|
||||
spinlock_t srr_lock;
|
||||
struct list_head srr_ctio_list;
|
||||
struct list_head srr_imm_list;
|
||||
struct work_struct srr_work;
|
||||
|
||||
atomic_t tgt_global_resets_count;
|
||||
|
||||
struct list_head tgt_list_entry;
|
||||
};
|
||||
|
||||
|
@ -910,92 +824,32 @@ struct qla_tgt_sess_op {
|
|||
bool aborted;
|
||||
};
|
||||
|
||||
enum qla_sess_deletion {
|
||||
QLA_SESS_DELETION_NONE = 0,
|
||||
QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
|
||||
* this one */
|
||||
QLA_SESS_DELETION_IN_PROGRESS = 2,
|
||||
enum trace_flags {
|
||||
TRC_NEW_CMD = BIT_0,
|
||||
TRC_DO_WORK = BIT_1,
|
||||
TRC_DO_WORK_ERR = BIT_2,
|
||||
TRC_XFR_RDY = BIT_3,
|
||||
TRC_XMIT_DATA = BIT_4,
|
||||
TRC_XMIT_STATUS = BIT_5,
|
||||
TRC_SRR_RSP = BIT_6,
|
||||
TRC_SRR_XRDY = BIT_7,
|
||||
TRC_SRR_TERM = BIT_8,
|
||||
TRC_SRR_CTIO = BIT_9,
|
||||
TRC_FLUSH = BIT_10,
|
||||
TRC_CTIO_ERR = BIT_11,
|
||||
TRC_CTIO_DONE = BIT_12,
|
||||
TRC_CTIO_ABORTED = BIT_13,
|
||||
TRC_CTIO_STRANGE= BIT_14,
|
||||
TRC_CMD_DONE = BIT_15,
|
||||
TRC_CMD_CHK_STOP = BIT_16,
|
||||
TRC_CMD_FREE = BIT_17,
|
||||
TRC_DATA_IN = BIT_18,
|
||||
TRC_ABORT = BIT_19,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
QLT_PLOGI_LINK_SAME_WWN,
|
||||
QLT_PLOGI_LINK_CONFLICT,
|
||||
QLT_PLOGI_LINK_MAX
|
||||
} qlt_plogi_link_t;
|
||||
|
||||
typedef struct {
|
||||
struct list_head list;
|
||||
struct imm_ntfy_from_isp iocb;
|
||||
port_id_t id;
|
||||
int ref_count;
|
||||
} qlt_plogi_ack_t;
|
||||
|
||||
/*
|
||||
* Equivilant to IT Nexus (Initiator-Target)
|
||||
*/
|
||||
struct qla_tgt_sess {
|
||||
uint16_t loop_id;
|
||||
port_id_t s_id;
|
||||
|
||||
unsigned int conf_compl_supported:1;
|
||||
unsigned int deleted:2;
|
||||
unsigned int local:1;
|
||||
unsigned int logout_on_delete:1;
|
||||
unsigned int keep_nport_handle:1;
|
||||
unsigned int send_els_logo:1;
|
||||
|
||||
unsigned char logout_completed;
|
||||
|
||||
int generation;
|
||||
|
||||
struct se_session *se_sess;
|
||||
struct kref sess_kref;
|
||||
struct scsi_qla_host *vha;
|
||||
struct qla_tgt *tgt;
|
||||
|
||||
struct list_head sess_list_entry;
|
||||
unsigned long expires;
|
||||
struct list_head del_list_entry;
|
||||
|
||||
uint8_t port_name[WWN_SIZE];
|
||||
struct work_struct free_work;
|
||||
|
||||
qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
/*
|
||||
* BIT_0 - Atio Arrival / schedule to work
|
||||
* BIT_1 - qlt_do_work
|
||||
* BIT_2 - qlt_do work failed
|
||||
* BIT_3 - xfer rdy/tcm_qla2xxx_write_pending
|
||||
* BIT_4 - read respond/tcm_qla2xx_queue_data_in
|
||||
* BIT_5 - status respond / tcm_qla2xx_queue_status
|
||||
* BIT_6 - tcm request to abort/Term exchange.
|
||||
* pre_xmit_response->qlt_send_term_exchange
|
||||
* BIT_7 - SRR received (qlt_handle_srr->qlt_xmit_response)
|
||||
* BIT_8 - SRR received (qlt_handle_srr->qlt_rdy_to_xfer)
|
||||
* BIT_9 - SRR received (qla_handle_srr->qlt_send_term_exchange)
|
||||
* BIT_10 - Data in - hanlde_data->tcm_qla2xxx_handle_data
|
||||
|
||||
* BIT_12 - good completion - qlt_ctio_do_completion -->free_cmd
|
||||
* BIT_13 - Bad completion -
|
||||
* qlt_ctio_do_completion --> qlt_term_ctio_exchange
|
||||
* BIT_14 - Back end data received/sent.
|
||||
* BIT_15 - SRR prepare ctio
|
||||
* BIT_16 - complete free
|
||||
* BIT_17 - flush - qlt_abort_cmd_on_host_reset
|
||||
* BIT_18 - completion w/abort status
|
||||
* BIT_19 - completion w/unknown status
|
||||
* BIT_20 - tcm_qla2xxx_free_cmd
|
||||
*/
|
||||
CMD_FLAG_DATA_WORK = BIT_11,
|
||||
CMD_FLAG_DATA_WORK_FREE = BIT_21,
|
||||
} cmd_flags_t;
|
||||
|
||||
struct qla_tgt_cmd {
|
||||
struct se_cmd se_cmd;
|
||||
struct qla_tgt_sess *sess;
|
||||
struct fc_port *sess;
|
||||
int state;
|
||||
struct work_struct free_work;
|
||||
struct work_struct work;
|
||||
|
@ -1014,6 +868,8 @@ struct qla_tgt_cmd {
|
|||
unsigned int cmd_sent_to_fw:1;
|
||||
unsigned int cmd_in_wq:1;
|
||||
unsigned int aborted:1;
|
||||
unsigned int data_work:1;
|
||||
unsigned int data_work_free:1;
|
||||
|
||||
struct scatterlist *sg; /* cmd data buffer SG vector */
|
||||
int sg_cnt; /* SG segments count */
|
||||
|
@ -1038,7 +894,7 @@ struct qla_tgt_cmd {
|
|||
uint64_t jiffies_at_alloc;
|
||||
uint64_t jiffies_at_free;
|
||||
|
||||
cmd_flags_t cmd_flags;
|
||||
enum trace_flags trc_flags;
|
||||
};
|
||||
|
||||
struct qla_tgt_sess_work_param {
|
||||
|
@ -1056,9 +912,9 @@ struct qla_tgt_sess_work_param {
|
|||
};
|
||||
|
||||
struct qla_tgt_mgmt_cmd {
|
||||
uint8_t tmr_func;
|
||||
uint16_t tmr_func;
|
||||
uint8_t fc_tm_rsp;
|
||||
struct qla_tgt_sess *sess;
|
||||
struct fc_port *sess;
|
||||
struct se_cmd se_cmd;
|
||||
struct work_struct free_work;
|
||||
unsigned int flags;
|
||||
|
@ -1090,18 +946,6 @@ struct qla_tgt_prm {
|
|||
uint16_t tot_dsds;
|
||||
};
|
||||
|
||||
struct qla_tgt_srr_imm {
|
||||
struct list_head srr_list_entry;
|
||||
int srr_id;
|
||||
struct imm_ntfy_from_isp imm_ntfy;
|
||||
};
|
||||
|
||||
struct qla_tgt_srr_ctio {
|
||||
struct list_head srr_list_entry;
|
||||
int srr_id;
|
||||
struct qla_tgt_cmd *cmd;
|
||||
};
|
||||
|
||||
/* Check for Switch reserved address */
|
||||
#define IS_SW_RESV_ADDR(_s_id) \
|
||||
((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
|
||||
|
@ -1121,7 +965,7 @@ extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *);
|
|||
extern int qlt_lport_register(void *, u64, u64, u64,
|
||||
int (*callback)(struct scsi_qla_host *, void *, u64, u64));
|
||||
extern void qlt_lport_deregister(struct scsi_qla_host *);
|
||||
void qlt_put_sess(struct qla_tgt_sess *sess);
|
||||
extern void qlt_unreg_sess(struct fc_port *);
|
||||
extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
|
||||
extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int);
|
||||
extern int __init qlt_init(void);
|
||||
|
@ -1133,24 +977,22 @@ extern void qlt_update_vp_map(struct scsi_qla_host *, int);
|
|||
* is not set. Right now, ha value is ignored.
|
||||
*/
|
||||
#define QLA_TGT_MODE_ENABLED() (ql2x_ini_mode != QLA2XXX_INI_MODE_ENABLED)
|
||||
|
||||
extern int ql2x_ini_mode;
|
||||
|
||||
static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
|
||||
{
|
||||
return ha->host->active_mode & MODE_TARGET;
|
||||
return ha->host->active_mode == MODE_TARGET;
|
||||
}
|
||||
|
||||
static inline bool qla_ini_mode_enabled(struct scsi_qla_host *ha)
|
||||
{
|
||||
return ha->host->active_mode & MODE_INITIATOR;
|
||||
return ha->host->active_mode == MODE_INITIATOR;
|
||||
}
|
||||
|
||||
static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
|
||||
static inline bool qla_dual_mode_enabled(struct scsi_qla_host *ha)
|
||||
{
|
||||
if (ha->host->active_mode & MODE_INITIATOR)
|
||||
ha->host->active_mode &= ~MODE_INITIATOR;
|
||||
else
|
||||
ha->host->active_mode |= MODE_INITIATOR;
|
||||
return (ha->host->active_mode == MODE_DUAL);
|
||||
}
|
||||
|
||||
static inline uint32_t sid_to_key(const uint8_t *s_id)
|
||||
|
|
|
@ -282,10 +282,10 @@ static void tcm_qla2xxx_complete_free(struct work_struct *work)
|
|||
|
||||
cmd->cmd_in_wq = 0;
|
||||
|
||||
WARN_ON(cmd->cmd_flags & BIT_16);
|
||||
WARN_ON(cmd->trc_flags & TRC_CMD_FREE);
|
||||
|
||||
cmd->vha->tgt_counters.qla_core_ret_sta_ctio++;
|
||||
cmd->cmd_flags |= BIT_16;
|
||||
cmd->trc_flags |= TRC_CMD_FREE;
|
||||
transport_generic_free_cmd(&cmd->se_cmd, 0);
|
||||
}
|
||||
|
||||
|
@ -299,8 +299,8 @@ static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd)
|
|||
cmd->vha->tgt_counters.core_qla_free_cmd++;
|
||||
cmd->cmd_in_wq = 1;
|
||||
|
||||
BUG_ON(cmd->cmd_flags & BIT_20);
|
||||
cmd->cmd_flags |= BIT_20;
|
||||
WARN_ON(cmd->trc_flags & TRC_CMD_DONE);
|
||||
cmd->trc_flags |= TRC_CMD_DONE;
|
||||
|
||||
INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free);
|
||||
queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
|
||||
|
@ -315,7 +315,7 @@ static int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd)
|
|||
|
||||
if ((se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) == 0) {
|
||||
cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
|
||||
cmd->cmd_flags |= BIT_14;
|
||||
cmd->trc_flags |= TRC_CMD_CHK_STOP;
|
||||
}
|
||||
|
||||
return target_put_sess_cmd(se_cmd);
|
||||
|
@ -339,9 +339,26 @@ static void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd)
|
|||
qlt_free_cmd(cmd);
|
||||
}
|
||||
|
||||
static void tcm_qla2xxx_release_session(struct kref *kref)
|
||||
{
|
||||
struct fc_port *sess = container_of(kref,
|
||||
struct fc_port, sess_kref);
|
||||
|
||||
qlt_unreg_sess(sess);
|
||||
}
|
||||
|
||||
static void tcm_qla2xxx_put_sess(struct fc_port *sess)
|
||||
{
|
||||
if (!sess)
|
||||
return;
|
||||
|
||||
assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
|
||||
kref_put(&sess->sess_kref, tcm_qla2xxx_release_session);
|
||||
}
|
||||
|
||||
static void tcm_qla2xxx_close_session(struct se_session *se_sess)
|
||||
{
|
||||
struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr;
|
||||
struct fc_port *sess = se_sess->fabric_sess_ptr;
|
||||
struct scsi_qla_host *vha;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -350,7 +367,7 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess)
|
|||
|
||||
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
||||
target_sess_cmd_list_set_waiting(se_sess);
|
||||
qlt_put_sess(sess);
|
||||
tcm_qla2xxx_put_sess(sess);
|
||||
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -377,7 +394,7 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
|
|||
cmd->se_cmd.se_cmd_flags);
|
||||
return 0;
|
||||
}
|
||||
cmd->cmd_flags |= BIT_3;
|
||||
cmd->trc_flags |= TRC_XFR_RDY;
|
||||
cmd->bufflen = se_cmd->data_length;
|
||||
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
|
||||
|
||||
|
@ -441,7 +458,7 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
|
|||
{
|
||||
struct se_cmd *se_cmd = &cmd->se_cmd;
|
||||
struct se_session *se_sess;
|
||||
struct qla_tgt_sess *sess;
|
||||
struct fc_port *sess;
|
||||
#ifdef CONFIG_TCM_QLA2XXX_DEBUG
|
||||
struct se_portal_group *se_tpg;
|
||||
struct tcm_qla2xxx_tpg *tpg;
|
||||
|
@ -456,7 +473,7 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
|
|||
|
||||
sess = cmd->sess;
|
||||
if (!sess) {
|
||||
pr_err("Unable to locate struct qla_tgt_sess from qla_tgt_cmd\n");
|
||||
pr_err("Unable to locate struct fc_port from qla_tgt_cmd\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -493,9 +510,9 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
|
|||
cmd->cmd_in_wq = 0;
|
||||
|
||||
spin_lock_irqsave(&cmd->cmd_lock, flags);
|
||||
cmd->cmd_flags |= CMD_FLAG_DATA_WORK;
|
||||
cmd->data_work = 1;
|
||||
if (cmd->aborted) {
|
||||
cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE;
|
||||
cmd->data_work_free = 1;
|
||||
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
|
||||
|
||||
tcm_qla2xxx_free_cmd(cmd);
|
||||
|
@ -532,7 +549,7 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
|
|||
*/
|
||||
static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
|
||||
{
|
||||
cmd->cmd_flags |= BIT_10;
|
||||
cmd->trc_flags |= TRC_DATA_IN;
|
||||
cmd->cmd_in_wq = 1;
|
||||
INIT_WORK(&cmd->work, tcm_qla2xxx_handle_data_work);
|
||||
queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
|
||||
|
@ -563,13 +580,49 @@ static void tcm_qla2xxx_handle_dif_err(struct qla_tgt_cmd *cmd)
|
|||
* Called from qla_target.c:qlt_issue_task_mgmt()
|
||||
*/
|
||||
static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, uint32_t lun,
|
||||
uint8_t tmr_func, uint32_t tag)
|
||||
uint16_t tmr_func, uint32_t tag)
|
||||
{
|
||||
struct qla_tgt_sess *sess = mcmd->sess;
|
||||
struct fc_port *sess = mcmd->sess;
|
||||
struct se_cmd *se_cmd = &mcmd->se_cmd;
|
||||
int transl_tmr_func = 0;
|
||||
|
||||
switch (tmr_func) {
|
||||
case QLA_TGT_ABTS:
|
||||
pr_debug("%ld: ABTS received\n", sess->vha->host_no);
|
||||
transl_tmr_func = TMR_ABORT_TASK;
|
||||
break;
|
||||
case QLA_TGT_2G_ABORT_TASK:
|
||||
pr_debug("%ld: 2G Abort Task received\n", sess->vha->host_no);
|
||||
transl_tmr_func = TMR_ABORT_TASK;
|
||||
break;
|
||||
case QLA_TGT_CLEAR_ACA:
|
||||
pr_debug("%ld: CLEAR_ACA received\n", sess->vha->host_no);
|
||||
transl_tmr_func = TMR_CLEAR_ACA;
|
||||
break;
|
||||
case QLA_TGT_TARGET_RESET:
|
||||
pr_debug("%ld: TARGET_RESET received\n", sess->vha->host_no);
|
||||
transl_tmr_func = TMR_TARGET_WARM_RESET;
|
||||
break;
|
||||
case QLA_TGT_LUN_RESET:
|
||||
pr_debug("%ld: LUN_RESET received\n", sess->vha->host_no);
|
||||
transl_tmr_func = TMR_LUN_RESET;
|
||||
break;
|
||||
case QLA_TGT_CLEAR_TS:
|
||||
pr_debug("%ld: CLEAR_TS received\n", sess->vha->host_no);
|
||||
transl_tmr_func = TMR_CLEAR_TASK_SET;
|
||||
break;
|
||||
case QLA_TGT_ABORT_TS:
|
||||
pr_debug("%ld: ABORT_TS received\n", sess->vha->host_no);
|
||||
transl_tmr_func = TMR_ABORT_TASK_SET;
|
||||
break;
|
||||
default:
|
||||
pr_debug("%ld: Unknown task mgmt fn 0x%x\n",
|
||||
sess->vha->host_no, tmr_func);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return target_submit_tmr(se_cmd, sess->se_sess, NULL, lun, mcmd,
|
||||
tmr_func, GFP_ATOMIC, tag, TARGET_SCF_ACK_KREF);
|
||||
transl_tmr_func, GFP_ATOMIC, tag, TARGET_SCF_ACK_KREF);
|
||||
}
|
||||
|
||||
static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
|
||||
|
@ -591,7 +644,7 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
cmd->cmd_flags |= BIT_4;
|
||||
cmd->trc_flags |= TRC_XMIT_DATA;
|
||||
cmd->bufflen = se_cmd->data_length;
|
||||
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
|
||||
|
||||
|
@ -622,11 +675,11 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
|
|||
cmd->sg_cnt = 0;
|
||||
cmd->offset = 0;
|
||||
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
|
||||
if (cmd->cmd_flags & BIT_5) {
|
||||
pr_crit("Bit_5 already set for cmd = %p.\n", cmd);
|
||||
if (cmd->trc_flags & TRC_XMIT_STATUS) {
|
||||
pr_crit("Multiple calls for status = %p.\n", cmd);
|
||||
dump_stack();
|
||||
}
|
||||
cmd->cmd_flags |= BIT_5;
|
||||
cmd->trc_flags |= TRC_XMIT_STATUS;
|
||||
|
||||
if (se_cmd->data_direction == DMA_FROM_DEVICE) {
|
||||
/*
|
||||
|
@ -682,10 +735,7 @@ static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
|
|||
qlt_xmit_tm_rsp(mcmd);
|
||||
}
|
||||
|
||||
|
||||
#define DATA_WORK_NOT_FREE(_flags) \
|
||||
(( _flags & (CMD_FLAG_DATA_WORK|CMD_FLAG_DATA_WORK_FREE)) == \
|
||||
CMD_FLAG_DATA_WORK)
|
||||
#define DATA_WORK_NOT_FREE(_cmd) (_cmd->data_work && !_cmd->data_work_free)
|
||||
static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
|
||||
{
|
||||
struct qla_tgt_cmd *cmd = container_of(se_cmd,
|
||||
|
@ -698,12 +748,12 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
|
|||
spin_lock_irqsave(&cmd->cmd_lock, flags);
|
||||
if ((cmd->state == QLA_TGT_STATE_NEW)||
|
||||
((cmd->state == QLA_TGT_STATE_DATA_IN) &&
|
||||
DATA_WORK_NOT_FREE(cmd->cmd_flags)) ) {
|
||||
|
||||
cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE;
|
||||
DATA_WORK_NOT_FREE(cmd))) {
|
||||
cmd->data_work_free = 1;
|
||||
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
|
||||
/* Cmd have not reached firmware.
|
||||
* Use this trigger to free it. */
|
||||
/*
|
||||
* cmd has not reached fw, Use this trigger to free it.
|
||||
*/
|
||||
tcm_qla2xxx_free_cmd(cmd);
|
||||
return;
|
||||
}
|
||||
|
@ -713,11 +763,11 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
|
|||
}
|
||||
|
||||
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
|
||||
struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *);
|
||||
struct tcm_qla2xxx_nacl *, struct fc_port *);
|
||||
/*
|
||||
* Expected to be called with struct qla_hw_data->tgt.sess_lock held
|
||||
*/
|
||||
static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess)
|
||||
static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct fc_port *sess)
|
||||
{
|
||||
struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
|
||||
struct se_portal_group *se_tpg = se_nacl->se_tpg;
|
||||
|
@ -756,7 +806,7 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess)
|
|||
tcm_qla2xxx_clear_sess_lookup(lport, nacl, sess);
|
||||
}
|
||||
|
||||
static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess)
|
||||
static void tcm_qla2xxx_shutdown_sess(struct fc_port *sess)
|
||||
{
|
||||
assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
|
||||
target_sess_cmd_list_set_waiting(sess->se_sess);
|
||||
|
@ -1141,7 +1191,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
|
|||
/*
|
||||
* Expected to be called with struct qla_hw_data->tgt.sess_lock held
|
||||
*/
|
||||
static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
|
||||
static struct fc_port *tcm_qla2xxx_find_sess_by_s_id(
|
||||
scsi_qla_host_t *vha,
|
||||
const uint8_t *s_id)
|
||||
{
|
||||
|
@ -1169,12 +1219,12 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
|
|||
se_nacl, se_nacl->initiatorname);
|
||||
|
||||
nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl);
|
||||
if (!nacl->qla_tgt_sess) {
|
||||
pr_err("Unable to locate struct qla_tgt_sess\n");
|
||||
if (!nacl->fc_port) {
|
||||
pr_err("Unable to locate struct fc_port\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nacl->qla_tgt_sess;
|
||||
return nacl->fc_port;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1185,7 +1235,7 @@ static void tcm_qla2xxx_set_sess_by_s_id(
|
|||
struct se_node_acl *new_se_nacl,
|
||||
struct tcm_qla2xxx_nacl *nacl,
|
||||
struct se_session *se_sess,
|
||||
struct qla_tgt_sess *qla_tgt_sess,
|
||||
struct fc_port *fc_port,
|
||||
uint8_t *s_id)
|
||||
{
|
||||
u32 key;
|
||||
|
@ -1209,22 +1259,22 @@ static void tcm_qla2xxx_set_sess_by_s_id(
|
|||
pr_debug("Wiping nonexisting fc_port entry\n");
|
||||
}
|
||||
|
||||
qla_tgt_sess->se_sess = se_sess;
|
||||
nacl->qla_tgt_sess = qla_tgt_sess;
|
||||
fc_port->se_sess = se_sess;
|
||||
nacl->fc_port = fc_port;
|
||||
return;
|
||||
}
|
||||
|
||||
if (nacl->qla_tgt_sess) {
|
||||
if (nacl->fc_port) {
|
||||
if (new_se_nacl == NULL) {
|
||||
pr_debug("Clearing existing nacl->qla_tgt_sess and fc_port entry\n");
|
||||
pr_debug("Clearing existing nacl->fc_port and fc_port entry\n");
|
||||
btree_remove32(&lport->lport_fcport_map, key);
|
||||
nacl->qla_tgt_sess = NULL;
|
||||
nacl->fc_port = NULL;
|
||||
return;
|
||||
}
|
||||
pr_debug("Replacing existing nacl->qla_tgt_sess and fc_port entry\n");
|
||||
pr_debug("Replacing existing nacl->fc_port and fc_port entry\n");
|
||||
btree_update32(&lport->lport_fcport_map, key, new_se_nacl);
|
||||
qla_tgt_sess->se_sess = se_sess;
|
||||
nacl->qla_tgt_sess = qla_tgt_sess;
|
||||
fc_port->se_sess = se_sess;
|
||||
nacl->fc_port = fc_port;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1234,19 +1284,19 @@ static void tcm_qla2xxx_set_sess_by_s_id(
|
|||
return;
|
||||
}
|
||||
|
||||
pr_debug("Replacing existing fc_port entry w/o active nacl->qla_tgt_sess\n");
|
||||
pr_debug("Replacing existing fc_port entry w/o active nacl->fc_port\n");
|
||||
btree_update32(&lport->lport_fcport_map, key, new_se_nacl);
|
||||
qla_tgt_sess->se_sess = se_sess;
|
||||
nacl->qla_tgt_sess = qla_tgt_sess;
|
||||
fc_port->se_sess = se_sess;
|
||||
nacl->fc_port = fc_port;
|
||||
|
||||
pr_debug("Setup nacl->qla_tgt_sess %p by s_id for se_nacl: %p, initiatorname: %s\n",
|
||||
nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname);
|
||||
pr_debug("Setup nacl->fc_port %p by s_id for se_nacl: %p, initiatorname: %s\n",
|
||||
nacl->fc_port, new_se_nacl, new_se_nacl->initiatorname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expected to be called with struct qla_hw_data->tgt.sess_lock held
|
||||
*/
|
||||
static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id(
|
||||
static struct fc_port *tcm_qla2xxx_find_sess_by_loop_id(
|
||||
scsi_qla_host_t *vha,
|
||||
const uint16_t loop_id)
|
||||
{
|
||||
|
@ -1274,12 +1324,12 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id(
|
|||
|
||||
nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl);
|
||||
|
||||
if (!nacl->qla_tgt_sess) {
|
||||
pr_err("Unable to locate struct qla_tgt_sess\n");
|
||||
if (!nacl->fc_port) {
|
||||
pr_err("Unable to locate struct fc_port\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nacl->qla_tgt_sess;
|
||||
return nacl->fc_port;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1290,7 +1340,7 @@ static void tcm_qla2xxx_set_sess_by_loop_id(
|
|||
struct se_node_acl *new_se_nacl,
|
||||
struct tcm_qla2xxx_nacl *nacl,
|
||||
struct se_session *se_sess,
|
||||
struct qla_tgt_sess *qla_tgt_sess,
|
||||
struct fc_port *fc_port,
|
||||
uint16_t loop_id)
|
||||
{
|
||||
struct se_node_acl *saved_nacl;
|
||||
|
@ -1305,27 +1355,27 @@ static void tcm_qla2xxx_set_sess_by_loop_id(
|
|||
if (!saved_nacl) {
|
||||
pr_debug("Setting up new fc_loopid->se_nacl to new_se_nacl\n");
|
||||
fc_loopid->se_nacl = new_se_nacl;
|
||||
if (qla_tgt_sess->se_sess != se_sess)
|
||||
qla_tgt_sess->se_sess = se_sess;
|
||||
if (nacl->qla_tgt_sess != qla_tgt_sess)
|
||||
nacl->qla_tgt_sess = qla_tgt_sess;
|
||||
if (fc_port->se_sess != se_sess)
|
||||
fc_port->se_sess = se_sess;
|
||||
if (nacl->fc_port != fc_port)
|
||||
nacl->fc_port = fc_port;
|
||||
return;
|
||||
}
|
||||
|
||||
if (nacl->qla_tgt_sess) {
|
||||
if (nacl->fc_port) {
|
||||
if (new_se_nacl == NULL) {
|
||||
pr_debug("Clearing nacl->qla_tgt_sess and fc_loopid->se_nacl\n");
|
||||
pr_debug("Clearing nacl->fc_port and fc_loopid->se_nacl\n");
|
||||
fc_loopid->se_nacl = NULL;
|
||||
nacl->qla_tgt_sess = NULL;
|
||||
nacl->fc_port = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("Replacing existing nacl->qla_tgt_sess and fc_loopid->se_nacl\n");
|
||||
pr_debug("Replacing existing nacl->fc_port and fc_loopid->se_nacl\n");
|
||||
fc_loopid->se_nacl = new_se_nacl;
|
||||
if (qla_tgt_sess->se_sess != se_sess)
|
||||
qla_tgt_sess->se_sess = se_sess;
|
||||
if (nacl->qla_tgt_sess != qla_tgt_sess)
|
||||
nacl->qla_tgt_sess = qla_tgt_sess;
|
||||
if (fc_port->se_sess != se_sess)
|
||||
fc_port->se_sess = se_sess;
|
||||
if (nacl->fc_port != fc_port)
|
||||
nacl->fc_port = fc_port;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1335,29 +1385,29 @@ static void tcm_qla2xxx_set_sess_by_loop_id(
|
|||
return;
|
||||
}
|
||||
|
||||
pr_debug("Replacing existing fc_loopid->se_nacl w/o active nacl->qla_tgt_sess\n");
|
||||
pr_debug("Replacing existing fc_loopid->se_nacl w/o active nacl->fc_port\n");
|
||||
fc_loopid->se_nacl = new_se_nacl;
|
||||
if (qla_tgt_sess->se_sess != se_sess)
|
||||
qla_tgt_sess->se_sess = se_sess;
|
||||
if (nacl->qla_tgt_sess != qla_tgt_sess)
|
||||
nacl->qla_tgt_sess = qla_tgt_sess;
|
||||
if (fc_port->se_sess != se_sess)
|
||||
fc_port->se_sess = se_sess;
|
||||
if (nacl->fc_port != fc_port)
|
||||
nacl->fc_port = fc_port;
|
||||
|
||||
pr_debug("Setup nacl->qla_tgt_sess %p by loop_id for se_nacl: %p, initiatorname: %s\n",
|
||||
nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname);
|
||||
pr_debug("Setup nacl->fc_port %p by loop_id for se_nacl: %p, initiatorname: %s\n",
|
||||
nacl->fc_port, new_se_nacl, new_se_nacl->initiatorname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Should always be called with qla_hw_data->tgt.sess_lock held.
|
||||
*/
|
||||
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport,
|
||||
struct tcm_qla2xxx_nacl *nacl, struct qla_tgt_sess *sess)
|
||||
struct tcm_qla2xxx_nacl *nacl, struct fc_port *sess)
|
||||
{
|
||||
struct se_session *se_sess = sess->se_sess;
|
||||
unsigned char be_sid[3];
|
||||
|
||||
be_sid[0] = sess->s_id.b.domain;
|
||||
be_sid[1] = sess->s_id.b.area;
|
||||
be_sid[2] = sess->s_id.b.al_pa;
|
||||
be_sid[0] = sess->d_id.b.domain;
|
||||
be_sid[1] = sess->d_id.b.area;
|
||||
be_sid[2] = sess->d_id.b.al_pa;
|
||||
|
||||
tcm_qla2xxx_set_sess_by_s_id(lport, NULL, nacl, se_sess,
|
||||
sess, be_sid);
|
||||
|
@ -1365,7 +1415,7 @@ static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport,
|
|||
sess, sess->loop_id);
|
||||
}
|
||||
|
||||
static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
|
||||
static void tcm_qla2xxx_free_session(struct fc_port *sess)
|
||||
{
|
||||
struct qla_tgt *tgt = sess->tgt;
|
||||
struct qla_hw_data *ha = tgt->ha;
|
||||
|
@ -1377,7 +1427,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
|
|||
|
||||
se_sess = sess->se_sess;
|
||||
if (!se_sess) {
|
||||
pr_err("struct qla_tgt_sess->se_sess is NULL\n");
|
||||
pr_err("struct fc_port->se_sess is NULL\n");
|
||||
dump_stack();
|
||||
return;
|
||||
}
|
||||
|
@ -1404,14 +1454,14 @@ static int tcm_qla2xxx_session_cb(struct se_portal_group *se_tpg,
|
|||
struct se_node_acl *se_nacl = se_sess->se_node_acl;
|
||||
struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
|
||||
struct tcm_qla2xxx_nacl, se_node_acl);
|
||||
struct qla_tgt_sess *qlat_sess = p;
|
||||
struct fc_port *qlat_sess = p;
|
||||
uint16_t loop_id = qlat_sess->loop_id;
|
||||
unsigned long flags;
|
||||
unsigned char be_sid[3];
|
||||
|
||||
be_sid[0] = qlat_sess->s_id.b.domain;
|
||||
be_sid[1] = qlat_sess->s_id.b.area;
|
||||
be_sid[2] = qlat_sess->s_id.b.al_pa;
|
||||
be_sid[0] = qlat_sess->d_id.b.domain;
|
||||
be_sid[1] = qlat_sess->d_id.b.area;
|
||||
be_sid[2] = qlat_sess->d_id.b.al_pa;
|
||||
|
||||
/*
|
||||
* And now setup se_nacl and session pointers into HW lport internal
|
||||
|
@ -1434,7 +1484,7 @@ static int tcm_qla2xxx_session_cb(struct se_portal_group *se_tpg,
|
|||
static int tcm_qla2xxx_check_initiator_node_acl(
|
||||
scsi_qla_host_t *vha,
|
||||
unsigned char *fc_wwpn,
|
||||
struct qla_tgt_sess *qlat_sess)
|
||||
struct fc_port *qlat_sess)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct tcm_qla2xxx_lport *lport;
|
||||
|
@ -1478,7 +1528,7 @@ static int tcm_qla2xxx_check_initiator_node_acl(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
|
||||
static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id,
|
||||
uint16_t loop_id, bool conf_compl_supported)
|
||||
{
|
||||
struct qla_tgt *tgt = sess->tgt;
|
||||
|
@ -1491,11 +1541,11 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
|
|||
u32 key;
|
||||
|
||||
|
||||
if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
|
||||
if (sess->loop_id != loop_id || sess->d_id.b24 != s_id.b24)
|
||||
pr_info("Updating session %p from port %8phC loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
|
||||
sess, sess->port_name,
|
||||
sess->loop_id, loop_id, sess->s_id.b.domain,
|
||||
sess->s_id.b.area, sess->s_id.b.al_pa, s_id.b.domain,
|
||||
sess->loop_id, loop_id, sess->d_id.b.domain,
|
||||
sess->d_id.b.area, sess->d_id.b.al_pa, s_id.b.domain,
|
||||
s_id.b.area, s_id.b.al_pa);
|
||||
|
||||
if (sess->loop_id != loop_id) {
|
||||
|
@ -1515,18 +1565,20 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
|
|||
sess->loop_id = loop_id;
|
||||
}
|
||||
|
||||
if (sess->s_id.b24 != s_id.b24) {
|
||||
key = (((u32) sess->s_id.b.domain << 16) |
|
||||
((u32) sess->s_id.b.area << 8) |
|
||||
((u32) sess->s_id.b.al_pa));
|
||||
if (sess->d_id.b24 != s_id.b24) {
|
||||
key = (((u32) sess->d_id.b.domain << 16) |
|
||||
((u32) sess->d_id.b.area << 8) |
|
||||
((u32) sess->d_id.b.al_pa));
|
||||
|
||||
if (btree_lookup32(&lport->lport_fcport_map, key))
|
||||
WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
|
||||
"Found wrong se_nacl when updating s_id %x:%x:%x\n",
|
||||
sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
|
||||
WARN(btree_remove32(&lport->lport_fcport_map, key) !=
|
||||
se_nacl, "Found wrong se_nacl when updating s_id %x:%x:%x\n",
|
||||
sess->d_id.b.domain, sess->d_id.b.area,
|
||||
sess->d_id.b.al_pa);
|
||||
else
|
||||
WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
|
||||
sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
|
||||
sess->d_id.b.domain, sess->d_id.b.area,
|
||||
sess->d_id.b.al_pa);
|
||||
|
||||
key = (((u32) s_id.b.domain << 16) |
|
||||
((u32) s_id.b.area << 8) |
|
||||
|
@ -1537,10 +1589,11 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
|
|||
s_id.b.domain, s_id.b.area, s_id.b.al_pa);
|
||||
btree_update32(&lport->lport_fcport_map, key, se_nacl);
|
||||
} else {
|
||||
btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
|
||||
btree_insert32(&lport->lport_fcport_map, key, se_nacl,
|
||||
GFP_ATOMIC);
|
||||
}
|
||||
|
||||
sess->s_id = s_id;
|
||||
sess->d_id = s_id;
|
||||
nacl->nport_id = key;
|
||||
}
|
||||
|
||||
|
@ -1567,6 +1620,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
|
|||
.find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id,
|
||||
.find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id,
|
||||
.clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map,
|
||||
.put_sess = tcm_qla2xxx_put_sess,
|
||||
.shutdown_sess = tcm_qla2xxx_shutdown_sess,
|
||||
};
|
||||
|
||||
|
@ -1690,7 +1744,7 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
|
|||
(struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr;
|
||||
struct fc_vport_identifiers vport_id;
|
||||
|
||||
if (!qla_tgt_mode_enabled(base_vha)) {
|
||||
if (qla_ini_mode_enabled(base_vha)) {
|
||||
pr_err("qla2xxx base_vha not enabled for target mode\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ struct tcm_qla2xxx_nacl {
|
|||
u64 nport_wwnn;
|
||||
/* ASCII formatted WWPN for FC Initiator Nport */
|
||||
char nport_name[TCM_QLA2XXX_NAMELEN];
|
||||
/* Pointer to qla_tgt_sess */
|
||||
struct qla_tgt_sess *qla_tgt_sess;
|
||||
/* Pointer to fc_port */
|
||||
struct fc_port *fc_port;
|
||||
/* Pointer to TCM FC nexus */
|
||||
struct se_session *nport_nexus;
|
||||
};
|
||||
|
|
|
@ -872,7 +872,8 @@ cxgbit_offload_init(struct cxgbit_sock *csk, int iptype, __u8 *peer_ip,
|
|||
goto out;
|
||||
csk->mtu = ndev->mtu;
|
||||
csk->tx_chan = cxgb4_port_chan(ndev);
|
||||
csk->smac_idx = (cxgb4_port_viid(ndev) & 0x7F) << 1;
|
||||
csk->smac_idx = cxgb4_tp_smt_idx(cdev->lldi.adapter_type,
|
||||
cxgb4_port_viid(ndev));
|
||||
step = cdev->lldi.ntxq /
|
||||
cdev->lldi.nchan;
|
||||
csk->txq_idx = cxgb4_port_idx(ndev) * step;
|
||||
|
@ -907,7 +908,8 @@ cxgbit_offload_init(struct cxgbit_sock *csk, int iptype, __u8 *peer_ip,
|
|||
port_id = cxgb4_port_idx(ndev);
|
||||
csk->mtu = dst_mtu(dst);
|
||||
csk->tx_chan = cxgb4_port_chan(ndev);
|
||||
csk->smac_idx = (cxgb4_port_viid(ndev) & 0x7F) << 1;
|
||||
csk->smac_idx = cxgb4_tp_smt_idx(cdev->lldi.adapter_type,
|
||||
cxgb4_port_viid(ndev));
|
||||
step = cdev->lldi.ntxq /
|
||||
cdev->lldi.nports;
|
||||
csk->txq_idx = (port_id * step) +
|
||||
|
@ -1066,6 +1068,7 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
|
|||
struct sk_buff *skb;
|
||||
const struct tcphdr *tcph;
|
||||
struct cpl_t5_pass_accept_rpl *rpl5;
|
||||
struct cxgb4_lld_info *lldi = &csk->com.cdev->lldi;
|
||||
unsigned int len = roundup(sizeof(*rpl5), 16);
|
||||
unsigned int mtu_idx;
|
||||
u64 opt0;
|
||||
|
@ -1111,6 +1114,9 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
|
|||
opt2 = RX_CHANNEL_V(0) |
|
||||
RSS_QUEUE_VALID_F | RSS_QUEUE_V(csk->rss_qid);
|
||||
|
||||
if (!is_t5(lldi->adapter_type))
|
||||
opt2 |= RX_FC_DISABLE_F;
|
||||
|
||||
if (req->tcpopt.tstamp)
|
||||
opt2 |= TSTAMPS_EN_F;
|
||||
if (req->tcpopt.sack)
|
||||
|
@ -1119,8 +1125,13 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
|
|||
opt2 |= WND_SCALE_EN_F;
|
||||
|
||||
hlen = ntohl(req->hdr_len);
|
||||
tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) +
|
||||
IP_HDR_LEN_G(hlen);
|
||||
|
||||
if (is_t5(lldi->adapter_type))
|
||||
tcph = (struct tcphdr *)((u8 *)(req + 1) +
|
||||
ETH_HDR_LEN_G(hlen) + IP_HDR_LEN_G(hlen));
|
||||
else
|
||||
tcph = (struct tcphdr *)((u8 *)(req + 1) +
|
||||
T6_ETH_HDR_LEN_G(hlen) + T6_IP_HDR_LEN_G(hlen));
|
||||
|
||||
if (tcph->ece && tcph->cwr)
|
||||
opt2 |= CCTRL_ECN_V(1);
|
||||
|
@ -1726,7 +1737,7 @@ static bool cxgbit_credit_err(const struct cxgbit_sock *csk)
|
|||
}
|
||||
|
||||
while (skb) {
|
||||
credit += skb->csum;
|
||||
credit += (__force u32)skb->csum;
|
||||
skb = cxgbit_skcb_tx_wr_next(skb);
|
||||
}
|
||||
|
||||
|
@ -1753,6 +1764,7 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb)
|
|||
|
||||
while (credits) {
|
||||
struct sk_buff *p = cxgbit_sock_peek_wr(csk);
|
||||
const u32 csum = (__force u32)p->csum;
|
||||
|
||||
if (unlikely(!p)) {
|
||||
pr_err("csk 0x%p,%u, cr %u,%u+%u, empty.\n",
|
||||
|
@ -1761,17 +1773,17 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
|
||||
if (unlikely(credits < p->csum)) {
|
||||
if (unlikely(credits < csum)) {
|
||||
pr_warn("csk 0x%p,%u, cr %u,%u+%u, < %u.\n",
|
||||
csk, csk->tid,
|
||||
credits, csk->wr_cred, csk->wr_una_cred,
|
||||
p->csum);
|
||||
p->csum -= credits;
|
||||
csum);
|
||||
p->csum = (__force __wsum)(csum - credits);
|
||||
break;
|
||||
}
|
||||
|
||||
cxgbit_sock_dequeue_wr(csk);
|
||||
credits -= p->csum;
|
||||
credits -= csum;
|
||||
kfree_skb(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,9 @@ enum cxgbit_pducb_flags {
|
|||
PDUCBF_RX_DATA = (1 << 1), /* received pdu payload */
|
||||
PDUCBF_RX_STATUS = (1 << 2), /* received ddp status */
|
||||
PDUCBF_RX_DATA_DDPD = (1 << 3), /* pdu payload ddp'd */
|
||||
PDUCBF_RX_HCRC_ERR = (1 << 4), /* header digest error */
|
||||
PDUCBF_RX_DCRC_ERR = (1 << 5), /* data digest error */
|
||||
PDUCBF_RX_DDP_CMP = (1 << 4), /* ddp completion */
|
||||
PDUCBF_RX_HCRC_ERR = (1 << 5), /* header digest error */
|
||||
PDUCBF_RX_DCRC_ERR = (1 << 6), /* data digest error */
|
||||
};
|
||||
|
||||
struct cxgbit_lro_pdu_cb {
|
||||
|
|
|
@ -165,29 +165,24 @@ static int cxgbit_uld_state_change(void *handle, enum cxgb4_state state)
|
|||
}
|
||||
|
||||
static void
|
||||
cxgbit_proc_ddp_status(unsigned int tid, struct cpl_rx_data_ddp *cpl,
|
||||
struct cxgbit_lro_pdu_cb *pdu_cb)
|
||||
cxgbit_process_ddpvld(struct cxgbit_sock *csk, struct cxgbit_lro_pdu_cb *pdu_cb,
|
||||
u32 ddpvld)
|
||||
{
|
||||
unsigned int status = ntohl(cpl->ddpvld);
|
||||
|
||||
pdu_cb->flags |= PDUCBF_RX_STATUS;
|
||||
pdu_cb->ddigest = ntohl(cpl->ulp_crc);
|
||||
pdu_cb->pdulen = ntohs(cpl->len);
|
||||
|
||||
if (status & (1 << CPL_RX_ISCSI_DDP_STATUS_HCRC_SHIFT)) {
|
||||
pr_info("tid 0x%x, status 0x%x, hcrc bad.\n", tid, status);
|
||||
if (ddpvld & (1 << CPL_RX_ISCSI_DDP_STATUS_HCRC_SHIFT)) {
|
||||
pr_info("tid 0x%x, status 0x%x, hcrc bad.\n", csk->tid, ddpvld);
|
||||
pdu_cb->flags |= PDUCBF_RX_HCRC_ERR;
|
||||
}
|
||||
|
||||
if (status & (1 << CPL_RX_ISCSI_DDP_STATUS_DCRC_SHIFT)) {
|
||||
pr_info("tid 0x%x, status 0x%x, dcrc bad.\n", tid, status);
|
||||
if (ddpvld & (1 << CPL_RX_ISCSI_DDP_STATUS_DCRC_SHIFT)) {
|
||||
pr_info("tid 0x%x, status 0x%x, dcrc bad.\n", csk->tid, ddpvld);
|
||||
pdu_cb->flags |= PDUCBF_RX_DCRC_ERR;
|
||||
}
|
||||
|
||||
if (status & (1 << CPL_RX_ISCSI_DDP_STATUS_PAD_SHIFT))
|
||||
pr_info("tid 0x%x, status 0x%x, pad bad.\n", tid, status);
|
||||
if (ddpvld & (1 << CPL_RX_ISCSI_DDP_STATUS_PAD_SHIFT))
|
||||
pr_info("tid 0x%x, status 0x%x, pad bad.\n", csk->tid, ddpvld);
|
||||
|
||||
if ((status & (1 << CPL_RX_ISCSI_DDP_STATUS_DDP_SHIFT)) &&
|
||||
if ((ddpvld & (1 << CPL_RX_ISCSI_DDP_STATUS_DDP_SHIFT)) &&
|
||||
(!(pdu_cb->flags & PDUCBF_RX_DATA))) {
|
||||
pdu_cb->flags |= PDUCBF_RX_DATA_DDPD;
|
||||
}
|
||||
|
@ -201,13 +196,17 @@ cxgbit_lro_add_packet_rsp(struct sk_buff *skb, u8 op, const __be64 *rsp)
|
|||
lro_cb->pdu_idx);
|
||||
struct cpl_rx_iscsi_ddp *cpl = (struct cpl_rx_iscsi_ddp *)(rsp + 1);
|
||||
|
||||
cxgbit_proc_ddp_status(lro_cb->csk->tid, cpl, pdu_cb);
|
||||
cxgbit_process_ddpvld(lro_cb->csk, pdu_cb, be32_to_cpu(cpl->ddpvld));
|
||||
|
||||
pdu_cb->flags |= PDUCBF_RX_STATUS;
|
||||
pdu_cb->ddigest = ntohl(cpl->ulp_crc);
|
||||
pdu_cb->pdulen = ntohs(cpl->len);
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_HDR)
|
||||
pdu_cb->complete = true;
|
||||
|
||||
lro_cb->complete = true;
|
||||
lro_cb->pdu_totallen += pdu_cb->pdulen;
|
||||
lro_cb->complete = true;
|
||||
lro_cb->pdu_idx++;
|
||||
}
|
||||
|
||||
|
@ -257,7 +256,7 @@ cxgbit_lro_add_packet_gl(struct sk_buff *skb, u8 op, const struct pkt_gl *gl)
|
|||
cxgbit_skcb_flags(skb) = 0;
|
||||
|
||||
lro_cb->complete = false;
|
||||
} else {
|
||||
} else if (op == CPL_ISCSI_DATA) {
|
||||
struct cpl_iscsi_data *cpl = (struct cpl_iscsi_data *)gl->va;
|
||||
|
||||
offset = sizeof(struct cpl_iscsi_data);
|
||||
|
@ -267,6 +266,36 @@ cxgbit_lro_add_packet_gl(struct sk_buff *skb, u8 op, const struct pkt_gl *gl)
|
|||
pdu_cb->doffset = lro_cb->offset;
|
||||
pdu_cb->nr_dfrags = gl->nfrags;
|
||||
pdu_cb->dfrag_idx = skb_shinfo(skb)->nr_frags;
|
||||
lro_cb->complete = false;
|
||||
} else {
|
||||
struct cpl_rx_iscsi_cmp *cpl;
|
||||
|
||||
cpl = (struct cpl_rx_iscsi_cmp *)gl->va;
|
||||
offset = sizeof(struct cpl_rx_iscsi_cmp);
|
||||
pdu_cb->flags |= (PDUCBF_RX_HDR | PDUCBF_RX_STATUS);
|
||||
len = be16_to_cpu(cpl->len);
|
||||
pdu_cb->hdr = gl->va + offset;
|
||||
pdu_cb->hlen = len;
|
||||
pdu_cb->hfrag_idx = skb_shinfo(skb)->nr_frags;
|
||||
pdu_cb->ddigest = be32_to_cpu(cpl->ulp_crc);
|
||||
pdu_cb->pdulen = ntohs(cpl->len);
|
||||
|
||||
if (unlikely(gl->nfrags > 1))
|
||||
cxgbit_skcb_flags(skb) = 0;
|
||||
|
||||
cxgbit_process_ddpvld(lro_cb->csk, pdu_cb,
|
||||
be32_to_cpu(cpl->ddpvld));
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_DATA_DDPD) {
|
||||
pdu_cb->flags |= PDUCBF_RX_DDP_CMP;
|
||||
pdu_cb->complete = true;
|
||||
} else if (pdu_cb->flags & PDUCBF_RX_DATA) {
|
||||
pdu_cb->complete = true;
|
||||
}
|
||||
|
||||
lro_cb->pdu_totallen += pdu_cb->hlen + pdu_cb->dlen;
|
||||
lro_cb->complete = true;
|
||||
lro_cb->pdu_idx++;
|
||||
}
|
||||
|
||||
cxgbit_copy_frags(skb, gl, offset);
|
||||
|
@ -413,6 +442,7 @@ cxgbit_uld_lro_rx_handler(void *hndl, const __be64 *rsp,
|
|||
switch (op) {
|
||||
case CPL_ISCSI_HDR:
|
||||
case CPL_ISCSI_DATA:
|
||||
case CPL_RX_ISCSI_CMP:
|
||||
case CPL_RX_ISCSI_DDP:
|
||||
case CPL_FW4_ACK:
|
||||
lro_flush = false;
|
||||
|
@ -454,12 +484,13 @@ cxgbit_uld_lro_rx_handler(void *hndl, const __be64 *rsp,
|
|||
if (unlikely(op != *(u8 *)gl->va)) {
|
||||
pr_info("? FL 0x%p,RSS%#llx,FL %#llx,len %u.\n",
|
||||
gl->va, be64_to_cpu(*rsp),
|
||||
be64_to_cpu(*(u64 *)gl->va),
|
||||
get_unaligned_be64(gl->va),
|
||||
gl->tot_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (op == CPL_ISCSI_HDR || op == CPL_ISCSI_DATA) {
|
||||
if ((op == CPL_ISCSI_HDR) || (op == CPL_ISCSI_DATA) ||
|
||||
(op == CPL_RX_ISCSI_CMP)) {
|
||||
if (!cxgbit_lro_receive(csk, op, rsp, gl, lro_mgr,
|
||||
napi))
|
||||
return 0;
|
||||
|
|
|
@ -162,12 +162,14 @@ cxgbit_tx_data_wr(struct cxgbit_sock *csk, struct sk_buff *skb, u32 dlen,
|
|||
u32 len, u32 credits, u32 compl)
|
||||
{
|
||||
struct fw_ofld_tx_data_wr *req;
|
||||
const struct cxgb4_lld_info *lldi = &csk->com.cdev->lldi;
|
||||
u32 submode = cxgbit_skcb_submode(skb);
|
||||
u32 wr_ulp_mode = 0;
|
||||
u32 hdr_size = sizeof(*req);
|
||||
u32 opcode = FW_OFLD_TX_DATA_WR;
|
||||
u32 immlen = 0;
|
||||
u32 force = TX_FORCE_V(!submode);
|
||||
u32 force = is_t5(lldi->adapter_type) ? TX_FORCE_V(!submode) :
|
||||
T6_TX_FORCE_F;
|
||||
|
||||
if (cxgbit_skcb_flags(skb) & SKCBF_TX_ISO) {
|
||||
opcode = FW_ISCSI_TX_DATA_WR;
|
||||
|
@ -243,7 +245,7 @@ void cxgbit_push_tx_frames(struct cxgbit_sock *csk)
|
|||
}
|
||||
__skb_unlink(skb, &csk->txq);
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, csk->txq_idx);
|
||||
skb->csum = credits_needed + flowclen16;
|
||||
skb->csum = (__force __wsum)(credits_needed + flowclen16);
|
||||
csk->wr_cred -= credits_needed;
|
||||
csk->wr_una_cred += credits_needed;
|
||||
|
||||
|
@ -651,26 +653,6 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
|
|||
u32 max_npdu, max_iso_npdu;
|
||||
|
||||
if (conn->login->leading_connection) {
|
||||
param = iscsi_find_param_from_key(DATASEQUENCEINORDER,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
pr_err("param not found key %s\n", DATASEQUENCEINORDER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(param->value, YES))
|
||||
return 0;
|
||||
|
||||
param = iscsi_find_param_from_key(DATAPDUINORDER,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
pr_err("param not found key %s\n", DATAPDUINORDER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(param->value, YES))
|
||||
return 0;
|
||||
|
||||
param = iscsi_find_param_from_key(MAXBURSTLENGTH,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
|
@ -681,11 +663,6 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
|
|||
if (kstrtou32(param->value, 0, &mbl) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
if (!conn->sess->sess_ops->DataSequenceInOrder)
|
||||
return 0;
|
||||
if (!conn->sess->sess_ops->DataPDUInOrder)
|
||||
return 0;
|
||||
|
||||
mbl = conn->sess->sess_ops->MaxBurstLength;
|
||||
}
|
||||
|
||||
|
@ -704,6 +681,53 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cxgbit_seq_pdu_inorder()
|
||||
* @csk: pointer to cxgbit socket structure
|
||||
*
|
||||
* This function checks whether data sequence and data
|
||||
* pdu are in order.
|
||||
*
|
||||
* Return: returns -1 on error, 0 if data sequence and
|
||||
* data pdu are in order, 1 if data sequence or data pdu
|
||||
* is not in order.
|
||||
*/
|
||||
static int cxgbit_seq_pdu_inorder(struct cxgbit_sock *csk)
|
||||
{
|
||||
struct iscsi_conn *conn = csk->conn;
|
||||
struct iscsi_param *param;
|
||||
|
||||
if (conn->login->leading_connection) {
|
||||
param = iscsi_find_param_from_key(DATASEQUENCEINORDER,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
pr_err("param not found key %s\n", DATASEQUENCEINORDER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(param->value, YES))
|
||||
return 1;
|
||||
|
||||
param = iscsi_find_param_from_key(DATAPDUINORDER,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
pr_err("param not found key %s\n", DATAPDUINORDER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(param->value, YES))
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
if (!conn->sess->sess_ops->DataSequenceInOrder)
|
||||
return 1;
|
||||
if (!conn->sess->sess_ops->DataPDUInOrder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxgbit_set_params(struct iscsi_conn *conn)
|
||||
{
|
||||
struct cxgbit_sock *csk = conn->context;
|
||||
|
@ -730,11 +754,24 @@ static int cxgbit_set_params(struct iscsi_conn *conn)
|
|||
}
|
||||
|
||||
if (!erl) {
|
||||
int ret;
|
||||
|
||||
ret = cxgbit_seq_pdu_inorder(csk);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
} else if (ret > 0) {
|
||||
if (is_t5(cdev->lldi.adapter_type))
|
||||
goto enable_ddp;
|
||||
else
|
||||
goto enable_digest;
|
||||
}
|
||||
|
||||
if (test_bit(CDEV_ISO_ENABLE, &cdev->flags)) {
|
||||
if (cxgbit_set_iso_npdu(csk))
|
||||
return -1;
|
||||
}
|
||||
|
||||
enable_ddp:
|
||||
if (test_bit(CDEV_DDP_ENABLE, &cdev->flags)) {
|
||||
if (cxgbit_setup_conn_pgidx(csk,
|
||||
ppm->tformat.pgsz_idx_dflt))
|
||||
|
@ -743,6 +780,7 @@ static int cxgbit_set_params(struct iscsi_conn *conn)
|
|||
}
|
||||
}
|
||||
|
||||
enable_digest:
|
||||
if (cxgbit_set_digest(csk))
|
||||
return -1;
|
||||
|
||||
|
@ -983,11 +1021,36 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
|
|||
int rc, sg_nents, sg_off;
|
||||
bool dcrc_err = false;
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_DDP_CMP) {
|
||||
u32 offset = be32_to_cpu(hdr->offset);
|
||||
u32 ddp_data_len;
|
||||
u32 payload_length = ntoh24(hdr->dlength);
|
||||
bool success = false;
|
||||
|
||||
cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, 0);
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
ddp_data_len = offset - cmd->write_data_done;
|
||||
atomic_long_add(ddp_data_len, &conn->sess->rx_data_octets);
|
||||
|
||||
cmd->write_data_done = offset;
|
||||
cmd->next_burst_len = ddp_data_len;
|
||||
cmd->data_sn = be32_to_cpu(hdr->datasn);
|
||||
|
||||
rc = __iscsit_check_dataout_hdr(conn, (unsigned char *)hdr,
|
||||
cmd, payload_length, &success);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
else if (!success)
|
||||
return 0;
|
||||
} else {
|
||||
rc = iscsit_check_dataout_hdr(conn, (unsigned char *)hdr, &cmd);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
else if (!cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_DCRC_ERR) {
|
||||
pr_err("ITT: 0x%08x, Offset: %u, Length: %u,"
|
||||
|
@ -1351,6 +1414,9 @@ static void cxgbit_lro_hskb_reset(struct cxgbit_sock *csk)
|
|||
for (i = 0; i < ssi->nr_frags; i++)
|
||||
put_page(skb_frag_page(&ssi->frags[i]));
|
||||
ssi->nr_frags = 0;
|
||||
skb->data_len = 0;
|
||||
skb->truesize -= skb->len;
|
||||
skb->len = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1364,39 +1430,42 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx)
|
|||
unsigned int len = 0;
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_HDR) {
|
||||
hpdu_cb->flags = pdu_cb->flags;
|
||||
u8 hfrag_idx = hssi->nr_frags;
|
||||
|
||||
hpdu_cb->flags |= pdu_cb->flags;
|
||||
hpdu_cb->seq = pdu_cb->seq;
|
||||
hpdu_cb->hdr = pdu_cb->hdr;
|
||||
hpdu_cb->hlen = pdu_cb->hlen;
|
||||
|
||||
memcpy(&hssi->frags[0], &ssi->frags[pdu_cb->hfrag_idx],
|
||||
sizeof(skb_frag_t));
|
||||
|
||||
get_page(skb_frag_page(&hssi->frags[0]));
|
||||
hssi->nr_frags = 1;
|
||||
hpdu_cb->frags = 1;
|
||||
hpdu_cb->hfrag_idx = 0;
|
||||
|
||||
len = hssi->frags[0].size;
|
||||
hskb->len = len;
|
||||
hskb->data_len = len;
|
||||
hskb->truesize = len;
|
||||
}
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_DATA) {
|
||||
u8 hfrag_idx = 1, i;
|
||||
|
||||
hpdu_cb->flags |= pdu_cb->flags;
|
||||
|
||||
len = 0;
|
||||
for (i = 0; i < pdu_cb->nr_dfrags; hfrag_idx++, i++) {
|
||||
memcpy(&hssi->frags[hfrag_idx],
|
||||
&ssi->frags[pdu_cb->dfrag_idx + i],
|
||||
memcpy(&hssi->frags[hfrag_idx], &ssi->frags[pdu_cb->hfrag_idx],
|
||||
sizeof(skb_frag_t));
|
||||
|
||||
get_page(skb_frag_page(&hssi->frags[hfrag_idx]));
|
||||
hssi->nr_frags++;
|
||||
hpdu_cb->frags++;
|
||||
hpdu_cb->hfrag_idx = hfrag_idx;
|
||||
|
||||
len += hssi->frags[hfrag_idx].size;
|
||||
len = hssi->frags[hfrag_idx].size;
|
||||
hskb->len += len;
|
||||
hskb->data_len += len;
|
||||
hskb->truesize += len;
|
||||
}
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_DATA) {
|
||||
u8 dfrag_idx = hssi->nr_frags, i;
|
||||
|
||||
hpdu_cb->flags |= pdu_cb->flags;
|
||||
hpdu_cb->dfrag_idx = dfrag_idx;
|
||||
|
||||
len = 0;
|
||||
for (i = 0; i < pdu_cb->nr_dfrags; dfrag_idx++, i++) {
|
||||
memcpy(&hssi->frags[dfrag_idx],
|
||||
&ssi->frags[pdu_cb->dfrag_idx + i],
|
||||
sizeof(skb_frag_t));
|
||||
|
||||
get_page(skb_frag_page(&hssi->frags[dfrag_idx]));
|
||||
|
||||
len += hssi->frags[dfrag_idx].size;
|
||||
|
||||
hssi->nr_frags++;
|
||||
hpdu_cb->frags++;
|
||||
|
@ -1405,7 +1474,6 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx)
|
|||
hpdu_cb->dlen = pdu_cb->dlen;
|
||||
hpdu_cb->doffset = hpdu_cb->hlen;
|
||||
hpdu_cb->nr_dfrags = pdu_cb->nr_dfrags;
|
||||
hpdu_cb->dfrag_idx = 1;
|
||||
hskb->len += len;
|
||||
hskb->data_len += len;
|
||||
hskb->truesize += len;
|
||||
|
@ -1490,10 +1558,15 @@ static int cxgbit_rx_lro_skb(struct cxgbit_sock *csk, struct sk_buff *skb)
|
|||
|
||||
static int cxgbit_rx_skb(struct cxgbit_sock *csk, struct sk_buff *skb)
|
||||
{
|
||||
struct cxgb4_lld_info *lldi = &csk->com.cdev->lldi;
|
||||
int ret = -1;
|
||||
|
||||
if (likely(cxgbit_skcb_flags(skb) & SKCBF_RX_LRO))
|
||||
if (likely(cxgbit_skcb_flags(skb) & SKCBF_RX_LRO)) {
|
||||
if (is_t5(lldi->adapter_type))
|
||||
ret = cxgbit_rx_lro_skb(csk, skb);
|
||||
else
|
||||
ret = cxgbit_process_lro_skb(csk, skb);
|
||||
}
|
||||
|
||||
__kfree_skb(skb);
|
||||
return ret;
|
||||
|
|
|
@ -1431,36 +1431,17 @@ static void iscsit_do_crypto_hash_buf(
|
|||
}
|
||||
|
||||
int
|
||||
iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
|
||||
struct iscsi_cmd **out_cmd)
|
||||
__iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
|
||||
struct iscsi_cmd *cmd, u32 payload_length,
|
||||
bool *success)
|
||||
{
|
||||
struct iscsi_data *hdr = (struct iscsi_data *)buf;
|
||||
struct iscsi_cmd *cmd = NULL;
|
||||
struct iscsi_data *hdr = buf;
|
||||
struct se_cmd *se_cmd;
|
||||
u32 payload_length = ntoh24(hdr->dlength);
|
||||
int rc;
|
||||
|
||||
if (!payload_length) {
|
||||
pr_warn("DataOUT payload is ZERO, ignoring.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* iSCSI write */
|
||||
atomic_long_add(payload_length, &conn->sess->rx_data_octets);
|
||||
|
||||
if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
|
||||
pr_err("DataSegmentLength: %u is greater than"
|
||||
" MaxXmitDataSegmentLength: %u\n", payload_length,
|
||||
conn->conn_ops->MaxXmitDataSegmentLength);
|
||||
return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
|
||||
buf);
|
||||
}
|
||||
|
||||
cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt,
|
||||
payload_length);
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x,"
|
||||
" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
|
||||
hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset),
|
||||
|
@ -1545,7 +1526,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
|
|||
}
|
||||
}
|
||||
/*
|
||||
* Preform DataSN, DataSequenceInOrder, DataPDUInOrder, and
|
||||
* Perform DataSN, DataSequenceInOrder, DataPDUInOrder, and
|
||||
* within-command recovery checks before receiving the payload.
|
||||
*/
|
||||
rc = iscsit_check_pre_dataout(cmd, buf);
|
||||
|
@ -1553,10 +1534,44 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
|
|||
return 0;
|
||||
else if (rc == DATAOUT_CANNOT_RECOVER)
|
||||
return -1;
|
||||
|
||||
*out_cmd = cmd;
|
||||
*success = true;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__iscsit_check_dataout_hdr);
|
||||
|
||||
int
|
||||
iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
|
||||
struct iscsi_cmd **out_cmd)
|
||||
{
|
||||
struct iscsi_data *hdr = buf;
|
||||
struct iscsi_cmd *cmd;
|
||||
u32 payload_length = ntoh24(hdr->dlength);
|
||||
int rc;
|
||||
bool success = false;
|
||||
|
||||
if (!payload_length) {
|
||||
pr_warn_ratelimited("DataOUT payload is ZERO, ignoring.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
|
||||
pr_err_ratelimited("DataSegmentLength: %u is greater than"
|
||||
" MaxXmitDataSegmentLength: %u\n", payload_length,
|
||||
conn->conn_ops->MaxXmitDataSegmentLength);
|
||||
return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf);
|
||||
}
|
||||
|
||||
cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, payload_length);
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
rc = __iscsit_check_dataout_hdr(conn, buf, cmd, payload_length, &success);
|
||||
|
||||
if (success)
|
||||
*out_cmd = cmd;
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_check_dataout_hdr);
|
||||
|
||||
static int
|
||||
|
@ -1920,6 +1935,28 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static enum tcm_tmreq_table iscsit_convert_tmf(u8 iscsi_tmf)
|
||||
{
|
||||
switch (iscsi_tmf) {
|
||||
case ISCSI_TM_FUNC_ABORT_TASK:
|
||||
return TMR_ABORT_TASK;
|
||||
case ISCSI_TM_FUNC_ABORT_TASK_SET:
|
||||
return TMR_ABORT_TASK_SET;
|
||||
case ISCSI_TM_FUNC_CLEAR_ACA:
|
||||
return TMR_CLEAR_ACA;
|
||||
case ISCSI_TM_FUNC_CLEAR_TASK_SET:
|
||||
return TMR_CLEAR_TASK_SET;
|
||||
case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
|
||||
return TMR_LUN_RESET;
|
||||
case ISCSI_TM_FUNC_TARGET_WARM_RESET:
|
||||
return TMR_TARGET_WARM_RESET;
|
||||
case ISCSI_TM_FUNC_TARGET_COLD_RESET:
|
||||
return TMR_TARGET_COLD_RESET;
|
||||
default:
|
||||
return TMR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
unsigned char *buf)
|
||||
|
@ -1929,7 +1966,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||
struct iscsi_tm *hdr;
|
||||
int out_of_order_cmdsn = 0, ret;
|
||||
bool sess_ref = false;
|
||||
u8 function;
|
||||
u8 function, tcm_function = TMR_UNKNOWN;
|
||||
|
||||
hdr = (struct iscsi_tm *) buf;
|
||||
hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
|
||||
|
@ -1975,54 +2012,27 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||
* LIO-Target $FABRIC_MOD
|
||||
*/
|
||||
if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
|
||||
|
||||
u8 tcm_function;
|
||||
int ret;
|
||||
|
||||
transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
|
||||
conn->sess->se_sess, 0, DMA_NONE,
|
||||
TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
|
||||
|
||||
target_get_sess_cmd(&cmd->se_cmd, true);
|
||||
sess_ref = true;
|
||||
|
||||
switch (function) {
|
||||
case ISCSI_TM_FUNC_ABORT_TASK:
|
||||
tcm_function = TMR_ABORT_TASK;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_ABORT_TASK_SET:
|
||||
tcm_function = TMR_ABORT_TASK_SET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_CLEAR_ACA:
|
||||
tcm_function = TMR_CLEAR_ACA;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_CLEAR_TASK_SET:
|
||||
tcm_function = TMR_CLEAR_TASK_SET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
|
||||
tcm_function = TMR_LUN_RESET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_TARGET_WARM_RESET:
|
||||
tcm_function = TMR_TARGET_WARM_RESET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_TARGET_COLD_RESET:
|
||||
tcm_function = TMR_TARGET_COLD_RESET;
|
||||
break;
|
||||
default:
|
||||
tcm_function = iscsit_convert_tmf(function);
|
||||
if (tcm_function == TMR_UNKNOWN) {
|
||||
pr_err("Unknown iSCSI TMR Function:"
|
||||
" 0x%02x\n", function);
|
||||
return iscsit_add_reject_cmd(cmd,
|
||||
ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
|
||||
}
|
||||
|
||||
ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req,
|
||||
tcm_function, GFP_KERNEL);
|
||||
}
|
||||
ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, tcm_function,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
return iscsit_add_reject_cmd(cmd,
|
||||
ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
|
||||
|
||||
cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
|
||||
}
|
||||
|
||||
cmd->iscsi_opcode = ISCSI_OP_SCSI_TMFUNC;
|
||||
cmd->i_state = ISTATE_SEND_TASKMGTRSP;
|
||||
|
@ -4136,7 +4146,7 @@ int iscsit_close_connection(
|
|||
/*
|
||||
* During Connection recovery drop unacknowledged out of order
|
||||
* commands for this connection, and prepare the other commands
|
||||
* for realligence.
|
||||
* for reallegiance.
|
||||
*
|
||||
* During normal operation clear the out of order commands (but
|
||||
* do not free the struct iscsi_ooo_cmdsn's) and release all
|
||||
|
@ -4144,7 +4154,7 @@ int iscsit_close_connection(
|
|||
*/
|
||||
if (atomic_read(&conn->connection_recovery)) {
|
||||
iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(conn);
|
||||
iscsit_prepare_cmds_for_realligance(conn);
|
||||
iscsit_prepare_cmds_for_reallegiance(conn);
|
||||
} else {
|
||||
iscsit_clear_ooo_cmdsns_for_conn(conn);
|
||||
iscsit_release_commands_from_conn(conn);
|
||||
|
|
|
@ -44,10 +44,8 @@ void iscsit_set_dataout_sequence_values(
|
|||
*/
|
||||
if (cmd->unsolicited_data) {
|
||||
cmd->seq_start_offset = cmd->write_data_done;
|
||||
cmd->seq_end_offset = (cmd->write_data_done +
|
||||
((cmd->se_cmd.data_length >
|
||||
conn->sess->sess_ops->FirstBurstLength) ?
|
||||
conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length));
|
||||
cmd->seq_end_offset = min(cmd->se_cmd.data_length,
|
||||
conn->sess->sess_ops->FirstBurstLength);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -312,7 +312,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
||||
int iscsit_prepare_cmds_for_reallegiance(struct iscsi_conn *conn)
|
||||
{
|
||||
u32 cmd_count = 0;
|
||||
struct iscsi_cmd *cmd, *cmd_tmp;
|
||||
|
@ -347,7 +347,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
|||
|
||||
if ((cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD) &&
|
||||
(cmd->iscsi_opcode != ISCSI_OP_NOOP_OUT)) {
|
||||
pr_debug("Not performing realligence on"
|
||||
pr_debug("Not performing reallegiance on"
|
||||
" Opcode: 0x%02x, ITT: 0x%08x, CmdSN: 0x%08x,"
|
||||
" CID: %hu\n", cmd->iscsi_opcode,
|
||||
cmd->init_task_tag, cmd->cmd_sn, conn->cid);
|
||||
|
@ -382,7 +382,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
|||
cmd_count++;
|
||||
pr_debug("Preparing Opcode: 0x%02x, ITT: 0x%08x,"
|
||||
" CmdSN: 0x%08x, StatSN: 0x%08x, CID: %hu for"
|
||||
" realligence.\n", cmd->iscsi_opcode,
|
||||
" reallegiance.\n", cmd->iscsi_opcode,
|
||||
cmd->init_task_tag, cmd->cmd_sn, cmd->stat_sn,
|
||||
conn->cid);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ extern int iscsit_remove_cmd_from_connection_recovery(struct iscsi_cmd *,
|
|||
struct iscsi_session *);
|
||||
extern void iscsit_discard_cr_cmds_by_expstatsn(struct iscsi_conn_recovery *, u32);
|
||||
extern int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *);
|
||||
extern int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *);
|
||||
extern int iscsit_prepare_cmds_for_reallegiance(struct iscsi_conn *);
|
||||
extern int iscsit_connection_recovery_transport_reset(struct iscsi_conn *);
|
||||
|
||||
#endif /*** ISCSI_TARGET_ERL2_H ***/
|
||||
|
|
|
@ -223,7 +223,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
|
|||
return 0;
|
||||
|
||||
pr_debug("%s iSCSI Session SID %u is still active for %s,"
|
||||
" preforming session reinstatement.\n", (sessiontype) ?
|
||||
" performing session reinstatement.\n", (sessiontype) ?
|
||||
"Discovery" : "Normal", sess->sid,
|
||||
sess->sess_ops->InitiatorName);
|
||||
|
||||
|
|
|
@ -440,14 +440,14 @@ static int iscsit_task_reassign_complete(
|
|||
break;
|
||||
default:
|
||||
pr_err("Illegal iSCSI Opcode 0x%02x during"
|
||||
" command realligence\n", cmd->iscsi_opcode);
|
||||
" command reallegiance\n", cmd->iscsi_opcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
pr_debug("Completed connection realligence for Opcode: 0x%02x,"
|
||||
pr_debug("Completed connection reallegiance for Opcode: 0x%02x,"
|
||||
" ITT: 0x%08x to CID: %hu.\n", cmd->iscsi_opcode,
|
||||
cmd->init_task_tag, conn->cid);
|
||||
|
||||
|
|
|
@ -417,6 +417,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
|
|||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_find_cmd_from_itt_or_dump);
|
||||
|
||||
struct iscsi_cmd *iscsit_find_cmd_from_ttt(
|
||||
struct iscsi_conn *conn,
|
||||
|
@ -1377,33 +1378,6 @@ int tx_data(
|
|||
return iscsit_do_tx_data(conn, &c);
|
||||
}
|
||||
|
||||
static bool sockaddr_equal(struct sockaddr_storage *x, struct sockaddr_storage *y)
|
||||
{
|
||||
switch (x->ss_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *sinx = (struct sockaddr_in *)x;
|
||||
struct sockaddr_in *siny = (struct sockaddr_in *)y;
|
||||
if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
|
||||
return false;
|
||||
if (sinx->sin_port != siny->sin_port)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
|
||||
struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
|
||||
if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
|
||||
return false;
|
||||
if (sinx->sin6_port != siny->sin6_port)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void iscsit_collect_login_stats(
|
||||
struct iscsi_conn *conn,
|
||||
u8 status_class,
|
||||
|
@ -1420,13 +1394,6 @@ void iscsit_collect_login_stats(
|
|||
ls = &tiqn->login_stats;
|
||||
|
||||
spin_lock(&ls->lock);
|
||||
if (sockaddr_equal(&conn->login_sockaddr, &ls->last_intr_fail_sockaddr) &&
|
||||
((get_jiffies_64() - ls->last_fail_time) < 10)) {
|
||||
/* We already have the failure info for this login */
|
||||
spin_unlock(&ls->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status_class == ISCSI_STATUS_CLS_SUCCESS)
|
||||
ls->accepts++;
|
||||
else if (status_class == ISCSI_STATUS_CLS_REDIRECT) {
|
||||
|
@ -1471,10 +1438,10 @@ struct iscsi_tiqn *iscsit_snmp_get_tiqn(struct iscsi_conn *conn)
|
|||
{
|
||||
struct iscsi_portal_group *tpg;
|
||||
|
||||
if (!conn || !conn->sess)
|
||||
if (!conn)
|
||||
return NULL;
|
||||
|
||||
tpg = conn->sess->tpg;
|
||||
tpg = conn->tpg;
|
||||
if (!tpg)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -78,12 +78,16 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
|
|||
&deve->read_bytes);
|
||||
|
||||
se_lun = rcu_dereference(deve->se_lun);
|
||||
|
||||
if (!percpu_ref_tryget_live(&se_lun->lun_ref)) {
|
||||
se_lun = NULL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
se_cmd->se_lun = rcu_dereference(deve->se_lun);
|
||||
se_cmd->pr_res_key = deve->pr_res_key;
|
||||
se_cmd->orig_fe_lun = unpacked_lun;
|
||||
se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
|
||||
|
||||
percpu_ref_get(&se_lun->lun_ref);
|
||||
se_cmd->lun_ref_active = true;
|
||||
|
||||
if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
|
||||
|
@ -97,6 +101,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
|
|||
goto ref_dev;
|
||||
}
|
||||
}
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!se_lun) {
|
||||
|
@ -163,7 +168,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
|
|||
rcu_read_lock();
|
||||
deve = target_nacl_find_deve(nacl, unpacked_lun);
|
||||
if (deve) {
|
||||
se_tmr->tmr_lun = rcu_dereference(deve->se_lun);
|
||||
se_cmd->se_lun = rcu_dereference(deve->se_lun);
|
||||
se_lun = rcu_dereference(deve->se_lun);
|
||||
se_cmd->pr_res_key = deve->pr_res_key;
|
||||
|
@ -816,6 +820,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
|||
xcopy_lun = &dev->xcopy_lun;
|
||||
rcu_assign_pointer(xcopy_lun->lun_se_dev, dev);
|
||||
init_completion(&xcopy_lun->lun_ref_comp);
|
||||
init_completion(&xcopy_lun->lun_shutdown_comp);
|
||||
INIT_LIST_HEAD(&xcopy_lun->lun_deve_list);
|
||||
INIT_LIST_HEAD(&xcopy_lun->lun_dev_link);
|
||||
mutex_init(&xcopy_lun->lun_tg_pt_md_mutex);
|
||||
|
|
|
@ -604,7 +604,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
|
|||
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
cmd->t_state = TRANSPORT_PROCESSING;
|
||||
cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
|
||||
cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
|
||||
__target_execute_cmd(cmd, false);
|
||||
|
|
|
@ -158,12 +158,28 @@ static ssize_t target_stat_tgt_resets_show(struct config_item *item,
|
|||
atomic_long_read(&to_stat_tgt_dev(item)->num_resets));
|
||||
}
|
||||
|
||||
static ssize_t target_stat_tgt_aborts_complete_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
return snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&to_stat_tgt_dev(item)->aborts_complete));
|
||||
}
|
||||
|
||||
static ssize_t target_stat_tgt_aborts_no_task_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
return snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&to_stat_tgt_dev(item)->aborts_no_task));
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, inst);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, indx);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, num_lus);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, status);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, non_access_lus);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, resets);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, aborts_complete);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, aborts_no_task);
|
||||
|
||||
static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
|
||||
&target_stat_tgt_attr_inst,
|
||||
|
@ -172,6 +188,8 @@ static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
|
|||
&target_stat_tgt_attr_status,
|
||||
&target_stat_tgt_attr_non_access_lus,
|
||||
&target_stat_tgt_attr_resets,
|
||||
&target_stat_tgt_attr_aborts_complete,
|
||||
&target_stat_tgt_attr_aborts_no_task,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -795,16 +813,34 @@ static ssize_t target_stat_transport_dev_name_show(struct config_item *item,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t target_stat_transport_proto_id_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
struct se_lun *lun = to_transport_stat(item);
|
||||
struct se_device *dev;
|
||||
struct se_portal_group *tpg = lun->lun_tpg;
|
||||
ssize_t ret = -ENODEV;
|
||||
|
||||
rcu_read_lock();
|
||||
dev = rcu_dereference(lun->lun_se_dev);
|
||||
if (dev)
|
||||
ret = snprintf(page, PAGE_SIZE, "%u\n", tpg->proto_id);
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, inst);
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, device);
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, indx);
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, dev_name);
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, proto_id);
|
||||
|
||||
static struct configfs_attribute *target_stat_scsi_transport_attrs[] = {
|
||||
&target_stat_transport_attr_inst,
|
||||
&target_stat_transport_attr_device,
|
||||
&target_stat_transport_attr_indx,
|
||||
&target_stat_transport_attr_dev_name,
|
||||
&target_stat_transport_attr_proto_id,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -175,10 +175,9 @@ void core_tmr_abort_task(
|
|||
printk("ABORT_TASK: Found referenced %s task_tag: %llu\n",
|
||||
se_cmd->se_tfo->get_fabric_name(), ref_tag);
|
||||
|
||||
if (!__target_check_io_state(se_cmd, se_sess, 0)) {
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
if (!__target_check_io_state(se_cmd, se_sess, 0))
|
||||
continue;
|
||||
|
||||
list_del_init(&se_cmd->se_cmd_list);
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
|
||||
|
@ -191,14 +190,15 @@ void core_tmr_abort_task(
|
|||
printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
|
||||
" ref_tag: %llu\n", ref_tag);
|
||||
tmr->response = TMR_FUNCTION_COMPLETE;
|
||||
atomic_long_inc(&dev->aborts_complete);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
|
||||
out:
|
||||
printk("ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: %lld\n",
|
||||
tmr->ref_task_tag);
|
||||
tmr->response = TMR_TASK_DOES_NOT_EXIST;
|
||||
atomic_long_inc(&dev->aborts_no_task);
|
||||
}
|
||||
|
||||
static void core_tmr_drain_tmr_list(
|
||||
|
@ -217,13 +217,8 @@ static void core_tmr_drain_tmr_list(
|
|||
* LUN_RESET tmr..
|
||||
*/
|
||||
spin_lock_irqsave(&dev->se_tmr_lock, flags);
|
||||
list_del_init(&tmr->tmr_list);
|
||||
list_for_each_entry_safe(tmr_p, tmr_pp, &dev->dev_tmr_list, tmr_list) {
|
||||
/*
|
||||
* Allow the received TMR to return with FUNCTION_COMPLETE.
|
||||
*/
|
||||
if (tmr_p == tmr)
|
||||
continue;
|
||||
|
||||
cmd = tmr_p->task_cmd;
|
||||
if (!cmd) {
|
||||
pr_err("Unable to locate struct se_cmd for TMR\n");
|
||||
|
|
|
@ -445,7 +445,7 @@ static void core_tpg_lun_ref_release(struct percpu_ref *ref)
|
|||
{
|
||||
struct se_lun *lun = container_of(ref, struct se_lun, lun_ref);
|
||||
|
||||
complete(&lun->lun_ref_comp);
|
||||
complete(&lun->lun_shutdown_comp);
|
||||
}
|
||||
|
||||
/* Does not change se_wwn->priv. */
|
||||
|
@ -572,6 +572,7 @@ struct se_lun *core_tpg_alloc_lun(
|
|||
lun->lun_link_magic = SE_LUN_LINK_MAGIC;
|
||||
atomic_set(&lun->lun_acl_count, 0);
|
||||
init_completion(&lun->lun_ref_comp);
|
||||
init_completion(&lun->lun_shutdown_comp);
|
||||
INIT_LIST_HEAD(&lun->lun_deve_list);
|
||||
INIT_LIST_HEAD(&lun->lun_dev_link);
|
||||
atomic_set(&lun->lun_tg_pt_secondary_offline, 0);
|
||||
|
|
|
@ -593,9 +593,6 @@ static void target_remove_from_state_list(struct se_cmd *cmd)
|
|||
if (!dev)
|
||||
return;
|
||||
|
||||
if (cmd->transport_state & CMD_T_BUSY)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev->execute_task_lock, flags);
|
||||
if (cmd->state_active) {
|
||||
list_del(&cmd->state_list);
|
||||
|
@ -604,24 +601,18 @@ static void target_remove_from_state_list(struct se_cmd *cmd)
|
|||
spin_unlock_irqrestore(&dev->execute_task_lock, flags);
|
||||
}
|
||||
|
||||
static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
|
||||
bool write_pending)
|
||||
static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (remove_from_lists) {
|
||||
target_remove_from_state_list(cmd);
|
||||
|
||||
/*
|
||||
* Clear struct se_cmd->se_lun before the handoff to FE.
|
||||
*/
|
||||
cmd->se_lun = NULL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||
if (write_pending)
|
||||
cmd->t_state = TRANSPORT_WRITE_PENDING;
|
||||
|
||||
/*
|
||||
* Determine if frontend context caller is requesting the stopping of
|
||||
* this command for frontend exceptions.
|
||||
|
@ -635,31 +626,18 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
|
|||
complete_all(&cmd->t_transport_stop_comp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmd->transport_state &= ~CMD_T_ACTIVE;
|
||||
if (remove_from_lists) {
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
|
||||
/*
|
||||
* Some fabric modules like tcm_loop can release
|
||||
* their internally allocated I/O reference now and
|
||||
* struct se_cmd now.
|
||||
* Some fabric modules like tcm_loop can release their internally
|
||||
* allocated I/O reference and struct se_cmd now.
|
||||
*
|
||||
* Fabric modules are expected to return '1' here if the
|
||||
* se_cmd being passed is released at this point,
|
||||
* or zero if not being released.
|
||||
* Fabric modules are expected to return '1' here if the se_cmd being
|
||||
* passed is released at this point, or zero if not being released.
|
||||
*/
|
||||
if (cmd->se_tfo->check_stop_free != NULL) {
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
return cmd->se_tfo->check_stop_free(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
|
||||
{
|
||||
return transport_cmd_check_stop(cmd, true, false);
|
||||
return cmd->se_tfo->check_stop_free ? cmd->se_tfo->check_stop_free(cmd)
|
||||
: 0;
|
||||
}
|
||||
|
||||
static void transport_lun_remove_cmd(struct se_cmd *cmd)
|
||||
|
@ -733,7 +711,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
|
|||
|
||||
|
||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||
cmd->transport_state &= ~CMD_T_BUSY;
|
||||
|
||||
if (dev && dev->transport->transport_complete) {
|
||||
dev->transport->transport_complete(cmd,
|
||||
|
@ -1246,7 +1223,6 @@ void transport_init_se_cmd(
|
|||
init_completion(&cmd->cmd_wait_comp);
|
||||
spin_lock_init(&cmd->t_state_lock);
|
||||
kref_init(&cmd->cmd_kref);
|
||||
cmd->transport_state = CMD_T_DEV_ACTIVE;
|
||||
|
||||
cmd->se_tfo = tfo;
|
||||
cmd->se_sess = se_sess;
|
||||
|
@ -1671,6 +1647,9 @@ void transport_generic_request_failure(struct se_cmd *cmd,
|
|||
{
|
||||
int ret = 0, post_ret = 0;
|
||||
|
||||
if (transport_check_aborted_status(cmd, 1))
|
||||
return;
|
||||
|
||||
pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08llx"
|
||||
" CDB: 0x%02x\n", cmd, cmd->tag, cmd->t_task_cdb[0]);
|
||||
pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n",
|
||||
|
@ -1801,7 +1780,7 @@ void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
|
|||
return;
|
||||
err:
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
|
||||
cmd->transport_state &= ~CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
|
||||
transport_generic_request_failure(cmd, ret);
|
||||
|
@ -1829,7 +1808,7 @@ static int target_write_prot_action(struct se_cmd *cmd)
|
|||
sectors, 0, cmd->t_prot_sg, 0);
|
||||
if (unlikely(cmd->pi_err)) {
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
|
||||
cmd->transport_state &= ~CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
transport_generic_request_failure(cmd, cmd->pi_err);
|
||||
return -1;
|
||||
|
@ -1918,7 +1897,7 @@ void target_execute_cmd(struct se_cmd *cmd)
|
|||
}
|
||||
|
||||
cmd->t_state = TRANSPORT_PROCESSING;
|
||||
cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
|
||||
cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
|
||||
if (target_write_prot_action(cmd))
|
||||
|
@ -1926,7 +1905,7 @@ void target_execute_cmd(struct se_cmd *cmd)
|
|||
|
||||
if (target_handle_task_attr(cmd)) {
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
cmd->transport_state &= ~(CMD_T_BUSY | CMD_T_SENT);
|
||||
cmd->transport_state &= ~CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
return;
|
||||
}
|
||||
|
@ -1979,8 +1958,6 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
|
|||
if (cmd->sam_task_attr == TCM_SIMPLE_TAG) {
|
||||
atomic_dec_mb(&dev->simple_cmds);
|
||||
dev->dev_cur_ordered_id++;
|
||||
pr_debug("Incremented dev->dev_cur_ordered_id: %u for SIMPLE\n",
|
||||
dev->dev_cur_ordered_id);
|
||||
} else if (cmd->sam_task_attr == TCM_HEAD_TAG) {
|
||||
dev->dev_cur_ordered_id++;
|
||||
pr_debug("Incremented dev_cur_ordered_id: %u for HEAD_OF_QUEUE\n",
|
||||
|
@ -2387,6 +2364,7 @@ EXPORT_SYMBOL(target_alloc_sgl);
|
|||
sense_reason_t
|
||||
transport_generic_new_cmd(struct se_cmd *cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
|
||||
|
||||
|
@ -2452,7 +2430,24 @@ transport_generic_new_cmd(struct se_cmd *cmd)
|
|||
target_execute_cmd(cmd);
|
||||
return 0;
|
||||
}
|
||||
transport_cmd_check_stop(cmd, false, true);
|
||||
|
||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||
cmd->t_state = TRANSPORT_WRITE_PENDING;
|
||||
/*
|
||||
* Determine if frontend context caller is requesting the stopping of
|
||||
* this command for frontend exceptions.
|
||||
*/
|
||||
if (cmd->transport_state & CMD_T_STOP) {
|
||||
pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n",
|
||||
__func__, __LINE__, cmd->tag);
|
||||
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
|
||||
complete_all(&cmd->t_transport_stop_comp);
|
||||
return 0;
|
||||
}
|
||||
cmd->transport_state &= ~CMD_T_ACTIVE;
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
|
||||
ret = cmd->se_tfo->write_pending(cmd);
|
||||
if (ret == -EAGAIN || ret == -ENOMEM)
|
||||
|
@ -2595,6 +2590,7 @@ static void target_release_cmd_kref(struct kref *kref)
|
|||
unsigned long flags;
|
||||
bool fabric_stop;
|
||||
|
||||
if (se_sess) {
|
||||
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
|
||||
|
||||
spin_lock(&se_cmd->t_state_lock);
|
||||
|
@ -2611,23 +2607,21 @@ static void target_release_cmd_kref(struct kref *kref)
|
|||
}
|
||||
list_del_init(&se_cmd->se_cmd_list);
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
}
|
||||
|
||||
target_free_cmd_mem(se_cmd);
|
||||
se_cmd->se_tfo->release_cmd(se_cmd);
|
||||
}
|
||||
|
||||
/* target_put_sess_cmd - Check for active I/O shutdown via kref_put
|
||||
* @se_cmd: command descriptor to drop
|
||||
/**
|
||||
* target_put_sess_cmd - decrease the command reference count
|
||||
* @se_cmd: command to drop a reference from
|
||||
*
|
||||
* Returns 1 if and only if this target_put_sess_cmd() call caused the
|
||||
* refcount to drop to zero. Returns zero otherwise.
|
||||
*/
|
||||
int target_put_sess_cmd(struct se_cmd *se_cmd)
|
||||
{
|
||||
struct se_session *se_sess = se_cmd->se_sess;
|
||||
|
||||
if (!se_sess) {
|
||||
target_free_cmd_mem(se_cmd);
|
||||
se_cmd->se_tfo->release_cmd(se_cmd);
|
||||
return 1;
|
||||
}
|
||||
return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
|
||||
}
|
||||
EXPORT_SYMBOL(target_put_sess_cmd);
|
||||
|
@ -2706,10 +2700,39 @@ void target_wait_for_sess_cmds(struct se_session *se_sess)
|
|||
}
|
||||
EXPORT_SYMBOL(target_wait_for_sess_cmds);
|
||||
|
||||
static void target_lun_confirm(struct percpu_ref *ref)
|
||||
{
|
||||
struct se_lun *lun = container_of(ref, struct se_lun, lun_ref);
|
||||
|
||||
complete(&lun->lun_ref_comp);
|
||||
}
|
||||
|
||||
void transport_clear_lun_ref(struct se_lun *lun)
|
||||
{
|
||||
percpu_ref_kill(&lun->lun_ref);
|
||||
/*
|
||||
* Mark the percpu-ref as DEAD, switch to atomic_t mode, drop
|
||||
* the initial reference and schedule confirm kill to be
|
||||
* executed after one full RCU grace period has completed.
|
||||
*/
|
||||
percpu_ref_kill_and_confirm(&lun->lun_ref, target_lun_confirm);
|
||||
/*
|
||||
* The first completion waits for percpu_ref_switch_to_atomic_rcu()
|
||||
* to call target_lun_confirm after lun->lun_ref has been marked
|
||||
* as __PERCPU_REF_DEAD on all CPUs, and switches to atomic_t
|
||||
* mode so that percpu_ref_tryget_live() lookup of lun->lun_ref
|
||||
* fails for all new incoming I/O.
|
||||
*/
|
||||
wait_for_completion(&lun->lun_ref_comp);
|
||||
/*
|
||||
* The second completion waits for percpu_ref_put_many() to
|
||||
* invoke ->release() after lun->lun_ref has switched to
|
||||
* atomic_t mode, and lun->lun_ref.count has reached zero.
|
||||
*
|
||||
* At this point all target-core lun->lun_ref references have
|
||||
* been dropped via transport_lun_remove_cmd(), and it's safe
|
||||
* to proceed with the remaining LUN shutdown.
|
||||
*/
|
||||
wait_for_completion(&lun->lun_shutdown_comp);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -2765,11 +2788,8 @@ __transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop,
|
|||
}
|
||||
|
||||
/**
|
||||
* transport_wait_for_tasks - wait for completion to occur
|
||||
* @cmd: command to wait
|
||||
*
|
||||
* Called from frontend fabric context to wait for storage engine
|
||||
* to pause and/or release frontend generated struct se_cmd.
|
||||
* transport_wait_for_tasks - set CMD_T_STOP and wait for t_transport_stop_comp
|
||||
* @cmd: command to wait on
|
||||
*/
|
||||
bool transport_wait_for_tasks(struct se_cmd *cmd)
|
||||
{
|
||||
|
|
|
@ -83,14 +83,12 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
|
|||
static void ft_free_cmd(struct ft_cmd *cmd)
|
||||
{
|
||||
struct fc_frame *fp;
|
||||
struct fc_lport *lport;
|
||||
struct ft_sess *sess;
|
||||
|
||||
if (!cmd)
|
||||
return;
|
||||
sess = cmd->sess;
|
||||
fp = cmd->req_frame;
|
||||
lport = fr_dev(fp);
|
||||
if (fr_seq(fp))
|
||||
fc_seq_release(fr_seq(fp));
|
||||
fc_frame_free(fp);
|
||||
|
|
|
@ -55,8 +55,12 @@ extern int iscsit_setup_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *,
|
|||
extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);
|
||||
extern int iscsit_process_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *,
|
||||
struct iscsi_scsi_req *);
|
||||
extern int iscsit_check_dataout_hdr(struct iscsi_conn *, unsigned char *,
|
||||
struct iscsi_cmd **);
|
||||
extern int
|
||||
__iscsit_check_dataout_hdr(struct iscsi_conn *, void *,
|
||||
struct iscsi_cmd *, u32, bool *);
|
||||
extern int
|
||||
iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
|
||||
struct iscsi_cmd **out_cmd);
|
||||
extern int iscsit_check_dataout_payload(struct iscsi_cmd *, struct iscsi_data *,
|
||||
bool);
|
||||
extern int iscsit_setup_nop_out(struct iscsi_conn *, struct iscsi_cmd *,
|
||||
|
@ -125,6 +129,9 @@ extern void iscsit_release_cmd(struct iscsi_cmd *);
|
|||
extern void iscsit_free_cmd(struct iscsi_cmd *, bool);
|
||||
extern void iscsit_add_cmd_to_immediate_queue(struct iscsi_cmd *,
|
||||
struct iscsi_conn *, u8);
|
||||
extern struct iscsi_cmd *
|
||||
iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *conn,
|
||||
itt_t init_task_tag, u32 length);
|
||||
|
||||
/*
|
||||
* From iscsi_target_nego.c
|
||||
|
|
|
@ -197,6 +197,7 @@ enum tcm_tmreq_table {
|
|||
TMR_LUN_RESET = 5,
|
||||
TMR_TARGET_WARM_RESET = 6,
|
||||
TMR_TARGET_COLD_RESET = 7,
|
||||
TMR_UNKNOWN = 0xff,
|
||||
};
|
||||
|
||||
/* fabric independent task management response values */
|
||||
|
@ -397,7 +398,6 @@ struct se_tmr_req {
|
|||
void *fabric_tmr_ptr;
|
||||
struct se_cmd *task_cmd;
|
||||
struct se_device *tmr_dev;
|
||||
struct se_lun *tmr_lun;
|
||||
struct list_head tmr_list;
|
||||
};
|
||||
|
||||
|
@ -488,8 +488,6 @@ struct se_cmd {
|
|||
#define CMD_T_COMPLETE (1 << 2)
|
||||
#define CMD_T_SENT (1 << 4)
|
||||
#define CMD_T_STOP (1 << 5)
|
||||
#define CMD_T_DEV_ACTIVE (1 << 7)
|
||||
#define CMD_T_BUSY (1 << 9)
|
||||
#define CMD_T_TAS (1 << 10)
|
||||
#define CMD_T_FABRIC_STOP (1 << 11)
|
||||
spinlock_t t_state_lock;
|
||||
|
@ -732,6 +730,7 @@ struct se_lun {
|
|||
struct config_group lun_group;
|
||||
struct se_port_stat_grps port_stat_grps;
|
||||
struct completion lun_ref_comp;
|
||||
struct completion lun_shutdown_comp;
|
||||
struct percpu_ref lun_ref;
|
||||
struct list_head lun_dev_link;
|
||||
struct hlist_node link;
|
||||
|
@ -767,6 +766,8 @@ struct se_device {
|
|||
u32 dev_index;
|
||||
u64 creation_time;
|
||||
atomic_long_t num_resets;
|
||||
atomic_long_t aborts_complete;
|
||||
atomic_long_t aborts_no_task;
|
||||
atomic_long_t num_cmds;
|
||||
atomic_long_t read_bytes;
|
||||
atomic_long_t write_bytes;
|
||||
|
|
|
@ -47,7 +47,7 @@ struct target_core_fabric_ops {
|
|||
u32 (*tpg_get_inst_index)(struct se_portal_group *);
|
||||
/*
|
||||
* Optional to release struct se_cmd and fabric dependent allocated
|
||||
* I/O descriptor in transport_cmd_check_stop().
|
||||
* I/O descriptor after command execution has finished.
|
||||
*
|
||||
* Returning 1 will signal a descriptor has been released.
|
||||
* Returning 0 will signal a descriptor has not been released.
|
||||
|
|
|
@ -105,26 +105,26 @@ struct tcmu_cmd_entry {
|
|||
|
||||
union {
|
||||
struct {
|
||||
uint32_t iov_cnt;
|
||||
uint32_t iov_bidi_cnt;
|
||||
uint32_t iov_dif_cnt;
|
||||
uint64_t cdb_off;
|
||||
uint64_t __pad1;
|
||||
uint64_t __pad2;
|
||||
__u32 iov_cnt;
|
||||
__u32 iov_bidi_cnt;
|
||||
__u32 iov_dif_cnt;
|
||||
__u64 cdb_off;
|
||||
__u64 __pad1;
|
||||
__u64 __pad2;
|
||||
struct iovec iov[0];
|
||||
} req;
|
||||
struct {
|
||||
uint8_t scsi_status;
|
||||
uint8_t __pad1;
|
||||
uint16_t __pad2;
|
||||
uint32_t __pad3;
|
||||
__u8 scsi_status;
|
||||
__u8 __pad1;
|
||||
__u16 __pad2;
|
||||
__u32 __pad3;
|
||||
char sense_buffer[TCMU_SENSE_BUFFERSIZE];
|
||||
} rsp;
|
||||
};
|
||||
|
||||
} __packed;
|
||||
|
||||
#define TCMU_OP_ALIGN_SIZE sizeof(uint64_t)
|
||||
#define TCMU_OP_ALIGN_SIZE sizeof(__u64)
|
||||
|
||||
enum tcmu_genl_cmd {
|
||||
TCMU_CMD_UNSPEC,
|
||||
|
|
Loading…
Reference in New Issue