Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 1 | /* |
Tallapragada Kalyan | 1b4d08d | 2016-12-15 22:19:58 +0530 | [diff] [blame] | 2 | * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for |
| 5 | * any purpose with or without fee is hereby granted, provided that the |
| 6 | * above copyright notice and this permission notice appear in all |
| 7 | * copies. |
| 8 | * |
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| 13 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| 14 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 15 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 16 | * PERFORMANCE OF THIS SOFTWARE. |
| 17 | */ |
| 18 | |
| 19 | #include "dp_types.h" |
| 20 | #include "dp_rx.h" |
| 21 | #include "dp_peer.h" |
| 22 | #include "hal_rx.h" |
| 23 | #include "hal_api.h" |
| 24 | #include "qdf_nbuf.h" |
| 25 | #include <ieee80211.h> |
Venkateswara Swamy Bandaru | c14b1b6 | 2017-02-24 12:26:08 +0530 | [diff] [blame] | 26 | #ifdef MESH_MODE_SUPPORT |
| 27 | #include "if_meta_hdr.h" |
| 28 | #endif |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 29 | #include "dp_internal.h" |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 30 | |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 31 | /* |
| 32 | * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs |
| 33 | * called during dp rx initialization |
| 34 | * and at the end of dp_rx_process. |
| 35 | * |
| 36 | * @soc: core txrx main context |
| 37 | * @mac_id: mac_id which is one of 3 mac_ids |
| 38 | * @desc_list: list of descs if called from dp_rx_process |
| 39 | * or NULL during dp rx initialization or out of buffer |
| 40 | * interrupt. |
| 41 | * @owner: who owns the nbuf (host, NSS etc...) |
| 42 | * Return: return success or failure |
| 43 | */ |
| 44 | QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, |
| 45 | uint32_t num_req_buffers, |
| 46 | union dp_rx_desc_list_elem_t **desc_list, |
| 47 | union dp_rx_desc_list_elem_t **tail, |
| 48 | uint8_t owner) |
| 49 | { |
| 50 | uint32_t num_alloc_desc; |
| 51 | uint16_t num_desc_to_free = 0; |
| 52 | struct dp_pdev *dp_pdev = dp_soc->pdev_list[mac_id]; |
| 53 | uint32_t num_entries_avail; |
| 54 | uint32_t count; |
| 55 | int sync_hw_ptr = 1; |
| 56 | qdf_dma_addr_t paddr; |
| 57 | qdf_nbuf_t rx_netbuf; |
| 58 | void *rxdma_ring_entry; |
| 59 | union dp_rx_desc_list_elem_t *next; |
Dhanashri Atre | 7351d17 | 2016-10-12 13:08:09 -0700 | [diff] [blame] | 60 | struct dp_srng *dp_rxdma_srng = &dp_pdev->rx_refill_buf_ring; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 61 | void *rxdma_srng = dp_rxdma_srng->hal_srng; |
Tallapragada Kalyan | 4e3341a | 2017-02-06 12:19:43 +0530 | [diff] [blame] | 62 | int32_t ret; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 63 | |
| 64 | if (!rxdma_srng) { |
| 65 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 66 | "rxdma srng not initialized"); |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 67 | DP_STATS_INC(dp_pdev, err.rxdma_unitialized, 1); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 68 | return QDF_STATUS_E_FAILURE; |
| 69 | } |
| 70 | |
| 71 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 72 | "requested %d buffers for replenish", num_req_buffers); |
| 73 | |
| 74 | /* |
| 75 | * if desc_list is NULL, allocate the descs from freelist |
| 76 | */ |
| 77 | if (!(*desc_list)) { |
| 78 | num_alloc_desc = dp_rx_get_free_desc_list(dp_soc, mac_id, |
| 79 | num_req_buffers, |
| 80 | desc_list, |
| 81 | tail); |
| 82 | |
| 83 | if (!num_alloc_desc) { |
| 84 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 85 | "no free rx_descs in freelist"); |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 86 | DP_STATS_INC(dp_pdev, err.desc_alloc_fail, |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 87 | num_alloc_desc); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 88 | return QDF_STATUS_E_NOMEM; |
| 89 | } |
| 90 | |
| 91 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 92 | "%d rx desc allocated", num_alloc_desc); |
| 93 | num_req_buffers = num_alloc_desc; |
| 94 | } |
| 95 | |
| 96 | hal_srng_access_start(dp_soc->hal_soc, rxdma_srng); |
| 97 | num_entries_avail = hal_srng_src_num_avail(dp_soc->hal_soc, |
| 98 | rxdma_srng, |
| 99 | sync_hw_ptr); |
| 100 | |
| 101 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 102 | "no of availble entries in rxdma ring: %d", |
| 103 | num_entries_avail); |
| 104 | |
| 105 | if (num_entries_avail < num_req_buffers) { |
| 106 | num_desc_to_free = num_req_buffers - num_entries_avail; |
| 107 | num_req_buffers = num_entries_avail; |
| 108 | } |
| 109 | |
Tallapragada Kalyan | 4e3341a | 2017-02-06 12:19:43 +0530 | [diff] [blame] | 110 | count = 0; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 111 | |
Tallapragada Kalyan | 4e3341a | 2017-02-06 12:19:43 +0530 | [diff] [blame] | 112 | while (count < num_req_buffers) { |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 113 | rx_netbuf = qdf_nbuf_alloc(dp_pdev->osif_pdev, |
| 114 | RX_BUFFER_SIZE, |
| 115 | RX_BUFFER_RESERVATION, |
| 116 | RX_BUFFER_ALIGNMENT, |
| 117 | FALSE); |
| 118 | |
Houston Hoffman | fc0a960 | 2017-01-26 22:36:31 -0800 | [diff] [blame] | 119 | if (rx_netbuf == NULL) |
Tallapragada Kalyan | 4e3341a | 2017-02-06 12:19:43 +0530 | [diff] [blame] | 120 | continue; |
Houston Hoffman | fc0a960 | 2017-01-26 22:36:31 -0800 | [diff] [blame] | 121 | |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 122 | qdf_nbuf_map_single(dp_soc->osdev, rx_netbuf, |
| 123 | QDF_DMA_BIDIRECTIONAL); |
| 124 | |
| 125 | paddr = qdf_nbuf_get_frag_paddr(rx_netbuf, 0); |
| 126 | |
Tallapragada Kalyan | 4e3341a | 2017-02-06 12:19:43 +0530 | [diff] [blame] | 127 | /* |
| 128 | * check if the physical address of nbuf->data is |
| 129 | * less then 0x50000000 then free the nbuf and try |
| 130 | * allocating new nbuf. We can try for 100 times. |
| 131 | * this is a temp WAR till we fix it properly. |
| 132 | */ |
| 133 | ret = check_x86_paddr(dp_soc, &rx_netbuf, &paddr, dp_pdev); |
| 134 | if (ret == QDF_STATUS_E_FAILURE) |
| 135 | break; |
| 136 | |
| 137 | count++; |
| 138 | |
| 139 | rxdma_ring_entry = hal_srng_src_get_next(dp_soc->hal_soc, |
| 140 | rxdma_srng); |
| 141 | |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 142 | next = (*desc_list)->next; |
| 143 | |
| 144 | (*desc_list)->rx_desc.nbuf = rx_netbuf; |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 145 | DP_STATS_INC_PKT(dp_pdev, replenished, 1, |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 146 | qdf_nbuf_len(rx_netbuf)); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 147 | hal_rxdma_buff_addr_info_set(rxdma_ring_entry, paddr, |
| 148 | (*desc_list)->rx_desc.cookie, |
| 149 | owner); |
| 150 | |
| 151 | *desc_list = next; |
| 152 | } |
| 153 | |
| 154 | hal_srng_access_end(dp_soc->hal_soc, rxdma_srng); |
| 155 | |
| 156 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 157 | "successfully replenished %d buffers", num_req_buffers); |
| 158 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 159 | "%d rx desc added back to free list", num_desc_to_free); |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 160 | DP_STATS_INC(dp_pdev, buf_freelist, num_desc_to_free); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 161 | |
| 162 | /* |
| 163 | * add any available free desc back to the free list |
| 164 | */ |
| 165 | if (*desc_list) |
| 166 | dp_rx_add_desc_list_to_free_list(dp_soc, desc_list, |
| 167 | tail, mac_id); |
| 168 | |
| 169 | return QDF_STATUS_SUCCESS; |
| 170 | } |
| 171 | |
Kalyan Tallapragada | 277f45e | 2017-01-30 14:25:27 +0530 | [diff] [blame] | 172 | /* |
| 173 | * dp_rx_deliver_raw() - process RAW mode pkts and hand over the |
| 174 | * pkts to RAW mode simulation to |
| 175 | * decapsulate the pkt. |
| 176 | * |
| 177 | * @vdev: vdev on which RAW mode is enabled |
| 178 | * @nbuf_list: list of RAW pkts to process |
| 179 | * |
| 180 | * Return: void |
| 181 | */ |
| 182 | static void |
| 183 | dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list) |
| 184 | { |
| 185 | qdf_nbuf_t deliver_list_head = NULL; |
| 186 | qdf_nbuf_t deliver_list_tail = NULL; |
| 187 | qdf_nbuf_t nbuf; |
| 188 | |
| 189 | nbuf = nbuf_list; |
| 190 | while (nbuf) { |
| 191 | qdf_nbuf_t next = qdf_nbuf_next(nbuf); |
| 192 | |
| 193 | DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, nbuf); |
| 194 | |
| 195 | /* |
| 196 | * reset the chfrag_start and chfrag_end bits in nbuf cb |
| 197 | * as this is a non-amsdu pkt and RAW mode simulation expects |
| 198 | * these bit s to be 0 for non-amsdu pkt. |
| 199 | */ |
| 200 | if (qdf_nbuf_is_chfrag_start(nbuf) && |
| 201 | qdf_nbuf_is_chfrag_end(nbuf)) { |
| 202 | qdf_nbuf_set_chfrag_start(nbuf, 0); |
| 203 | qdf_nbuf_set_chfrag_end(nbuf, 0); |
| 204 | } |
| 205 | |
| 206 | nbuf = next; |
| 207 | } |
| 208 | |
| 209 | vdev->osif_rsim_rx_decap(vdev->osif_vdev, &deliver_list_head, |
| 210 | &deliver_list_tail); |
| 211 | |
| 212 | vdev->osif_rx(vdev->osif_vdev, deliver_list_head); |
| 213 | } |
| 214 | |
| 215 | |
Pramod Simha | b17d067 | 2017-03-06 17:20:13 -0800 | [diff] [blame] | 216 | #ifdef DP_LFR |
| 217 | /* |
| 218 | * In case of LFR, data of a new peer might be sent up |
| 219 | * even before peer is added. |
| 220 | */ |
| 221 | static inline struct dp_vdev * |
| 222 | dp_get_vdev_from_peer(struct dp_soc *soc, |
| 223 | uint16_t peer_id, |
| 224 | struct dp_peer *peer, |
| 225 | struct hal_rx_mpdu_desc_info mpdu_desc_info) |
| 226 | { |
| 227 | struct dp_vdev *vdev; |
| 228 | uint8_t vdev_id; |
Kalyan Tallapragada | 277f45e | 2017-01-30 14:25:27 +0530 | [diff] [blame] | 229 | |
Pramod Simha | b17d067 | 2017-03-06 17:20:13 -0800 | [diff] [blame] | 230 | if (unlikely(!peer)) { |
| 231 | if (peer_id != HTT_INVALID_PEER) { |
| 232 | vdev_id = DP_PEER_METADATA_ID_GET( |
| 233 | mpdu_desc_info.peer_meta_data); |
| 234 | QDF_TRACE(QDF_MODULE_ID_DP, |
| 235 | QDF_TRACE_LEVEL_ERROR, |
| 236 | FL("PeerID %d not found use vdevID %d"), |
| 237 | peer_id, vdev_id); |
| 238 | vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, |
| 239 | vdev_id); |
| 240 | } else { |
| 241 | QDF_TRACE(QDF_MODULE_ID_DP, |
| 242 | QDF_TRACE_LEVEL_ERROR, |
| 243 | FL("Invalid PeerID %d"), |
| 244 | peer_id); |
| 245 | return NULL; |
| 246 | } |
| 247 | } else { |
| 248 | vdev = peer->vdev; |
| 249 | } |
| 250 | return vdev; |
| 251 | } |
| 252 | #else |
| 253 | static inline struct dp_vdev * |
| 254 | dp_get_vdev_from_peer(struct dp_soc *soc, |
| 255 | uint16_t peer_id, |
| 256 | struct dp_peer *peer, |
| 257 | struct hal_rx_mpdu_desc_info mpdu_desc_info) |
| 258 | { |
| 259 | if (unlikely(!peer)) { |
| 260 | QDF_TRACE(QDF_MODULE_ID_DP, |
| 261 | QDF_TRACE_LEVEL_ERROR, |
| 262 | FL("Peer not found for peerID %d"), |
| 263 | peer_id); |
| 264 | return NULL; |
| 265 | } else { |
| 266 | return peer->vdev; |
| 267 | } |
| 268 | } |
| 269 | #endif |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 270 | /** |
| 271 | * dp_rx_intrabss_fwd() - Implements the Intra-BSS forwarding logic |
| 272 | * |
| 273 | * @soc: core txrx main context |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 274 | * @sa_peer : source peer entry |
| 275 | * @rx_tlv_hdr : start address of rx tlvs |
| 276 | * @nbuf : nbuf that has to be intrabss forwarded |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 277 | * |
| 278 | * Return: bool: true if it is forwarded else false |
| 279 | */ |
| 280 | static bool |
| 281 | dp_rx_intrabss_fwd(struct dp_soc *soc, |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 282 | struct dp_peer *sa_peer, |
| 283 | uint8_t *rx_tlv_hdr, |
| 284 | qdf_nbuf_t nbuf) |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 285 | { |
Tallapragada Kalyan | 6f6166e | 2017-02-17 17:00:23 +0530 | [diff] [blame^] | 286 | uint16_t da_idx; |
| 287 | uint16_t len; |
| 288 | struct dp_peer *da_peer; |
| 289 | struct dp_ast_entry *ast_entry; |
| 290 | qdf_nbuf_t nbuf_copy; |
| 291 | |
| 292 | /* check if the destination peer is available in peer table |
| 293 | * and also check if the source peer and destination peer |
| 294 | * belong to the same vap and destination peer is not bss peer. |
| 295 | */ |
| 296 | if ((hal_rx_msdu_end_da_is_valid_get(rx_tlv_hdr) && |
| 297 | !hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr))) { |
| 298 | da_idx = hal_rx_msdu_end_da_idx_get(rx_tlv_hdr); |
| 299 | |
| 300 | ast_entry = soc->ast_table[da_idx]; |
| 301 | if (!ast_entry) |
| 302 | return false; |
| 303 | |
| 304 | da_peer = ast_entry->peer; |
| 305 | |
| 306 | if (!da_peer) |
| 307 | return false; |
| 308 | |
| 309 | if (da_peer->vdev == sa_peer->vdev && !da_peer->bss_peer) { |
| 310 | memset(nbuf->cb, 0x0, sizeof(nbuf->cb)); |
| 311 | len = qdf_nbuf_len(nbuf); |
| 312 | if (!dp_tx_send(sa_peer->vdev, nbuf)) { |
| 313 | DP_STATS_INC_PKT(sa_peer, rx.intra_bss, 1, len); |
| 314 | return true; |
| 315 | } else |
| 316 | return false; |
| 317 | } |
| 318 | } |
| 319 | /* if it is a broadcast pkt (eg: ARP) and it is not its own |
| 320 | * source, then clone the pkt and send the cloned pkt for |
| 321 | * intra BSS forwarding and original pkt up the network stack |
| 322 | * Note: how do we handle multicast pkts. do we forward |
| 323 | * all multicast pkts as is or let a higher layer module |
| 324 | * like igmpsnoop decide whether to forward or not with |
| 325 | * Mcast enhancement. |
| 326 | */ |
| 327 | else if (qdf_unlikely((hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr) && |
| 328 | !sa_peer->bss_peer))) { |
| 329 | nbuf_copy = qdf_nbuf_copy(nbuf); |
| 330 | if (!nbuf_copy) |
| 331 | return false; |
| 332 | memset(nbuf_copy->cb, 0x0, sizeof(nbuf_copy->cb)); |
| 333 | len = qdf_nbuf_len(nbuf_copy); |
| 334 | if (dp_tx_send(sa_peer->vdev, nbuf_copy)) |
| 335 | qdf_nbuf_free(nbuf_copy); |
| 336 | else |
| 337 | DP_STATS_INC_PKT(sa_peer, rx.intra_bss, 1, len); |
| 338 | } |
| 339 | /* return false as we have to still send the original pkt |
| 340 | * up the stack |
| 341 | */ |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 342 | return false; |
| 343 | } |
| 344 | |
Venkateswara Swamy Bandaru | c14b1b6 | 2017-02-24 12:26:08 +0530 | [diff] [blame] | 345 | #ifdef MESH_MODE_SUPPORT |
| 346 | |
| 347 | /** |
| 348 | * dp_rx_fill_mesh_stats() - Fills the mesh per packet receive stats |
| 349 | * |
| 350 | * @vdev: DP Virtual device handle |
| 351 | * @nbuf: Buffer pointer |
| 352 | * |
| 353 | * This function allocated memory for mesh receive stats and fill the |
| 354 | * required stats. Stores the memory address in skb cb. |
| 355 | * |
| 356 | * Return: void |
| 357 | */ |
| 358 | static |
| 359 | void dp_rx_fill_mesh_stats(struct dp_vdev *vdev, qdf_nbuf_t nbuf) |
| 360 | { |
| 361 | struct mesh_recv_hdr_s *rx_info = NULL; |
| 362 | uint32_t pkt_type; |
| 363 | uint32_t nss; |
| 364 | uint32_t rate_mcs; |
| 365 | uint8_t *rx_tlv_hdr = qdf_nbuf_data(nbuf); |
| 366 | |
| 367 | /* fill recv mesh stats */ |
| 368 | rx_info = qdf_mem_malloc(sizeof(struct mesh_recv_hdr_s)); |
| 369 | |
| 370 | /* upper layers are resposible to free this memory */ |
| 371 | |
| 372 | if (rx_info == NULL) { |
| 373 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 374 | "Memory allocation failed for mesh rx stats"); |
| 375 | return; |
| 376 | } |
| 377 | |
| 378 | if (qdf_nbuf_is_chfrag_start(nbuf)) |
| 379 | rx_info->rs_flags |= MESH_RX_FIRST_MSDU; |
| 380 | |
| 381 | if (qdf_nbuf_is_chfrag_end(nbuf)) |
| 382 | rx_info->rs_flags |= MESH_RX_LAST_MSDU; |
| 383 | |
| 384 | if (hal_rx_attn_msdu_get_is_decrypted(rx_tlv_hdr)) { |
| 385 | rx_info->rs_flags |= MESH_RX_DECRYPTED; |
| 386 | rx_info->rs_keyix = hal_rx_msdu_get_keyid(rx_tlv_hdr); |
| 387 | rx_info->rs_flags |= MESH_KEY_NOTFILLED; |
| 388 | } |
| 389 | |
| 390 | rx_info->rs_rssi = hal_rx_msdu_start_get_rssi(rx_tlv_hdr); |
| 391 | rx_info->rs_channel = hal_rx_msdu_start_get_freq(rx_tlv_hdr); |
| 392 | pkt_type = hal_rx_msdu_start_get_pkt_type(rx_tlv_hdr); |
| 393 | rate_mcs = hal_rx_msdu_start_rate_mcs_get(rx_tlv_hdr); |
| 394 | nss = hal_rx_msdu_start_nss_get(rx_tlv_hdr); |
| 395 | rx_info->rs_ratephy1 = rate_mcs | (nss << 0x4) | (pkt_type << 6); |
| 396 | |
| 397 | qdf_nbuf_set_fctx_type(nbuf, (void *)rx_info, CB_FTYPE_MESH_RX_INFO); |
Venkateswara Swamy Bandaru | c64c862 | 2017-02-27 20:08:33 +0530 | [diff] [blame] | 398 | |
| 399 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, |
| 400 | FL("Mesh rx stats: flags %x, rssi %x, chn %x, rate %x, kix %x"), |
| 401 | rx_info->rs_flags, |
| 402 | rx_info->rs_rssi, |
| 403 | rx_info->rs_channel, |
| 404 | rx_info->rs_ratephy1, |
| 405 | rx_info->rs_keyix); |
| 406 | |
Venkateswara Swamy Bandaru | c14b1b6 | 2017-02-24 12:26:08 +0530 | [diff] [blame] | 407 | } |
Venkateswara Swamy Bandaru | ec4f8e6 | 2017-03-07 11:04:28 +0530 | [diff] [blame] | 408 | |
| 409 | /** |
| 410 | * dp_rx_fill_mesh_stats() - Filters mesh unwanted packets |
| 411 | * |
| 412 | * @vdev: DP Virtual device handle |
| 413 | * @nbuf: Buffer pointer |
| 414 | * |
| 415 | * This checks if the received packet is matching any filter out |
| 416 | * catogery and and drop the packet if it matches. |
| 417 | * |
| 418 | * Return: status(0 indicates drop, 1 indicate to no drop) |
| 419 | */ |
| 420 | |
| 421 | static inline |
| 422 | QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf) |
| 423 | { |
| 424 | uint8_t *rx_tlv_hdr = qdf_nbuf_data(nbuf); |
| 425 | union dp_align_mac_addr mac_addr; |
| 426 | |
| 427 | if (qdf_unlikely(vdev->mesh_rx_filter)) { |
| 428 | if (vdev->mesh_rx_filter & MESH_FILTER_OUT_FROMDS) |
| 429 | if (hal_rx_mpdu_get_fr_ds(rx_tlv_hdr)) |
| 430 | return QDF_STATUS_SUCCESS; |
| 431 | |
| 432 | if (vdev->mesh_rx_filter & MESH_FILTER_OUT_TODS) |
| 433 | if (hal_rx_mpdu_get_to_ds(rx_tlv_hdr)) |
| 434 | return QDF_STATUS_SUCCESS; |
| 435 | |
| 436 | if (vdev->mesh_rx_filter & MESH_FILTER_OUT_NODS) |
| 437 | if (!hal_rx_mpdu_get_fr_ds(rx_tlv_hdr) |
| 438 | && !hal_rx_mpdu_get_to_ds(rx_tlv_hdr)) |
| 439 | return QDF_STATUS_SUCCESS; |
| 440 | |
| 441 | if (vdev->mesh_rx_filter & MESH_FILTER_OUT_RA) { |
| 442 | if (hal_rx_mpdu_get_addr1(rx_tlv_hdr, |
| 443 | &mac_addr.raw[0])) |
| 444 | return QDF_STATUS_E_FAILURE; |
| 445 | |
| 446 | if (!qdf_mem_cmp(&mac_addr.raw[0], |
| 447 | &vdev->mac_addr.raw[0], |
| 448 | DP_MAC_ADDR_LEN)) |
| 449 | return QDF_STATUS_SUCCESS; |
| 450 | } |
| 451 | |
| 452 | if (vdev->mesh_rx_filter & MESH_FILTER_OUT_TA) { |
| 453 | if (hal_rx_mpdu_get_addr2(rx_tlv_hdr, |
| 454 | &mac_addr.raw[0])) |
| 455 | return QDF_STATUS_E_FAILURE; |
| 456 | |
| 457 | if (!qdf_mem_cmp(&mac_addr.raw[0], |
| 458 | &vdev->mac_addr.raw[0], |
| 459 | DP_MAC_ADDR_LEN)) |
| 460 | return QDF_STATUS_SUCCESS; |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | return QDF_STATUS_E_FAILURE; |
| 465 | } |
| 466 | |
Venkateswara Swamy Bandaru | c14b1b6 | 2017-02-24 12:26:08 +0530 | [diff] [blame] | 467 | #else |
| 468 | static |
| 469 | void dp_rx_fill_mesh_stats(struct dp_vdev *vdev, qdf_nbuf_t nbuf) |
| 470 | { |
| 471 | } |
| 472 | |
Venkateswara Swamy Bandaru | ec4f8e6 | 2017-03-07 11:04:28 +0530 | [diff] [blame] | 473 | static inline |
| 474 | QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf) |
| 475 | { |
| 476 | return QDF_STATUS_E_FAILURE; |
| 477 | } |
| 478 | |
Venkateswara Swamy Bandaru | c14b1b6 | 2017-02-24 12:26:08 +0530 | [diff] [blame] | 479 | #endif |
| 480 | |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 481 | /** |
| 482 | * dp_rx_process() - Brain of the Rx processing functionality |
| 483 | * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) |
| 484 | * @soc: core txrx main context |
| 485 | * @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced |
| 486 | * @quota: No. of units (packets) that can be serviced in one shot. |
| 487 | * |
| 488 | * This function implements the core of Rx functionality. This is |
| 489 | * expected to handle only non-error frames. |
| 490 | * |
| 491 | * Return: uint32_t: No. of elements processed |
| 492 | */ |
| 493 | uint32_t |
| 494 | dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) |
| 495 | { |
| 496 | void *hal_soc; |
| 497 | void *ring_desc; |
| 498 | struct dp_rx_desc *rx_desc; |
| 499 | qdf_nbuf_t nbuf; |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 500 | union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT] = { NULL }; |
| 501 | union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT] = { NULL }; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 502 | uint32_t rx_bufs_used = 0, rx_buf_cookie, l2_hdr_offset; |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 503 | uint16_t msdu_len; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 504 | uint16_t peer_id; |
| 505 | struct dp_peer *peer = NULL; |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 506 | struct dp_vdev *vdev = NULL; |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 507 | struct dp_vdev *vdev_list[WLAN_UMAC_PSOC_MAX_VDEVS] = { NULL }; |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 508 | uint32_t pkt_len; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 509 | struct hal_rx_mpdu_desc_info mpdu_desc_info; |
Kalyan Tallapragada | 277f45e | 2017-01-30 14:25:27 +0530 | [diff] [blame] | 510 | struct hal_rx_msdu_desc_info msdu_desc_info; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 511 | enum hal_reo_error_status error; |
Tallapragada Kalyan | e7d51ef | 2017-02-06 11:58:21 +0530 | [diff] [blame] | 512 | static uint32_t peer_mdata; |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 513 | uint8_t *rx_tlv_hdr; |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 514 | uint32_t rx_bufs_reaped[MAX_PDEV_CNT] = { 0 }; |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 515 | uint32_t sgi, rate_mcs, tid, nss, bw, reception_type; |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 516 | uint64_t vdev_map = 0; |
| 517 | uint8_t mac_id; |
| 518 | uint16_t i, vdev_cnt = 0; |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 519 | uint32_t ampdu_flag, amsdu_flag; |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 520 | struct ether_header *eh; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 521 | |
| 522 | /* Debug -- Remove later */ |
| 523 | qdf_assert(soc && hal_ring); |
| 524 | |
| 525 | hal_soc = soc->hal_soc; |
| 526 | |
| 527 | /* Debug -- Remove later */ |
| 528 | qdf_assert(hal_soc); |
| 529 | |
| 530 | if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) { |
| 531 | |
| 532 | /* |
| 533 | * Need API to convert from hal_ring pointer to |
| 534 | * Ring Type / Ring Id combo |
| 535 | */ |
| 536 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, |
Tallapragada Kalyan | 1ef5480 | 2016-11-30 12:54:55 +0530 | [diff] [blame] | 537 | FL("HAL RING Access Failed -- %p"), hal_ring); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 538 | hal_srng_access_end(hal_soc, hal_ring); |
| 539 | goto done; |
| 540 | } |
| 541 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 542 | /* |
| 543 | * start reaping the buffers from reo ring and queue |
| 544 | * them in per vdev queue. |
| 545 | * Process the received pkts in a different per vdev loop. |
| 546 | */ |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 547 | while (qdf_likely((ring_desc = |
| 548 | hal_srng_dst_get_next(hal_soc, hal_ring)) |
| 549 | && quota--)) { |
| 550 | |
| 551 | error = HAL_RX_ERROR_STATUS_GET(ring_desc); |
| 552 | |
| 553 | if (qdf_unlikely(error == HAL_REO_ERROR_DETECTED)) { |
| 554 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
Tallapragada Kalyan | 1ef5480 | 2016-11-30 12:54:55 +0530 | [diff] [blame] | 555 | FL("HAL RING 0x%p:error %d"), hal_ring, error); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 556 | /* Don't know how to deal with this -- assert */ |
| 557 | qdf_assert(0); |
| 558 | } |
| 559 | |
| 560 | rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc); |
| 561 | |
| 562 | rx_desc = dp_rx_cookie_2_va(soc, rx_buf_cookie); |
| 563 | |
| 564 | qdf_assert(rx_desc); |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 565 | rx_bufs_reaped[rx_desc->pool_id]++; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 566 | |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 567 | /* TODO */ |
| 568 | /* |
| 569 | * Need a separate API for unmapping based on |
| 570 | * phyiscal address |
| 571 | */ |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 572 | qdf_nbuf_unmap_single(soc->osdev, rx_desc->nbuf, |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 573 | QDF_DMA_BIDIRECTIONAL); |
| 574 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 575 | /* Get MPDU DESC info */ |
| 576 | hal_rx_mpdu_desc_info_get(ring_desc, &mpdu_desc_info); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 577 | peer_id = DP_PEER_METADATA_PEER_ID_GET( |
| 578 | mpdu_desc_info.peer_meta_data); |
| 579 | |
| 580 | peer = dp_peer_find_by_id(soc, peer_id); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 581 | |
Pramod Simha | b17d067 | 2017-03-06 17:20:13 -0800 | [diff] [blame] | 582 | vdev = dp_get_vdev_from_peer(soc, peer_id, peer, |
| 583 | mpdu_desc_info); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 584 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 585 | if (!vdev) { |
| 586 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 587 | FL("vdev is NULL")); |
| 588 | qdf_nbuf_free(rx_desc->nbuf); |
| 589 | goto fail; |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 590 | |
| 591 | } |
| 592 | |
| 593 | if (!((vdev_map >> vdev->vdev_id) & 1)) { |
| 594 | vdev_map |= 1 << vdev->vdev_id; |
| 595 | vdev_list[vdev_cnt] = vdev; |
| 596 | vdev_cnt++; |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 597 | } |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 598 | |
Kalyan Tallapragada | 277f45e | 2017-01-30 14:25:27 +0530 | [diff] [blame] | 599 | /* Get MSDU DESC info */ |
| 600 | hal_rx_msdu_desc_info_get(ring_desc, &msdu_desc_info); |
| 601 | |
| 602 | /* |
| 603 | * save msdu flags first, last and continuation msdu in |
| 604 | * nbuf->cb |
| 605 | */ |
| 606 | if (msdu_desc_info.msdu_flags & HAL_MSDU_F_FIRST_MSDU_IN_MPDU) |
| 607 | qdf_nbuf_set_chfrag_start(rx_desc->nbuf, 1); |
| 608 | |
| 609 | if (msdu_desc_info.msdu_flags & HAL_MSDU_F_MSDU_CONTINUATION) |
| 610 | qdf_nbuf_set_chfrag_cont(rx_desc->nbuf, 1); |
| 611 | |
| 612 | if (msdu_desc_info.msdu_flags & HAL_MSDU_F_LAST_MSDU_IN_MPDU) |
| 613 | qdf_nbuf_set_chfrag_end(rx_desc->nbuf, 1); |
| 614 | |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 615 | DP_STATS_INC_PKT(peer, rx.rcvd_reo, 1, |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 616 | qdf_nbuf_len(rx_desc->nbuf)); |
| 617 | |
| 618 | ampdu_flag = (mpdu_desc_info.mpdu_flags & |
| 619 | HAL_MPDU_F_AMPDU_FLAG); |
| 620 | DP_STATS_INCC(vdev->pdev, rx.ampdu_cnt, 1, ampdu_flag); |
| 621 | DP_STATS_INCC(vdev->pdev, rx.non_ampdu_cnt, 1, !(ampdu_flag)); |
| 622 | |
| 623 | hal_rx_msdu_desc_info_get(ring_desc, &msdu_desc_info); |
| 624 | amsdu_flag = ((msdu_desc_info.msdu_flags & |
| 625 | HAL_MSDU_F_FIRST_MSDU_IN_MPDU) && |
| 626 | (msdu_desc_info.msdu_flags & |
| 627 | HAL_MSDU_F_LAST_MSDU_IN_MPDU)); |
| 628 | |
| 629 | DP_STATS_INCC(vdev->pdev, rx.non_amsdu_cnt, 1, |
| 630 | amsdu_flag); |
| 631 | DP_STATS_INCC(vdev->pdev, rx.amsdu_cnt, 1, |
| 632 | !(amsdu_flag)); |
| 633 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 634 | qdf_nbuf_queue_add(&vdev->rxq, rx_desc->nbuf); |
| 635 | fail: |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 636 | dp_rx_add_to_free_desc_list(&head[rx_desc->pool_id], |
| 637 | &tail[rx_desc->pool_id], |
| 638 | rx_desc); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 639 | } |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 640 | done: |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 641 | hal_srng_access_end(hal_soc, hal_ring); |
| 642 | |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 643 | for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) { |
| 644 | /* |
| 645 | * continue with next mac_id if no pkts were reaped |
| 646 | * from that pool |
| 647 | */ |
| 648 | if (!rx_bufs_reaped[mac_id]) |
| 649 | continue; |
| 650 | |
| 651 | dp_rx_buffers_replenish(soc, mac_id, |
| 652 | rx_bufs_reaped[mac_id], |
| 653 | &head[mac_id], |
| 654 | &tail[mac_id], |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 655 | HAL_RX_BUF_RBM_SW3_BM); |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 656 | } |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 657 | |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 658 | for (i = 0; i < vdev_cnt; i++) { |
Dhanashri Atre | bda02dc | 2017-02-02 16:28:12 -0800 | [diff] [blame] | 659 | qdf_nbuf_t deliver_list_head = NULL; |
| 660 | qdf_nbuf_t deliver_list_tail = NULL; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 661 | |
Tallapragada Kalyan | aae8c41 | 2017-02-13 12:00:17 +0530 | [diff] [blame] | 662 | vdev = vdev_list[i]; |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 663 | while ((nbuf = qdf_nbuf_queue_remove(&vdev->rxq))) { |
| 664 | rx_tlv_hdr = qdf_nbuf_data(nbuf); |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 665 | eh = (struct ether_header *)qdf_nbuf_data(nbuf); |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 666 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 667 | /* |
| 668 | * Check if DMA completed -- msdu_done is the last bit |
| 669 | * to be written |
| 670 | */ |
| 671 | if (!hal_rx_attn_msdu_done_get(rx_tlv_hdr)) { |
| 672 | |
| 673 | QDF_TRACE(QDF_MODULE_ID_DP, |
| 674 | QDF_TRACE_LEVEL_ERROR, |
Tallapragada Kalyan | 67ad342 | 2017-02-06 15:59:45 +0530 | [diff] [blame] | 675 | FL("MSDU DONE failure")); |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 676 | |
Tallapragada Kalyan | 67ad342 | 2017-02-06 15:59:45 +0530 | [diff] [blame] | 677 | hal_rx_dump_pkt_tlvs(rx_tlv_hdr, |
| 678 | QDF_TRACE_LEVEL_INFO); |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 679 | qdf_assert(0); |
| 680 | } |
| 681 | |
Tallapragada Kalyan | e7d51ef | 2017-02-06 11:58:21 +0530 | [diff] [blame] | 682 | if (qdf_nbuf_is_chfrag_start(nbuf)) |
| 683 | peer_mdata = hal_rx_mpdu_peer_meta_data_get(rx_tlv_hdr); |
| 684 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 685 | peer_id = DP_PEER_METADATA_PEER_ID_GET(peer_mdata); |
| 686 | peer = dp_peer_find_by_id(soc, peer_id); |
| 687 | |
| 688 | /* TODO */ |
| 689 | /* |
| 690 | * In case of roaming peer object may not be |
| 691 | * immediately available -- need to handle this |
| 692 | * Cannot drop these packets right away. |
| 693 | */ |
| 694 | /* Peer lookup failed */ |
Pramod Simha | b17d067 | 2017-03-06 17:20:13 -0800 | [diff] [blame] | 695 | if (!peer && !vdev) { |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 696 | |
| 697 | /* Drop & free packet */ |
| 698 | qdf_nbuf_free(nbuf); |
| 699 | |
| 700 | /* Statistics */ |
| 701 | continue; |
| 702 | } |
| 703 | |
Pramod Simha | b17d067 | 2017-03-06 17:20:13 -0800 | [diff] [blame] | 704 | if (peer && qdf_unlikely(peer->bss_peer)) { |
Tallapragada Kalyan | 3549b43 | 2017-02-06 16:34:42 +0530 | [diff] [blame] | 705 | QDF_TRACE(QDF_MODULE_ID_DP, |
| 706 | QDF_TRACE_LEVEL_INFO, |
| 707 | FL("received pkt with same src MAC")); |
| 708 | |
| 709 | /* Drop & free packet */ |
| 710 | qdf_nbuf_free(nbuf); |
| 711 | /* Statistics */ |
| 712 | continue; |
| 713 | } |
Tallapragada Kalyan | 1b4d08d | 2016-12-15 22:19:58 +0530 | [diff] [blame] | 714 | |
| 715 | sgi = hal_rx_msdu_start_sgi_get(rx_tlv_hdr); |
| 716 | rate_mcs = hal_rx_msdu_start_rate_mcs_get(rx_tlv_hdr); |
| 717 | tid = hal_rx_mpdu_start_tid_get(rx_tlv_hdr); |
| 718 | |
| 719 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, |
| 720 | "%s: %d, SGI: %d, rate_mcs: %d, tid: %d", |
| 721 | __func__, __LINE__, sgi, rate_mcs, tid); |
| 722 | |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 723 | bw = hal_rx_msdu_start_bw_get(rx_tlv_hdr); |
| 724 | reception_type = hal_rx_msdu_start_reception_type_get( |
| 725 | rx_tlv_hdr); |
| 726 | nss = hal_rx_msdu_start_nss_get(rx_tlv_hdr); |
| 727 | |
| 728 | DP_STATS_INC(vdev->pdev, rx.bw[bw], 1); |
| 729 | DP_STATS_INC(vdev->pdev, |
| 730 | rx.reception_type[reception_type], 1); |
| 731 | DP_STATS_INCC(vdev->pdev, rx.nss[nss], 1, |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 732 | ((reception_type == REPT_MU_MIMO) || |
| 733 | (reception_type == REPT_MU_OFDMA_MIMO)) |
| 734 | ); |
| 735 | DP_STATS_INC(peer, rx.sgi_count[sgi], 1); |
| 736 | DP_STATS_INC(peer, rx.mcs_count[rate_mcs], 1); |
| 737 | DP_STATS_INCC(peer, rx.err.mic_err, 1, |
| 738 | hal_rx_mpdu_end_mic_err_get( |
| 739 | rx_tlv_hdr)); |
| 740 | DP_STATS_INCC(peer, rx.err.decrypt_err, 1, |
| 741 | hal_rx_mpdu_end_decrypt_err_get( |
| 742 | rx_tlv_hdr)); |
| 743 | |
| 744 | DP_STATS_INC(peer, rx.wme_ac_type[TID_TO_WME_AC(tid)], |
| 745 | 1); |
| 746 | DP_STATS_INC(peer, rx.bw[bw], 1); |
| 747 | DP_STATS_INC(peer, rx.reception_type[reception_type], |
| 748 | 1); |
Ishank Jain | bc2d91f | 2017-01-03 18:14:54 +0530 | [diff] [blame] | 749 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 750 | /* |
| 751 | * HW structures call this L3 header padding -- |
| 752 | * even though this is actually the offset from |
| 753 | * the buffer beginning where the L2 header |
| 754 | * begins. |
| 755 | */ |
Dhanashri Atre | 1404917 | 2016-11-11 18:32:36 -0800 | [diff] [blame] | 756 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, |
| 757 | FL("rxhash: flow id toeplitz: 0x%x\n"), |
| 758 | hal_rx_msdu_start_toeplitz_get(rx_tlv_hdr)); |
| 759 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 760 | l2_hdr_offset = |
| 761 | hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr); |
| 762 | |
| 763 | msdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr); |
| 764 | pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN; |
| 765 | |
| 766 | /* Set length in nbuf */ |
| 767 | qdf_nbuf_set_pktlen(nbuf, pkt_len); |
| 768 | |
Venkateswara Swamy Bandaru | ec4f8e6 | 2017-03-07 11:04:28 +0530 | [diff] [blame] | 769 | if (qdf_unlikely(vdev->mesh_vdev)) { |
| 770 | if (dp_rx_filter_mesh_packets(vdev, nbuf) |
| 771 | == QDF_STATUS_SUCCESS) { |
| 772 | QDF_TRACE(QDF_MODULE_ID_DP, |
| 773 | QDF_TRACE_LEVEL_INFO_MED, |
| 774 | FL("mesh pkt filtered")); |
| 775 | |
| 776 | qdf_nbuf_free(nbuf); |
| 777 | continue; |
| 778 | } |
Venkateswara Swamy Bandaru | c14b1b6 | 2017-02-24 12:26:08 +0530 | [diff] [blame] | 779 | dp_rx_fill_mesh_stats(vdev, nbuf); |
Venkateswara Swamy Bandaru | ec4f8e6 | 2017-03-07 11:04:28 +0530 | [diff] [blame] | 780 | } |
Venkateswara Swamy Bandaru | c14b1b6 | 2017-02-24 12:26:08 +0530 | [diff] [blame] | 781 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 782 | /* |
| 783 | * Advance the packet start pointer by total size of |
| 784 | * pre-header TLV's |
| 785 | */ |
| 786 | qdf_nbuf_pull_head(nbuf, |
| 787 | RX_PKT_TLVS_LEN + l2_hdr_offset); |
| 788 | |
Debashis Dutt | af64522 | 2017-01-20 19:29:25 -0800 | [diff] [blame] | 789 | #ifdef QCA_WIFI_NAPIER_EMULATION /* Debug code, remove later */ |
| 790 | QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, |
| 791 | "p_id %d msdu_len %d hdr_off %d", |
| 792 | peer_id, msdu_len, l2_hdr_offset); |
| 793 | |
| 794 | print_hex_dump(KERN_ERR, |
| 795 | "\t Pkt Data:", DUMP_PREFIX_NONE, 32, 4, |
| 796 | qdf_nbuf_data(nbuf), 128, false); |
| 797 | #endif /* NAPIER_EMULATION */ |
| 798 | |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 799 | /* WDS Source Port Learning */ |
Ishank Jain | 2bf04b4 | 2017-02-23 22:38:42 +0530 | [diff] [blame] | 800 | dp_rx_wds_srcport_learn(soc, rx_tlv_hdr, peer, nbuf); |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 801 | |
| 802 | /* Intrabss-fwd */ |
Tallapragada Kalyan | 6f6166e | 2017-02-17 17:00:23 +0530 | [diff] [blame^] | 803 | if (vdev->opmode != wlan_op_mode_sta) |
| 804 | if (dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, |
| 805 | nbuf)) |
| 806 | continue; /* Get next descriptor */ |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 807 | |
| 808 | rx_bufs_used++; |
| 809 | DP_RX_LIST_APPEND(deliver_list_head, |
| 810 | deliver_list_tail, |
| 811 | nbuf); |
Ishank Jain | 1e7401c | 2017-02-17 15:38:39 +0530 | [diff] [blame] | 812 | |
| 813 | DP_STATS_INCC_PKT(peer, rx.multicast, 1, pkt_len, |
| 814 | DP_FRAME_IS_MULTICAST((eh)->ether_dhost |
| 815 | )); |
| 816 | DP_STATS_INCC_PKT(peer, rx.unicast, 1, pkt_len, |
| 817 | !(DP_FRAME_IS_MULTICAST( |
| 818 | (eh)->ether_dhost))); |
| 819 | DP_STATS_INC_PKT(peer, rx.to_stack, 1, |
| 820 | pkt_len); |
| 821 | |
| 822 | if (hal_rx_attn_first_mpdu_get(rx_tlv_hdr)) { |
| 823 | if (soc->cdp_soc.ol_ops->update_dp_stats) |
| 824 | soc->cdp_soc.ol_ops->update_dp_stats( |
| 825 | vdev->pdev->osif_pdev, |
| 826 | &peer->stats, |
| 827 | peer_id, |
| 828 | UPDATE_PEER_STATS); |
| 829 | |
| 830 | dp_aggregate_vdev_stats(peer->vdev); |
| 831 | |
| 832 | if (soc->cdp_soc.ol_ops->update_dp_stats) |
| 833 | soc->cdp_soc.ol_ops->update_dp_stats( |
| 834 | vdev->pdev->osif_pdev, |
| 835 | &peer->vdev->stats, |
| 836 | peer->vdev->vdev_id, |
| 837 | UPDATE_VDEV_STATS); |
| 838 | } |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 839 | } |
| 840 | |
Ishank Jain | 949674c | 2017-02-27 17:09:29 +0530 | [diff] [blame] | 841 | if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw)) |
Kalyan Tallapragada | 277f45e | 2017-01-30 14:25:27 +0530 | [diff] [blame] | 842 | dp_rx_deliver_raw(vdev, deliver_list_head); |
| 843 | else if (qdf_likely(vdev->osif_rx) && deliver_list_head) |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 844 | vdev->osif_rx(vdev->osif_vdev, deliver_list_head); |
| 845 | |
| 846 | } |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 847 | return rx_bufs_used; /* Assume no scale factor for now */ |
| 848 | } |
| 849 | |
| 850 | /** |
| 851 | * dp_rx_detach() - detach dp rx |
| 852 | * @soc: core txrx main context |
| 853 | * |
| 854 | * This function will detach DP RX into main device context |
| 855 | * will free DP Rx resources. |
| 856 | * |
| 857 | * Return: void |
| 858 | */ |
| 859 | void |
| 860 | dp_rx_pdev_detach(struct dp_pdev *pdev) |
| 861 | { |
| 862 | uint8_t pdev_id = pdev->pdev_id; |
| 863 | struct dp_soc *soc = pdev->soc; |
| 864 | |
| 865 | dp_rx_desc_pool_free(soc, pdev_id); |
| 866 | qdf_spinlock_destroy(&soc->rx_desc_mutex[pdev_id]); |
Tallapragada Kalyan | 603c594 | 2016-12-07 21:30:44 +0530 | [diff] [blame] | 867 | |
| 868 | return; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 869 | } |
| 870 | |
| 871 | /** |
| 872 | * dp_rx_attach() - attach DP RX |
| 873 | * @soc: core txrx main context |
| 874 | * |
| 875 | * This function will attach a DP RX instance into the main |
| 876 | * device (SOC) context. Will allocate dp rx resource and |
| 877 | * initialize resources. |
| 878 | * |
| 879 | * Return: QDF_STATUS_SUCCESS: success |
| 880 | * QDF_STATUS_E_RESOURCES: Error return |
| 881 | */ |
| 882 | QDF_STATUS |
| 883 | dp_rx_pdev_attach(struct dp_pdev *pdev) |
| 884 | { |
| 885 | uint8_t pdev_id = pdev->pdev_id; |
| 886 | struct dp_soc *soc = pdev->soc; |
| 887 | struct dp_srng rxdma_srng; |
| 888 | uint32_t rxdma_entries; |
| 889 | union dp_rx_desc_list_elem_t *desc_list = NULL; |
| 890 | union dp_rx_desc_list_elem_t *tail = NULL; |
| 891 | |
| 892 | qdf_spinlock_create(&soc->rx_desc_mutex[pdev_id]); |
| 893 | pdev = soc->pdev_list[pdev_id]; |
Dhanashri Atre | 7351d17 | 2016-10-12 13:08:09 -0700 | [diff] [blame] | 894 | rxdma_srng = pdev->rx_refill_buf_ring; |
Debashis Dutt | c4c52dc | 2016-10-04 17:12:23 -0700 | [diff] [blame] | 895 | |
| 896 | rxdma_entries = rxdma_srng.alloc_size/hal_srng_get_entrysize( |
| 897 | soc->hal_soc, RXDMA_BUF); |
| 898 | dp_rx_desc_pool_alloc(soc, pdev_id); |
| 899 | |
| 900 | /* For Rx buffers, WBM release ring is SW RING 3,for all pdev's */ |
| 901 | dp_rx_buffers_replenish(soc, pdev_id, rxdma_entries, |
| 902 | &desc_list, &tail, HAL_RX_BUF_RBM_SW3_BM); |
| 903 | |
| 904 | return QDF_STATUS_SUCCESS; |
| 905 | } |