Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Mar 2017 22:52:05 +0000 (14:52 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Mar 2017 22:52:05 +0000 (14:52 -0800)
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
  ...

12 files changed:
1  2 
drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_tpg.c
include/target/target_core_base.h

index 5043b64805f0b2fb74a4535131f731f7dc7fa302,21fc2fe1fc10c6d4e5cba43ad2084d88828da46d..8098c93cd16e680cee122f494cb8b0590b593181
@@@ -1175,21 -1175,6 +1175,21 @@@ struct cpl_rx_pkt 
  #define RXERR_CSUM_V(x) ((x) << RXERR_CSUM_S)
  #define RXERR_CSUM_F    RXERR_CSUM_V(1U)
  
 +#define T6_COMPR_RXERR_LEN_S    1
 +#define T6_COMPR_RXERR_LEN_V(x) ((x) << T6_COMPR_RXERR_LEN_S)
 +#define T6_COMPR_RXERR_LEN_F    T6_COMPR_RXERR_LEN_V(1U)
 +
 +#define T6_COMPR_RXERR_VEC_S    0
 +#define T6_COMPR_RXERR_VEC_M    0x3F
 +#define T6_COMPR_RXERR_VEC_V(x) ((x) << T6_COMPR_RXERR_LEN_S)
 +#define T6_COMPR_RXERR_VEC_G(x) \
 +              (((x) >> T6_COMPR_RXERR_VEC_S) & T6_COMPR_RXERR_VEC_M)
 +
 +/* Logical OR of RX_ERROR_CSUM, RX_ERROR_CSIP */
 +#define T6_COMPR_RXERR_SUM_S    4
 +#define T6_COMPR_RXERR_SUM_V(x) ((x) << T6_COMPR_RXERR_SUM_S)
 +#define T6_COMPR_RXERR_SUM_F    T6_COMPR_RXERR_SUM_V(1U)
 +
  struct cpl_trace_pkt {
        u8 opcode;
        u8 intf;
@@@ -1364,6 -1349,10 +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,
index 40ca75bbcb9d3e3864df45ac5e69bb3df57f7ec7,975e7a1175329d81701fe266f10a84de564f9664..84c9098cc089fc599774dfc82dc029895d229060
  
  /* 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 +59,7 @@@
            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 +391,7 @@@ qla2x00_process_els(struct bsg_job *bsg
        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 +539,7 @@@ qla2x00_process_ct(struct bsg_job *bsg_
        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;
        }
@@@ -921,7 -918,7 +918,7 @@@ qla2x00_process_loopback(struct bsg_jo
  
        bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
            sizeof(response) + sizeof(uint8_t);
 -      fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
 +      fw_sts_ptr = ((uint8_t *)scsi_req(bsg_job->req)->sense) +
            sizeof(struct fc_bsg_reply);
        memcpy(fw_sts_ptr, response, sizeof(response));
        fw_sts_ptr += sizeof(response);
@@@ -2578,6 -2575,6 +2575,6 @@@ qla24xx_bsg_timeout(struct bsg_job *bsg
  
  done:
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
-       sp->free(vha, sp);
+       sp->free(sp);
        return 0;
  }
index 2f14adfab018d845505f8f67844ae2153769191b,ac37e91aee209fa5655726c6d708283439b0c747..625d438e3cce01e39a57bfdd3d581ac24e6a5c55
@@@ -55,6 -55,8 +55,8 @@@
  
  #include "qla_settings.h"
  
+ #define MODE_DUAL (MODE_TARGET | MODE_INITIATOR)
  /*
   * Data bit definitions
   */
  
  #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 +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 +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
                        __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;
  #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 +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 +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 +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,
        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 +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;
  
  
        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 +2398,10 @@@ static const char * const port_state_st
  #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
@@@ -2248,7 -2496,7 +2496,7 @@@ struct ct_fdmiv2_hba_attr 
                uint32_t num_ports;
                uint8_t fabric_name[WWN_SIZE];
                uint8_t bios_name[32];
 -              uint8_t vendor_indentifer[8];
 +              uint8_t vendor_identifier[8];
        } a;
  };
  
@@@ -2423,7 -2671,7 +2671,7 @@@ struct ct_sns_req 
                } rsnn_nn;
  
                struct {
 -                      uint8_t hba_indentifier[8];
 +                      uint8_t hba_identifier[8];
                } ghat;
  
                struct {
                        uint8_t reserved;
                        uint8_t port_name[3];
                } gff_id;
+               struct {
+                       uint8_t port_name[8];
+               } gid_pn;
        } req;
  };
  
@@@ -2558,6 -2810,10 +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 +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 +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 +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 +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 +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 +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 +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
        /* 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;
        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 {
index ee3df87948067ca090686af57dc900deb448eb02,6d500fd0676817e5c2dc34edf450a0f45ea802f6..ab0f873fd6a1d9a6fe34d09b9af60366f59385fe
@@@ -24,12 -24,12 +24,12 @@@ static int qla2x00_sns_rnn_id(scsi_qla_
   * 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;
        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++;
   * 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 +117,7 @@@ qla2x00_prep_ct_req(struct ct_sns_pkt *
        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 +183,21 @@@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc
        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 +276,24 @@@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw
        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 +359,22 @@@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw
        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 +428,22 @@@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw
        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 +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 +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,
                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 +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 +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,
                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 +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;
@@@ -1939,15 -1997,15 +1997,15 @@@ qla2x00_fdmiv2_rhba(scsi_qla_host_t *vh
        /* Vendor Identifier */
        eiter = entries + size;
        eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER);
 -      snprintf(eiter->a.vendor_indentifer, sizeof(eiter->a.vendor_indentifer),
 +      snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier),
            "%s", "QLGC");
 -      alen = strlen(eiter->a.vendor_indentifer);
 +      alen = strlen(eiter->a.vendor_identifier);
        alen += 4 - (alen & 3);
        eiter->len = cpu_to_be16(4 + alen);
        size += 4 + alen;
  
        ql_dbg(ql_dbg_disc, vha, 0x20b1,
 -          "Vendor Identifier = %s.\n", eiter->a.vendor_indentifer);
 +          "Vendor Identifier = %s.\n", eiter->a.vendor_identifier);
  
        /* Update MS request size. */
        qla2x00_update_ms_fdmi_iocb(vha, size + 16);
@@@ -2425,15 -2483,22 +2483,22 @@@ qla2x00_gfpn_id(scsi_qla_host_t *vha, s
        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,
        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 +2565,10 @@@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_i
        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;
        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 +2683,7 @@@ qla2x00_gff_id(scsi_qla_host_t *vha, sw
        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
                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,
                        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;
+ }
index 265e1395bdb837315bfea3f698fc60270b794da9,ac579fc5f202316087da53e1413a5c1ab1e68a42..32fb9007f13770e4cd43650521b67e991a66d3e9
@@@ -30,15 -30,15 +30,15 @@@ static int qla2x00_configure_hba(scsi_q
  static int qla2x00_configure_loop(scsi_qla_host_t *);
  static int qla2x00_configure_local_loop(scsi_qla_host_t *);
  static int qla2x00_configure_fabric(scsi_qla_host_t *);
- static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *, struct list_head *);
- static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
-     uint16_t *);
+ static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *);
  static int qla2x00_restart_isp(scsi_qla_host_t *);
  
  static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
  static int qla84xx_init_chip(scsi_qla_host_t *);
  static int qla25xx_init_queues(struct qla_hw_data *);
+ static int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
+ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
+     struct event_arg *);
  
  /* SRB Extensions ---------------------------------------------------------- */
  
@@@ -47,29 -47,27 +47,27 @@@ qla2x00_sp_timeout(unsigned long __data
  {
        srb_t *sp = (srb_t *)__data;
        struct srb_iocb *iocb;
-       fc_port_t *fcport = sp->fcport;
-       struct qla_hw_data *ha = fcport->vha->hw;
+       scsi_qla_host_t *vha = sp->vha;
        struct req_que *req;
        unsigned long flags;
  
-       spin_lock_irqsave(&ha->hardware_lock, flags);
-       req = ha->req_q_map[0];
+       spin_lock_irqsave(&vha->hw->hardware_lock, flags);
+       req = vha->hw->req_q_map[0];
        req->outstanding_cmds[sp->handle] = NULL;
        iocb = &sp->u.iocb_cmd;
        iocb->timeout(sp);
-       sp->free(fcport->vha, sp);
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       sp->free(sp);
+       spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
  }
  
  void
- qla2x00_sp_free(void *data, void *ptr)
+ qla2x00_sp_free(void *ptr)
  {
-       srb_t *sp = (srb_t *)ptr;
+       srb_t *sp = ptr;
        struct srb_iocb *iocb = &sp->u.iocb_cmd;
-       struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
  
        del_timer(&iocb->timer);
-       qla2x00_rel_sp(vha, sp);
+       qla2x00_rel_sp(sp);
  }
  
  /* Asynchronous Login/Logout Routines -------------------------------------- */
@@@ -94,43 -92,72 +92,72 @@@ qla2x00_get_async_timeout(struct scsi_q
        return tmo;
  }
  
static void
+ void
  qla2x00_async_iocb_timeout(void *data)
  {
-       srb_t *sp = (srb_t *)data;
+       srb_t *sp = data;
        fc_port_t *fcport = sp->fcport;
+       struct srb_iocb *lio = &sp->u.iocb_cmd;
+       struct event_arg ea;
  
        ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
-           "Async-%s timeout - hdl=%x portid=%02x%02x%02x.\n",
-           sp->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area,
-           fcport->d_id.b.al_pa);
+           "Async-%s timeout - hdl=%x portid=%06x %8phC.\n",
+           sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
  
        fcport->flags &= ~FCF_ASYNC_SENT;
-       if (sp->type == SRB_LOGIN_CMD) {
-               struct srb_iocb *lio = &sp->u.iocb_cmd;
-               qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
+       switch (sp->type) {
+       case SRB_LOGIN_CMD:
                /* Retry as needed. */
                lio->u.logio.data[0] = MBS_COMMAND_ERROR;
                lio->u.logio.data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
                        QLA_LOGIO_LOGIN_RETRIED : 0;
-               qla2x00_post_async_login_done_work(fcport->vha, fcport,
-                       lio->u.logio.data);
-       } else if (sp->type == SRB_LOGOUT_CMD) {
+               memset(&ea, 0, sizeof(ea));
+               ea.event = FCME_PLOGI_DONE;
+               ea.fcport = sp->fcport;
+               ea.data[0] = lio->u.logio.data[0];
+               ea.data[1] = lio->u.logio.data[1];
+               ea.sp = sp;
+               qla24xx_handle_plogi_done_event(fcport->vha, &ea);
+               break;
+       case SRB_LOGOUT_CMD:
                qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
+               break;
+       case SRB_CT_PTHRU_CMD:
+       case SRB_MB_IOCB:
+       case SRB_NACK_PLOGI:
+       case SRB_NACK_PRLI:
+       case SRB_NACK_LOGO:
+               sp->done(sp, QLA_FUNCTION_TIMEOUT);
+               break;
        }
  }
  
  static void
- qla2x00_async_login_sp_done(void *data, void *ptr, int res)
+ qla2x00_async_login_sp_done(void *ptr, int res)
  {
-       srb_t *sp = (srb_t *)ptr;
+       srb_t *sp = ptr;
+       struct scsi_qla_host *vha = sp->vha;
        struct srb_iocb *lio = &sp->u.iocb_cmd;
-       struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
+       struct event_arg ea;
  
-       if (!test_bit(UNLOADING, &vha->dpc_flags))
-               qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport,
-                   lio->u.logio.data);
-       sp->free(sp->fcport->vha, sp);
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "%s %8phC res %d \n", __func__, sp->fcport->port_name, res);
+       sp->fcport->flags &= ~FCF_ASYNC_SENT;
+       if (!test_bit(UNLOADING, &vha->dpc_flags)) {
+               memset(&ea, 0, sizeof(ea));
+               ea.event = FCME_PLOGI_DONE;
+               ea.fcport = sp->fcport;
+               ea.data[0] = lio->u.logio.data[0];
+               ea.data[1] = lio->u.logio.data[1];
+               ea.iop[0] = lio->u.logio.iop[0];
+               ea.iop[1] = lio->u.logio.iop[1];
+               ea.sp = sp;
+               qla2x00_fcport_event_handler(vha, &ea);
+       }
+       sp->free(sp);
  }
  
  int
