blob: e28bb0cda6cb10e8af9ac6d9fa0f9ac6c8a1398a [file] [log] [blame]
/*
* Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
*
* 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.
*/
/**
* @file ol_tx.h
* @brief Internal definitions for the high-level tx module.
*/
#ifndef _OL_TX__H_
#define _OL_TX__H_
#include <qdf_nbuf.h> /* qdf_nbuf_t */
#include <qdf_lock.h>
#include <cdp_txrx_cmn.h> /* ol_txrx_vdev_t, etc. */
#include <cdp_txrx_misc.h> /* ol_tx_spec */
#include <cdp_txrx_handle.h>
#include <ol_txrx_types.h> /* ol_tx_desc_t, ol_txrx_msdu_info_t */
#include <ol_txrx.h>
#include <hif.h>
#ifdef IPA_OFFLOAD
/**
* ol_tx_send_ipa_data_frame() - send IPA data frame
* @soc_hdl: datapath soc handle
* @vdev: virtual interface id
* @skb: skb
*
* Return: skb/ NULL is for success
*/
qdf_nbuf_t ol_tx_send_ipa_data_frame(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
qdf_nbuf_t skb);
#endif
#ifdef CONFIG_LL_DP_SUPPORT
struct ol_tx_desc_t *
ol_tx_prepare_ll(ol_txrx_vdev_handle vdev,
qdf_nbuf_t msdu,
struct ol_txrx_msdu_info_t *msdu_info);
#endif
qdf_nbuf_t ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
#ifdef WLAN_FEATURE_FASTPATH
qdf_nbuf_t ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
void ol_tx_setup_fastpath_ce_handles(struct hif_opaque_softc *osc,
struct ol_txrx_pdev_t *pdev);
#else
static inline
void ol_tx_setup_fastpath_ce_handles(struct hif_opaque_softc *osc,
struct ol_txrx_pdev_t *pdev)
{ }
qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
#endif
qdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
#ifdef CONFIG_HL_SUPPORT
#define OL_TX_SEND ol_tx_hl
#else
#define OL_TX_SEND OL_TX_LL
#endif
#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
#define OL_TX_LL ol_tx_ll_queue
#else
#define OL_TX_LL ol_tx_ll_wrapper
#endif
#ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE
void ol_tx_hl_vdev_bundle_timer(void *context);
void ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t *vdev);
qdf_nbuf_t
ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t *pdev);
#else
static inline
void ol_tx_hl_vdev_bundle_timer(void *context)
{
}
static inline
void ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t *vdev)
{
}
static inline
qdf_nbuf_t
ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t *pdev)
{
return NULL;
}
#endif
#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
void ol_tx_vdev_ll_pause_queue_send(void *context);
void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev);
#else
static inline void ol_tx_vdev_ll_pause_queue_send(void *context)
{
}
static inline
void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev)
{
}
#endif
static inline
int ol_txrx_tx_is_raw(enum ol_tx_spec tx_spec)
{
return tx_spec &
(OL_TX_SPEC_RAW | OL_TX_SPEC_NO_AGGR | OL_TX_SPEC_NO_ENCRYPT);
}
static inline
uint8_t ol_txrx_tx_raw_subtype(enum ol_tx_spec tx_spec)
{
uint8_t sub_type = 0x1; /* 802.11 MAC header present */
if (tx_spec & OL_TX_SPEC_NO_AGGR)
sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_AGGR_S;
if (tx_spec & OL_TX_SPEC_NO_ENCRYPT)
sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S;
if (tx_spec & OL_TX_SPEC_NWIFI_NO_ENCRYPT)
sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S;
return sub_type;
}
/**
* ol_tx_hl() - transmit tx frames for a HL system.
* @vdev: the virtual device transmit the data
* @msdu_list: the tx frames to send
*
* Return: NULL if all MSDUs are accepted
*/
qdf_nbuf_t
ol_tx_hl(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
/**
* ol_tx_non_std() - Allow the control-path SW to send data frames
* @soc_hdl: Datapath soc handle
* @vdev_id: id of vdev
* @tx_spec: what non-standard handling to apply to the tx data frames
* @msdu_list: NULL-terminated list of tx MSDUs
*
* Generally, all tx data frames come from the OS shim into the txrx layer.
* However, there are rare cases such as TDLS messaging where the UMAC
* control-path SW creates tx data frames.
* This UMAC SW can call this function to provide the tx data frames to
* the txrx layer.
* The UMAC SW can request a callback for these data frames after their
* transmission completes, by using the ol_txrx_data_tx_cb_set function
* to register a tx completion callback, and by specifying
* ol_tx_spec_no_free as the tx_spec arg when giving the frames to
* ol_tx_non_std.
* The MSDUs need to have the appropriate L2 header type (802.3 vs. 802.11),
* as specified by ol_cfg_frame_type().
*
* Return: null - success, skb - failure
*/
#ifdef CONFIG_HL_SUPPORT
qdf_nbuf_t ol_tx_non_std_hl(struct ol_txrx_vdev_t *vdev,
enum ol_tx_spec tx_spec,
qdf_nbuf_t msdu_list);
static inline qdf_nbuf_t
ol_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list)
{
struct ol_txrx_vdev_t *vdev;
vdev = (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
return ol_tx_non_std_hl(vdev, tx_spec, msdu_list);
}
#else
qdf_nbuf_t ol_tx_non_std_ll(struct ol_txrx_vdev_t *vdev,
enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list);
static inline qdf_nbuf_t
ol_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list)
{
struct ol_txrx_vdev_t *vdev;
vdev = (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
return ol_tx_non_std_ll(vdev, tx_spec, msdu_list);
}
#endif
void ol_txrx_mgmt_tx_complete(void *ctxt, qdf_nbuf_t netbuf, int err);
/**
* ol_txrx_mgmt_tx_cb_set() - Store a callback for delivery
* notifications for management frames.
* @ppdev: the data physical device object
* @type: the type of mgmt frame the callback is used for
* @download_cb: the callback for notification of delivery to the target
* @ota_ack_cb: the callback for notification of delivery to the peer
* @ctxt: context to use with the callback
*
* When the txrx SW receives notifications from the target that a tx frame
* has been delivered to its recipient, it will check if the tx frame
* is a management frame. If so, the txrx SW will check the management
* frame type specified when the frame was submitted for transmission.
* If there is a callback function registered for the type of management
* frame in question, the txrx code will invoke the callback to inform
* the management + control SW that the mgmt frame was delivered.
* This function is used by the control SW to store a callback pointer
* for a given type of management frame.
*/
void
ol_txrx_mgmt_tx_cb_set(struct cdp_pdev *ppdev, uint8_t type,
ol_txrx_mgmt_tx_cb download_cb,
ol_txrx_mgmt_tx_cb ota_ack_cb, void *ctxt);
/**
* ol_txrx_mgmt_send_ext() - Transmit a management frame
* @pvdev: virtual device transmitting the frame
* @tx_mgmt_frm: management frame to transmit
* @type: the type of management frame (determines what callback to use)
* @use_6mbps: specify whether management frame to transmit should
* use 6 Mbps rather than 1 Mbps min rate(for 5GHz band or P2P)
* @chanfreq: channel to transmit the frame on
*
* Send the specified management frame from the specified virtual device.
* The type is used for determining whether to invoke a callback to inform
* the sender that the tx mgmt frame was delivered, and if so, which
* callback to use.
*
* Return: 0 - the frame is accepted for transmission
* 1 - the frame was not accepted
*/
int
ol_txrx_mgmt_send_ext(struct cdp_vdev *pvdev,
qdf_nbuf_t tx_mgmt_frm,
uint8_t type, uint8_t use_6mbps, uint16_t chanfreq);
qdf_nbuf_t
ol_tx_reinject(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu, uint16_t peer_id);
#if defined(FEATURE_TSO)
void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg);
void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev);
void ol_tso_num_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg);
void ol_tso_num_seg_list_deinit(struct ol_txrx_pdev_t *pdev);
uint32_t ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t *pdev);
uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,
qdf_nbuf_t msdu,
struct ol_txrx_msdu_info_t *msdu_info);
void ol_tx_tso_update_stats(struct ol_txrx_pdev_t *pdev,
struct qdf_tso_info_t *tso_info, qdf_nbuf_t msdu,
uint32_t tso_msdu_idx);
#else
static inline uint32_t ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t *pdev)
{
return 0;
}
static inline void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev,
uint32_t num_seg)
{
}
static inline void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev)
{
}
static inline void ol_tso_num_seg_list_init(struct ol_txrx_pdev_t *pdev,
uint32_t num_seg)
{
}
static inline void ol_tso_num_seg_list_deinit(struct ol_txrx_pdev_t *pdev)
{
}
static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,
qdf_nbuf_t msdu,
struct ol_txrx_msdu_info_t *msdu_info)
{
return 0;
}
static inline void ol_tx_tso_update_stats(struct ol_txrx_pdev_t *pdev,
struct qdf_tso_info_t *tso_info,
qdf_nbuf_t msdu,
uint32_t tso_msdu_idx)
{
}
#endif
#ifdef QCA_HL_NETDEV_FLOW_CONTROL
bool ol_tx_desc_is_high_prio(qdf_nbuf_t msdu);
#endif
#if defined(HELIUMPLUS)
void ol_txrx_dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc);
#else
static inline
void ol_txrx_dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc)
{
}
#endif
#endif /* _OL_TX__H_ */