@@ -9948,8 +9948,15 @@ static void prepare_pdu_data_tx(struct connection *conn,
99489948
99499949 if (!conn -> pkt_tx_ctrl &&
99509950 (conn -> pkt_tx_head != conn -> pkt_tx_data )) {
9951- conn -> pkt_tx_ctrl = conn -> pkt_tx_ctrl_last =
9952- conn -> pkt_tx_head ;
9951+ struct pdu_data * pdu_data_tx ;
9952+
9953+ pdu_data_tx = (void * )conn -> pkt_tx_head -> pdu_data ;
9954+ if ((pdu_data_tx -> ll_id != PDU_DATA_LLID_CTRL ) ||
9955+ (pdu_data_tx -> llctrl .opcode !=
9956+ PDU_DATA_LLCTRL_TYPE_ENC_REQ )) {
9957+ conn -> pkt_tx_ctrl = conn -> pkt_tx_ctrl_last =
9958+ conn -> pkt_tx_head ;
9959+ }
99539960 }
99549961 }
99559962
@@ -9970,8 +9977,9 @@ static void ctrl_tx_last_enqueue(struct connection *conn,
99709977 conn -> pkt_tx_ctrl_last = node_tx ;
99719978}
99729979
9973- static void ctrl_tx_enqueue (struct connection * conn ,
9974- struct radio_pdu_node_tx * node_tx )
9980+ static inline void ctrl_tx_pause_enqueue (struct connection * conn ,
9981+ struct radio_pdu_node_tx * node_tx ,
9982+ bool pause )
99759983{
99769984 /* check if a packet was tx-ed and not acked by peer */
99779985 if (
@@ -9999,9 +10007,27 @@ static void ctrl_tx_enqueue(struct connection *conn,
999910007 if (!conn -> pkt_tx_ctrl ) {
1000010008 node_tx -> next = conn -> pkt_tx_head -> next ;
1000110009 conn -> pkt_tx_head -> next = node_tx ;
10002- conn -> pkt_tx_ctrl = node_tx ;
10003- conn -> pkt_tx_ctrl_last = node_tx ;
10010+
10011+ /* If in Encryption Procedure, other control PDUs,
10012+ * Feature Rsp and Version Ind, are placed before data
10013+ * marker and after control last marker. Hence, if no
10014+ * control marker i.e. this is the first control PDU and
10015+ * to be paused, do not set the control marker. A valid
10016+ * control PDU in Encryption Procedure that is not
10017+ * implicitly paused, will set the control and control
10018+ * last marker.
10019+ */
10020+ if (!pause ) {
10021+ conn -> pkt_tx_ctrl = node_tx ;
10022+ conn -> pkt_tx_ctrl_last = node_tx ;
10023+ }
1000410024 } else {
10025+ /* ENC_REQ PDU is always allocated from data pool, hence
10026+ * the head can not have the control marker, and pause
10027+ * be true.
10028+ */
10029+ LL_ASSERT (!pause );
10030+
1000510031 ctrl_tx_last_enqueue (conn , node_tx );
1000610032 }
1000710033 } else {
@@ -10013,9 +10039,13 @@ static void ctrl_tx_enqueue(struct connection *conn,
1001310039 if (!conn -> pkt_tx_ctrl ) {
1001410040 node_tx -> next = conn -> pkt_tx_head ;
1001510041 conn -> pkt_tx_head = node_tx ;
10016- conn -> pkt_tx_ctrl = node_tx ;
10017- conn -> pkt_tx_ctrl_last = node_tx ;
10042+ if (!pause ) {
10043+ conn -> pkt_tx_ctrl = node_tx ;
10044+ conn -> pkt_tx_ctrl_last = node_tx ;
10045+ }
1001810046 } else {
10047+ LL_ASSERT (!pause );
10048+
1001910049 ctrl_tx_last_enqueue (conn , node_tx );
1002010050 }
1002110051 }
@@ -10026,19 +10056,54 @@ static void ctrl_tx_enqueue(struct connection *conn,
1002610056 }
1002710057}
1002810058
10059+ static void ctrl_tx_enqueue (struct connection * conn ,
10060+ struct radio_pdu_node_tx * node_tx )
10061+ {
10062+ ctrl_tx_pause_enqueue (conn , node_tx , false);
10063+ }
10064+
1002910065static void ctrl_tx_sec_enqueue (struct connection * conn ,
1003010066 struct radio_pdu_node_tx * node_tx )
1003110067{
1003210068 if (conn -> pause_tx ) {
1003310069 if (!conn -> pkt_tx_ctrl ) {
10070+ /* As data PDU tx is paused and no control PDU in queue,
10071+ * its safe to add new control PDU at head.
10072+ * Note, here the PDUs are stacked, not queued. Last In
10073+ * First Out.
10074+ */
1003410075 node_tx -> next = conn -> pkt_tx_head ;
1003510076 conn -> pkt_tx_head = node_tx ;
1003610077 } else {
10078+ /* As data PDU tx is paused and there are control PDUs
10079+ * in the queue, add it after control PDUs last marker
10080+ * and before the data start marker.
10081+ * Note, here the PDUs are stacked, not queued. Last In
10082+ * First Out.
10083+ */
1003710084 node_tx -> next = conn -> pkt_tx_ctrl_last -> next ;
1003810085 conn -> pkt_tx_ctrl_last -> next = node_tx ;
1003910086 }
1004010087 } else {
10041- ctrl_tx_enqueue (conn , node_tx );
10088+ bool pause = false;
10089+
10090+ /* check if Encryption Request is at head, it may have been
10091+ * transmitted and not ack-ed. Hence, enqueue this control PDU
10092+ * after control last marker and before data marker.
10093+ * This way it is paused until Encryption Setup completes.
10094+ */
10095+ if (conn -> pkt_tx_head ) {
10096+ struct pdu_data * pdu_data_tx ;
10097+
10098+ pdu_data_tx = (void * )conn -> pkt_tx_head -> pdu_data ;
10099+ if ((pdu_data_tx -> ll_id == PDU_DATA_LLID_CTRL ) &&
10100+ (pdu_data_tx -> llctrl .opcode ==
10101+ PDU_DATA_LLCTRL_TYPE_ENC_REQ )) {
10102+ pause = true;
10103+ }
10104+ }
10105+
10106+ ctrl_tx_pause_enqueue (conn , node_tx , pause );
1004210107 }
1004310108}
1004410109
0 commit comments