From a2a364bac43ecb8de78e8cf54a3fbc0562c102a2 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 15 May 2017 23:09:10 +0200 Subject: [PATCH] Bluetooth: controller: Fix DLE crossover assert When initiating Data Length Change at the same instant the crossover condition was not handled correctly causing the controller to assert. This fix will allow crossover of Data Length Update procedure, and this collison is harmless as per Bluetooth specification, and gracefully handled by the controller. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ctrl.c | 41 ++++++++++++++---------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index 92c95acd00e..7a6f3650edf 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -1583,30 +1583,35 @@ static inline u8_t isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx, eff_rx_octets = _radio.conn_curr->max_rx_octets; eff_tx_octets = _radio.conn_curr->max_tx_octets; - if (/* Local idle, and peer request; complete the peer procedure + if (/* Local idle, and Peer request then complete the Peer procedure * with response. */ ((_radio.conn_curr->llcp_length.req == _radio.conn_curr->llcp_length.ack) && - (PDU_DATA_LLCTRL_TYPE_LENGTH_REQ == - pdu_data_rx->payload.llctrl.opcode)) || - /* or Local has requested... */ + (pdu_data_rx->payload.llctrl.opcode == + PDU_DATA_LLCTRL_TYPE_LENGTH_REQ)) || + /* or Local has active... */ ((_radio.conn_curr->llcp_length.req != _radio.conn_curr->llcp_length.ack) && - /* and Local request, and peer request; override with peer - * procedure, and complete the peer procedure with response. + /* with Local requested and Peer request then complete the + * Peer procedure with response. */ - (((LLCP_LENGTH_STATE_REQ == _radio.conn_curr->llcp_length.state) && - (PDU_DATA_LLCTRL_TYPE_LENGTH_REQ == - pdu_data_rx->payload.llctrl.opcode)) || - /* and Local wait, and peer response; complete the - * local procedure. + ((((_radio.conn_curr->llcp_length.state == + LLCP_LENGTH_STATE_REQ) || + (_radio.conn_curr->llcp_length.state == + LLCP_LENGTH_STATE_ACK_WAIT)) && + (pdu_data_rx->payload.llctrl.opcode == + PDU_DATA_LLCTRL_TYPE_LENGTH_REQ)) || + /* with Local waiting for response, and Peer response then + * complete the Local procedure or Peer request then complete the + * Peer procedure with response. */ - ((LLCP_LENGTH_STATE_RSP_WAIT == - _radio.conn_curr->llcp_length.state) && - (PDU_DATA_LLCTRL_TYPE_LENGTH_RSP == - pdu_data_rx->payload.llctrl.opcode))))) { - + ((_radio.conn_curr->llcp_length.state == + LLCP_LENGTH_STATE_RSP_WAIT) && + ((pdu_data_rx->payload.llctrl.opcode == + PDU_DATA_LLCTRL_TYPE_LENGTH_RSP) || + (pdu_data_rx->payload.llctrl.opcode == + PDU_DATA_LLCTRL_TYPE_LENGTH_REQ)))))) { struct pdu_data_llctrl_length_req_rsp *lr; lr = (struct pdu_data_llctrl_length_req_rsp *) @@ -1684,7 +1689,9 @@ static inline u8_t isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx, *rx_enqueue = 1; } } else { - LL_ASSERT(0); + /* Drop response with no Local initiated request. */ + LL_ASSERT(pdu_data_rx->payload.llctrl.opcode == + PDU_DATA_LLCTRL_TYPE_LENGTH_RSP); } if ((PDU_DATA_LLCTRL_TYPE_LENGTH_REQ ==