scsi: cxgb4i: add wait_for_completion()
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>
This commit is contained in:
Родитель
4a01ab60f5
Коммит
9e8f1c7983
|
@ -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,
|
||||
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,
|
||||
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->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
|
||||
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->word = htons(31);
|
||||
req->mask = cpu_to_be64(0xF0000000);
|
||||
|
@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
|
|||
* @tid: connection id
|
||||
* @hcrc: header digest enabled
|
||||
* @dcrc: data digest enabled
|
||||
* @reply: request reply from h/w
|
||||
* 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,
|
||||
int hcrc, int dcrc, int reply)
|
||||
int hcrc, int dcrc)
|
||||
{
|
||||
struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
|
||||
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->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
|
||||
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->word = htons(31);
|
||||
req->mask = cpu_to_be64(0x0F000000);
|
||||
|
|
|
@ -1548,16 +1548,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
|
|||
struct cxgbi_sock *csk;
|
||||
|
||||
csk = lookup_tid(t, tid);
|
||||
if (!csk)
|
||||
if (!csk) {
|
||||
pr_err("can't find conn. for tid %u.\n", tid);
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
|
||||
"csk 0x%p,%u,%lx,%u, status 0x%x.\n",
|
||||
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",
|
||||
csk, tid, rpl->status);
|
||||
csk->err = -EINVAL;
|
||||
}
|
||||
|
||||
complete(&csk->cmpl);
|
||||
|
||||
__kfree_skb(skb);
|
||||
}
|
||||
|
@ -1983,7 +1989,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,
|
||||
int pg_idx, bool reply)
|
||||
int pg_idx)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct cpl_set_tcb_field *req;
|
||||
|
@ -1999,7 +2005,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
|
|||
req = (struct cpl_set_tcb_field *)skb->head;
|
||||
INIT_TP_WR(req, 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->mask = cpu_to_be64(0x3 << 8);
|
||||
req->val = cpu_to_be64(pg_idx << 8);
|
||||
|
@ -2008,12 +2014,15 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
|
|||
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);
|
||||
|
||||
reinit_completion(&csk->cmpl);
|
||||
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,
|
||||
int hcrc, int dcrc, int reply)
|
||||
int hcrc, int dcrc)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct cpl_set_tcb_field *req;
|
||||
|
@ -2031,7 +2040,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
|
|||
req = (struct cpl_set_tcb_field *)skb->head;
|
||||
INIT_TP_WR(req, 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->mask = cpu_to_be64(0x3 << 4);
|
||||
req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
|
||||
|
@ -2041,8 +2050,11 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
|
|||
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);
|
||||
|
||||
reinit_completion(&csk->cmpl);
|
||||
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)
|
||||
|
|
|
@ -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->write_queue);
|
||||
timer_setup(&csk->retry_timer, NULL, 0);
|
||||
init_completion(&csk->cmpl);
|
||||
rwlock_init(&csk->callback_lock);
|
||||
csk->cdev = cdev;
|
||||
csk->flags = 0;
|
||||
|
@ -2251,14 +2252,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
|
|||
if (!err && conn->hdrdgst_en)
|
||||
err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
|
||||
conn->hdrdgst_en,
|
||||
conn->datadgst_en, 0);
|
||||
conn->datadgst_en);
|
||||
break;
|
||||
case ISCSI_PARAM_DATADGST_EN:
|
||||
err = iscsi_set_param(cls_conn, param, buf, buflen);
|
||||
if (!err && conn->datadgst_en)
|
||||
err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
|
||||
conn->hdrdgst_en,
|
||||
conn->datadgst_en, 0);
|
||||
conn->datadgst_en);
|
||||
break;
|
||||
case ISCSI_PARAM_MAX_R2T:
|
||||
return iscsi_tcp_set_max_r2t(conn, buf);
|
||||
|
@ -2384,7 +2385,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
|
|||
|
||||
ppm = csk->cdev->cdev2ppm(csk->cdev);
|
||||
err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
|
||||
ppm->tformat.pgsz_idx_dflt, 0);
|
||||
ppm->tformat.pgsz_idx_dflt);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -149,6 +149,7 @@ struct cxgbi_sock {
|
|||
struct sk_buff_head receive_queue;
|
||||
struct sk_buff_head write_queue;
|
||||
struct timer_list retry_timer;
|
||||
struct completion cmpl;
|
||||
int err;
|
||||
rwlock_t callback_lock;
|
||||
void *user_data;
|
||||
|
@ -490,9 +491,9 @@ struct cxgbi_device {
|
|||
struct cxgbi_ppm *,
|
||||
struct cxgbi_task_tag_info *);
|
||||
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 *,
|
||||
unsigned int, int, bool);
|
||||
unsigned int, int);
|
||||
|
||||
void (*csk_release_offload_resources)(struct cxgbi_sock *);
|
||||
int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
|
||||
|
|
Загрузка…
Ссылка в новой задаче