qcacmn: Add Non Association WDS(NAWDS) Support for Lithium

Add API to handle NAWDS packets on tx side.
Add API to handle invalid peers and pass them to umac.

Change-Id: Ie8c2508e4f51c7d6969c9eb6439919c57dd427d4
CRs-Fixed: 2008205
This commit is contained in:
Ishank Jain
2017-03-30 18:37:42 +05:30
committed by Sandeep Puligilla
parent e0a0247ead
commit 9f174c6e2f
9 changed files with 231 additions and 6 deletions

View File

@@ -401,7 +401,17 @@ struct cdp_soc_t {
struct ol_if_ops *ol_ops;
};
/*
* cdp_vdev_param_type: different types of parameters
* to set values in vdev
* @CDP_ENABLE_NAWDS: set nawds enable/disable
* @CDP_ENABLE_MCAST_EN: enable/disable multicast enhancement
*
*/
enum cdp_vdev_param_type {
CDP_ENABLE_NAWDS,
CDP_ENABLE_MCAST_EN,
};
#define TXRX_FW_STATS_TXSTATS 1
#define TXRX_FW_STATS_RXSTATS 2

View File

@@ -288,4 +288,22 @@ static inline void cdp_tx_flush_buffers
return;
}
static inline void cdp_txrx_set_vdev_param(ol_txrx_soc_handle soc,
struct cdp_vdev *vdev, enum cdp_vdev_param_type type,
uint32_t val)
{
if (soc->ops->ctrl_ops->txrx_set_vdev_param)
return soc->ops->ctrl_ops->txrx_set_vdev_param(vdev, type, val);
return;
}
static inline void
cdp_peer_set_nawds(ol_txrx_soc_handle soc,
struct ol_txrx_peer_t *peer, uint8_t value)
{
if (soc->ops->ctrl_ops->txrx_peer_set_nawds)
return soc->ops->ctrl_ops->txrx_peer_set_nawds
(peer, value);
return;
}
#endif

View File

@@ -359,6 +359,10 @@ struct cdp_ctrl_ops {
int (*txrx_is_target_ar900b)(struct cdp_vdev *vdev);
void (*txrx_set_vdev_param)(struct cdp_vdev *vdev,
enum cdp_vdev_param_type param, uint32_t val);
void (*txrx_peer_set_nawds)(void *peer, uint8_t value);
};
struct cdp_me_ops {
@@ -557,6 +561,7 @@ struct ol_if_ops {
struct cdp_lro_hash_config *lro_hash);
void (*update_dp_stats)(void *soc, void *stats, uint16_t id,
uint8_t type);
uint8_t (*rx_invalid_peer)(void *osif_pdev, void *msg);
/* TODO: Add any other control path calls required to OL_IF/WMA layer */
};

View File

@@ -2960,6 +2960,38 @@ dp_get_peer_stats(struct cdp_pdev *pdev_handle, char *mac_addr)
dp_print_peer_stats(peer);
return;
}
/*
* dp_set_vdev_param: function to set parameters in vdev
* @param: parameter type to be set
* @val: value of parameter to be set
*
* return: void
*/
static void dp_set_vdev_param(struct cdp_vdev *vdev_handle,
enum cdp_vdev_param_type param, uint32_t val)
{
struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle;
switch (param) {
case CDP_ENABLE_NAWDS:
vdev->nawds_enabled = val;
default:
break;
}
}
/**
* dp_peer_set_nawds: set nawds bit in peer
* @peer_handle: pointer to peer
* @value: enable/disable nawds
*
* return: void
*/
static void dp_peer_set_nawds(void *peer_handle, uint8_t value)
{
struct dp_peer *peer = (struct dp_peer *)peer_handle;
peer->nawds_enabled = value;
}
/*
* dp_set_vdev_dscp_tid_map_wifi3(): Update Map ID selected for particular vdev
@@ -3065,6 +3097,8 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
.txrx_set_mesh_mode = dp_peer_set_mesh_mode,
.txrx_set_mesh_rx_filter = dp_peer_set_mesh_rx_filter,
#endif
.txrx_set_vdev_param = dp_set_vdev_param,
.txrx_peer_set_nawds = dp_peer_set_nawds,
/* TODO: Add other functions */
};

View File

@@ -495,6 +495,78 @@ QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
#endif
#ifdef CONFIG_WIN
/**
* dp_rx_process_invalid_peer(): Function to pass invalid peer list to umac
* @soc: DP SOC handle
* @nbuf: nbuf for which peer is invalid
*
* return: integer type
*/
uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
{
struct dp_invalid_peer_msg msg;
struct dp_vdev *vdev = NULL;
struct dp_pdev *pdev = NULL;
struct ieee80211_frame *wh;
uint8_t i;
uint8_t *rx_pkt_hdr;
rx_pkt_hdr = qdf_nbuf_data(nbuf);
wh = (struct ieee80211_frame *)rx_pkt_hdr;
if (!DP_FRAME_IS_DATA(wh)) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
"NAWDS valid only for data frames");
return 1;
}
if (qdf_nbuf_len(nbuf) < sizeof(struct ieee80211_frame)) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"Invalid nbuf length");
return 1;
}
for (i = 0; i < MAX_PDEV_CNT; i++) {
pdev = soc->pdev_list[i];
if (!pdev) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"PDEV not found");
continue;
}
TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
if (qdf_mem_cmp(wh->i_addr1, vdev->mac_addr.raw,
DP_MAC_ADDR_LEN) == 0) {
goto out;
}
}
}
if (!vdev) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"VDEV not found");
return 1;
}
out:
msg.wh = wh;
msg.nbuf = nbuf;
msg.vdev_id = vdev->vdev_id;
if (pdev->soc->cdp_soc.ol_ops->rx_invalid_peer)
return pdev->soc->cdp_soc.ol_ops->rx_invalid_peer(
pdev->osif_pdev, &msg);
return 0;
}
#else
uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
{
return 0;
}
#endif
/**
* dp_rx_process() - Brain of the Rx processing functionality
* Called from the bottom half (tasklet/NET_RX_SOFTIRQ)
@@ -717,6 +789,7 @@ done:
/* Peer lookup failed */
if (!peer && !vdev) {
dp_rx_process_invalid_peer(soc, nbuf);
/* Drop & free packet */
qdf_nbuf_free(nbuf);

View File

@@ -256,6 +256,7 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc,
}
#endif
uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf);
#define DP_RX_LIST_APPEND(head, tail, elem) \
do { \
if (!(head)) { \

View File

@@ -274,7 +274,8 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
if (!peer) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("peer is NULL"));
qdf_nbuf_free(nbuf);
qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN);
dp_rx_process_invalid_peer(soc, nbuf);
goto fail;
}

View File

