root/drivers/net/wireless/marvell/mwifiex/util.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mwifiex_init_fw_complete
  2. mwifiex_init_shutdown_fw
  3. mwifiex_get_debug_info
  4. mwifiex_debug_info_to_buffer
  5. mwifiex_parse_mgmt_packet
  6. mwifiex_process_mgmt_packet
  7. mwifiex_recv_packet
  8. mwifiex_complete_cmd
  9. mwifiex_get_sta_entry
  10. mwifiex_get_tdls_sta_entry
  11. mwifiex_is_tdls_chan_switching
  12. mwifiex_is_tdls_off_chan
  13. mwifiex_is_send_cmd_allowed
  14. mwifiex_add_sta_entry
  15. mwifiex_set_sta_ht_cap
  16. mwifiex_del_sta_entry
  17. mwifiex_del_all_sta_list
  18. mwifiex_hist_data_add
  19. mwifiex_hist_data_set
  20. mwifiex_hist_data_reset
  21. mwifiex_alloc_dma_align_buf
  22. mwifiex_fw_dump_event

   1 /*
   2  * Marvell Wireless LAN device driver: utility functions
   3  *
   4  * Copyright (C) 2011-2014, Marvell International Ltd.
   5  *
   6  * This software file (the "File") is distributed by Marvell International
   7  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
   8  * (the "License").  You may use, redistribute and/or modify this File in
   9  * accordance with the terms and conditions of the License, a copy of which
  10  * is available by writing to the Free Software Foundation, Inc.,
  11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
  12  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  13  *
  14  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
  17  * this warranty disclaimer.
  18  */
  19 
  20 #include "decl.h"
  21 #include "ioctl.h"
  22 #include "util.h"
  23 #include "fw.h"
  24 #include "main.h"
  25 #include "wmm.h"
  26 #include "11n.h"
  27 
  28 static struct mwifiex_debug_data items[] = {
  29         {"debug_mask", item_size(debug_mask),
  30          item_addr(debug_mask), 1},
  31         {"int_counter", item_size(int_counter),
  32          item_addr(int_counter), 1},
  33         {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]),
  34          item_addr(packets_out[WMM_AC_VO]), 1},
  35         {"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]),
  36          item_addr(packets_out[WMM_AC_VI]), 1},
  37         {"wmm_ac_be", item_size(packets_out[WMM_AC_BE]),
  38          item_addr(packets_out[WMM_AC_BE]), 1},
  39         {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]),
  40          item_addr(packets_out[WMM_AC_BK]), 1},
  41         {"tx_buf_size", item_size(tx_buf_size),
  42          item_addr(tx_buf_size), 1},
  43         {"curr_tx_buf_size", item_size(curr_tx_buf_size),
  44          item_addr(curr_tx_buf_size), 1},
  45         {"ps_mode", item_size(ps_mode),
  46          item_addr(ps_mode), 1},
  47         {"ps_state", item_size(ps_state),
  48          item_addr(ps_state), 1},
  49         {"is_deep_sleep", item_size(is_deep_sleep),
  50          item_addr(is_deep_sleep), 1},
  51         {"wakeup_dev_req", item_size(pm_wakeup_card_req),
  52          item_addr(pm_wakeup_card_req), 1},
  53         {"wakeup_tries", item_size(pm_wakeup_fw_try),
  54          item_addr(pm_wakeup_fw_try), 1},
  55         {"hs_configured", item_size(is_hs_configured),
  56          item_addr(is_hs_configured), 1},
  57         {"hs_activated", item_size(hs_activated),
  58          item_addr(hs_activated), 1},
  59         {"num_tx_timeout", item_size(num_tx_timeout),
  60          item_addr(num_tx_timeout), 1},
  61         {"is_cmd_timedout", item_size(is_cmd_timedout),
  62          item_addr(is_cmd_timedout), 1},
  63         {"timeout_cmd_id", item_size(timeout_cmd_id),
  64          item_addr(timeout_cmd_id), 1},
  65         {"timeout_cmd_act", item_size(timeout_cmd_act),
  66          item_addr(timeout_cmd_act), 1},
  67         {"last_cmd_id", item_size(last_cmd_id),
  68          item_addr(last_cmd_id), DBG_CMD_NUM},
  69         {"last_cmd_act", item_size(last_cmd_act),
  70          item_addr(last_cmd_act), DBG_CMD_NUM},
  71         {"last_cmd_index", item_size(last_cmd_index),
  72          item_addr(last_cmd_index), 1},
  73         {"last_cmd_resp_id", item_size(last_cmd_resp_id),
  74          item_addr(last_cmd_resp_id), DBG_CMD_NUM},
  75         {"last_cmd_resp_index", item_size(last_cmd_resp_index),
  76          item_addr(last_cmd_resp_index), 1},
  77         {"last_event", item_size(last_event),
  78          item_addr(last_event), DBG_CMD_NUM},
  79         {"last_event_index", item_size(last_event_index),
  80          item_addr(last_event_index), 1},
  81         {"last_mp_wr_bitmap", item_size(last_mp_wr_bitmap),
  82          item_addr(last_mp_wr_bitmap), MWIFIEX_DBG_SDIO_MP_NUM},
  83         {"last_mp_wr_ports", item_size(last_mp_wr_ports),
  84          item_addr(last_mp_wr_ports), MWIFIEX_DBG_SDIO_MP_NUM},
  85         {"last_mp_wr_len", item_size(last_mp_wr_len),
  86          item_addr(last_mp_wr_len), MWIFIEX_DBG_SDIO_MP_NUM},
  87         {"last_mp_curr_wr_port", item_size(last_mp_curr_wr_port),
  88          item_addr(last_mp_curr_wr_port), MWIFIEX_DBG_SDIO_MP_NUM},
  89         {"last_sdio_mp_index", item_size(last_sdio_mp_index),
  90          item_addr(last_sdio_mp_index), 1},
  91         {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure),
  92          item_addr(num_cmd_host_to_card_failure), 1},
  93         {"num_cmd_sleep_cfm_fail",
  94          item_size(num_cmd_sleep_cfm_host_to_card_failure),
  95          item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1},
  96         {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure),
  97          item_addr(num_tx_host_to_card_failure), 1},
  98         {"num_evt_deauth", item_size(num_event_deauth),
  99          item_addr(num_event_deauth), 1},
 100         {"num_evt_disassoc", item_size(num_event_disassoc),
 101          item_addr(num_event_disassoc), 1},
 102         {"num_evt_link_lost", item_size(num_event_link_lost),
 103          item_addr(num_event_link_lost), 1},
 104         {"num_cmd_deauth", item_size(num_cmd_deauth),
 105          item_addr(num_cmd_deauth), 1},
 106         {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success),
 107          item_addr(num_cmd_assoc_success), 1},
 108         {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure),
 109          item_addr(num_cmd_assoc_failure), 1},
 110         {"cmd_sent", item_size(cmd_sent),
 111          item_addr(cmd_sent), 1},
 112         {"data_sent", item_size(data_sent),
 113          item_addr(data_sent), 1},
 114         {"cmd_resp_received", item_size(cmd_resp_received),
 115          item_addr(cmd_resp_received), 1},
 116         {"event_received", item_size(event_received),
 117          item_addr(event_received), 1},
 118 
 119         /* variables defined in struct mwifiex_adapter */
 120         {"cmd_pending", adapter_item_size(cmd_pending),
 121          adapter_item_addr(cmd_pending), 1},
 122         {"tx_pending", adapter_item_size(tx_pending),
 123          adapter_item_addr(tx_pending), 1},
 124         {"rx_pending", adapter_item_size(rx_pending),
 125          adapter_item_addr(rx_pending), 1},
 126 };
 127 
 128 static int num_of_items = ARRAY_SIZE(items);
 129 
 130 /*
 131  * Firmware initialization complete callback handler.
 132  *
 133  * This function wakes up the function waiting on the init
 134  * wait queue for the firmware initialization to complete.
 135  */
 136 int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter)
 137 {
 138 
 139         if (adapter->hw_status == MWIFIEX_HW_STATUS_READY)
 140                 if (adapter->if_ops.init_fw_port)
 141                         adapter->if_ops.init_fw_port(adapter);
 142 
 143         adapter->init_wait_q_woken = true;
 144         wake_up_interruptible(&adapter->init_wait_q);
 145         return 0;
 146 }
 147 
 148 /*
 149  * This function sends init/shutdown command
 150  * to firmware.
 151  */
 152 int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
 153                              u32 func_init_shutdown)
 154 {
 155         u16 cmd;
 156 
 157         if (func_init_shutdown == MWIFIEX_FUNC_INIT) {
 158                 cmd = HostCmd_CMD_FUNC_INIT;
 159         } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) {
 160                 cmd = HostCmd_CMD_FUNC_SHUTDOWN;
 161         } else {
 162                 mwifiex_dbg(priv->adapter, ERROR,
 163                             "unsupported parameter\n");
 164                 return -1;
 165         }
 166 
 167         return mwifiex_send_cmd(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL, true);
 168 }
 169 EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw);
 170 
 171 /*
 172  * IOCTL request handler to set/get debug information.
 173  *
 174  * This function collates/sets the information from/to different driver
 175  * structures.
 176  */
 177 int mwifiex_get_debug_info(struct mwifiex_private *priv,
 178                            struct mwifiex_debug_info *info)
 179 {
 180         struct mwifiex_adapter *adapter = priv->adapter;
 181 
 182         if (info) {
 183                 info->debug_mask = adapter->debug_mask;
 184                 memcpy(info->packets_out,
 185                        priv->wmm.packets_out,
 186                        sizeof(priv->wmm.packets_out));
 187                 info->curr_tx_buf_size = (u32) adapter->curr_tx_buf_size;
 188                 info->tx_buf_size = (u32) adapter->tx_buf_size;
 189                 info->rx_tbl_num = mwifiex_get_rx_reorder_tbl(priv,
 190                                                               info->rx_tbl);
 191                 info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl(priv,
 192                                                                 info->tx_tbl);
 193                 info->tdls_peer_num = mwifiex_get_tdls_list(priv,
 194                                                             info->tdls_list);
 195                 info->ps_mode = adapter->ps_mode;
 196                 info->ps_state = adapter->ps_state;
 197                 info->is_deep_sleep = adapter->is_deep_sleep;
 198                 info->pm_wakeup_card_req = adapter->pm_wakeup_card_req;
 199                 info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try;
 200                 info->is_hs_configured = test_bit(MWIFIEX_IS_HS_CONFIGURED,
 201                                                   &adapter->work_flags);
 202                 info->hs_activated = adapter->hs_activated;
 203                 info->is_cmd_timedout = test_bit(MWIFIEX_IS_CMD_TIMEDOUT,
 204                                                  &adapter->work_flags);
 205                 info->num_cmd_host_to_card_failure
 206                                 = adapter->dbg.num_cmd_host_to_card_failure;
 207                 info->num_cmd_sleep_cfm_host_to_card_failure
 208                         = adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
 209                 info->num_tx_host_to_card_failure
 210                                 = adapter->dbg.num_tx_host_to_card_failure;
 211                 info->num_event_deauth = adapter->dbg.num_event_deauth;
 212                 info->num_event_disassoc = adapter->dbg.num_event_disassoc;
 213                 info->num_event_link_lost = adapter->dbg.num_event_link_lost;
 214                 info->num_cmd_deauth = adapter->dbg.num_cmd_deauth;
 215                 info->num_cmd_assoc_success =
 216                                         adapter->dbg.num_cmd_assoc_success;
 217                 info->num_cmd_assoc_failure =
 218                                         adapter->dbg.num_cmd_assoc_failure;
 219                 info->num_tx_timeout = adapter->dbg.num_tx_timeout;
 220                 info->timeout_cmd_id = adapter->dbg.timeout_cmd_id;
 221                 info->timeout_cmd_act = adapter->dbg.timeout_cmd_act;
 222                 memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id,
 223                        sizeof(adapter->dbg.last_cmd_id));
 224                 memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act,
 225                        sizeof(adapter->dbg.last_cmd_act));
 226                 info->last_cmd_index = adapter->dbg.last_cmd_index;
 227                 memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id,
 228                        sizeof(adapter->dbg.last_cmd_resp_id));
 229                 info->last_cmd_resp_index = adapter->dbg.last_cmd_resp_index;
 230                 memcpy(info->last_event, adapter->dbg.last_event,
 231                        sizeof(adapter->dbg.last_event));
 232                 info->last_event_index = adapter->dbg.last_event_index;
 233                 memcpy(info->last_mp_wr_bitmap, adapter->dbg.last_mp_wr_bitmap,
 234                        sizeof(adapter->dbg.last_mp_wr_bitmap));
 235                 memcpy(info->last_mp_wr_ports, adapter->dbg.last_mp_wr_ports,
 236                        sizeof(adapter->dbg.last_mp_wr_ports));
 237                 memcpy(info->last_mp_curr_wr_port,
 238                        adapter->dbg.last_mp_curr_wr_port,
 239                        sizeof(adapter->dbg.last_mp_curr_wr_port));
 240                 memcpy(info->last_mp_wr_len, adapter->dbg.last_mp_wr_len,
 241                        sizeof(adapter->dbg.last_mp_wr_len));
 242                 info->last_sdio_mp_index = adapter->dbg.last_sdio_mp_index;
 243                 info->data_sent = adapter->data_sent;
 244                 info->cmd_sent = adapter->cmd_sent;
 245                 info->cmd_resp_received = adapter->cmd_resp_received;
 246         }
 247 
 248         return 0;
 249 }
 250 
 251 int mwifiex_debug_info_to_buffer(struct mwifiex_private *priv, char *buf,
 252                                  struct mwifiex_debug_info *info)
 253 {
 254         char *p = buf;
 255         struct mwifiex_debug_data *d = &items[0];
 256         size_t size, addr;
 257         long val;
 258         int i, j;
 259 
 260         if (!info)
 261                 return 0;
 262 
 263         for (i = 0; i < num_of_items; i++) {
 264                 p += sprintf(p, "%s=", d[i].name);
 265 
 266                 size = d[i].size / d[i].num;
 267 
 268                 if (i < (num_of_items - 3))
 269                         addr = d[i].addr + (size_t)info;
 270                 else /* The last 3 items are struct mwifiex_adapter variables */
 271                         addr = d[i].addr + (size_t)priv->adapter;
 272 
 273                 for (j = 0; j < d[i].num; j++) {
 274                         switch (size) {
 275                         case 1:
 276                                 val = *((u8 *)addr);
 277                                 break;
 278                         case 2:
 279                                 val = get_unaligned((u16 *)addr);
 280                                 break;
 281                         case 4:
 282                                 val = get_unaligned((u32 *)addr);
 283                                 break;
 284                         case 8:
 285                                 val = get_unaligned((long long *)addr);
 286                                 break;
 287                         default:
 288                                 val = -1;
 289                                 break;
 290                         }
 291 
 292                         p += sprintf(p, "%#lx ", val);
 293                         addr += size;
 294                 }
 295 
 296                 p += sprintf(p, "\n");
 297         }
 298 
 299         if (info->tx_tbl_num) {
 300                 p += sprintf(p, "Tx BA stream table:\n");
 301                 for (i = 0; i < info->tx_tbl_num; i++)
 302                         p += sprintf(p, "tid = %d, ra = %pM\n",
 303                                      info->tx_tbl[i].tid, info->tx_tbl[i].ra);
 304         }
 305 
 306         if (info->rx_tbl_num) {
 307                 p += sprintf(p, "Rx reorder table:\n");
 308                 for (i = 0; i < info->rx_tbl_num; i++) {
 309                         p += sprintf(p, "tid = %d, ta = %pM, ",
 310                                      info->rx_tbl[i].tid,
 311                                      info->rx_tbl[i].ta);
 312                         p += sprintf(p, "start_win = %d, ",
 313                                      info->rx_tbl[i].start_win);
 314                         p += sprintf(p, "win_size = %d, buffer: ",
 315                                      info->rx_tbl[i].win_size);
 316 
 317                         for (j = 0; j < info->rx_tbl[i].win_size; j++)
 318                                 p += sprintf(p, "%c ",
 319                                              info->rx_tbl[i].buffer[j] ?
 320                                              '1' : '0');
 321 
 322                         p += sprintf(p, "\n");
 323                 }
 324         }
 325 
 326         if (info->tdls_peer_num) {
 327                 p += sprintf(p, "TDLS peer table:\n");
 328                 for (i = 0; i < info->tdls_peer_num; i++) {
 329                         p += sprintf(p, "peer = %pM",
 330                                      info->tdls_list[i].peer_addr);
 331                         p += sprintf(p, "\n");
 332                 }
 333         }
 334 
 335         return p - buf;
 336 }
 337 
 338 static int
 339 mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
 340                           struct rxpd *rx_pd)
 341 {
 342         u16 stype;
 343         u8 category, action_code, *addr2;
 344         struct ieee80211_hdr *ieee_hdr = (void *)payload;
 345 
 346         stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE);
 347 
 348         switch (stype) {
 349         case IEEE80211_STYPE_ACTION:
 350                 category = *(payload + sizeof(struct ieee80211_hdr));
 351                 switch (category) {
 352                 case WLAN_CATEGORY_PUBLIC:
 353                         action_code = *(payload + sizeof(struct ieee80211_hdr)
 354                                         + 1);
 355                         if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
 356                                 addr2 = ieee_hdr->addr2;
 357                                 mwifiex_dbg(priv->adapter, INFO,
 358                                             "TDLS discovery response %pM nf=%d, snr=%d\n",
 359                                             addr2, rx_pd->nf, rx_pd->snr);
 360                                 mwifiex_auto_tdls_update_peer_signal(priv,
 361                                                                      addr2,
 362                                                                      rx_pd->snr,
 363                                                                      rx_pd->nf);
 364                         }
 365                         break;
 366                 case WLAN_CATEGORY_BACK:
 367                         /*we dont indicate BACK action frames to cfg80211*/
 368                         mwifiex_dbg(priv->adapter, INFO,
 369                                     "drop BACK action frames");
 370                         return -1;
 371                 default:
 372                         mwifiex_dbg(priv->adapter, INFO,
 373                                     "unknown public action frame category %d\n",
 374                                     category);
 375                 }
 376                 break;
 377         default:
 378                 mwifiex_dbg(priv->adapter, INFO,
 379                     "unknown mgmt frame subtype %#x\n", stype);
 380                 return 0;
 381         }
 382 
 383         return 0;
 384 }
 385 /*
 386  * This function processes the received management packet and send it
 387  * to the kernel.
 388  */
 389 int
 390 mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
 391                             struct sk_buff *skb)
 392 {
 393         struct rxpd *rx_pd;
 394         u16 pkt_len;
 395         struct ieee80211_hdr *ieee_hdr;
 396 
 397         if (!skb)
 398                 return -1;
 399 
 400         if (!priv->mgmt_frame_mask ||
 401             priv->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) {
 402                 mwifiex_dbg(priv->adapter, ERROR,
 403                             "do not receive mgmt frames on uninitialized intf");
 404                 return -1;
 405         }
 406 
 407         rx_pd = (struct rxpd *)skb->data;
 408 
 409         skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
 410         skb_pull(skb, sizeof(pkt_len));
 411 
 412         pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
 413 
 414         ieee_hdr = (void *)skb->data;
 415         if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
 416                 if (mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
 417                                               pkt_len, rx_pd))
 418                         return -1;
 419         }
 420         /* Remove address4 */
 421         memmove(skb->data + sizeof(struct ieee80211_hdr_3addr),
 422                 skb->data + sizeof(struct ieee80211_hdr),
 423                 pkt_len - sizeof(struct ieee80211_hdr));
 424 
 425         pkt_len -= ETH_ALEN + sizeof(pkt_len);
 426         rx_pd->rx_pkt_length = cpu_to_le16(pkt_len);
 427 
 428         cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq,
 429                          CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len,
 430                          0);
 431 
 432         return 0;
 433 }
 434 
 435 /*
 436  * This function processes the received packet before sending it to the
 437  * kernel.
 438  *
 439  * It extracts the SKB from the received buffer and sends it to kernel.
 440  * In case the received buffer does not contain the data in SKB format,
 441  * the function creates a blank SKB, fills it with the data from the
 442  * received buffer and then sends this new SKB to the kernel.
 443  */
 444 int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
 445 {
 446         struct mwifiex_sta_node *src_node;
 447         struct ethhdr *p_ethhdr;
 448 
 449         if (!skb)
 450                 return -1;
 451 
 452         priv->stats.rx_bytes += skb->len;
 453         priv->stats.rx_packets++;
 454 
 455         if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
 456                 p_ethhdr = (void *)skb->data;
 457                 src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source);
 458                 if (src_node) {
 459                         src_node->stats.last_rx = jiffies;
 460                         src_node->stats.rx_bytes += skb->len;
 461                         src_node->stats.rx_packets++;
 462                 }
 463         }
 464 
 465         skb->dev = priv->netdev;
 466         skb->protocol = eth_type_trans(skb, priv->netdev);
 467         skb->ip_summed = CHECKSUM_NONE;
 468 
 469         /* This is required only in case of 11n and USB/PCIE as we alloc
 470          * a buffer of 4K only if its 11N (to be able to receive 4K
 471          * AMSDU packets). In case of SD we allocate buffers based
 472          * on the size of packet and hence this is not needed.
 473          *
 474          * Modifying the truesize here as our allocation for each
 475          * skb is 4K but we only receive 2K packets and this cause
 476          * the kernel to start dropping packets in case where
 477          * application has allocated buffer based on 2K size i.e.
 478          * if there a 64K packet received (in IP fragments and
 479          * application allocates 64K to receive this packet but
 480          * this packet would almost double up because we allocate
 481          * each 1.5K fragment in 4K and pass it up. As soon as the
 482          * 64K limit hits kernel will start to drop rest of the
 483          * fragments. Currently we fail the Filesndl-ht.scr script
 484          * for UDP, hence this fix
 485          */
 486         if ((priv->adapter->iface_type == MWIFIEX_USB ||
 487              priv->adapter->iface_type == MWIFIEX_PCIE) &&
 488             (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
 489                 skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
 490 
 491         if (in_interrupt())
 492                 netif_rx(skb);
 493         else
 494                 netif_rx_ni(skb);
 495 
 496         return 0;
 497 }
 498 
 499 /*
 500  * IOCTL completion callback handler.
 501  *
 502  * This function is called when a pending IOCTL is completed.
 503  *
 504  * If work queue support is enabled, the function wakes up the
 505  * corresponding waiting function. Otherwise, it processes the
 506  * IOCTL response and frees the response buffer.
 507  */
 508 int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
 509                          struct cmd_ctrl_node *cmd_node)
 510 {
 511         WARN_ON(!cmd_node->wait_q_enabled);
 512         mwifiex_dbg(adapter, CMD, "cmd completed: status=%d\n",
 513                     adapter->cmd_wait_q.status);
 514 
 515         *cmd_node->condition = true;
 516         wake_up_interruptible(&adapter->cmd_wait_q.wait);
 517 
 518         return 0;
 519 }
 520 
 521 /* This function will return the pointer to station entry in station list
 522  * table which matches specified mac address.
 523  * This function should be called after acquiring RA list spinlock.
 524  * NULL is returned if station entry is not found in associated STA list.
 525  */
 526 struct mwifiex_sta_node *
 527 mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac)
 528 {
 529         struct mwifiex_sta_node *node;
 530 
 531         if (!mac)
 532                 return NULL;
 533 
 534         list_for_each_entry(node, &priv->sta_list, list) {
 535                 if (!memcmp(node->mac_addr, mac, ETH_ALEN))
 536                         return node;
 537         }
 538 
 539         return NULL;
 540 }
 541 
 542 static struct mwifiex_sta_node *
 543 mwifiex_get_tdls_sta_entry(struct mwifiex_private *priv, u8 status)
 544 {
 545         struct mwifiex_sta_node *node;
 546 
 547         list_for_each_entry(node, &priv->sta_list, list) {
 548                 if (node->tdls_status == status)
 549                         return node;
 550         }
 551 
 552         return NULL;
 553 }
 554 
 555 /* If tdls channel switching is on-going, tx data traffic should be
 556  * blocked until the switching stage completed.
 557  */
 558 u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv)
 559 {
 560         struct mwifiex_sta_node *sta_ptr;
 561 
 562         if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
 563                 return false;
 564 
 565         sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_CHAN_SWITCHING);
 566         if (sta_ptr)
 567                 return true;
 568 
 569         return false;
 570 }
 571 
 572 u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv)
 573 {
 574         struct mwifiex_sta_node *sta_ptr;
 575 
 576         if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
 577                 return false;
 578 
 579         sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_IN_OFF_CHAN);
 580         if (sta_ptr)
 581                 return true;
 582 
 583         return false;
 584 }
 585 
 586 /* If tdls channel switching is on-going or tdls operate on off-channel,
 587  * cmd path should be blocked until tdls switched to base-channel.
 588  */
 589 u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv)
 590 {
 591         if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
 592                 return true;
 593 
 594         if (mwifiex_is_tdls_chan_switching(priv) ||
 595             mwifiex_is_tdls_off_chan(priv))
 596                 return false;
 597 
 598         return true;
 599 }
 600 
 601 /* This function will add a sta_node entry to associated station list
 602  * table with the given mac address.
 603  * If entry exist already, existing entry is returned.
 604  * If received mac address is NULL, NULL is returned.
 605  */
 606 struct mwifiex_sta_node *
 607 mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)
 608 {
 609         struct mwifiex_sta_node *node;
 610 
 611         if (!mac)
 612                 return NULL;
 613 
 614         spin_lock_bh(&priv->sta_list_spinlock);
 615         node = mwifiex_get_sta_entry(priv, mac);
 616         if (node)
 617                 goto done;
 618 
 619         node = kzalloc(sizeof(*node), GFP_ATOMIC);
 620         if (!node)
 621                 goto done;
 622 
 623         memcpy(node->mac_addr, mac, ETH_ALEN);
 624         list_add_tail(&node->list, &priv->sta_list);
 625 
 626 done:
 627         spin_unlock_bh(&priv->sta_list_spinlock);
 628         return node;
 629 }
 630 
 631 /* This function will search for HT IE in association request IEs
 632  * and set station HT parameters accordingly.
 633  */
 634 void
 635 mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
 636                        int ies_len, struct mwifiex_sta_node *node)
 637 {
 638         struct ieee_types_header *ht_cap_ie;
 639         const struct ieee80211_ht_cap *ht_cap;
 640 
 641         if (!ies)
 642                 return;
 643 
 644         ht_cap_ie = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies,
 645                                              ies_len);
 646         if (ht_cap_ie) {
 647                 ht_cap = (void *)(ht_cap_ie + 1);
 648                 node->is_11n_enabled = 1;
 649                 node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
 650                                   IEEE80211_HT_CAP_MAX_AMSDU ?
 651                                   MWIFIEX_TX_DATA_BUF_SIZE_8K :
 652                                   MWIFIEX_TX_DATA_BUF_SIZE_4K;
 653         } else {
 654                 node->is_11n_enabled = 0;
 655         }
 656 
 657         return;
 658 }
 659 
 660 /* This function will delete a station entry from station list */
 661 void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
 662 {
 663         struct mwifiex_sta_node *node;
 664 
 665         spin_lock_bh(&priv->sta_list_spinlock);
 666 
 667         node = mwifiex_get_sta_entry(priv, mac);
 668         if (node) {
 669                 list_del(&node->list);
 670                 kfree(node);
 671         }
 672 
 673         spin_unlock_bh(&priv->sta_list_spinlock);
 674         return;
 675 }
 676 
 677 /* This function will delete all stations from associated station list. */
 678 void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
 679 {
 680         struct mwifiex_sta_node *node, *tmp;
 681 
 682         spin_lock_bh(&priv->sta_list_spinlock);
 683 
 684         list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
 685                 list_del(&node->list);
 686                 kfree(node);
 687         }
 688 
 689         INIT_LIST_HEAD(&priv->sta_list);
 690         spin_unlock_bh(&priv->sta_list_spinlock);
 691         return;
 692 }
 693 
 694 /* This function adds histogram data to histogram array*/
 695 void mwifiex_hist_data_add(struct mwifiex_private *priv,
 696                            u8 rx_rate, s8 snr, s8 nflr)
 697 {
 698         struct mwifiex_histogram_data *phist_data = priv->hist_data;
 699 
 700         if (atomic_read(&phist_data->num_samples) > MWIFIEX_HIST_MAX_SAMPLES)
 701                 mwifiex_hist_data_reset(priv);
 702         mwifiex_hist_data_set(priv, rx_rate, snr, nflr);
 703 }
 704 
 705 /* function to add histogram record */
 706 void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr,
 707                            s8 nflr)
 708 {
 709         struct mwifiex_histogram_data *phist_data = priv->hist_data;
 710         s8 nf   = -nflr;
 711         s8 rssi = snr - nflr;
 712 
 713         atomic_inc(&phist_data->num_samples);
 714         atomic_inc(&phist_data->rx_rate[rx_rate]);
 715         atomic_inc(&phist_data->snr[snr + 128]);
 716         atomic_inc(&phist_data->noise_flr[nf + 128]);
 717         atomic_inc(&phist_data->sig_str[rssi + 128]);
 718 }
 719 
 720 /* function to reset histogram data during init/reset */
 721 void mwifiex_hist_data_reset(struct mwifiex_private *priv)
 722 {
 723         int ix;
 724         struct mwifiex_histogram_data *phist_data = priv->hist_data;
 725 
 726         atomic_set(&phist_data->num_samples, 0);
 727         for (ix = 0; ix < MWIFIEX_MAX_AC_RX_RATES; ix++)
 728                 atomic_set(&phist_data->rx_rate[ix], 0);
 729         for (ix = 0; ix < MWIFIEX_MAX_SNR; ix++)
 730                 atomic_set(&phist_data->snr[ix], 0);
 731         for (ix = 0; ix < MWIFIEX_MAX_NOISE_FLR; ix++)
 732                 atomic_set(&phist_data->noise_flr[ix], 0);
 733         for (ix = 0; ix < MWIFIEX_MAX_SIG_STRENGTH; ix++)
 734                 atomic_set(&phist_data->sig_str[ix], 0);
 735 }
 736 
 737 void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags)
 738 {
 739         struct sk_buff *skb;
 740         int buf_len, pad;
 741 
 742         buf_len = rx_len + MWIFIEX_RX_HEADROOM + MWIFIEX_DMA_ALIGN_SZ;
 743 
 744         skb = __dev_alloc_skb(buf_len, flags);
 745 
 746         if (!skb)
 747                 return NULL;
 748 
 749         skb_reserve(skb, MWIFIEX_RX_HEADROOM);
 750 
 751         pad = MWIFIEX_ALIGN_ADDR(skb->data, MWIFIEX_DMA_ALIGN_SZ) -
 752               (long)skb->data;
 753 
 754         skb_reserve(skb, pad);
 755 
 756         return skb;
 757 }
 758 EXPORT_SYMBOL_GPL(mwifiex_alloc_dma_align_buf);
 759 
 760 void mwifiex_fw_dump_event(struct mwifiex_private *priv)
 761 {
 762         mwifiex_send_cmd(priv, HostCmd_CMD_FW_DUMP_EVENT, HostCmd_ACT_GEN_SET,
 763                          0, NULL, true);
 764 }
 765 EXPORT_SYMBOL_GPL(mwifiex_fw_dump_event);

/* [<][>][^][v][top][bottom][index][help] */