# TX_AGG
[TX]

TX Aggregation specific functions. More...

Collaboration diagram for TX_AGG:

## Data Structures
struct | tx_agg_desc
| Aggregation descriptor, containing AMPDU THD, BAR descriptor, BAR payload and Policy Table. More...
## Defines
#define | TX_SEC_IRQ_BITS_MERGED
| Bits indicating activity on secondary users (merged trigger and buffer).
#define | MU_AMPDU_CLOSE()
| Operations performed upon the closure of a MU-MIMO A-MPDU during A-MPDU formation.
#define | VHT_BW 4
| Number of BW configurations in VHT.
#define | VHT_MCS 10
| Number of MCS in VHT.
#define | TX_MIN_AMPDU_NB_PER_AC (3 * RW_USER_MAX)
| Minimum of A-MPDU descriptors per queue.
#define | TX_AGG_DIVIDER (8 / RW_USER_MAX)
| Number of TX descriptors for 1 AGG descriptor.
#define | TX_MAX_AMPDU_NB_PER_AC0 TX_MIN_AMPDU_NB_PER_AC
| Max number of AMPDU descriptors for the BK queue.
#define | TX_MAX_AMPDU_NB_PER_AC1 TX_MIN_AMPDU_NB_PER_AC
| Max number of AMPDU descriptors for the BE queue.
#define | TX_MAX_AMPDU_NB_PER_AC2 TX_MIN_AMPDU_NB_PER_AC
| Max number of AMPDU descriptors for the VI queue.
#define | TX_MAX_AMPDU_NB_PER_AC3 TX_MIN_AMPDU_NB_PER_AC
| Max number of AMPDU descriptors for the VO queue.
#define | TX_MAX_AMPDU_NB_PER_AC4 TX_MIN_AMPDU_NB_PER_AC
| Max number of AMPDU descriptors for the BCN queue.
#define | TX_AMPDU_DESC_QUEUE_CNT (NX_TXQ_CNT + NX_MAC_HE)
| Number of A-MPDU descriptor queues.
## Functions
static bool | txl_desc_is_agg (struct txdesc *txdesc, struct tx_agg_desc *agg_desc)
| Check if a txdesc can be aggregated in an AMPDU.
static bool | txl_ampdu_has_ht_vht_rate (struct txdesc *txdesc)
| Check if the phy_flags in TX descriptor indicate a HT or VHT rate, that would allow aggregation.
static uint32_t | txl_vht_idx_to_32us_len_get (int base_idx, uint8_t bw)
| Get the 32us length from the HT/VHT table for a given base index, bw pair.
static uint16_t | txl_vht_idx_to_1us_len_get (int base_idx, uint8_t bw)
| Get the 1us length from the HT/VHT table for a given base index, bw pair.
static int | txl_ht_vht_ampdu_param_get (struct txdesc *txdesc, uint8_t format_mod, uint32_t *max_len_sta, uint32_t *nss)
| Compute the base rate index that should be used to compute the Maximum PHY length of the HT/VHT A-MPDU and the minimum A-MPDU subframe length.
static void | txl_ampdu_constraints_get (struct txdesc *txdesc, uint8_t ac, struct txl_agg_build_tag *agg)
| Calculate number of blank delimiters to ensure MMSS after a txdesc This number will be set in the THD of the NEXT txdesc in AMPDU.
static void | txl_fill_bar (struct tx_agg_desc *agg_desc, uint16_t sn, uint8_t staid, uint8_t tid, uint8_t bw)
| Fill BAR frame (THD and payload).
static void | txl_agg_hwdesc_init (void)
| Initialize Hardware TX descriptors for A-MPDU.
static void | txl_agg_hwdesc_reset (void)
| Reset all hardware TX descriptor for A-MPDU.
static void | txl_mumimo_convert (uint8_t ac, uint8_t user_pos)
| Convert a MU-MIMO A-MPDU or MPDU into a SU one.
static uint32_t | txl_mumimo_duration_ns (uint32_t length, uint8_t mcs, bool sgi, uint8_t bw, uint8_t nss)
| Compute the duration of the data part of a MU-MIMO A-MPDU.
static void | txl_mumimo_ampdu_finish (uint8_t ac, uint8_t user_pos)
| Terminates the MU-MIMO A-MPDU under construction.
static int | txl_mumimo_check (struct txdesc *txdesc, uint8_t ac, uint8_t *user_pos)
| This function checks if the newly pushed TX descriptor can be part of a MU-MIMO PPDU under construction, or if it can start a new MU-MIMO PPDU.
static void | txl_mumimo_secondary_done (uint8_t access_category, uint8_t user_idx)
| Unchains the frame exchanges that have been completed.
## Variables
const uint8_t | TX_VHT_RATE_TO_MIN_SEP [10 *4 *2]
| Table linking HT or VHT MCS+GI+BW to minimum number of bytes for 1us min MPDU start spacing in AMPDU Index of the table is (MCS_IDX << 3) | (BW << 1) | (GI_400) where BW is 0 for 20 MHz, 1 for 40MHz and 2 for 80MHz GI_400 is 1 if packet is being sent with 400ns GI, 0 if 800ns GI.
const uint16_t | TX_VHT_RATE_TO_32US_LEN [10 *4 *2]
| Table linking HT or VHT MCS+GI+BW to the number of bytes transmitted in 32us Index of the table is (MCS_IDX << 3) | (BW << 1) | (GI_400) where BW is 0 for 20 MHz, 1 for 40MHz and 2 for 80MHz GI_400 is 1 if packet is being sent with 400ns GI, 0 if 800ns GI.
const uint16_t | VHT_NDBPS [VHT_BW][VHT_MCS]
| IEEE P802.11ac D3.0 Chptr 22.5 Parameters for VHT MCSs Note that some BW, MCS, NSS combinations are not allowed (e.g 20MHz, MCS9, NSS 1,2) The NDBPS value given for MCS9 20MHz is for NSS=3.
static struct tx_agg_desc | tx_agg_desc_array0 [TX_MAX_AMPDU_NB_PER_AC0]
| Array of aggregation descriptors for the BK queue.
static struct tx_agg_desc | tx_agg_desc_array1 [TX_MAX_AMPDU_NB_PER_AC1]
| Array of aggregation descriptors for the BE queue.
static struct tx_agg_desc | tx_agg_desc_array2 [TX_MAX_AMPDU_NB_PER_AC2]
| Array of aggregation descriptors for the VI queue.
static struct tx_agg_desc | tx_agg_desc_array3 [TX_MAX_AMPDU_NB_PER_AC3]
| Array of aggregation descriptors for the VO queue.
static struct tx_agg_desc | tx_agg_desc_array4 [TX_MAX_AMPDU_NB_PER_AC4]
| Array of aggregation descriptors for the BCN queue.
static struct tx_agg_desc *const | tx_agg_desc_array [TX_AMPDU_DESC_QUEUE_CNT]
| Table of pointers to the different aggregation descriptor arrays.
static const int | tx_agg_desc_cnt [TX_AMPDU_DESC_QUEUE_CNT]
| Number of aggregation descriptor per queue.
struct co_list | tx_agg_desc_pool [TX_AMPDU_DESC_QUEUE_CNT]
| Per-ac pools of free aggregation descriptors.
struct co_list | tx_agg_desc_pool []
| Per-ac pools of free aggregation descriptors.
## External API
void | txl_agg_mumimo_close (uint8_t ac)
| Terminates the MU-MIMO PPDU.
uint16_t | txl_agg_mpdu_nb_delims (struct tx_hd *thd, uint16_t mmss_bytes)
| Calculate number of blank delimiters to ensure MMSS after a THD This number will be set in the THD of the NEXT txdesc in AMPDU.
void | txl_agg_init (void)
| Initializes the TX aggregation module.
void | txl_agg_reset (void)
| Reset the TX aggregation module.
void | txl_agg_finish (uint8_t ac)
| Terminates the non MU-MIMO A-MPDU under construction This function can be called in several cases: The new TX descriptor pushed is not compliant with the current A-MPDU The length of the current A-MPDU has reached the limit The number of MPDUs in the current A-MPDU has reached the limit The TX queue will become empty and new data shall be programmed for transmission.
int | txl_agg_push_mpdu (struct txdesc *txdesc, uint8_t ac)
| Try and aggregate txdesc, several checks are made, when they fail the MPDU goes on to be downloaded as a normal singleton MPDU.
void | txl_agg_release (struct tx_agg_desc *agg_desc)
| Release all AMPDU related space: BA, BAR, aggregate control and its AMPDU THD.
struct tx_hd * | txl_agg_change_to_singleton (struct txdesc *txdesc, bool he_tb)
| Transform a MPDU part of an A-MPDU into a singleton MPDU.
void | txl_agg_bw_drop_handle (uint8_t access_category)
| Handler of the HW BW drop mechanism interrupt Based on the actual BW of transmission, this function cuts the A-MPDU under transmission and chains the following MPDUs as singleton.
void | txl_agg_check (uint8_t access_category)
| Check if there is an A-MPDU under construction and if the TX queue is empty.
void | txl_agg_sec_transmit_trigger (void)
| Process secondary user events of the MACTX IRQ.
void | txl_agg_set_ampdu_protection (uint32_t *rc)
| Add Self-CTS protection to the A-MPDU.
void | txl_agg_check_rtscts_retry_limit (struct tx_hd *a_thd, uint8_t access_category)
| Check if the current A-MPDU header descriptor indicates that the RTS/CTS retry limit has been reached.
void | txl_agg_check_saved_agg_desc (uint8_t access_category)
| Check if an A-MPDU descriptor is currently saved and free it.
__INLINE bool | is_mpdu_agg (struct txdesc *txdesc)
| Return boolean corresponding to MPDU being aggregatable or not.
__INLINE bool | is_mpdu_first (struct txdesc *txdesc)
| Return boolean corresponding to MPDU being first in an AMPDU or not.
__INLINE bool | is_mpdu_interm (struct txdesc *txdesc)
| Return boolean corresponding to MPDU being intermediate in an AMPDU or not.
__INLINE bool | is_mpdu_last (struct txdesc *txdesc)
| Return boolean corresponding to MPDU being last in an AMPDU or not.
__INLINE bool | is_mpdu_unpos (struct txdesc *txdesc)
| Return boolean corresponding to MPDU having no position in an AMPDU yet (inherent check for aggregatable too).
__INLINE void | set_mpdu_pos (struct txdesc *txdesc, uint32_t pos)
| Set position of MPDU inside an AMPDU.
__INLINE uint16_t | txl_mpdu_subframe_len (struct tx_hd *thd)
| Calculate AMPDU subframe length for an MPDU (without blank delimiters).
__INLINE bool | is_in_mumimo_ppdu (struct txdesc *txdesc)
| Return a boolean indicating if the MPDU is part of a MU-MIMO PPDU.
__INLINE bool | is_primary_user (struct txdesc *txdesc)
| Return a boolean indicating if the MPDU is part of the A-MPDU sent on the primary HW queue.
__INLINE bool | is_mumimo_group_id (uint8_t group_id)
| Return a boolean indicating if the GroupID passed as parameter is a MU-MIMO one.
__INLINE uint8_t | get_group_id (struct txdesc *txdesc)
| Return the MU-MIMO GroupId from the TX descriptor.
__INLINE uint8_t | get_user_pos (struct txdesc *txdesc)
| Return the MU-MIMO User Position from the TX descriptor.
__INLINE struct tx_agg_desc * | txl_agg_desc_alloc (uint8_t access_category)
| Get a free aggregation descriptor structure from the free pool.
__INLINE void | txl_agg_desc_free (struct tx_agg_desc *agg_desc)
| Free a used aggregation descriptor structure.

## Detailed Description

TX Aggregation specific functions.

## Define Documentation

#define MU_AMPDU_CLOSE | ( |  | ) |

Value:

    {                                                                                        \
        txl_mumimo_ampdu_finish(ac, user_pos);                                               \
        /* Check if the other user positions are still open */                               \
        if (txlist->mumimo.open & txlist->mumimo.users)                                      \
        {                                                                                    \
            /* We could still receive packets on other user positions, */                    \
            /* so save the current packet */                                                 \
            ASSERT_ERR(txlist->mumimo.txdesc[user_pos] == NULL);                             \
            txlist->mumimo.txdesc[user_pos] = txdesc;                                        \
            status = MU_PAUSED;                                                              \
            break;                                                                           \
        }                                                                                    \
        else                                                                                 \
        {                                                                                    \
            /* Close the MU-MIMO PPDU under construction */                                  \
            txl_agg_mumimo_close(ac);                                                        \
                                                                                             \
            /* Start a new MU-MIMO PPDU */                                                   \
            continue;                                                                        \
        }                                                                                    \
    }

Operations performed upon the closure of a MU-MIMO A-MPDU during A-MPDU formation.

Definition at line 89 of file txl_agg.c.

#define TX_SEC_IRQ_BITS_MERGED

Value:

    ( NXMAC_SEC_U_3AC_3_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_3AC_2_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_3AC_1_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_3AC_0_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_2AC_3_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_2AC_2_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_2AC_1_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_2AC_0_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_1AC_3_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_1AC_2_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_1AC_1_TX_TRIGGER_BIT     |                 \
                                      NXMAC_SEC_U_1AC_0_TX_TRIGGER_BIT )

Bits indicating activity on secondary users (merged trigger and buffer).

Definition at line 75 of file txl_agg.c.

## Function Documentation

__INLINE uint8_t get_group_id | ( | struct txdesc * | txdesc | ) |

Return the MU-MIMO GroupId from the TX descriptor.

Parameters:

  `[in]` | txdesc | Pointer to the TX descriptor

Returns:
  The MU-MIMO GroupId included in the TX descriptor

Definition at line 267 of file txl_agg.h.

References txdesc::host, and hostdesc::mumimo_info.

Referenced by txl_mumimo_check().

__INLINE uint8_t get_user_pos | ( | struct txdesc * | txdesc | ) |

Return the MU-MIMO User Position from the TX descriptor.

Parameters:

  `[in]` | txdesc | Pointer to the TX descriptor

Returns:
  The MU-MIMO GroupId included in the TX descriptor

Definition at line 282 of file txl_agg.h.

References txdesc::host, and hostdesc::mumimo_info.

Referenced by macif_tx_cfm_push(), txl_frame_exchange_done(), txl_mumimo_check(), and txl_mumimo_secondary_done().

__INLINE bool is_in_mumimo_ppdu | ( | struct txdesc * | txdesc | ) |

Return a boolean indicating if the MPDU is part of a MU-MIMO PPDU.

Parameters:

  `[in]` | txdesc | Pointer to the MPDU TX descriptor

Returns:
  true if MPDU is part of a MU-MIMO PPDU, false otherwise

Definition at line 223 of file txl_agg.h.

References lmacdesc::agg_desc, txdesc::lmac, and tx_agg_desc::prim_agg_desc.

Referenced by bfr_is_frame_bf_compliant(), txl_frame_exchange_manage(), and txl_hwdesc_config_post().

__INLINE bool is_mpdu_agg | ( | struct txdesc * | txdesc | ) |

Return boolean corresponding to MPDU being aggregatable or not.

Parameters:

  `[in]` | txdesc | Txdesc pointer to access its flags elements.

Returns:
  Boolean True if MPDU is aggregatable and false otherwise

Definition at line 131 of file txl_agg.h.

References AMPDU_BIT, umacdesc::flags, and txdesc::umac.

Referenced by bfr_is_frame_bf_compliant(), txl_buffer_update_thd(), txl_cfm_push(), txl_desc_is_agg(), txl_frame_exchange_done(), txl_frame_exchange_manage(), txl_hwdesc_config_post(), txl_mumimo_check(), and txl_mumimo_convert().

__INLINE bool is_mpdu_first | ( | struct txdesc * | txdesc | ) |

Return boolean corresponding to MPDU being first in an AMPDU or not.

Parameters:

  `[in]` | txdesc | Txdesc pointer to access its flags elements.

Returns:
  Boolean True if MPDU is first in the AMPDU and false otherwise

Definition at line 143 of file txl_agg.h.

References umacdesc::flags, txdesc::umac, WHICHDESC_AMPDU_FIRST, and WHICHDESC_MSK.

Referenced by bfr_is_frame_bf_compliant(), txl_cfm_evt(), txl_desc_is_agg(), txl_frame_exchange_done(), and txl_hwdesc_config_post().

__INLINE bool is_mpdu_interm | ( | struct txdesc * | txdesc | ) |

Return boolean corresponding to MPDU being intermediate in an AMPDU or not.

Parameters:

  `[in]` | txdesc | Txdesc pointer to access its flags elements.

Returns:
  Boolean True if MPDU is intermediate in the AMPDU and false otherwise

Definition at line 155 of file txl_agg.h.

References umacdesc::flags, txdesc::umac, WHICHDESC_AMPDU_INT, and WHICHDESC_MSK.

__INLINE bool is_mpdu_last | ( | struct txdesc * | txdesc | ) |

Return boolean corresponding to MPDU being last in an AMPDU or not.

Parameters:

  `[in]` | txdesc | Txdesc pointer to access its flags elements.

Returns:
  Boolean True if MPDU is last in the AMPDU and false otherwise

Definition at line 167 of file txl_agg.h.

References umacdesc::flags, txdesc::umac, WHICHDESC_AMPDU_LAST, and WHICHDESC_MSK.

Referenced by txl_buffer_update_tbd(), txl_buffer_update_thd(), txl_cfm_evt(), and txl_frame_exchange_done().

__INLINE bool is_mpdu_unpos | ( | struct txdesc * | txdesc | ) |

Return boolean corresponding to MPDU having no position in an AMPDU yet (inherent check for aggregatable too).

Parameters:

  `[in]` | txdesc | Txdesc pointer to access its flags elements.

Returns:
  Boolean True if MPDU has no position in AMPDU, false otherwise

Definition at line 180 of file txl_agg.h.

References umacdesc::flags, txdesc::umac, WHICHDESC_AMPDU_EXTRA, and WHICHDESC_MSK.

__INLINE bool is_mumimo_group_id | ( | uint8_t | group_id | ) |

Return a boolean indicating if the GroupID passed as parameter is a MU-MIMO one.

Parameters:

  `[in]` | group_id | GroupID to be checked

Returns:
  true if the GroupId is a MU-MIMO one, false otherwise

Definition at line 253 of file txl_agg.h.

Referenced by txl_mumimo_check().

__INLINE bool is_primary_user | ( | struct txdesc * | txdesc | ) |

Return a boolean indicating if the MPDU is part of the A-MPDU sent on the primary HW queue.

Note:
  This function assumes that the MPDU is sent as part of a MU-MIMO PPDU

Parameters:

  `[in]` | txdesc | Pointer to the MPDU TX descriptor

Returns:
  true if MPDU is part of the primary MU-MIMO PPDU, false otherwise

Definition at line 239 of file txl_agg.h.

References lmacdesc::agg_desc, txdesc::lmac, and tx_agg_desc::prim_agg_desc.

Referenced by txl_hwdesc_config_post().

__INLINE void set_mpdu_pos | ( | struct txdesc * | txdesc,
|  | uint32_t | pos |
| ) |  |  |

Set position of MPDU inside an AMPDU.

Parameters:

  `[in]` | txdesc | Txdesc pointer to modify its flags elements.
  `[in]` | pos | Which Descriptor value for the position in AMPDU - see hal_desc.h

Returns:
  Boolean True if MPDU is aggregatable and false otherwise

Definition at line 196 of file txl_agg.h.

References AMPDU_BIT, umacdesc::flags, txdesc::umac, and WHICHDESC_MSK.

Referenced by txl_mumimo_ampdu_finish().

void txl_agg_bw_drop_handle | ( | uint8_t | access_category | ) |

Handler of the HW BW drop mechanism interrupt Based on the actual BW of transmission, this function cuts the A-MPDU under transmission and chains the following MPDUs as singleton.

Parameters:

  `[in]` | access_category | Access category of the ongoing transmission

struct tx_hd * txl_agg_change_to_singleton | ( | struct txdesc * | txdesc,
|  | bool | he_tb |
| ) |  |  | `[read]`

Transform a MPDU part of an A-MPDU into a singleton MPDU.

This feature is used both for the BW drop and for the HE Trigger-Based transmissions.

Parameters:

  `[in]` | txdesc | Descriptor of the MPDU to be changed into singleton
  `[in]` | he_tb | Flag indicating whether the MPDU will be sent as a HE TB PPDU or not

Returns:
  The pointer to the THD of the MPDU, if the MPDU buffer is already allocated. NULL otherwise.

void txl_agg_check | ( | uint8_t | access_category | ) |

Check if there is an A-MPDU under construction and if the TX queue is empty.

If both conditions are met, the A-MPDU is closed and programmed for TX.

Parameters:

  `[in]` | access_category | Access category of the queue to be checked

void txl_agg_check_rtscts_retry_limit | ( | struct tx_hd * | a_thd,
|  | uint8_t | access_category |
| ) |  |  |

Check if the current A-MPDU header descriptor indicates that the RTS/CTS retry limit has been reached.

In such case, reprogram the A-MPDU transmission with protection changed to CTS-to-self to ensure that packet will go out.

Parameters:

  `[in]` | a_thd | Pointer to the A-MPDU header descriptor
  `[in]` | access_category | Queue on which the A-MPDU is transmitted

Referenced by txl_frame_exchange_done().

void txl_agg_check_saved_agg_desc | ( | uint8_t | access_category | ) |

Check if an A-MPDU descriptor is currently saved and free it.

This function is called each time a MPDU is marked as done by the MAC HW. Indeed a A-MPDU descriptor might have been saved earlier because a new frame exchange was "newTail'ed" to it, and therefore the HW could re-fetch the previous descriptor to get the new one. When the new descriptor is marked as done, we are sure that we can free the previous one.

Parameters:

  `[in]` | access_category | Queue that needs to be checked

Referenced by txl_frame_exchange_done().

__INLINE struct tx_agg_desc* txl_agg_desc_alloc | ( | uint8_t | access_category | ) | `[read]`

Get a free aggregation descriptor structure from the free pool.

Parameters:

  `[in]` | access_category | Access category

Returns:
  Pointer to the retrieved free structure.

Definition at line 300 of file txl_agg.h.

References co_list_pop_front(), and tx_agg_desc_pool.

__INLINE void txl_agg_desc_free | ( | struct tx_agg_desc * | agg_desc | ) |

Free a used aggregation descriptor structure.

Parameters:

  `[in]` | agg_desc | Pointer to the structure to be freed.

Definition at line 312 of file txl_agg.h.

References co_list_push_back(), and tx_agg_desc::free_list.

Referenced by txl_mumimo_convert().

void txl_agg_finish | ( | uint8_t | ac | ) |

Terminates the non MU-MIMO A-MPDU under construction This function can be called in several cases:

- The new TX descriptor pushed is not compliant with the current A-MPDU
- The length of the current A-MPDU has reached the limit
- The number of MPDUs in the current A-MPDU has reached the limit
- The TX queue will become empty and new data shall be programmed for transmission.

Parameters:

  `[in]` | ac | Access Category

Referenced by txl_frame_exchange_done().

static void txl_agg_hwdesc_init | ( | void |  | ) | `[static]`

Initialize Hardware TX descriptors for A-MPDU.

Definition at line 573 of file txl_agg.c.

References tx_agg_desc::a_thd, tx_agg_desc::bar_payl, tx_agg_desc::bar_pol_tbl, tx_agg_desc::bar_thd, co_list_push_back(), CPU2HW, tx_hd::dataendptr, tx_hd::datastartptr, mac_hdr_ctrl::durid, EXPECTED_ACK_COMPRESSED_BLOCK_ACK, mac_hdr_ctrl::fctl, tx_hd::first_pbd_ptr, tx_agg_desc::free_list, FRM_CNTL_SUBTYPE_BAR, FRM_TYPE_CNTL, tx_hd::frmlen, tx_hd::frmlifetime, bar_frame::h, INTERRUPT_EN_TX, MAC_FCTRL_BAR_ST, MAC_FCTRL_CTRL_T, tx_policy_tbl::maccntrlinfo1, tx_policy_tbl::maccntrlinfo2, tx_hd::macctrlinfo1, tx_hd::macctrlinfo2, tx_hd::nextmpdudesc_ptr, NX_TX_PT_OFT, tx_hd::optlen, phy_get_ntx(), tx_policy_tbl::phycntrlinfo1, tx_policy_tbl::phycntrlinfo2, tx_hd::phyctrlinfo, POLICY_TABLE_PATTERN, tx_hd::policyentryaddr, TS_VALID_BIT, tx_agg_desc_cnt, tx_agg_desc_pool, TX_AMPDU_DESC_QUEUE_CNT, TX_HEADER_DESC_PATTERN, TX_NTX_2_ANTENNA_SET, tx_policy_tbl::upatterntx, tx_hd::upatterntx, WHICHDESC_AMPDU_EXTRA, and WHICHDESC_UNFRAGMENTED_MSDU.

