be2iscsi: Fix processing CQE before connection resources are freed
authorJayamohan Kallickal <jayamohan.kallickal@emulex.com>
Fri, 8 Aug 2014 05:00:01 +0000 (01:00 -0400)
committerChristoph Hellwig <hch@lst.de>
Tue, 16 Sep 2014 16:09:47 +0000 (09:09 -0700)
 Driver should process the completion queue entries before a connection
 resources are freed. While running mixed traffic due to latency, driver
 processes the CQE after the connection resources are freed. This fix
 processes all the completion queue before the connection resources are
 freed.

Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/scsi/be2iscsi/be_iscsi.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_main.h

index e25203ef1138ad2a5891b168439542d1e4b6fbff..b7391a3f9f0ba1d3e1f9ba96649d7ca8a9e2af16 100644 (file)
@@ -1273,6 +1273,31 @@ int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
                return 0;
 }
 
+/**
+ * beiscsi_flush_cq()- Flush the CQ created.
+ * @phba: ptr device priv structure.
+ *
+ * Before the connection resource are freed flush
+ * all the CQ enteries
+ **/
+static void beiscsi_flush_cq(struct beiscsi_hba *phba)
+{
+       uint16_t i;
+       struct be_eq_obj *pbe_eq;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+
+       for (i = 0; i < phba->num_cpus; i++) {
+               pbe_eq = &phwi_context->be_eq[i];
+               blk_iopoll_disable(&pbe_eq->iopoll);
+               beiscsi_process_cq(pbe_eq);
+               blk_iopoll_enable(&pbe_eq->iopoll);
+       }
+}
+
 /**
  * beiscsi_close_conn - Upload the  connection
  * @ep: The iscsi endpoint
@@ -1294,6 +1319,10 @@ static int beiscsi_close_conn(struct  beiscsi_endpoint *beiscsi_ep, int flag)
        }
 
        ret = beiscsi_mccq_compl(phba, tag, NULL, NULL);
+
+       /* Flush the CQ entries */
+       beiscsi_flush_cq(phba);
+
        return ret;
 }
 
index 0762b8e44f95a7d88ddd0373d816c5e86746ea0e..c44dce2aa1f22ac37013172273ae003c3accf3f4 100644 (file)
@@ -2068,7 +2068,7 @@ static void  beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
  * return
  *     Number of Completion Entries processed.
  **/
-static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
+unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 {
        struct be_queue_info *cq;
        struct sol_cqe *sol;
@@ -2110,6 +2110,18 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 
                cri_index = BE_GET_CRI_FROM_CID(cid);
                ep = phba->ep_array[cri_index];
+
+               if (ep == NULL) {
+                       /* connection has already been freed
+                        * just move on to next one
+                        */
+                       beiscsi_log(phba, KERN_WARNING,
+                                   BEISCSI_LOG_INIT,
+                                   "BM_%d : proc cqe of disconn ep: cid %d\n",
+                                   cid);
+                       goto proc_next_cqe;
+               }
+
                beiscsi_ep = ep->dd_data;
                beiscsi_conn = beiscsi_ep->conn;
 
@@ -2219,6 +2231,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                        break;
                }
 
+proc_next_cqe:
                AMAP_SET_BITS(struct amap_sol_cqe, valid, sol, 0);
                queue_tail_inc(cq);
                sol = queue_tail_node(cq);
index 1e3428a4dbfbceaaf1053ee4c38fc5da72f07d9f..5f8b0fcbe22a9537c95230f744b4e17c27698056 100644 (file)
@@ -840,6 +840,9 @@ void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
 void hwi_ring_cq_db(struct beiscsi_hba *phba,
                     unsigned int id, unsigned int num_processed,
                     unsigned char rearm, unsigned char event);
+
+unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq);
+
 static inline bool beiscsi_error(struct beiscsi_hba *phba)
 {
        return phba->ue_detected || phba->fw_timeout;