Commit 51ef4c26 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes

- Fix vport ndlp ref counting errors
- Fix use after free of ndlp structure
- Use the correct flag to check for LOADING setting.
- Fix driver unload bugs (related to shost references) after link down or rscn
- Fix up HBQ initialization
- Fix port_list locking around driver unload.
- Fix references to hostdata as a phba
- Fix GFFID type offset to work correctly with big endian structure.
- Only call pci_disable_msi if the pci_enable_msi succeeded
- Fix vport_delete wait/fail if in discovery
- Put a reference on the nameservers ndlp when performing CT traffic.
- Remove unbalanced hba unlock.
- Fix up HBQ processing
- Fix lpfc debugfs discovery trace output for ELS rsp cmpl
- Send ADISC when rpi is 0
- Stop FDISC retrying forever
- Unable to retrieve correct config parameter for vport
- Fix sli_validate_fcp_iocb, sli_sum_iocb, sli_abort_iocb to be vport-aware.
- Fix index-out-of-range error in iocb. Spotted by Coverity.
Signed-off-by: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 78b2d852
...@@ -78,6 +78,7 @@ struct lpfc_dma_pool { ...@@ -78,6 +78,7 @@ struct lpfc_dma_pool {
struct hbq_dmabuf { struct hbq_dmabuf {
struct lpfc_dmabuf dbuf; struct lpfc_dmabuf dbuf;
uint32_t size;
uint32_t tag; uint32_t tag;
}; };
...@@ -329,15 +330,7 @@ struct lpfc_vport { ...@@ -329,15 +330,7 @@ struct lpfc_vport {
#define FC_LOADING 0x1 /* HBA in process of loading drvr */ #define FC_LOADING 0x1 /* HBA in process of loading drvr */
#define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */
char *vname; /* Application assigned name */ char *vname; /* Application assigned name */
struct fc_vport *fc_vport;
#ifdef CONFIG_LPFC_DEBUG_FS
struct dentry *debug_disc_trc;
struct dentry *debug_nodelist;
struct dentry *vport_debugfs_root;
struct lpfc_debugfs_trc *disc_trc;
atomic_t disc_trc_cnt;
#endif
/* Vport Config Parameters */ /* Vport Config Parameters */
uint32_t cfg_scan_down; uint32_t cfg_scan_down;
uint32_t cfg_lun_queue_depth; uint32_t cfg_lun_queue_depth;
...@@ -353,6 +346,16 @@ struct lpfc_vport { ...@@ -353,6 +346,16 @@ struct lpfc_vport {
uint32_t cfg_max_luns; uint32_t cfg_max_luns;
uint32_t dev_loss_tmo_changed; uint32_t dev_loss_tmo_changed;
struct fc_vport *fc_vport;
#ifdef CONFIG_LPFC_DEBUG_FS
struct dentry *debug_disc_trc;
struct dentry *debug_nodelist;
struct dentry *vport_debugfs_root;
struct lpfc_debugfs_trc *disc_trc;
atomic_t disc_trc_cnt;
#endif
}; };
struct hbq_s { struct hbq_s {
...@@ -360,11 +363,19 @@ struct hbq_s { ...@@ -360,11 +363,19 @@ struct hbq_s {
uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */ uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */
uint32_t hbqPutIdx; /* HBQ slot to use */ uint32_t hbqPutIdx; /* HBQ slot to use */
uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */ uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */
void *hbq_virt; /* Virtual ptr to this hbq */
struct list_head hbq_buffer_list; /* buffers assigned to this HBQ */
/* Callback for HBQ buffer allocation */
struct hbq_dmabuf *(*hbq_alloc_buffer) (struct lpfc_hba *);
/* Callback for HBQ buffer free */
void (*hbq_free_buffer) (struct lpfc_hba *,
struct hbq_dmabuf *);
}; };
#define LPFC_MAX_HBQS 16 #define LPFC_MAX_HBQS 4
/* this matches the possition in the lpfc_hbq_defs array */ /* this matches the position in the lpfc_hbq_defs array */
#define LPFC_ELS_HBQ 0 #define LPFC_ELS_HBQ 0
#define LPFC_EXTRA_HBQ 1
struct lpfc_hba { struct lpfc_hba {
struct lpfc_sli sli; struct lpfc_sli sli;
...@@ -460,7 +471,6 @@ struct lpfc_hba { ...@@ -460,7 +471,6 @@ struct lpfc_hba {
wait_queue_head_t *work_wait; wait_queue_head_t *work_wait;
struct task_struct *worker_thread; struct task_struct *worker_thread;
struct list_head hbq_buffer_list;
uint32_t hbq_count; /* Count of configured HBQs */ uint32_t hbq_count; /* Count of configured HBQs */
struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */ struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */
...@@ -529,6 +539,7 @@ struct lpfc_hba { ...@@ -529,6 +539,7 @@ struct lpfc_hba {
mempool_t *nlp_mem_pool; mempool_t *nlp_mem_pool;
struct fc_host_statistics link_stats; struct fc_host_statistics link_stats;
uint8_t using_msi;
struct list_head port_list; struct list_head port_list;
struct lpfc_vport *pport; /* physical lpfc_vport pointer */ struct lpfc_vport *pport; /* physical lpfc_vport pointer */
......
...@@ -1027,8 +1027,8 @@ static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ ...@@ -1027,8 +1027,8 @@ static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
static ssize_t static ssize_t
lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) lpfc_soft_wwnn_show(struct class_device *cdev, char *buf)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
return snprintf(buf, PAGE_SIZE, "0x%llx\n", return snprintf(buf, PAGE_SIZE, "0x%llx\n",
(unsigned long long)phba->cfg_soft_wwnn); (unsigned long long)phba->cfg_soft_wwnn);
} }
...@@ -1037,8 +1037,8 @@ lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) ...@@ -1037,8 +1037,8 @@ lpfc_soft_wwnn_show(struct class_device *cdev, char *buf)
static ssize_t static ssize_t
lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count) lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count)
{ {
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *shost = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
unsigned int i, j, cnt=count; unsigned int i, j, cnt=count;
u8 wwnn[8]; u8 wwnn[8];
...@@ -1153,24 +1153,15 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val) ...@@ -1153,24 +1153,15 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
static void static void
lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
{ {
struct lpfc_vport **vports;
struct Scsi_Host *shost; struct Scsi_Host *shost;
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;
int i;
vports = lpfc_create_vport_work_array(vport->phba); shost = lpfc_shost_from_vport(vport);
if (vports != NULL) spin_lock_irq(shost->host_lock);
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
shost = lpfc_shost_from_vport(vports[i]); if (ndlp->rport)
spin_lock_irq(shost->host_lock); ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
list_for_each_entry(ndlp, &vports[i]->fc_nodes, spin_unlock_irq(shost->host_lock);
nlp_listp)
if (ndlp->rport)
ndlp->rport->dev_loss_tmo =
vport->cfg_devloss_tmo;
spin_unlock_irq(shost->host_lock);
}
lpfc_destroy_vport_work_array(vports);
} }
static int static int
......
...@@ -102,7 +102,7 @@ int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); ...@@ -102,7 +102,7 @@ int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t);
int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t); struct lpfc_nodelist *, LPFC_MBOXQ_t *);
int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
struct lpfc_nodelist *, LPFC_MBOXQ_t *); struct lpfc_nodelist *, LPFC_MBOXQ_t *);
int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *, int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *,
...@@ -163,9 +163,11 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); ...@@ -163,9 +163,11 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_mbox_tmo_val(struct lpfc_hba *, int); int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
void lpfc_config_hbq(struct lpfc_hba *, struct lpfc_hbq_init *, uint32_t , void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *,
LPFC_MBOXQ_t *); uint32_t , LPFC_MBOXQ_t *);
struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t); struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t);
struct hbq_dmabuf *lpfc_els_hbq_alloc(struct lpfc_hba *);
void lpfc_els_hbq_free(struct lpfc_hba *, struct hbq_dmabuf *);
int lpfc_mem_alloc(struct lpfc_hba *); int lpfc_mem_alloc(struct lpfc_hba *);
void lpfc_mem_free(struct lpfc_hba *); void lpfc_mem_free(struct lpfc_hba *);
...@@ -202,6 +204,7 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, ...@@ -202,6 +204,7 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
struct lpfc_sli_ring *, struct lpfc_sli_ring *,
dma_addr_t); dma_addr_t);
int lpfc_sli_hbq_count(void);
int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t); int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t);
int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t);
void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *); void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *);
...@@ -209,10 +212,9 @@ struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t); ...@@ -209,10 +212,9 @@ struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t);
int lpfc_sli_hbq_size(void); int lpfc_sli_hbq_size(void);
int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *); struct lpfc_iocbq *);
int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd);
uint64_t, lpfc_ctx_cmd); int lpfc_sli_abort_iocb(struct lpfc_vport *, struct lpfc_sli_ring *, uint16_t,
int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, uint64_t, lpfc_ctx_cmd);
uint64_t, uint32_t, lpfc_ctx_cmd);
void lpfc_mbox_timeout(unsigned long); void lpfc_mbox_timeout(unsigned long);
void lpfc_mbox_timeout_handler(struct lpfc_hba *); void lpfc_mbox_timeout_handler(struct lpfc_hba *);
...@@ -236,8 +238,6 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, ...@@ -236,8 +238,6 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba,
struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb); struct lpfc_iocbq * rspiocb);
void *lpfc_hbq_alloc(struct lpfc_hba *, int, dma_addr_t *);
void lpfc_hbq_free(struct lpfc_hba *, void *, dma_addr_t);
void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *); void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *);
void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *); void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
......
...@@ -257,6 +257,10 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) ...@@ -257,6 +257,10 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb)
{ {
struct lpfc_dmabuf *buf_ptr; struct lpfc_dmabuf *buf_ptr;
if (ctiocb->context_un.ndlp) {
lpfc_nlp_put(ctiocb->context_un.ndlp);
ctiocb->context_un.ndlp = NULL;
}
if (ctiocb->context1) { if (ctiocb->context1) {
buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1; buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1;
lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
...@@ -314,6 +318,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, ...@@ -314,6 +318,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
/* Save for completion so we can release these resources */ /* Save for completion so we can release these resources */
geniocb->context1 = (uint8_t *) inp; geniocb->context1 = (uint8_t *) inp;
geniocb->context2 = (uint8_t *) outp; geniocb->context2 = (uint8_t *) outp;
geniocb->context_un.ndlp = ndlp;
/* Fill in payload, bp points to frame payload */ /* Fill in payload, bp points to frame payload */
icmd->ulpCommand = CMD_GEN_REQUEST64_CR; icmd->ulpCommand = CMD_GEN_REQUEST64_CR;
...@@ -548,8 +553,12 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -548,8 +553,12 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_dmabuf *bmp; struct lpfc_dmabuf *bmp;
struct lpfc_dmabuf *outp; struct lpfc_dmabuf *outp;
struct lpfc_sli_ct_request *CTrsp; struct lpfc_sli_ct_request *CTrsp;
struct lpfc_nodelist *ndlp;
int rc; int rc;
/* First save ndlp, before we overwrite it */
ndlp = cmdiocb->context_un.ndlp;
/* we pass cmdiocb to state machine which needs rspiocb as well */ /* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb; cmdiocb->context_un.rsp_iocb = rspiocb;
...@@ -674,6 +683,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -674,6 +683,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_disc_start(vport); lpfc_disc_start(vport);
} }
out: out:
cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
lpfc_ct_free_iocb(phba, cmdiocb); lpfc_ct_free_iocb(phba, cmdiocb);
return; return;
} }
...@@ -776,10 +786,14 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -776,10 +786,14 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_dmabuf *outp; struct lpfc_dmabuf *outp;
IOCB_t *irsp; IOCB_t *irsp;
struct lpfc_sli_ct_request *CTrsp; struct lpfc_sli_ct_request *CTrsp;
struct lpfc_nodelist *ndlp;
int cmdcode, rc; int cmdcode, rc;
uint8_t retry; uint8_t retry;
uint32_t latt; uint32_t latt;
/* First save ndlp, before we overwrite it */
ndlp = cmdiocb->context_un.ndlp;
/* we pass cmdiocb to state machine which needs rspiocb as well */ /* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb; cmdiocb->context_un.rsp_iocb = rspiocb;
...@@ -828,6 +842,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -828,6 +842,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
} }
out: out:
cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
lpfc_ct_free_iocb(phba, cmdiocb); lpfc_ct_free_iocb(phba, cmdiocb);
return; return;
} }
...@@ -1066,6 +1081,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, ...@@ -1066,6 +1081,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
cmpl = lpfc_cmpl_ct_cmd_rff_id; cmpl = lpfc_cmpl_ct_cmd_rff_id;
break; break;
} }
lpfc_nlp_get(ndlp);
if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
/* On success, The cmpl function will free the buffers */ /* On success, The cmpl function will free the buffers */
...@@ -1076,6 +1092,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, ...@@ -1076,6 +1092,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
} }
rc=6; rc=6;
lpfc_nlp_put(ndlp);
lpfc_mbuf_free(phba, bmp->virt, bmp->phys); lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
ns_cmd_free_bmp: ns_cmd_free_bmp:
kfree(bmp); kfree(bmp);
...@@ -1501,10 +1518,12 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) ...@@ -1501,10 +1518,12 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
bpl->tus.w = le32_to_cpu(bpl->tus.w); bpl->tus.w = le32_to_cpu(bpl->tus.w);
cmpl = lpfc_cmpl_ct_cmd_fdmi; cmpl = lpfc_cmpl_ct_cmd_fdmi;
lpfc_nlp_get(ndlp);
if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0)) if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0))
return 0; return 0;
lpfc_nlp_put(ndlp);
lpfc_mbuf_free(phba, bmp->virt, bmp->phys); lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
fdmi_cmd_free_bmp: fdmi_cmd_free_bmp:
kfree(bmp); kfree(bmp);
......
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
* lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in * lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in
* lpfc_debugfs.h . * lpfc_debugfs.h .
*/ */
static int lpfc_debugfs_enable = 0; static int lpfc_debugfs_enable = 1;
module_param(lpfc_debugfs_enable, int, 0); module_param(lpfc_debugfs_enable, int, 0);
MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services"); MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
...@@ -113,7 +113,6 @@ struct lpfc_debug { ...@@ -113,7 +113,6 @@ struct lpfc_debug {
}; };
extern struct lpfc_hbq_init *lpfc_hbq_defs[]; extern struct lpfc_hbq_init *lpfc_hbq_defs[];
extern int lpfc_sli_hbq_count(void);
atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
unsigned long lpfc_debugfs_start_time = 0L; unsigned long lpfc_debugfs_start_time = 0L;
...@@ -233,8 +232,9 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) ...@@ -233,8 +232,9 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
len += snprintf(buf+len, size-len, "HBQ %d Info\n", i); len += snprintf(buf+len, size-len, "HBQ %d Info\n", i);
hbqs = &phba->hbqs[i];
posted = 0; posted = 0;
list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list)
posted++; posted++;
hip = lpfc_hbq_defs[i]; hip = lpfc_hbq_defs[i];
...@@ -243,7 +243,6 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) ...@@ -243,7 +243,6 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
hip->hbq_index, hip->profile, hip->rn, hip->hbq_index, hip->profile, hip->rn,
hip->buffer_count, hip->init_count, hip->add_count, posted); hip->buffer_count, hip->init_count, hip->add_count, posted);
hbqs = &phba->hbqs[i];
raw_index = phba->hbq_get[i]; raw_index = phba->hbq_get[i];
getidx = le32_to_cpu(raw_index); getidx = le32_to_cpu(raw_index);
len += snprintf(buf+len, size-len, len += snprintf(buf+len, size-len,
...@@ -251,7 +250,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) ...@@ -251,7 +250,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx, hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx,
hbqs->local_hbqGetIdx, getidx); hbqs->local_hbqGetIdx, getidx);
hbqe = (struct lpfc_hbq_entry *) phba->hbqslimp.virt; hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt;
for (j=0; j<hbqs->entry_count; j++) { for (j=0; j<hbqs->entry_count; j++) {
len += snprintf(buf+len, size-len, len += snprintf(buf+len, size-len,
"%03d: %08x %04x %05x ", j, "%03d: %08x %04x %05x ", j,
...@@ -277,7 +276,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) ...@@ -277,7 +276,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
} }
/* Get the Buffer info for the posted buffer */ /* Get the Buffer info for the posted buffer */
list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) { list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) {
hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff);
if (phys == hbqe->bde.addrLow) { if (phys == hbqe->bde.addrLow) {
......
...@@ -196,9 +196,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, ...@@ -196,9 +196,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
bpl->tus.w = le32_to_cpu(bpl->tus.w); bpl->tus.w = le32_to_cpu(bpl->tus.w);
} }
/* Save for completion so we can release these resources */ elsiocb->context1 = lpfc_nlp_get(ndlp);
if (elscmd != ELS_CMD_LS_RJT)
elsiocb->context1 = lpfc_nlp_get(ndlp);
elsiocb->context2 = pcmd; elsiocb->context2 = pcmd;
elsiocb->context3 = pbuflist; elsiocb->context3 = pbuflist;
elsiocb->retry = retry; elsiocb->retry = retry;
...@@ -1809,8 +1807,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -1809,8 +1807,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
"retrying...\n"); "retrying...\n");
lpfc_mbx_unreg_vpi(vport); lpfc_mbx_unreg_vpi(vport);
retry = 1; retry = 1;
/* Always retry for this case */ /* FDISC retry policy */
cmdiocb->retry = 0; maxretry = 48;
if (cmdiocb->retry >= 32)
delay = 1000;
} }
break; break;
...@@ -1886,8 +1886,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -1886,8 +1886,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
delay = 1000; delay = 1000;
maxretry = 48; maxretry = 48;
} else if (cmd == ELS_CMD_FDISC) { } else if (cmd == ELS_CMD_FDISC) {
/* Always retry for this case */ /* FDISC retry policy */
cmdiocb->retry = 0; maxretry = 48;
if (cmdiocb->retry >= 32)
delay = 1000;
} }
retry = 1; retry = 1;
break; break;
...@@ -2121,9 +2123,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -2121,9 +2123,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
} }
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
"ACC cmpl: status:x%x/x%x did:x%x", "ELS rsp cmpl: status:x%x/x%x did:x%x",
irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpStatus, irsp->un.ulpWord[4],
irsp->un.rcvels.remoteID); cmdiocb->iocb.un.elsreq64.remoteID);
/* ELS response tag <ulpIoTag> completes */ /* ELS response tag <ulpIoTag> completes */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0110 ELS response tag x%x completes " "0110 ELS response tag x%x completes "
...@@ -2184,7 +2186,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -2184,7 +2186,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
int int
lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
LPFC_MBOXQ_t *mbox, uint8_t newnode) LPFC_MBOXQ_t *mbox)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
...@@ -2270,11 +2272,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, ...@@ -2270,11 +2272,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
default: default:
return 1; return 1;
} }
if (newnode) {
lpfc_nlp_put(ndlp);
elsiocb->context1 = NULL;
}
/* Xmit ELS ACC response tag <ulpIoTag> */ /* Xmit ELS ACC response tag <ulpIoTag> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0128 Xmit ELS ACC response tag x%x, XRI: x%x, " "0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
...@@ -2333,10 +2330,8 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, ...@@ -2333,10 +2330,8 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
pcmd += sizeof(uint32_t); pcmd += sizeof(uint32_t);
*((uint32_t *) (pcmd)) = rejectError; *((uint32_t *) (pcmd)) = rejectError;
if (mbox) { if (mbox)
elsiocb->context_un.mbox = mbox; elsiocb->context_un.mbox = mbox;
elsiocb->context1 = lpfc_nlp_get(ndlp);
}
/* Xmit ELS RJT <err> response tag <ulpIoTag> */ /* Xmit ELS RJT <err> response tag <ulpIoTag> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
...@@ -2353,6 +2348,15 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, ...@@ -2353,6 +2348,15 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
phba->fc_stat.elsXmitLSRJT++; phba->fc_stat.elsXmitLSRJT++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
/* If the node is in the UNUSED state, and we are sending
* a reject, we are done with it. Release driver reference
* count here. The outstanding els will release its reference on
* completion and the node can be freed then.
*/
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
lpfc_nlp_put(ndlp);
if (rc == IOCB_ERROR) { if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb); lpfc_els_free_iocb(phba, elsiocb);
return 1; return 1;
...@@ -2747,7 +2751,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) ...@@ -2747,7 +2751,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
static int static int
lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp, uint8_t newnode) struct lpfc_nodelist *ndlp)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
...@@ -2781,8 +2785,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -2781,8 +2785,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
"RCV RSCN ignore: did:x%x/ste:x%x flg:x%x", "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
newnode);
return 0; return 0;
} }
...@@ -2814,7 +2817,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -2814,7 +2817,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
ndlp->nlp_flag); ndlp->nlp_flag);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
ndlp, NULL, newnode); ndlp, NULL);
return 0; return 0;
} }
} }
...@@ -2870,8 +2873,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -2870,8 +2873,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
vport->port_state); vport->port_state);
} }
/* Send back ACC */ /* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
newnode);
/* send RECOVERY event for ALL nodes that match RSCN payload */ /* send RECOVERY event for ALL nodes that match RSCN payload */
lpfc_rscn_recovery_check(vport); lpfc_rscn_recovery_check(vport);
...@@ -2896,7 +2898,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -2896,7 +2898,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
lpfc_set_disctmo(vport); lpfc_set_disctmo(vport);
/* Send back ACC */ /* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
/* send RECOVERY event for ALL nodes that match RSCN payload */ /* send RECOVERY event for ALL nodes that match RSCN payload */
lpfc_rscn_recovery_check(vport); lpfc_rscn_recovery_check(vport);
...@@ -2965,7 +2967,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) ...@@ -2965,7 +2967,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
static int static int
lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp, uint8_t newnode) struct lpfc_nodelist *ndlp)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
...@@ -3048,7 +3050,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3048,7 +3050,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
} }
/* Send back ACC */ /* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
return 0; return 0;
} }
...@@ -3409,7 +3411,7 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3409,7 +3411,7 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0600 FARP-RSP received from DID x%x\n", did); "0600 FARP-RSP received from DID x%x\n", did);
/* ACCEPT the Farp resp request */ /* ACCEPT the Farp resp request */
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
return 0; return 0;
} }
...@@ -3791,7 +3793,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3791,7 +3793,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
did, vport->port_state, ndlp->nlp_flag); did, vport->port_state, ndlp->nlp_flag);
phba->fc_stat.elsRcvFLOGI++; phba->fc_stat.elsRcvFLOGI++;
lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode); lpfc_els_rcv_flogi(vport, elsiocb, ndlp);
if (newnode) if (newnode)
lpfc_drop_node(vport, ndlp); lpfc_drop_node(vport, ndlp);
break; break;
...@@ -3821,7 +3823,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3821,7 +3823,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
break; break;
case ELS_CMD_RSCN: case ELS_CMD_RSCN:
phba->fc_stat.elsRcvRSCN++; phba->fc_stat.elsRcvRSCN++;
lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode); lpfc_els_rcv_rscn(vport, elsiocb, ndlp);
if (newnode) if (newnode)
lpfc_drop_node(vport, ndlp); lpfc_drop_node(vport, ndlp);
break; break;
...@@ -3951,8 +3953,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3951,8 +3953,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp, lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
NULL); NULL);
if (newnode)
lpfc_drop_node(vport, ndlp);
} }
return; return;
......
...@@ -83,10 +83,17 @@ lpfc_terminate_rport_io(struct fc_rport *rport) ...@@ -83,10 +83,17 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
if (ndlp->nlp_sid != NLP_NO_SID) { if (ndlp->nlp_sid != NLP_NO_SID) {
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], lpfc_sli_abort_iocb(ndlp->vport,
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, LPFC_CTX_TGT);
} }
/*
* A device is normally blocked for rediscovery and unblocked when
* devloss timeout happens. In case a vport is removed or driver
* unloaded before devloss timeout happens, we need to unblock here.
*/
scsi_target_unblock(&rport->dev);
return; return;
} }
...@@ -194,8 +201,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -194,8 +201,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
if (ndlp->nlp_sid != NLP_NO_SID) { if (ndlp->nlp_sid != NLP_NO_SID) {
warn_on = 1; warn_on = 1;
/* flush the target */ /* flush the target */
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); ndlp->nlp_sid, 0, LPFC_CTX_TGT);
} }
if (vport->load_flag & FC_UNLOADING) if (vport->load_flag & FC_UNLOADING)
warn_on = 0; warn_on = 0;
...@@ -348,6 +355,7 @@ lpfc_work_done(struct lpfc_hba *phba) ...@@ -348,6 +355,7 @@ lpfc_work_done(struct lpfc_hba *phba)
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
uint32_t ha_copy, status, control, work_port_events; uint32_t ha_copy, status, control, work_port_events;
struct lpfc_vport **vports; struct lpfc_vport **vports;
struct lpfc_vport *vport;
int i; int i;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
...@@ -365,12 +373,22 @@ lpfc_work_done(struct lpfc_hba *phba) ...@@ -365,12 +373,22 @@ lpfc_work_done(struct lpfc_hba *phba)
lpfc_handle_latt(phba); lpfc_handle_latt(phba);
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { for(i = 0; i < LPFC_MAX_VPORTS; i++) {
work_port_events = vports[i]->work_port_events; /*
* We could have no vports in array if unloading, so if
* this happens then just use the pport
*/
if (vports[i] == NULL && i == 0)
vport = phba->pport;
else
vport = vports[i];
if (vport == NULL)
break;
work_port_events = vport->work_port_events;
if (work_port_events & WORKER_DISC_TMO) if (work_port_events & WORKER_DISC_TMO)
lpfc_disc_timeout_handler(vports[i]); lpfc_disc_timeout_handler(vport);
if (work_port_events & WORKER_ELS_TMO) if (work_port_events & WORKER_ELS_TMO)
lpfc_els_timeout_handler(vports[i]); lpfc_els_timeout_handler(vport);
if (work_port_events & WORKER_HB_TMO) if (work_port_events & WORKER_HB_TMO)
lpfc_hb_timeout_handler(phba); lpfc_hb_timeout_handler(phba);
if (work_port_events & WORKER_MBOX_TMO) if (work_port_events & WORKER_MBOX_TMO)
...@@ -378,14 +396,14 @@ lpfc_work_done(struct lpfc_hba *phba) ...@@ -378,14 +396,14 @@ lpfc_work_done(struct lpfc_hba *phba)
if (work_port_events & WORKER_FABRIC_BLOCK_TMO) if (work_port_events & WORKER_FABRIC_BLOCK_TMO)
lpfc_unblock_fabric_iocbs(phba); lpfc_unblock_fabric_iocbs(phba);
if (work_port_events & WORKER_FDMI_TMO) if (work_port_events & WORKER_FDMI_TMO)
lpfc_fdmi_timeout_handler(vports[i]); lpfc_fdmi_timeout_handler(vport);
if (work_port_events & WORKER_RAMP_DOWN_QUEUE) if (work_port_events & WORKER_RAMP_DOWN_QUEUE)
lpfc_ramp_down_queue_handler(phba); lpfc_ramp_down_queue_handler(phba);
if (work_port_events & WORKER_RAMP_UP_QUEUE) if (work_port_events & WORKER_RAMP_UP_QUEUE)
lpfc_ramp_up_queue_handler(phba); lpfc_ramp_up_queue_handler(phba);
spin_lock_irq(&vports[i]->work_port_lock); spin_lock_irq(&vport->work_port_lock);
vports[i]->work_port_events &= ~work_port_events; vport->work_port_events &= ~work_port_events;
spin_unlock_irq(&vports[i]->work_port_lock); spin_unlock_irq(&vport->work_port_lock);
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(vports);
...@@ -1638,16 +1656,7 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -1638,16 +1656,7 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
void void
lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport); lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
lpfc_cancel_retry_delay_tmo(vport, ndlp);
if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
spin_lock_irq(shost->host_lock);
list_del_init(&ndlp->nlp_listp);
ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
spin_unlock_irq(shost->host_lock);
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
} }
......
...@@ -150,7 +150,11 @@ struct lpfc_sli_ct_request { ...@@ -150,7 +150,11 @@ struct lpfc_sli_ct_request {
struct gff_acc { struct gff_acc {
uint8_t fbits[128]; uint8_t fbits[128];
} gff_acc; } gff_acc;
#ifdef __BIG_ENDIAN_BITFIELD
#define FCP_TYPE_FEATURE_OFFSET 7
#else /* __LITTLE_ENDIAN_BITFIELD */
#define FCP_TYPE_FEATURE_OFFSET 4 #define FCP_TYPE_FEATURE_OFFSET 4
#endif
struct rff { struct rff {
uint32_t PortId; uint32_t PortId;
uint8_t reserved[2]; uint8_t reserved[2];
......
...@@ -55,6 +55,8 @@ static DEFINE_IDR(lpfc_hba_index); ...@@ -55,6 +55,8 @@ static DEFINE_IDR(lpfc_hba_index);
extern struct lpfc_hbq_init *lpfc_hbq_defs[];
/************************************************************************/ /************************************************************************/
/* */ /* */
/* lpfc_config_port_prep */ /* lpfc_config_port_prep */
...@@ -429,18 +431,11 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -429,18 +431,11 @@ lpfc_config_port_post(struct lpfc_hba *phba)
int int
lpfc_hba_down_prep(struct lpfc_hba *phba) lpfc_hba_down_prep(struct lpfc_hba *phba)
{ {
struct lpfc_vport **vports;
int i;
/* Disable interrupts */ /* Disable interrupts */
writel(0, phba->HCregaddr); writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */ readl(phba->HCregaddr); /* flush */
vports = lpfc_create_vport_work_array(phba); lpfc_cleanup_discovery_resources(phba->pport);
if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++)
lpfc_cleanup_discovery_resources(vports[i]);
lpfc_destroy_vport_work_array(vports);
return 0; return 0;
} }
...@@ -512,7 +507,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) ...@@ -512,7 +507,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
mempool_free(pmboxq, phba->mbox_mem_pool); mempool_free(pmboxq, phba->mbox_mem_pool);
if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) && if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) &&
!(phba->link_state == LPFC_HBA_ERROR) && !(phba->link_state == LPFC_HBA_ERROR) &&
!(phba->pport->fc_flag & FC_UNLOADING)) !(phba->pport->load_flag & FC_UNLOADING))
mod_timer(&phba->hb_tmofunc, mod_timer(&phba->hb_tmofunc,
jiffies + HZ * LPFC_HB_MBOX_INTERVAL); jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
return; return;
...@@ -526,7 +521,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) ...@@ -526,7 +521,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
if ((phba->link_state == LPFC_HBA_ERROR) || if ((phba->link_state == LPFC_HBA_ERROR) ||
(phba->pport->fc_flag & FC_UNLOADING) || (phba->pport->load_flag & FC_UNLOADING) ||
(phba->pport->fc_flag & FC_OFFLINE_MODE)) (phba->pport->fc_flag & FC_OFFLINE_MODE))
return; return;
...@@ -1340,16 +1335,9 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport) ...@@ -1340,16 +1335,9 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
static void static void
lpfc_stop_phba_timers(struct lpfc_hba *phba) lpfc_stop_phba_timers(struct lpfc_hba *phba)
{ {
struct lpfc_vport **vports;
int i;
del_timer_sync(&phba->fcp_poll_timer); del_timer_sync(&phba->fcp_poll_timer);
del_timer_sync(&phba->fc_estabtmo); del_timer_sync(&phba->fc_estabtmo);
vports = lpfc_create_vport_work_array(phba); lpfc_stop_vport_timers(phba->pport);
if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++)
lpfc_stop_vport_timers(vports[i]);
lpfc_destroy_vport_work_array(vports);
del_timer_sync(&phba->sli.mbox_tmo); del_timer_sync(&phba->sli.mbox_tmo);
del_timer_sync(&phba->fabric_block_timer); del_timer_sync(&phba->fabric_block_timer);
phba->hb_outstanding = 0; phba->hb_outstanding = 0;
...@@ -1455,6 +1443,11 @@ lpfc_offline(struct lpfc_hba *phba) ...@@ -1455,6 +1443,11 @@ lpfc_offline(struct lpfc_hba *phba)
/* stop all timers associated with this hba */ /* stop all timers associated with this hba */
lpfc_stop_phba_timers(phba); lpfc_stop_phba_timers(phba);
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++)
lpfc_stop_vport_timers(vports[i]);
lpfc_destroy_vport_work_array(vports);
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"0460 Bring Adapter offline\n"); "0460 Bring Adapter offline\n");
/* Bring down the SLI Layer and cleanup. The HBA is offline /* Bring down the SLI Layer and cleanup. The HBA is offline
...@@ -1629,7 +1622,7 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) ...@@ -1629,7 +1622,7 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
if (vport->fc_flag & FC_UNLOADING) { if (vport->load_flag & FC_UNLOADING) {
stat = 1; stat = 1;
goto finished; goto finished;
} }
...@@ -1706,7 +1699,7 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) ...@@ -1706,7 +1699,7 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
fc_host_max_npiv_vports(shost) = phba->max_vpi; fc_host_max_npiv_vports(shost) = phba->max_vpi;
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_LOADING; vport->load_flag &= ~FC_LOADING;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
...@@ -1718,9 +1711,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) ...@@ -1718,9 +1711,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
struct lpfc_sli *psli; struct lpfc_sli *psli;
struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL; struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;
struct Scsi_Host *shost = NULL; struct Scsi_Host *shost = NULL;
void *ptr;
unsigned long bar0map_len, bar2map_len; unsigned long bar0map_len, bar2map_len;
int error = -ENODEV; int error = -ENODEV;
int i; int i, hbq_count;
uint16_t iotag; uint16_t iotag;
if (pci_enable_device(pdev)) if (pci_enable_device(pdev))
...@@ -1741,7 +1735,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) ...@@ -1741,7 +1735,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_free_phba; goto out_free_phba;
INIT_LIST_HEAD(&phba->port_list); INIT_LIST_HEAD(&phba->port_list);
INIT_LIST_HEAD(&phba->hbq_buffer_list);
/* /*
* Get all the module params for configuring this host and then * Get all the module params for configuring this host and then
* establish the host. * establish the host.
...@@ -1819,6 +1812,17 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) ...@@ -1819,6 +1812,17 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
if (!phba->hbqslimp.virt) if (!phba->hbqslimp.virt)
goto out_free_slim; goto out_free_slim;
hbq_count = lpfc_sli_hbq_count();
ptr = phba->hbqslimp.virt;
for (i = 0; i < hbq_count; ++i) {
phba->hbqs[i].hbq_virt = ptr;
INIT_LIST_HEAD(&phba->hbqs[i].hbq_buffer_list);
ptr += (lpfc_hbq_defs[i]->entry_count *
sizeof(struct lpfc_hbq_entry));
}
phba->hbqs[LPFC_ELS_HBQ].hbq_alloc_buffer = lpfc_els_hbq_alloc;
phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer = lpfc_els_hbq_free;
memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size()); memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size());
/* Initialize the SLI Layer to run with lpfc HBAs. */ /* Initialize the SLI Layer to run with lpfc HBAs. */
...@@ -1894,7 +1898,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) ...@@ -1894,7 +1898,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
if (phba->cfg_use_msi) { if (phba->cfg_use_msi) {
error = pci_enable_msi(phba->pcidev); error = pci_enable_msi(phba->pcidev);
if (error) if (!error)
phba->using_msi = 1;
else
lpfc_printf_log(phba, KERN_INFO, LOG_INIT, lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"0452 Enable MSI failed, continuing " "0452 Enable MSI failed, continuing "
"with IRQ\n"); "with IRQ\n");
...@@ -1941,14 +1947,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) ...@@ -1941,14 +1947,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
out_remove_device: out_remove_device:
lpfc_free_sysfs_attr(vport); lpfc_free_sysfs_attr(vport);
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_UNLOADING; vport->load_flag |= FC_UNLOADING;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
out_free_irq: out_free_irq:
lpfc_stop_phba_timers(phba); lpfc_stop_phba_timers(phba);
phba->pport->work_port_events = 0; phba->pport->work_port_events = 0;
free_irq(phba->pcidev->irq, phba); free_irq(phba->pcidev->irq, phba);
out_disable_msi: out_disable_msi:
pci_disable_msi(phba->pcidev); if (phba->using_msi)
pci_disable_msi(phba->pcidev);
destroy_port(vport); destroy_port(vport);
out_kthread_stop: out_kthread_stop:
kthread_stop(phba->worker_thread); kthread_stop(phba->worker_thread);
...@@ -1990,10 +1997,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -1990,10 +1997,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
struct Scsi_Host *shost = pci_get_drvdata(pdev); struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
struct lpfc_vport *port_iterator;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
list_for_each_entry(port_iterator, &phba->port_list, listentry) vport->load_flag |= FC_UNLOADING;
port_iterator->load_flag |= FC_UNLOADING;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
kfree(vport->vname); kfree(vport->vname);
...@@ -2001,7 +2006,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -2001,7 +2006,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
fc_remove_host(shost); fc_remove_host(shost);
scsi_remove_host(shost); scsi_remove_host(shost);
/* /*
* Bring down the SLI Layer. This step disable all interrupts, * Bring down the SLI Layer. This step disable all interrupts,
* clears the rings, discards all mailbox commands, and resets * clears the rings, discards all mailbox commands, and resets
...@@ -2022,7 +2026,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -2022,7 +2026,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
/* Release the irq reservation */ /* Release the irq reservation */
free_irq(phba->pcidev->irq, phba); free_irq(phba->pcidev->irq, phba);
pci_disable_msi(phba->pcidev); if (phba->using_msi)
pci_disable_msi(phba->pcidev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
scsi_host_put(shost); scsi_host_put(shost);
...@@ -2064,8 +2069,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -2064,8 +2069,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state) pci_channel_state_t state)
{ {
struct Scsi_Host *host = pci_get_drvdata(pdev); struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
...@@ -2081,6 +2086,11 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, ...@@ -2081,6 +2086,11 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
pring = &psli->ring[psli->fcp_ring]; pring = &psli->ring[psli->fcp_ring];
lpfc_sli_abort_iocb_ring(phba, pring); lpfc_sli_abort_iocb_ring(phba, pring);
/* Release the irq reservation */
free_irq(phba->pcidev->irq, phba);
if (phba->using_msi)
pci_disable_msi(phba->pcidev);
/* Request a slot reset. */ /* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET; return PCI_ERS_RESULT_NEED_RESET;
} }
...@@ -2093,8 +2103,8 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, ...@@ -2093,8 +2103,8 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
*/ */
static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
{ {
struct Scsi_Host *host = pci_get_drvdata(pdev); struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
int bars = pci_select_bars(pdev, IORESOURCE_MEM); int bars = pci_select_bars(pdev, IORESOURCE_MEM);
...@@ -2108,9 +2118,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) ...@@ -2108,9 +2118,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
pci_set_master(pdev); pci_set_master(pdev);
/* Re-establishing Link */ /* Re-establishing Link */
spin_lock_irq(host->host_lock); spin_lock_irq(shost->host_lock);
phba->pport->fc_flag |= FC_ESTABLISH_LINK; phba->pport->fc_flag |= FC_ESTABLISH_LINK;
spin_unlock_irq(host->host_lock); spin_unlock_irq(shost->host_lock);
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE; psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
...@@ -2133,8 +2143,8 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) ...@@ -2133,8 +2143,8 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
*/ */
static void lpfc_io_resume(struct pci_dev *pdev) static void lpfc_io_resume(struct pci_dev *pdev)
{ {
struct Scsi_Host *host = pci_get_drvdata(pdev); struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
if (lpfc_online(phba) == 0) { if (lpfc_online(phba) == 0) {
mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
......
...@@ -560,7 +560,8 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb, ...@@ -560,7 +560,8 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
} }
void void
lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc, lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id,
struct lpfc_hbq_init *hbq_desc,
uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb) uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb)
{ {
int i; int i;
...@@ -568,6 +569,7 @@ lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc, ...@@ -568,6 +569,7 @@ lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc,
struct config_hbq_var *hbqmb = &mb->un.varCfgHbq; struct config_hbq_var *hbqmb = &mb->un.varCfgHbq;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
hbqmb->hbqId = id;
hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */ hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */
hbqmb->recvNotify = hbq_desc->rn; /* Receive hbqmb->recvNotify = hbq_desc->rn; /* Receive
* Notification */ * Notification */
...@@ -687,7 +689,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -687,7 +689,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */ mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count();
if (phba->max_vpi && phba->cfg_enable_npiv && if (phba->max_vpi && phba->cfg_enable_npiv &&
phba->vpd.sli3Feat.cmv) { phba->vpd.sli3Feat.cmv) {
mb->un.varCfgPort.max_vpi = phba->max_vpi; mb->un.varCfgPort.max_vpi = phba->max_vpi;
......
...@@ -231,21 +231,34 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) ...@@ -231,21 +231,34 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
return; return;
} }
void * struct hbq_dmabuf *
lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) lpfc_els_hbq_alloc(struct lpfc_hba *phba)
{ {
void *ret; struct hbq_dmabuf *hbqbp;
ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle);
return ret; hbqbp = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL);
if (!hbqbp)
return NULL;
hbqbp->dbuf.virt = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL,
&hbqbp->dbuf.phys);
if (!hbqbp->dbuf.virt) {
kfree(hbqbp);
return NULL;
}
hbqbp->size = LPFC_BPL_SIZE;
return hbqbp;
} }
void void
lpfc_hbq_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma) lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
{ {
pci_pool_free(phba->lpfc_hbq_pool, virt, dma); pci_pool_free(phba->lpfc_hbq_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys);
kfree(hbqbp);
return; return;
} }
/* This is ONLY called for the LPFC_ELS_HBQ */
void void
lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
{ {
...@@ -254,9 +267,8 @@ lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) ...@@ -254,9 +267,8 @@ lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf);
if (hbq_entry->tag == -1) { if (hbq_entry->tag == -1) {
lpfc_hbq_free(phba, hbq_entry->dbuf.virt, (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer)
hbq_entry->dbuf.phys); (phba, hbq_entry);
kfree(hbq_entry);
} else { } else {
lpfc_sli_free_hbq(phba, hbq_entry); lpfc_sli_free_hbq(phba, hbq_entry);
} }
......
...@@ -329,7 +329,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -329,7 +329,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
case NLP_STE_PRLI_ISSUE: case NLP_STE_PRLI_ISSUE:
case NLP_STE_UNMAPPED_NODE: case NLP_STE_UNMAPPED_NODE:
case NLP_STE_MAPPED_NODE: case NLP_STE_MAPPED_NODE:
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
return 1; return 1;
} }
...@@ -407,7 +407,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -407,7 +407,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp, mbox); ndlp, mbox);
return 1; return 1;
} }
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox);
return 1; return 1;
out: out:
...@@ -451,7 +451,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -451,7 +451,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
} else { } else {
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp,
NULL, 0); NULL);
} }
return 1; return 1;
} }
...@@ -488,9 +488,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -488,9 +488,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_flag |= NLP_LOGO_ACC; ndlp->nlp_flag |= NLP_LOGO_ACC;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
if (els_cmd == ELS_CMD_PRLO) if (els_cmd == ELS_CMD_PRLO)
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
else else
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
if (!(ndlp->nlp_type & NLP_FABRIC) || if (!(ndlp->nlp_type & NLP_FABRIC) ||
(ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
...@@ -564,6 +564,11 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -564,6 +564,11 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (!ndlp->nlp_rpi) {
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
return 0;
}
/* Check config parameter use-adisc or FCP-2 */ /* Check config parameter use-adisc or FCP-2 */
if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
...@@ -627,7 +632,7 @@ lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -627,7 +632,7 @@ lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_LOGO_ACC; ndlp->nlp_flag |= NLP_LOGO_ACC;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
return ndlp->nlp_state; return ndlp->nlp_state;
...@@ -723,7 +728,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -723,7 +728,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_els_abort(phba, ndlp); lpfc_els_abort(phba, ndlp);
if (evt == NLP_EVT_RCV_LOGO) { if (evt == NLP_EVT_RCV_LOGO) {
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
} else { } else {
lpfc_issue_els_logo(vport, ndlp, 0); lpfc_issue_els_logo(vport, ndlp, 0);
} }
...@@ -1167,7 +1172,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport, ...@@ -1167,7 +1172,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,
struct lpfc_iocbq *cmdiocb; struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg; cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
return ndlp->nlp_state; return ndlp->nlp_state;
} }
...@@ -1322,7 +1327,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1322,7 +1327,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
{ {
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
return ndlp->nlp_state; return ndlp->nlp_state;
} }
...@@ -1514,7 +1519,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1514,7 +1519,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
{ {
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
return ndlp->nlp_state; return ndlp->nlp_state;
} }
...@@ -1585,8 +1590,8 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1585,8 +1590,8 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
/* flush the target */ /* flush the target */
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); ndlp->nlp_sid, 0, LPFC_CTX_TGT);
/* Treat like rcv logo */ /* Treat like rcv logo */
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
...@@ -1719,7 +1724,7 @@ lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1719,7 +1724,7 @@ lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_flag |= NLP_LOGO_ACC; ndlp->nlp_flag |= NLP_LOGO_ACC;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) { if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
......
...@@ -152,7 +152,6 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) ...@@ -152,7 +152,6 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
} }
} }
lpfc_destroy_vport_work_array(vports); lpfc_destroy_vport_work_array(vports);
spin_unlock_irq(&phba->hbalock);
atomic_set(&phba->num_rsrc_err, 0); atomic_set(&phba->num_rsrc_err, 0);
atomic_set(&phba->num_cmd_success, 0); atomic_set(&phba->num_cmd_success, 0);
} }
...@@ -1195,14 +1194,12 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) ...@@ -1195,14 +1194,12 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
* Unfortunately, some targets do not abide by this forcing the driver * Unfortunately, some targets do not abide by this forcing the driver
* to double check. * to double check.
*/ */
cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, cmnd->device->lun,
cmnd->device->id, cmnd->device->lun,
LPFC_CTX_LUN); LPFC_CTX_LUN);
if (cnt) if (cnt)
lpfc_sli_abort_iocb(phba, lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
&phba->sli.ring[phba->sli.fcp_ring],
cmnd->device->id, cmnd->device->lun, cmnd->device->id, cmnd->device->lun,
0, LPFC_CTX_LUN); LPFC_CTX_LUN);
loopcnt = 0; loopcnt = 0;
while(cnt) { while(cnt) {
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
...@@ -1211,10 +1208,8 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) ...@@ -1211,10 +1208,8 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
> (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT) > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT)
break; break;
cnt = lpfc_sli_sum_iocb(phba, cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id,
&phba->sli.ring[phba->sli.fcp_ring], cmnd->device->lun, LPFC_CTX_LUN);
cmnd->device->id, cmnd->device->lun,
LPFC_CTX_LUN);
} }
if (cnt) { if (cnt) {
...@@ -1304,11 +1299,10 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) ...@@ -1304,11 +1299,10 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
* the targets. Unfortunately, some targets do not abide by * the targets. Unfortunately, some targets do not abide by
* this forcing the driver to double check. * this forcing the driver to double check.
*/ */
cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST);
0, 0, LPFC_CTX_HOST);
if (cnt) if (cnt)
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
0, 0, 0, LPFC_CTX_HOST); 0, 0, LPFC_CTX_HOST);
loopcnt = 0; loopcnt = 0;
while(cnt) { while(cnt) {
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
...@@ -1317,9 +1311,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) ...@@ -1317,9 +1311,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
> (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT) > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT)
break; break;
cnt = lpfc_sli_sum_iocb(phba, cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST);
&phba->sli.ring[phba->sli.fcp_ring],
0, 0, LPFC_CTX_HOST);
} }
if (cnt) { if (cnt) {
......
...@@ -545,7 +545,8 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) ...@@ -545,7 +545,8 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
return NULL; return NULL;
} }
return (struct lpfc_hbq_entry *) phba->hbqslimp.virt + hbqp->hbqPutIdx; return (struct lpfc_hbq_entry *) phba->hbqs[hbqno].hbq_virt +
hbqp->hbqPutIdx;
} }
void void
...@@ -553,18 +554,21 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) ...@@ -553,18 +554,21 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
{ {
struct lpfc_dmabuf *dmabuf, *next_dmabuf; struct lpfc_dmabuf *dmabuf, *next_dmabuf;
struct hbq_dmabuf *hbq_buf; struct hbq_dmabuf *hbq_buf;
int i, hbq_count;
hbq_count = lpfc_sli_hbq_count();
/* Return all memory used by all HBQs */ /* Return all memory used by all HBQs */
list_for_each_entry_safe(dmabuf, next_dmabuf, for (i = 0; i < hbq_count; ++i) {
&phba->hbq_buffer_list, list) { list_for_each_entry_safe(dmabuf, next_dmabuf,
hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf); &phba->hbqs[i].hbq_buffer_list, list) {
list_del(&hbq_buf->dbuf.list); hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf);
lpfc_hbq_free(phba, hbq_buf->dbuf.virt, hbq_buf->dbuf.phys); list_del(&hbq_buf->dbuf.list);
kfree(hbq_buf); (phba->hbqs[i].hbq_free_buffer)(phba, hbq_buf);
}
} }
} }
static void static struct lpfc_hbq_entry *
lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
struct hbq_dmabuf *hbq_buf) struct hbq_dmabuf *hbq_buf)
{ {
...@@ -578,7 +582,7 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, ...@@ -578,7 +582,7 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr)); hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
hbqe->bde.addrLow = le32_to_cpu(putPaddrLow(physaddr)); hbqe->bde.addrLow = le32_to_cpu(putPaddrLow(physaddr));
hbqe->bde.tus.f.bdeSize = FCELSSIZE; hbqe->bde.tus.f.bdeSize = hbq_buf->size;
hbqe->bde.tus.f.bdeFlags = 0; hbqe->bde.tus.f.bdeFlags = 0;
hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w); hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w);
hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag); hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag);
...@@ -587,8 +591,9 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, ...@@ -587,8 +591,9 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno); writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno);
/* flush */ /* flush */
readl(phba->hbq_put + hbqno); readl(phba->hbq_put + hbqno);
list_add_tail(&hbq_buf->dbuf.list, &phba->hbq_buffer_list); list_add_tail(&hbq_buf->dbuf.list, &hbqp->hbq_buffer_list);
} }
return hbqe;
} }
static struct lpfc_hbq_init lpfc_els_hbq = { static struct lpfc_hbq_init lpfc_els_hbq = {
...@@ -596,14 +601,26 @@ static struct lpfc_hbq_init lpfc_els_hbq = { ...@@ -596,14 +601,26 @@ static struct lpfc_hbq_init lpfc_els_hbq = {
.entry_count = 200, .entry_count = 200,
.mask_count = 0, .mask_count = 0,
.profile = 0, .profile = 0,
.ring_mask = 1 << LPFC_ELS_RING, .ring_mask = (1 << LPFC_ELS_RING),
.buffer_count = 0, .buffer_count = 0,
.init_count = 20, .init_count = 20,
.add_count = 5, .add_count = 5,
}; };
static struct lpfc_hbq_init lpfc_extra_hbq = {
.rn = 1,
.entry_count = 200,
.mask_count = 0,
.profile = 0,
.ring_mask = (1 << LPFC_EXTRA_RING),
.buffer_count = 0,
.init_count = 0,
.add_count = 5,
};
struct lpfc_hbq_init *lpfc_hbq_defs[] = { struct lpfc_hbq_init *lpfc_hbq_defs[] = {
&lpfc_els_hbq, &lpfc_els_hbq,
&lpfc_extra_hbq,
}; };
int int
...@@ -612,6 +629,10 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) ...@@ -612,6 +629,10 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
uint32_t i, start, end; uint32_t i, start, end;
struct hbq_dmabuf *hbq_buffer; struct hbq_dmabuf *hbq_buffer;
if (!phba->hbqs[hbqno].hbq_alloc_buffer) {
return 0;
}
start = lpfc_hbq_defs[hbqno]->buffer_count; start = lpfc_hbq_defs[hbqno]->buffer_count;
end = count + lpfc_hbq_defs[hbqno]->buffer_count; end = count + lpfc_hbq_defs[hbqno]->buffer_count;
if (end > lpfc_hbq_defs[hbqno]->entry_count) { if (end > lpfc_hbq_defs[hbqno]->entry_count) {
...@@ -620,17 +641,14 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) ...@@ -620,17 +641,14 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
/* Populate HBQ entries */ /* Populate HBQ entries */
for (i = start; i < end; i++) { for (i = start; i < end; i++) {
hbq_buffer = kmalloc(sizeof(struct hbq_dmabuf), hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
GFP_KERNEL);
if (!hbq_buffer) if (!hbq_buffer)
return 1; return 1;
hbq_buffer->dbuf.virt = lpfc_hbq_alloc(phba, MEM_PRI,
&hbq_buffer->dbuf.phys);
if (hbq_buffer->dbuf.virt == NULL)
return 1;
hbq_buffer->tag = (i | (hbqno << 16)); hbq_buffer->tag = (i | (hbqno << 16));
lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer); if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer))
lpfc_hbq_defs[hbqno]->buffer_count++; lpfc_hbq_defs[hbqno]->buffer_count++;
else
(phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
} }
return 0; return 0;
} }
...@@ -654,10 +672,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) ...@@ -654,10 +672,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
{ {
struct lpfc_dmabuf *d_buf; struct lpfc_dmabuf *d_buf;
struct hbq_dmabuf *hbq_buf; struct hbq_dmabuf *hbq_buf;
uint32_t hbqno;
hbqno = tag >> 16;
if (hbqno > LPFC_MAX_HBQS)
return NULL;
list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) { list_for_each_entry(d_buf, &phba->hbqs[hbqno].hbq_buffer_list, list) {
hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
if ((hbq_buf->tag & 0xffff) == tag) { if (hbq_buf->tag == tag) {
return hbq_buf; return hbq_buf;
} }
} }
...@@ -668,13 +691,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) ...@@ -668,13 +691,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
} }
void void
lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *sp) lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer)
{ {
uint32_t hbqno; uint32_t hbqno;
if (sp) { if (hbq_buffer) {
hbqno = sp->tag >> 16; hbqno = hbq_buffer->tag >> 16;
lpfc_sli_hbq_to_firmware(phba, hbqno, sp); if (!lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) {
(phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
}
} }
} }
...@@ -904,21 +929,26 @@ static struct lpfc_dmabuf * ...@@ -904,21 +929,26 @@ static struct lpfc_dmabuf *
lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
{ {
struct hbq_dmabuf *hbq_entry, *new_hbq_entry; struct hbq_dmabuf *hbq_entry, *new_hbq_entry;
uint32_t hbqno;
void *virt; /* virtual address ptr */
dma_addr_t phys; /* mapped address */
hbq_entry = lpfc_sli_hbqbuf_find(phba, tag); hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
if (hbq_entry == NULL) if (hbq_entry == NULL)
return NULL; return NULL;
list_del(&hbq_entry->dbuf.list); list_del(&hbq_entry->dbuf.list);
new_hbq_entry = kmalloc(sizeof(struct hbq_dmabuf), GFP_ATOMIC);
hbqno = tag >> 16;
new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
if (new_hbq_entry == NULL) if (new_hbq_entry == NULL)
return &hbq_entry->dbuf; return &hbq_entry->dbuf;
new_hbq_entry->dbuf = hbq_entry->dbuf;
new_hbq_entry->tag = -1; new_hbq_entry->tag = -1;
hbq_entry->dbuf.virt = lpfc_hbq_alloc(phba, 0, &hbq_entry->dbuf.phys); phys = new_hbq_entry->dbuf.phys;
if (hbq_entry->dbuf.virt == NULL) { virt = new_hbq_entry->dbuf.virt;
kfree(new_hbq_entry); new_hbq_entry->dbuf.phys = hbq_entry->dbuf.phys;
return &hbq_entry->dbuf; new_hbq_entry->dbuf.virt = hbq_entry->dbuf.virt;
} hbq_entry->dbuf.phys = phys;
hbq_entry->dbuf.virt = virt;
lpfc_sli_free_hbq(phba, hbq_entry); lpfc_sli_free_hbq(phba, hbq_entry);
return &new_hbq_entry->dbuf; return &new_hbq_entry->dbuf;
} }
...@@ -964,7 +994,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -964,7 +994,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
irsp->un.ulpWord[3]); irsp->un.ulpWord[3]);
if (irsp->ulpBdeCount == 2) if (irsp->ulpBdeCount == 2)
saveq->context3 = lpfc_sli_replace_hbqbuff(phba, saveq->context3 = lpfc_sli_replace_hbqbuff(phba,
irsp->un.ulpWord[15]); irsp->unsli3.sli3Words[7]);
} }
/* unSolicited Responses */ /* unSolicited Responses */
...@@ -2189,8 +2219,8 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba) ...@@ -2189,8 +2219,8 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
phba->hbqs[hbqno].local_hbqGetIdx = 0; phba->hbqs[hbqno].local_hbqGetIdx = 0;
phba->hbqs[hbqno].entry_count = phba->hbqs[hbqno].entry_count =
lpfc_hbq_defs[hbqno]->entry_count; lpfc_hbq_defs[hbqno]->entry_count;
lpfc_config_hbq(phba, lpfc_hbq_defs[hbqno], hbq_entry_index, lpfc_config_hbq(phba, hbqno, lpfc_hbq_defs[hbqno],
pmb); hbq_entry_index, pmb);
hbq_entry_index += phba->hbqs[hbqno].entry_count; hbq_entry_index += phba->hbqs[hbqno].entry_count;
if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
...@@ -3433,8 +3463,8 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3433,8 +3463,8 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
} }
static int static int
lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
uint64_t lun_id, uint32_t ctx, uint16_t tgt_id, uint64_t lun_id,
lpfc_ctx_cmd ctx_cmd) lpfc_ctx_cmd ctx_cmd)
{ {
struct lpfc_scsi_buf *lpfc_cmd; struct lpfc_scsi_buf *lpfc_cmd;
...@@ -3444,6 +3474,9 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, ...@@ -3444,6 +3474,9 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
if (!(iocbq->iocb_flag & LPFC_IO_FCP)) if (!(iocbq->iocb_flag & LPFC_IO_FCP))
return rc; return rc;
if (iocbq->vport != vport)
return rc;
lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
cmnd = lpfc_cmd->pCmd; cmnd = lpfc_cmd->pCmd;
...@@ -3460,10 +3493,6 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, ...@@ -3460,10 +3493,6 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
if (cmnd->device->id == tgt_id) if (cmnd->device->id == tgt_id)
rc = 0; rc = 0;
break; break;
case LPFC_CTX_CTX:
if (iocbq->iocb.ulpContext == ctx)
rc = 0;
break;
case LPFC_CTX_HOST: case LPFC_CTX_HOST:
rc = 0; rc = 0;
break; break;
...@@ -3477,17 +3506,18 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, ...@@ -3477,17 +3506,18 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
} }
int int
lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) lpfc_ctx_cmd ctx_cmd)
{ {
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *iocbq; struct lpfc_iocbq *iocbq;
int sum, i; int sum, i;
for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) {
iocbq = phba->sli.iocbq_lookup[i]; iocbq = phba->sli.iocbq_lookup[i];
if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id, if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id,
0, ctx_cmd) == 0) ctx_cmd) == 0)
sum++; sum++;
} }
...@@ -3503,10 +3533,10 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -3503,10 +3533,10 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
} }
int int
lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
uint16_t tgt_id, uint64_t lun_id, uint32_t ctx, uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd abort_cmd)
lpfc_ctx_cmd abort_cmd)
{ {
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *iocbq; struct lpfc_iocbq *iocbq;
struct lpfc_iocbq *abtsiocb; struct lpfc_iocbq *abtsiocb;
IOCB_t *cmd = NULL; IOCB_t *cmd = NULL;
...@@ -3516,7 +3546,7 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3516,7 +3546,7 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
for (i = 1; i <= phba->sli.last_iotag; i++) { for (i = 1; i <= phba->sli.last_iotag; i++) {
iocbq = phba->sli.iocbq_lookup[i]; iocbq = phba->sli.iocbq_lookup[i];
if (lpfc_sli_validate_fcp_iocb(iocbq, tgt_id, lun_id, 0, if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id,
abort_cmd) != 0) abort_cmd) != 0)
continue; continue;
......
...@@ -26,7 +26,6 @@ struct lpfc_vport; ...@@ -26,7 +26,6 @@ struct lpfc_vport;
typedef enum _lpfc_ctx_cmd { typedef enum _lpfc_ctx_cmd {
LPFC_CTX_LUN, LPFC_CTX_LUN,
LPFC_CTX_TGT, LPFC_CTX_TGT,
LPFC_CTX_CTX,
LPFC_CTX_HOST LPFC_CTX_HOST
} lpfc_ctx_cmd; } lpfc_ctx_cmd;
...@@ -54,9 +53,10 @@ struct lpfc_iocbq { ...@@ -54,9 +53,10 @@ struct lpfc_iocbq {
void *context2; /* caller context information */ void *context2; /* caller context information */
void *context3; /* caller context information */ void *context3; /* caller context information */
union { union {
wait_queue_head_t *wait_queue; wait_queue_head_t *wait_queue;
struct lpfc_iocbq *rsp_iocb; struct lpfc_iocbq *rsp_iocb;
struct lpfcMboxq *mbox; struct lpfcMboxq *mbox;
struct lpfc_nodelist *ndlp;
} context_un; } context_un;
void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
......
...@@ -432,8 +432,29 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -432,8 +432,29 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
long timeout; long timeout;
int rc = VPORT_ERROR;
if (vport->port_type == LPFC_PHYSICAL_PORT) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
"1812 vport_delete failed: Cannot delete "
"physical host\n");
return VPORT_ERROR;
}
/*
* If we are not unloading the driver then prevent the vport_delete
* from happening until after this vport's discovery is finished.
*/
if (!(phba->pport->load_flag & FC_UNLOADING)) {
int check_count = 0;
while (check_count < ((phba->fc_ratov * 3) + 3) &&
vport->port_state > LPFC_VPORT_FAILED &&
vport->port_state < LPFC_VPORT_READY) {
check_count++;
msleep(1000);
}
if (vport->port_state > LPFC_VPORT_FAILED &&
vport->port_state < LPFC_VPORT_READY)
return -EAGAIN;
}
/* /*
* This is a bit of a mess. We want to ensure the shost doesn't get * This is a bit of a mess. We want to ensure the shost doesn't get
* torn down until we're done with the embedded lpfc_vport structure. * torn down until we're done with the embedded lpfc_vport structure.
...@@ -451,16 +472,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -451,16 +472,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
*/ */
if (!scsi_host_get(shost) || !scsi_host_get(shost)) if (!scsi_host_get(shost) || !scsi_host_get(shost))
return VPORT_INVAL; return VPORT_INVAL;
spin_lock_irq(&phba->hbalock);
if (vport->port_type == LPFC_PHYSICAL_PORT) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
"1812 vport_delete failed: Cannot delete "
"physical host\n");
goto out;
}
vport->load_flag |= FC_UNLOADING; vport->load_flag |= FC_UNLOADING;
spin_unlock_irq(&phba->hbalock);
kfree(vport->vname); kfree(vport->vname);
lpfc_debugfs_terminate(vport); lpfc_debugfs_terminate(vport);
fc_remove_host(lpfc_shost_from_vport(vport)); fc_remove_host(lpfc_shost_from_vport(vport));
...@@ -514,10 +528,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -514,10 +528,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
"1828 Vport Deleted.\n"); "1828 Vport Deleted.\n");
rc = VPORT_OK;
out:
scsi_host_put(shost); scsi_host_put(shost);
return rc; return VPORT_OK;
} }
EXPORT_SYMBOL(lpfc_vport_create); EXPORT_SYMBOL(lpfc_vport_create);
...@@ -536,7 +548,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) ...@@ -536,7 +548,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba)
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
list_for_each_entry(port_iterator, &phba->port_list, listentry) { list_for_each_entry(port_iterator, &phba->port_list, listentry) {
if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) { if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) {
lpfc_printf_vlog(port_iterator, KERN_ERR, LOG_VPORT, lpfc_printf_vlog(port_iterator, KERN_WARNING, LOG_VPORT,
"1801 Create vport work array FAILED: " "1801 Create vport work array FAILED: "
"cannot do scsi_host_get\n"); "cannot do scsi_host_get\n");
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment