Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 315199
b: refs/heads/master
c: d4e50c5
h: refs/heads/master
i:
  315197: ba61815
  315195: 435bbe9
  315191: d2c8f77
  315183: 9f3a306
  315167: f5c0e2a
  315135: 58b06f4
v: v3
  • Loading branch information
Michal Kazior authored and Johannes Berg committed Jun 29, 2012
1 parent b2eec19 commit 93800e7
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2e165b818456ecc1024dd0387eeac64745526377
refs/heads/master: d4e50c5917e110451ced8f8de594cea858791f37
8 changes: 8 additions & 0 deletions trunk/net/wireless/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,14 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
if (WARN_ON(!c->num_different_channels))
return -EINVAL;

/*
* Put a sane limit on maximum number of different
* channels to simplify channel accounting code.
*/
if (WARN_ON(c->num_different_channels >
CFG80211_MAX_NUM_DIFFERENT_CHANNELS))
return -EINVAL;

if (WARN_ON(!c->n_limits))
return -EINVAL;

Expand Down
29 changes: 26 additions & 3 deletions trunk/net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,20 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
u32 *flags, struct vif_params *params);
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);

int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
enum nl80211_iftype iftype);
int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
enum nl80211_iftype iftype,
struct ieee80211_channel *chan,
enum cfg80211_chan_mode chanmode);

static inline int
cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
enum nl80211_iftype iftype)
{
return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL,
CHAN_MODE_UNDEFINED);
}

static inline int
cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
Expand All @@ -439,6 +450,16 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
return cfg80211_can_change_interface(rdev, NULL, iftype);
}

static inline int
cfg80211_can_use_chan(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
enum cfg80211_chan_mode chanmode)
{
return cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
chan, chanmode);
}

void
cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
Expand All @@ -461,6 +482,8 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype, int num);

#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10

#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
#else
Expand Down
59 changes: 54 additions & 5 deletions trunk/net/wireless/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -938,13 +938,20 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
return res;
}

int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
enum nl80211_iftype iftype)
int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
enum nl80211_iftype iftype,
struct ieee80211_channel *chan,
enum cfg80211_chan_mode chanmode)
{
struct wireless_dev *wdev_iter;
u32 used_iftypes = BIT(iftype);
int num[NUM_NL80211_IFTYPES];
struct ieee80211_channel
*used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS];
struct ieee80211_channel *ch;
enum cfg80211_chan_mode chmode;
int num_different_channels = 0;
int total = 1;
int i, j;

Expand All @@ -955,9 +962,23 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
return 0;

memset(num, 0, sizeof(num));
memset(used_channels, 0, sizeof(used_channels));

num[iftype] = 1;

switch (chanmode) {
case CHAN_MODE_UNDEFINED:
break;
case CHAN_MODE_SHARED:
WARN_ON(!chan);
used_channels[0] = chan;
num_different_channels++;
break;
case CHAN_MODE_EXCLUSIVE:
num_different_channels++;
break;
}

mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev_iter, &rdev->netdev_list, list) {
if (wdev_iter == wdev)
Expand All @@ -968,6 +989,31 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
continue;

cfg80211_get_chan_state(rdev, wdev_iter, &ch, &chmode);

switch (chmode) {
case CHAN_MODE_UNDEFINED:
break;
case CHAN_MODE_SHARED:
for (i = 0; i < CFG80211_MAX_NUM_DIFFERENT_CHANNELS; i++)
if (!used_channels[i] || used_channels[i] == ch)
break;

if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS) {
mutex_unlock(&rdev->devlist_mtx);
return -EBUSY;
}

if (used_channels[i] == NULL) {
used_channels[i] = ch;
num_different_channels++;
}
break;
case CHAN_MODE_EXCLUSIVE:
num_different_channels++;
break;
}

num[wdev_iter->iftype]++;
total++;
used_iftypes |= BIT(wdev_iter->iftype);
Expand All @@ -984,12 +1030,15 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,

c = &rdev->wiphy.iface_combinations[i];

if (total > c->max_interfaces)
continue;
if (num_different_channels > c->num_different_channels)
continue;

limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
GFP_KERNEL);
if (!limits)
return -ENOMEM;
if (total > c->max_interfaces)
goto cont;

for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
if (rdev->wiphy.software_iftypes & BIT(iftype))
Expand Down

0 comments on commit 93800e7

Please sign in to comment.