void txl_agg_init | ( | void |  | ) |

Initializes the TX aggregation module.

uint16_t txl_agg_mpdu_nb_delims | ( | struct tx_hd * | thd,
|  | uint16_t | mmss_bytes |
| ) |  |  |

Calculate number of blank delimiters to ensure MMSS after a THD This number will be set in the THD of the NEXT txdesc in AMPDU.

Parameters:

  `[in]` | thd | Pointer to THD whose length number of blank delimiters is calculated
  `[in]` | mmss_bytes | Minimal number of bytes in the A-MPDU subframe

Returns:
  Number of blank delimiters to ensure Min MPDU Start Spacing

void txl_agg_mumimo_close | ( | uint8_t | ac | ) |

Terminates the MU-MIMO PPDU.

This function goes through the different user positions, close the pending A-MPDUs, and finds which user position will be sent on primary queue (i.e. the longest in duration). It then performs the chaining of the different A-MPDU THDs to form the MU-MIMO PPDU to HW, and proceeds to the allocation of the buffers whenever possible.

Parameters:

  `[in]` | ac | Access Category

Referenced by txl_frame_exchange_done(), and txl_mumimo_check().

int txl_agg_push_mpdu | ( | struct txdesc * | txdesc,
|  | uint8_t | ac |
| ) |  |  |

Try and aggregate txdesc, several checks are made, when they fail the MPDU goes on to be downloaded as a normal singleton MPDU.

The idea is to check if at least two txdescs in a row

- can be aggregated (UMAC set the flag AND txdesc not marked as part of AMPDU)
- have same (staid,tid)
- that (staid, tid) matches and existing BA agreement
- the SN fits within the current bitmap window of the BA agreement
- not both AMPDU header descriptors for this STA have been already prepared

Then, the next txdescs are looped over to see if they can be aggregated too, if so they are marked and the AMPDU desc length is increased.

Parameters:

  `[in]` | txdesc | Descriptor of the first packet in pending list for an AC, analysed for aggregation possibility
  `[in]` | ac | Access category for which creation of an AMPDU is being analysed

Returns:
  The status of the packet just pushed (SU_PACKET, MU_PACKET or MU_PAUSED if the descriptor has been saved and the IPC needs to be paused).

void txl_agg_release | ( | struct tx_agg_desc * | agg_desc | ) |

Release all AMPDU related space: BA, BAR, aggregate control and its AMPDU THD.

Parameters:

  `[in]` | agg_desc | Pointer to A-MPDU descriptor

Referenced by txl_cfm_evt().

void txl_agg_reset | ( | void |  | ) |

Reset the TX aggregation module.

This function is called as part of the recovery procedure

void txl_agg_sec_transmit_trigger | ( | void |  | ) |

Process secondary user events of the MACTX IRQ.

This function releases packets transmitted for the second user in a MU transmission

void txl_agg_set_ampdu_protection | ( | uint32_t * | rc | ) |

Add Self-CTS protection to the A-MPDU.

This function first checks whether protection is already configured or not, and if not it adds the Self-CTS. The rate of transmission of the CTS is decided depending on the MCS used for the packet transmission (6 Mbps for MCS <= 2, 24 Mbps otherwise).

Parameters:

  `[in,out]` | rc | The pointer to the RC step

Referenced by txl_hwdesc_config_post().

static void txl_ampdu_constraints_get | ( | struct txdesc * | txdesc,
|  | uint8_t | ac,
|  | struct txl_agg_build_tag * | agg |
| ) |  |  | `[static]`

Calculate number of blank delimiters to ensure MMSS after a txdesc This number will be set in the THD of the NEXT txdesc in AMPDU.

Parameters:

  `[in]` | txdesc | Pointer to txdesc whose length number of blank delimiters is calculated
  `[in]` | ac | Access Category
  `[in]` | agg | Pointer to the A-MPDU descriptor under builing process

Definition at line 443 of file txl_agg.c.

References mm_env_tag::ampdu_max_dur, sta_info_tag::ampdu_spacing_min, ASSERT_ERR, txl_agg_build_tag::bw, txl_agg_build_tag::bw_idx, BW_TX_RCX_MASK, BW_TX_RCX_OFT, co_min(), FORMAT_MOD_TX_RCX_MASK, FORMAT_MOD_TX_RCX_OFT, FORMATMOD_HE_SU, FORMATMOD_NON_HT_DUP_OFDM, txdesc::host, txl_agg_build_tag::max_cnt, txl_agg_build_tag::max_len, mm_env, txl_agg_build_tag::mmss_bytes, umacdesc::phy_flags, sta_info_tab, sta_mgmt_get_tx_buff_size(), hostdesc::staid, hostdesc::tid, txl_ht_vht_ampdu_param_get(), txl_vht_idx_to_1us_len_get(), txl_vht_idx_to_32us_len_get(), and txdesc::umac.

static bool txl_ampdu_has_ht_vht_rate | ( | struct txdesc * | txdesc | ) | `[static]`

Check if the phy_flags in TX descriptor indicate a HT or VHT rate, that would allow aggregation.

In case of a legacy rate this function returns false.

Parameters:

  `[in]` | txdesc | Pointer to txdesc whose phy_flags is checked

Returns:
  true if the rate is ht or vht, false otherwise

Definition at line 334 of file txl_agg.c.

References FORMAT_MOD_TX_RCX_MASK, FORMAT_MOD_TX_RCX_OFT, FORMATMOD_NON_HT_DUP_OFDM, umacdesc::phy_flags, and txdesc::umac.

static bool txl_desc_is_agg | ( | struct txdesc * | txdesc,
|  | struct tx_agg_desc * | agg_desc |
| ) |  |  | `[static]`

Check if a txdesc can be aggregated in an AMPDU.

Parameters:

  `[in]` | txdesc | Pending txdesc
  `[in]` | agg_desc | Already established params of ongoing aggregate

Returns:
  true if MPDU can be aggregated, false otherwise

Definition at line 309 of file txl_agg.c.

References txdesc::host, is_mpdu_agg(), is_mpdu_first(), tx_agg_desc::sta_idx, hostdesc::staid, hostdesc::tid, and tx_agg_desc::tid.

static void txl_fill_bar | ( | struct tx_agg_desc * | agg_desc,
|  | uint16_t | sn,
|  | uint8_t | staid,
|  | uint8_t | tid,
|  | uint8_t | bw |
| ) |  |  | `[static]`

Fill BAR frame (THD and payload).

Parameters:

  `[in]` | agg_desc | Aggregate descriptor in which BAR THD and payload is found
  `[in]` | sn | Sequence number to be put in the BAR frame
  `[in]` | staid | Station ID for this AMPDU
  `[in]` | tid | TID for this AMPDU
  `[in]` | bw | Transmission bandwidth of this AMPDU

Definition at line 525 of file txl_agg.c.

References mac_hdr_ctrl::addr1, mac_hdr_ctrl::addr2, bar_frame::bar_cntrl, bar_frame::bar_information, tx_agg_desc::bar_payl, tx_agg_desc::bar_pol_tbl, tx_agg_desc::bar_thd, BW_TX_RCX_OFT, FORMAT_MOD_TX_RCX_OFT, FORMATMOD_NON_HT_DUP_OFDM, bar_frame::h, HW_RATE_24MBPS, sta_info_tag::inst_nbr, vif_info_tag::mac_addr, sta_info_tag::mac_addr, MCS_INDEX_TX_RCX_OFT, tx_hd::nextfrmexseq_ptr, tx_policy_tbl::powercntrlinfo, tx_policy_tbl::ratecntrlinfo, sta_info_tab, tx_hd::statinfo, TX_PWR_LEVEL_SET, and vif_info_tab.

Referenced by txl_mumimo_ampdu_finish().

static int txl_ht_vht_ampdu_param_get | ( | struct txdesc * | txdesc,
|  | uint8_t | format_mod,
|  | uint32_t * | max_len_sta,
|  | uint32_t * | nss |
| ) |  |  | `[static]`

Compute the base rate index that should be used to compute the Maximum PHY length of the HT/VHT A-MPDU and the minimum A-MPDU subframe length.

Parameters:

  `[in]` | txdesc | Pointer to txdesc whose length number of blank delimiters is calculated
  `[in]` | format_mod | Modulation format (HT or VHT)
  `[out]` | max_len_sta | Maximum A-MPDU length that the STA could receive
  `[out]` | nss | Number of spatial streams for the transmission

Returns:
  The base rate index that should be used to get the maximum A-MPDU length that could be transmitted on the requested PHY rate

Definition at line 387 of file txl_agg.c.

References sta_info_tag::ampdu_size_max_ht, sta_info_tag::ampdu_size_max_vht, ASSERT_ERR, FORMATMOD_VHT, txdesc::host, HT_MCS_MASK, HT_MCS_OFT, HT_NSS_MASK, HT_NSS_OFT, MCS_INDEX_TX_RCX_MASK, MCS_INDEX_TX_RCX_OFT, umacdesc::phy_flags, SHORT_GI_TX_RCX_MASK, SHORT_GI_TX_RCX_OFT, sta_info_tab, hostdesc::staid, txdesc::umac, VHT_MCS_MASK, VHT_MCS_OFT, VHT_NSS_MASK, and VHT_NSS_OFT.

Referenced by txl_ampdu_constraints_get().

__INLINE uint16_t txl_mpdu_subframe_len | ( | struct tx_hd * | thd | ) |

Calculate AMPDU subframe length for an MPDU (without blank delimiters).

Parameters:

  `[in]` | thd | Pointer to the THD whose length +Delimiter(4B)+FCS(4)+PAD(0-3) is calculated.

Returns:
  AMPDU Subframe length.

Definition at line 209 of file txl_agg.h.

References CO_ALIGN4_HI, DELIMITER_LEN, and tx_hd::frmlen.

static void txl_mumimo_ampdu_finish | ( | uint8_t | ac,
|  | uint8_t | user_pos |
| ) |  |  | `[static]`

Terminates the MU-MIMO A-MPDU under construction.

Parameters:

  `[in]` | ac | Access Category
  `[in]` | user_pos | User Position in the group (only for MU-MIMO, 0 if not MU-MIMO)

Definition at line 1647 of file txl_agg.c.

References tx_agg_desc::a_thd, txl_list::agg, AGG_FORMATTED, tx_cfm_tag::ampdu_size, txl_agg_build_tag::bw, tx_hw_desc::cfm, CO_BIT, txl_agg_build_tag::curr_cnt, txl_agg_build_tag::desc, umacdesc::flags, tx_hd::frmlen, lmacdesc::hw_desc, INTERRUPT_EN_TX, txl_mumimo_build_info_tag::length, txdesc::lmac, tx_hd::macctrlinfo2, txl_list::mumimo, tx_hd::nextmpdudesc_ptr, txl_mumimo_build_info_tag::open, PROF_AGG_FINISH_AMPDU_CLR, PROF_AGG_FINISH_AMPDU_SET, PROF_MU_USER_POS_SET, set_mpdu_pos(), umacdesc::sn_win, tx_agg_desc::sta_idx, tx_agg_desc::status, tx_hw_desc::thd, tx_agg_desc::tid, txl_agg_build_tag::txdesc_last, txl_cntrl_env, txl_fill_bar(), txl_cntrl_env_tag::txlist, txdesc::umac, WHICHDESC_AMPDU_LAST, and WHICHDESC_UNFRAGMENTED_MSDU.

Referenced by txl_mumimo_check().

static int txl_mumimo_check | ( | struct txdesc * | txdesc,
|  | uint8_t | ac,
|  | uint8_t * | user_pos |
| ) |  |  | `[static]`

This function checks if the newly pushed TX descriptor can be part of a MU-MIMO PPDU under construction, or if it can start a new MU-MIMO PPDU.

Depending on the current status of the pending MU-MIMO PPDU, this function may decide to close it and start the new one immediately, or keep the current one open and pause the IPC queue of the new TX descriptor until the MU-MIMO PPDU is closed.

Parameters:

  `[in]` | txdesc | TX descriptor of the new packet pushed
  `[in]` | ac | Access Category
  `[out]` | user_pos | Pointer to the user position that will be returned

