Changes between Version 2 and Version 3 of 802.11/wlan_exp/app_notes/tutorial_token_mac/CPU_LOW


Ignore:
Timestamp:
Jul 9, 2015, 11:15:39 AM (9 years ago)
Author:
chunter
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • 802.11/wlan_exp/app_notes/tutorial_token_mac/CPU_LOW

    v2 v3  
    6767
    6868{{{
     69#!c
    6970case IPC_MBOX_TOKEN_NEW_RESERVATION:
    7071        new_reservation = (ipc_token_new_reservation*)msg->payload_ptr;
     
    7576----
    7677
    77 
    78 
    79 
     78The most significant change to the MAC Low Framework is the handling of the {{{IPC_MBOX_TX_MPDU_READY}}} message. In the default codebase, that message will directly lead to calling the {{{frame_tx_callback()}}} callback function pointer. In TokenMAC, we need to be able to defer a transmission until later if it currently is not our token reservation period. So, instead of calling {{{frame_tx_callback()}}} directly within the IPC handling of {{{IPC_MBOX_TX_MPDU_READY}}}, we move everything out of that case statement into a new function:
     79
     80{{{
     81#!c
     82
     83void wlan_mac_low_proc_pkt_buf(u16 tx_pkt_buf){
     84        u32                      status;
     85        tx_frame_info          * tx_mpdu;
     86        mac_header_80211       * tx_80211_header;
     87        u8                       rate;
     88        u16                      ACK_N_DBPS;
     89        u32                      isLocked, owner;
     90        u32                      low_tx_details_size;
     91        wlan_ipc_msg             ipc_msg_to_high;
     92
     93        if(lock_pkt_buf_tx(tx_pkt_buf) != PKT_BUF_MUTEX_SUCCESS){
     94                warp_printf(PL_ERROR, "Error: unable to lock TX pkt_buf %d\n", tx_pkt_buf);
     95
     96                status_pkt_buf_tx(tx_pkt_buf, &isLocked, &owner);
     97
     98                warp_printf(PL_ERROR, " TX pkt_buf %d status: isLocked = %d, owner = %d\n", tx_pkt_buf, isLocked, owner);
     99
     100        } else {
     101
     102                tx_mpdu = (tx_frame_info*)TX_PKT_BUF_TO_ADDR(tx_pkt_buf);
     103
     104                tx_mpdu->delay_accept = (u32)(get_usec_timestamp() - tx_mpdu->timestamp_create);
     105
     106                //Convert rate index into rate code used in PHY's SIGNAL field
     107                //ACK_N_DBPS is used to calculate duration of received ACKs.
     108                //The selection of ACK rates given DATA rates is specified in 9.7.6.5.2 of 802.11-2012
     109                rate = wlan_mac_mcs_to_phy_rate(tx_mpdu->params.phy.rate);
     110                ACK_N_DBPS = wlan_mac_mcs_to_n_dbps(wlan_mac_mcs_to_ctrl_resp_mcs(tx_mpdu->params.phy.rate));
     111
     112                if((tx_mpdu->flags) & TX_MPDU_FLAGS_FILL_DURATION){
     113                        //Get pointer to start of MAC header in packet buffer
     114                        tx_80211_header = (mac_header_80211*)(TX_PKT_BUF_TO_ADDR(tx_pkt_buf)+PHY_TX_PKT_BUF_MPDU_OFFSET);
     115
     116                        //Compute and fill in the duration of any time-on-air following this packet's transmission
     117                        // For DATA Tx, DURATION = T_SIFS + T_ACK, where T_ACK is function of the ACK Tx rate
     118                        tx_80211_header->duration_id = wlan_ofdm_txtime(sizeof(mac_header_80211_ACK)+WLAN_PHY_FCS_NBYTES, ACK_N_DBPS) + T_SIFS;
     119                }
     120
     121                if((tx_mpdu->flags) & TX_MPDU_FLAGS_FILL_TIMESTAMP){
     122                        //Some management packets contain the node's local 64-bit microsecond timer value
     123                        // The Tx hardware can insert this value into the outgoing byte stream automatically
     124                        // This ensures the timestamp value is not skewed by any pre-Tx deferrals
     125
     126                        //The macros below set the first and last byte index where the Tx logic should insert
     127                        // the 8-byte timestamp.
     128                        //In the current implementation these indexes must span an 8-byte-aligned
     129                        // region of the packet buffer (i.e. (start_ind % 8)==0 )
     130                        wlan_phy_tx_timestamp_ins_start((24+PHY_TX_PKT_BUF_PHY_HDR_SIZE));
     131                        wlan_phy_tx_timestamp_ins_end((31+PHY_TX_PKT_BUF_PHY_HDR_SIZE));
     132
     133                } else {
     134                        //When start>end, the Tx logic will not insert any timestamp
     135                        wlan_phy_tx_timestamp_ins_start(1);
     136                        wlan_phy_tx_timestamp_ins_end(0);
     137                }
     138
     139                //Submit the MPDU for transmission - this callback will return only when the MPDU Tx is
     140                // complete (after all re-transmissions, ACK Rx, timeouts, etc.)
     141
     142                status = frame_tx_callback(tx_pkt_buf, rate, tx_mpdu->length, low_tx_details);
     143
     144                if((tx_mpdu->flags) & TX_MPDU_FLAGS_FILL_TIMESTAMP){
     145                        //The Tx logic automatically inserted the timestamp at the time that the bytes
     146                        //were being fed out to the Tx PHY. We can go back and re-insert this time into the
     147                        //payload so that further processing (e.g. logging) sees the correct payload.
     148
     149                        //First, calculate what the value should be
     150
     151                        *((u64*)( (TX_PKT_BUF_TO_ADDR(tx_pkt_buf)+PHY_TX_PKT_BUF_MPDU_OFFSET + 24)) ) = (u64) ( (u64)get_tx_start_timestamp() + (s64)wlan_mac_get_timestamp_offset() );
     152                }
     153
     154                //Record the total time this MPDU spent in the Tx state machine
     155                tx_mpdu->delay_done = (u32)(get_usec_timestamp() - (tx_mpdu->timestamp_create + (u64)(tx_mpdu->delay_accept)));
     156
     157                low_tx_details_size = (tx_mpdu->num_tx_attempts)*sizeof(wlan_mac_low_tx_details);
     158
     159                if(status == TX_MPDU_RESULT_SUCCESS){
     160                        tx_mpdu->tx_result = TX_MPDU_RESULT_SUCCESS;
     161                } else {
     162                        tx_mpdu->tx_result = TX_MPDU_RESULT_FAILURE;
     163                }
     164
     165                //Revert the state of the packet buffer and return control to CPU High
     166                if(unlock_pkt_buf_tx(tx_pkt_buf) != PKT_BUF_MUTEX_SUCCESS){
     167                        warp_printf(PL_ERROR, "Error: unable to unlock TX pkt_buf %d\n", tx_pkt_buf);
     168                        wlan_mac_low_send_exception(EXC_MUTEX_TX_FAILURE);
     169                } else {
     170                        ipc_msg_to_high.msg_id =  IPC_MBOX_MSG_ID(IPC_MBOX_TX_MPDU_DONE);
     171
     172                        //Add the per-Tx-event details to the IPC message so CPU High can add them to the log as TX_LOW entries
     173                        if(low_tx_details != NULL){
     174                                ipc_msg_to_high.payload_ptr = (u32*)low_tx_details;
     175
     176                                //Make sure we don't overfill the IPC mailbox with TX_LOW data; truncate the Tx details if necessary
     177                                if(low_tx_details_size < (IPC_BUFFER_MAX_NUM_WORDS << 2)){
     178                                        ipc_msg_to_high.num_payload_words = ( low_tx_details_size ) >> 2; // # of u32 words
     179                                } else {
     180                                        ipc_msg_to_high.num_payload_words = ( ((IPC_BUFFER_MAX_NUM_WORDS << 2)/sizeof(wlan_mac_low_tx_details)  )*sizeof(wlan_mac_low_tx_details) ) >> 2; // # of u32 words
     181                                }
     182                        } else {
     183                                ipc_msg_to_high.num_payload_words = 0;
     184                                ipc_msg_to_high.payload_ptr = NULL;
     185                        }
     186                        ipc_msg_to_high.arg0 = tx_pkt_buf;
     187                        ipc_mailbox_write_msg(&ipc_msg_to_high);
     188                }
     189        }
     190}
     191}}}
     192
     193Now we will change the {{{IPC_MBOX_TX_MPDU_READY}}} case to the following:
     194
     195{{{
     196#!c
     197
     198case IPC_MBOX_TX_MPDU_READY:
     199        if(allow_new_mpdu_tx){
     200                wlan_mac_low_proc_pkt_buf( msg->arg0 );
     201        } else {
     202                pkt_buf_pending_tx = msg->arg0;
     203        }                       
     204        break;
     205}}}
     206
     207Basically, we will rely on the new {{{allow_new_mpdu_tx}}} global variable to tell us whether or not we are allowed to process a new MPDU for transmission. If we are, we will call the new {{{wlan_mac_low_proc_pkt_buf}}} function just like before. If we are not allowed to transmit, we will store the pending packet buffer to the new {{{pkt_buf_pending_tx}}} global variable and worry about calling {{{wlan_mac_low_proc_pkt_buf}}} later when we are allowed to transmit once again.
     208
     209----
     210
     211