Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[pandora-kernel.git] / net / mac80211 / ieee80211.c
index 8ba69ae..67b7c75 100644 (file)
@@ -177,21 +177,21 @@ static int ieee80211_open(struct net_device *dev)
                        /*
                         * check whether it may have the same address
                         */
-                       if (!identical_mac_addr_allowed(sdata->type,
-                                                       nsdata->type))
+                       if (!identical_mac_addr_allowed(sdata->vif.type,
+                                                       nsdata->vif.type))
                                return -ENOTUNIQ;
 
                        /*
                         * can only add VLANs to enabled APs
                         */
-                       if (sdata->type == IEEE80211_IF_TYPE_VLAN &&
-                           nsdata->type == IEEE80211_IF_TYPE_AP &&
+                       if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
+                           nsdata->vif.type == IEEE80211_IF_TYPE_AP &&
                            netif_running(nsdata->dev))
                                sdata->u.vlan.ap = nsdata;
                }
        }
 
-       switch (sdata->type) {
+       switch (sdata->vif.type) {
        case IEEE80211_IF_TYPE_WDS:
                if (is_zero_ether_addr(sdata->u.wds.remote_addr))
                        return -ENOLINK;
@@ -219,9 +219,10 @@ static int ieee80211_open(struct net_device *dev)
                if (res)
                        return res;
                ieee80211_hw_config(local);
+               ieee80211_led_radio(local, local->hw.conf.radio_enabled);
        }
 
-       switch (sdata->type) {
+       switch (sdata->vif.type) {
        case IEEE80211_IF_TYPE_VLAN:
                list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
                /* no need to tell driver */
@@ -242,8 +243,8 @@ static int ieee80211_open(struct net_device *dev)
                sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
                /* fall through */
        default:
-               conf.if_id = dev->ifindex;
-               conf.type = sdata->type;
+               conf.vif = &sdata->vif;
+               conf.type = sdata->vif.type;
                conf.mac_addr = dev->dev_addr;
                res = local->ops->add_interface(local_to_hw(local), &conf);
                if (res && !local->open_count && local->ops->stop)
@@ -255,7 +256,7 @@ static int ieee80211_open(struct net_device *dev)
                ieee80211_reset_erp_info(dev);
                ieee80211_enable_keys(sdata);
 
-               if (sdata->type == IEEE80211_IF_TYPE_STA &&
+               if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
                    !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
                        netif_carrier_off(dev);
                else
@@ -298,9 +299,11 @@ static int ieee80211_stop(struct net_device *dev)
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        list_for_each_entry(sta, &local->sta_list, list) {
-               for (i = 0; i <  STA_TID_NUM; i++)
-                       ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr,
-                                               i, WLAN_BACK_RECIPIENT,
+               if (sta->dev == dev)
+                       for (i = 0; i <  STA_TID_NUM; i++)
+                               ieee80211_sta_stop_rx_ba_session(sta->dev,
+                                               sta->addr, i,
+                                               WLAN_BACK_RECIPIENT,
                                                WLAN_REASON_QSTA_LEAVE_QBSS);
        }
 
@@ -320,10 +323,17 @@ static int ieee80211_stop(struct net_device *dev)
 
        dev_mc_unsync(local->mdev, dev);
 
-       /* down all dependent devices, that is VLANs */
-       if (sdata->type == IEEE80211_IF_TYPE_AP) {
+       /* APs need special treatment */
+       if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
                struct ieee80211_sub_if_data *vlan, *tmp;
+               struct beacon_data *old_beacon = sdata->u.ap.beacon;
 
+               /* remove beacon */
+               rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+               synchronize_rcu();
+               kfree(old_beacon);
+
+               /* down all dependent devices, that is VLANs */
                list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
                                         u.vlan.list)
                        dev_close(vlan->dev);
@@ -332,7 +342,7 @@ static int ieee80211_stop(struct net_device *dev)
 
        local->open_count--;
 
-       switch (sdata->type) {
+       switch (sdata->vif.type) {
        case IEEE80211_IF_TYPE_VLAN:
                list_del(&sdata->u.vlan.list);
                sdata->u.vlan.ap = NULL;
@@ -377,8 +387,8 @@ static int ieee80211_stop(struct net_device *dev)
                sdata->u.sta.extra_ie_len = 0;
                /* fall through */
        default:
-               conf.if_id = dev->ifindex;
-               conf.type = sdata->type;
+               conf.vif = &sdata->vif;
+               conf.type = sdata->vif.type;
                conf.mac_addr = dev->dev_addr;
                /* disable all keys for as long as this netdev is down */
                ieee80211_disable_keys(sdata);
@@ -392,6 +402,8 @@ static int ieee80211_stop(struct net_device *dev)
                if (local->ops->stop)
                        local->ops->stop(local_to_hw(local));
 
+               ieee80211_led_radio(local, 0);
+
                tasklet_disable(&local->tx_pending_tasklet);
                tasklet_disable(&local->tasklet);
        }
@@ -499,20 +511,20 @@ static int __ieee80211_if_config(struct net_device *dev,
                return 0;
 
        memset(&conf, 0, sizeof(conf));
-       conf.type = sdata->type;
-       if (sdata->type == IEEE80211_IF_TYPE_STA ||
-           sdata->type == IEEE80211_IF_TYPE_IBSS) {
+       conf.type = sdata->vif.type;
+       if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+           sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
                conf.bssid = sdata->u.sta.bssid;
                conf.ssid = sdata->u.sta.ssid;
                conf.ssid_len = sdata->u.sta.ssid_len;
-       } else if (sdata->type == IEEE80211_IF_TYPE_AP) {
+       } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
                conf.ssid = sdata->u.ap.ssid;
                conf.ssid_len = sdata->u.ap.ssid_len;
                conf.beacon = beacon;
                conf.beacon_control = control;
        }
        return local->ops->config_interface(local_to_hw(local),
-                                          dev->ifindex, &conf);
+                                           &sdata->vif, &conf);
 }
 
 int ieee80211_if_config(struct net_device *dev)
@@ -524,11 +536,13 @@ int ieee80211_if_config_beacon(struct net_device *dev)
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_tx_control control;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct sk_buff *skb;
 
        if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
                return 0;
-       skb = ieee80211_beacon_get(local_to_hw(local), dev->ifindex, &control);
+       skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif,
+                                  &control);
        if (!skb)
                return -ENOMEM;
        return __ieee80211_if_config(dev, skb, &control);
@@ -623,25 +637,30 @@ int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
        return 0;
 }
 
-void ieee80211_erp_info_change_notify(struct net_device *dev, u8 changes)
+void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
+                                     u32 changed)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       if (local->ops->erp_ie_changed)
-               local->ops->erp_ie_changed(local_to_hw(local), changes,
-                       !!(sdata->flags & IEEE80211_SDATA_USE_PROTECTION),
-                       !(sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE));
+       struct ieee80211_local *local = sdata->local;
+
+       if (!changed)
+               return;
+
+       if (local->ops->bss_info_changed)
+               local->ops->bss_info_changed(local_to_hw(local),
+                                            &sdata->vif,
+                                            &sdata->bss_conf,
+                                            changed);
 }
 
 void ieee80211_reset_erp_info(struct net_device *dev)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       sdata->flags &= ~(IEEE80211_SDATA_USE_PROTECTION |
-                       IEEE80211_SDATA_SHORT_PREAMBLE);
-       ieee80211_erp_info_change_notify(dev,
-                                        IEEE80211_ERP_CHANGE_PROTECTION |
-                                        IEEE80211_ERP_CHANGE_PREAMBLE);
+       sdata->bss_conf.use_cts_prot = 0;
+       sdata->bss_conf.use_short_preamble = 0;
+       ieee80211_bss_info_change_notify(sdata,
+                                        BSS_CHANGED_ERP_CTS_PROT |
+                                        BSS_CHANGED_ERP_PREAMBLE);
 }
 
 void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
