summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames Smart2008-08-25 03:50:00 +0200
committerJames Bottomley2008-10-13 15:28:53 +0200
commitd7c255b26d8e3f12164d82093de3bf22efad2b4a (patch)
tree0b3467eda322ec2d90e5a7369891ab4ba12ff0a1 /drivers/scsi/lpfc/lpfc_sli.c
parent[SCSI] lpfc 8.2.8 : Update driver for new SLI-3 features (diff)
downloadkernel-qcow2-linux-d7c255b26d8e3f12164d82093de3bf22efad2b4a.tar.gz
kernel-qcow2-linux-d7c255b26d8e3f12164d82093de3bf22efad2b4a.tar.xz
kernel-qcow2-linux-d7c255b26d8e3f12164d82093de3bf22efad2b4a.zip
[SCSI] lpfc 8.2.8 : Miscellaneous Bug Fixes
Miscellaneous Fixes: - Fix the wrong variable name used for checking node active usage status - Fix numerous duplicate log message numbers - Fix change KERN_WARNING messages to KERN_INFO. - Stop sending erroneous LOGO to fabric after vport is already terminated - Fix HBQ allocates that were kalloc'ing w/ GFP_KERNEL while holding a lock. - Fix gcc 4.3.2 compiler warnings and a sparse warning - Fix bugs in handling unsolicited ct event queue - Reorder some of the initial link up checks, to remove odd VPI states. - Correct poor VPI handling - Add debug messages - Expand Update_CFG mailbox definition - Fix handling of VPD data offsets - Reorder loopback flags - convert to use offsetof() Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c105
1 files changed, 62 insertions, 43 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 77afa2ba6a2b..c7a520fa1aaa 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -844,48 +844,58 @@ struct lpfc_hbq_init *lpfc_hbq_defs[] = {
* @hbqno: HBQ number.
* @count: Number of HBQ buffers to be posted.
*
- * This function is called with no lock held to post more
- * hbq buffers to the given HBQ. The function returns 0
- * when successful and returns 1 other wise.
+ * This function is called with no lock held to post more hbq buffers to the
+ * given HBQ. The function returns the number of HBQ buffers successfully
+ * posted.
**/
static int
lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
{
- uint32_t i, start, end;
+ uint32_t i, posted = 0;
unsigned long flags;
struct hbq_dmabuf *hbq_buffer;
-
+ LIST_HEAD(hbq_buf_list);
if (!phba->hbqs[hbqno].hbq_alloc_buffer)
return 0;
- start = phba->hbqs[hbqno].buffer_count;
- end = count + start;
- if (end > lpfc_hbq_defs[hbqno]->entry_count)
- end = lpfc_hbq_defs[hbqno]->entry_count;
-
+ if ((phba->hbqs[hbqno].buffer_count + count) >
+ lpfc_hbq_defs[hbqno]->entry_count)
+ count = lpfc_hbq_defs[hbqno]->entry_count -
+ phba->hbqs[hbqno].buffer_count;
+ if (!count)
+ return 0;
+ /* Allocate HBQ entries */
+ for (i = 0; i < count; i++) {
+ hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
+ if (!hbq_buffer)
+ break;
+ list_add_tail(&hbq_buffer->dbuf.list, &hbq_buf_list);
+ }
/* Check whether HBQ is still in use */
spin_lock_irqsave(&phba->hbalock, flags);
if (!phba->hbq_in_use)
- goto out;
-
- /* Populate HBQ entries */
- for (i = start; i < end; i++) {
- hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
- if (!hbq_buffer)
- goto err;
- hbq_buffer->tag = (i | (hbqno << 16));
- if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer))
+ goto err;
+ while (!list_empty(&hbq_buf_list)) {
+ list_remove_head(&hbq_buf_list, hbq_buffer, struct hbq_dmabuf,
+ dbuf.list);
+ hbq_buffer->tag = (phba->hbqs[hbqno].buffer_count |
+ (hbqno << 16));
+ if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) {
phba->hbqs[hbqno].buffer_count++;
- else
+ posted++;
+ } else
(phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
}
-
- out:
spin_unlock_irqrestore(&phba->hbalock, flags);
- return 0;
- err:
+ return posted;
+err:
spin_unlock_irqrestore(&phba->hbalock, flags);
- return 1;
+ while (!list_empty(&hbq_buf_list)) {
+ list_remove_head(&hbq_buf_list, hbq_buffer, struct hbq_dmabuf,
+ dbuf.list);
+ (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
+ }
+ return 0;
}
/**
@@ -894,8 +904,8 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
* @qno: HBQ number.
*
* This function posts more buffers to the HBQ. This function
- * is called with no lock held. The function returns 0 when
- * successful and returns 1 otherwise.
+ * is called with no lock held. The function returns the number of HBQ entries
+ * successfully allocated.
**/
int
lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
@@ -911,7 +921,7 @@ lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
*
* This function is called from SLI initialization code path with
* no lock held to post initial HBQ buffers to firmware. The
- * function returns 0 when successful and returns 1 otherwise.
+ * function returns the number of HBQ entries successfully allocated.
**/
static int
lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
@@ -1253,7 +1263,9 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
* This function is called from unsolicited event handler code path to get the
* HBQ buffer associated with an unsolicited iocb. This function is called with
* no lock held. It returns the buffer associated with the given tag and posts
- * another buffer to the firmware.
+ * another buffer to the firmware. Note that the new buffer must be allocated
+ * before taking the hbalock and that the hba lock must be held until it is
+ * finished with the hbq entry swap.
**/
static struct lpfc_dmabuf *
lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
@@ -1264,22 +1276,28 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
dma_addr_t phys; /* mapped address */
unsigned long flags;
+ hbqno = tag >> 16;
+ new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
/* Check whether HBQ is still in use */
spin_lock_irqsave(&phba->hbalock, flags);
if (!phba->hbq_in_use) {
+ if (new_hbq_entry)
+ (phba->hbqs[hbqno].hbq_free_buffer)(phba,
+ new_hbq_entry);
spin_unlock_irqrestore(&phba->hbalock, flags);
return NULL;
}
hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
if (hbq_entry == NULL) {
+ if (new_hbq_entry)
+ (phba->hbqs[hbqno].hbq_free_buffer)(phba,
+ new_hbq_entry);
spin_unlock_irqrestore(&phba->hbalock, flags);
return NULL;
}
list_del(&hbq_entry->dbuf.list);
- hbqno = tag >> 16;
- new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
if (new_hbq_entry == NULL) {
list_add_tail(&hbq_entry->dbuf.list, &phba->hbqbuf_in_list);
spin_unlock_irqrestore(&phba->hbalock, flags);
@@ -1748,8 +1766,8 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
irsp->un.ulpWord[3],
irsp->un.ulpWord[4],
irsp->un.ulpWord[5],
- *(((uint32_t *) irsp) + 6),
- *(((uint32_t *) irsp) + 7));
+ *(uint32_t *)&irsp->un1,
+ *((uint32_t *)&irsp->un1 + 1));
}
switch (type) {
@@ -1935,8 +1953,8 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
irsp->un.ulpWord[3],
irsp->un.ulpWord[4],
irsp->un.ulpWord[5],
- *(((uint32_t *) irsp) + 6),
- *(((uint32_t *) irsp) + 7));
+ *(uint32_t *)&irsp->un1,
+ *((uint32_t *)&irsp->un1 + 1));
}
switch (type) {
@@ -2921,10 +2939,8 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
mempool_free(pmb, phba->mbox_mem_pool);
/* Initially populate or replenish the HBQs */
- for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
- if (lpfc_sli_hbqbuf_init_hbqs(phba, hbqno))
- return -ENOMEM;
- }
+ for (hbqno = 0; hbqno < hbq_count; ++hbqno)
+ lpfc_sli_hbqbuf_init_hbqs(phba, hbqno);
return 0;
}
@@ -3034,6 +3050,7 @@ lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
phba->port_gp = phba->mbox->us.s2.port;
phba->inb_ha_copy = NULL;
phba->inb_counter = NULL;
+ phba->max_vpi = 0;
}
do_prep_failed:
mempool_free(pmb, phba->mbox_mem_pool);
@@ -4335,7 +4352,7 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
spin_unlock_irq(&phba->hbalock);
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0410 Cannot find virtual addr for buffer tag on "
+ "0402 Cannot find virtual addr for buffer tag on "
"ring %d Data x%lx x%p x%p x%x\n",
pring->ringno, (unsigned long) tag,
slp->next, slp->prev, pring->postbufq_cnt);
@@ -4482,7 +4499,7 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* ELS cmd tag <ulpIoTag> completes */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "0133 Ignoring ELS cmd tag x%x completion Data: "
+ "0139 Ignoring ELS cmd tag x%x completion Data: "
"x%x x%x x%x\n",
irsp->ulpIoTag, irsp->ulpStatus,
irsp->un.ulpWord[4], irsp->ulpTimeout);
@@ -4568,6 +4585,8 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
iabt->un.acxri.abortIoTag, abtsiocbp->iotag);
retval = __lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
+ if (retval)
+ __lpfc_sli_release_iocbq(phba, abtsiocbp);
abort_iotag_exit:
/*
* Caller to this routine should check for IOCB_ERROR
@@ -4899,7 +4918,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
}
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- ":0332 IOCB wait issue failed, Data x%x\n",
+ "0332 IOCB wait issue failed, Data x%x\n",
retval);
retval = IOCB_ERROR;
}
@@ -5271,7 +5290,7 @@ lpfc_intr_handler(int irq, void *dev_id)
lpfc_printf_log(phba,
KERN_ERR,
LOG_MBOX | LOG_SLI,
- "0306 rc should have"
+ "0350 rc should have"
"been MBX_BUSY");
goto send_current_mbox;
}