wireless: Remove unnecessary OOM logging messages
[pandora-kernel.git] / net / wireless / util.c
index 4d7b83f..39dbf4a 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/bitops.h>
 #include <linux/etherdevice.h>
 #include <linux/slab.h>
+#include <linux/crc32.h>
 #include <net/cfg80211.h>
 #include <net/ip.h>
 #include "core.h"
@@ -512,10 +513,9 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
                if (head_need)
                        skb_orphan(skb);
 
-               if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) {
-                       pr_err("failed to reallocate Tx buffer\n");
+               if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC))
                        return -ENOMEM;
-               }
+
                skb->truesize += head_need;
        }
 
@@ -1006,3 +1006,208 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
 
        return -EBUSY;
 }
+
+int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
+                          const u8 *rates, unsigned int n_rates,
+                          u32 *mask)
+{
+       int i, j;
+
+       if (!sband)
+               return -EINVAL;
+
+       if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES)
+               return -EINVAL;
+
+       *mask = 0;
+
+       for (i = 0; i < n_rates; i++) {
+               int rate = (rates[i] & 0x7f) * 5;
+               bool found = false;
+
+               for (j = 0; j < sband->n_bitrates; j++) {
+                       if (sband->bitrates[j].bitrate == rate) {
+                               found = true;
+                               *mask |= BIT(j);
+                               break;
+                       }
+               }
+               if (!found)
+                       return -EINVAL;
+       }
+
+       /*
+        * mask must have at least one bit set here since we
+        * didn't accept a 0-length rates array nor allowed
+        * entries in the array that didn't exist
+        */
+
+       return 0;
+}
+
+u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
+                              struct ieee802_11_elems *elems,
+                              u64 filter, u32 crc)
+{
+       size_t left = len;
+       u8 *pos = start;
+       bool calc_crc = filter != 0;
+
+       memset(elems, 0, sizeof(*elems));
+       elems->ie_start = start;
+       elems->total_len = len;
+
+       while (left >= 2) {
+               u8 id, elen;
+
+               id = *pos++;
+               elen = *pos++;
+               left -= 2;
+
+               if (elen > left)
+                       break;
+
+               if (calc_crc && id < 64 && (filter & (1ULL << id)))
+                       crc = crc32_be(crc, pos - 2, elen + 2);
+
+               switch (id) {
+               case WLAN_EID_SSID:
+                       elems->ssid = pos;
+                       elems->ssid_len = elen;
+                       break;
+               case WLAN_EID_SUPP_RATES:
+                       elems->supp_rates = pos;
+                       elems->supp_rates_len = elen;
+                       break;
+               case WLAN_EID_FH_PARAMS:
+                       elems->fh_params = pos;
+                       elems->fh_params_len = elen;
+                       break;
+               case WLAN_EID_DS_PARAMS:
+                       elems->ds_params = pos;
+                       elems->ds_params_len = elen;
+                       break;
+               case WLAN_EID_CF_PARAMS:
+                       elems->cf_params = pos;
+                       elems->cf_params_len = elen;
+                       break;
+               case WLAN_EID_TIM:
+                       if (elen >= sizeof(struct ieee80211_tim_ie)) {
+                               elems->tim = (void *)pos;
+                               elems->tim_len = elen;
+                       }
+                       break;
+               case WLAN_EID_IBSS_PARAMS:
+                       elems->ibss_params = pos;
+                       elems->ibss_params_len = elen;
+                       break;
+               case WLAN_EID_CHALLENGE:
+                       elems->challenge = pos;
+                       elems->challenge_len = elen;
+                       break;
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
+                           pos[2] == 0xf2) {
+                               /* Microsoft OUI (00:50:F2) */
+
+                               if (calc_crc)
+                                       crc = crc32_be(crc, pos - 2, elen + 2);
+
+                               if (pos[3] == 1) {
+                                       /* OUI Type 1 - WPA IE */
+                                       elems->wpa = pos;
+                                       elems->wpa_len = elen;
+                               } else if (elen >= 5 && pos[3] == 2) {
+                                       /* OUI Type 2 - WMM IE */
+                                       if (pos[4] == 0) {
+                                               elems->wmm_info = pos;
+                                               elems->wmm_info_len = elen;
+                                       } else if (pos[4] == 1) {
+                                               elems->wmm_param = pos;
+                                               elems->wmm_param_len = elen;
+                                       }
+                               }
+                       }
+                       break;
+               case WLAN_EID_RSN:
+                       elems->rsn = pos;
+                       elems->rsn_len = elen;
+                       break;
+               case WLAN_EID_ERP_INFO:
+                       elems->erp_info = pos;
+                       elems->erp_info_len = elen;
+                       break;
+               case WLAN_EID_EXT_SUPP_RATES:
+                       elems->ext_supp_rates = pos;
+                       elems->ext_supp_rates_len = elen;
+                       break;
+               case WLAN_EID_HT_CAPABILITY:
+                       if (elen >= sizeof(struct ieee80211_ht_cap))
+                               elems->ht_cap_elem = (void *)pos;
+                       break;
+               case WLAN_EID_HT_INFORMATION:
+                       if (elen >= sizeof(struct ieee80211_ht_info))
+                               elems->ht_info_elem = (void *)pos;
+                       break;
+               case WLAN_EID_MESH_ID:
+                       elems->mesh_id = pos;
+                       elems->mesh_id_len = elen;
+                       break;
+               case WLAN_EID_MESH_CONFIG:
+                       if (elen >= sizeof(struct ieee80211_meshconf_ie))
+                               elems->mesh_config = (void *)pos;
+                       break;
+               case WLAN_EID_PEER_MGMT:
+                       elems->peering = pos;
+                       elems->peering_len = elen;
+                       break;
+               case WLAN_EID_PREQ:
+                       elems->preq = pos;
+                       elems->preq_len = elen;
+                       break;
+               case WLAN_EID_PREP:
+                       elems->prep = pos;
+                       elems->prep_len = elen;
+                       break;
+               case WLAN_EID_PERR:
+                       elems->perr = pos;
+                       elems->perr_len = elen;
+                       break;
+               case WLAN_EID_RANN:
+                       if (elen >= sizeof(struct ieee80211_rann_ie))
+                               elems->rann = (void *)pos;
+                       break;
+               case WLAN_EID_CHANNEL_SWITCH:
+                       elems->ch_switch_elem = pos;
+                       elems->ch_switch_elem_len = elen;
+                       break;
+               case WLAN_EID_QUIET:
+                       if (!elems->quiet_elem) {
+                               elems->quiet_elem = pos;
+                               elems->quiet_elem_len = elen;
+                       }
+                       elems->num_of_quiet_elem++;
+                       break;
+               case WLAN_EID_COUNTRY:
+                       elems->country_elem = pos;
+                       elems->country_elem_len = elen;
+                       break;
+               case WLAN_EID_PWR_CONSTRAINT:
+                       elems->pwr_constr_elem = pos;
+                       elems->pwr_constr_elem_len = elen;
+                       break;
+               case WLAN_EID_TIMEOUT_INTERVAL:
+                       elems->timeout_int = pos;
+                       elems->timeout_int_len = elen;
+                       break;
+               default:
+                       break;
+               }
+
+               left -= elen;
+               pos += elen;
+       }
+
+       return crc;
+}
+EXPORT_SYMBOL(ieee802_11_parse_elems_crc);