@@@ -139,13 -166,23 +166,23 @@@ qla2x00_async_login(struct scsi_qla_hos
  {
        srb_t *sp;
        struct srb_iocb *lio;
-       int rval;
+       int rval = QLA_FUNCTION_FAILED;
+       if (!vha->flags.online)
+               goto done;
+       if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
+           (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
+           (fcport->fw_login_state == DSC_LS_PRLI_PEND))
+               goto done;
  
-       rval = QLA_FUNCTION_FAILED;
        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
        if (!sp)
                goto done;
  
+       fcport->flags |= FCF_ASYNC_SENT;
+       fcport->logout_completed = 0;
        sp->type = SRB_LOGIN_CMD;
        sp->name = "login";
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
        }
  
        ql_dbg(ql_dbg_disc, vha, 0x2072,
-           "Async-login - hdl=%x, loopid=%x portid=%02x%02x%02x "
-           "retries=%d.\n", sp->handle, fcport->loop_id,
+           "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
+               "retries=%d.\n", fcport->port_name, sp->handle, fcport->loop_id,
            fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
            fcport->login_retry);
        return rval;
  
  done_free_sp:
-       sp->free(fcport->vha, sp);
+       sp->free(sp);
  done:
+       fcport->flags &= ~FCF_ASYNC_SENT;
        return rval;
  }
  
  static void
- qla2x00_async_logout_sp_done(void *data, void *ptr, int res)
+ qla2x00_async_logout_sp_done(void *ptr, int res)
  {
-       srb_t *sp = (srb_t *)ptr;
+       srb_t *sp = ptr;
        struct srb_iocb *lio = &sp->u.iocb_cmd;
-       struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
  
-       if (!test_bit(UNLOADING, &vha->dpc_flags))
-               qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
+       sp->fcport->flags &= ~FCF_ASYNC_SENT;
+       if (!test_bit(UNLOADING, &sp->vha->dpc_flags))
+               qla2x00_post_async_logout_done_work(sp->vha, sp->fcport,
                    lio->u.logio.data);
-       sp->free(sp->fcport->vha, sp);
+       sp->free(sp);
  }
  
  int
@@@ -198,6 -236,7 +236,7 @@@ qla2x00_async_logout(struct scsi_qla_ho
        int rval;
  
        rval = QLA_FUNCTION_FAILED;
+       fcport->flags |= FCF_ASYNC_SENT;
        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
        if (!sp)
                goto done;
                goto done_free_sp;
  
        ql_dbg(ql_dbg_disc, vha, 0x2070,
-           "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
+           "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC.\n",
            sp->handle, fcport->loop_id, fcport->d_id.b.domain,
-           fcport->d_id.b.area, fcport->d_id.b.al_pa);
+               fcport->d_id.b.area, fcport->d_id.b.al_pa,
+               fcport->port_name);
        return rval;
  
  done_free_sp:
-       sp->free(fcport->vha, sp);
+       sp->free(sp);
  done:
+       fcport->flags &= ~FCF_ASYNC_SENT;
        return rval;
  }
  
  static void
- qla2x00_async_adisc_sp_done(void *data, void *ptr, int res)
+ qla2x00_async_adisc_sp_done(void *ptr, int res)
  {
-       srb_t *sp = (srb_t *)ptr;
+       srb_t *sp = ptr;
+       struct scsi_qla_host *vha = sp->vha;
        struct srb_iocb *lio = &sp->u.iocb_cmd;
-       struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
  
        if (!test_bit(UNLOADING, &vha->dpc_flags))
-               qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
+               qla2x00_post_async_adisc_done_work(sp->vha, sp->fcport,
                    lio->u.logio.data);
-       sp->free(sp->fcport->vha, sp);
+       sp->free(sp);
  }
  
  int
