@@ -9948,8 +9948,15 @@ static void prepare_pdu_data_tx(struct connection *conn,
9948
9948
9949
9949
if (!conn -> pkt_tx_ctrl &&
9950
9950
(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
+ }
9953
9960
}
9954
9961
}
9955
9962
@@ -9970,8 +9977,9 @@ static void ctrl_tx_last_enqueue(struct connection *conn,
9970
9977
conn -> pkt_tx_ctrl_last = node_tx ;
9971
9978
}
9972
9979
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 )
9975
9983
{
9976
9984
/* check if a packet was tx-ed and not acked by peer */
9977
9985
if (
@@ -9999,9 +10007,27 @@ static void ctrl_tx_enqueue(struct connection *conn,
9999
10007
if (!conn -> pkt_tx_ctrl ) {
10000
10008
node_tx -> next = conn -> pkt_tx_head -> next ;
10001
10009
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
+ }
10004
10024
} 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
+
10005
10031
ctrl_tx_last_enqueue (conn , node_tx );
10006
10032
}
10007
10033
} else {
@@ -10013,9 +10039,13 @@ static void ctrl_tx_enqueue(struct connection *conn,
10013
10039
if (!conn -> pkt_tx_ctrl ) {
10014
10040
node_tx -> next = conn -> pkt_tx_head ;
10015
10041
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
+ }
10018
10046
} else {
10047
+ LL_ASSERT (!pause );
10048
+
10019
10049
ctrl_tx_last_enqueue (conn , node_tx );
10020
10050
}
10021
10051
}
@@ -10026,19 +10056,54 @@ static void ctrl_tx_enqueue(struct connection *conn,
10026
10056
}
10027
10057
}
10028
10058
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
+
10029
10065
static void ctrl_tx_sec_enqueue (struct connection * conn ,
10030
10066
struct radio_pdu_node_tx * node_tx )
10031
10067
{
10032
10068
if (conn -> pause_tx ) {
10033
10069
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
+ */
10034
10075
node_tx -> next = conn -> pkt_tx_head ;
10035
10076
conn -> pkt_tx_head = node_tx ;
10036
10077
} 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
+ */
10037
10084
node_tx -> next = conn -> pkt_tx_ctrl_last -> next ;
10038
10085
conn -> pkt_tx_ctrl_last -> next = node_tx ;
10039
10086
}
10040
10087
} 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 );
10042
10107
}
10043
10108
}
10044
10109
0 commit comments