Bluetooth: controller: split: Fix enc procedure reject handling

This is a port of the commit 4135fb55f1 ("Bluetooth:
controller: Fix rejected enc procedure not terminated") and
commit 4d59ef306b ("Bluetooth: controller: Check if enc
procedure is in progress").

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2019-10-29 16:00:58 +05:30 committed by Carles Cufí
commit f344516a0b

View file

@ -4061,7 +4061,7 @@ static int reject_ext_ind_send(struct ll_conn *conn, struct node_rx_pdu *rx,
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ || PHY */
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
static inline void reject_ind_conn_upd_recv(struct ll_conn *conn,
static inline int reject_ind_conn_upd_recv(struct ll_conn *conn,
struct node_rx_pdu *rx,
struct pdu_data *pdu_rx)
{
@ -4069,13 +4069,9 @@ static inline void reject_ind_conn_upd_recv(struct ll_conn *conn,
struct node_rx_cu *cu;
struct lll_conn *lll;
rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
if (rej_ext_ind->reject_opcode != PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ) {
goto reject_ind_conn_upd_recv_exit;
}
/* Unsupported remote feature */
lll = &conn->lll;
rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
if (!lll->role && (rej_ext_ind->error_code ==
BT_HCI_ERR_UNSUPP_REMOTE_FEATURE)) {
LL_ASSERT(conn->llcp_req == conn->llcp_ack);
@ -4094,7 +4090,7 @@ static inline void reject_ind_conn_upd_recv(struct ll_conn *conn,
conn->llcp_type = LLCP_CONN_UPD;
conn->llcp_ack -= 2U;
goto reject_ind_conn_upd_recv_exit;
return -EINVAL;
}
/* FIXME: handle unsupported LL parameters error */
else if (rej_ext_ind->error_code != BT_HCI_ERR_LL_PROC_COLLISION) {
@ -4122,7 +4118,7 @@ static inline void reject_ind_conn_upd_recv(struct ll_conn *conn,
/* skip event generation if not cmd initiated */
if (!conn->llcp_conn_param.cmd) {
goto reject_ind_conn_upd_recv_exit;
return -EINVAL;
}
/* generate conn update complete event with error code */
@ -4136,23 +4132,14 @@ static inline void reject_ind_conn_upd_recv(struct ll_conn *conn,
cu->timeout = conn->supervision_reload *
lll->interval * 125U / 1000;
return;
reject_ind_conn_upd_recv_exit:
/* Mark for buffer for release */
rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
return 0;
}
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
static inline void reject_ind_dle_recv(struct ll_conn *conn,
struct node_rx_pdu *rx,
static inline int reject_ind_dle_recv(struct ll_conn *conn,
struct pdu_data *pdu_rx)
{
struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
if (rej_ext_ind->reject_opcode == PDU_DATA_LLCTRL_TYPE_LENGTH_REQ) {
struct pdu_data_llctrl_length_req *lr;
/* Procedure complete */
@ -4177,23 +4164,16 @@ static inline void reject_ind_dle_recv(struct ll_conn *conn,
lr->max_tx_time = sys_cpu_to_le16(conn->lll.max_tx_time);
#endif /* CONFIG_BT_CTLR_PHY */
return;
}
/* Mark for buffer for release */
rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
return 0;
}
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
#if defined(CONFIG_BT_CTLR_PHY)
static inline void reject_ind_phy_upd_recv(struct ll_conn *conn,
static inline int reject_ind_phy_upd_recv(struct ll_conn *conn,
struct node_rx_pdu *rx,
struct pdu_data *pdu_rx)
{
struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
if (rej_ext_ind->reject_opcode == PDU_DATA_LLCTRL_TYPE_PHY_REQ) {
struct node_rx_pu *p;
/* Same Procedure or Different Procedure Collision */
@ -4201,13 +4181,14 @@ static inline void reject_ind_phy_upd_recv(struct ll_conn *conn,
/* If not same procedure, stop procedure timeout, else
* continue timer until phy upd ind is received.
*/
rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
if (rej_ext_ind->error_code != BT_HCI_ERR_LL_PROC_COLLISION) {
/* Procedure complete */
conn->llcp_phy.ack = conn->llcp_phy.req;
conn->llcp_phy.pause_tx = 0U;
/* Reset packet timing restrictions */
conn->lll.phy_tx_time = conn->lll.phy_tx;
conn->llcp_phy.pause_tx = 0U;
/* Stop procedure timeout */
conn->procedure_expire = 0U;
@ -4215,7 +4196,7 @@ static inline void reject_ind_phy_upd_recv(struct ll_conn *conn,
/* skip event generation if not cmd initiated */
if (!conn->llcp_phy.cmd) {
goto reject_ind_phy_upd_recv_exit;
return -EINVAL;
}
/* generate phy update complete event with error code */
@ -4226,42 +4207,18 @@ static inline void reject_ind_phy_upd_recv(struct ll_conn *conn,
p->tx = conn->lll.phy_tx;
p->rx = conn->lll.phy_rx;
return;
}
reject_ind_phy_upd_recv_exit:
/* Mark for buffer for release */
rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
return 0;
}
#endif /* CONFIG_BT_CTLR_PHY */
static void reject_ext_ind_recv(struct ll_conn *conn, struct node_rx_pdu *rx,
struct pdu_data *pdu_rx)
{
if (0) {
#if defined(CONFIG_BT_CTLR_PHY)
} else if (conn->llcp_phy.ack != conn->llcp_phy.req) {
reject_ind_phy_upd_recv(conn, rx, pdu_rx);
#endif /* CONFIG_BT_CTLR_PHY */
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
} else if (conn->llcp_conn_param.ack != conn->llcp_conn_param.req) {
reject_ind_conn_upd_recv(conn, rx, pdu_rx);
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
} else if (conn->llcp_length.ack != conn->llcp_length.req) {
reject_ind_dle_recv(conn, rx, pdu_rx);
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
#if defined(CONFIG_BT_CTLR_LE_ENC)
} else {
static inline int reject_ind_enc_recv(struct ll_conn *conn,
struct pdu_data *pdu_rx)
{
struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
switch (rej_ext_ind->reject_opcode) {
case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
/* resume data packet rx and tx */
conn->llcp_enc.pause_rx = 0U;
conn->llcp_enc.pause_tx = 0U;
@ -4272,18 +4229,62 @@ static void reject_ext_ind_recv(struct ll_conn *conn, struct node_rx_pdu *rx,
/* enqueue as if it were a reject ind */
pdu_rx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_IND;
pdu_rx->llctrl.reject_ind.error_code =
rej_ext_ind->error_code;
break;
pdu_rx->llctrl.reject_ind.error_code = rej_ext_ind->error_code;
default:
/* Ignore */
/* Mark for buffer for release */
rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
break;
return 0;
}
#endif /* CONFIG_BT_CTLR_LE_ENC */
static inline void reject_ext_ind_recv(struct ll_conn *conn,
struct node_rx_pdu *rx,
struct pdu_data *pdu_rx)
{
struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
int err = -EINVAL;
rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
switch (rej_ext_ind->reject_opcode) {
#if defined(CONFIG_BT_CTLR_LE_ENC)
case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
if ((conn->llcp_ack != conn->llcp_req) &&
(conn->llcp_type == LLCP_ENCRYPTION)) {
err = reject_ind_enc_recv(conn, pdu_rx);
}
break;
#endif /* CONFIG_BT_CTLR_LE_ENC */
#if defined(CONFIG_BT_CTLR_PHY)
case PDU_DATA_LLCTRL_TYPE_PHY_REQ:
if (conn->llcp_phy.ack != conn->llcp_phy.req) {
err = reject_ind_phy_upd_recv(conn, rx, pdu_rx);
}
break;
#endif /* CONFIG_BT_CTLR_PHY */
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
case PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ:
if (conn->llcp_conn_param.ack != conn->llcp_conn_param.req) {
err = reject_ind_conn_upd_recv(conn, rx, pdu_rx);
}
break;
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
case PDU_DATA_LLCTRL_TYPE_LENGTH_REQ:
if (conn->llcp_length.ack != conn->llcp_length.req) {
err = reject_ind_dle_recv(conn, pdu_rx);
}
break;
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
default:
/* Ignore */
break;
}
if (err) {
/* Mark for buffer for release */
rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
}
}