]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/mac80211/cfg.c
fat: Fix _fat_bmap() race
[linux-2.6-omap-h63xx.git] / net / mac80211 / cfg.c
index 297c257864c771c069c44f2b04aa68c2ad1b48c7..855126a3039daa16ae64ca60c8087e0439a0d61f 100644 (file)
 #include "rate.h"
 #include "mesh.h"
 
-static enum ieee80211_if_types
-nl80211_type_to_mac80211_type(enum nl80211_iftype type)
+struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+       return &local->hw;
+}
+EXPORT_SYMBOL(wiphy_to_hw);
+
+static bool nl80211_type_check(enum nl80211_iftype type)
 {
        switch (type) {
-       case NL80211_IFTYPE_UNSPECIFIED:
-               return IEEE80211_IF_TYPE_STA;
        case NL80211_IFTYPE_ADHOC:
-               return IEEE80211_IF_TYPE_IBSS;
        case NL80211_IFTYPE_STATION:
-               return IEEE80211_IF_TYPE_STA;
        case NL80211_IFTYPE_MONITOR:
-               return IEEE80211_IF_TYPE_MNTR;
 #ifdef CONFIG_MAC80211_MESH
        case NL80211_IFTYPE_MESH_POINT:
-               return IEEE80211_IF_TYPE_MESH_POINT;
 #endif
        case NL80211_IFTYPE_WDS:
-               return IEEE80211_IF_TYPE_WDS;
+               return true;
        default:
-               return IEEE80211_IF_TYPE_INVALID;
+               return false;
        }
 }
 
@@ -45,17 +45,15 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
                               struct vif_params *params)
 {
        struct ieee80211_local *local = wiphy_priv(wiphy);
-       enum ieee80211_if_types itype;
        struct net_device *dev;
        struct ieee80211_sub_if_data *sdata;
        int err;
 
-       itype = nl80211_type_to_mac80211_type(type);
-       if (itype == IEEE80211_IF_TYPE_INVALID)
+       if (!nl80211_type_check(type))
                return -EINVAL;
 
-       err = ieee80211_if_add(local, name, &dev, itype, params);
-       if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
+       err = ieee80211_if_add(local, name, &dev, type, params);
+       if (err || type != NL80211_IFTYPE_MONITOR || !flags)
                return err;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -66,13 +64,16 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
 static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
 {
        struct net_device *dev;
+       struct ieee80211_sub_if_data *sdata;
 
        /* we're under RTNL */
        dev = __dev_get_by_index(&init_net, ifindex);
        if (!dev)
                return -ENODEV;
 
-       ieee80211_if_remove(dev);
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       ieee80211_if_remove(sdata);
 
        return 0;
 }
@@ -81,9 +82,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
                                  enum nl80211_iftype type, u32 *flags,
                                  struct vif_params *params)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct net_device *dev;
-       enum ieee80211_if_types itype;
        struct ieee80211_sub_if_data *sdata;
        int ret;
 
@@ -92,25 +91,24 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
        if (!dev)
                return -ENODEV;
 
-       itype = nl80211_type_to_mac80211_type(type);
-       if (itype == IEEE80211_IF_TYPE_INVALID)
+       if (!nl80211_type_check(type))
                return -EINVAL;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       ret = ieee80211_if_change_type(sdata, itype);
+       ret = ieee80211_if_change_type(sdata, type);
        if (ret)
                return ret;
 
+       if (netif_running(sdata->dev))
+               return -EBUSY;
+
        if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
-               ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
-                                            params->mesh_id_len,
-                                            params->mesh_id);
+               ieee80211_sdata_set_mesh_id(sdata,
+                                           params->mesh_id_len,
+                                           params->mesh_id);
 
-       if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags)
+       if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
                return 0;
 
        sdata->u.mntr_flags = *flags;
@@ -121,16 +119,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                             u8 key_idx, u8 *mac_addr,
                             struct key_params *params)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct sta_info *sta = NULL;
        enum ieee80211_key_alg alg;
        struct ieee80211_key *key;
        int err;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        switch (params->cipher) {
@@ -175,14 +169,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
                             u8 key_idx, u8 *mac_addr)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct sta_info *sta;
        int ret;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        rcu_read_lock();
@@ -223,7 +213,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                             void (*callback)(void *cookie,
                                              struct key_params *params))
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct sta_info *sta = NULL;
        u8 seq[6] = {0};