@@@ -247,6 -288,7 +288,7 @@@ qla2x00_async_adisc(struct scsi_qla_hos
        int rval;
  
        rval = QLA_FUNCTION_FAILED;
+       fcport->flags |= FCF_ASYNC_SENT;
        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
        if (!sp)
                goto done;
        if (rval != QLA_SUCCESS)
                goto done_free_sp;
  
-       ql_dbg(ql_dbg_disc, vha, 0x206f,
-           "Async-adisc - hdl=%x loopid=%x portid=%02x%02x%02x.\n",
-           sp->handle, fcport->loop_id, fcport->d_id.b.domain,
-           fcport->d_id.b.area, fcport->d_id.b.al_pa);
-       return rval;
+       ql_dbg(ql_dbg_disc, vha, 0x206f,
+           "Async-adisc - hdl=%x loopid=%x portid=%02x%02x%02x.\n",
+           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;
+ }
+ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
+       struct event_arg *ea)
+ {
+       fc_port_t *fcport, *conflict_fcport;
+       struct get_name_list_extended *e;
+       u16 i, n, found = 0, loop_id;
+       port_id_t id;
+       u64 wwn;
+       u8 opt = 0;
+       fcport = ea->fcport;
+       if (ea->rc) { /* rval */
+               if (fcport->login_retry == 0) {
+                       fcport->login_retry = vha->hw->login_retry_count;
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                               "GNL failed Port login retry %8phN, retry cnt=%d.\n",
+                               fcport->port_name, fcport->login_retry);
+               }
+               return;
+       }
+       if (fcport->last_rscn_gen != fcport->rscn_gen) {
+               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                   "%s %8phC rscn gen changed rscn %d|%d \n",
+                   __func__, fcport->port_name,
+                   fcport->last_rscn_gen, fcport->rscn_gen);
+               qla24xx_post_gidpn_work(vha, fcport);
+               return;
+       } else if (fcport->last_login_gen != fcport->login_gen) {
+               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                       "%s %8phC login gen changed login %d|%d \n",
+                       __func__, fcport->port_name,
+                       fcport->last_login_gen, fcport->login_gen);
+               return;
+       }
+       n = ea->data[0] / sizeof(struct get_name_list_extended);
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "%s %d %8phC n %d %02x%02x%02x lid %d \n",
+           __func__, __LINE__, fcport->port_name, n,
+           fcport->d_id.b.domain, fcport->d_id.b.area,
+           fcport->d_id.b.al_pa, fcport->loop_id);
+       for (i = 0; i < n; i++) {
+               e = &vha->gnl.l[i];
+               wwn = wwn_to_u64(e->port_name);
+               if (memcmp((u8 *)&wwn, fcport->port_name, WWN_SIZE))
+                       continue;
+               found = 1;
+               id.b.domain = e->port_id[2];
+               id.b.area = e->port_id[1];
+               id.b.al_pa = e->port_id[0];
+               id.b.rsvd_1 = 0;
+               loop_id = le16_to_cpu(e->nport_handle);
+               loop_id = (loop_id & 0x7fff);
+               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                       "%s found %8phC CLS [%d|%d] ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
+                          __func__, fcport->port_name,
+                       e->current_login_state, fcport->fw_login_state,
+                       id.b.domain, id.b.area, id.b.al_pa,
+                       fcport->d_id.b.domain, fcport->d_id.b.area,
+                       fcport->d_id.b.al_pa, loop_id, fcport->loop_id);
+               if ((id.b24 != fcport->d_id.b24) ||
+                   ((fcport->loop_id != FC_NO_LOOP_ID) &&
+                       (fcport->loop_id != loop_id))) {
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post del sess\n",
+                          __func__, __LINE__, fcport->port_name);
+                       qlt_schedule_sess_for_deletion(fcport, 1);
+                       return;
+               }
+               fcport->loop_id = loop_id;
+               wwn = wwn_to_u64(fcport->port_name);
+               qlt_find_sess_invalidate_other(vha, wwn,
+                       id, loop_id, &conflict_fcport);
+               if (conflict_fcport) {
+                       /*
+                        * Another share fcport share the same loop_id &
+                        * nport id. Conflict fcport needs to finish
+                        * cleanup before this fcport can proceed to login.
+                        */
+                       conflict_fcport->conflict = fcport;
+                       fcport->login_pause = 1;
+               }
+               switch (e->current_login_state) {
+               case DSC_LS_PRLI_COMP:
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post gpdb\n",
+                          __func__, __LINE__, fcport->port_name);
+                       opt = PDO_FORCE_ADISC;
+                       qla24xx_post_gpdb_work(vha, fcport, opt);
+                       break;
+               case DSC_LS_PORT_UNAVAIL:
+               default:
+                       if (fcport->loop_id == FC_NO_LOOP_ID) {
+                               qla2x00_find_new_loop_id(vha, fcport);
+                               fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+                       }
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC \n",
+                          __func__, __LINE__, fcport->port_name);
+                       qla24xx_fcport_handle_login(vha, fcport);
+                       break;
+               }
+       }
+       if (!found) {
+               /* fw has no record of this port */
+               if (fcport->loop_id == FC_NO_LOOP_ID) {
+                       qla2x00_find_new_loop_id(vha, fcport);
+                       fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+               } else {
+                       for (i = 0; i < n; i++) {
+                               e = &vha->gnl.l[i];
+                               id.b.domain = e->port_id[0];
+                               id.b.area = e->port_id[1];
+                               id.b.al_pa = e->port_id[2];
+                               id.b.rsvd_1 = 0;
+                               loop_id = le16_to_cpu(e->nport_handle);
+                               if (fcport->d_id.b24 == id.b24) {
+                                       conflict_fcport =
+                                           qla2x00_find_fcport_by_wwpn(vha,
+                                               e->port_name, 0);
+                                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                                           "%s %d %8phC post del sess\n",
+                                           __func__, __LINE__,
+                                           conflict_fcport->port_name);
+                                       qlt_schedule_sess_for_deletion
+                                               (conflict_fcport, 1);
+                               }
+                               if (fcport->loop_id == loop_id) {
+                                       /* FW already picked this loop id for another fcport */
+                                       qla2x00_find_new_loop_id(vha, fcport);
+                               }
+                       }
+               }
+               qla24xx_fcport_handle_login(vha, fcport);
+       }
+ } /* gnl_event */
+ static void
+ qla24xx_async_gnl_sp_done(void *s, int res)
+ {
+       struct srb *sp = s;
+       struct scsi_qla_host *vha = sp->vha;
+       unsigned long flags;
+       struct fc_port *fcport = NULL, *tf;
+       u16 i, n = 0, loop_id;
+       struct event_arg ea;
+       struct get_name_list_extended *e;
+       u64 wwn;
+       struct list_head h;
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "Async done-%s res %x mb[1]=%x mb[2]=%x \n",
+           sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
+           sp->u.iocb_cmd.u.mbx.in_mb[2]);
+       memset(&ea, 0, sizeof(ea));
+       ea.sp = sp;
+       ea.rc = res;
+       ea.event = FCME_GNL_DONE;
+       if (sp->u.iocb_cmd.u.mbx.in_mb[1] >=
+           sizeof(struct get_name_list_extended)) {
+               n = sp->u.iocb_cmd.u.mbx.in_mb[1] /
+                   sizeof(struct get_name_list_extended);
+               ea.data[0] = sp->u.iocb_cmd.u.mbx.in_mb[1]; /* amnt xfered */
+       }
+       for (i = 0; i < n; i++) {
+               e = &vha->gnl.l[i];
+               loop_id = le16_to_cpu(e->nport_handle);
+               /* mask out reserve bit */
+               loop_id = (loop_id & 0x7fff);
+               set_bit(loop_id, vha->hw->loop_id_map);
+               wwn = wwn_to_u64(e->port_name);
+               ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+                   "%s %8phC %02x:%02x:%02x state %d/%d lid %x \n",
+                   __func__, (void *)&wwn, e->port_id[2], e->port_id[1],
+                   e->port_id[0], e->current_login_state, e->last_login_state,
+                   (loop_id & 0x7fff));
+       }
+       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+       vha->gnl.sent = 0;
+       INIT_LIST_HEAD(&h);
+       fcport = tf = NULL;
+       if (!list_empty(&vha->gnl.fcports))
+               list_splice_init(&vha->gnl.fcports, &h);
+       list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
+               list_del_init(&fcport->gnl_entry);
+               fcport->flags &= ~FCF_ASYNC_SENT;
+               ea.fcport = fcport;
+               qla2x00_fcport_event_handler(vha, &ea);
+       }
+       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+       sp->free(sp);
+ }
+ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
+ {
+       srb_t *sp;
+       struct srb_iocb *mbx;
+       int rval = QLA_FUNCTION_FAILED;
+       unsigned long flags;
+       u16 *mb;
+       if (!vha->flags.online)
+               goto done;
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "Async-gnlist WWPN %8phC \n", fcport->port_name);
+       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+       fcport->flags |= FCF_ASYNC_SENT;
+       fcport->disc_state = DSC_GNL;
+       fcport->last_rscn_gen = fcport->rscn_gen;
+       fcport->last_login_gen = fcport->login_gen;
+       list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports);
+       if (vha->gnl.sent) {
+               spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+               rval = QLA_SUCCESS;
+               goto done;
+       }
+       vha->gnl.sent = 1;
+       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+       sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+       if (!sp)
+               goto done;
+       sp->type = SRB_MB_IOCB;
+       sp->name = "gnlist";
+       sp->gen1 = fcport->rscn_gen;
+       sp->gen2 = fcport->login_gen;
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
+       mb = sp->u.iocb_cmd.u.mbx.out_mb;
+       mb[0] = MBC_PORT_NODE_NAME_LIST;
+       mb[1] = BIT_2 | BIT_3;
+       mb[2] = MSW(vha->gnl.ldma);
+       mb[3] = LSW(vha->gnl.ldma);
+       mb[6] = MSW(MSD(vha->gnl.ldma));
+       mb[7] = LSW(MSD(vha->gnl.ldma));
+       mb[8] = vha->gnl.size;
+       mb[9] = vha->vp_idx;
+       mbx = &sp->u.iocb_cmd;
+       mbx->timeout = qla2x00_async_iocb_timeout;
+       sp->done = qla24xx_async_gnl_sp_done;
+       rval = qla2x00_start_sp(sp);
+       if (rval != QLA_SUCCESS)
+               goto done_free_sp;
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+               "Async-%s - OUT WWPN %8phC hndl %x\n",
+               sp->name, fcport->port_name, sp->handle);
+       return rval;
+ done_free_sp:
+       sp->free(sp);
+ done:
+       fcport->flags &= ~FCF_ASYNC_SENT;
+       return rval;
+ }
+ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+ {
+       struct qla_work_evt *e;
+       e = qla2x00_alloc_work(vha, QLA_EVT_GNL);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+       e->u.fcport.fcport = fcport;
+       return qla2x00_post_work(vha, e);
+ }
+ static
+ void qla24xx_async_gpdb_sp_done(void *s, int res)
+ {
+       struct srb *sp = s;
+       struct scsi_qla_host *vha = sp->vha;
+       struct qla_hw_data *ha = vha->hw;
+       uint64_t zero = 0;
+       struct port_database_24xx *pd;
+       fc_port_t *fcport = sp->fcport;
+       u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
+       int rval = QLA_SUCCESS;
+       struct event_arg ea;
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n",
+           sp->name, res, fcport->port_name, mb[1], mb[2]);
+       fcport->flags &= ~FCF_ASYNC_SENT;
+       if (res) {
+               rval = res;
+               goto gpd_error_out;
+       }
+       pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
+       /* Check for logged in state. */
+       if (pd->current_login_state != PDS_PRLI_COMPLETE &&
+           pd->last_login_state != PDS_PRLI_COMPLETE) {
+               ql_dbg(ql_dbg_mbx, vha, 0xffff,
+                   "Unable to verify login-state (%x/%x) for "
+                   "loop_id %x.\n", pd->current_login_state,
+                   pd->last_login_state, fcport->loop_id);
+               rval = QLA_FUNCTION_FAILED;
+               goto gpd_error_out;
+       }
+       if (fcport->loop_id == FC_NO_LOOP_ID ||
+           (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
+               memcmp(fcport->port_name, pd->port_name, 8))) {
+               /* We lost the device mid way. */
+               rval = QLA_NOT_LOGGED_IN;
+               goto gpd_error_out;
+       }
+       /* Names are little-endian. */
+       memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
+       /* Get port_id of device. */
+       fcport->d_id.b.domain = pd->port_id[0];
+       fcport->d_id.b.area = pd->port_id[1];
+       fcport->d_id.b.al_pa = pd->port_id[2];
+       fcport->d_id.b.rsvd_1 = 0;
+       /* If not target must be initiator or unknown type. */
+       if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
+               fcport->port_type = FCT_INITIATOR;
+       else
+               fcport->port_type = FCT_TARGET;
+       /* Passback COS information. */
+       fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
+               FC_COS_CLASS2 : FC_COS_CLASS3;
+       if (pd->prli_svc_param_word_3[0] & BIT_7) {
+               fcport->flags |= FCF_CONF_COMP_SUPPORTED;
+               fcport->conf_compl_supported = 1;
+       }
+ gpd_error_out:
+       memset(&ea, 0, sizeof(ea));
+       ea.event = FCME_GPDB_DONE;
+       ea.rc = rval;
+       ea.fcport = fcport;
+       ea.sp = sp;
+       qla2x00_fcport_event_handler(vha, &ea);
+       dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
+               sp->u.iocb_cmd.u.mbx.in_dma);
+       sp->free(sp);
+ }
+ static int qla24xx_post_gpdb_work(struct scsi_qla_host *vha, fc_port_t *fcport,
+     u8 opt)
+ {
+       struct qla_work_evt *e;
+       e = qla2x00_alloc_work(vha, QLA_EVT_GPDB);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+       e->u.fcport.fcport = fcport;
+       e->u.fcport.opt = opt;
+       return qla2x00_post_work(vha, e);
+ }
+ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
+ {
+       srb_t *sp;
+       struct srb_iocb *mbx;
+       int rval = QLA_FUNCTION_FAILED;
+       u16 *mb;
+       dma_addr_t pd_dma;
+       struct port_database_24xx *pd;
+       struct qla_hw_data *ha = vha->hw;
+       if (!vha->flags.online)
+               goto done;
+       fcport->flags |= FCF_ASYNC_SENT;
+       fcport->disc_state = DSC_GPDB;
+       sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+       if (!sp)
+               goto done;
+       pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
+       if (pd == NULL) {
+               ql_log(ql_log_warn, vha, 0xffff,
+                       "Failed to allocate port database structure.\n");
+               goto done_free_sp;
+       }
+       memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
+       sp->type = SRB_MB_IOCB;
+       sp->name = "gpdb";
+       sp->gen1 = fcport->rscn_gen;
+       sp->gen2 = fcport->login_gen;
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+       mb = sp->u.iocb_cmd.u.mbx.out_mb;
+       mb[0] = MBC_GET_PORT_DATABASE;
+       mb[1] = fcport->loop_id;
+       mb[2] = MSW(pd_dma);
+       mb[3] = LSW(pd_dma);
+       mb[6] = MSW(MSD(pd_dma));
+       mb[7] = LSW(MSD(pd_dma));
+       mb[9] = vha->vp_idx;
+       mb[10] = opt;
+       mbx = &sp->u.iocb_cmd;
+       mbx->timeout = qla2x00_async_iocb_timeout;
+       mbx->u.mbx.in = (void *)pd;
+       mbx->u.mbx.in_dma = pd_dma;
+       sp->done = qla24xx_async_gpdb_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 hndl %x opt %x\n",
+               sp->name, fcport->port_name, sp->handle, opt);
+       return rval;
+ done_free_sp:
+       if (pd)
+               dma_pool_free(ha->s_dma_pool, pd, pd_dma);
+       sp->free(sp);
+ done:
+       fcport->flags &= ~FCF_ASYNC_SENT;
+       qla24xx_post_gpdb_work(vha, fcport, opt);
+       return rval;
+ }
+ static
+ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
+ {
+       int rval = ea->rc;
+       fc_port_t *fcport = ea->fcport;
+       unsigned long flags;
+       fcport->flags &= ~FCF_ASYNC_SENT;
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
+           fcport->disc_state, fcport->fw_login_state, rval);
+       if (ea->sp->gen2 != fcport->login_gen) {
+               /* target side must have changed it. */
+               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;
+       } else if (ea->sp->gen1 != fcport->rscn_gen) {
+               ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC post gidpn\n",
+                   __func__, __LINE__, fcport->port_name);
+               qla24xx_post_gidpn_work(vha, fcport);
+               return;
+       }
+       if (rval != QLA_SUCCESS) {
+               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);
+               return;
+       }
+       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+       ea->fcport->login_gen++;
+       ea->fcport->deleted = 0;
+       ea->fcport->logout_on_delete = 1;
+       if (!ea->fcport->login_succ && !IS_SW_RESV_ADDR(ea->fcport->d_id)) {
+               vha->fcport_count++;
+               ea->fcport->login_succ = 1;
+               if (!IS_IIDMA_CAPABLE(vha->hw) ||
+                   !vha->hw->flags.gpsc_supported) {
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                           "%s %d %8phC post upd_fcport fcp_cnt %d\n",
+                           __func__, __LINE__, fcport->port_name,
+                           vha->fcport_count);
+                       qla24xx_post_upd_fcport_work(vha, fcport);
+               } else {
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                           "%s %d %8phC post gpsc fcp_cnt %d\n",
+                           __func__, __LINE__, fcport->port_name,
+                           vha->fcport_count);
+                       qla24xx_post_gpsc_work(vha, fcport);
+               }
+       }
+       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+ } /* gpdb event */
+ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
+ {
+       if (fcport->login_retry == 0)
+               return 0;
+       if (fcport->scan_state != QLA_FCPORT_FOUND)
+               return 0;
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d\n",
+           __func__, fcport->port_name, fcport->disc_state,
+           fcport->fw_login_state, fcport->login_pause, fcport->flags,
+           fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
+           fcport->last_login_gen, fcport->login_gen, fcport->login_retry,
+           fcport->loop_id);
+       fcport->login_retry--;
+       if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
+           (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
+           (fcport->fw_login_state == DSC_LS_PRLI_PEND))
+               return 0;
+       /* for pure Target Mode. Login will not be initiated */
+       if (vha->host->active_mode == MODE_TARGET)
+               return 0;
+       if (fcport->flags & FCF_ASYNC_SENT) {
+               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+               return 0;
+       }
+       switch (fcport->disc_state) {
+       case DSC_DELETED:
+               if (fcport->loop_id == FC_NO_LOOP_ID) {
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post gnl\n",
+                          __func__, __LINE__, fcport->port_name);
+                       qla24xx_async_gnl(vha, fcport);
+               } else {
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post login\n",
+                          __func__, __LINE__, fcport->port_name);
+                       fcport->disc_state = DSC_LOGIN_PEND;
+                       qla2x00_post_async_login_work(vha, fcport, NULL);
+               }
+               break;
+       case DSC_GNL:
+               if (fcport->login_pause) {
+                       fcport->last_rscn_gen = fcport->rscn_gen;
+                       fcport->last_login_gen = fcport->login_gen;
+                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+                       break;
+               }
+               if (fcport->flags & FCF_FCP2_DEVICE) {
+                       u8 opt = PDO_FORCE_ADISC;
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post gpdb\n",
+                          __func__, __LINE__, fcport->port_name);
+                       fcport->disc_state = DSC_GPDB;
+                       qla24xx_post_gpdb_work(vha, fcport, opt);
+               } else {
+                       ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post login \n",
+                          __func__, __LINE__, fcport->port_name);
+                       fcport->disc_state = DSC_LOGIN_PEND;
+                       qla2x00_post_async_login_work(vha, fcport, NULL);
+               }
+               break;
+       case DSC_LOGIN_FAILED:
+               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post gidpn \n",
+                          __func__, __LINE__, fcport->port_name);
+               qla24xx_post_gidpn_work(vha, fcport);
+               break;
+       case DSC_LOGIN_COMPLETE:
+               /* recheck login state */
+               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post gpdb \n",
+                          __func__, __LINE__, fcport->port_name);
+               qla24xx_post_gpdb_work(vha, fcport, PDO_FORCE_ADISC);
+               break;
+       default:
+               break;
+       }
+       return 0;
+ }
+ static
+ void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
+ {
+       fcport->rscn_gen++;
+       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);
+       if (fcport->flags & FCF_ASYNC_SENT)
+               return;
+       switch (fcport->disc_state) {
+       case DSC_DELETED:
+       case DSC_LOGIN_COMPLETE:
+               qla24xx_post_gidpn_work(fcport->vha, fcport);
+               break;
+       default:
+               break;
+       }
+ }
+ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
+       u8 *port_name, void *pla)
+ {
+       struct qla_work_evt *e;
+       e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+       e->u.new_sess.id = *id;
+       e->u.new_sess.pla = pla;
+       memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE);
+       return qla2x00_post_work(vha, e);
+ }
+ static
+ int qla24xx_handle_delete_done_event(scsi_qla_host_t *vha,
+       struct event_arg *ea)
+ {
+       fc_port_t *fcport = ea->fcport;
+       if (test_bit(UNLOADING, &vha->dpc_flags))
+               return 0;
+       switch (vha->host->active_mode) {
+       case MODE_INITIATOR:
+       case MODE_DUAL:
+               if (fcport->scan_state == QLA_FCPORT_FOUND)
+                       qla24xx_fcport_handle_login(vha, fcport);
+               break;
+       case MODE_TARGET:
+       default:
+               /* no-op */
+               break;
+       }
+       return 0;
+ }
+ static
+ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
+       struct event_arg *ea)
+ {
+       fc_port_t *fcport = ea->fcport;
+       if (fcport->scan_state != QLA_FCPORT_FOUND) {
+               fcport->login_retry++;
+               return;
+       }
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+               "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n",
+               __func__, fcport->port_name, fcport->disc_state,
+               fcport->fw_login_state, fcport->login_pause,
+               fcport->deleted, fcport->conflict,
+               fcport->last_rscn_gen, fcport->rscn_gen,
+               fcport->last_login_gen, fcport->login_gen,
+               fcport->flags);
+       if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
+           (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
+           (fcport->fw_login_state == DSC_LS_PRLI_PEND))
+               return;
+       if (fcport->flags & FCF_ASYNC_SENT) {
+               fcport->login_retry++;
+               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+               return;
+       }
+       if (fcport->disc_state == DSC_DELETE_PEND) {
+               fcport->login_retry++;
+               return;
+       }
+       if (fcport->last_rscn_gen != fcport->rscn_gen) {
+               ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC post gidpn\n",
+                   __func__, __LINE__, fcport->port_name);
+               qla24xx_async_gidpn(vha, fcport);
+               return;
+       }
+       qla24xx_fcport_handle_login(vha, fcport);
+ }
+ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
+ {
+       fc_port_t *fcport, *f, *tf;
+       uint32_t id = 0, mask, rid;
+       int rc;
+       switch (ea->event) {
+       case FCME_RELOGIN:
+               if (test_bit(UNLOADING, &vha->dpc_flags))
+                       return;
  
- done_free_sp:
-       sp->free(fcport->vha, sp);
- done:
-       return rval;
+               qla24xx_handle_relogin_event(vha, ea);
+               break;
+       case FCME_RSCN:
+               if (test_bit(UNLOADING, &vha->dpc_flags))
+                       return;
+               switch (ea->id.b.rsvd_1) {
+               case RSCN_PORT_ADDR:
+                       fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+                       if (!fcport) {
+                               /* cable moved */
+                               rc = qla24xx_post_gpnid_work(vha, &ea->id);
+                               if (rc) {
+                                       ql_log(ql_log_warn, vha, 0xffff,
+                                               "RSCN GPNID work failed %02x%02x%02x\n",
+                                               ea->id.b.domain, ea->id.b.area,
+                                               ea->id.b.al_pa);
+                               }
+                       } else {
+                               ea->fcport = fcport;
+                               qla24xx_handle_rscn_event(fcport, ea);
+                       }
+                       break;
+               case RSCN_AREA_ADDR:
+               case RSCN_DOM_ADDR:
+                       if (ea->id.b.rsvd_1 == RSCN_AREA_ADDR) {
+                               mask = 0xffff00;
+                               ql_log(ql_dbg_async, vha, 0xffff,
+                                          "RSCN: Area 0x%06x was affected\n",
+                                          ea->id.b24);
+                       } else {
+                               mask = 0xff0000;
+                               ql_log(ql_dbg_async, vha, 0xffff,
+                                          "RSCN: Domain 0x%06x was affected\n",
+                                          ea->id.b24);
+                       }
+                       rid = ea->id.b24 & mask;
+                       list_for_each_entry_safe(f, tf, &vha->vp_fcports,
+                           list) {
+                               id = f->d_id.b24 & mask;
+                               if (rid == id) {
+                                       ea->fcport = f;
+                                       qla24xx_handle_rscn_event(f, ea);
+                               }
+                       }
+                       break;
+               case RSCN_FAB_ADDR:
+               default:
+                       ql_log(ql_log_warn, vha, 0xffff,
+                               "RSCN: Fabric was affected. Addr format %d\n",
+                               ea->id.b.rsvd_1);
+                       qla2x00_mark_all_devices_lost(vha, 1);
+                       set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+                       set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+               }
+               break;
+       case FCME_GIDPN_DONE:
+               qla24xx_handle_gidpn_event(vha, ea);
+               break;
+       case FCME_GNL_DONE:
+               qla24xx_handle_gnl_done_event(vha, ea);
+               break;
+       case FCME_GPSC_DONE:
+               qla24xx_post_upd_fcport_work(vha, ea->fcport);
+               break;
+       case FCME_PLOGI_DONE:   /* Initiator side sent LLIOCB */
+               qla24xx_handle_plogi_done_event(vha, ea);
+               break;
+       case FCME_GPDB_DONE:
+               qla24xx_handle_gpdb_event(vha, ea);
+               break;
+       case FCME_GPNID_DONE:
+               qla24xx_handle_gpnid_event(vha, ea);
+               break;
+       case FCME_DELETE_DONE:
+               qla24xx_handle_delete_done_event(vha, ea);
+               break;
+       default:
+               BUG_ON(1);
+               break;
+       }
  }
  
  static void
  qla2x00_tmf_iocb_timeout(void *data)
  {
-       srb_t *sp = (srb_t *)data;
+       srb_t *sp = data;
        struct srb_iocb *tmf = &sp->u.iocb_cmd;
  
        tmf->u.tmf.comp_status = CS_TIMEOUT;
  }
  
  static void
