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:
Linus Torvalds 2017-03-02 14:52:05 -08:00
commit 821fd6f6cb
43 changed files with 4761 additions and 2829 deletions

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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;
}

View File

@ -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,10 +2141,22 @@ 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.
*/
typedef enum {
typedef enum {
FCT_UNKNOWN,
FCT_RSCN,
FCT_SWITCH,
@ -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,11 +2955,11 @@ 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_fdmi_iocb) (struct scsi_qla_host *, 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);
uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint8_t *(*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
int (*write_nvram) (struct scsi_qla_host *, uint8_t *, 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 {

View File

@ -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->loop_id);
}
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);
}

View File

@ -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 vp_idx_map[16];
uint8_t ls_rjt_vendor;
uint8_t ls_rjt_explanation;
uint8_t ls_rjt_reason;
uint8_t rsv3[5];
uint8_t reserved_4[24];
uint16_t bbcr;
uint8_t reserved_5[6];
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. */

View File

@ -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 */

View File

@ -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,
@ -2530,9 +2565,10 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
int rval;
uint16_t i;
struct qla_hw_data *ha = vha->hw;
ms_iocb_entry_t *ms_pkt;
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

View File

@ -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);

View File

@ -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;

View File

@ -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);
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
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);
qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
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,53 +1429,66 @@ 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;
bsg_job = sp->u.bsg_job;
bsg_reply = bsg_job->reply;
switch (sp->type) {
case SRB_CT_CMD:
bsg_job = sp->u.bsg_job;
bsg_reply = bsg_job->reply;
type = "ct pass-through";
type = "ct pass-through";
comp_status = le16_to_cpu(pkt->comp_status);
comp_status = le16_to_cpu(pkt->comp_status);
/* 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;
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
/*
* 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;
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
if (comp_status != CS_COMPLETE) {
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
if (comp_status != CS_COMPLETE) {
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
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",
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);
res = DID_ERROR << 16;
bsg_reply->reply_payload_rcv_len = 0;
}
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
(uint8_t *)pkt, sizeof(*pkt));
} else {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
bsg_job->reply_payload.payload_len;
bsg_job->reply_len = 0;
ql_log(ql_log_warn, vha, 0x5048,
"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=0x%x.\n",
type, comp_status);
res = DID_ERROR << 16;
bsg_reply->reply_payload_rcv_len = 0;
}
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
(uint8_t *)pkt, sizeof(*pkt));
} else {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
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,
"Port to be marked lost on fcport=%02x%02x%02x, current "
"port state= %s.\n", fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
port_state_str[atomic_read(&fcport->state)]);
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 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)],
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,8 +2790,9 @@ process_err:
if (IS_P3P_TYPE(ha)) {
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
WRT_REG_DWORD(&reg->rsp_q_out[0], rsp->ring_index);
} else
} else {
WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
}
}
static void

View File

@ -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,80 +3611,124 @@ 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;
/* FA-WWN is only for physical port */
if (!vp_idx) {
void *wwpn = ha->init_cb->port_name;
if (rptid_entry->vp_idx == 0) {
if (rptid_entry->vp_status == VP_STAT_COMPL) {
/* FA-WWN is only for physical port */
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);
}
if (!MSB(stat)) {
if (rptid_entry->vp_idx_map[1] & BIT_6)
wwpn = rptid_entry->reserved_4 + 8;
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);
}
memcpy(vha->port_name, wwpn, WWN_SIZE);
fc_host_port_name(vha->host) =
wwn_to_u64(vha->port_name);
ql_dbg(ql_dbg_mbx, vha, 0x1018,
"FA-WWN portname %016llx (%x)\n",
fc_host_port_name(vha->host), MSB(stat));
}
vp = vha;
if (vp_idx == 0)
goto reg_needed;
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),
rptid_entry->vp_status);
if (MSB(stat) != 0 && MSB(stat) != 2) {
ql_dbg(ql_dbg_mbx, vha, 0x10ba,
"Could not acquire ID for VP[%d].\n", 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) {
found = 1;
break;
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",
rptid_entry->vp_idx);
return;
}
found = 0;
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list) {
if (rptid_entry->vp_idx == vp->vp_idx) {
found = 1;
break;
}
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
if (!found)
return;
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);
set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags);
set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags);
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
if (!found)
return;
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];
/*
* 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);
}
}

View File

@ -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,

View File

@ -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,77 +4591,38 @@ 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;
} 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
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_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);
} else {
fcport->login_retry = 0;
}
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);
} else {
fcport->login_retry = 0;
if (fcport->login_retry == 0 &&
status != QLA_SUCCESS)
qla2x00_clear_loop_id(fcport);
}
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

View File

@ -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)

View File

@ -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,
@ -697,13 +747,13 @@ 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;
((cmd->state == QLA_TGT_STATE_DATA_IN) &&
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;
}

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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 {

View File

@ -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;

View File

@ -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;
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_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],
memcpy(&hssi->frags[hfrag_idx], &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;
get_page(skb_frag_page(&hssi->frags[hfrag_idx]));
hssi->nr_frags++;
hpdu_cb->frags++;
hpdu_cb->hfrag_idx = hfrag_idx;
len = hssi->frags[0].size;
hskb->len = len;
hskb->data_len = len;
hskb->truesize = len;
len = hssi->frags[hfrag_idx].size;
hskb->len += len;
hskb->data_len += len;
hskb->truesize += len;
}
if (pdu_cb->flags & PDUCBF_RX_DATA) {
u8 hfrag_idx = 1, i;
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; hfrag_idx++, i++) {
memcpy(&hssi->frags[hfrag_idx],
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[hfrag_idx]));
get_page(skb_frag_page(&hssi->frags[dfrag_idx]));
len += hssi->frags[hfrag_idx].size;
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))
ret = cxgbit_rx_lro_skb(csk, skb);
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;

View File

@ -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);
if (ret < 0)
return iscsit_add_reject_cmd(cmd,
}
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->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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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 ***/