@@ -233,9 +222,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
        u16 iv16;
        int err = -ENOENT;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        rcu_read_lock();
@@ -311,12 +297,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
                                        struct net_device *dev,
                                        u8 key_idx)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        rcu_read_lock();
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -365,7 +347,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
        sta = sta_info_get_by_idx(local, idx, dev);
        if (sta) {
                ret = 0;
-               memcpy(mac, sta->addr, ETH_ALEN);
+               memcpy(mac, sta->sta.addr, ETH_ALEN);
                sta_set_sinfo(sta, sinfo);
        }
 
@@ -497,16 +479,12 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
                                struct beacon_parameters *params)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct beacon_data *old;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
+       if (sdata->vif.type != NL80211_IFTYPE_AP)
                return -EINVAL;
 
        old = sdata->u.ap.beacon;
@@ -520,16 +498,12 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
 static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
                                struct beacon_parameters *params)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct beacon_data *old;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
+       if (sdata->vif.type != NL80211_IFTYPE_AP)
                return -EINVAL;
 
        old = sdata->u.ap.beacon;
@@ -542,16 +516,12 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 
 static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct beacon_data *old;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
+       if (sdata->vif.type != NL80211_IFTYPE_AP)
                return -EINVAL;
 
        old = sdata->u.ap.beacon;
@@ -594,7 +564,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
         * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
 
        memset(msg->da, 0xff, ETH_ALEN);
-       memcpy(msg->sa, sta->addr, ETH_ALEN);
+       memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
        msg->len = htons(6);
        msg->dsap = 0;
        msg->ssap = 0x01;       /* NULL LSAP, CR Bit: Response */
@@ -649,9 +619,9 @@ static void sta_apply_parameters(struct ieee80211_local *local,
         */
 
        if (params->aid) {
-               sta->aid = params->aid;
-               if (sta->aid > IEEE80211_MAX_AID)
-                       sta->aid = 0; /* XXX: should this be an error? */
+               sta->sta.aid = params->aid;
+               if (sta->sta.aid > IEEE80211_MAX_AID)
+                       sta->sta.aid = 0; /* XXX: should this be an error? */
        }
 
        if (params->listen_interval >= 0)
@@ -668,7 +638,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,
                                        rates |= BIT(j);
                        }
                }
-               sta->supp_rates[local->oper_channel->band] = rates;
+               sta->sta.supp_rates[local->oper_channel->band] = rates;
+       }
+
+       if (params->ht_capa) {
+               ieee80211_ht_cap_ie_to_ht_info(params->ht_capa,
+                                              &sta->sta.ht_info);
        }
 
        if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
@@ -691,9 +666,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata;
        int err;
 
-       if (dev == local->mdev || params->vlan == local->mdev)
-               return -EOPNOTSUPP;
-
        /* Prevent a race with changing the rate control algorithm */
        if (!netif_running(dev))
                return -ENETDOWN;
@@ -701,8 +673,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (params->vlan) {
                sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
-               if (sdata->vif.type != IEEE80211_IF_TYPE_VLAN &&
-                   sdata->vif.type != IEEE80211_IF_TYPE_AP)
+               if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+                   sdata->vif.type != NL80211_IFTYPE_AP)
                        return -EINVAL;
        } else
                sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -721,7 +693,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 
        sta_apply_parameters(local, sta, params);
 
-       rate_control_rate_init(sta, local);
+       rate_control_rate_init(sta);
 
        rcu_read_lock();
 
@@ -732,8 +704,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
                return err;
        }
 
-       if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
-           sdata->vif.type == IEEE80211_IF_TYPE_AP)
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+           sdata->vif.type == NL80211_IFTYPE_AP)
                ieee80211_send_layer2_update(sta);
 
        rcu_read_unlock();