- qla2x00_tmf_sp_done(void *data, void *ptr, int res)
+ qla2x00_tmf_sp_done(void *ptr, int res)
  {
-       srb_t *sp = (srb_t *)ptr;
+       srb_t *sp = ptr;
        struct srb_iocb *tmf = &sp->u.iocb_cmd;
        complete(&tmf->u.tmf.comp);
  }
  
@@@ -348,7 -1234,7 +1234,7 @@@ qla2x00_async_tm_cmd(fc_port_t *fcport
        }
  
  done_free_sp:
-       sp->free(vha, sp);
+       sp->free(sp);
  done:
        return rval;
  }
  static void
  qla24xx_abort_iocb_timeout(void *data)
  {
-       srb_t *sp = (srb_t *)data;
+       srb_t *sp = data;
        struct srb_iocb *abt = &sp->u.iocb_cmd;
  
        abt->u.abt.comp_status = CS_TIMEOUT;
  }
  
  static void
- qla24xx_abort_sp_done(void *data, void *ptr, int res)
+ qla24xx_abort_sp_done(void *ptr, int res)
  {
-       srb_t *sp = (srb_t *)ptr;
+       srb_t *sp = ptr;
        struct srb_iocb *abt = &sp->u.iocb_cmd;
  
        complete(&abt->u.abt.comp);
  static int
  qla24xx_async_abort_cmd(srb_t *cmd_sp)
  {
-       scsi_qla_host_t *vha = cmd_sp->fcport->vha;
+       scsi_qla_host_t *vha = cmd_sp->vha;
        fc_port_t *fcport = cmd_sp->fcport;
        struct srb_iocb *abt_iocb;
        srb_t *sp;
            QLA_SUCCESS : QLA_FUNCTION_FAILED;
  
  done_free_sp:
-       sp->free(vha, sp);
+       sp->free(sp);
  done:
        return rval;
  }
@@@ -441,59 -1327,65 +1327,65 @@@ qla24xx_async_abort_command(srb_t *sp
        return qla24xx_async_abort_cmd(sp);
  }
  
- void
- qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
-     uint16_t *data)
+ static void
+ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
  {
-       int rval;
+       port_id_t cid;  /* conflict Nport id */
  
-       switch (data[0]) {
+       switch (ea->data[0]) {
        case MBS_COMMAND_COMPLETE:
                /*
                 * Driver must validate login state - If PRLI not complete,
                 * force a relogin attempt via implicit LOGO, PLOGI, and PRLI
                 * requests.
                 */
-               rval = qla2x00_get_port_database(vha, fcport, 0);
-               if (rval == QLA_NOT_LOGGED_IN) {
-                       fcport->flags &= ~FCF_ASYNC_SENT;
-                       fcport->flags |= FCF_LOGIN_NEEDED;
-                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
-                       break;
-               }
-               if (rval != QLA_SUCCESS) {
-                       qla2x00_post_async_logout_work(vha, fcport, NULL);
-                       qla2x00_post_async_login_work(vha, fcport, NULL);
-                       break;
-               }
-               if (fcport->flags & FCF_FCP2_DEVICE) {
-                       qla2x00_post_async_adisc_work(vha, fcport, data);
-                       break;
-               }
-               qla2x00_update_fcport(vha, fcport);
+               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                          "%s %d %8phC post gpdb\n",
+                          __func__, __LINE__, ea->fcport->port_name);
+               ea->fcport->chip_reset = vha->hw->chip_reset;
+               ea->fcport->logout_on_delete = 1;
+               qla24xx_post_gpdb_work(vha, ea->fcport, 0);
                break;
        case MBS_COMMAND_ERROR:
-               fcport->flags &= ~FCF_ASYNC_SENT;
-               if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
+               ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC cmd error %x\n",
+                   __func__, __LINE__, ea->fcport->port_name, ea->data[1]);
+               ea->fcport->flags &= ~FCF_ASYNC_SENT;
+               ea->fcport->disc_state = DSC_LOGIN_FAILED;
+               if (ea->data[1] & QLA_LOGIO_LOGIN_RETRIED)
                        set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
                else
-                       qla2x00_mark_device_lost(vha, fcport, 1, 0);
-               break;
-       case MBS_PORT_ID_USED:
-               fcport->loop_id = data[1];
-               qla2x00_post_async_logout_work(vha, fcport, NULL);
-               qla2x00_post_async_login_work(vha, fcport, NULL);
+                       qla2x00_mark_device_lost(vha, ea->fcport, 1, 0);
                break;
        case MBS_LOOP_ID_USED:
-               fcport->loop_id++;
-               rval = qla2x00_find_new_loop_id(vha, fcport);
-               if (rval != QLA_SUCCESS) {
-                       fcport->flags &= ~FCF_ASYNC_SENT;
-                       qla2x00_mark_device_lost(vha, fcport, 1, 0);
-                       break;
+               /* data[1] = IO PARAM 1 = nport ID  */
+               cid.b.domain = (ea->iop[1] >> 16) & 0xff;
+               cid.b.area   = (ea->iop[1] >>  8) & 0xff;
+               cid.b.al_pa  = ea->iop[1] & 0xff;
+               cid.b.rsvd_1 = 0;
+               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                       "%s %d %8phC LoopID 0x%x in use post gnl\n",
+                       __func__, __LINE__, ea->fcport->port_name,
+                       ea->fcport->loop_id);
+               if (IS_SW_RESV_ADDR(cid)) {
+                       set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
+                       ea->fcport->loop_id = FC_NO_LOOP_ID;
+               } else {
+                       qla2x00_clear_loop_id(ea->fcport);
                }
-               qla2x00_post_async_login_work(vha, fcport, NULL);
+               qla24xx_post_gnl_work(vha, ea->fcport);
+               break;
+       case MBS_PORT_ID_USED:
+               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                       "%s %d %8phC NPortId %02x%02x%02x inuse post gidpn\n",
+                       __func__, __LINE__, ea->fcport->port_name,
+                       ea->fcport->d_id.b.domain, ea->fcport->d_id.b.area,
+                       ea->fcport->d_id.b.al_pa);
+               qla2x00_clear_loop_id(ea->fcport);
+               qla24xx_post_gidpn_work(vha, ea->fcport);
                break;
        }
        return;
