]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
be2iscsi: Fix updating the next pointer during WRB posting
authorJitendra Bhivare <jitendra.bhivare@avagotech.com>
Fri, 9 Oct 2015 10:11:28 +0000 (15:41 +0530)
committerDan Duval <dan.duval@oracle.com>
Mon, 12 Oct 2015 18:45:25 +0000 (14:45 -0400)
Orabug: 21862307

While posting WRB the next_pointer of the current WRB should point
to itself and the previous WRB next_pointer should point to the
current WRB.

The next pointer value was retrieved during alloc_pdu and was updated
in wrb before ringing the doorbell. The fix retrieves the
next_pointer just before ringing the doorbell and updates in the WRB.

Signed-off-by: John Soni Jose <sony.john@avagotech.com>
Signed-off-by: Dan Duval <dan.duval@oracle.com>
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_main.h
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/be2iscsi/be_mgmt.h

index 97d92cc51a0fbcffa82543311147c9186540b07f..a980a62e9896ebaacc614f182399d49d62c40a98 100644 (file)
@@ -1186,14 +1186,16 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
  * alloc_wrb_handle - To allocate a wrb handle
  * @phba: The hba pointer
  * @cid: The cid to use for allocation
+ * @pwrb_context: ptr to ptr to wrb context
  *
  * This happens under session_lock until submission to chip
  */
-struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
+                                    struct hwi_wrb_context **pcontext)
 {
        struct hwi_wrb_context *pwrb_context;
        struct hwi_controller *phwi_ctrlr;
-       struct wrb_handle *pwrb_handle, *pwrb_handle_tmp;
+       struct wrb_handle *pwrb_handle;
        uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
 
        phwi_ctrlr = phba->phwi_ctrlr;
@@ -1207,9 +1209,9 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
                        pwrb_context->alloc_index = 0;
                else
                        pwrb_context->alloc_index++;
-               pwrb_handle_tmp = pwrb_context->pwrb_handle_base[
-                                               pwrb_context->alloc_index];
-               pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index;
+
+               /* Return the context address */
+               *pcontext = pwrb_context;
        } else
                pwrb_handle = NULL;
        return pwrb_handle;
@@ -4649,6 +4651,7 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
                           struct beiscsi_offload_params *params)
 {
        struct wrb_handle *pwrb_handle;
+       struct hwi_wrb_context *pwrb_context = NULL;
        struct beiscsi_hba *phba = beiscsi_conn->phba;
        struct iscsi_task *task = beiscsi_conn->task;
        struct iscsi_session *session = task->conn->session;
@@ -4663,14 +4666,17 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
        beiscsi_cleanup_task(task);
        spin_unlock_bh(&session->back_lock);
 
-       pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid);
+       pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid,
+                                      &pwrb_context);
 
        /* Check for the adapter family */
        if (is_chip_be2_be3r(phba))
                beiscsi_offload_cxn_v0(params, pwrb_handle,
-                                      phba->init_mem);
+                                      phba->init_mem,
+                                      pwrb_context);
        else
-               beiscsi_offload_cxn_v2(params, pwrb_handle);
+               beiscsi_offload_cxn_v2(params, pwrb_handle,
+                                      pwrb_context);
 
        be_dws_le_to_cpu(pwrb_handle->pwrb,
                         sizeof(struct iscsi_target_context_update_wrb));
@@ -4740,7 +4746,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                        goto free_hndls;
                }
                io_task->pwrb_handle = alloc_wrb_handle(phba,
-                                       beiscsi_conn->beiscsi_conn_cid);
+                                       beiscsi_conn->beiscsi_conn_cid,
+                                       &io_task->pwrb_context);
                if (!io_task->pwrb_handle) {
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4774,7 +4781,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                                                        io_task->psgl_handle;
                                io_task->pwrb_handle =
                                        alloc_wrb_handle(phba,
-                                       beiscsi_conn->beiscsi_conn_cid);
+                                       beiscsi_conn->beiscsi_conn_cid,
+                                       &io_task->pwrb_context);
                                if (!io_task->pwrb_handle) {
                                        beiscsi_log(phba, KERN_ERR,
                                                    BEISCSI_LOG_IO |
@@ -4810,7 +4818,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                        }
                        io_task->pwrb_handle =
                                        alloc_wrb_handle(phba,
-                                       beiscsi_conn->beiscsi_conn_cid);
+                                       beiscsi_conn->beiscsi_conn_cid,
+                                       &io_task->pwrb_context);
                        if (!io_task->pwrb_handle) {
                                beiscsi_log(phba, KERN_ERR,
                                            BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4896,7 +4905,12 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
 
        hwi_write_sgl_v2(pwrb, sg, num_sg, io_task);
        AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
-                     io_task->pwrb_handle->nxt_wrb_index);
+                     io_task->pwrb_handle->wrb_index);
+       if (io_task->pwrb_context->plast_wrb)
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb,
+                             io_task->pwrb_context->plast_wrb,
+                             io_task->pwrb_handle->wrb_index);
+       io_task->pwrb_context->plast_wrb = pwrb;
 
        be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
 
@@ -4953,7 +4967,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
        hwi_write_sgl(pwrb, sg, num_sg, io_task);
 
        AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
