Skip to content

Commit

Permalink
scsi: qedi: Add support for fastpath doorvell recovery
Browse files Browse the repository at this point in the history
Driver fastpath employs doorbells to indicate to the device that work
is available. Each doorbell translates to a message sent to the device
over the pci. These messages are queued by the doorbell queue HW block,
and handled by the HW.
If a sufficient amount of CPU cores are sending messages at a sufficient
rate, the queue can overflow, and messages can be dropped. There are
many entities in the driver which can send doorbell messages.
When overflow happens, a fatal HW attention is indicated, and the
Doorbell HW block stops accepting new doorbell messages until recovery
procedure is done.

When overflow occurs, all doorbells are dropped. Since doorbells are
aggregatives, if more doorbells are sent nothing has to be done.
But if the "last" doorbell is dropped, the doorbelling entity doesn’t know
this happened, and may wait forever for the device to perform the action.
The doorbell recovery mechanism addresses just that - it sends the last
doorbell of every entity.

Signed-off-by: Manish Rangankar <mrangankar@marvell.com>
Signed-off-by: Shai Malin <smalin@marvell.com>
  • Loading branch information
smalin1 authored and intel-lab-lkp committed Aug 4, 2021
1 parent 3c89644 commit 10706db
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 11 deletions.
14 changes: 4 additions & 10 deletions drivers/scsi/qedi/qedi_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,17 +936,11 @@ void qedi_fp_process_cqes(struct qedi_work *work)

static void qedi_ring_doorbell(struct qedi_conn *qedi_conn)
{
struct iscsi_db_data dbell = { 0 };
qedi_conn->ep->db_data.sq_prod = qedi_conn->ep->fw_sq_prod_idx

dbell.agg_flags = 0;

dbell.params |= DB_DEST_XCM << ISCSI_DB_DATA_DEST_SHIFT;
dbell.params |= DB_AGG_CMD_SET << ISCSI_DB_DATA_AGG_CMD_SHIFT;
dbell.params |=
DQ_XCM_ISCSI_SQ_PROD_CMD << ISCSI_DB_DATA_AGG_VAL_SEL_SHIFT;

dbell.sq_prod = qedi_conn->ep->fw_sq_prod_idx;
writel(*(u32 *)&dbell, qedi_conn->ep->p_doorbell);
/* wmb - Make sure fw idx is coherent */
wmb();
writel(*(u32 *)&qedi_conn->ep->db_data, qedi_conn->ep->p_doorbell);

/* Make sure fw write idx is coherent, and include both memory barriers
* as a failsafe as for some architectures the call is the same but on
Expand Down
33 changes: 32 additions & 1 deletion drivers/scsi/qedi/qedi_iscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,9 @@ static u16 qedi_calc_mss(u16 pmtu, u8 is_ipv6, u8 tcp_ts_en, u8 vlan_en)

static int qedi_iscsi_offload_conn(struct qedi_endpoint *qedi_ep)
{
struct qedi_ctx *qedi = qedi_ep->qedi;
struct qed_iscsi_params_offload *conn_info;
struct qedi_ctx *qedi = qedi_ep->qedi;
struct qedi_ep->db_data.params
int rval;
int i;

Expand Down Expand Up @@ -577,8 +578,33 @@ static int qedi_iscsi_offload_conn(struct qedi_endpoint *qedi_ep)
"Default cq index [%d], mss [%d]\n",
conn_info->default_cq, conn_info->mss);

/* Prepare the doorbell parameters */
qedi_ep->db_data.agg_flags = 0;
qedi_ep->db_data.params = 0;
SET_FIELD(qedi_ep->db_data.params, ISCSI_DB_DATA_DEST, DB_DEST_XCM);
SET_FIELD(qedi_ep->db_data.params, ISCSI_DB_DATA_AGG_CMD,
DB_AGG_CMD_MAX);
SET_FIELD(qedi_ep->db_data.params, ISCSI_DB_DATA_AGG_VAL_SEL,
DQ_XCM_ISCSI_SQ_PROD_CMD);
SET_FIELD(qedi_ep->db_data.params, ISCSI_DB_DATA_BYPASS_EN, 1);

/* register doorbell with doorbell recovery mechanism */
rc = qedi_ops->common->db_recovery_add(qedi->cdev,
qedi_ep.p_doorbell,
&qedi_ep.db_data,
DB_REC_WIDTH_32B, DB_REC_KERNEL);
if (rc) {
kfree(conn_info);
return rval;
}

rval = qedi_ops->offload_conn(qedi->cdev, qedi_ep->handle, conn_info);
if (rval)
/* delete doorbell from doorbell recovery mechanism */
rc = qedi_ops->common->db_recovery_del(qedi->cdev,
qedi_ep.p_doorbell,
&qedi_ep.db_data);

QEDI_ERR(&qedi->dbg_ctx, "offload_conn returned %d, ep=%p\n",
rval, qedi_ep);

Expand Down Expand Up @@ -1100,6 +1126,11 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
break;
}

/* delete doorbell from doorbell recovery mechanism */
rc = qedi_ops->common->db_recovery_del(qedi->cdev,
qedi_ep.p_doorbell,
&qedi_ep.db_data);

if (!abrt_conn)
wait_delay += qedi->pf_params.iscsi_pf_params.two_msl_timer;

Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/qedi/qedi_iscsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ struct qedi_endpoint {
u32 handle;
u32 fw_cid;
void __iomem *p_doorbell;
struct iscsi_db_data db_data;

/* Send queue management */
struct iscsi_wqe *sq;
Expand Down

0 comments on commit 10706db

Please sign in to comment.