@@@ -503,10 -1395,9 +1395,9 @@@ voi
  qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
      uint16_t *data)
  {
-       /* Don't re-login in target mode */
-       if (!fcport->tgt_session)
-               qla2x00_mark_device_lost(vha, fcport, 1, 0);
+       qla2x00_mark_device_lost(vha, fcport, 1, 0);
        qlt_logo_completion_handler(fcport, data[0]);
+       fcport->login_gen++;
        return;
  }
  
@@@ -709,7 -1600,7 +1600,7 @@@ qla2x00_initialize_adapter(scsi_qla_hos
                }
        }
  
-       if (qla_ini_mode_enabled(vha))
+       if (qla_ini_mode_enabled(vha) || qla_dual_mode_enabled(vha))
                rval = qla2x00_init_rings(vha);
  
        ha->flags.chip_reset_done = 1;
@@@ -2088,6 -2979,21 +2979,21 @@@ qla24xx_update_fw_options(scsi_qla_host
                        __func__, ha->fw_options[2]);
        }
  
+       /* Move PUREX, ABTS RX & RIDA to ATIOQ */
+       if (ql2xmvasynctoatio) {
+               if (qla_tgt_mode_enabled(vha) ||
+                   qla_dual_mode_enabled(vha))
+                       ha->fw_options[2] |= BIT_11;
+               else
+                       ha->fw_options[2] &= ~BIT_11;
+       }
+       ql_dbg(ql_dbg_init, vha, 0xffff,
+               "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
+               __func__, ha->fw_options[1], ha->fw_options[2],
+               ha->fw_options[3], vha->host->active_mode);
+       qla2x00_set_fw_options(vha, ha->fw_options);
        /* Update Serial Link options. */
        if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
                return;
@@@ -2968,8 -3874,14 +3874,14 @@@ qla2x00_rport_del(void *data
        rport = fcport->drport ? fcport->drport: fcport->rport;
        fcport->drport = NULL;
        spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
-       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);
+       }
  }
  
  /**
@@@ -2995,9 -3907,42 +3907,42 @@@ qla2x00_alloc_fcport(scsi_qla_host_t *v
        qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
        fcport->supported_classes = FC_COS_UNSPECIFIED;
  
+       fcport->ct_desc.ct_sns = dma_alloc_coherent(&vha->hw->pdev->dev,
+               sizeof(struct ct_sns_pkt), &fcport->ct_desc.ct_sns_dma,
+               flags);
+       fcport->disc_state = DSC_DELETED;
+       fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+       fcport->deleted = QLA_SESS_DELETED;
+       fcport->login_retry = vha->hw->login_retry_count;
+       fcport->login_retry = 5;
+       fcport->logout_on_delete = 1;
+       if (!fcport->ct_desc.ct_sns) {
+               ql_log(ql_log_warn, vha, 0xffff,
+                   "Failed to allocate ct_sns request.\n");
+               kfree(fcport);
+               fcport = NULL;
+       }
+       INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
+       INIT_LIST_HEAD(&fcport->gnl_entry);
+       INIT_LIST_HEAD(&fcport->list);
        return fcport;
  }
  
+ void
+ qla2x00_free_fcport(fc_port_t *fcport)
+ {
+       if (fcport->ct_desc.ct_sns) {
+               dma_free_coherent(&fcport->vha->hw->pdev->dev,
+                       sizeof(struct ct_sns_pkt), fcport->ct_desc.ct_sns,
+                       fcport->ct_desc.ct_sns_dma);
+               fcport->ct_desc.ct_sns = NULL;
+       }
+       kfree(fcport);
+ }
  /*
   * qla2x00_configure_loop
   *      Updates Fibre Channel Device Database with what is actually on loop.
@@@ -3055,10 -4000,11 +4000,11 @@@ qla2x00_configure_loop(scsi_qla_host_t 
  
        } else if (ha->current_topology == ISP_CFG_N) {
                clear_bit(RSCN_UPDATE, &flags);
+       } else if (ha->current_topology == ISP_CFG_NL) {
+               clear_bit(RSCN_UPDATE, &flags);
+               set_bit(LOCAL_LOOP_UPDATE, &flags);
        } else if (!vha->flags.online ||
            (test_bit(ABORT_ISP_ACTIVE, &flags))) {
                set_bit(RSCN_UPDATE, &flags);
                set_bit(LOCAL_LOOP_UPDATE, &flags);
        }
                         * Process any ATIO queue entries that came in
                         * while we weren't online.
                         */
-                       if (qla_tgt_mode_enabled(vha)) {
+                       if (qla_tgt_mode_enabled(vha) ||
+                           qla_dual_mode_enabled(vha)) {
                                if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
                                        spin_lock_irqsave(&ha->tgt.atio_lock,
                                            flags);
@@@ -3159,6 -4106,7 +4106,7 @@@ qla2x00_configure_local_loop(scsi_qla_h
        uint16_t        loop_id;
        uint8_t         domain, area, al_pa;
        struct qla_hw_data *ha = vha->hw;
+       unsigned long flags;
  
        found_devs = 0;
        new_fcport = NULL;
                            "Marking port lost loop_id=0x%04x.\n",
                            fcport->loop_id);
  
-                       qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
+                       qla2x00_mark_device_lost(vha, fcport, 0, 0);
                }
        }
  
                if (loop_id > LAST_LOCAL_LOOP_ID)
                        continue;
  
-               memset(new_fcport, 0, sizeof(fc_port_t));
+               memset(new_fcport->port_name, 0, WWN_SIZE);
  
                /* Fill in member data. */
                new_fcport->d_id.b.domain = domain;
                new_fcport->d_id.b.area = area;
                new_fcport->d_id.b.al_pa = al_pa;
                new_fcport->loop_id = loop_id;
                rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
                if (rval2 != QLA_SUCCESS) {
                        ql_dbg(ql_dbg_disc, vha, 0x201a,
                        continue;
                }
  
+               spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
                /* Check for matching device in port list. */
                found = 0;
                fcport = NULL;
                        memcpy(fcport->node_name, new_fcport->node_name,
                            WWN_SIZE);
  
+                       if (!fcport->login_succ) {
+                               vha->fcport_count++;
+                               fcport->login_succ = 1;
+                               fcport->disc_state = DSC_LOGIN_COMPLETE;
+                       }
                        found++;
                        break;
                }
  
                        /* Allocate a new replacement fcport. */
                        fcport = new_fcport;
+                       if (!fcport->login_succ) {
+                               vha->fcport_count++;
+                               fcport->login_succ = 1;
+                               fcport->disc_state = DSC_LOGIN_COMPLETE;
+                       }
+                       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
                        new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
                        if (new_fcport == NULL) {
                                ql_log(ql_log_warn, vha, 0x201c,
                                    "Failed to allocate memory for fcport.\n");
                                rval = QLA_MEMORY_ALLOC_FAILED;
                                goto cleanup_allocation;
                        }
+                       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
                        new_fcport->flags &= ~FCF_FABRIC_DEVICE;
                }
  
+               spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
                /* Base iIDMA settings on HBA port speed. */
                fcport->fp_speed = ha->link_data_rate;
  
@@@ -3334,6 -4302,7 +4302,7 @@@ qla2x00_iidma_fcport(scsi_qla_host_t *v
        }
  }
  
+ /* qla2x00_reg_remote_port is reserved for Initiator Mode only.*/
  static void
  qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
  {
                    "Unable to allocate fc remote port.\n");
                return;
        }
-       /*
-        * Create target mode FC NEXUS in qla_target.c if target mode is
-        * enabled..
-        */
-       qlt_fc_port_added(vha, fcport);
  
        spin_lock_irqsave(fcport->vha->host->host_lock, flags);
        *((fc_port_t **)rport->dd_data) = fcport;
                rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
        if (fcport->port_type == FCT_TARGET)
                rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+               "%s %8phN. rport %p is %s mode \n",
+               __func__, fcport->port_name, rport,
+               (fcport->port_type == FCT_TARGET) ? "tgt" : "ini");
        fc_remote_port_rolechg(rport, rport_ids.roles);
  }
  
@@@ -3393,25 -4362,44 +4362,44 @@@ qla2x00_update_fcport(scsi_qla_host_t *
  {
        fcport->vha = vha;
  
+       if (IS_SW_RESV_ADDR(fcport->d_id))
+               return;
+       ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %8phC \n",
+           __func__, fcport->port_name);
        if (IS_QLAFX00(vha->hw)) {
                qla2x00_set_fcport_state(fcport, FCS_ONLINE);
                goto reg_port;
        }
        fcport->login_retry = 0;
        fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+       fcport->disc_state = DSC_LOGIN_COMPLETE;
+       fcport->deleted = 0;
+       fcport->logout_on_delete = 1;
  
        qla2x00_set_fcport_state(fcport, FCS_ONLINE);
        qla2x00_iidma_fcport(vha, fcport);
        qla24xx_update_fcport_fcp_prio(vha, fcport);
  
  reg_port:
-       if (qla_ini_mode_enabled(vha))
+       switch (vha->host->active_mode) {
+       case MODE_INITIATOR:
                qla2x00_reg_remote_port(vha, fcport);
-       else {
-               /*
-                * Create target mode FC NEXUS in qla_target.c
-                */
-               qlt_fc_port_added(vha, fcport);
+               break;
+       case MODE_TARGET:
+               if (!vha->vha_tgt.qla_tgt->tgt_stop &&
+                       !vha->vha_tgt.qla_tgt->tgt_stopped)
+                       qlt_fc_port_added(vha, fcport);
+               break;
+       case MODE_DUAL:
+               qla2x00_reg_remote_port(vha, fcport);
+               if (!vha->vha_tgt.qla_tgt->tgt_stop &&
+                       !vha->vha_tgt.qla_tgt->tgt_stopped)
+                       qlt_fc_port_added(vha, fcport);
+               break;
+       default:
+               break;
        }
  }
  
@@@ -3430,13 -4418,11 +4418,11 @@@ static in
  qla2x00_configure_fabric(scsi_qla_host_t *vha)
  {
        int     rval;
-       fc_port_t       *fcport, *fcptemp;
-       uint16_t        next_loopid;
+       fc_port_t       *fcport;
        uint16_t        mb[MAILBOX_REGISTER_COUNT];
        uint16_t        loop_id;
        LIST_HEAD(new_fcports);
        struct qla_hw_data *ha = vha->hw;
-       struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
        int             discovery_gen;
  
        /* If FL port exists, then SNS is present */
        }
        vha->device_flags |= SWITCH_FOUND;
  
+       if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
+               rval = qla2x00_send_change_request(vha, 0x3, 0);
+               if (rval != QLA_SUCCESS)
+                       ql_log(ql_log_warn, vha, 0x121,
+                               "Failed to enable receiving of RSCN requests: 0x%x.\n",
+                               rval);
+       }
        do {
+               qla2x00_mgmt_svr_login(vha);
                /* FDMI support. */
                if (ql2xfdmienable &&
                    test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags))
                        }
                }
  
