aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h16
-rw-r--r--net/mac80211/ieee80211.c29
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 */
354struct ieee80211_if_init_conf { 361struct 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 :/ */