Commit 340c99e9 authored by John Soni Jose's avatar John Soni Jose Committed by James Bottomley

be2iscsi: Fix updating the next pointer during WRB posting

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: default avatarJohn Soni Jose <sony.john@avagotech.com>
Reviewed-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent 40998193
...@@ -1198,14 +1198,16 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) ...@@ -1198,14 +1198,16 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
* alloc_wrb_handle - To allocate a wrb handle * alloc_wrb_handle - To allocate a wrb handle
* @phba: The hba pointer * @phba: The hba pointer
* @cid: The cid to use for allocation * @cid: The cid to use for allocation
* @pwrb_context: ptr to ptr to wrb context
* *
* This happens under session_lock until submission to chip * 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_wrb_context *pwrb_context;
struct hwi_controller *phwi_ctrlr; 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); uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
phwi_ctrlr = phba->phwi_ctrlr; phwi_ctrlr = phba->phwi_ctrlr;
...@@ -1219,9 +1221,9 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid) ...@@ -1219,9 +1221,9 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
pwrb_context->alloc_index = 0; pwrb_context->alloc_index = 0;
else else
pwrb_context->alloc_index++; pwrb_context->alloc_index++;
pwrb_handle_tmp = pwrb_context->pwrb_handle_base[
pwrb_context->alloc_index]; /* Return the context address */
pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index; *pcontext = pwrb_context;
} else } else
pwrb_handle = NULL; pwrb_handle = NULL;
return pwrb_handle; return pwrb_handle;
...@@ -4678,6 +4680,7 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, ...@@ -4678,6 +4680,7 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
struct beiscsi_offload_params *params) struct beiscsi_offload_params *params)
{ {
struct wrb_handle *pwrb_handle; struct wrb_handle *pwrb_handle;
struct hwi_wrb_context *pwrb_context = NULL;
struct beiscsi_hba *phba = beiscsi_conn->phba; struct beiscsi_hba *phba = beiscsi_conn->phba;
struct iscsi_task *task = beiscsi_conn->task; struct iscsi_task *task = beiscsi_conn->task;
struct iscsi_session *session = task->conn->session; struct iscsi_session *session = task->conn->session;
...@@ -4692,14 +4695,17 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, ...@@ -4692,14 +4695,17 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
beiscsi_cleanup_task(task); beiscsi_cleanup_task(task);
spin_unlock_bh(&session->back_lock); 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 */ /* Check for the adapter family */
if (is_chip_be2_be3r(phba)) if (is_chip_be2_be3r(phba))
beiscsi_offload_cxn_v0(params, pwrb_handle, beiscsi_offload_cxn_v0(params, pwrb_handle,
phba->init_mem); phba->init_mem,
pwrb_context);
else 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, be_dws_le_to_cpu(pwrb_handle->pwrb,
sizeof(struct iscsi_target_context_update_wrb)); sizeof(struct iscsi_target_context_update_wrb));
...@@ -4769,7 +4775,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) ...@@ -4769,7 +4775,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
goto free_hndls; goto free_hndls;
} }
io_task->pwrb_handle = alloc_wrb_handle(phba, 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) { if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
...@@ -4803,7 +4810,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) ...@@ -4803,7 +4810,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
io_task->psgl_handle; io_task->psgl_handle;
io_task->pwrb_handle = io_task->pwrb_handle =
alloc_wrb_handle(phba, alloc_wrb_handle(phba,
beiscsi_conn->beiscsi_conn_cid); beiscsi_conn->beiscsi_conn_cid,
&io_task->pwrb_context);
if (!io_task->pwrb_handle) { if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_IO |
...@@ -4839,7 +4847,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) ...@@ -4839,7 +4847,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
} }
io_task->pwrb_handle = io_task->pwrb_handle =
alloc_wrb_handle(phba, alloc_wrb_handle(phba,
beiscsi_conn->beiscsi_conn_cid); beiscsi_conn->beiscsi_conn_cid,
&io_task->pwrb_context);
if (!io_task->pwrb_handle) { if (!io_task->pwrb_handle) {
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
...@@ -4925,7 +4934,12 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, ...@@ -4925,7 +4934,12 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
hwi_write_sgl_v2(pwrb, sg, num_sg, io_task); hwi_write_sgl_v2(pwrb, sg, num_sg, io_task);
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, 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)); be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
...@@ -4982,7 +4996,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, ...@@ -4982,7 +4996,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
hwi_write_sgl(pwrb, sg, num_sg, io_task); hwi_write_sgl(pwrb, sg, num_sg, io_task);
AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, 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)); be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
...@@ -5020,7 +5040,13 @@ static int beiscsi_mtask(struct iscsi_task *task) ...@@ -5020,7 +5040,13 @@ static int beiscsi_mtask(struct iscsi_task *task)
AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
task->data_count); task->data_count);
AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, 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; pwrb_typeoffset = BE_WRB_TYPE_OFFSET;
} else { } else {
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
...@@ -5032,7 +5058,13 @@ static int beiscsi_mtask(struct iscsi_task *task) ...@@ -5032,7 +5058,13 @@ static int beiscsi_mtask(struct iscsi_task *task)
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb,
task->data_count); task->data_count);
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, 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; pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
} }
......
...@@ -502,6 +502,7 @@ struct beiscsi_io_task { ...@@ -502,6 +502,7 @@ struct beiscsi_io_task {
struct sgl_handle *psgl_handle; struct sgl_handle *psgl_handle;
struct beiscsi_conn *conn; struct beiscsi_conn *conn;
struct scsi_cmnd *scsi_cmnd; struct scsi_cmnd *scsi_cmnd;
struct hwi_wrb_context *pwrb_context;
unsigned int cmd_sn; unsigned int cmd_sn;
unsigned int flags; unsigned int flags;
unsigned short cid; unsigned short cid;
...@@ -833,7 +834,8 @@ struct amap_iscsi_wrb_v2 { ...@@ -833,7 +834,8 @@ struct amap_iscsi_wrb_v2 {
} __packed; } __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 void
free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
...@@ -1044,7 +1046,6 @@ enum hwh_type_enum { ...@@ -1044,7 +1046,6 @@ enum hwh_type_enum {
struct wrb_handle { struct wrb_handle {
enum hwh_type_enum type; enum hwh_type_enum type;
unsigned short wrb_index; unsigned short wrb_index;
unsigned short nxt_wrb_index;
struct iscsi_task *pio_handle; struct iscsi_task *pio_handle;
struct iscsi_wrb *pwrb; struct iscsi_wrb *pwrb;
......
...@@ -1573,7 +1573,8 @@ beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr, ...@@ -1573,7 +1573,8 @@ beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr,
void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
struct wrb_handle *pwrb_handle, 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; struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
...@@ -1617,7 +1618,14 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, ...@@ -1617,7 +1618,14 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
max_burst_length) / 32]); max_burst_length) / 32]);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb, 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, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
session_state, pwrb, 0); session_state, pwrb, 0);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
...@@ -1637,7 +1645,8 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, ...@@ -1637,7 +1645,8 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
} }
void beiscsi_offload_cxn_v2(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; struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
...@@ -1652,7 +1661,14 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, ...@@ -1652,7 +1661,14 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
BE_TGT_CTX_UPDT_CMD); BE_TGT_CTX_UPDT_CMD);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
ptr2nextwrb, 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, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx,
pwrb, pwrb_handle->wrb_index); pwrb, pwrb_handle->wrb_index);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
......
...@@ -330,10 +330,13 @@ ssize_t beiscsi_phys_port_disp(struct device *dev, ...@@ -330,10 +330,13 @@ ssize_t beiscsi_phys_port_disp(struct device *dev,
void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
struct wrb_handle *pwrb_handle, 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, 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); void beiscsi_ue_detect(struct beiscsi_hba *phba);
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
struct be_set_eqd *, int num); struct be_set_eqd *, int num);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment