Commit 4c3b23e9 authored by Varun Prakash's avatar Varun Prakash Committed by Greg Kroah-Hartman

scsi: cxgb4i: add wait_for_completion()

[ Upstream commit 9e8f1c79 ]

In case of ->set_param() and ->bind_conn() cxgb4i driver does not wait for
cmd completion, this can create race conditions, to avoid this add
wait_for_completion().
Signed-off-by: default avatarVarun Prakash <varun@chelsio.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent b2ae8247
...@@ -1144,7 +1144,7 @@ static void ddp_clear_map(struct cxgbi_device *cdev, struct cxgbi_ppm *ppm, ...@@ -1144,7 +1144,7 @@ static void ddp_clear_map(struct cxgbi_device *cdev, struct cxgbi_ppm *ppm,
} }
static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
unsigned int tid, int pg_idx, bool reply) unsigned int tid, int pg_idx)
{ {
struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0, struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
GFP_KERNEL); GFP_KERNEL);
...@@ -1160,7 +1160,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, ...@@ -1160,7 +1160,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
req = (struct cpl_set_tcb_field *)skb->head; req = (struct cpl_set_tcb_field *)skb->head;
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
req->reply = V_NO_REPLY(reply ? 0 : 1); req->reply = V_NO_REPLY(1);
req->cpu_idx = 0; req->cpu_idx = 0;
req->word = htons(31); req->word = htons(31);
req->mask = cpu_to_be64(0xF0000000); req->mask = cpu_to_be64(0xF0000000);
...@@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, ...@@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
* @tid: connection id * @tid: connection id
* @hcrc: header digest enabled * @hcrc: header digest enabled
* @dcrc: data digest enabled * @dcrc: data digest enabled
* @reply: request reply from h/w
* set up the iscsi digest settings for a connection identified by tid * set up the iscsi digest settings for a connection identified by tid
*/ */
static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
int hcrc, int dcrc, int reply) int hcrc, int dcrc)
{ {
struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0, struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
GFP_KERNEL); GFP_KERNEL);
...@@ -1197,7 +1196,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, ...@@ -1197,7 +1196,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
req = (struct cpl_set_tcb_field *)skb->head; req = (struct cpl_set_tcb_field *)skb->head;
req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
req->reply = V_NO_REPLY(reply ? 0 : 1); req->reply = V_NO_REPLY(1);
req->cpu_idx = 0; req->cpu_idx = 0;
req->word = htons(31); req->word = htons(31);
req->mask = cpu_to_be64(0x0F000000); req->mask = cpu_to_be64(0x0F000000);
......
...@@ -1517,16 +1517,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb) ...@@ -1517,16 +1517,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
struct cxgbi_sock *csk; struct cxgbi_sock *csk;
csk = lookup_tid(t, tid); csk = lookup_tid(t, tid);
if (!csk) if (!csk) {
pr_err("can't find conn. for tid %u.\n", tid); pr_err("can't find conn. for tid %u.\n", tid);
return;
}
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p,%u,%lx,%u, status 0x%x.\n", "csk 0x%p,%u,%lx,%u, status 0x%x.\n",
csk, csk->state, csk->flags, csk->tid, rpl->status); csk, csk->state, csk->flags, csk->tid, rpl->status);
if (rpl->status != CPL_ERR_NONE) if (rpl->status != CPL_ERR_NONE) {
pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n", pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n",
csk, tid, rpl->status); csk, tid, rpl->status);
csk->err = -EINVAL;
}
complete(&csk->cmpl);
__kfree_skb(skb); __kfree_skb(skb);
} }
...@@ -1903,7 +1909,7 @@ static int ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbi_sock *csk, ...@@ -1903,7 +1909,7 @@ static int ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbi_sock *csk,
} }
static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
int pg_idx, bool reply) int pg_idx)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct cpl_set_tcb_field *req; struct cpl_set_tcb_field *req;
...@@ -1919,7 +1925,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, ...@@ -1919,7 +1925,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
req = (struct cpl_set_tcb_field *)skb->head; req = (struct cpl_set_tcb_field *)skb->head;
INIT_TP_WR(req, csk->tid); INIT_TP_WR(req, csk->tid);
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid));
req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid)); req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
req->word_cookie = htons(0); req->word_cookie = htons(0);
req->mask = cpu_to_be64(0x3 << 8); req->mask = cpu_to_be64(0x3 << 8);
req->val = cpu_to_be64(pg_idx << 8); req->val = cpu_to_be64(pg_idx << 8);
...@@ -1928,12 +1934,15 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, ...@@ -1928,12 +1934,15 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx); "csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx);
reinit_completion(&csk->cmpl);
cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
return 0; wait_for_completion(&csk->cmpl);
return csk->err;
} }
static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
int hcrc, int dcrc, int reply) int hcrc, int dcrc)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct cpl_set_tcb_field *req; struct cpl_set_tcb_field *req;
...@@ -1951,7 +1960,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, ...@@ -1951,7 +1960,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
req = (struct cpl_set_tcb_field *)skb->head; req = (struct cpl_set_tcb_field *)skb->head;
INIT_TP_WR(req, tid); INIT_TP_WR(req, tid);
OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid)); req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
req->word_cookie = htons(0); req->word_cookie = htons(0);
req->mask = cpu_to_be64(0x3 << 4); req->mask = cpu_to_be64(0x3 << 4);
req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) | req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
...@@ -1961,8 +1970,11 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, ...@@ -1961,8 +1970,11 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc); "csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc);
reinit_completion(&csk->cmpl);
cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
return 0; wait_for_completion(&csk->cmpl);
return csk->err;
} }
static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev) static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev)
......
...@@ -573,6 +573,7 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev) ...@@ -573,6 +573,7 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
skb_queue_head_init(&csk->receive_queue); skb_queue_head_init(&csk->receive_queue);
skb_queue_head_init(&csk->write_queue); skb_queue_head_init(&csk->write_queue);
timer_setup(&csk->retry_timer, NULL, 0); timer_setup(&csk->retry_timer, NULL, 0);
init_completion(&csk->cmpl);
rwlock_init(&csk->callback_lock); rwlock_init(&csk->callback_lock);
csk->cdev = cdev; csk->cdev = cdev;
csk->flags = 0; csk->flags = 0;
...@@ -2252,14 +2253,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn, ...@@ -2252,14 +2253,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
if (!err && conn->hdrdgst_en) if (!err && conn->hdrdgst_en)
err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid, err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
conn->hdrdgst_en, conn->hdrdgst_en,
conn->datadgst_en, 0); conn->datadgst_en);
break; break;
case ISCSI_PARAM_DATADGST_EN: case ISCSI_PARAM_DATADGST_EN:
err = iscsi_set_param(cls_conn, param, buf, buflen); err = iscsi_set_param(cls_conn, param, buf, buflen);
if (!err && conn->datadgst_en) if (!err && conn->datadgst_en)
err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid, err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
conn->hdrdgst_en, conn->hdrdgst_en,
conn->datadgst_en, 0); conn->datadgst_en);
break; break;
case ISCSI_PARAM_MAX_R2T: case ISCSI_PARAM_MAX_R2T:
return iscsi_tcp_set_max_r2t(conn, buf); return iscsi_tcp_set_max_r2t(conn, buf);
...@@ -2385,7 +2386,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session, ...@@ -2385,7 +2386,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
ppm = csk->cdev->cdev2ppm(csk->cdev); ppm = csk->cdev->cdev2ppm(csk->cdev);
err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid, err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
ppm->tformat.pgsz_idx_dflt, 0); ppm->tformat.pgsz_idx_dflt);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -146,6 +146,7 @@ struct cxgbi_sock { ...@@ -146,6 +146,7 @@ struct cxgbi_sock {
struct sk_buff_head receive_queue; struct sk_buff_head receive_queue;
struct sk_buff_head write_queue; struct sk_buff_head write_queue;
struct timer_list retry_timer; struct timer_list retry_timer;
struct completion cmpl;
int err; int err;
rwlock_t callback_lock; rwlock_t callback_lock;
void *user_data; void *user_data;
...@@ -487,9 +488,9 @@ struct cxgbi_device { ...@@ -487,9 +488,9 @@ struct cxgbi_device {
struct cxgbi_ppm *, struct cxgbi_ppm *,
struct cxgbi_task_tag_info *); struct cxgbi_task_tag_info *);
int (*csk_ddp_setup_digest)(struct cxgbi_sock *, int (*csk_ddp_setup_digest)(struct cxgbi_sock *,
unsigned int, int, int, int); unsigned int, int, int);
int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *, int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *,
unsigned int, int, bool); unsigned int, int);
void (*csk_release_offload_resources)(struct cxgbi_sock *); void (*csk_release_offload_resources)(struct cxgbi_sock *);
int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *); int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
......
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