Returns:
  The status of the packet just pushed (SU_PACKET, MU_PACKET or MU_PAUSED if the descriptor has been saved and the IPC needs to be paused).

Definition at line 1728 of file txl_agg.c.

References ASSERT_ERR, bfr_is_calibrated(), CO_BIT, get_group_id(), get_user_pos(), txl_mumimo_build_info_tag::group_id, txdesc::host, is_mpdu_agg(), is_mumimo_group_id(), MCS_INDEX_TX_RCX_MASK, MU_PACKET, MU_PAUSED, MU_RESTART_CHECK, txl_list::mumimo, txl_mumimo_build_info_tag::open, txl_mumimo_build_info_tag::phy_flags, umacdesc::phy_flags, PROF_MU_PPDU_START_CLR, PROF_MU_PPDU_START_SET, PROF_MU_USER_POS_SET, hostdesc::staid, SU_PACKET, txl_mumimo_build_info_tag::txdesc, txl_agg_mumimo_close(), txl_cntrl_env, txl_mumimo_ampdu_finish(), txl_cntrl_env_tag::txlist, txdesc::umac, txl_mumimo_build_info_tag::users, VHT_MCS_MASK, and VHT_NSS_MASK.

static void txl_mumimo_convert | ( | uint8_t | ac,
|  | uint8_t | user_pos |
| ) |  |  | `[static]`

Convert a MU-MIMO A-MPDU or MPDU into a SU one.

Parameters:

  `[in]` | ac | Access Category
  `[in]` | user_pos | User position

Definition at line 1492 of file txl_agg.c.

References lmacdesc::agg_desc, txl_list::aggregates, tx_agg_desc::bar_thd, co_list_concat(), co_list_pick(), co_list_pick_last(), co_list_push_back(), CPU2HW, txl_list::first_to_download, lmacdesc::hw_desc, is_mpdu_agg(), tx_agg_desc::list_hdr, txdesc::lmac, txl_list::mumimo, tx_hd::nextmpdudesc_ptr, txl_list::ppdu_cnt, tx_hw_desc::thd, txl_list::transmitting, txl_mumimo_build_info_tag::tx, tx_desc_next(), txl_agg_desc_free(), txl_cntrl_env, txl_payload_alloc(), and txl_cntrl_env_tag::txlist.

static uint32_t txl_mumimo_duration_ns | ( | uint32_t | length,
|  | uint8_t | mcs,
|  | bool | sgi,
|  | uint8_t | bw,
|  | uint8_t | nss |
| ) |  |  | `[static]`

Compute the duration of the data part of a MU-MIMO A-MPDU.

Parameters:

  `[in]` | length | Total data length, in bytes, of the A-MPDU
  `[in]` | mcs | MCS used for the transmission
  `[in]` | sgi | Flag indicating whether Short GI is used or not
  `[in]` | bw | The transmission bandwidth
  `[in]` | nss | The number of Spatial Streams used for the transmission

Returns:
  The duration of the A-MPDU in ns

Definition at line 1551 of file txl_agg.c.

References BW_80MHZ, and VHT_NDBPS.

static void txl_mumimo_secondary_done | ( | uint8_t | access_category,
|  | uint8_t | user_idx |
| ) |  |  | `[static]`

Unchains the frame exchanges that have been completed.

This primitive goes through the list of completed frame exchanges, check their status, and put them in the correct list (cfm or waiting block-ack)

Parameters:

  `[in]` | access_category | Access category for the frame exchanges to unchain
  `[in]` | user_idx | User index (for MU-MIMO TX only, 0 otherwise)

Definition at line 1838 of file txl_agg.c.

References lmacdesc::agg_desc, ASSERT_ERR, tx_agg_desc::cfm, tx_hw_desc::cfm, co_list_pick(), co_list_pop_front(), co_list_push_back(), DESC_DONE_TX_BIT, get_user_pos(), lmacdesc::hw_desc, txdesc::lmac, PROF_AGG_SMPDU_DONETX_CLR, PROF_AGG_SMPDU_DONETX_SET, PROF_MU_USER_POS_IRQ_SET, tx_hd::statinfo, tx_cfm_tag::status, tx_hw_desc::thd, txl_list::transmitting, txl_check_done_amsdu_subframe(), txl_cntrl_env, txl_free_done_mpdu(), and txl_cntrl_env_tag::txlist.

static uint16_t txl_vht_idx_to_1us_len_get | ( | int | base_idx,
|  | uint8_t | bw |
| ) |  |  | `[static]`

Get the 1us length from the HT/VHT table for a given base index, bw pair.

Parameters:

  `[in]` | base_idx | Base index in the table
  `[in]` | bw | Bandwidth of transmission

Returns:
  The 1us byte length

Definition at line 367 of file txl_agg.c.

References TX_VHT_RATE_TO_MIN_SEP.

Referenced by txl_ampdu_constraints_get().

static uint32_t txl_vht_idx_to_32us_len_get | ( | int | base_idx,
|  | uint8_t | bw |
| ) |  |  | `[static]`

Get the 32us length from the HT/VHT table for a given base index, bw pair.

Parameters:

  `[in]` | base_idx | Base index in the table
  `[in]` | bw | Bandwidth of transmission

Returns:
  The 32us byte length

Definition at line 351 of file txl_agg.c.

References TX_VHT_RATE_TO_32US_LEN.

Referenced by txl_ampdu_constraints_get().

## Variable Documentation

struct tx_agg_desc* const tx_agg_desc_array[TX_AMPDU_DESC_QUEUE_CNT]`[static]`

Initial value:

    {
        tx_agg_desc_array0,
        tx_agg_desc_array1,
        tx_agg_desc_array2,
        tx_agg_desc_array3,

        tx_agg_desc_array4,

    }

Table of pointers to the different aggregation descriptor arrays.

Definition at line 263 of file txl_agg.c.

const int tx_agg_desc_cnt[TX_AMPDU_DESC_QUEUE_CNT]`[static]`

Initial value:

    {
        TX_MAX_AMPDU_NB_PER_AC0,
        TX_MAX_AMPDU_NB_PER_AC1,
        TX_MAX_AMPDU_NB_PER_AC2,
        TX_MAX_AMPDU_NB_PER_AC3,

        TX_MAX_AMPDU_NB_PER_AC4,

    }

Number of aggregation descriptor per queue.

Definition at line 278 of file txl_agg.c.

