Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorDavid S. Miller <davem@davemloft.net>
Tue, 20 Jan 2009 22:37:10 +0000 (14:37 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 20 Jan 2009 22:37:10 +0000 (14:37 -0800)
drivers/net/wireless/ath9k/rc.c
drivers/net/wireless/ath9k/regd_common.h
drivers/net/wireless/iwlwifi/iwl-hcmd.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/libertas/hostcmd.h
drivers/net/wireless/p54/p54common.c
drivers/net/wireless/rt2x00/rt2x00rfkill.c
include/net/mac80211.h
net/mac80211/sta_info.h
net/wireless/reg.c

index 04ab457a8faa3f3bce73692b583a61866c72e6e2..1b71b934bb5eb07ac979cf06684d16cfc090be01 100644 (file)
@@ -490,7 +490,7 @@ static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
 
 static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
 {
-       if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG))
+       if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
                return 0;
        if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
                return 0;
index 9112c030b1e86b4e6c72d3a69a6230ca5127bb9c..6df1b3b77c253730a8e234ea954ae9ea568028cf 100644 (file)
@@ -228,7 +228,7 @@ enum {
 };
 
 #define REG_DOMAIN_2GHZ_MASK    (REQ_MASK & \
-       (!(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB)))
+       (~(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB)))
 #define REG_DOMAIN_5GHZ_MASK    REQ_MASK
 
 static struct reg_dmn_pair_mapping regDomainPairs[] = {
index 8c71ad4f88c5f98e027293a1459d5700a388bb17..4b35b30e493e8abc82a90aa393d018683fa2359b 100644 (file)
@@ -224,7 +224,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                IWL_ERROR("Error: Response NULL in '%s'\n",
                          get_cmd_string(cmd->id));
                ret = -EIO;
-               goto out;
+               goto cancel;
        }
 
        ret = 0;
index d64580805d6efbef7cb48a5bafec23ca02f55f6d..15f5655c636e2ce8c8dbb4cda119737a98413fb6 100644 (file)
@@ -745,7 +745,7 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_
                IWL_ERROR("Error: Response NULL in '%s'\n",
                          get_cmd_string(cmd->id));
                ret = -EIO;
-               goto out;
+               goto cancel;
        }
 
        ret = 0;