-                     io_task->pwrb_handle->nxt_wrb_index);
+                     io_task->pwrb_handle->wrb_index);
+       if (io_task->pwrb_context->plast_wrb)
+               AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb,
+                             io_task->pwrb_context->plast_wrb,
+                             io_task->pwrb_handle->wrb_index);
+       io_task->pwrb_context->plast_wrb = pwrb;
+
        be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
 
        doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
@@ -4991,7 +5011,13 @@ static int beiscsi_mtask(struct iscsi_task *task)
                AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
                              task->data_count);
                AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
-                             io_task->pwrb_handle->nxt_wrb_index);
+                             io_task->pwrb_handle->wrb_index);
+               if (io_task->pwrb_context->plast_wrb)
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb,
+                                     io_task->pwrb_context->plast_wrb,
+                                     io_task->pwrb_handle->wrb_index);
+               io_task->pwrb_context->plast_wrb = pwrb;
+
                pwrb_typeoffset = BE_WRB_TYPE_OFFSET;
        } else {
                AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
@@ -5003,7 +5029,13 @@ static int beiscsi_mtask(struct iscsi_task *task)
                AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb,
                              task->data_count);
                AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
-                             io_task->pwrb_handle->nxt_wrb_index);
+                             io_task->pwrb_handle->wrb_index);
+               if (io_task->pwrb_context->plast_wrb)
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb,
+                                     io_task->pwrb_context->plast_wrb,
+                                     io_task->pwrb_handle->wrb_index);
+               io_task->pwrb_context->plast_wrb = pwrb;
+
                pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
        }
 
index e70ea26bbc2b0fff8a82c540edd4aceab371da45..ebdd523c1728f58649f7a96b2cb00fea05de77c3 100644 (file)
@@ -498,6 +498,7 @@ struct beiscsi_io_task {
        struct sgl_handle *psgl_handle;
        struct beiscsi_conn *conn;
        struct scsi_cmnd *scsi_cmnd;
+       struct hwi_wrb_context *pwrb_context;
        unsigned int cmd_sn;
        unsigned int flags;
        unsigned short cid;
@@ -829,7 +830,8 @@ struct amap_iscsi_wrb_v2 {
 } __packed;
 
 
-struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid);
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
+                                    struct hwi_wrb_context **pcontext);
 void
 free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
 
@@ -1040,7 +1042,6 @@ enum hwh_type_enum {
 struct wrb_handle {
        enum hwh_type_enum type;
        unsigned short wrb_index;
-       unsigned short nxt_wrb_index;
 
        struct iscsi_task *pio_handle;
        struct iscsi_wrb *pwrb;
index ac08adb290989fb1e38c0dca1965c96f9af6e878..4fe7654f81437082e45a72077b99fa35b9eb0f54 100644 (file)
@@ -1574,7 +1574,8 @@ beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr,
 
 void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
                             struct wrb_handle *pwrb_handle,
-                            struct be_mem_descriptor *mem_descr)
+                            struct be_mem_descriptor *mem_descr,
+                            struct hwi_wrb_context *pwrb_context)
 {
        struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
 
@@ -1618,7 +1619,14 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
                      max_burst_length) / 32]);
 
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
-                     pwrb, pwrb_handle->nxt_wrb_index);
+                     pwrb, pwrb_handle->wrb_index);
+       if (pwrb_context->plast_wrb)
+               AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                             ptr2nextwrb,
+                             pwrb_context->plast_wrb,
+                             pwrb_handle->wrb_index);
+       pwrb_context->plast_wrb = pwrb;
+
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
                      session_state, pwrb, 0);
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
@@ -1638,7 +1646,8 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
 }
 
 void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
-                            struct wrb_handle *pwrb_handle)
+                            struct wrb_handle *pwrb_handle,
+                            struct hwi_wrb_context *pwrb_context)
 {
        struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
 
@@ -1653,7 +1662,14 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
                      BE_TGT_CTX_UPDT_CMD);
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
                      ptr2nextwrb,
-                     pwrb, pwrb_handle->nxt_wrb_index);
+                     pwrb, pwrb_handle->wrb_index);
+       if (pwrb_context->plast_wrb)
+               AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                             ptr2nextwrb,
+                             pwrb_context->plast_wrb,
+                             pwrb_handle->wrb_index);
+       pwrb_context->plast_wrb = pwrb;
+
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx,
                      pwrb, pwrb_handle->wrb_index);
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
index b58a7decbd94aa437ab0c5c6f99b8287ccecffac..1df0a018b3e892c0edc9d9629156d69a7a39a0d1 100644 (file)
@@ -330,10 +330,13 @@ ssize_t beiscsi_phys_port_disp(struct device *dev,
 
 void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
                             struct wrb_handle *pwrb_handle,
-                            struct be_mem_descriptor *mem_descr);
+                            struct be_mem_descriptor *mem_descr,
+                            struct hwi_wrb_context *pwrb_context);
 
 void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
-                            struct wrb_handle *pwrb_handle);
+                            struct wrb_handle *pwrb_handle,
+                            struct hwi_wrb_context *pwrb_context);
+
 void beiscsi_ue_detect(struct beiscsi_hba *phba);
 int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
                         struct be_set_eqd *, int num);