blob: 9a13307b92c3478a029a9bcf633362999b50d7f7 [file] [log] [blame]
/*
* Copyright (c) 2011-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> / * uint16_t, etc. * / */
#include <osdep.h> /* uint16_t, etc. */
#include <qdf_nbuf.h> /* qdf_nbuf_t */
#include <ol_cfg.h> /* wlan_frm_fmt */
#include <htt.h> /* needed by inline functions */
#include <qdf_net_types.h>
#include <ol_htt_api.h> /* htt_pdev_handle */
#include <htt_types.h>
#include <qdf_trace.h>
#include <cds_api.h>
#define HTT_INVALID_CHANNEL -1
/* 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,
};
/**
* struct ocb_tx_ctrl_hdr_t - TX control header
* @version: must be 1
* @length: length of this structure
* @channel_freq: channel on which to transmit the packet
* @valid_pwr: bit 0: if set, tx pwr spec is valid
* @valid_datarate: bit 1: if set, tx MCS mask spec is valid
* @valid_retries: bit 2: if set, tx retries spec is valid
* @valid_chain_mask: bit 3: if set, chain mask is valid
* @valid_expire_tsf: bit 4: if set, tx expire TSF spec is valid
* @valid_tid: bit 5: if set, TID is valid
* @reserved0_15_6: bits 15:6 - unused, set to 0x0
* @all_flags: union of all the flags
* @expire_tsf_lo: TX expiry time (TSF) LSBs
* @expire_tsf_hi: TX expiry time (TSF) MSBs
* @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.
* @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
* @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.
* @chain_mask: specify which chains to transmit from
* @ext_tid: Extended Traffic ID (0-15)
* @reserved: Ensure that the size of the structure is a multiple of
* 4. Must be 0.
*
* 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 {
uint16_t version;
uint16_t length;
uint16_t channel_freq;
union {
struct {
uint16_t
valid_pwr:1,
valid_datarate:1,
valid_retries:1,
valid_chain_mask:1,
valid_expire_tsf:1,
valid_tid:1,
reserved0_15_6:10;
};
uint16_t all_flags;
};
uint32_t expire_tsf_lo;
uint32_t expire_tsf_hi;
int8_t pwr;
uint8_t datarate;
uint8_t retry_limit;
uint8_t chain_mask;
uint8_t ext_tid;
uint8_t 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 {
uint16_t ethertype;
#define HTT_INVALID_PEER_ID 0xffff
uint16_t peer_id;
uint8_t vdev_id;
uint8_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 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.
*/
uint8_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.
*/
uint8_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.
*/
uint8_t frame_subtype; /* enum htt_frm_subtype */
uint8_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.
uint8_t *dest_addr;
*/
uint8_t l3_hdr_offset; /* wrt qdf_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.
*/
/* uint8_t l4_hdr_offset; - wrt qdf_nbuf_data(msdu), in bytes */
} info;
/* the action sub-struct specifies how to process the MSDU */
struct {
uint8_t use_6mbps; /* mgmt frames: option to force
6 Mbps rate */
uint8_t do_encrypt;
uint8_t do_tx_complete;
uint8_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
*/
qdf_nbuf_tx_cksum_t cksum_offload;
} action;
};
static inline void htt_msdu_info_dump(struct htt_msdu_info_t *msdu_info)
{
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
"HTT MSDU info object (%p)\n", msdu_info);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" ethertype: %#x\n", msdu_info->info.ethertype);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" peer_id: %d\n", msdu_info->info.peer_id);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" vdev_id: %d\n", msdu_info->info.vdev_id);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" ext_tid: %d\n", msdu_info->info.ext_tid);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" l2_hdr_type: %d\n", msdu_info->info.l2_hdr_type);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" frame_type: %d\n", msdu_info->info.frame_type);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" frame_subtype: %d\n", msdu_info->info.frame_subtype);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" is_unicast: %u\n", msdu_info->info.is_unicast);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" l3_hdr_offset: %u\n", msdu_info->info.l3_hdr_offset);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" use 6 Mbps: %d\n", msdu_info->action.use_6mbps);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" do_encrypt: %d\n", msdu_info->action.do_encrypt);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" do_tx_complete: %d\n", msdu_info->action.do_tx_complete);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW,
" is_unicast: %u\n", msdu_info->info.is_unicast);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_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
*/
uint16_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 pdev, qdf_dma_addr_t *paddr,
uint16_t index);
/**
* @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);
#if defined(HELIUMPLUS)
/**
* @brief Allocate TX frag descriptor
* @details
* Allocate TX frag descriptor
*
* @param pdev - handle to the HTT instance that made the allocation
* @param index - tx descriptor index
* @param frag_paddr_lo - fragment descriptor physical address lower 32bits
* @param frag_ptr - fragment descriptor hlos pointe
* @return success 0
*/
int htt_tx_frag_alloc(htt_pdev_handle pdev,
u_int16_t index, qdf_dma_addr_t *frag_paddr, void **frag_ptr);
#else
static inline int htt_tx_frag_alloc(htt_pdev_handle pdev,
u_int16_t index, qdf_dma_addr_t *frag_paddr, void **frag_ptr)
{
*frag_ptr = NULL;
return 0;
}
#endif /* defined(HELIUMPLUS) */
#if defined(CONFIG_HL_SUPPORT)
/**
* @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
* @param[OUT] frag_paddr_lo - physical address of the fragment descriptor
* (MSDU Link Extension Descriptor)
*/
static inline void htt_tx_pending_discard(htt_pdev_handle pdev)
{
return;
}
#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 qdf_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, qdf_nbuf_t msdu, uint16_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
*/
qdf_nbuf_t
htt_tx_send_batch(htt_pdev_handle htt_pdev,
qdf_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,
qdf_nbuf_t msdu,
uint16_t msdu_id, enum htt_pkt_type pkt_type);
/**
* htt_pkt_dl_len_get() Gets the HTT PKT download length.
* @pdev: pointer to struct htt_pdev_t
*
* Return: size of HTT packet download length.
*/
int
htt_pkt_dl_len_get(struct htt_pdev_t *pdev);
#define HTT_TX_CLASSIFY_BIT_S 4 /* Used to set
* classify bit in HTT desc.*/
/**
* enum htt_ce_tx_pkt_type - enum of packet types to be set in CE
* descriptor
* @tx_pkt_type_raw: Value set for RAW frames
* @tx_pkt_type_native_wifi: Value set for NATIVE WIFI frames
* @tx_pkt_type_eth2: Value set for Ethernet II frames (mostly default)
* @tx_pkt_type_802_3: Value set for 802.3 / original ethernet frames
* @tx_pkt_type_mgmt: Value set for MGMT frames over HTT
*
*/
enum htt_ce_tx_pkt_type {
tx_pkt_type_raw = 0,
tx_pkt_type_native_wifi = 1,
tx_pkt_type_eth2 = 2,
tx_pkt_type_802_3 = 3,
tx_pkt_type_mgmt = 4
};
/**
* enum extension_header_type - extension header type
* @EXT_HEADER_NOT_PRESENT: extension header not present
* @OCB_MODE_EXT_HEADER: Extension header for OCB mode
* @WISA_MODE_EXT_HEADER_6MBPS: WISA mode 6Mbps header
* @WISA_MODE_EXT_HEADER_24MBPS: WISA mode 24Mbps header
*/
enum extension_header_type {
EXT_HEADER_NOT_PRESENT,
OCB_MODE_EXT_HEADER,
WISA_MODE_EXT_HEADER_6MBPS,
WISA_MODE_EXT_HEADER_24MBPS,
};
extern const uint32_t htt_to_ce_pkt_type[];
/**
* 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
void
htt_tx_desc_init(htt_pdev_handle pdev,
void *htt_tx_desc,
qdf_dma_addr_t htt_tx_desc_paddr,
uint16_t msdu_id,
qdf_nbuf_t msdu, struct htt_msdu_info_t *msdu_info,
struct qdf_tso_info_t *tso_info,
void *ext_header_data,
enum extension_header_type type);
/**
* @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, uint32_t num_frags)
{
/*
* Set the element after the valid frag elems to 0x0,
* to terminate the list of fragments.
*/
#if defined(HELIUMPLUS)
if (HTT_WIFI_IP(pdev, 2, 0)) {
struct msdu_ext_frag_desc *fdesc;
/** Skip TSO related 4 dwords WIFI2.0*/
fdesc = (struct msdu_ext_frag_desc *)
&(((struct msdu_ext_desc_t *)desc)->frags[0]);
fdesc[num_frags].u.desc64 = 0;
} else {
/* This piece of code should never be executed on HELIUMPLUS */
*((u_int32_t *)
(((char *) desc) + HTT_TX_DESC_LEN + num_frags * 8)) = 0;
}
#else /* ! HELIUMPLUS */
*((uint32_t *)
(((char *)desc) + HTT_TX_DESC_LEN + num_frags * 8)) = 0;
#endif /* HELIUMPLUS */
}
/* checksum offload flags for hw */
#define IPV4_CSUM_EN 0x00010000
#define UDP_IPV4_CSUM_EN 0x00020000
#define UDP_IPV6_CSUM_EN 0x00040000
#define TCP_IPV4_CSUM_EN 0x00080000
#define TCP_IPV6_CSUM_EN 0x00100000
#define PARTIAL_CSUM_EN 0x00200000
/**
* @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, qdf_dma_addr_t frag_phys_addr, uint16_t frag_len)
{
uint32_t *word32;
#if defined(HELIUMPLUS)
uint64_t *word64;
if (HTT_WIFI_IP(pdev, 2, 0)) {
word32 = (u_int32_t *)(desc);
/* Initialize top 6 words of TSO flags per packet */
*word32++ = 0;
*word32++ = 0;
*word32++ = 0;
if (((struct txrx_pdev_cfg_t *)(pdev->ctrl_pdev))
->ip_tcp_udp_checksum_offload)
*word32 |= (IPV4_CSUM_EN | TCP_IPV4_CSUM_EN |
TCP_IPV6_CSUM_EN | UDP_IPV4_CSUM_EN |
UDP_IPV6_CSUM_EN);
else
*word32 = 0;
word32++;
*word32++ = 0;
*word32++ = 0;
qdf_assert_always(word32 == (uint32_t *)
&(((struct msdu_ext_desc_t *)desc)->frags[0]));
/* Each fragment consumes 2 DWORDS */
word32 += (frag_num << 1);
word64 = (uint64_t *)word32;
*word64 = frag_phys_addr;
/* The frag_phys address is 37 bits. So, the higher 16 bits will be
for len */
word32++;
*word32 &= 0x0000ffff;
*word32 |= (frag_len << 16);
} else {
/* For Helium+, this block cannot exist */
QDF_ASSERT(0);
}
#else /* !defined(HELIUMPLUS) */
{
uint64_t u64 = (uint64_t)frag_phys_addr;
uint32_t u32l = (u64 & 0xffffffff);
uint32_t u32h = (uint32_t)((u64 >> 32) & 0x1f);
uint64_t *word64;
word32 = (uint32_t *) (((char *)desc) + HTT_TX_DESC_LEN + frag_num * 8);
word64 = (uint64_t *)word32;
*word32 = u32l;
word32++;
*word32 = (u32h << 16) | frag_len;
}
#endif /* defined(HELIUMPLUS) */
}
void htt_tx_desc_frags_table_set(htt_pdev_handle pdev,
void *desc,
qdf_dma_addr_t paddr,
qdf_dma_addr_t frag_desc_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, uint8_t sub_type)
{
uint32_t *word0;
word0 = (uint32_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
*/
qdf_nbuf_t
htt_tx_mgmt_desc_alloc(struct htt_pdev_t *pdev, A_UINT32 *desc_id,
qdf_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, uint16_t peer_id)
{
uint16_t *peer_id_field_ptr;
peer_id_field_ptr = (uint16_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, uint16_t chanfreq)
{
uint16_t *chanfreq_field_ptr;
/* The reason we dont use CHAN_FREQ_OFFSET_BYTES is because
it uses DWORD as unit */
/* The reason we dont use the SET macro in htt.h is because
htt_tx_desc is incomplete type */
chanfreq_field_ptr = (uint16_t *)
(htt_tx_desc +
HTT_TX_DESC_PEERID_DESC_PADDR_OFFSET_BYTES
+ sizeof(A_UINT16));
*chanfreq_field_ptr = chanfreq;
}
#if defined(FEATURE_TSO)
void
htt_tx_desc_fill_tso_info(htt_pdev_handle pdev, void *desc,
struct qdf_tso_info_t *tso_info);
#else
#define htt_tx_desc_fill_tso_info(pdev, desc, tso_info)
#endif
#endif /* _OL_HTT_TX_API__H_ */