blob: 353b106050399ef979dd3938d4a6544e1ff17bbb [file] [log] [blame]
/*
* Copyright (c) 2011-2014, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/**
* @file ol_htt_tx_api.h
* @brief Specify the tx HTT API functions called by the host data SW.
* @details
* This file declares the HTT API functions that are specifically
* related to transmit processing.
* In particular, the methods of the abstract HTT tx descriptor are
* specified.
*/
#ifndef _OL_HTT_TX_API__H_
#define _OL_HTT_TX_API__H_
//#include <osapi_linux.h> /* u_int16_t, etc. */
#include <osdep.h> /* u_int16_t, etc. */
#include <adf_nbuf.h> /* adf_nbuf_t */
#include <ol_cfg.h> /* wlan_frm_fmt */
#include <htt.h> /* needed by inline functions */
#include <adf_net_types.h>
#include <ol_htt_api.h> /* htt_pdev_handle */
#include <htt_types.h>
#include <vos_trace.h>
/* Remove these macros when they get added to htt.h. */
#ifndef HTT_TX_DESC_EXTENSION_GET
#define HTT_TX_DESC_EXTENSION_OFFSET_BYTES 0
#define HTT_TX_DESC_EXTENSION_OFFSET_DWORD 0
#define HTT_TX_DESC_EXTENSION_M 0x10000000
#define HTT_TX_DESC_EXTENSION_S 28
#define HTT_TX_DESC_EXTENSION_GET(_var) \
(((_var) & HTT_TX_DESC_EXTENSION_M) >> HTT_TX_DESC_EXTENSION_S)
#define HTT_TX_DESC_EXTENSION_SET(_var, _val) \
do { \
HTT_CHECK_SET_VAL(HTT_TX_DESC_EXTENSION, _val); \
((_var) |= ((_val) << HTT_TX_DESC_EXTENSION_S)); \
} while (0)
#endif
/*================ meta-info about tx MSDUs =================================*/
/*
* For simplicity, use the IEEE 802.11 frame type values.
*/
enum htt_frm_type {
htt_frm_type_mgmt = 0,
htt_frm_type_ctrl = 1,
htt_frm_type_data = 2
};
/*
* For simplicity, use the IEEE 802.11 frame sub-type values.
*/
enum htt_frm_subtype {
htt_frm_subtype_mgmt_assoc_req = 0,
htt_frm_subtype_mgmt_assoc_resp = 1,
htt_frm_subtype_mgmt_reassoc_req = 2,
htt_frm_subtype_mgmt_reassoc_resp = 3,
htt_frm_subtype_mgmt_probe_req = 4,
htt_frm_subtype_mgmt_probe_resp = 5,
htt_frm_subtype_mgmt_timing_adv = 6,
htt_frm_subtype_mgmt_beacon = 8,
htt_frm_subtype_mgmt_atim = 9,
htt_frm_subtype_mgmt_disassoc = 10,
htt_frm_subtype_mgmt_auth = 11,
htt_frm_subtype_mgmt_deauth = 12,
htt_frm_subtype_mgmt_action = 13,
htt_frm_subtype_mgmt_action_no_ack = 14,
htt_frm_subtype_data_data = 0,
htt_frm_subtype_data_data_cf_ack = 1,
htt_frm_subtype_data_data_cf_poll = 2,
htt_frm_subtype_data_data_cf_ack_cf_poll = 3,
htt_frm_subtype_data_null = 4,
htt_frm_subtype_data_cf_ack = 5,
htt_frm_subtype_data_cf_poll = 6,
htt_frm_subtype_data_cf_ack_cf_poll = 7,
htt_frm_subtype_data_QoS_data = 8,
htt_frm_subtype_data_QoS_data_cf_ack = 9,
htt_frm_subtype_data_QoS_data_cf_poll = 10,
htt_frm_subtype_data_QoS_data_cf_ack_cf_poll = 11,
htt_frm_subtype_data_QoS_null = 12,
htt_frm_subtype_data_QoS_cf_poll = 14,
htt_frm_subtype_data_QoS_cf_ack_cf_poll = 15,
};
enum htt_ofdm_datarate { // Value MBPS Modulation Coding
htt_ofdm_datarate_6_mbps = 0, // 0 6 BPSK 1/2
htt_ofdm_datarate_9_mbps = 1, // 1 9 BPSK 3/4
htt_ofdm_datarate_12_mbps = 2, // 2 12 QPSK 1/2
htt_ofdm_datarate_18_mbps = 3, // 3 18 QPSK 3/4
htt_ofdm_datarate_24_mbps = 4, // 4 24 16-QAM 1/2
htt_ofdm_datarate_36_mbps = 5, // 5 36 16-QAM 3/4
htt_ofdm_datarate_48_mbps = 6, // 6 48 64-QAM 1/2
htt_ofdm_datarate_54_mbps = 7, // 7 54 64-QAM 3/4
htt_ofdm_datarate_max = 7,
};
/**
* @brief TX control header
* @details
* When sending an OCB packet, the user application has
* the option of including the following struct following an ethernet header
* with the proto field set to 0x8151. This struct includes various TX
* paramaters including the TX power and MCS.
*/
PREPACK struct ocb_tx_ctrl_hdr_t {
/* The version must be 1. */
A_UINT16 version;
A_UINT16 length;
A_UINT16 channel_freq;
/* flags */
union {
struct {
A_UINT16
/* bit 0: if set, tx pwr spec is valid */
valid_pwr: 1,
/* bit 1: if set, tx MCS mask spec is valid */
valid_datarate: 1,
/* bit 2: if set, tx retries spec is valid */
valid_retries: 1,
/* bit 3: if set, chain mask is valid */
valid_chain_mask: 1,
/* bit 4: if set, tx expire TSF spec is valid*/
valid_expire_tsf: 1,
/* bit 5: if set, TID is valid */
valid_tid: 1,
/* bit 6: if set, tx frame with 802.3 ethernet header */
valid_eth_mode: 1,
/* bits 15:7 - unused, set to 0x0 */
reserved0_15_7: 9;
};
A_UINT16 all_flags;
};
/* TX expiry time (TSF) LSBs */
A_UINT32 expire_tsf_lo;
/* TX expiry time (TSF) MSBs */
A_UINT32 expire_tsf_hi;
/* pwr -
* Specify what power the tx frame needs to be transmitted at.
* The power a signed (two's complement) value is in units of 0.5 dBm.
* The value needs to be appropriately sign-extended when extracting
* the value from the message and storing it in a variable that is
* larger than A_INT8.
* If the transmission uses multiple tx chains, this power spec is
* the total transmit power, assuming incoherent combination of
* per-chain power to produce the total power.
*/
A_INT8 pwr;
/* datarate -
* The desired modulation and coding scheme.
*
* VALUE DATA RATE MODULATION CODING RATE
* @ 20 MHz
* (MBPS)
* 0 6 BPSK 1/2
* 1 9 BPSK 3/4
* 2 12 QPSK 1/2
* 3 18 QPSK 3/4
* 4 24 16-QAM 1/2
* 5 36 16-QAM 3/4
* 6 48 64-QAM 1/2
* 7 54 64-QAM 3/4
*/
A_UINT8 datarate;
/* retry_limit -
* Specify the maximum number of transmissions, including the
* initial transmission, to attempt before giving up if no ack
* is received.
* If the tx rate is specified, then all retries shall use the
* same rate as the initial transmission.
* If no tx rate is specified, the target can choose whether to
* retain the original rate during the retransmissions, or to
* fall back to a more robust rate.
*/
A_UINT8 retry_limit;
/* Chain mask - specify which chains to transmit from. */
A_UINT8 chain_mask;
/* Extended Traffic ID (0-15) */
A_UINT8 ext_tid;
/* Ensure that the size of the structure is a multiple of 4. */
A_UINT8 reserved[3];
} POSTPACK;
/**
* @brief tx MSDU meta-data that HTT may use to program the FW/HW tx descriptor
*/
struct htt_msdu_info_t {
/* the info sub-struct specifies the characteristics of the MSDU */
struct {
u_int16_t ethertype;
#define HTT_INVALID_PEER_ID 0xffff
u_int16_t peer_id;
u_int8_t vdev_id;
u_int8_t ext_tid;
/*
* l2_hdr_type - L2 format (802.3, native WiFi 802.11, or raw 802.11)
* Based on attach-time configuration, the tx frames provided by the
* OS to the tx data SW are expected to be either 802.3 format or
* the "native WiFi" variant of 802.11 format.
* Internally, the driver may also inject tx frames into the tx
* datapath, and these frames may be either 802.3 format, or 802.11
* "raw" format, with no further 802.11 encapsulation needed.
* The tx frames are tagged with their frame format, so the target
* FW/HW will know how to interpret the packet's encapsulation
* headers when doing tx classification, and what form of 802.11
* header encapsulation is needed, if any.
*/
u_int8_t l2_hdr_type; /* enum htt_pkt_type */
/*
* frame_type - is the tx frame management or data?
* Just to avoid confusion, the enum values for this frame type field
* use the 802.11 frame type values, although it is unexpected for
* control frames to be sent through the host data path.
*/
u_int8_t frame_type; /* enum htt_frm_type */
/*
* frame subtype - this field specifies the sub-type of management
* frames
* Just to avoid confusion, the enum values for this frame subtype
* field use the 802.11 management frame subtype values.
*/
u_int8_t frame_subtype; /* enum htt_frm_subtype */
u_int8_t is_unicast;
/* dest_addr is not currently used.
* It could be used as an input to a Tx BD (Riva tx descriptor)
* signature computation.
u_int8_t *dest_addr;
*/
u_int8_t l3_hdr_offset; // w.r.t. adf_nbuf_data(msdu), in bytes
/* l4_hdr_offset is not currently used.
* It could be used to specify to a TCP/UDP checksum computation
* engine where the TCP/UDP header starts.
u_int8_t l4_hdr_offset; // w.r.t. adf_nbuf_data(msdu), in bytes
*/
} info;
/* the action sub-struct specifies how to process the MSDU */
struct {
u_int8_t use_6mbps; /* mgmt frames: option to force 6 Mbps rate */
u_int8_t do_encrypt;
u_int8_t do_tx_complete;
u_int8_t tx_comp_req;
/*
* cksum_offload - Specify whether checksum offload is enabled or not
* Target FW uses this flag to turn on HW checksumming
* 0x0 - No checksum offload
* 0x1 - L3 header checksum only
* 0x2 - L4 checksum only
* 0x3 - L3 header checksum + L4 checksum
*/
adf_nbuf_tx_cksum_t cksum_offload;
} action;
};
static inline void
htt_msdu_info_dump(struct htt_msdu_info_t *msdu_info)
{
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
"HTT MSDU info object (%pK)\n", msdu_info);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" ethertype: %#x\n", msdu_info->info.ethertype);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" peer_id: %d\n", msdu_info->info.peer_id);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" vdev_id: %d\n", msdu_info->info.vdev_id);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" ext_tid: %d\n", msdu_info->info.ext_tid);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" l2_hdr_type: %d\n", msdu_info->info.l2_hdr_type);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" frame_type: %d\n", msdu_info->info.frame_type);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" frame_subtype: %d\n", msdu_info->info.frame_subtype);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" is_unicast: %u\n", msdu_info->info.is_unicast);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" l3_hdr_offset: %u\n", msdu_info->info.l3_hdr_offset);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" use 6 Mbps: %d\n", msdu_info->action.use_6mbps);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" do_encrypt: %d\n", msdu_info->action.do_encrypt);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" do_tx_complete: %d\n", msdu_info->action.do_tx_complete);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" is_unicast: %u\n", msdu_info->info.is_unicast);
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO_LOW,
" is_unicast: %u\n", msdu_info->info.is_unicast);
}
/*================ tx completion message field access methods ===============*/
/**
* @brief Look up the descriptor ID of the nth MSDU from a tx completion msg.
* @details
* A tx completion message tells the host that the target is done
* transmitting a series of MSDUs. The message uses a descriptor ID
* to identify each such MSDU. This function/macro is used to
* find the ID of one such MSDU referenced by the tx completion message.
*
* @param iterator - tx completion message context provided by HTT to the
* tx completion message handler. This abstract reference to the
* HTT tx completion message's payload allows the data SW's tx
* completion handler to not care about the format of the HTT
* tx completion message.
* @param num - (zero-based) index to specify a single MSDU within the
* series of MSDUs referenced by the tx completion message
* @return descriptor ID for the specified MSDU
*/
u_int16_t
htt_tx_compl_desc_id(void *iterator, int num);
/*========================= tx descriptor operations ========================*/
/**
* @brief Allocate a HTT abstract tx descriptor.
* @details
* Allocate a HTT abstract tx descriptor from a pool within "consistent"
* memory, which is accessible by HIF and/or MAC DMA as well as by the
* host CPU.
* It is expected that the tx datapath will allocate HTT tx descriptors
* and link them with datapath SW tx descriptors up front as the driver
* is loaded. Thereafter, the link from datapath SW tx descriptor to
* HTT tx descriptor will be maintained until the driver is unloaded.
*
* @param htt_pdev - handle to the HTT instance making the allocation
* @param[OUT] paddr_lo - physical address of the HTT descriptor
* @return success -> descriptor handle, -OR- failure -> NULL
*/
void *
htt_tx_desc_alloc(htt_pdev_handle htt_pdev, u_int32_t *paddr_lo);
/**
* @brief Free a HTT abstract tx descriptor.
*
* @param htt_pdev - handle to the HTT instance that made the allocation
* @param htt_tx_desc - the descriptor to free
*/
void
htt_tx_desc_free(htt_pdev_handle htt_pdev, void *htt_tx_desc);
/**
* @brief Discard all tx frames in the process of being downloaded.
* @details
* This function dicards any tx frames queued in HTT or the layers
* under HTT.
* The download completion callback is invoked on these frames.
*
* @param htt_pdev - handle to the HTT instance
*/
#if defined(CONFIG_HL_SUPPORT)
#define htt_tx_pending_discard(pdev) /* no-op */
#else
void
htt_tx_pending_discard(htt_pdev_handle pdev);
#endif
/**
* @brief Download a MSDU descriptor and (a portion of) the MSDU payload.
* @details
* This function is used within LL systems to download a tx descriptor and
* the initial portion of the tx MSDU payload, and within HL systems to
* download the tx descriptor and the entire tx MSDU payload.
* The HTT layer determines internally how much of the tx descriptor
* actually needs to be downloaded. In particular, the HTT layer does not
* download the fragmentation descriptor, and only for the LL case downloads
* the physical address of the fragmentation descriptor.
* In HL systems, the tx descriptor and the entire frame are downloaded.
* In LL systems, only the tx descriptor and the header of the frame are
* downloaded. To determine how much of the tx frame to download, this
* function assumes the tx frame is the default frame type, as specified
* by ol_cfg_frame_type. "Raw" frames need to be transmitted through the
* alternate htt_tx_send_nonstd function.
* The tx descriptor has already been attached to the adf_nbuf object during
* a preceding call to htt_tx_desc_init.
*
* @param htt_pdev - the handle of the physical device sending the tx data
* @param msdu - the frame being transmitted
* @param msdu_id - unique ID for the frame being transmitted
* @return 0 -> success, -OR- 1 -> failure
*/
int
htt_tx_send_std(
htt_pdev_handle htt_pdev,
adf_nbuf_t msdu,
u_int16_t msdu_id);
/**
* @brief Download a Batch Of Tx MSDUs
* @details
* Each MSDU already has the MSDU ID stored in the headroom of the
* netbuf data buffer, and has the HTT tx descriptor already attached
* as a prefix fragment to the netbuf.
*
* @param htt_pdev - the handle of the physical device sending the tx data
* @param head_msdu - the MSDU Head for Tx batch being transmitted
* @param num_msdus - The total Number of MSDU's provided for batch tx
* @return null-terminated linked-list of unaccepted frames
*/
adf_nbuf_t
htt_tx_send_batch(
htt_pdev_handle htt_pdev,
adf_nbuf_t head_msdu,
int num_msdus);
/* The htt scheduler for queued packets in htt
* htt when unable to send to HTC because of lack of resource
* forms a nbuf queue which is flushed when tx completion event from
* target is recieved
*/
void
htt_tx_sched(htt_pdev_handle pdev);
/**
* @brief Same as htt_tx_send_std, but can handle raw frames.
*/
int
htt_tx_send_nonstd(
htt_pdev_handle htt_pdev,
adf_nbuf_t msdu,
u_int16_t msdu_id,
enum htt_pkt_type pkt_type);
/**
* @brief Initialize the tx descriptor.
* @details
* This function initializes the tx descriptor.
* The values for the standard tx descriptor fields are provided as
* function arguments. Non-standard descriptor fields, which don't
* have function arguments to specify their value, are set to zero.
* An exception to this initialization of non-standard fields to zero
* is the "extended TID" field, which is initialized to the "invalid"
* value (0x1f).
*
* @param pdev - the handle of the physical device sending the tx data
* @param htt_tx_desc - abstract handle to the tx descriptor
* @param htt_tx_desc_paddr_lo - physical address of the HTT tx descriptor
* @param desc_id - ID to tag the descriptor with.
* The target FW uses this ID to identify to the host which MSDUs
* the target is referring to in its tx completion / postpone / drop
* messages.
* This ID is abstract - it is only interpreted inside the host
* tx datapath SW. In practice, though, the ID is an index into an
* array of tx descriptor structs.
* This ID is used for both HL and LL systems, since in both systems
* the target may need to refer to a particular MSDU to explicitly tell
* the host when it may free the MSDU descriptor and network buffer.
* @param msdu - the MSDU that is being prepared for transmission
* @param msdu_info - tx MSDU meta-data
*/
/*
* Provide a constant to specify the offset of the HTT portion of the
* HTT tx descriptor, to avoid having to export the descriptor defintion.
* The htt module checks internally that this exported offset is consistent
* with the private tx descriptor definition.
*
* Similarly, export a definition of the HTT tx descriptor size, and then
* check internally that this exported constant matches the private tx
* descriptor definition.
*/
#define HTT_TX_DESC_VADDR_OFFSET 8
#define HTT_TX_DESC_SIZE 24
static inline
void
htt_tx_desc_init(
htt_pdev_handle pdev,
void *htt_tx_desc,
u_int32_t htt_tx_desc_paddr_lo,
u_int16_t msdu_id,
adf_nbuf_t msdu,
struct htt_msdu_info_t *msdu_info,
struct ocb_tx_ctrl_hdr_t *tx_ctrl,
u_int8_t is_dsrc)
{
u_int32_t *word0, *word1, *word3;
u_int32_t local_word0, local_word1, local_word3;
struct htt_host_tx_desc_t *htt_host_tx_desc = (struct htt_host_tx_desc_t *)
(((char *) htt_tx_desc) - HTT_TX_DESC_VADDR_OFFSET);
bool desc_ext_required = (tx_ctrl && tx_ctrl->all_flags != 0);
word0 = (u_int32_t *) htt_tx_desc;
word1 = word0 + 1;
/*
* word2 is frag desc pointer
* word3 is peer_id
*/
word3 = word0 + 3; // Dword 3
/*
* HTT Tx Desc is in uncached memory. Used cached writes per word, to
* reduce unnecessary memory access.
*/
local_word0 = 0;
HTT_H2T_MSG_TYPE_SET(local_word0, HTT_H2T_MSG_TYPE_TX_FRM);
HTT_TX_DESC_PKT_TYPE_SET(local_word0, msdu_info->info.l2_hdr_type);
HTT_TX_DESC_VDEV_ID_SET(local_word0, msdu_info->info.vdev_id);
if (tx_ctrl && tx_ctrl->valid_tid) {
HTT_TX_DESC_EXT_TID_SET(local_word0, tx_ctrl->ext_tid);
} else {
HTT_TX_DESC_EXT_TID_SET(local_word0, msdu_info->info.ext_tid);
}
HTT_TX_DESC_CKSUM_OFFLOAD_SET(local_word0, msdu_info->action.cksum_offload);
HTT_TX_DESC_EXTENSION_SET(local_word0, desc_ext_required);
if (pdev->cfg.is_high_latency)
HTT_TX_DESC_TX_COMP_SET(local_word0, msdu_info->action.tx_comp_req);
HTT_TX_DESC_NO_ENCRYPT_SET(local_word0, msdu_info->action.do_encrypt ? 0 : 1);
*word0 = local_word0;
local_word1 = 0;
HTT_TX_DESC_FRM_LEN_SET(local_word1, adf_nbuf_len(msdu));
HTT_TX_DESC_FRM_ID_SET(local_word1, msdu_id);
*word1 = local_word1;
/* Initialize peer_id to INVALID_PEER bcoz this is NOT Reinjection path*/
local_word3 = HTT_INVALID_PEER;
if (tx_ctrl && tx_ctrl->channel_freq) {
HTT_TX_DESC_CHAN_FREQ_SET(local_word3, tx_ctrl->channel_freq);
}
*word3 = local_word3;
/*
* If any of the tx control flags are set, then we need the extended
* HTT header.
*/
if (desc_ext_required)
{
struct htt_tx_msdu_desc_ext_t local_desc_ext = {0};
/*
* Copy the info that was read from TX control header from the user
* application to the extended HTT header.
* First copy everything
* to a local temp structure, and then copy everything to the
* actual uncached structure in one go to save memory writes.
*/
local_desc_ext.valid_pwr = tx_ctrl->valid_pwr;
local_desc_ext.valid_mcs_mask = tx_ctrl->valid_datarate;
local_desc_ext.valid_retries = tx_ctrl->valid_retries;
local_desc_ext.valid_expire_tsf = tx_ctrl->valid_expire_tsf;
local_desc_ext.valid_chainmask = tx_ctrl->valid_chain_mask;
local_desc_ext.pwr = tx_ctrl->pwr;
if (tx_ctrl->valid_datarate &&
tx_ctrl->datarate <= htt_ofdm_datarate_max)
local_desc_ext.mcs_mask = (1 << (tx_ctrl->datarate + 4));
local_desc_ext.retry_limit = tx_ctrl->retry_limit;
local_desc_ext.expire_tsf_lo = tx_ctrl->expire_tsf_lo;
local_desc_ext.expire_tsf_hi = tx_ctrl->expire_tsf_hi;
local_desc_ext.chain_mask = tx_ctrl->chain_mask;
local_desc_ext.is_dsrc = (is_dsrc != 0);
adf_nbuf_push_head(msdu, sizeof(local_desc_ext));
adf_os_mem_copy(adf_nbuf_data(msdu), &local_desc_ext,
sizeof(local_desc_ext)); }
/*
* Specify that the data provided by the OS is a bytestream,
* and thus should not be byte-swapped during the HIF download
* even if the host is big-endian.
* There could be extra fragments added before the OS's fragments,
* e.g. for TSO, so it's incorrect to clear the frag 0 wordstream flag.
* Instead, clear the wordstream flag for the final fragment, which
* is certain to be (one of the) fragment(s) provided by the OS.
* Setting the flag for this final fragment suffices for specifying
* all fragments provided by the OS rather than added by the driver.
*/
adf_nbuf_set_frag_is_wordstream(msdu, adf_nbuf_get_num_frags(msdu) - 1, 0);
/* store a link to the HTT tx descriptor within the netbuf */
adf_nbuf_frag_push_head(
msdu,
HTT_TX_DESC_SIZE,
(char *) htt_host_tx_desc, /* virtual addr */
htt_tx_desc_paddr_lo, 0 /* phys addr MSBs - n/a */);
/*
* Indicate that the HTT header (and HTC header) is a meta-data
* "wordstream", i.e. series of u_int32_t, rather than a data
* bytestream.
* This allows the HIF download to byteswap the HTT + HTC headers if
* the host is big-endian, to convert to the target's little-endian
* format.
*/
adf_nbuf_set_frag_is_wordstream(msdu, 0, 1);
}
/**
* @brief Set a flag to indicate that the MSDU in question was postponed.
* @details
* In systems in which the host retains its tx frame until the target sends
* a tx completion, the target has the option of discarding it's copy of
* the tx descriptor (and frame, for HL) and sending a "postpone" message
* to the host, to inform the host that it must eventually download the
* tx descriptor (and frame, for HL).
* Before the host downloads the postponed tx desc/frame again, it will use
* this function to set a flag in the HTT tx descriptor indicating that this
* is a re-send of a postponed frame, rather than a new frame. The target
* uses this flag to keep the correct order between re-sent and new tx frames.
* This function is relevant for LL systems.
*
* @param pdev - the handle of the physical device sending the tx data
* @param desc - abstract handle to the tx descriptor
*/
void
htt_tx_desc_flag_postponed(htt_pdev_handle pdev, void *desc);
/**
* @brief Set a flag to tell the target that more tx downloads are en route.
* @details
* At times, particularly in response to a U-APSD trigger in a HL system, the
* host will download multiple tx descriptors (+ frames, in HL) in a batch.
* The host will use this function to set a "more" flag in the initial
* and interior frames of the batch, to tell the target that more tx frame
* downloads within the batch are imminent.
*
* @param pdev - the handle of the physical device sending the tx data
* @param desc - abstract handle to the tx descriptor
*/
void
htt_tx_desc_flag_batch_more(htt_pdev_handle pdev, void *desc);
/**
* @brief Specify the number of fragments in the fragmentation descriptor.
* @details
* Specify the number of fragments within the MSDU, i.e. the number of
* elements within the fragmentation descriptor.
* For LL, this is used to terminate the list of fragments used by the
* HW's tx MAC DMA.
* For HL, this is used to terminate the list of fragments provided to
* HTC for download.
*
* @param pdev - the handle of the physical device sending the tx data
* @param desc - abstract handle to the tx descriptor
* @param num_frags - the number of fragments comprising the MSDU
*/
static inline
void
htt_tx_desc_num_frags(htt_pdev_handle pdev, void *desc, u_int32_t num_frags)
{
/*
* Set the element after the valid frag elems to 0x0,
* to terminate the list of fragments.
*/
*((u_int32_t *)
(((char *) desc) + HTT_TX_DESC_LEN + num_frags * 8)) = 0;
}
/**
* @brief Specify the location and size of a fragment of a tx MSDU.
* @details
* In LL systems, the tx MAC DMA needs to know how the MSDU is constructed
* from fragments.
* In LL and HL systems, the HIF's download DMA to the target (LL: tx desc
* + header of tx payload; HL: tx desc + entire tx payload) needs to know
* where to find the fragments to download.
* The tx data SW uses this function to specify the location and size of
* each of the MSDU's fragments.
*
* @param pdev - the handle of the physical device sending the tx data
* @param desc - abstract handle to the HTT tx descriptor
* @param frag_num - which fragment is being specified (zero-based indexing)
* @param frag_phys_addr - DMA/physical address of the fragment
* @param frag_len - number of bytes within the fragment
*/
static inline
void
htt_tx_desc_frag(
htt_pdev_handle pdev,
void *desc,
int frag_num,
u_int32_t frag_phys_addr,
u_int16_t frag_len)
{
u_int32_t *word =
(u_int32_t *) (((char *) desc) + HTT_TX_DESC_LEN + frag_num * 8);
*word = frag_phys_addr;
word++;
*word = frag_len;
}
void htt_tx_desc_frags_table_set(
htt_pdev_handle pdev,
void *desc,
u_int32_t paddr,
int reset);
/**
* @brief Specify the type and subtype of a tx frame.
*
* @param pdev - the handle of the physical device sending the tx data
* @param type - format of the MSDU (802.3, native WiFi, raw, or mgmt)
* @param sub_type - sub_type (relevant for raw frames)
*/
static inline
void
htt_tx_desc_type(
htt_pdev_handle pdev,
void *htt_tx_desc,
enum wlan_frm_fmt type,
u_int8_t sub_type)
{
u_int32_t *word0;
word0 = (u_int32_t *) htt_tx_desc;
/* clear old values */
*word0 &= ~(HTT_TX_DESC_PKT_TYPE_M | HTT_TX_DESC_PKT_SUBTYPE_M);
/* write new values */
HTT_TX_DESC_PKT_TYPE_SET(*word0, type);
HTT_TX_DESC_PKT_SUBTYPE_SET(*word0, sub_type);
}
/***** TX MGMT DESC management APIs ****/
/* Number of mgmt descriptors in the pool */
#define HTT_MAX_NUM_MGMT_DESCS 32
/** htt_tx_mgmt_desc_pool_alloc
* @description - allocates the memory for mgmt frame descriptors
* @param - htt pdev object
* @param - num of descriptors to be allocated in the pool
*/
void
htt_tx_mgmt_desc_pool_alloc(struct htt_pdev_t *pdev, A_UINT32 num_elems);
/** htt_tx_mgmt_desc_alloc
* @description - reserves a mgmt descriptor from the pool
* @param - htt pdev object
* @param - pointer to variable to hold the allocated desc id
* @param - pointer to the mamangement from UMAC
* @return - pointer the allocated mgmt descriptor
*/
adf_nbuf_t
htt_tx_mgmt_desc_alloc(struct htt_pdev_t *pdev, A_UINT32 *desc_id, adf_nbuf_t mgmt_frm);
/** htt_tx_mgmt_desc_free
* @description - releases the management descriptor back to the pool
* @param - htt pdev object
* @param - descriptor ID
*/
void
htt_tx_mgmt_desc_free(struct htt_pdev_t *pdev, A_UINT8 desc_id, A_UINT32 status);
/** htt_tx_mgmt_desc_pool_free
* @description - releases all the resources allocated for mgmt desc pool
* @param - htt pdev object
*/
void
htt_tx_mgmt_desc_pool_free(struct htt_pdev_t *pdev);
/**
* @brief Provide a buffer to store a 802.11 header added by SW tx encap
*
* @param htt_tx_desc - which frame the 802.11 header is being added to
* @param new_l2_hdr_size - how large the buffer needs to be
*/
#define htt_tx_desc_mpdu_header(htt_tx_desc, new_l2_hdr_size) /*NULL*/
/**
* @brief How many tx credits would be consumed by the specified tx frame.
*
* @param msdu - the tx frame in question
* @return number of credits used for this tx frame
*/
#define htt_tx_msdu_credit(msdu) 1 /* 1 credit per buffer */
#ifdef HTT_DBG
void
htt_tx_desc_display(void *tx_desc);
#else
#define htt_tx_desc_display(tx_desc)
#endif
static inline
void htt_tx_desc_set_peer_id(void *htt_tx_desc, u_int16_t peer_id)
{
u_int16_t *peer_id_field_ptr;
peer_id_field_ptr = (u_int16_t *)
(htt_tx_desc + HTT_TX_DESC_PEERID_DESC_PADDR_OFFSET_BYTES);
*peer_id_field_ptr = peer_id;
}
static inline
void htt_tx_desc_set_chanfreq(void *htt_tx_desc, u_int16_t chanfreq)
{
u_int16_t *chanfreq_field_ptr;
chanfreq_field_ptr = (u_int16_t *)
(htt_tx_desc + HTT_TX_DESC_CHAN_FREQ_OFFSET_BYTES);
*chanfreq_field_ptr = chanfreq;
}
#endif /* _OL_HTT_TX_API__H_ */