Commit a257bf90 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.1: misc fixes/changes

8.3.1 Fixes/Changes :

- Fix incorrect byte-swapping on word 4 of IOCB (data length) which
  caused LUNs to not be discovered on big-endian (e.g. PPC)

- Remove a bad cast of MBslimaddr which loses the __iomem (sparse)

- Make lpfc_debugfs_mask_disc_trc static (sparse)

- Correct misspelled word BlockGuard in lpfc_logmsg.h comment

- Replaced repeated code segment for canceling IOCBs from a list with
  a function call, lpfc_sli_cancel_iocbs().

- Increased HBQ buffers to support 40KB SSC sequences.

- Added sysfs interface to update speed and topology parameter without
  link bounce.

- Fixed bug with sysfs fc_host WWNs not being updated after changing
  the WWNs.

- Check if the active mailbox is NULL in the beginning of the mailbox
  timeout handler - fixes panic in the mailbox timeout handler while
  running IO stress test

- Fixed system panic in lpfc_pci_remove_one() due to ndlp indirect
  reference to phba through vport

- Removed de-reference of scsi device after call to scsi_done() to fix
  panic in scsi completion path while accessing scsi device after
  scsi_done is called.

- Fixed "Nodelist not empty" message when unloading the driver after
  target reboot test

- Added LP2105 HBA model description

- Added code to print all 16 words of unrecognized ASYNC events

- Fixed memory leak in vport create + delete loop

- Added support for handling dual error bit from HBA

- Fixed a driver NULL pointer dereference in lpfc_sli_process_sol_iocb

- Fixed a discovery bug with FC switch reboot in lpfc_setup_disc_node