- #define QLA_FCPORT_SCAN               1
- #define QLA_FCPORT_FOUND      2
                list_for_each_entry(fcport, &vha->vp_fcports, list) {
                        fcport->scan_state = QLA_FCPORT_SCAN;
                }
                 * will be newer than discovery_gen. */
                qlt_do_generation_tick(vha, &discovery_gen);
  
-               rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
+               rval = qla2x00_find_all_fabric_devs(vha);
                if (rval != QLA_SUCCESS)
                        break;
-               /*
-                * Logout all previous fabric devices marked lost, except
-                * FCP2 devices.
-                */
-               list_for_each_entry(fcport, &vha->vp_fcports, list) {
-                       if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
-                               break;
-                       if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
-                               continue;
-                       if (fcport->scan_state == QLA_FCPORT_SCAN) {
-                               if (qla_ini_mode_enabled(base_vha) &&
-                                   atomic_read(&fcport->state) == FCS_ONLINE) {
-                                       qla2x00_mark_device_lost(vha, fcport,
-                                           ql2xplogiabsentdevice, 0);
-                                       if (fcport->loop_id != FC_NO_LOOP_ID &&
-                                           (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
-                                           fcport->port_type != FCT_INITIATOR &&
-                                           fcport->port_type != FCT_BROADCAST) {
-                                               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);
-                                               qla2x00_clear_loop_id(fcport);
-                                       }
-                               } else if (!qla_ini_mode_enabled(base_vha)) {
-                                       /*
-                                        * In target mode, explicitly kill
-                                        * sessions and log out of devices
-                                        * that are gone, so that we don't
-                                        * end up with an initiator using the
-                                        * wrong ACL (if the fabric recycles
-                                        * an FC address and we have a stale
-                                        * session around) and so that we don't
-                                        * report initiators that are no longer
-                                        * on the fabric.
-                                        */
-                                       ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077,
-                                           "port gone, logging out/killing session: "
-                                           "%8phC state 0x%x flags 0x%x fc4_type 0x%x "
-                                           "scan_state %d\n",
-                                           fcport->port_name,
-                                           atomic_read(&fcport->state),
-                                           fcport->flags, fcport->fc4_type,
-                                           fcport->scan_state);
-                                       qlt_fc_port_deleted(vha, fcport,
-                                           discovery_gen);
-                               }
-                       }
-               }
-               /* Starting free loop ID. */
-               next_loopid = ha->min_external_loopid;
-               /*
-                * Scan through our port list and login entries that need to be
-                * logged in.
-                */
-               list_for_each_entry(fcport, &vha->vp_fcports, list) {
-                       if (atomic_read(&vha->loop_down_timer) ||
-                           test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
-                               break;
-                       if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
-                           (fcport->flags & FCF_LOGIN_NEEDED) == 0)
-                               continue;
-                       /*
-                        * If we're not an initiator, skip looking for devices
-                        * and logging in.  There's no reason for us to do it,
-                        * and it seems to actively cause problems in target
-                        * mode if we race with the initiator logging into us
-                        * (we might get the "port ID used" status back from
-                        * our login command and log out the initiator, which
-                        * seems to cause havoc).
-                        */
-                       if (!qla_ini_mode_enabled(base_vha)) {
-                               if (fcport->scan_state == QLA_FCPORT_FOUND) {
-                                       ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078,
-                                           "port %8phC state 0x%x flags 0x%x fc4_type 0x%x "
-                                           "scan_state %d (initiator mode disabled; skipping "
-                                           "login)\n", fcport->port_name,
-                                           atomic_read(&fcport->state),
-                                           fcport->flags, fcport->fc4_type,
-                                           fcport->scan_state);
-                               }
-                               continue;
-                       }
-                       if (fcport->loop_id == FC_NO_LOOP_ID) {
-                               fcport->loop_id = next_loopid;
-                               rval = qla2x00_find_new_loop_id(
-                                   base_vha, fcport);
-                               if (rval != QLA_SUCCESS) {
-                                       /* Ran out of IDs to use */
-                                       break;
-                               }
-                       }
-                       /* Login and update database */
-                       qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
-               }
-               /* Exit if out of loop IDs. */
-               if (rval != QLA_SUCCESS) {
-                       break;
-               }
-               /*
-                * Login and add the new devices to our port list.
-                */
-               list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
-                       if (atomic_read(&vha->loop_down_timer) ||
-                           test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
-                               break;
-                       /*
-                        * If we're not an initiator, skip looking for devices
-                        * and logging in.  There's no reason for us to do it,
-                        * and it seems to actively cause problems in target
-                        * mode if we race with the initiator logging into us
-                        * (we might get the "port ID used" status back from
-                        * our login command and log out the initiator, which
-                        * seems to cause havoc).
-                        */
-                       if (qla_ini_mode_enabled(base_vha)) {
-                               /* Find a new loop ID to use. */
-                               fcport->loop_id = next_loopid;
-                               rval = qla2x00_find_new_loop_id(base_vha,
-                                   fcport);
-                               if (rval != QLA_SUCCESS) {
-                                       /* Ran out of IDs to use */
-                                       break;
-                               }
-                               /* Login and update database */
-                               qla2x00_fabric_dev_login(vha, fcport,
-                                   &next_loopid);
-                       } else {
-                               ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079,
-                                       "new port %8phC state 0x%x flags 0x%x fc4_type "
-                                       "0x%x scan_state %d (initiator mode disabled; "
-                                       "skipping login)\n",
-                                       fcport->port_name,
-                                       atomic_read(&fcport->state),
-                                       fcport->flags, fcport->fc4_type,
-                                       fcport->scan_state);
-                       }
-                       list_move_tail(&fcport->list, &vha->vp_fcports);
-               }
        } while (0);
  
-       /* Free all new device structures not processed. */
-       list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
-               list_del(&fcport->list);
-               kfree(fcport);
-       }
-       if (rval) {
+       if (rval)
                ql_dbg(ql_dbg_disc, vha, 0x2068,
                    "Configure fabric error exit rval=%d.\n", rval);
-       }
  
        return (rval);
  }
   *    Kernel context.
   */
  static int
- qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
-       struct list_head *new_fcports)
+ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
  {
        int             rval;
        uint16_t        loop_id;
-       fc_port_t       *fcport, *new_fcport, *fcptemp;
+       fc_port_t       *fcport, *new_fcport;
        int             found;
  
        sw_info_t       *swl;
        port_id_t       wrap = {}, nxt_d_id;
        struct qla_hw_data *ha = vha->hw;
        struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+       unsigned long flags;
  
        rval = QLA_SUCCESS;
  
                        swl = NULL;
                } else if (qla2x00_gnn_id(vha, swl) != QLA_SUCCESS) {
                        swl = NULL;
-               } else if (ql2xiidmaenable &&
-                   qla2x00_gfpn_id(vha, swl) == QLA_SUCCESS) {
-                       qla2x00_gpsc(vha, swl);
+               } else if (qla2x00_gfpn_id(vha, swl) != QLA_SUCCESS) {
+                       swl = NULL;
                }
  
                /* If other queries succeeded probe for FC-4 type */
                                ql_log(ql_log_warn, vha, 0x2064,
                                    "SNS scan failed -- assuming "
                                    "zero-entry result.\n");
-                               list_for_each_entry_safe(fcport, fcptemp,
-                                   new_fcports, list) {
-                                       list_del(&fcport->list);
-                                       kfree(fcport);
-                               }
                                rval = QLA_SUCCESS;
                                break;
                        }
                    new_fcport->fc4_type != FC4_TYPE_UNKNOWN))
                        continue;
  
+               spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
                /* Locate matching device in database. */
                found = 0;
                list_for_each_entry(fcport, &vha->vp_fcports, list) {
                         */
                        if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
                            (atomic_read(&fcport->state) == FCS_ONLINE ||
-                            !qla_ini_mode_enabled(base_vha))) {
+                            (vha->host->active_mode == MODE_TARGET))) {
                                break;
                        }
  
                         * Log it out if still logged in and mark it for
                         * relogin later.
                         */
-                       if (!qla_ini_mode_enabled(base_vha)) {
+                       if (qla_tgt_mode_enabled(base_vha)) {
                                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
                                         "port changed FC ID, %8phC"
                                         " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
  
                        fcport->d_id.b24 = new_fcport->d_id.b24;
                        fcport->flags |= FCF_LOGIN_NEEDED;
-                       if (fcport->loop_id != FC_NO_LOOP_ID &&
-                           (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
-                           (fcport->flags & FCF_ASYNC_SENT) == 0 &&
-                           fcport->port_type != FCT_INITIATOR &&
-                           fcport->port_type != FCT_BROADCAST) {
-                               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);
-                               qla2x00_clear_loop_id(fcport);
-                       }
                        break;
                }
  
-               if (found)
+               if (found) {
+                       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
                        continue;
+               }
                /* If device was not in our fcports list, then add it. */
                new_fcport->scan_state = QLA_FCPORT_FOUND;
-               list_add_tail(&new_fcport->list, new_fcports);
+               list_add_tail(&new_fcport->list, &vha->vp_fcports);
+               spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
  
                /* Allocate a new replacement fcport. */
                nxt_d_id.b24 = new_fcport->d_id.b24;
                new_fcport->d_id.b24 = nxt_d_id.b24;
        }
  
-       kfree(new_fcport);
+       qla2x00_free_fcport(new_fcport);
+       /*
+        * Logout all previous fabric dev marked lost, except FCP2 devices.
+        */
+       list_for_each_entry(fcport, &vha->vp_fcports, list) {
+               if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+                       break;
+               if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
+                   (fcport->flags & FCF_LOGIN_NEEDED) == 0)
+                       continue;
+               if (fcport->scan_state == QLA_FCPORT_SCAN) {
+                       if ((qla_dual_mode_enabled(vha) ||
+                           qla_ini_mode_enabled(vha)) &&
+                           atomic_read(&fcport->state) == FCS_ONLINE) {
+                               qla2x00_mark_device_lost(vha, fcport,
+                                       ql2xplogiabsentdevice, 0);
+                               if (fcport->loop_id != FC_NO_LOOP_ID &&
+                                   (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
+                                   fcport->port_type != FCT_INITIATOR &&
+                                   fcport->port_type != FCT_BROADCAST) {
+                                       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);
+                                       continue;
+                               }
+                       }
+               }
  
