scsi: cxgb4i: add wait_for_completion()
[ Upstream commit 9e8f1c79831424d30c0e3df068be7f4a244157c9 ] 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: Varun Prakash <varun@chelsio.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
b2ae824798
commit
4c3b23e903
@@ -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,
|
|||||||
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,
|
|||||||
* @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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
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 *);
|
||||||
|
|||||||
Reference in New Issue
Block a user