]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/lpfc/lpfc_mem.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / scsi / lpfc / lpfc_mem.c
index 3594c469494face18a422e6811516cda4574d35a..3c0cebc718002a3e65e0ea66443d39400e575f95 100644 (file)
@@ -98,6 +98,7 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
 
  fail_free_hbq_pool:
        lpfc_sli_hbqbuf_free_all(phba);
+       pci_pool_destroy(phba->lpfc_hbq_pool);
  fail_free_nlp_mem_pool:
        mempool_destroy(phba->nlp_mem_pool);
        phba->nlp_mem_pool = NULL;
@@ -231,39 +232,62 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
        return;
 }
 
-void *
-lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
+struct hbq_dmabuf *
+lpfc_els_hbq_alloc(struct lpfc_hba *phba)
 {
-       void *ret;
-       ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle);
-       return ret;
+       struct hbq_dmabuf *hbqbp;
+
+       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
-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;
 }
 
+/* This is ONLY called for the LPFC_ELS_HBQ */
 void
 lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
 {
        struct hbq_dmabuf *hbq_entry;
+       unsigned long flags;
+
+       if (!mp)
+               return;
 
        if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
+               /* Check whether HBQ is still in use */
+               spin_lock_irqsave(&phba->hbalock, flags);
+               if (!phba->hbq_in_use) {
+                       spin_unlock_irqrestore(&phba->hbalock, flags);
+                       return;
+               }
                hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf);
+               list_del(&hbq_entry->dbuf.list);
                if (hbq_entry->tag == -1) {
-                       lpfc_hbq_free(phba, hbq_entry->dbuf.virt,
-                                     hbq_entry->dbuf.phys);
-                       kfree(hbq_entry);
+                       (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer)
+                               (phba, hbq_entry);
                } else {
                        lpfc_sli_free_hbq(phba, hbq_entry);
                }
+               spin_unlock_irqrestore(&phba->hbalock, flags);
        } else {
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
        }
        return;
 }
-