+               if (fcport->scan_state == QLA_FCPORT_FOUND)
+                       qla24xx_fcport_handle_login(vha, fcport);
+       }
        return (rval);
  }
  
@@@ -3992,64 -4853,6 +4853,6 @@@ qla2x00_find_new_loop_id(scsi_qla_host_
        return (rval);
  }
  
- /*
-  * qla2x00_fabric_dev_login
-  *    Login fabric target device and update FC port database.
-  *
-  * Input:
-  *    ha:             adapter state pointer.
-  *    fcport:         port structure list pointer.
-  *    next_loopid:    contains value of a new loop ID that can be used
-  *                    by the next login attempt.
-  *
-  * Returns:
-  *    qla2x00 local function return status code.
-  *
-  * Context:
-  *    Kernel context.
-  */
- static int
- qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport,
-     uint16_t *next_loopid)
- {
-       int     rval;
-       uint8_t opts;
-       struct qla_hw_data *ha = vha->hw;
-       rval = QLA_SUCCESS;
-       if (IS_ALOGIO_CAPABLE(ha)) {
-               if (fcport->flags & FCF_ASYNC_SENT)
-                       return rval;
-               fcport->flags |= FCF_ASYNC_SENT;
-               rval = qla2x00_post_async_login_work(vha, fcport, NULL);
-               if (!rval)
-                       return rval;
-       }
-       fcport->flags &= ~FCF_ASYNC_SENT;
-       rval = qla2x00_fabric_login(vha, fcport, next_loopid);
-       if (rval == QLA_SUCCESS) {
-               /* Send an ADISC to FCP2 devices.*/
-               opts = 0;
-               if (fcport->flags & FCF_FCP2_DEVICE)
-                       opts |= BIT_1;
-               rval = qla2x00_get_port_database(vha, fcport, opts);
-               if (rval != QLA_SUCCESS) {
-                       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);
-                       qla2x00_mark_device_lost(vha, fcport, 1, 0);
-               } else {
-                       qla2x00_update_fcport(vha, fcport);
-               }
-       } else {
-               /* Retry Login. */
-               qla2x00_mark_device_lost(vha, fcport, 1, 0);
-       }
-       return (rval);
- }
  
  /*
   * qla2x00_fabric_login
@@@ -4341,13 -5144,6 +5144,6 @@@ qla2x00_update_fcports(scsi_qla_host_t 
                                spin_unlock_irqrestore(&ha->vport_slock, flags);
                                qla2x00_rport_del(fcport);
  
-                               /*
-                                * Release the target mode FC NEXUS in
-                                * qla_target.c, if target mod is enabled.
-                                */
-                               qlt_fc_port_deleted(vha, fcport,
-                                   base_vha->total_fcport_update_gen);
                                spin_lock_irqsave(&ha->vport_slock, flags);
                        }
                }
@@@ -4730,6 -5526,8 +5526,8 @@@ qla2x00_abort_isp_cleanup(scsi_qla_host
        if (!(IS_P3P_TYPE(ha)))
                ha->isp_ops->reset_chip(vha);
  
+       ha->chip_reset++;
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
        if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
                atomic_set(&vha->loop_state, LOOP_DOWN);
                /* Requeue all commands in outstanding command list. */
                qla2x00_abort_all_cmds(vha, DID_RESET << 16);
        }
-       ha->chip_reset++;
        /* memory barrier */
        wmb();
  }
@@@ -4981,7 -5777,6 +5777,6 @@@ qla2x00_restart_isp(scsi_qla_host_t *vh
                if (!status) {
                        /* Issue a marker after FW becomes ready. */
                        qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
                        set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                }
  
@@@ -5209,7 -6004,7 +6004,7 @@@ qla24xx_nvram_config(scsi_qla_host_t *v
                rval = 1;
        }
  
-       if (!qla_ini_mode_enabled(vha)) {
+       if (qla_tgt_mode_enabled(vha)) {
                /* Don't enable full login after initial LIP */
                nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
                /* Don't enable LIP full login for initiator */
@@@ -5400,6 -6195,7 +6195,7 @@@ uint8_t qla27xx_find_valid_image(struc
  
        for (chksum = 0; cnt--; wptr++)
                chksum += le32_to_cpu(*wptr);
        if (chksum) {
                ql_dbg(ql_dbg_init, vha, 0x018c,
                    "Checksum validation failed for primary image (0x%x)\n",
@@@ -5669,7 -6465,7 +6465,7 @@@ qla2x00_load_risc(scsi_qla_host_t *vha
        /* Validate firmware image by checking version. */
        if (blob->fw->size < 8 * sizeof(uint16_t)) {
                ql_log(ql_log_fatal, vha, 0x0085,
 -                  "Unable to verify integrity of firmware image (%Zd).\n",
 +                  "Unable to verify integrity of firmware image (%zd).\n",
                    blob->fw->size);
                goto fail_fw_integrity;
        }
                if (blob->fw->size < fwclen) {
                        ql_log(ql_log_fatal, vha, 0x0088,
                            "Unable to verify integrity of firmware image "
 -                          "(%Zd).\n", blob->fw->size);
 +                          "(%zd).\n", blob->fw->size);
                        goto fail_fw_integrity;
                }
  
@@@ -5778,7 -6574,7 +6574,7 @@@ qla24xx_load_risc_blob(scsi_qla_host_t 
        /* Validate firmware image by checking version. */
        if (blob->fw->size < 8 * sizeof(uint32_t)) {
                ql_log(ql_log_fatal, vha, 0x0093,
 -                  "Unable to verify integrity of firmware image (%Zd).\n",
 +                  "Unable to verify integrity of firmware image (%zd).\n",
                    blob->fw->size);
                return QLA_FUNCTION_FAILED;
        }
            (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
                dcode[3] == 0)) {
                ql_log(ql_log_fatal, vha, 0x0094,
 -                  "Unable to verify integrity of firmware image (%Zd).\n",
 +                  "Unable to verify integrity of firmware image (%zd).\n",
                    blob->fw->size);
                ql_log(ql_log_fatal, vha, 0x0095,
                    "Firmware data: %08x %08x %08x %08x.\n",
                if (blob->fw->size < fwclen) {
                        ql_log(ql_log_fatal, vha, 0x0096,
                            "Unable to verify integrity of firmware image "
 -                          "(%Zd).\n", blob->fw->size);
 +                          "(%zd).\n", blob->fw->size);
                        return QLA_FUNCTION_FAILED;
                }
  
@@@ -6412,6 -7208,10 +7208,10 @@@ qla81xx_nvram_config(scsi_qla_host_t *v
                vha->flags.process_response_queue = 1;
        }
  
+        /* enable RIDA Format2 */
+       if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
+               icb->firmware_options_3 |= BIT_0;
        if (rval) {
                ql_log(ql_log_warn, vha, 0x0076,
                    "NVRAM configuration failed.\n");
@@@ -6536,13 -7336,26 +7336,26 @@@ qla81xx_update_fw_options(scsi_qla_host
                        __func__, ha->fw_options[2]);
        }
  
-       if (!ql2xetsenable)
-               goto out;
+       /* Move PUREX, ABTS RX & RIDA to ATIOQ */
+       if (ql2xmvasynctoatio) {
+               if (qla_tgt_mode_enabled(vha) ||
+                   qla_dual_mode_enabled(vha))
+                       ha->fw_options[2] |= BIT_11;
+               else
+                       ha->fw_options[2] &= ~BIT_11;
+       }
+       if (ql2xetsenable) {
+               /* Enable ETS Burst. */
+               memset(ha->fw_options, 0, sizeof(ha->fw_options));
+               ha->fw_options[2] |= BIT_9;
+       }
+       ql_dbg(ql_dbg_init, vha, 0xffff,
+               "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
+               __func__, ha->fw_options[1], ha->fw_options[2],
+               ha->fw_options[3], vha->host->active_mode);
  
-       /* Enable ETS Burst. */
-       memset(ha->fw_options, 0, sizeof(ha->fw_options));
-       ha->fw_options[2] |= BIT_9;
- out:
        qla2x00_set_fw_options(vha, ha->fw_options);
  }
  
@@@ -6748,6 -7561,7 +7561,7 @@@ struct qla_qpair *qla2xxx_create_qpair(
                memset(qpair, 0, sizeof(struct qla_qpair));
  
                qpair->hw = vha->hw;
+               qpair->vha = vha;
  
                /* Assign available que pair id */
                mutex_lock(&ha->mq_lock);
index edc2264db45becfc96d2666b13b604bcc2275ef7,914cc5a66b3419f22266508ef0c827f3d45c1de3..352cfb6292c6baddf66c38ad4383fececea08186
@@@ -561,14 -561,50 +561,50 @@@ qla2x00_is_a_vp_did(scsi_qla_host_t *vh
        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;
+       f = tf = NULL;
+       list_for_each_entry_safe(f, tf, &vha->vp_fcports, list)
+               if (f->loop_id == loop_id)
+                       return f;
+       return NULL;
+ }
  
-       list_for_each_entry(fcport, &vha->vp_fcports, list)
-               if (fcport->loop_id == loop_id)
-                       return fcport;
+ 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 +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:
  
                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);
                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;
-               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);
+               {
+                       struct event_arg ea;
+                       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 +1241,7 @@@ qla2x00_process_completed_request(struc
                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 +1264,8 @@@ qla2x00_get_sp_from_handle(scsi_qla_hos
        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 +1373,50 @@@ qla2x00_mbx_iocb_entry(scsi_qla_host_t 
            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 +1429,66 @@@ qla2x00_ct_entry(scsi_qla_host_t *vha, 
        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;
-       type = "ct pass-through";
-       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);
-       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;
+       switch (sp->type) {
+       case SRB_CT_CMD:
+           bsg_job = sp->u.bsg_job;
+           bsg_reply = bsg_job->reply;
+           type = "ct pass-through";
+           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);
+           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=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 +1524,16 @@@ qla24xx_els_ct_entry(scsi_qla_host_t *v
                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,
                            type, sp->handle, comp_status, fw_status[1], fw_status[2],
                            le16_to_cpu(((struct els_sts_entry_24xx *)
                                pkt)->total_byte_count));
 -                      fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
 +                      fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) +
 +                              sizeof(struct fc_bsg_reply);
                        memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
                }
                else {
                                    pkt)->error_subcode_2));
                        res = DID_ERROR << 16;
                        bsg_reply->reply_payload_rcv_len = 0;
 -                      fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
 +                      fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) +
 +                                      sizeof(struct fc_bsg_reply);
                        memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
                }
                ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056,
                bsg_job->reply_len = 0;
        }
  
-       sp->done(vha, sp, res);
+       sp->done(sp, res);
  }
  
  static void
@@@ -1543,6 -1636,7 +1638,7 @@@ qla24xx_logio_entry(scsi_qla_host_t *vh
                    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;
  
        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;
        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;
            le32_to_cpu(logio->io_parameter[1]));
  
  logio_done:
-       sp->done(vha, sp, 0);
+       sp->done(sp, 0);
  }
  
  static void