Referenced by txl_agg_hwdesc_init(), and txl_agg_hwdesc_reset().

const uint16_t TX_VHT_RATE_TO_32US_LEN[10 *4 *2]

Initial value:

    {

        [  0] =   26,   [  1] =   28,   [  2] =   54,   [  3] =   60,
        [  8] =   52,   [  9] =   57,   [ 10] =  108,   [ 11] =  120,
        [ 16] =   78,   [ 17] =   86,   [ 18] =  162,   [ 19] =  180,
        [ 24] =  104,   [ 25] =  115,   [ 26] =  216,   [ 27] =  240,
        [ 32] =  156,   [ 33] =  173,   [ 34] =  324,   [ 35] =  360,
        [ 40] =  208,   [ 41] =  231,   [ 42] =  432,   [ 43] =  480,
        [ 48] =  234,   [ 49] =  260,   [ 50] =  486,   [ 51] =  540,
        [ 56] =  260,   [ 57] =  288,   [ 58] =  540,   [ 59] =  600,
        [ 64] =  312,   [ 65] =  346,   [ 66] =  648,   [ 67] =  720,
        [ 72] =  346,   [ 73] =  385,   [ 74] =  720,   [ 75] =  800,

        [  4] =  117,   [  5] =  130,   [  6] =  234,   [  7] =  260,
        [ 12] =  234,   [ 13] =  260,   [ 14] =  468,   [ 15] =  520,
        [ 20] =  351,   [ 21] =  390,   [ 22] =  702,   [ 23] =  780,
        [ 28] =  468,   [ 29] =  520,   [ 30] =  936,   [ 31] = 1040,
        [ 36] =  702,   [ 37] =  780,   [ 38] = 1404,   [ 39] = 1560,
        [ 44] =  936,   [ 45] = 1040,   [ 46] = 1872,   [ 47] = 2080,
        [ 52] = 1053,   [ 53] = 1170,   [ 54] = 2106,   [ 55] = 2340,
        [ 60] = 1170,   [ 61] = 1300,   [ 62] = 2340,   [ 63] = 2600,
        [ 68] = 1404,   [ 69] = 1560,   [ 70] = 2808,   [ 71] = 3120,
        [ 76] = 1560,   [ 77] = 1733,   [ 78] = 3120,   [ 79] = 3466,
    }

Table linking HT or VHT MCS+GI+BW to the number of bytes transmitted in 32us Index of the table is (MCS_IDX << 3) | (BW << 1) | (GI_400) where BW is 0 for 20 MHz, 1 for 40MHz and 2 for 80MHz GI_400 is 1 if packet is being sent with 400ns GI, 0 if 800ns GI.

Definition at line 148 of file txl_agg.c.

Referenced by txl_vht_idx_to_32us_len_get().

const uint8_t TX_VHT_RATE_TO_MIN_SEP[10 *4 *2]

Initial value:

    {

        [  0] =  1,   [  1] =  1,   [  2] =  2,   [  3] =  2,
        [  8] =  2,   [  9] =  2,   [ 10] =  4,   [ 11] =  4,
        [ 16] =  3,   [ 17] =  3,   [ 18] =  6,   [ 19] =  6,
        [ 24] =  4,   [ 25] =  4,   [ 26] =  7,   [ 27] =  8,
        [ 32] =  5,   [ 33] =  6,   [ 34] = 11,   [ 35] = 12,
        [ 40] =  7,   [ 41] =  8,   [ 42] = 14,   [ 43] = 15,
        [ 48] =  8,   [ 49] =  9,   [ 50] = 16,   [ 51] = 17,
        [ 56] =  9,   [ 57] = 10,   [ 58] = 17,   [ 59] = 19,
        [ 64] = 10,   [ 65] = 11,   [ 66] = 21,   [ 67] = 23,
        [ 72] = 11,   [ 73] = 13,   [ 74] = 23,   [ 75] = 25,

        [  4] =  4,   [  5] =  5,   [  6] =  8,   [  7] =  9,
        [ 12] =  8,   [ 13] =  9,   [ 14] = 15,   [ 15] = 17,
        [ 20] = 11,   [ 21] = 13,   [ 22] = 22,   [ 23] = 25,
        [ 28] = 15,   [ 29] = 17,   [ 30] = 30,   [ 31] = 33,
        [ 36] = 22,   [ 37] = 25,   [ 38] = 44,   [ 39] = 49,
        [ 44] = 30,   [ 45] = 33,   [ 46] = 59,   [ 47] = 65,
        [ 52] = 33,   [ 53] = 37,   [ 54] = 66,   [ 55] = 74,
        [ 60] = 37,   [ 61] = 41,   [ 62] = 74,   [ 63] = 82,
        [ 68] = 44,   [ 69] = 49,   [ 70] = 88,   [ 71] = 98,
        [ 76] = 49,   [ 77] = 55,   [ 78] = 98,   [ 79] = 109,
    }

Table linking HT or VHT MCS+GI+BW to minimum number of bytes for 1us min MPDU start spacing in AMPDU Index of the table is (MCS_IDX << 3) | (BW << 1) | (GI_400) where BW is 0 for 20 MHz, 1 for 40MHz and 2 for 80MHz GI_400 is 1 if packet is being sent with 400ns GI, 0 if 800ns GI.

Definition at line 117 of file txl_agg.c.

Referenced by txl_vht_idx_to_1us_len_get().

const uint16_t VHT_NDBPS[VHT_BW][VHT_MCS]

Initial value:

     {

       [BW_20MHZ]  = {26,   52,    78,     104,   156,   208,   234,   260,   312,   1040},
       [BW_40MHZ]  = {54,   108,   162,    216,   324,   432,   486,   540,   648,   720 },
       [BW_80MHZ]  = {117,  234,   351,    468,   702,   936,   1053,  1170,  1404,  1560},
       [BW_160MHZ] = {234,  468,   702,    936,   1404,  1872,  2106,  2340,  2808,  3120},
    }

IEEE P802.11ac D3.0 Chptr 22.5 Parameters for VHT MCSs Note that some BW, MCS, NSS combinations are not allowed (e.g 20MHz, MCS9, NSS 1,2) The NDBPS value given for MCS9 20MHz is for NSS=3.

Definition at line 183 of file txl_agg.c.

Referenced by txl_mumimo_duration_ns().