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 <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2017-05-15 23:09:10 +02:00 committed by Johan Hedberg
commit a2a364bac4

View file

@ -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 ==