diff options
author | Varun Prakash <varun@chelsio.com> | 2019-01-10 12:59:28 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-01-11 22:33:49 -0500 |
commit | 9e8f1c79831424d30c0e3df068be7f4a244157c9 (patch) | |
tree | 9b3157c61a9aa424ca35c610a38d43a7356e4409 | |
parent | 4a01ab60f55041b1ccc760e43258a5b3aeeca1bc (diff) |
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>
-rw-r--r-- | drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 9 | ||||
-rw-r--r-- | drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 28 | ||||
-rw-r--r-- | drivers/scsi/cxgbi/libcxgbi.c | 7 | ||||
-rw-r--r-- | drivers/scsi/cxgbi/libcxgbi.h | 5 |
4 files changed, 31 insertions, 18 deletions
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index 8a20411699d9..75e1273a44b3 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | |||
@@ -1144,7 +1144,7 @@ static void ddp_clear_map(struct cxgbi_device *cdev, struct cxgbi_ppm *ppm, | |||
1144 | } | 1144 | } |
1145 | 1145 | ||
1146 | static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, | 1146 | static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, |
1147 | unsigned int tid, int pg_idx, bool reply) | 1147 | unsigned int tid, int pg_idx) |
1148 | { | 1148 | { |
1149 | struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0, | 1149 | struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0, |
1150 | GFP_KERNEL); | 1150 | GFP_KERNEL); |
@@ -1160,7 +1160,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, | |||
1160 | req = (struct cpl_set_tcb_field *)skb->head; | 1160 | req = (struct cpl_set_tcb_field *)skb->head; |
1161 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 1161 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
1162 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); | 1162 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); |
1163 | req->reply = V_NO_REPLY(reply ? 0 : 1); | 1163 | req->reply = V_NO_REPLY(1); |
1164 | req->cpu_idx = 0; | 1164 | req->cpu_idx = 0; |
1165 | req->word = htons(31); | 1165 | req->word = htons(31); |
1166 | req->mask = cpu_to_be64(0xF0000000); | 1166 | req->mask = cpu_to_be64(0xF0000000); |
@@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, | |||
1177 | * @tid: connection id | 1177 | * @tid: connection id |
1178 | * @hcrc: header digest enabled | 1178 | * @hcrc: header digest enabled |
1179 | * @dcrc: data digest enabled | 1179 | * @dcrc: data digest enabled |
1180 | * @reply: request reply from h/w | ||
1181 | * set up the iscsi digest settings for a connection identified by tid | 1180 | * set up the iscsi digest settings for a connection identified by tid |
1182 | */ | 1181 | */ |
1183 | static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, | 1182 | static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, |
1184 | int hcrc, int dcrc, int reply) | 1183 | int hcrc, int dcrc) |
1185 | { | 1184 | { |
1186 | struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0, | 1185 | struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0, |
1187 | GFP_KERNEL); | 1186 | GFP_KERNEL); |
@@ -1197,7 +1196,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, | |||
1197 | req = (struct cpl_set_tcb_field *)skb->head; | 1196 | req = (struct cpl_set_tcb_field *)skb->head; |
1198 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 1197 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
1199 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); | 1198 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); |
1200 | req->reply = V_NO_REPLY(reply ? 0 : 1); | 1199 | req->reply = V_NO_REPLY(1); |
1201 | req->cpu_idx = 0; | 1200 | req->cpu_idx = 0; |
1202 | req->word = htons(31); | 1201 | req->word = htons(31); |
1203 | req->mask = cpu_to_be64(0x0F000000); | 1202 | req->mask = cpu_to_be64(0x0F000000); |
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 49f8028ac524..d26f50af00ea 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | |||
@@ -1548,16 +1548,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb) | |||
1548 | struct cxgbi_sock *csk; | 1548 | struct cxgbi_sock *csk; |
1549 | 1549 | ||
1550 | csk = lookup_tid(t, tid); | 1550 | csk = lookup_tid(t, tid); |
1551 | if (!csk) | 1551 | if (!csk) { |
1552 | pr_err("can't find conn. for tid %u.\n", tid); | 1552 | pr_err("can't find conn. for tid %u.\n", tid); |
1553 | return; | ||
1554 | } | ||
1553 | 1555 | ||
1554 | log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, | 1556 | log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, |
1555 | "csk 0x%p,%u,%lx,%u, status 0x%x.\n", | 1557 | "csk 0x%p,%u,%lx,%u, status 0x%x.\n", |
1556 | csk, csk->state, csk->flags, csk->tid, rpl->status); | 1558 | csk, csk->state, csk->flags, csk->tid, rpl->status); |
1557 | 1559 | ||
1558 | if (rpl->status != CPL_ERR_NONE) | 1560 | if (rpl->status != CPL_ERR_NONE) { |
1559 | pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n", | 1561 | pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n", |
1560 | csk, tid, rpl->status); | 1562 | csk, tid, rpl->status); |
1563 | csk->err = -EINVAL; | ||
1564 | } | ||
1565 | |||
1566 | complete(&csk->cmpl); | ||
1561 | 1567 | ||
1562 | __kfree_skb(skb); | 1568 | __kfree_skb(skb); |
1563 | } | 1569 | } |
@@ -1983,7 +1989,7 @@ static int ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbi_sock *csk, | |||
1983 | } | 1989 | } |
1984 | 1990 | ||
1985 | static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, | 1991 | static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, |
1986 | int pg_idx, bool reply) | 1992 | int pg_idx) |
1987 | { | 1993 | { |
1988 | struct sk_buff *skb; | 1994 | struct sk_buff *skb; |
1989 | struct cpl_set_tcb_field *req; | 1995 | struct cpl_set_tcb_field *req; |
@@ -1999,7 +2005,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid, | |||
1999 | req = (struct cpl_set_tcb_field *)skb->head; | 2005 | req = (struct cpl_set_tcb_field *)skb->head; |
2000 | INIT_TP_WR(req, csk->tid); | 2006 | INIT_TP_WR(req, csk->tid); |
2001 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid)); | 2007 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid)); |
2002 | req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid)); | 2008 | req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid)); |
2003 | req->word_cookie = htons(0); | 2009 | req->word_cookie = htons(0); |
2004 | req->mask = cpu_to_be64(0x3 << 8); | 2010 | req->mask = cpu_to_be64(0x3 << 8); |
2005 | req->val = cpu_to_be64(pg_idx << 8); | 2011 | 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, | |||
2008 | log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, | 2014 | log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, |
2009 | "csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx); | 2015 | "csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx); |
2010 | 2016 | ||
2017 | reinit_completion(&csk->cmpl); | ||
2011 | cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); | 2018 | cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); |
2012 | return 0; | 2019 | wait_for_completion(&csk->cmpl); |
2020 | |||
2021 | return csk->err; | ||
2013 | } | 2022 | } |
2014 | 2023 | ||
2015 | static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, | 2024 | static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, |
2016 | int hcrc, int dcrc, int reply) | 2025 | int hcrc, int dcrc) |
2017 | { | 2026 | { |
2018 | struct sk_buff *skb; | 2027 | struct sk_buff *skb; |
2019 | struct cpl_set_tcb_field *req; | 2028 | struct cpl_set_tcb_field *req; |
@@ -2031,7 +2040,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid, | |||
2031 | req = (struct cpl_set_tcb_field *)skb->head; | 2040 | req = (struct cpl_set_tcb_field *)skb->head; |
2032 | INIT_TP_WR(req, tid); | 2041 | INIT_TP_WR(req, tid); |
2033 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); | 2042 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); |
2034 | req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid)); | 2043 | req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid)); |
2035 | req->word_cookie = htons(0); | 2044 | req->word_cookie = htons(0); |
2036 | req->mask = cpu_to_be64(0x3 << 4); | 2045 | req->mask = cpu_to_be64(0x3 << 4); |
2037 | req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) | | 2046 | 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, | |||
2041 | log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, | 2050 | log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, |
2042 | "csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc); | 2051 | "csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc); |
2043 | 2052 | ||
2053 | reinit_completion(&csk->cmpl); | ||
2044 | cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); | 2054 | cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb); |
2045 | return 0; | 2055 | wait_for_completion(&csk->cmpl); |
2056 | |||
2057 | return csk->err; | ||
2046 | } | 2058 | } |
2047 | 2059 | ||
2048 | static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev) | 2060 | static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev) |
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 75f876409fb9..245742557c03 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c | |||
@@ -573,6 +573,7 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev) | |||
573 | skb_queue_head_init(&csk->receive_queue); | 573 | skb_queue_head_init(&csk->receive_queue); |
574 | skb_queue_head_init(&csk->write_queue); | 574 | skb_queue_head_init(&csk->write_queue); |
575 | timer_setup(&csk->retry_timer, NULL, 0); | 575 | timer_setup(&csk->retry_timer, NULL, 0); |
576 | init_completion(&csk->cmpl); | ||
576 | rwlock_init(&csk->callback_lock); | 577 | rwlock_init(&csk->callback_lock); |
577 | csk->cdev = cdev; | 578 | csk->cdev = cdev; |
578 | csk->flags = 0; | 579 | csk->flags = 0; |
@@ -2251,14 +2252,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn, | |||
2251 | if (!err && conn->hdrdgst_en) | 2252 | if (!err && conn->hdrdgst_en) |
2252 | err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid, | 2253 | err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid, |
2253 | conn->hdrdgst_en, | 2254 | conn->hdrdgst_en, |
2254 | conn->datadgst_en, 0); | 2255 | conn->datadgst_en); |
2255 | break; | 2256 | break; |
2256 | case ISCSI_PARAM_DATADGST_EN: | 2257 | case ISCSI_PARAM_DATADGST_EN: |
2257 | err = iscsi_set_param(cls_conn, param, buf, buflen); | 2258 | err = iscsi_set_param(cls_conn, param, buf, buflen); |
2258 | if (!err && conn->datadgst_en) | 2259 | if (!err && conn->datadgst_en) |
2259 | err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid, | 2260 | err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid, |
2260 | conn->hdrdgst_en, | 2261 | conn->hdrdgst_en, |
2261 | conn->datadgst_en, 0); | 2262 | conn->datadgst_en); |
2262 | break; | 2263 | break; |
2263 | case ISCSI_PARAM_MAX_R2T: | 2264 | case ISCSI_PARAM_MAX_R2T: |
2264 | return iscsi_tcp_set_max_r2t(conn, buf); | 2265 | return iscsi_tcp_set_max_r2t(conn, buf); |
@@ -2384,7 +2385,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session, | |||
2384 | 2385 | ||
2385 | ppm = csk->cdev->cdev2ppm(csk->cdev); | 2386 | ppm = csk->cdev->cdev2ppm(csk->cdev); |
2386 | err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid, | 2387 | err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid, |
2387 | ppm->tformat.pgsz_idx_dflt, 0); | 2388 | ppm->tformat.pgsz_idx_dflt); |
2388 | if (err < 0) | 2389 | if (err < 0) |
2389 | return err; | 2390 | return err; |
2390 | 2391 | ||
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 5d5d8b50d842..1917ff57651d 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h | |||
@@ -149,6 +149,7 @@ struct cxgbi_sock { | |||
149 | struct sk_buff_head receive_queue; | 149 | struct sk_buff_head receive_queue; |
150 | struct sk_buff_head write_queue; | 150 | struct sk_buff_head write_queue; |
151 | struct timer_list retry_timer; | 151 | struct timer_list retry_timer; |
152 | struct completion cmpl; | ||
152 | int err; | 153 | int err; |
153 | rwlock_t callback_lock; | 154 | rwlock_t callback_lock; |
154 | void *user_data; | 155 | void *user_data; |
@@ -490,9 +491,9 @@ struct cxgbi_device { | |||
490 | struct cxgbi_ppm *, | 491 | struct cxgbi_ppm *, |
491 | struct cxgbi_task_tag_info *); | 492 | struct cxgbi_task_tag_info *); |
492 | int (*csk_ddp_setup_digest)(struct cxgbi_sock *, | 493 | int (*csk_ddp_setup_digest)(struct cxgbi_sock *, |
493 | unsigned int, int, int, int); | 494 | unsigned int, int, int); |
494 | int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *, | 495 | int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *, |
495 | unsigned int, int, bool); | 496 | unsigned int, int); |
496 | 497 | ||
497 | void (*csk_release_offload_resources)(struct cxgbi_sock *); | 498 | void (*csk_release_offload_resources)(struct cxgbi_sock *); |
498 | int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *); | 499 | int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *); |