- Take NULL termintator into account when calculating available buffer space
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 3621a710
...@@ -443,6 +443,7 @@ struct lpfc_hba { ...@@ -443,6 +443,7 @@ struct lpfc_hba {
uint32_t hba_flag; /* hba generic flags */ uint32_t hba_flag; /* hba generic flags */
#define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */ #define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */
#define DEFER_ERATT 0x4 /* Deferred error attention in progress */
struct lpfc_dmabuf slim2p; struct lpfc_dmabuf slim2p;
MAILBOX_t *mbox; MAILBOX_t *mbox;
...@@ -723,4 +724,3 @@ lpfc_sli_read_hs(struct lpfc_hba *phba) ...@@ -723,4 +724,3 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
return; return;
} }
...@@ -2216,18 +2216,41 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1, ...@@ -2216,18 +2216,41 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1,
* non-zero return value from lpfc_issue_lip() * non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range * -EINVAL val out of range
**/ **/
static int static ssize_t
lpfc_topology_set(struct lpfc_hba *phba, int val) lpfc_topology_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{ {
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
int val = 0;
int nolip = 0;
const char *val_buf = buf;
int err; int err;
uint32_t prev_val; uint32_t prev_val;
if (!strncmp(buf, "nolip ", strlen("nolip "))) {
nolip = 1;
val_buf = &buf[strlen("nolip ")];
}
if (!isdigit(val_buf[0]))
return -EINVAL;
if (sscanf(val_buf, "%i", &val) != 1)
return -EINVAL;
if (val >= 0 && val <= 6) { if (val >= 0 && val <= 6) {
prev_val = phba->cfg_topology; prev_val = phba->cfg_topology;
phba->cfg_topology = val; phba->cfg_topology = val;
if (nolip)
return strlen(buf);
err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
if (err) if (err) {
phba->cfg_topology = prev_val; phba->cfg_topology = prev_val;
return err; return -EINVAL;
} else
return strlen(buf);
} }
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"%d:0467 lpfc_topology attribute cannot be set to %d, " "%d:0467 lpfc_topology attribute cannot be set to %d, "
...@@ -2240,7 +2263,6 @@ module_param(lpfc_topology, int, 0); ...@@ -2240,7 +2263,6 @@ module_param(lpfc_topology, int, 0);
MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology"); MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");
lpfc_param_show(topology) lpfc_param_show(topology)
lpfc_param_init(topology, 0, 0, 6) lpfc_param_init(topology, 0, 0, 6)
lpfc_param_store(topology)
static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR, static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
lpfc_topology_show, lpfc_topology_store); lpfc_topology_show, lpfc_topology_store);
...@@ -2281,7 +2303,7 @@ lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr, ...@@ -2281,7 +2303,7 @@ lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr,
unsigned long base, step, bucket_type; unsigned long base, step, bucket_type;
if (!strncmp(buf, "setbucket", strlen("setbucket"))) { if (!strncmp(buf, "setbucket", strlen("setbucket"))) {
if (strlen(buf) > LPFC_MAX_DATA_CTRL_LEN) if (strlen(buf) > (LPFC_MAX_DATA_CTRL_LEN - 1))
return -EINVAL; return -EINVAL;
strcpy(bucket_data, buf); strcpy(bucket_data, buf);
...@@ -2598,12 +2620,29 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = { ...@@ -2598,12 +2620,29 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = {
* non-zero return value from lpfc_issue_lip() * non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range * -EINVAL val out of range
**/ **/
static int static ssize_t
lpfc_link_speed_set(struct lpfc_hba *phba, int val) lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{ {
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
int val = 0;
int nolip = 0;
const char *val_buf = buf;
int err; int err;
uint32_t prev_val; uint32_t prev_val;
if (!strncmp(buf, "nolip ", strlen("nolip "))) {
nolip = 1;
val_buf = &buf[strlen("nolip ")];
}
if (!isdigit(val_buf[0]))
return -EINVAL;
if (sscanf(val_buf, "%i", &val) != 1)
return -EINVAL;
if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) || if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) || ((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) || ((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
...@@ -2611,14 +2650,19 @@ lpfc_link_speed_set(struct lpfc_hba *phba, int val) ...@@ -2611,14 +2650,19 @@ lpfc_link_speed_set(struct lpfc_hba *phba, int val)
((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb))) ((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)))
return -EINVAL; return -EINVAL;
if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED) if ((val >= 0 && val <= 8)
&& (LPFC_LINK_SPEED_BITMAP & (1 << val))) { && (LPFC_LINK_SPEED_BITMAP & (1 << val))) {
prev_val = phba->cfg_link_speed; prev_val = phba->cfg_link_speed;
phba->cfg_link_speed = val; phba->cfg_link_speed = val;
if (nolip)
return strlen(buf);
err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
if (err) if (err) {
phba->cfg_link_speed = prev_val; phba->cfg_link_speed = prev_val;
return err; return -EINVAL;
} else
return strlen(buf);
} }
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
...@@ -2665,7 +2709,6 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val) ...@@ -2665,7 +2709,6 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val)
return -EINVAL; return -EINVAL;
} }
lpfc_param_store(link_speed)
static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR, static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
lpfc_link_speed_show, lpfc_link_speed_store); lpfc_link_speed_show, lpfc_link_speed_store);
......
...@@ -184,6 +184,8 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *); ...@@ -184,6 +184,8 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *); struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *); void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *); uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
uint32_t);
void lpfc_reset_barrier(struct lpfc_hba * phba); void lpfc_reset_barrier(struct lpfc_hba * phba);
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
......
...@@ -95,7 +95,7 @@ module_param(lpfc_debugfs_max_slow_ring_trc, int, 0); ...@@ -95,7 +95,7 @@ module_param(lpfc_debugfs_max_slow_ring_trc, int, 0);
MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc, MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
"Set debugfs slow ring trace depth"); "Set debugfs slow ring trace depth");
int lpfc_debugfs_mask_disc_trc; static int lpfc_debugfs_mask_disc_trc;
module_param(lpfc_debugfs_mask_disc_trc, int, 0); module_param(lpfc_debugfs_mask_disc_trc, int, 0);
MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
"Set debugfs discovery trace mask"); "Set debugfs discovery trace mask");
...@@ -399,8 +399,7 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) ...@@ -399,8 +399,7 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
len += snprintf(buf+len, size-len, "HBA SLIM\n"); len += snprintf(buf+len, size-len, "HBA SLIM\n");
lpfc_memcpy_from_slim(buffer, lpfc_memcpy_from_slim(buffer,
((uint8_t *)phba->MBslimaddr) + lpfc_debugfs_last_hba_slim_off, phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024);
1024);
ptr = (uint32_t *)&buffer[0]; ptr = (uint32_t *)&buffer[0];
off = lpfc_debugfs_last_hba_slim_off; off = lpfc_debugfs_last_hba_slim_off;
......
...@@ -99,6 +99,7 @@ struct lpfc_nodelist { ...@@ -99,6 +99,7 @@ struct lpfc_nodelist {
#define NLP_USG_FREE_ACK_BIT 0x8 /* Indicate ndlp memory free invoked */ #define NLP_USG_FREE_ACK_BIT 0x8 /* Indicate ndlp memory free invoked */
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */ struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
struct lpfc_hba *phba;
struct fc_rport *rport; /* Corresponding FC transport struct fc_rport *rport; /* Corresponding FC transport
port structure */ port structure */
struct lpfc_vport *vport; struct lpfc_vport *vport;
......
...@@ -5058,19 +5058,9 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) ...@@ -5058,19 +5058,9 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
} }
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) { /* Cancell all the IOCBs from the completions list */
piocb = list_get_first(&completions, struct lpfc_iocbq, list); lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
cmd = &piocb->iocb; IOERR_SLI_ABORTED);
list_del_init(&piocb->list);
if (!piocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, piocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(piocb->iocb_cmpl) (phba, piocb, piocb);
}
}
return; return;
} }
...@@ -5121,18 +5111,11 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba) ...@@ -5121,18 +5111,11 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
lpfc_sli_issue_abort_iotag(phba, pring, piocb); lpfc_sli_issue_abort_iotag(phba, pring, piocb);
} }
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) {
piocb = list_get_first(&completions, struct lpfc_iocbq, list); /* Cancel all the IOCBs from the completions list */
cmd = &piocb->iocb; lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
list_del_init(&piocb->list); IOERR_SLI_ABORTED);
if (!piocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, piocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(piocb->iocb_cmpl) (phba, piocb, piocb);
}
}
return; return;
} }
...@@ -6468,7 +6451,6 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport) ...@@ -6468,7 +6451,6 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
LIST_HEAD(completions); LIST_HEAD(completions);
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *tmp_iocb, *piocb; struct lpfc_iocbq *tmp_iocb, *piocb;
IOCB_t *cmd;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list, list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
...@@ -6481,15 +6463,9 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport) ...@@ -6481,15 +6463,9 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
} }
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) { /* Cancel all the IOCBs from the completions list */
piocb = list_get_first(&completions, struct lpfc_iocbq, list); lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
list_del_init(&piocb->list); IOERR_SLI_ABORTED);
cmd = &piocb->iocb;
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(piocb->iocb_cmpl) (phba, piocb, piocb);
}
} }
/** /**
...@@ -6506,10 +6482,9 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport) ...@@ -6506,10 +6482,9 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp) void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
{ {
LIST_HEAD(completions); LIST_HEAD(completions);
struct lpfc_hba *phba = ndlp->vport->phba; struct lpfc_hba *phba = ndlp->phba;
struct lpfc_iocbq *tmp_iocb, *piocb; struct lpfc_iocbq *tmp_iocb, *piocb;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
IOCB_t *cmd;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list, list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
...@@ -6521,15 +6496,9 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp) ...@@ -6521,15 +6496,9 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
} }
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) { /* Cancel all the IOCBs from the completions list */
piocb = list_get_first(&completions, struct lpfc_iocbq, list); lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
list_del_init(&piocb->list); IOERR_SLI_ABORTED);
cmd = &piocb->iocb;
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(piocb->iocb_cmpl) (phba, piocb, piocb);
}
} }
/** /**
...@@ -6546,20 +6515,12 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp) ...@@ -6546,20 +6515,12 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
void lpfc_fabric_abort_hba(struct lpfc_hba *phba) void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
{ {
LIST_HEAD(completions); LIST_HEAD(completions);
struct lpfc_iocbq *piocb;
IOCB_t *cmd;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
list_splice_init(&phba->fabric_iocb_list, &completions); list_splice_init(&phba->fabric_iocb_list, &completions);
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) { /* Cancel all the IOCBs from the completions list */
piocb = list_get_first(&completions, struct lpfc_iocbq, list); lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
list_del_init(&piocb->list); IOERR_SLI_ABORTED);
cmd = &piocb->iocb;
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(piocb->iocb_cmpl) (phba, piocb, piocb);
}
} }
...@@ -78,7 +78,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport) ...@@ -78,7 +78,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
return; return;
} }
phba = ndlp->vport->phba; phba = ndlp->phba;
lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT, lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
"rport terminate: sid:x%x did:x%x flg:x%x", "rport terminate: sid:x%x did:x%x flg:x%x",
...@@ -1862,9 +1862,14 @@ lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -1862,9 +1862,14 @@ lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* @vport: Pointer to Virtual Port object. * @vport: Pointer to Virtual Port object.
* @ndlp: Pointer to FC node object. * @ndlp: Pointer to FC node object.
* @did: FC_ID of the node. * @did: FC_ID of the node.
* This function is always called when node object need to *
* be initialized. It initializes all the fields of the node * This function is always called when node object need to be initialized.
* object. * It initializes all the fields of the node object. Although the reference
* to phba from @ndlp can be obtained indirectly through it's reference to
* @vport, a direct reference to phba is taken here by @ndlp. This is due
* to the life-span of the @ndlp might go beyond the existence of @vport as
* the final release of ndlp is determined by its reference count. And, the
* operation on @ndlp needs the reference to phba.
**/ **/
static inline void static inline void
lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
...@@ -1877,6 +1882,7 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1877,6 +1882,7 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_delayfunc.data = (unsigned long)ndlp; ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
ndlp->nlp_DID = did; ndlp->nlp_DID = did;
ndlp->vport = vport; ndlp->vport = vport;
ndlp->phba = vport->phba;
ndlp->nlp_sid = NLP_NO_SID; ndlp->nlp_sid = NLP_NO_SID;
kref_init(&ndlp->kref); kref_init(&ndlp->kref);
NLP_INT_NODE_ACT(ndlp); NLP_INT_NODE_ACT(ndlp);
...@@ -2086,7 +2092,6 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) ...@@ -2086,7 +2092,6 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
struct lpfc_sli *psli; struct lpfc_sli *psli;
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
struct lpfc_iocbq *iocb, *next_iocb; struct lpfc_iocbq *iocb, *next_iocb;
IOCB_t *icmd;
uint32_t rpi, i; uint32_t rpi, i;
lpfc_fabric_abort_nport(ndlp); lpfc_fabric_abort_nport(ndlp);
...@@ -2122,19 +2127,9 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) ...@@ -2122,19 +2127,9 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
} }
} }
while (!list_empty(&completions)) { /* Cancel all the IOCBs from the completions list */
iocb = list_get_first(&completions, struct lpfc_iocbq, list); lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
list_del_init(&iocb->list); IOERR_SLI_ABORTED);
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
icmd = &iocb->iocb;
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl)(phba, iocb, iocb);
}
}
return 0; return 0;
} }
...@@ -2186,9 +2181,13 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) ...@@ -2186,9 +2181,13 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport)
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->context1 = NULL; mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
if (rc == MBX_NOT_FINISHED) { if (rc != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool); mempool_free(mbox, phba->mbox_mem_pool);
}
if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED))
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
"1836 Could not issue "
"unreg_login(all_rpis) status %d\n", rc);
} }
} }
...@@ -2206,12 +2205,14 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) ...@@ -2206,12 +2205,14 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport)
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->context1 = NULL; mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
if (rc == MBX_NOT_FINISHED) { if (rc != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED))
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
"1815 Could not issue " "1815 Could not issue "
"unreg_did (default rpis)\n"); "unreg_did (default rpis) status %d\n",
mempool_free(mbox, phba->mbox_mem_pool); rc);
}
} }
} }
...@@ -2470,14 +2471,13 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) ...@@ -2470,14 +2471,13 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
if (ndlp->nlp_flag & NLP_RCV_PLOGI) if (ndlp->nlp_flag & NLP_RCV_PLOGI)
return NULL; return NULL;
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
/* Since this node is marked for discovery, /* Since this node is marked for discovery,
* delay timeout is not needed. * delay timeout is not needed.
*/ */
lpfc_cancel_retry_delay_tmo(vport, ndlp); lpfc_cancel_retry_delay_tmo(vport, ndlp);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
} else } else
ndlp = NULL; ndlp = NULL;
} else { } else {
...@@ -2740,19 +2740,9 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) ...@@ -2740,19 +2740,9 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
} }
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) { /* Cancel all the IOCBs from the completions list */
iocb = list_get_first(&completions, struct lpfc_iocbq, list); lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
list_del_init(&iocb->list); IOERR_SLI_ABORTED);
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
icmd = &iocb->iocb;
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl) (phba, iocb, iocb);
}
}
} }
static void static void
...@@ -3173,7 +3163,7 @@ lpfc_nlp_release(struct kref *kref) ...@@ -3173,7 +3163,7 @@ lpfc_nlp_release(struct kref *kref)
lpfc_nlp_remove(ndlp->vport, ndlp); lpfc_nlp_remove(ndlp->vport, ndlp);
/* clear the ndlp active flag for all release cases */ /* clear the ndlp active flag for all release cases */
phba = ndlp->vport->phba; phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags); spin_lock_irqsave(&phba->ndlp_lock, flags);
NLP_CLR_NODE_ACT(ndlp); NLP_CLR_NODE_ACT(ndlp);
spin_unlock_irqrestore(&phba->ndlp_lock, flags); spin_unlock_irqrestore(&phba->ndlp_lock, flags);
...@@ -3181,7 +3171,7 @@ lpfc_nlp_release(struct kref *kref) ...@@ -3181,7 +3171,7 @@ lpfc_nlp_release(struct kref *kref)
/* free ndlp memory for final ndlp release */ /* free ndlp memory for final ndlp release */
if (NLP_CHK_FREE_REQ(ndlp)) { if (NLP_CHK_FREE_REQ(ndlp)) {
kfree(ndlp->lat_data); kfree(ndlp->lat_data);
mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); mempool_free(ndlp, ndlp->phba->nlp_mem_pool);
} }
} }
...@@ -3204,7 +3194,7 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp) ...@@ -3204,7 +3194,7 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp)
* ndlp reference count that is in the process of being * ndlp reference count that is in the process of being
* released. * released.
*/ */
phba = ndlp->vport->phba; phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags); spin_lock_irqsave(&phba->ndlp_lock, flags);
if (!NLP_CHK_NODE_ACT(ndlp) || NLP_CHK_FREE_ACK(ndlp)) { if (!NLP_CHK_NODE_ACT(ndlp) || NLP_CHK_FREE_ACK(ndlp)) {
spin_unlock_irqrestore(&phba->ndlp_lock, flags); spin_unlock_irqrestore(&phba->ndlp_lock, flags);
...@@ -3240,7 +3230,7 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp) ...@@ -3240,7 +3230,7 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp)
"node put: did:x%x flg:x%x refcnt:x%x", "node put: did:x%x flg:x%x refcnt:x%x",
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_DID, ndlp->nlp_flag,
atomic_read(&ndlp->kref.refcount)); atomic_read(&ndlp->kref.refcount));
phba = ndlp->vport->phba; phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags); spin_lock_irqsave(&phba->ndlp_lock, flags);
/* Check the ndlp memory free acknowledge flag to avoid the /* Check the ndlp memory free acknowledge flag to avoid the
* possible race condition that kref_put got invoked again * possible race condition that kref_put got invoked again
......
...@@ -302,6 +302,7 @@ int ...@@ -302,6 +302,7 @@ int
lpfc_config_port_post(struct lpfc_hba *phba) lpfc_config_port_post(struct lpfc_hba *phba)
{ {
struct lpfc_vport *vport = phba->pport; struct lpfc_vport *vport = phba->pport;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
LPFC_MBOXQ_t *pmb; LPFC_MBOXQ_t *pmb;
MAILBOX_t *mb; MAILBOX_t *mb;
struct lpfc_dmabuf *mp; struct lpfc_dmabuf *mp;
...@@ -359,6 +360,11 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -359,6 +360,11 @@ lpfc_config_port_post(struct lpfc_hba *phba)
sizeof (struct lpfc_name)); sizeof (struct lpfc_name));
memcpy(&vport->fc_portname, &vport->fc_sparam.portName, memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
sizeof (struct lpfc_name)); sizeof (struct lpfc_name));
/* Update the fc_host data structures with new wwn. */
fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
/* If no serial number in VPD data, use low 6 bytes of WWNN */ /* If no serial number in VPD data, use low 6 bytes of WWNN */
/* This should be consolidated into parse_vpd ? - mr */ /* This should be consolidated into parse_vpd ? - mr */
if (phba->SerialNumber[0] == 0) { if (phba->SerialNumber[0] == 0) {
...@@ -598,8 +604,6 @@ lpfc_hba_down_post(struct lpfc_hba *phba) ...@@ -598,8 +604,6 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *mp, *next_mp; struct lpfc_dmabuf *mp, *next_mp;
struct lpfc_iocbq *iocb;
IOCB_t *cmd = NULL;
LIST_HEAD(completions); LIST_HEAD(completions);
int i; int i;
...@@ -627,20 +631,9 @@ lpfc_hba_down_post(struct lpfc_hba *phba) ...@@ -627,20 +631,9 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
pring->txcmplq_cnt = 0; pring->txcmplq_cnt = 0;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) { /* Cancel all the IOCBs from the completions list */
iocb = list_get_first(&completions, struct lpfc_iocbq, lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
list); IOERR_SLI_ABORTED);
cmd = &iocb->iocb;
list_del_init(&iocb->list);
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl) (phba, iocb, iocb);
}
}
lpfc_sli_abort_iocb_ring(phba, pring); lpfc_sli_abort_iocb_ring(phba, pring);
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
...@@ -855,6 +848,72 @@ lpfc_offline_eratt(struct lpfc_hba *phba) ...@@ -855,6 +848,72 @@ lpfc_offline_eratt(struct lpfc_hba *phba)
return; return;
} }
/**
* lpfc_handle_deferred_eratt - The HBA hardware deferred error handler
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to handle the deferred HBA hardware error
* conditions. This type of error is indicated by HBA by setting ER1
* and another ER bit in the host status register. The driver will
* wait until the ER1 bit clears before handling the error condition.
**/
static void
lpfc_handle_deferred_eratt(struct lpfc_hba *phba)
{
uint32_t old_host_status = phba->work_hs;
struct lpfc_sli_ring *pring;
struct lpfc_sli *psli = &phba->sli;
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0479 Deferred Adapter Hardware Error "
"Data: x%x x%x x%x\n",
phba->work_hs,
phba->work_status[0], phba->work_status[1]);
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock);
/*
* Firmware stops when it triggred erratt. That could cause the I/Os
* dropped by the firmware. Error iocb (I/O) on txcmplq and let the
* SCSI layer retry it after re-establishing link.
*/
pring = &psli->ring[psli->fcp_ring];
lpfc_sli_abort_iocb_ring(phba, pring);
/*
* There was a firmware error. Take the hba offline and then
* attempt to restart it.
*/
lpfc_offline_prep(phba);
lpfc_offline(phba);
/* Wait for the ER1 bit to clear.*/
while (phba->work_hs & HS_FFER1) {
msleep(100);
phba->work_hs = readl(phba->HSregaddr);
/* If driver is unloading let the worker thread continue */
if (phba->pport->load_flag & FC_UNLOADING) {
phba->work_hs = 0;
break;
}
}
/*
* This is to ptrotect against a race condition in which
* first write to the host attention register clear the
* host status register.
*/
if ((!phba->work_hs) && (!(phba->pport->load_flag & FC_UNLOADING)))
phba->work_hs = old_host_status & ~HS_FFER1;
phba->hba_flag &= ~DEFER_ERATT;
phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
phba->work_status[1] = readl(phba->MBslimaddr + 0xac);
}
/** /**
* lpfc_handle_eratt - The HBA hardware error handler * lpfc_handle_eratt - The HBA hardware error handler
* @phba: pointer to lpfc hba data structure. * @phba: pointer to lpfc hba data structure.
...@@ -894,6 +953,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba) ...@@ -894,6 +953,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
(char *) &board_event, (char *) &board_event,
LPFC_NL_VENDOR_ID); LPFC_NL_VENDOR_ID);
if (phba->hba_flag & DEFER_ERATT)
lpfc_handle_deferred_eratt(phba);
if (phba->work_hs & HS_FFER6) { if (phba->work_hs & HS_FFER6) {
/* Re-establishing Link */ /* Re-establishing Link */
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
...@@ -1321,7 +1383,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) ...@@ -1321,7 +1383,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
m = (typeof(m)){"LPe11000", max_speed, "PCIe"}; m = (typeof(m)){"LPe11000", max_speed, "PCIe"};
break; break;
case PCI_DEVICE_ID_ZEPHYR_DCSP: case PCI_DEVICE_ID_ZEPHYR_DCSP:
m = (typeof(m)){"LPe11002-SP", max_speed, "PCIe"}; m = (typeof(m)){"LP2105", max_speed, "PCIe"};
GE = 1;
break; break;
case PCI_DEVICE_ID_ZMID: case PCI_DEVICE_ID_ZMID:
m = (typeof(m)){"LPe1150", max_speed, "PCIe"}; m = (typeof(m)){"LPe1150", max_speed, "PCIe"};
...@@ -3032,8 +3095,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -3032,8 +3095,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
lpfc_free_sysfs_attr(vport); lpfc_free_sysfs_attr(vport);
kthread_stop(phba->worker_thread);
/* Release all the vports against this physical port */ /* Release all the vports against this physical port */
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) if (vports != NULL)
...@@ -3051,7 +3112,12 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -3051,7 +3112,12 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
* clears the rings, discards all mailbox commands, and resets * clears the rings, discards all mailbox commands, and resets
* the HBA. * the HBA.
*/ */
/* HBA interrupt will be diabled after this call */
lpfc_sli_hba_down(phba); lpfc_sli_hba_down(phba);
/* Stop kthread signal shall trigger work_done one more time */
kthread_stop(phba->worker_thread);
/* Final cleanup of txcmplq and reset the HBA */
lpfc_sli_brdrestart(phba); lpfc_sli_brdrestart(phba);
lpfc_stop_phba_timers(phba); lpfc_stop_phba_timers(phba);
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define LOG_FCP 0x40 /* FCP traffic history */ #define LOG_FCP 0x40 /* FCP traffic history */
#define LOG_NODE 0x80 /* Node table events */ #define LOG_NODE 0x80 /* Node table events */
#define LOG_TEMP 0x100 /* Temperature sensor events */ #define LOG_TEMP 0x100 /* Temperature sensor events */
#define LOG_BG 0x200 /* BlockBuard events */ #define LOG_BG 0x200 /* BlockGuard events */
#define LOG_MISC 0x400 /* Miscellaneous events */ #define LOG_MISC 0x400 /* Miscellaneous events */
#define LOG_SLI 0x800 /* SLI events */ #define LOG_SLI 0x800 /* SLI events */
#define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */ #define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */
......
...@@ -192,7 +192,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) ...@@ -192,7 +192,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
struct lpfc_iocbq *iocb, *next_iocb; struct lpfc_iocbq *iocb, *next_iocb;
IOCB_t *cmd;
/* Abort outstanding I/O on NPort <nlp_DID> */ /* Abort outstanding I/O on NPort <nlp_DID> */
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY, lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,
...@@ -223,19 +222,10 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) ...@@ -223,19 +222,10 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
} }
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
while (!list_empty(&completions)) { /* Cancel all the IOCBs from the completions list */
iocb = list_get_first(&completions, struct lpfc_iocbq, list); lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
cmd = &iocb->iocb; IOERR_SLI_ABORTED);
list_del_init(&iocb->list);
if (!iocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, iocb);
else {
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
(iocb->iocb_cmpl) (phba, iocb, iocb);
}
}
lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
return 0; return 0;
} }
......
...@@ -272,14 +272,14 @@ lpfc_rampdown_queue_depth(struct lpfc_hba *phba) ...@@ -272,14 +272,14 @@ lpfc_rampdown_queue_depth(struct lpfc_hba *phba)
**/ **/
static inline void static inline void
lpfc_rampup_queue_depth(struct lpfc_vport *vport, lpfc_rampup_queue_depth(struct lpfc_vport *vport,
struct scsi_device *sdev) uint32_t queue_depth)
{ {
unsigned long flags; unsigned long flags;
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
uint32_t evt_posted; uint32_t evt_posted;
atomic_inc(&phba->num_cmd_success); atomic_inc(&phba->num_cmd_success);
if (vport->cfg_lun_queue_depth <= sdev->queue_depth) if (vport->cfg_lun_queue_depth <= queue_depth)
return; return;
spin_lock_irqsave(&phba->hbalock, flags); spin_lock_irqsave(&phba->hbalock, flags);
if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) || if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) ||
...@@ -737,7 +737,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) ...@@ -737,7 +737,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
* Due to difference in data length between DIF/non-DIF paths, * Due to difference in data length between DIF/non-DIF paths,
* we need to set word 4 of IOCB here * we need to set word 4 of IOCB here
*/ */
iocb_cmd->un.fcpi.fcpi_parm = le32_to_cpu(scsi_bufflen(scsi_cmnd)); iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
return 0; return 0;
} }
...@@ -1693,10 +1693,12 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, ...@@ -1693,10 +1693,12 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct lpfc_nodelist *pnode = rdata->pnode; struct lpfc_nodelist *pnode = rdata->pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd; struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
int result; int result;
struct scsi_device *sdev, *tmp_sdev; struct scsi_device *tmp_sdev;
int depth = 0; int depth = 0;
unsigned long flags; unsigned long flags;
struct lpfc_fast_path_event *fast_path_evt; struct lpfc_fast_path_event *fast_path_evt;
struct Scsi_Host *shost = cmd->device->host;
uint32_t queue_depth, scsi_id;
lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
lpfc_cmd->status = pIocbOut->iocb.ulpStatus; lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
...@@ -1807,11 +1809,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, ...@@ -1807,11 +1809,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
lpfc_update_stats(phba, lpfc_cmd); lpfc_update_stats(phba, lpfc_cmd);
result = cmd->result; result = cmd->result;
sdev = cmd->device;
if (vport->cfg_max_scsicmpl_time && if (vport->cfg_max_scsicmpl_time &&
time_after(jiffies, lpfc_cmd->start_time + time_after(jiffies, lpfc_cmd->start_time +
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) { msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
spin_lock_irqsave(sdev->host->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
if (pnode && NLP_CHK_NODE_ACT(pnode)) { if (pnode && NLP_CHK_NODE_ACT(pnode)) {
if (pnode->cmd_qdepth > if (pnode->cmd_qdepth >
atomic_read(&pnode->cmd_pending) && atomic_read(&pnode->cmd_pending) &&
...@@ -1824,22 +1825,26 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, ...@@ -1824,22 +1825,26 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
pnode->last_change_time = jiffies; pnode->last_change_time = jiffies;
} }
spin_unlock_irqrestore(sdev->host->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
} else if (pnode && NLP_CHK_NODE_ACT(pnode)) { } else if (pnode && NLP_CHK_NODE_ACT(pnode)) {
if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) && if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) &&
time_after(jiffies, pnode->last_change_time + time_after(jiffies, pnode->last_change_time +
msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) { msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) {
spin_lock_irqsave(sdev->host->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
pnode->cmd_qdepth += pnode->cmd_qdepth * pnode->cmd_qdepth += pnode->cmd_qdepth *
LPFC_TGTQ_RAMPUP_PCENT / 100; LPFC_TGTQ_RAMPUP_PCENT / 100;
if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH) if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH)
pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH; pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
pnode->last_change_time = jiffies; pnode->last_change_time = jiffies;
spin_unlock_irqrestore(sdev->host->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
} }
} }
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
queue_depth = cmd->device->queue_depth;
scsi_id = cmd->device->id;
cmd->scsi_done(cmd); cmd->scsi_done(cmd);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
...@@ -1847,28 +1852,28 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, ...@@ -1847,28 +1852,28 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
* If there is a thread waiting for command completion * If there is a thread waiting for command completion
* wake up the thread. * wake up the thread.
*/ */
spin_lock_irqsave(sdev->host->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
lpfc_cmd->pCmd = NULL; lpfc_cmd->pCmd = NULL;
if (lpfc_cmd->waitq) if (lpfc_cmd->waitq)
wake_up(lpfc_cmd->waitq); wake_up(lpfc_cmd->waitq);
spin_unlock_irqrestore(sdev->host->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
lpfc_release_scsi_buf(phba, lpfc_cmd); lpfc_release_scsi_buf(phba, lpfc_cmd);
return; return;
} }
if (!result) if (!result)
lpfc_rampup_queue_depth(vport, sdev); lpfc_rampup_queue_depth(vport, queue_depth);
if (!result && pnode && NLP_CHK_NODE_ACT(pnode) && if (!result && pnode && NLP_CHK_NODE_ACT(pnode) &&
((jiffies - pnode->last_ramp_up_time) > ((jiffies - pnode->last_ramp_up_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) && LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
((jiffies - pnode->last_q_full_time) > ((jiffies - pnode->last_q_full_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) && LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
(vport->cfg_lun_queue_depth > sdev->queue_depth)) { (vport->cfg_lun_queue_depth > queue_depth)) {
shost_for_each_device(tmp_sdev, sdev->host) { shost_for_each_device(tmp_sdev, shost) {
if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){ if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){
if (tmp_sdev->id != sdev->id) if (tmp_sdev->id != scsi_id)
continue; continue;
if (tmp_sdev->ordered_tags) if (tmp_sdev->ordered_tags)
scsi_adjust_queue_depth(tmp_sdev, scsi_adjust_queue_depth(tmp_sdev,
...@@ -1884,7 +1889,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, ...@@ -1884,7 +1889,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
} }
lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode, lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode,
0xFFFFFFFF, 0xFFFFFFFF,
sdev->queue_depth - 1, sdev->queue_depth); queue_depth , queue_depth + 1);
} }
/* /*
...@@ -1895,8 +1900,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, ...@@ -1895,8 +1900,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
NLP_CHK_NODE_ACT(pnode)) { NLP_CHK_NODE_ACT(pnode)) {
pnode->last_q_full_time = jiffies; pnode->last_q_full_time = jiffies;
shost_for_each_device(tmp_sdev, sdev->host) { shost_for_each_device(tmp_sdev, shost) {
if (tmp_sdev->id != sdev->id) if (tmp_sdev->id != scsi_id)
continue; continue;
depth = scsi_track_queue_full(tmp_sdev, depth = scsi_track_queue_full(tmp_sdev,
tmp_sdev->queue_depth - 1); tmp_sdev->queue_depth - 1);
...@@ -1908,7 +1913,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, ...@@ -1908,7 +1913,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
* scsi_track_queue_full. * scsi_track_queue_full.
*/ */
if (depth == -1) if (depth == -1)
depth = sdev->host->cmd_per_lun; depth = shost->cmd_per_lun;
if (depth) { if (depth) {
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
...@@ -1924,11 +1929,11 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, ...@@ -1924,11 +1929,11 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
* If there is a thread waiting for command completion * If there is a thread waiting for command completion
* wake up the thread. * wake up the thread.
*/ */
spin_lock_irqsave(sdev->host->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
lpfc_cmd->pCmd = NULL; lpfc_cmd->pCmd = NULL;
if (lpfc_cmd->waitq) if (lpfc_cmd->waitq)
wake_up(lpfc_cmd->waitq); wake_up(lpfc_cmd->waitq);
spin_unlock_irqrestore(sdev->host->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
lpfc_release_scsi_buf(phba, lpfc_cmd); lpfc_release_scsi_buf(phba, lpfc_cmd);
} }
......
This diff is collapsed.
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