index e173b1b46c232754efdaca10211af22fff489fe0..f6a79a653b7ba5bfb00e14588963ae6692429221 100644 (file)
@@ -32,7 +32,7 @@ struct txpd {
        u8 pktdelay_2ms;
        /* reserved */
        u8 reserved1;
-};
+} __attribute__ ((packed));
 
 /* RxPD Descriptor */
 struct rxpd {
@@ -63,7 +63,7 @@ struct rxpd {
        /* Pkt Priority */
        u8 priority;
        u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_header {
        __le16 command;
@@ -97,7 +97,7 @@ struct enc_key {
 struct lbs_offset_value {
        u32 offset;
        u32 value;
-};
+} __attribute__ ((packed));
 
 /* Define general data structure */
 /* cmd_DS_GEN */
@@ -107,7 +107,7 @@ struct cmd_ds_gen {
        __le16 seqnum;
        __le16 result;
        void *cmdresp[0];
-};
+} __attribute__ ((packed));
 
 #define S_DS_GEN sizeof(struct cmd_ds_gen)
 
@@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event {
         * bump this up a bit.
         */
        uint8_t tlv[128];
-};
+} __attribute__ ((packed));
 
 /*
  * This scan handle Country Information IE(802.11d compliant)
@@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan {
        mrvlietypes_chanlistparamset_t ChanListParamSet;
        mrvlietypes_ratesparamset_t OpRateSet;
 #endif
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_scan_rsp {
        struct cmd_header hdr;
@@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp {
        __le16 bssdescriptsize;
        uint8_t nr_sets;
        uint8_t bssdesc_and_tlvbuffer[0];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_get_log {
        struct cmd_header hdr;
@@ -206,33 +206,33 @@ struct cmd_ds_802_11_get_log {
        __le32 fcserror;
        __le32 txframe;
        __le32 wepundecryptable;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_control {
        struct cmd_header hdr;
        __le16 action;
        u16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_multicast_adr {
        struct cmd_header hdr;
        __le16 action;
        __le16 nr_of_adrs;
        u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_authenticate {
        u8 macaddr[ETH_ALEN];
        u8 authtype;
        u8 reserved[10];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_deauthenticate {
        struct cmd_header hdr;
 
        u8 macaddr[ETH_ALEN];
        __le16 reasoncode;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_associate {
        u8 peerstaaddr[6];
@@ -251,7 +251,7 @@ struct cmd_ds_802_11_associate {
 
 struct cmd_ds_802_11_associate_rsp {
        struct ieeetypes_assocrsp assocRsp;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_set_wep {
        struct cmd_header hdr;
@@ -265,7 +265,7 @@ struct cmd_ds_802_11_set_wep {
        /* 40, 128bit or TXWEP */
        uint8_t keytype[4];
        uint8_t keymaterial[4][16];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_3_get_stat {
        __le32 xmitok;
@@ -274,7 +274,7 @@ struct cmd_ds_802_3_get_stat {
        __le32 rcverror;
        __le32 rcvnobuffer;
        __le32 rcvcrcerror;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_get_stat {
        __le32 txfragmentcnt;
@@ -294,7 +294,7 @@ struct cmd_ds_802_11_get_stat {
        __le32 txbeacon;
        __le32 rxbeacon;
        __le32 wepundecryptable;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_snmp_mib {
        struct cmd_header hdr;
@@ -303,58 +303,58 @@ struct cmd_ds_802_11_snmp_mib {
        __le16 oid;
        __le16 bufsize;
        u8 value[128];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_reg_map {
        __le16 buffersize;
        u8 regmap[128];
        __le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_bbp_reg_map {
        __le16 buffersize;
        u8 regmap[128];
        __le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_rf_reg_map {
        __le16 buffersize;
        u8 regmap[64];
        __le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_reg_access {
        __le16 action;
        __le16 offset;
        __le32 value;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_bbp_reg_access {
        __le16 action;
        __le16 offset;
        u8 value;
        u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_rf_reg_access {
        __le16 action;
        __le16 offset;
        u8 value;
        u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_radio_control {
        struct cmd_header hdr;
 
        __le16 action;
        __le16 control;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_beacon_control {
        __le16 action;
        __le16 beacon_enable;
        __le16 beacon_period;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_sleep_params {
        struct cmd_header hdr;
@@ -379,7 +379,7 @@ struct cmd_ds_802_11_sleep_params {
 
        /* reserved field, should be set to zero */
        __le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_inactivity_timeout {
        struct cmd_header hdr;
@@ -389,7 +389,7 @@ struct cmd_ds_802_11_inactivity_timeout {
 
        /* Inactivity timeout in msec */
        __le16 timeout;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_channel {
        struct cmd_header hdr;
@@ -399,7 +399,7 @@ struct cmd_ds_802_11_rf_channel {
        __le16 rftype;      /* unused */
        __le16 reserved;    /* unused */
        u8 channellist[32]; /* unused */
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rssi {
        /* weighting factor */
@@ -408,21 +408,21 @@ struct cmd_ds_802_11_rssi {
        __le16 reserved_0;
        __le16 reserved_1;
        __le16 reserved_2;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rssi_rsp {
        __le16 SNR;
        __le16 noisefloor;
        __le16 avgSNR;
        __le16 avgnoisefloor;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_mac_address {
        struct cmd_header hdr;
 
        __le16 action;
        u8 macadd[ETH_ALEN];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_tx_power {
        struct cmd_header hdr;
@@ -431,7 +431,7 @@ struct cmd_ds_802_11_rf_tx_power {
        __le16 curlevel;
        s8 maxlevel;
        s8 minlevel;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_antenna {
        __le16 action;
@@ -439,33 +439,33 @@ struct cmd_ds_802_11_rf_antenna {
        /* Number of antennas or 0xffff(diversity) */
        __le16 antennamode;
 
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_monitor_mode {
        __le16 action;
        __le16 mode;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_set_boot2_ver {
        struct cmd_header hdr;
 
        __le16 action;
        __le16 version;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_fw_wake_method {
        struct cmd_header hdr;
 
        __le16 action;
        __le16 method;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_sleep_period {
        struct cmd_header hdr;
 
        __le16 action;
        __le16 period;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_ps_mode {
        __le16 action;
@@ -473,7 +473,7 @@ struct cmd_ds_802_11_ps_mode {
        __le16 multipledtim;
        __le16 reserved;
        __le16 locallisteninterval;
-};
+} __attribute__ ((packed));
 
 struct cmd_confirm_sleep {
        struct cmd_header hdr;
@@ -483,7 +483,7 @@ struct cmd_confirm_sleep {
        __le16 multipledtim;
        __le16 reserved;
        __le16 locallisteninterval;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_data_rate {
        struct cmd_header hdr;
@@ -491,14 +491,14 @@ struct cmd_ds_802_11_data_rate {
        __le16 action;
        __le16 reserved;
        u8 rates[MAX_RATES];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rate_adapt_rateset {
        struct cmd_header hdr;
        __le16 action;
        __le16 enablehwauto;
        __le16 bitmap;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_ad_hoc_start {
        struct cmd_header hdr;
@@ -520,7 +520,7 @@ struct cmd_ds_802_11_ad_hoc_result {
 
        u8 pad[3];
        u8 bssid[ETH_ALEN];
-};
+} __attribute__ ((packed));
 
 struct adhoc_bssdesc {
        u8 bssid[ETH_ALEN];
@@ -578,7 +578,7 @@ struct MrvlIEtype_keyParamSet {
 
        /* key material of size keylen */
        u8 key[32];
-};
+} __attribute__ ((packed));
 
 #define MAX_WOL_RULES          16
 
@@ -590,7 +590,7 @@ struct host_wol_rule {
        __le16 reserve;
        __be32 sig_mask;
        __be32 signature;
-};
+} __attribute__ ((packed));
 
 struct wol_config {
        uint8_t action;
@@ -598,8 +598,7 @@ struct wol_config {
        uint8_t no_rules_in_cmd;
        uint8_t result;
        struct host_wol_rule rule[MAX_WOL_RULES];
-};
-
+} __attribute__ ((packed));
 
 struct cmd_ds_host_sleep {
        struct cmd_header hdr;
index c6a370fa9bcbf11115fdd9063327356339f4504d..12d0717c3992219fc6da29ab8e27de398016665c 100644 (file)
@@ -1147,7 +1147,7 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
 
        skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
                      sizeof(struct p54_hdr) + sizeof(*tim),
-                     P54_CONTROL_TYPE_TIM, GFP_KERNEL);
+                     P54_CONTROL_TYPE_TIM, GFP_ATOMIC);
        if (!skb)
                return -ENOMEM;
 
@@ -1610,7 +1610,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
 
  err:
        printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
-       kfree_skb(skb);
+       p54_free_skb(dev, skb);
        return -EINVAL;
 }
 
@@ -2077,7 +2077,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
                        algo = P54_CRYPTO_AESCCMP;
                        break;
                default:
-                       return -EINVAL;
+                       return -EOPNOTSUPP;
                }
        }
 
index c3f53a92180a02c4a42533e4bd7ad4eddf56b4e2..3298cae1e12d50056aa2b22896dea537a9ab9e67 100644 (file)
@@ -162,7 +162,7 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
 
 void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
 {
-       if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->flags))
+       if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
                return;
 
        cancel_delayed_work_sync(&rt2x00dev->rfkill_work);
index b3bd00a9d9928ce228c1e3d6e855cdf8a9b17682..559422fc0943837d35563677a25a35ecbe1b5a10 100644 (file)
@@ -322,7 +322,6 @@ struct ieee80211_tx_rate {
  * @control: union for control data
  * @status: union for status data
  * @driver_data: array of driver_data pointers
- * @retry_count: number of retries
  * @ampdu_ack_len: number of aggregated frames.
  *     relevant only if IEEE80211_TX_STATUS_AMPDU was set.
  * @ampdu_ack_map: block ack bit map for the aggregation.
index dc2606d0ae7713fbc850bdaf2339573f22d8a2f2..e49a5b99cf10424daba5ed3d8f2bece1447a4b2b 100644 (file)
@@ -195,7 +195,6 @@ struct sta_ampdu_mlme {
  * @tx_packets: number of RX/TX MSDUs
  * @tx_bytes: number of bytes transmitted to this STA
  * @tx_fragments: number of transmitted MPDUs
- * @last_txrate: description of the last used transmit rate
  * @tid_seq: per-TID sequence numbers for sending to this STA
  * @ampdu_mlme: A-MPDU state machine state
  * @timer_to_tid: identity mapping to ID timers
index 4f877535e666ba8f22f9af132628e510d1627b94..bc494cef21026e943215670b9899378fcdd900c3 100644 (file)
@@ -421,6 +421,31 @@ static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range,
        return 0;
 }
 
+/**
+ * freq_in_rule_band - tells us if a frequency is in a frequency band
+ * @freq_range: frequency rule we want to query
+ * @freq_khz: frequency we are inquiring about
+ *
+ * This lets us know if a specific frequency rule is or is not relevant to
+ * a specific frequency's band. Bands are device specific and artificial
+ * definitions (the "2.4 GHz band" and the "5 GHz band"), however it is
+ * safe for now to assume that a frequency rule should not be part of a
+ * frequency's band if the start freq or end freq are off by more than 2 GHz.
+ * This resolution can be lowered and should be considered as we add
+ * regulatory rule support for other "bands".
+ **/
+static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
+       u32 freq_khz)
+{
+#define ONE_GHZ_IN_KHZ 1000000
+       if (abs(freq_khz - freq_range->start_freq_khz) <= (2 * ONE_GHZ_IN_KHZ))
+               return true;
+       if (abs(freq_khz - freq_range->end_freq_khz) <= (2 * ONE_GHZ_IN_KHZ))
+               return true;
+       return false;
+#undef ONE_GHZ_IN_KHZ
+}
+
 /* Converts a country IE to a regulatory domain. A regulatory domain
  * structure has a lot of information which the IE doesn't yet have,
  * so for the other values we use upper max values as we will intersect
@@ -538,6 +563,7 @@ static struct ieee80211_regdomain *country_ie_2_rd(
 
        /* This time around we fill in the rd */
        while (country_ie_len >= 3) {
+               int end_channel = 0;
                struct ieee80211_country_ie_triplet *triplet =
                        (struct ieee80211_country_ie_triplet *) country_ie;
                struct ieee80211_reg_rule *reg_rule = NULL;
@@ -559,6 +585,23 @@ static struct ieee80211_regdomain *country_ie_2_rd(
 
                reg_rule->flags = flags;
 
+               /* 2 GHz */
+               if (triplet->chans.first_channel <= 14)
+                       end_channel = triplet->chans.first_channel +
+                               triplet->chans.num_channels;
+               else
+                       /*
+                        * 5 GHz -- For example in country IEs if the first
+                        * channel given is 36 and the number of channels is 4
+                        * then the individual channel numbers defined for the
+                        * 5 GHz PHY by these parameters are: 36, 40, 44, and 48
+                        * and not 36, 37, 38, 39.
+                        *
+                        * See: http://tinyurl.com/11d-clarification
+                        */
+                       end_channel =  triplet->chans.first_channel +
+                               (4 * (triplet->chans.num_channels - 1));
+
                /* The +10 is since the regulatory domain expects
                 * the actual band edge, not the center of freq for
                 * its start and end freqs, assuming 20 MHz bandwidth on
@@ -568,8 +611,7 @@ static struct ieee80211_regdomain *country_ie_2_rd(
                                triplet->chans.first_channel) - 10);
                freq_range->end_freq_khz =
                        MHZ_TO_KHZ(ieee80211_channel_to_frequency(
-                               triplet->chans.first_channel +
-                                       triplet->chans.num_channels) + 10);
+                               end_channel) + 10);
 
                /* Large arbitrary values, we intersect later */
                /* Increment this if we ever support >= 40 MHz channels
@@ -748,12 +790,23 @@ static u32 map_regdom_flags(u32 rd_flags)
  *     this value to the maximum allowed bandwidth.
  * @reg_rule: the regulatory rule which we have for this frequency
  *
- * Use this function to get the regulatory rule for a specific frequency.
+ * Use this function to get the regulatory rule for a specific frequency on
+ * a given wireless device. If the device has a specific regulatory domain
+ * it wants to follow we respect that unless a country IE has been received
+ * and processed already.
+ *
+ * Returns 0 if it was able to find a valid regulatory rule which does
+ * apply to the given center_freq otherwise it returns non-zero. It will
+ * also return -ERANGE if we determine the given center_freq does not even have
+ * a regulatory rule for a frequency range in the center_freq's band. See
+ * freq_in_rule_band() for our current definition of a band -- this is purely
+ * subjective and right now its 802.11 specific.
  */
 static int freq_reg_info(u32 center_freq, u32 *bandwidth,
                         const struct ieee80211_reg_rule **reg_rule)
 {
        int i;
+       bool band_rule_found = false;
        u32 max_bandwidth = 0;
 
        if (!cfg80211_regdomain)
@@ -767,7 +820,15 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth,
                rr = &cfg80211_regdomain->reg_rules[i];
                fr = &rr->freq_range;
                pr = &rr->power_rule;
+
+               /* We only need to know if one frequency rule was
+                * was in center_freq's band, that's enough, so lets
+                * not overwrite it once found */
+               if (!band_rule_found)
+                       band_rule_found = freq_in_rule_band(fr, center_freq);
+
                max_bandwidth = freq_max_bandwidth(fr, center_freq);
+
                if (max_bandwidth && *bandwidth <= max_bandwidth) {
                        *reg_rule = rr;
                        *bandwidth = max_bandwidth;
@@ -775,23 +836,64 @@ static int freq_reg_info(u32 center_freq, u32 *bandwidth,
                }
        }
 
+       if (!band_rule_found)
+               return -ERANGE;
+
        return !max_bandwidth;
 }
 
-static void handle_channel(struct ieee80211_channel *chan)
+static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
+                          unsigned int chan_idx)
 {
        int r;
-       u32 flags = chan->orig_flags;
+       u32 flags;
        u32 max_bandwidth = 0;
        const struct ieee80211_reg_rule *reg_rule = NULL;
        const struct ieee80211_power_rule *power_rule = NULL;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *chan;
+
+       sband = wiphy->bands[band];
+       BUG_ON(chan_idx >= sband->n_channels);
+       chan = &sband->channels[chan_idx];
+
+       flags = chan->orig_flags;
 
        r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq),
                &max_bandwidth, &reg_rule);
 
        if (r) {
-               flags |= IEEE80211_CHAN_DISABLED;
-               chan->flags = flags;
+               /* This means no regulatory rule was found in the country IE
+                * with a frequency range on the center_freq's band, since
+                * IEEE-802.11 allows for a country IE to have a subset of the
+                * regulatory information provided in a country we ignore
+                * disabling the channel unless at least one reg rule was
+                * found on the center_freq's band. For details see this
+                * clarification:
+                *
+                * http://tinyurl.com/11d-clarification
+                */
+               if (r == -ERANGE &&
+                   last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
+#ifdef CONFIG_CFG80211_REG_DEBUG
+                       printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz "
+                               "intact on %s - no rule found in band on "
+                               "Country IE\n",
+                               chan->center_freq, wiphy_name(wiphy));
+#endif
+               } else {
+               /* In this case we know the country IE has at least one reg rule
+                * for the band so we respect its band definitions */
+#ifdef CONFIG_CFG80211_REG_DEBUG
+                       if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
+                               printk(KERN_DEBUG "cfg80211: Disabling "
+                                       "channel %d MHz on %s due to "
+                                       "Country IE\n",
+                                       chan->center_freq, wiphy_name(wiphy));
+#endif
+                       flags |= IEEE80211_CHAN_DISABLED;
+                       chan->flags = flags;
+               }
                return;
        }
 
@@ -808,12 +910,16 @@ static void handle_channel(struct ieee80211_channel *chan)
                chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
 }
 
-static void handle_band(struct ieee80211_supported_band *sband)
+static void handle_band(struct wiphy *wiphy, enum ieee80211_band band)
 {
-       int i;
+       unsigned int i;
+       struct ieee80211_supported_band *sband;
+
+       BUG_ON(!wiphy->bands[band]);
+       sband = wiphy->bands[band];
 
        for (i = 0; i < sband->n_channels; i++)
-               handle_channel(&sband->channels[i]);
+               handle_channel(wiphy, band, i);
 }
 
 static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby)
@@ -840,7 +946,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby)
        enum ieee80211_band band;
        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                if (wiphy->bands[band])
-                       handle_band(wiphy->bands[band]);
+                       handle_band(wiphy, band);
                if (wiphy->reg_notifier)
                        wiphy->reg_notifier(wiphy, setby);
        }