@@@ -1640,7 -1751,7 +1753,7 @@@ qla24xx_tm_iocb_entry(scsi_qla_host_t *
                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 -1839,7 +1841,7 @@@ static inline voi
  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;
  
        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 -1889,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 -2154,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 -2187,7 +2189,7 @@@ qla2x00_status_entry(scsi_qla_host_t *v
        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 -2448,7 +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:
                                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 -2527,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 -2584,7 +2586,7 @@@ qla2x00_status_cont_entry(struct rsp_qu
        /* 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 -2620,7 +2622,7 @@@ qla2x00_error_entry(scsi_qla_host_t *vh
  
        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 -2678,7 +2680,7 @@@ qla24xx_abort_iocb_entry(scsi_qla_host_
  
        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 -2749,16 +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
                        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,
        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
@@@ -2997,14 -3128,14 +3130,14 @@@ struct qla_init_msix_entry 
        irq_handler_t handler;
  };
  
 -static struct qla_init_msix_entry msix_entries[] = {
 +static const struct qla_init_msix_entry msix_entries[] = {
        { "qla2xxx (default)", qla24xx_msix_default },
        { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
        { "qla2xxx (atio_q)", qla83xx_msix_atio_q },
        { "qla2xxx (qpair_multiq)", qla2xxx_msix_rsp_q },
  };
  
 -static struct qla_init_msix_entry qla82xx_msix_entries[] = {
 +static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
        { "qla2xxx (default)", qla82xx_msix_default },
        { "qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
  };
@@@ -3078,7 -3209,7 +3211,7 @@@ qla24xx_enable_msix(struct qla_hw_data 
                qentry->handle = rsp;
                rsp->msix = qentry;
                scnprintf(qentry->name, sizeof(qentry->name),
 -                  msix_entries[i].name);
 +                  "%s", msix_entries[i].name);
                if (IS_P3P_TYPE(ha))
                        ret = request_irq(qentry->vector,
                                qla82xx_msix_entries[i].handler,
                rsp->msix = qentry;
                qentry->handle = rsp;
                scnprintf(qentry->name, sizeof(qentry->name),
 -                  msix_entries[QLA_ATIO_VECTOR].name);
 +                  "%s", msix_entries[QLA_ATIO_VECTOR].name);
                qentry->in_use = 1;
                ret = request_irq(qentry->vector,
                        msix_entries[QLA_ATIO_VECTOR].handler,
@@@ -3244,7 -3375,7 +3377,7 @@@ qla2x00_free_irqs(scsi_qla_host_t *vha
         * from a probe failure context.
         */
        if (!ha->rsp_q_map || !ha->rsp_q_map[0])
 -              return;
 +              goto free_irqs;
        rsp = ha->rsp_q_map[0];
  
        if (ha->flags.msix_enabled) {
                free_irq(pci_irq_vector(ha->pdev, 0), rsp);
        }
  
 +free_irqs:
        pci_free_irq_vectors(ha->pdev);
  }
  
  int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair,
        struct qla_msix_entry *msix, int vector_type)
  {
 -      struct qla_init_msix_entry *intr = &msix_entries[vector_type];
 +      const struct qla_init_msix_entry *intr = &msix_entries[vector_type];
        scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        int ret;
  
index 96c33e292ebacc0572fb948ff5bdddaf529f969d,945b6320e7d76eaa8220696a045070cfb83baa5c..10b742d27e16467e4bd06f40bd030dd60a766b61
@@@ -1789,16 -1789,16 +1789,16 @@@ qlafx00_update_host_attr(scsi_qla_host_
  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 +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 +2127,7 @@@ static inline voi
  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;
  
        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 +2181,7 @@@ qlafx00_tm_iocb_entry(scsi_qla_host_t *
            (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 +2198,7 @@@ qlafx00_abort_iocb_entry(scsi_qla_host_
  
        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
@@@ -2244,7 -2244,7 +2244,7 @@@ qlafx00_ioctl_iosb_entry(scsi_qla_host_
                memcpy(fstatus.reserved_3,
                    pkt->reserved_2, 20 * sizeof(uint8_t));
  
 -              fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
 +              fw_sts_ptr = ((uint8_t *)scsi_req(bsg_job->req)->sense) +
                    sizeof(struct fc_bsg_reply);
  
                memcpy(fw_sts_ptr, (uint8_t *)&fstatus,
                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 +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 +2614,7 @@@ qlafx00_status_cont_entry(struct rsp_qu
        /* 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 +2695,7 @@@ qlafx00_error_entry(scsi_qla_host_t *vh
  
        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 +2997,7 @@@ qlafx00_build_scsi_iocbs(srb_t *sp, str
        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 +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 +3205,7 @@@ voi
  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 +3232,7 @@@ voi
  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 +3346,7 @@@ qlafx00_fxdisc_iocb(srb_t *sp, struct f
                                            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;
                                            &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);
                                }
                                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);
                        }
                }
                                            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;
                                            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);
                                }
                                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);
                        }
                }
        }
  
        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,
index d01c90c7dd04f047e562a6e22178d936fa91b4b3,4f5965281395f40fab9630a9bcf422a83b58c0d3..bbf1ad9562512e809d1f9a347805dd727dec1bbe
@@@ -237,6 -237,13 +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
   */
@@@ -262,7 -269,6 +269,7 @@@ struct scsi_host_template qla2xxx_drive
        .name                   = QLA2XXX_DRIVER_NAME,
        .queuecommand           = qla2xxx_queuecommand,
  
 +      .eh_timed_out           = fc_eh_timed_out,
        .eh_abort_handler       = qla2xxx_eh_abort,
        .eh_device_reset_handler = qla2xxx_eh_device_reset,
        .eh_target_reset_handler = qla2xxx_eh_target_reset,
@@@ -607,11 -613,11 +614,11 @@@ qla24xx_fw_version_str(struct scsi_qla_
  }
  
  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) {
        }
  
        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)
        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);
  }
  
  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;
        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 -868,7 +869,7 @@@ qla2xxx_queuecommand(struct Scsi_Host *
        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 -957,7 +958,7 @@@ qla2xxx_mqueuecommand(struct Scsi_Host 
        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 -1049,34 +1050,34 @@@ qla2x00_wait_for_hba_online(scsi_qla_ho
        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 -1237,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 -1282,7 +1283,7 @@@ qla2x00_eh_wait_for_pending_commands(sc
                        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);
@@@ -1617,7 -1650,7 +1651,7 @@@ qla2x00_abort_all_cmds(scsi_qla_host_t 
                                /* Don't abort commands in adapter during EEH
                                 * recovery as it's not accessible/responding.
                                 */
 -                              if (!ha->flags.eeh_busy) {
 +                              if (GET_CMD_SP(sp) && !ha->flags.eeh_busy) {
                                        /* Get a reference to the sp and drop the lock.
                                         * The reference ensures this sp->done() call
                                         * - and not the call in qla2xxx_eh_abort() -
                                        spin_lock_irqsave(&ha->hardware_lock, flags);
                                }
                                req->outstanding_cmds[cnt] = NULL;
-                               sp->done(vha, sp, res);
+                               sp->done(sp, res);
                        }
                }
        }
@@@ -3124,7 -3157,8 +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 -3407,26 +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 -3575,14 +3576,14 @@@ qla2x00_schedule_rport_del(struct scsi_
                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 -3625,7 +3626,7 @@@ void qla2x00_mark_device_lost(scsi_qla_
                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 -3648,13 +3649,13 @@@ qla2x00_mark_all_devices_lost(scsi_qla_
  {
        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 -4244,10 +4245,10 @@@ struct scsi_qla_host *qla2x00_create_ho
        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 */
        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,
            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;
        return e;
  }
  
static int
+ int
  qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
  {
        unsigned long flags;
@@@ -4316,7 -4375,6 +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 -4427,67 +4428,67 @@@ qlafx00_post_aenfx_work(struct scsi_qla
        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)
  {
                        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;
                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 -4579,7 +4580,7 @@@ void qla2x00_relogin(struct scsi_qla_ho
  {
        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) {
        /*
                    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 -5285,8 +5286,8 @@@ qla2x00_disable_board_on_pci_error(stru
        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))
        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 -5515,6 +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;
  
index 3084983c128720588390a1d6e618ce1c774f8bc5,8b878a2d7304037097ae9f10eb8c97abb616a675..c2f8c35808801808517911620c48a2285b7c4daa
@@@ -282,10 -282,10 +282,10 @@@ static void tcm_qla2xxx_complete_free(s
  
        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 +299,8 @@@ static void tcm_qla2xxx_free_cmd(struc
        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 +315,7 @@@ static int tcm_qla2xxx_check_stop_free(
  
        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 +339,26 @@@ static void tcm_qla2xxx_release_cmd(str
        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;
  
  
        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);
  }
  
@@@ -371,13 -388,13 +388,13 @@@ static int tcm_qla2xxx_write_pending(st
                 */
                pr_debug("write_pending aborted cmd[%p] refcount %d "
                        "transport_state %x, t_state %x, se_cmd_flags %x\n",
 -                      cmd,cmd->se_cmd.cmd_kref.refcount.counter,
 +                      cmd, kref_read(&cmd->se_cmd.cmd_kref),
                        cmd->se_cmd.transport_state,
                        cmd->se_cmd.t_state,
                        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 +458,7 @@@ static int tcm_qla2xxx_handle_cmd(scsi_
  {
        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;
  
        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 +510,9 @@@ static void tcm_qla2xxx_handle_data_wor
        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);
   */
  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 +580,49 @@@ static void tcm_qla2xxx_handle_dif_err(
   * 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)
                 */
                pr_debug("queue_data_in aborted cmd[%p] refcount %d "
                        "transport_state %x, t_state %x, se_cmd_flags %x\n",
 -                      cmd,cmd->se_cmd.cmd_kref.refcount.counter,
 +                      cmd, kref_read(&cmd->se_cmd.cmd_kref),
                        cmd->se_cmd.transport_state,
                        cmd->se_cmd.t_state,
                        cmd->se_cmd.se_cmd_flags);
                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 +675,11 @@@ static int tcm_qla2xxx_queue_status(str
        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 +735,7 @@@ static void tcm_qla2xxx_queue_tm_rsp(st
        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,
  
        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;
        }
  }
  
  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;
        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 +1191,7 @@@ static struct se_portal_group *tcm_qla2
  /*
   * 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)
  {
            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 +1235,7 @@@ static void tcm_qla2xxx_set_sess_by_s_i
        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;
                        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;
        }
  
                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)
  {
  
        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 +1340,7 @@@ static void tcm_qla2xxx_set_sess_by_loo
        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;
        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;
        }
  
                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);
                                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;
  
        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 +1454,14 @@@ static int tcm_qla2xxx_session_cb(struc
        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
  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;
        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;
        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) {
                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) |
                             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 +1620,7 @@@ static struct qla_tgt_func_tmpl tcm_qla
        .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 +1744,7 @@@ static int tcm_qla2xxx_lport_register_n
                        (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;
        }
index eab274d17b5cbdfdf649756ede874fb16f0764ef,303cb6574a93da44e5d0ea9639ab2abfafae696c..746b97f8e4f74fc25d2d497c45dfadd0920b8164
@@@ -17,7 -17,6 +17,7 @@@
   ******************************************************************************/
  
  #include <crypto/hash.h>
 +#include <linux/module.h>
  #include <linux/string.h>
  #include <linux/kthread.h>
  #include <linux/idr.h>
@@@ -223,7 -222,7 +223,7 @@@ int iscsi_check_for_session_reinstateme
                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);
  
index 4a8b180c478bce1917b469282733e01614e37178,2744251178adb898e7c6df68d01e6063d6091705..c0dbfa0165750523e552b93fdbb0c64c94cdab2d
@@@ -445,10 -445,9 +445,10 @@@ static void core_tpg_lun_ref_release(st
  {
        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. */
  int core_tpg_register(
        struct se_wwn *se_wwn,
        struct se_portal_group *se_tpg,
@@@ -572,6 -571,7 +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);
index 878560e60c75276a1cffe84b09982427f2d8e167,49ce5bc9912fb49f44720344d0f8b035aeededb8..72166412989423b475dc7eba1445e67bac31343d
@@@ -197,6 -197,7 +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 +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 +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 +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 +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;
@@@ -914,7 -915,6 +915,7 @@@ static inline struct se_portal_group *p
  
  struct se_wwn {
        struct target_fabric_configfs *wwn_tf;
 +      void                    *priv;
        struct config_group     wwn_group;
        struct config_group     fabric_stat_group;
  };