diff options
-rw-r--r-- | include/net/mac80211.h | 16 | ||||
-rw-r--r-- | net/mac80211/ieee80211.c | 29 |
2 files changed, 24 insertions, 21 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 627885765a36..c34fd9a6160a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -347,9 +347,16 @@ enum ieee80211_if_types { | |||
347 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid | 347 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid |
348 | * until the interface is removed (i.e. it cannot be used after | 348 | * until the interface is removed (i.e. it cannot be used after |
349 | * remove_interface() callback was called for this interface). | 349 | * remove_interface() callback was called for this interface). |
350 | * This pointer will be %NULL for monitor interfaces, be careful. | ||
350 | * | 351 | * |
351 | * This structure is used in add_interface() and remove_interface() | 352 | * This structure is used in add_interface() and remove_interface() |
352 | * callbacks of &struct ieee80211_hw. | 353 | * callbacks of &struct ieee80211_hw. |
354 | * | ||
355 | * When you allow multiple interfaces to be added to your PHY, take care | ||
356 | * that the hardware can actually handle multiple MAC addresses. However, | ||
357 | * also take care that when there's no interface left with mac_addr != %NULL | ||
358 | * you remove the MAC address from the device to avoid acknowledging packets | ||
359 | * in pure monitor mode. | ||
353 | */ | 360 | */ |
354 | struct ieee80211_if_init_conf { | 361 | struct ieee80211_if_init_conf { |
355 | int if_id; | 362 | int if_id; |
@@ -574,10 +581,11 @@ struct ieee80211_ops { | |||
574 | * to returning zero. By returning non-zero addition of the interface | 581 | * to returning zero. By returning non-zero addition of the interface |
575 | * is inhibited. Unless monitor_during_oper is set, it is guaranteed | 582 | * is inhibited. Unless monitor_during_oper is set, it is guaranteed |
576 | * that monitor interfaces and normal interfaces are mutually | 583 | * that monitor interfaces and normal interfaces are mutually |
577 | * exclusive. The open() handler is called after add_interface() | 584 | * exclusive. If assigned, the open() handler is called after |
578 | * if this is the first device added. At least one of the open() | 585 | * add_interface() if this is the first device added. The |
579 | * open() and add_interface() callbacks has to be assigned. If | 586 | * add_interface() callback has to be assigned because it is the only |
580 | * add_interface() is NULL, one STA interface is permitted only. */ | 587 | * way to obtain the requested MAC address for any interface. |
588 | */ | ||
581 | int (*add_interface)(struct ieee80211_hw *hw, | 589 | int (*add_interface)(struct ieee80211_hw *hw, |
582 | struct ieee80211_if_init_conf *conf); | 590 | struct ieee80211_if_init_conf *conf); |
583 | 591 | ||
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 773a103ee3a1..fe32a2d16053 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -2605,8 +2605,7 @@ static void ieee80211_start_hard_monitor(struct ieee80211_local *local) | |||
2605 | struct ieee80211_if_init_conf conf; | 2605 | struct ieee80211_if_init_conf conf; |
2606 | 2606 | ||
2607 | if (local->open_count && local->open_count == local->monitors && | 2607 | if (local->open_count && local->open_count == local->monitors && |
2608 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) && | 2608 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { |
2609 | local->ops->add_interface) { | ||
2610 | conf.if_id = -1; | 2609 | conf.if_id = -1; |
2611 | conf.type = IEEE80211_IF_TYPE_MNTR; | 2610 | conf.type = IEEE80211_IF_TYPE_MNTR; |
2612 | conf.mac_addr = NULL; | 2611 | conf.mac_addr = NULL; |
@@ -2649,21 +2648,14 @@ static int ieee80211_open(struct net_device *dev) | |||
2649 | } | 2648 | } |
2650 | ieee80211_start_soft_monitor(local); | 2649 | ieee80211_start_soft_monitor(local); |
2651 | 2650 | ||
2652 | if (local->ops->add_interface) { | 2651 | conf.if_id = dev->ifindex; |
2653 | conf.if_id = dev->ifindex; | 2652 | conf.type = sdata->type; |
2654 | conf.type = sdata->type; | 2653 | conf.mac_addr = dev->dev_addr; |
2655 | conf.mac_addr = dev->dev_addr; | 2654 | res = local->ops->add_interface(local_to_hw(local), &conf); |
2656 | res = local->ops->add_interface(local_to_hw(local), &conf); | 2655 | if (res) { |
2657 | if (res) { | 2656 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) |
2658 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) | 2657 | ieee80211_start_hard_monitor(local); |
2659 | ieee80211_start_hard_monitor(local); | 2658 | return res; |
2660 | return res; | ||
2661 | } | ||
2662 | } else { | ||
2663 | if (sdata->type != IEEE80211_IF_TYPE_STA) | ||
2664 | return -EOPNOTSUPP; | ||
2665 | if (local->open_count > 0) | ||
2666 | return -ENOBUFS; | ||
2667 | } | 2659 | } |
2668 | 2660 | ||
2669 | if (local->open_count == 0) { | 2661 | if (local->open_count == 0) { |
@@ -4896,6 +4888,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
4896 | ((sizeof(struct ieee80211_local) + | 4888 | ((sizeof(struct ieee80211_local) + |
4897 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 4889 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
4898 | 4890 | ||
4891 | BUG_ON(!ops->tx); | ||
4892 | BUG_ON(!ops->config); | ||
4893 | BUG_ON(!ops->add_interface); | ||
4899 | local->ops = ops; | 4894 | local->ops = ops; |
4900 | 4895 | ||
4901 | /* for now, mdev needs sub_if_data :/ */ | 4896 | /* for now, mdev needs sub_if_data :/ */ |