@@ -748,9 +720,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata;
        struct sta_info *sta;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        if (mac) {
@@ -782,9 +751,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
        struct sta_info *sta;
        struct ieee80211_sub_if_data *vlansdata;
 
-       if (dev == local->mdev || params->vlan == local->mdev)
-               return -EOPNOTSUPP;
-
        rcu_read_lock();
 
        /* XXX: get sta belonging to dev */
@@ -797,8 +763,8 @@ static int ieee80211_change_station(struct wiphy *wiphy,
        if (params->vlan && params->vlan != sta->sdata->dev) {
                vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
-               if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN &&
-                   vlansdata->vif.type != IEEE80211_IF_TYPE_AP) {
+               if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+                   vlansdata->vif.type != NL80211_IFTYPE_AP) {
                        rcu_read_unlock();
                        return -EINVAL;
                }
@@ -824,15 +790,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
        struct sta_info *sta;
        int err;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        if (!netif_running(dev))
                return -ENETDOWN;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
+       if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
                return -ENOTSUPP;
 
        rcu_read_lock();
@@ -842,13 +805,13 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
                return -ENOENT;
        }
 
-       err = mesh_path_add(dst, dev);
+       err = mesh_path_add(dst, sdata);
        if (err) {
                rcu_read_unlock();
                return err;
        }
 
-       mpath = mesh_path_lookup(dst, dev);
+       mpath = mesh_path_lookup(dst, sdata);
        if (!mpath) {
                rcu_read_unlock();
                return -ENXIO;
@@ -862,10 +825,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
 static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
                                 u8 *dst)
 {
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
        if (dst)
-               return mesh_path_del(dst, dev);
+               return mesh_path_del(dst, sdata);
 
-       mesh_path_flush(dev);
+       mesh_path_flush(sdata);
        return 0;
 }
 
@@ -878,15 +843,12 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
        struct mesh_path *mpath;
        struct sta_info *sta;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        if (!netif_running(dev))
                return -ENETDOWN;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
+       if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
                return -ENOTSUPP;
 
        rcu_read_lock();
@@ -897,7 +859,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
                return -ENOENT;
        }
 
-       mpath = mesh_path_lookup(dst, dev);
+       mpath = mesh_path_lookup(dst, sdata);
        if (!mpath) {
                rcu_read_unlock();
                return -ENOENT;
@@ -913,7 +875,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
                            struct mpath_info *pinfo)
 {
        if (mpath->next_hop)
-               memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
+               memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
        else
                memset(next_hop, 0, ETH_ALEN);
 
@@ -952,20 +914,16 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
                               u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
 
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct mesh_path *mpath;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
+       if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
                return -ENOTSUPP;
 
        rcu_read_lock();
-       mpath = mesh_path_lookup(dst, dev);
+       mpath = mesh_path_lookup(dst, sdata);
        if (!mpath) {
                rcu_read_unlock();
                return -ENOENT;
@@ -980,20 +938,16 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
                                 int idx, u8 *dst, u8 *next_hop,
                                 struct mpath_info *pinfo)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata;
        struct mesh_path *mpath;
 
-       if (dev == local->mdev)
-               return -EOPNOTSUPP;
-
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
+       if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
                return -ENOTSUPP;
 
        rcu_read_lock();
-       mpath = mesh_path_lookup_by_idx(idx, dev);
+       mpath = mesh_path_lookup_by_idx(idx, sdata);
        if (!mpath) {
                rcu_read_unlock();
                return -ENOENT;
@@ -1005,6 +959,38 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
 }
 #endif
 
+static int ieee80211_change_bss(struct wiphy *wiphy,
+                               struct net_device *dev,
+                               struct bss_parameters *params)
+{
+       struct ieee80211_sub_if_data *sdata;
+       u32 changed = 0;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (sdata->vif.type != NL80211_IFTYPE_AP)
+               return -EINVAL;
+
+       if (params->use_cts_prot >= 0) {
+               sdata->bss_conf.use_cts_prot = params->use_cts_prot;
+               changed |= BSS_CHANGED_ERP_CTS_PROT;
+       }
+       if (params->use_short_preamble >= 0) {
+               sdata->bss_conf.use_short_preamble =
+                       params->use_short_preamble;
+               changed |= BSS_CHANGED_ERP_PREAMBLE;
+       }
+       if (params->use_short_slot_time >= 0) {
+               sdata->bss_conf.use_short_slot =
+                       params->use_short_slot_time;
+               changed |= BSS_CHANGED_ERP_SLOT;
+       }
+
+       ieee80211_bss_info_change_notify(sdata, changed);
+
+       return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
        .add_virtual_intf = ieee80211_add_iface,
        .del_virtual_intf = ieee80211_del_iface,
@@ -1028,4 +1014,5 @@ struct cfg80211_ops mac80211_config_ops = {
        .get_mpath = ieee80211_get_mpath,
        .dump_mpath = ieee80211_dump_mpath,
 #endif
+       .change_bss = ieee80211_change_bss,
 };