@@ -830,20 +830,23 @@ static void dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
* @nbuf: skb
* @tid: TID from HLOS for overriding default DSCP-TID mapping
* @tx_q: Tx queue to be used for this Tx frame
* @peer_id: peer_id of the peer in case of NAWDS frames
*
* Return: NULL on success,
* nbuf when it fails to send
*/
static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
uint8_t tid, struct dp_tx_queue *tx_q,
uint32_t *meta_data)
uint32_t *meta_data, uint16_t peer_id)
{
struct dp_pdev *pdev = vdev->pdev;
struct dp_soc *soc = pdev->soc;
struct dp_tx_desc_s *tx_desc;
QDF_STATUS status;
void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng;
uint16_t htt_tcl_metadata = 0;
HTT_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 0);
/* Setup Tx descriptor for an MSDU, and MSDU extension descriptor */
tx_desc = dp_tx_prepare_desc_single(vdev, nbuf, tx_q->desc_pool_id, meta_data);
if (!tx_desc) {
@@ -862,9 +865,17 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
goto fail_return;
}
if (qdf_unlikely(peer_id != HTT_INVALID_PEER)) {
HTT_TX_TCL_METADATA_TYPE_SET(htt_tcl_metadata,
HTT_TCL_METADATA_TYPE_PEER_BASED);
HTT_TX_TCL_METADATA_PEER_ID_SET(htt_tcl_metadata,
peer_id);
} else
htt_tcl_metadata = vdev->htt_tcl_metadata;
/* Enqueue the Tx MSDU descriptor to HW for transmit */
status = dp_tx_hw_enqueue(soc, vdev, tx_desc, tid,
vdev->htt_tcl_metadata, tx_q->ring_id);
htt_tcl_metadata, tx_q->ring_id);
if (status != QDF_STATUS_SUCCESS) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
@@ -1160,6 +1171,49 @@ void dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
#endif
/**
* dp_tx_prepare_nawds(): Tramit NAWDS frames
* @vdev: dp_vdev handle
* @nbuf: skb
* @tid: TID from HLOS for overriding default DSCP-TID mapping
* @tx_q: Tx queue to be used for this Tx frame
* @meta_data: Meta date for mesh
* @peer_id: peer_id of the peer in case of NAWDS frames
*
* return: NULL on success nbuf on failure
*/
static qdf_nbuf_t dp_tx_prepare_nawds(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
uint8_t tid, struct dp_tx_queue *tx_q, uint32_t *meta_data,
uint32_t peer_id)
{
struct dp_peer *peer = NULL;
qdf_nbuf_t nbuf_copy;
TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
if ((peer->peer_ids[0] != HTT_INVALID_PEER) &&
(peer->nawds_enabled || peer->bss_peer)) {
nbuf_copy = qdf_nbuf_copy(nbuf);
if (!nbuf_copy) {
QDF_TRACE(QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_ERROR,
"nbuf copy failed");
}
peer_id = peer->peer_ids[0];
nbuf_copy = dp_tx_send_msdu_single(vdev, nbuf_copy, tid,
tx_q, meta_data, peer_id);
if (nbuf_copy != NULL) {
qdf_nbuf_free(nbuf);
return nbuf_copy;
}
}
}
if (peer_id == HTT_INVALID_PEER)
return nbuf;
qdf_nbuf_free(nbuf);
return NULL;
}
/**
* dp_tx_send() - Transmit a frame on a given VAP
* @vap_dev: DP vdev handle
@@ -1174,10 +1228,11 @@ void dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
*/
qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
{
struct ether_header *eh;
struct ether_header *eh = NULL;
struct dp_tx_msdu_info_s msdu_info;
struct dp_tx_seg_info_s seg_info;
struct dp_vdev *vdev = (struct dp_vdev *) vap_dev;
uint16_t peer_id = HTT_INVALID_PEER;
qdf_mem_set(&msdu_info, sizeof(msdu_info), 0x0);
qdf_mem_set(&seg_info, sizeof(seg_info), 0x0);
@@ -1294,6 +1349,16 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
}
if (vdev->nawds_enabled) {
eh = (struct ether_header *)qdf_nbuf_data(nbuf);
if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost)) {
nbuf = dp_tx_prepare_nawds(vdev, nbuf, msdu_info.tid,
&msdu_info.tx_queue,
msdu_info.meta_data, peer_id);
return nbuf;
}
}
/* Single linear frame */
/*
* If nbuf is a simple linear frame, use send_single function to
@@ -1301,7 +1366,7 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
* SRNG. There is no need to setup a MSDU extension descriptor.
*/
nbuf = dp_tx_send_msdu_single(vdev, nbuf, msdu_info.tid,
&msdu_info.tx_queue, msdu_info.meta_data);
&msdu_info.tx_queue, msdu_info.meta_data, peer_id);
return nbuf;

View File

@@ -104,6 +104,10 @@ union dp_rx_desc_list_elem_t;
(_a)[4] == 0xff && \
(_a)[5] == 0xff)
#define IS_LLC_PRESENT(typeorlen) ((typeorlen) >= 0x600)
#define DP_FRAME_FC0_TYPE_MASK 0x0c
#define DP_FRAME_FC0_TYPE_DATA 0x08
#define DP_FRAME_IS_DATA(_frame) \
(((_frame)->i_fc[0] & DP_FRAME_FC0_TYPE_MASK) == DP_FRAME_FC0_TYPE_DATA)
/**
* macros to convert hw mac id to sw mac id:
@@ -968,4 +972,18 @@ struct dp_peer {
TAILQ_HEAD(, dp_ast_entry) ast_entry_list;
/* TBD */
};
#ifdef CONFIG_WIN
/*
* dp_invalid_peer_msg
* @nbuf: data buffer
* @wh: 802.11 header
* @vdev_id: id of vdev
*/
struct dp_invalid_peer_msg {
qdf_nbuf_t nbuf;
struct ieee80211_frame *wh;
uint8_t vdev_id;
};
#endif
#endif /* _DP_TYPES_H_ */