[SCSI] lpfc 8.3.29: Remove GFP_KERNEL allocation while lock is held
authorJames Smart <james.smart@emulex.com>
Wed, 18 Jan 2012 21:25:55 +0000 (16:25 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Sun, 19 Feb 2012 14:08:53 +0000 (08:08 -0600)
Note: this is a replacement patch for the issue pointed out in
http://www.gossamer-threads.com/lists/linux/kernel/1477270

Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/lpfc/lpfc_sli.c

index e5d22b10ff2f84617eb1cfc544b4c2ee3fbf9250..e0e4d8d18244a9402ccfa5647bd07bdde8ca8576 100644 (file)
@@ -557,81 +557,6 @@ __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag)
        return sglq;
 }
 
-/**
- * __lpfc_set_rrq_active - set RRQ active bit in the ndlp's xri_bitmap.
- * @phba: Pointer to HBA context object.
- * @ndlp: nodelist pointer for this target.
- * @xritag: xri used in this exchange.
- * @rxid: Remote Exchange ID.
- * @send_rrq: Flag used to determine if we should send rrq els cmd.
- *
- * This function is called with hbalock held.
- * The active bit is set in the ndlp's active rrq xri_bitmap. Allocates an
- * rrq struct and adds it to the active_rrq_list.
- *
- * returns  0 for rrq slot for this xri
- *         < 0  Were not able to get rrq mem or invalid parameter.
- **/
-static int
-__lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
-               uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
-{
-       struct lpfc_node_rrq *rrq;
-       int empty;
-       uint32_t did = 0;
-
-
-       if (!ndlp)
-               return -EINVAL;
-
-       if (!phba->cfg_enable_rrq)
-               return -EINVAL;
-
-       if (phba->pport->load_flag & FC_UNLOADING) {
-               phba->hba_flag &= ~HBA_RRQ_ACTIVE;
-               goto out;
-       }
-       did = ndlp->nlp_DID;
-
-       /*
-        * set the active bit even if there is no mem available.
-        */
-       if (NLP_CHK_FREE_REQ(ndlp))
-               goto out;
-
-       if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING))
-               goto out;
-
-       if (test_and_set_bit(xritag, ndlp->active_rrqs.xri_bitmap))
-               goto out;
-
-       rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
-       if (rrq) {
-               rrq->send_rrq = send_rrq;
-               rrq->xritag = xritag;
-               rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
-               rrq->ndlp = ndlp;
-               rrq->nlp_DID = ndlp->nlp_DID;
-               rrq->vport = ndlp->vport;
-               rrq->rxid = rxid;
-               empty = list_empty(&phba->active_rrq_list);
-               rrq->send_rrq = send_rrq;
-               list_add_tail(&rrq->list, &phba->active_rrq_list);
-               if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) {
-                       phba->hba_flag |= HBA_RRQ_ACTIVE;
-                       if (empty)
-                               lpfc_worker_wake_up(phba);
-               }
-               return 0;
-       }
-out:
-       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                       "2921 Can't set rrq active xri:0x%x rxid:0x%x"
-                       " DID:0x%x Send:%d\n",
-                       xritag, rxid, did, send_rrq);
-       return -EINVAL;
-}
-
 /**
  * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
  * @phba: Pointer to HBA context object.
@@ -860,15 +785,68 @@ lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
  **/
 int
 lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
-                       uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
+                   uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
 {
-       int ret;
        unsigned long iflags;
+       struct lpfc_node_rrq *rrq;
+       int empty;
+
+       if (!ndlp)
+               return -EINVAL;
+
+       if (!phba->cfg_enable_rrq)
+               return -EINVAL;
 
        spin_lock_irqsave(&phba->hbalock, iflags);
-       ret = __lpfc_set_rrq_active(phba, ndlp, xritag, rxid, send_rrq);
+       if (phba->pport->load_flag & FC_UNLOADING) {
+               phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+               goto out;
+       }
+
+       /*
+        * set the active bit even if there is no mem available.
+        */
+       if (NLP_CHK_FREE_REQ(ndlp))
+               goto out;
+
+       if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING))
+               goto out;
+
+       if (test_and_set_bit(xritag, ndlp->active_rrqs.xri_bitmap))
+               goto out;
+
        spin_unlock_irqrestore(&phba->hbalock, iflags);
-       return ret;
+       rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
+       if (!rrq) {
+               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                               "3155 Unable to allocate RRQ xri:0x%x rxid:0x%x"
+                               " DID:0x%x Send:%d\n",
+                               xritag, rxid, ndlp->nlp_DID, send_rrq);
+               return -EINVAL;
+       }
+       rrq->send_rrq = send_rrq;
+       rrq->xritag = xritag;
+       rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
+       rrq->ndlp = ndlp;
+       rrq->nlp_DID = ndlp->nlp_DID;
+       rrq->vport = ndlp->vport;
+       rrq->rxid = rxid;
+       rrq->send_rrq = send_rrq;
+       spin_lock_irqsave(&phba->hbalock, iflags);
+       empty = list_empty(&phba->active_rrq_list);
+       list_add_tail(&rrq->list, &phba->active_rrq_list);
+       phba->hba_flag |= HBA_RRQ_ACTIVE;
+       if (empty)
+               lpfc_worker_wake_up(phba);
+       spin_unlock_irqrestore(&phba->hbalock, iflags);
+       return 0;
+out:
+       spin_unlock_irqrestore(&phba->hbalock, iflags);
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "2921 Can't set rrq active xri:0x%x rxid:0x%x"
+                       " DID:0x%x Send:%d\n",
+                       xritag, rxid, ndlp->nlp_DID, send_rrq);
+       return -EINVAL;
 }
 
 /**