View File

@ -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);

View File

@ -1249,16 +1249,16 @@ int iscsi_target_start_negotiation(
{
int ret;
if (conn->sock) {
struct sock *sk = conn->sock->sk;
if (conn->sock) {
struct sock *sk = conn->sock->sk;
write_lock_bh(&sk->sk_callback_lock);
set_bit(LOGIN_FLAGS_READY, &conn->login_flags);
write_unlock_bh(&sk->sk_callback_lock);
}
write_lock_bh(&sk->sk_callback_lock);
set_bit(LOGIN_FLAGS_READY, &conn->login_flags);
write_unlock_bh(&sk->sk_callback_lock);
}
ret = iscsi_target_do_login(conn, login);
if (ret < 0) {
ret = iscsi_target_do_login(conn, login);
if (ret < 0) {
cancel_delayed_work_sync(&conn->login_work);
cancel_delayed_work_sync(&conn->login_cleanup_work);
iscsi_target_restore_sock_callbacks(conn);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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,
};

View File

@ -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");

View File

@ -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);

View File

@ -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);
target_remove_from_state_list(cmd);
/*
* Clear struct se_cmd->se_lun before the handoff to FE.
*/
cmd->se_lun = NULL;
}
/*
* 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) {
/*
* Some fabric modules like tcm_loop can release
* their internally allocated I/O reference now 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.
*/
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);
/*
* 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.
*/
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,39 +2590,38 @@ static void target_release_cmd_kref(struct kref *kref)
unsigned long flags;
bool fabric_stop;
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
if (se_sess) {
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
spin_lock(&se_cmd->t_state_lock);
fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) &&
(se_cmd->transport_state & CMD_T_ABORTED);
spin_unlock(&se_cmd->t_state_lock);
spin_lock(&se_cmd->t_state_lock);
fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) &&
(se_cmd->transport_state & CMD_T_ABORTED);
spin_unlock(&se_cmd->t_state_lock);
if (se_cmd->cmd_wait_set || fabric_stop) {
if (se_cmd->cmd_wait_set || fabric_stop) {
list_del_init(&se_cmd->se_cmd_list);
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
target_free_cmd_mem(se_cmd);
complete(&se_cmd->cmd_wait_comp);
return;
}
list_del_init(&se_cmd->se_cmd_list);
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
target_free_cmd_mem(se_cmd);
complete(&se_cmd->cmd_wait_comp);
return;
}
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)
{

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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,