@@ -698,7 +717,7 @@ static void ieee80211_tasklet_handler(unsigned long data)
                case IEEE80211_RX_MSG:
                        /* status is in skb->cb */
                        memcpy(&rx_status, skb->cb, sizeof(rx_status));
-                       /* Clear skb->type in order to not confuse kernel
+                       /* Clear skb->pkt_type in order to not confuse kernel
                         * netstack. */
                        skb->pkt_type = 0;
                        __ieee80211_rx(local_to_hw(local), skb, &rx_status);
@@ -733,7 +752,7 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
        struct ieee80211_tx_packet_data *pkt_data;
 
        pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
-       pkt_data->ifindex = control->ifindex;
+       pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex;
        pkt_data->flags = 0;
        if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
                pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
@@ -957,7 +976,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
                if (!monitors || !skb)
                        goto out;
 
-               if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
+               if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
                        if (!netif_running(sdata->dev))
                                continue;
                        monitors--;
@@ -1079,7 +1098,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        mdev->header_ops = &ieee80211_header_ops;
        mdev->set_multicast_list = ieee80211_master_set_multicast_list;
 
-       sdata->type = IEEE80211_IF_TYPE_AP;
+       sdata->vif.type = IEEE80211_IF_TYPE_AP;
        sdata->dev = mdev;
        sdata->local = local;
        sdata->u.ap.force_unicast_rateidx = -1;
@@ -1325,17 +1344,17 @@ static int __init ieee80211_init(void)
 
        ret = rc80211_simple_init();
        if (ret)
-               goto fail;
+               goto out;
 
        ret = rc80211_pid_init();
        if (ret)
-               goto fail_simple;
+               goto out_cleanup_simple;
 
        ret = ieee80211_wme_register();
        if (ret) {
                printk(KERN_DEBUG "ieee80211_init: failed to "
                       "initialize WME (err=%d)\n", ret);
-               goto fail_pid;
+               goto out_cleanup_pid;
        }
 
        ieee80211_debugfs_netdev_init();
@@ -1343,11 +1362,11 @@ static int __init ieee80211_init(void)
 
        return 0;
 
- fail_pid:
-       rc80211_simple_exit();
- fail_simple:
+ out_cleanup_pid:
        rc80211_pid_exit();
- fail:
+ out_cleanup_simple:
+       rc80211_simple_exit();
+ out:
        return ret;
 }