Commit 8ad2a970 authored by Ayush Sawal's avatar Ayush Sawal Committed by Jakub Kicinski

cxgb4/chtls: Fix tid stuck due to wrong update of qid

TID stuck is seen when there is a race in
CPL_PASS_ACCEPT_RPL/CPL_ABORT_REQ and abort is arriving
before the accept reply, which sets the queue number.
In this case HW ends up sending CPL_ABORT_RPL_RSS to an
incorrect ingress queue.

V1->V2:
- Removed the unused variable len in chtls_set_quiesce_ctrl().

V2->V3:
- As kfree_skb() has a check for null skb, so removed this
check before calling kfree_skb() in func chtls_send_reset().

Fixes: cc35c88a ("crypto : chtls - CPL handler definition")
Signed-off-by: default avatarRohit Maheshwari <rohitm@chelsio.com>
Signed-off-by: default avatarAyush Sawal <ayush.sawal@chelsio.com>
Link: https://lore.kernel.org/r/20210112053600.24590-1-ayush.sawal@chelsio.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 7128c834
...@@ -40,6 +40,13 @@ ...@@ -40,6 +40,13 @@
#define TCB_L2T_IX_M 0xfffULL #define TCB_L2T_IX_M 0xfffULL
#define TCB_L2T_IX_V(x) ((x) << TCB_L2T_IX_S) #define TCB_L2T_IX_V(x) ((x) << TCB_L2T_IX_S)
#define TCB_T_FLAGS_W 1
#define TCB_T_FLAGS_S 0
#define TCB_T_FLAGS_M 0xffffffffffffffffULL
#define TCB_T_FLAGS_V(x) ((__u64)(x) << TCB_T_FLAGS_S)
#define TCB_FIELD_COOKIE_TFLAG 1
#define TCB_SMAC_SEL_W 0 #define TCB_SMAC_SEL_W 0
#define TCB_SMAC_SEL_S 24 #define TCB_SMAC_SEL_S 24
#define TCB_SMAC_SEL_M 0xffULL #define TCB_SMAC_SEL_M 0xffULL
......
...@@ -575,7 +575,11 @@ int send_tx_flowc_wr(struct sock *sk, int compl, ...@@ -575,7 +575,11 @@ int send_tx_flowc_wr(struct sock *sk, int compl,
void chtls_tcp_push(struct sock *sk, int flags); void chtls_tcp_push(struct sock *sk, int flags);
int chtls_push_frames(struct chtls_sock *csk, int comp); int chtls_push_frames(struct chtls_sock *csk, int comp);
int chtls_set_tcb_tflag(struct sock *sk, unsigned int bit_pos, int val); int chtls_set_tcb_tflag(struct sock *sk, unsigned int bit_pos, int val);
void chtls_set_tcb_field_rpl_skb(struct sock *sk, u16 word,
u64 mask, u64 val, u8 cookie,
int through_l2t);
int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 mode, int cipher_type); int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 mode, int cipher_type);
void chtls_set_quiesce_ctrl(struct sock *sk, int val);
void skb_entail(struct sock *sk, struct sk_buff *skb, int flags); void skb_entail(struct sock *sk, struct sk_buff *skb, int flags);
unsigned int keyid_to_addr(int start_addr, int keyid); unsigned int keyid_to_addr(int start_addr, int keyid);
void free_tls_keyid(struct sock *sk); void free_tls_keyid(struct sock *sk);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "chtls.h" #include "chtls.h"
#include "chtls_cm.h" #include "chtls_cm.h"
#include "clip_tbl.h" #include "clip_tbl.h"
#include "t4_tcb.h"
/* /*
* State transitions and actions for close. Note that if we are in SYN_SENT * State transitions and actions for close. Note that if we are in SYN_SENT
...@@ -267,7 +268,9 @@ static void chtls_send_reset(struct sock *sk, int mode, struct sk_buff *skb) ...@@ -267,7 +268,9 @@ static void chtls_send_reset(struct sock *sk, int mode, struct sk_buff *skb)
if (sk->sk_state != TCP_SYN_RECV) if (sk->sk_state != TCP_SYN_RECV)
chtls_send_abort(sk, mode, skb); chtls_send_abort(sk, mode, skb);
else else
goto out; chtls_set_tcb_field_rpl_skb(sk, TCB_T_FLAGS_W,
TCB_T_FLAGS_V(TCB_T_FLAGS_M), 0,
TCB_FIELD_COOKIE_TFLAG, 1);
return; return;
out: out:
...@@ -1949,6 +1952,8 @@ static void chtls_close_con_rpl(struct sock *sk, struct sk_buff *skb) ...@@ -1949,6 +1952,8 @@ static void chtls_close_con_rpl(struct sock *sk, struct sk_buff *skb)
else if (tcp_sk(sk)->linger2 < 0 && else if (tcp_sk(sk)->linger2 < 0 &&
!csk_flag_nochk(csk, CSK_ABORT_SHUTDOWN)) !csk_flag_nochk(csk, CSK_ABORT_SHUTDOWN))
chtls_abort_conn(sk, skb); chtls_abort_conn(sk, skb);
else if (csk_flag_nochk(csk, CSK_TX_DATA_SENT))
chtls_set_quiesce_ctrl(sk, 0);
break; break;
default: default:
pr_info("close_con_rpl in bad state %d\n", sk->sk_state); pr_info("close_con_rpl in bad state %d\n", sk->sk_state);
...@@ -2292,6 +2297,28 @@ static int chtls_wr_ack(struct chtls_dev *cdev, struct sk_buff *skb) ...@@ -2292,6 +2297,28 @@ static int chtls_wr_ack(struct chtls_dev *cdev, struct sk_buff *skb)
return 0; return 0;
} }
static int chtls_set_tcb_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
{
struct cpl_set_tcb_rpl *rpl = cplhdr(skb) + RSS_HDR;
unsigned int hwtid = GET_TID(rpl);
struct sock *sk;
sk = lookup_tid(cdev->tids, hwtid);
/* return EINVAL if socket doesn't exist */
if (!sk)
return -EINVAL;
/* Reusing the skb as size of cpl_set_tcb_field structure
* is greater than cpl_abort_req
*/
if (TCB_COOKIE_G(rpl->cookie) == TCB_FIELD_COOKIE_TFLAG)
chtls_send_abort(sk, CPL_ABORT_SEND_RST, NULL);
kfree_skb(skb);
return 0;
}
chtls_handler_func chtls_handlers[NUM_CPL_CMDS] = { chtls_handler_func chtls_handlers[NUM_CPL_CMDS] = {
[CPL_PASS_OPEN_RPL] = chtls_pass_open_rpl, [CPL_PASS_OPEN_RPL] = chtls_pass_open_rpl,
[CPL_CLOSE_LISTSRV_RPL] = chtls_close_listsrv_rpl, [CPL_CLOSE_LISTSRV_RPL] = chtls_close_listsrv_rpl,
...@@ -2304,5 +2331,6 @@ chtls_handler_func chtls_handlers[NUM_CPL_CMDS] = { ...@@ -2304,5 +2331,6 @@ chtls_handler_func chtls_handlers[NUM_CPL_CMDS] = {
[CPL_CLOSE_CON_RPL] = chtls_conn_cpl, [CPL_CLOSE_CON_RPL] = chtls_conn_cpl,
[CPL_ABORT_REQ_RSS] = chtls_conn_cpl, [CPL_ABORT_REQ_RSS] = chtls_conn_cpl,
[CPL_ABORT_RPL_RSS] = chtls_conn_cpl, [CPL_ABORT_RPL_RSS] = chtls_conn_cpl,
[CPL_FW4_ACK] = chtls_wr_ack, [CPL_FW4_ACK] = chtls_wr_ack,
[CPL_SET_TCB_RPL] = chtls_set_tcb_rpl,
}; };
...@@ -88,6 +88,24 @@ static int chtls_set_tcb_field(struct sock *sk, u16 word, u64 mask, u64 val) ...@@ -88,6 +88,24 @@ static int chtls_set_tcb_field(struct sock *sk, u16 word, u64 mask, u64 val)
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
void chtls_set_tcb_field_rpl_skb(struct sock *sk, u16 word,
u64 mask, u64 val, u8 cookie,
int through_l2t)
{
struct sk_buff *skb;
unsigned int wrlen;
wrlen = sizeof(struct cpl_set_tcb_field) + sizeof(struct ulptx_idata);
wrlen = roundup(wrlen, 16);
skb = alloc_skb(wrlen, GFP_KERNEL | __GFP_NOFAIL);
if (!skb)
return;
__set_tcb_field(sk, skb, word, mask, val, cookie, 0);
send_or_defer(sk, tcp_sk(sk), skb, through_l2t);
}
/* /*
* Set one of the t_flags bits in the TCB. * Set one of the t_flags bits in the TCB.
*/ */
...@@ -113,6 +131,29 @@ static int chtls_set_tcb_quiesce(struct sock *sk, int val) ...@@ -113,6 +131,29 @@ static int chtls_set_tcb_quiesce(struct sock *sk, int val)
TF_RX_QUIESCE_V(val)); TF_RX_QUIESCE_V(val));
} }
void chtls_set_quiesce_ctrl(struct sock *sk, int val)
{
struct chtls_sock *csk;
struct sk_buff *skb;
unsigned int wrlen;
int ret;
wrlen = sizeof(struct cpl_set_tcb_field) + sizeof(struct ulptx_idata);
wrlen = roundup(wrlen, 16);
skb = alloc_skb(wrlen, GFP_ATOMIC);
if (!skb)
return;
csk = rcu_dereference_sk_user_data(sk);
__set_tcb_field(sk, skb, 1, TF_RX_QUIESCE_V(1), 0, 0, 1);
set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
ret = cxgb4_ofld_send(csk->egress_dev, skb);
if (ret < 0)
kfree_skb(skb);
}
/* TLS Key bitmap processing */ /* TLS Key bitmap processing */
int chtls_init_kmap(struct chtls_dev *cdev, struct cxgb4_lld_info *lldi) int chtls_init_kmap(struct chtls_dev *cdev, struct cxgb4_lld_info *lldi)
{ {
......
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