Commit 2ca27bcff7127da1aa7dd39cd2a6f7cb187e327f
Committed by
John W. Linville
1 parent
074ac8df9f
Exists in
master
and in
39 other branches
mac80211: add p2p device type support
When a driver advertises p2p device support, mac80211 will handle it, but internally it will rewrite the interface type to STA/AP rather than P2P-STA/GO since otherwise a lot of paths need to be touched that are otherwise identical. A p2p boolean tells drivers whether or not a given interface will be used for p2p or not. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Showing 9 changed files with 117 additions and 43 deletions Side-by-side Diff
drivers/net/wireless/mac80211_hwsim.c
... | ... | @@ -595,7 +595,8 @@ |
595 | 595 | struct ieee80211_vif *vif) |
596 | 596 | { |
597 | 597 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", |
598 | - __func__, vif->type, vif->addr); | |
598 | + __func__, ieee80211_vif_type_p2p(vif), | |
599 | + vif->addr); | |
599 | 600 | hwsim_set_magic(vif); |
600 | 601 | return 0; |
601 | 602 | } |
602 | 603 | |
603 | 604 | |
... | ... | @@ -603,11 +604,14 @@ |
603 | 604 | |
604 | 605 | static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, |
605 | 606 | struct ieee80211_vif *vif, |
606 | - enum nl80211_iftype newtype) | |
607 | + enum nl80211_iftype newtype, | |
608 | + bool newp2p) | |
607 | 609 | { |
610 | + newtype = ieee80211_iftype_p2p(newtype, newp2p); | |
608 | 611 | wiphy_debug(hw->wiphy, |
609 | 612 | "%s (old type=%d, new type=%d, mac_addr=%pM)\n", |
610 | - __func__, vif->type, newtype, vif->addr); | |
613 | + __func__, ieee80211_vif_type_p2p(vif), | |
614 | + newtype, vif->addr); | |
611 | 615 | hwsim_check_magic(vif); |
612 | 616 | |
613 | 617 | return 0; |
... | ... | @@ -617,7 +621,8 @@ |
617 | 621 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
618 | 622 | { |
619 | 623 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", |
620 | - __func__, vif->type, vif->addr); | |
624 | + __func__, ieee80211_vif_type_p2p(vif), | |
625 | + vif->addr); | |
621 | 626 | hwsim_check_magic(vif); |
622 | 627 | hwsim_clear_magic(vif); |
623 | 628 | } |
... | ... | @@ -1310,6 +1315,8 @@ |
1310 | 1315 | hw->wiphy->interface_modes = |
1311 | 1316 | BIT(NL80211_IFTYPE_STATION) | |
1312 | 1317 | BIT(NL80211_IFTYPE_AP) | |
1318 | + BIT(NL80211_IFTYPE_P2P_CLIENT) | | |
1319 | + BIT(NL80211_IFTYPE_P2P_GO) | | |
1313 | 1320 | BIT(NL80211_IFTYPE_ADHOC) | |
1314 | 1321 | BIT(NL80211_IFTYPE_MESH_POINT); |
1315 | 1322 |
include/net/mac80211.h
... | ... | @@ -769,6 +769,8 @@ |
769 | 769 | * @bss_conf: BSS configuration for this interface, either our own |
770 | 770 | * or the BSS we're associated to |
771 | 771 | * @addr: address of this interface |
772 | + * @p2p: indicates whether this AP or STA interface is a p2p | |
773 | + * interface, i.e. a GO or p2p-sta respectively | |
772 | 774 | * @drv_priv: data area for driver use, will always be aligned to |
773 | 775 | * sizeof(void *). |
774 | 776 | */ |
... | ... | @@ -776,6 +778,7 @@ |
776 | 778 | enum nl80211_iftype type; |
777 | 779 | struct ieee80211_bss_conf bss_conf; |
778 | 780 | u8 addr[ETH_ALEN]; |
781 | + bool p2p; | |
779 | 782 | /* must be last */ |
780 | 783 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); |
781 | 784 | }; |
... | ... | @@ -1701,7 +1704,7 @@ |
1701 | 1704 | struct ieee80211_vif *vif); |
1702 | 1705 | int (*change_interface)(struct ieee80211_hw *hw, |
1703 | 1706 | struct ieee80211_vif *vif, |
1704 | - enum nl80211_iftype new_type); | |
1707 | + enum nl80211_iftype new_type, bool p2p); | |
1705 | 1708 | void (*remove_interface)(struct ieee80211_hw *hw, |
1706 | 1709 | struct ieee80211_vif *vif); |
1707 | 1710 | int (*config)(struct ieee80211_hw *hw, u32 changed); |
... | ... | @@ -2719,6 +2722,28 @@ |
2719 | 2722 | conf_is_ht(struct ieee80211_conf *conf) |
2720 | 2723 | { |
2721 | 2724 | return conf->channel_type != NL80211_CHAN_NO_HT; |
2725 | +} | |
2726 | + | |
2727 | +static inline enum nl80211_iftype | |
2728 | +ieee80211_iftype_p2p(enum nl80211_iftype type, bool p2p) | |
2729 | +{ | |
2730 | + if (p2p) { | |
2731 | + switch (type) { | |
2732 | + case NL80211_IFTYPE_STATION: | |
2733 | + return NL80211_IFTYPE_P2P_CLIENT; | |
2734 | + case NL80211_IFTYPE_AP: | |
2735 | + return NL80211_IFTYPE_P2P_GO; | |
2736 | + default: | |
2737 | + break; | |
2738 | + } | |
2739 | + } | |
2740 | + return type; | |
2741 | +} | |
2742 | + | |
2743 | +static inline enum nl80211_iftype | |
2744 | +ieee80211_vif_type_p2p(struct ieee80211_vif *vif) | |
2745 | +{ | |
2746 | + return ieee80211_iftype_p2p(vif->type, vif->p2p); | |
2722 | 2747 | } |
2723 | 2748 | |
2724 | 2749 | #endif /* MAC80211_H */ |
net/mac80211/cfg.c
... | ... | @@ -1151,15 +1151,26 @@ |
1151 | 1151 | struct net_device *dev, |
1152 | 1152 | struct cfg80211_scan_request *req) |
1153 | 1153 | { |
1154 | - struct ieee80211_sub_if_data *sdata; | |
1154 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
1155 | 1155 | |
1156 | - sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
1157 | - | |
1158 | - if (sdata->vif.type != NL80211_IFTYPE_STATION && | |
1159 | - sdata->vif.type != NL80211_IFTYPE_ADHOC && | |
1160 | - sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | |
1161 | - (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon)) | |
1156 | + switch (ieee80211_vif_type_p2p(&sdata->vif)) { | |
1157 | + case NL80211_IFTYPE_STATION: | |
1158 | + case NL80211_IFTYPE_ADHOC: | |
1159 | + case NL80211_IFTYPE_MESH_POINT: | |
1160 | + case NL80211_IFTYPE_P2P_CLIENT: | |
1161 | + break; | |
1162 | + case NL80211_IFTYPE_P2P_GO: | |
1163 | + if (sdata->local->ops->hw_scan) | |
1164 | + break; | |
1165 | + /* FIXME: implement NoA while scanning in software */ | |
1162 | 1166 | return -EOPNOTSUPP; |
1167 | + case NL80211_IFTYPE_AP: | |
1168 | + if (sdata->u.ap.beacon) | |
1169 | + return -EOPNOTSUPP; | |
1170 | + break; | |
1171 | + default: | |
1172 | + return -EOPNOTSUPP; | |
1173 | + } | |
1163 | 1174 | |
1164 | 1175 | return ieee80211_request_scan(sdata, req); |
1165 | 1176 | } |
net/mac80211/driver-ops.h
... | ... | @@ -56,14 +56,14 @@ |
56 | 56 | |
57 | 57 | static inline int drv_change_interface(struct ieee80211_local *local, |
58 | 58 | struct ieee80211_sub_if_data *sdata, |
59 | - enum nl80211_iftype type) | |
59 | + enum nl80211_iftype type, bool p2p) | |
60 | 60 | { |
61 | 61 | int ret; |
62 | 62 | |
63 | 63 | might_sleep(); |
64 | 64 | |
65 | - trace_drv_change_interface(local, sdata, type); | |
66 | - ret = local->ops->change_interface(&local->hw, &sdata->vif, type); | |
65 | + trace_drv_change_interface(local, sdata, type, p2p); | |
66 | + ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); | |
67 | 67 | trace_drv_return_int(local, ret); |
68 | 68 | return ret; |
69 | 69 | } |
net/mac80211/driver-trace.h
... | ... | @@ -25,12 +25,14 @@ |
25 | 25 | #define STA_PR_FMT " sta:%pM" |
26 | 26 | #define STA_PR_ARG __entry->sta_addr |
27 | 27 | |
28 | -#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ | |
28 | +#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ | |
29 | + __field(bool, p2p) \ | |
29 | 30 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
30 | -#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ | |
31 | +#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ | |
32 | + __entry->p2p = sdata->vif.p2p; \ | |
31 | 33 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
32 | -#define VIF_PR_FMT " vif:%s(%d)" | |
33 | -#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type | |
34 | +#define VIF_PR_FMT " vif:%s(%d%s)" | |
35 | +#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | |
34 | 36 | |
35 | 37 | /* |
36 | 38 | * Tracing for driver callbacks. |
37 | 39 | |
38 | 40 | |
39 | 41 | |
40 | 42 | |
... | ... | @@ -139,25 +141,28 @@ |
139 | 141 | TRACE_EVENT(drv_change_interface, |
140 | 142 | TP_PROTO(struct ieee80211_local *local, |
141 | 143 | struct ieee80211_sub_if_data *sdata, |
142 | - enum nl80211_iftype type), | |
144 | + enum nl80211_iftype type, bool p2p), | |
143 | 145 | |
144 | - TP_ARGS(local, sdata, type), | |
146 | + TP_ARGS(local, sdata, type, p2p), | |
145 | 147 | |
146 | 148 | TP_STRUCT__entry( |
147 | 149 | LOCAL_ENTRY |
148 | 150 | VIF_ENTRY |
149 | 151 | __field(u32, new_type) |
152 | + __field(bool, new_p2p) | |
150 | 153 | ), |
151 | 154 | |
152 | 155 | TP_fast_assign( |
153 | 156 | LOCAL_ASSIGN; |
154 | 157 | VIF_ASSIGN; |
155 | 158 | __entry->new_type = type; |
159 | + __entry->new_p2p = p2p; | |
156 | 160 | ), |
157 | 161 | |
158 | 162 | TP_printk( |
159 | - LOCAL_PR_FMT VIF_PR_FMT " new type:%d", | |
160 | - LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type | |
163 | + LOCAL_PR_FMT VIF_PR_FMT " new type:%d%s", | |
164 | + LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type, | |
165 | + __entry->new_p2p ? "/p2p" : "" | |
161 | 166 | ) |
162 | 167 | ); |
163 | 168 |
net/mac80211/iface.c
... | ... | @@ -188,6 +188,8 @@ |
188 | 188 | break; |
189 | 189 | case NL80211_IFTYPE_UNSPECIFIED: |
190 | 190 | case NUM_NL80211_IFTYPES: |
191 | + case NL80211_IFTYPE_P2P_CLIENT: | |
192 | + case NL80211_IFTYPE_P2P_GO: | |
191 | 193 | /* cannot happen */ |
192 | 194 | WARN_ON(1); |
193 | 195 | break; |
... | ... | @@ -844,6 +846,7 @@ |
844 | 846 | |
845 | 847 | /* and set some type-dependent values */ |
846 | 848 | sdata->vif.type = type; |
849 | + sdata->vif.p2p = false; | |
847 | 850 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; |
848 | 851 | sdata->wdev.iftype = type; |
849 | 852 | |
850 | 853 | |
... | ... | @@ -857,10 +860,20 @@ |
857 | 860 | INIT_WORK(&sdata->work, ieee80211_iface_work); |
858 | 861 | |
859 | 862 | switch (type) { |
863 | + case NL80211_IFTYPE_P2P_GO: | |
864 | + type = NL80211_IFTYPE_AP; | |
865 | + sdata->vif.type = type; | |
866 | + sdata->vif.p2p = true; | |
867 | + /* fall through */ | |
860 | 868 | case NL80211_IFTYPE_AP: |
861 | 869 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
862 | 870 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
863 | 871 | break; |
872 | + case NL80211_IFTYPE_P2P_CLIENT: | |
873 | + type = NL80211_IFTYPE_STATION; | |
874 | + sdata->vif.type = type; | |
875 | + sdata->vif.p2p = true; | |
876 | + /* fall through */ | |
864 | 877 | case NL80211_IFTYPE_STATION: |
865 | 878 | ieee80211_sta_setup_sdata(sdata); |
866 | 879 | break; |
... | ... | @@ -894,6 +907,8 @@ |
894 | 907 | { |
895 | 908 | struct ieee80211_local *local = sdata->local; |
896 | 909 | int ret, err; |
910 | + enum nl80211_iftype internal_type = type; | |
911 | + bool p2p = false; | |
897 | 912 | |
898 | 913 | ASSERT_RTNL(); |
899 | 914 | |
900 | 915 | |
... | ... | @@ -926,11 +941,19 @@ |
926 | 941 | * code isn't prepared to handle). |
927 | 942 | */ |
928 | 943 | break; |
944 | + case NL80211_IFTYPE_P2P_CLIENT: | |
945 | + p2p = true; | |
946 | + internal_type = NL80211_IFTYPE_STATION; | |
947 | + break; | |
948 | + case NL80211_IFTYPE_P2P_GO: | |
949 | + p2p = true; | |
950 | + internal_type = NL80211_IFTYPE_AP; | |
951 | + break; | |
929 | 952 | default: |
930 | 953 | return -EBUSY; |
931 | 954 | } |
932 | 955 | |
933 | - ret = ieee80211_check_concurrent_iface(sdata, type); | |
956 | + ret = ieee80211_check_concurrent_iface(sdata, internal_type); | |
934 | 957 | if (ret) |
935 | 958 | return ret; |
936 | 959 | |
... | ... | @@ -938,7 +961,7 @@ |
938 | 961 | |
939 | 962 | ieee80211_teardown_sdata(sdata->dev); |
940 | 963 | |
941 | - ret = drv_change_interface(local, sdata, type); | |
964 | + ret = drv_change_interface(local, sdata, internal_type, p2p); | |
942 | 965 | if (ret) |
943 | 966 | type = sdata->vif.type; |
944 | 967 | |
... | ... | @@ -957,7 +980,7 @@ |
957 | 980 | |
958 | 981 | ASSERT_RTNL(); |
959 | 982 | |
960 | - if (type == sdata->vif.type) | |
983 | + if (type == ieee80211_vif_type_p2p(&sdata->vif)) | |
961 | 984 | return 0; |
962 | 985 | |
963 | 986 | /* Setting ad-hoc mode on non-IBSS channel is not supported. */ |
net/mac80211/main.c
... | ... | @@ -459,6 +459,21 @@ |
459 | 459 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
460 | 460 | BIT(IEEE80211_STYPE_ACTION >> 4), |
461 | 461 | }, |
462 | + [NL80211_IFTYPE_P2P_CLIENT] = { | |
463 | + .tx = 0xffff, | |
464 | + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | |
465 | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | |
466 | + }, | |
467 | + [NL80211_IFTYPE_P2P_GO] = { | |
468 | + .tx = 0xffff, | |
469 | + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | |
470 | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | |
471 | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | |
472 | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | | |
473 | + BIT(IEEE80211_STYPE_AUTH >> 4) | | |
474 | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | | |
475 | + BIT(IEEE80211_STYPE_ACTION >> 4), | |
476 | + }, | |
462 | 477 | }; |
463 | 478 | |
464 | 479 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
net/mac80211/rx.c
... | ... | @@ -2588,9 +2588,7 @@ |
2588 | 2588 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
2589 | 2589 | return 0; |
2590 | 2590 | break; |
2591 | - case NL80211_IFTYPE_MONITOR: | |
2592 | - case NL80211_IFTYPE_UNSPECIFIED: | |
2593 | - case NUM_NL80211_IFTYPES: | |
2591 | + default: | |
2594 | 2592 | /* should never get here */ |
2595 | 2593 | WARN_ON(1); |
2596 | 2594 | break; |
net/mac80211/util.c
... | ... | @@ -474,16 +474,10 @@ |
474 | 474 | |
475 | 475 | list_for_each_entry(sdata, &local->interfaces, list) { |
476 | 476 | switch (sdata->vif.type) { |
477 | - case NUM_NL80211_IFTYPES: | |
478 | - case NL80211_IFTYPE_UNSPECIFIED: | |
479 | 477 | case NL80211_IFTYPE_MONITOR: |
480 | 478 | case NL80211_IFTYPE_AP_VLAN: |
481 | 479 | continue; |
482 | - case NL80211_IFTYPE_AP: | |
483 | - case NL80211_IFTYPE_STATION: | |
484 | - case NL80211_IFTYPE_ADHOC: | |
485 | - case NL80211_IFTYPE_WDS: | |
486 | - case NL80211_IFTYPE_MESH_POINT: | |
480 | + default: | |
487 | 481 | break; |
488 | 482 | } |
489 | 483 | if (ieee80211_sdata_running(sdata)) |
490 | 484 | |
... | ... | @@ -508,16 +502,10 @@ |
508 | 502 | |
509 | 503 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
510 | 504 | switch (sdata->vif.type) { |
511 | - case NUM_NL80211_IFTYPES: | |
512 | - case NL80211_IFTYPE_UNSPECIFIED: | |
513 | 505 | case NL80211_IFTYPE_MONITOR: |
514 | 506 | case NL80211_IFTYPE_AP_VLAN: |
515 | 507 | continue; |
516 | - case NL80211_IFTYPE_AP: | |
517 | - case NL80211_IFTYPE_STATION: | |
518 | - case NL80211_IFTYPE_ADHOC: | |
519 | - case NL80211_IFTYPE_WDS: | |
520 | - case NL80211_IFTYPE_MESH_POINT: | |
508 | + default: | |
521 | 509 | break; |
522 | 510 | } |
523 | 511 | if (ieee80211_sdata_running(sdata)) |
... | ... | @@ -1193,6 +1181,8 @@ |
1193 | 1181 | break; |
1194 | 1182 | case NL80211_IFTYPE_UNSPECIFIED: |
1195 | 1183 | case NUM_NL80211_IFTYPES: |
1184 | + case NL80211_IFTYPE_P2P_CLIENT: | |
1185 | + case NL80211_IFTYPE_P2P_GO: | |
1196 | 1186 | WARN_ON(1); |
1197 | 1187 | break; |
1198 | 1188 | } |