diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-09-16 08:58:23 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-09-16 15:46:07 -0400 |
commit | 2ca27bcff7127da1aa7dd39cd2a6f7cb187e327f (patch) | |
tree | fae1b81c56763a53d432310b8fcbb81b9bb48d7e /net/mac80211 | |
parent | 074ac8df9f93f2a35a356d92fd7f16cd846f0a03 (diff) |
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 25 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 6 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 21 | ||||
-rw-r--r-- | net/mac80211/iface.c | 29 | ||||
-rw-r--r-- | net/mac80211/main.c | 15 | ||||
-rw-r--r-- | net/mac80211/rx.c | 4 | ||||
-rw-r--r-- | net/mac80211/util.c | 18 |
7 files changed, 80 insertions, 38 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 171e8ff8e028..c981604b71e6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1151,15 +1151,26 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1151 | struct net_device *dev, | 1151 | struct net_device *dev, |
1152 | struct cfg80211_scan_request *req) | 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 | |||
1156 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1157 | 1155 | ||
1158 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1156 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { |
1159 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | 1157 | case NL80211_IFTYPE_STATION: |
1160 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 1158 | case NL80211_IFTYPE_ADHOC: |
1161 | (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon)) | 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 */ | ||
1166 | return -EOPNOTSUPP; | ||
1167 | case NL80211_IFTYPE_AP: | ||
1168 | if (sdata->u.ap.beacon) | ||
1169 | return -EOPNOTSUPP; | ||
1170 | break; | ||
1171 | default: | ||
1162 | return -EOPNOTSUPP; | 1172 | return -EOPNOTSUPP; |
1173 | } | ||
1163 | 1174 | ||
1164 | return ieee80211_request_scan(sdata, req); | 1175 | return ieee80211_request_scan(sdata, req); |
1165 | } | 1176 | } |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 6064b7b09e01..16983825f8e8 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -56,14 +56,14 @@ static inline int drv_add_interface(struct ieee80211_local *local, | |||
56 | 56 | ||
57 | static inline int drv_change_interface(struct ieee80211_local *local, | 57 | static inline int drv_change_interface(struct ieee80211_local *local, |
58 | struct ieee80211_sub_if_data *sdata, | 58 | struct ieee80211_sub_if_data *sdata, |
59 | enum nl80211_iftype type) | 59 | enum nl80211_iftype type, bool p2p) |
60 | { | 60 | { |
61 | int ret; | 61 | int ret; |
62 | 62 | ||
63 | might_sleep(); | 63 | might_sleep(); |
64 | 64 | ||
65 | trace_drv_change_interface(local, sdata, type); | 65 | trace_drv_change_interface(local, sdata, type, p2p); |
66 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type); | 66 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); |
67 | trace_drv_return_int(local, ret); | 67 | trace_drv_return_int(local, ret); |
68 | return ret; | 68 | return ret; |
69 | } | 69 | } |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index f6f3d89e43fa..6831fb1641c8 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -25,12 +25,14 @@ static inline void trace_ ## name(proto) {} | |||
25 | #define STA_PR_FMT " sta:%pM" | 25 | #define STA_PR_FMT " sta:%pM" |
26 | #define STA_PR_ARG __entry->sta_addr | 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 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 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 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 33 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
32 | #define VIF_PR_FMT " vif:%s(%d)" | 34 | #define VIF_PR_FMT " vif:%s(%d%s)" |
33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type | 35 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
34 | 36 | ||
35 | /* | 37 | /* |
36 | * Tracing for driver callbacks. | 38 | * Tracing for driver callbacks. |
@@ -139,25 +141,28 @@ TRACE_EVENT(drv_add_interface, | |||
139 | TRACE_EVENT(drv_change_interface, | 141 | TRACE_EVENT(drv_change_interface, |
140 | TP_PROTO(struct ieee80211_local *local, | 142 | TP_PROTO(struct ieee80211_local *local, |
141 | struct ieee80211_sub_if_data *sdata, | 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 | TP_STRUCT__entry( | 148 | TP_STRUCT__entry( |
147 | LOCAL_ENTRY | 149 | LOCAL_ENTRY |
148 | VIF_ENTRY | 150 | VIF_ENTRY |
149 | __field(u32, new_type) | 151 | __field(u32, new_type) |
152 | __field(bool, new_p2p) | ||
150 | ), | 153 | ), |
151 | 154 | ||
152 | TP_fast_assign( | 155 | TP_fast_assign( |
153 | LOCAL_ASSIGN; | 156 | LOCAL_ASSIGN; |
154 | VIF_ASSIGN; | 157 | VIF_ASSIGN; |
155 | __entry->new_type = type; | 158 | __entry->new_type = type; |
159 | __entry->new_p2p = p2p; | ||
156 | ), | 160 | ), |
157 | 161 | ||
158 | TP_printk( | 162 | TP_printk( |
159 | LOCAL_PR_FMT VIF_PR_FMT " new type:%d", | 163 | LOCAL_PR_FMT VIF_PR_FMT " new type:%d%s", |
160 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type | 164 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type, |
165 | __entry->new_p2p ? "/p2p" : "" | ||
161 | ) | 166 | ) |
162 | ); | 167 | ); |
163 | 168 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 95908aaa8a68..66785739dad3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -188,6 +188,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
188 | break; | 188 | break; |
189 | case NL80211_IFTYPE_UNSPECIFIED: | 189 | case NL80211_IFTYPE_UNSPECIFIED: |
190 | case NUM_NL80211_IFTYPES: | 190 | case NUM_NL80211_IFTYPES: |
191 | case NL80211_IFTYPE_P2P_CLIENT: | ||
192 | case NL80211_IFTYPE_P2P_GO: | ||
191 | /* cannot happen */ | 193 | /* cannot happen */ |
192 | WARN_ON(1); | 194 | WARN_ON(1); |
193 | break; | 195 | break; |
@@ -844,6 +846,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
844 | 846 | ||
845 | /* and set some type-dependent values */ | 847 | /* and set some type-dependent values */ |
846 | sdata->vif.type = type; | 848 | sdata->vif.type = type; |
849 | sdata->vif.p2p = false; | ||
847 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | 850 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; |
848 | sdata->wdev.iftype = type; | 851 | sdata->wdev.iftype = type; |
849 | 852 | ||
@@ -857,10 +860,20 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
857 | INIT_WORK(&sdata->work, ieee80211_iface_work); | 860 | INIT_WORK(&sdata->work, ieee80211_iface_work); |
858 | 861 | ||
859 | switch (type) { | 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 | case NL80211_IFTYPE_AP: | 868 | case NL80211_IFTYPE_AP: |
861 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 869 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
862 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 870 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
863 | break; | 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 | case NL80211_IFTYPE_STATION: | 877 | case NL80211_IFTYPE_STATION: |
865 | ieee80211_sta_setup_sdata(sdata); | 878 | ieee80211_sta_setup_sdata(sdata); |
866 | break; | 879 | break; |
@@ -894,6 +907,8 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
894 | { | 907 | { |
895 | struct ieee80211_local *local = sdata->local; | 908 | struct ieee80211_local *local = sdata->local; |
896 | int ret, err; | 909 | int ret, err; |
910 | enum nl80211_iftype internal_type = type; | ||
911 | bool p2p = false; | ||
897 | 912 | ||
898 | ASSERT_RTNL(); | 913 | ASSERT_RTNL(); |
899 | 914 | ||
@@ -926,11 +941,19 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
926 | * code isn't prepared to handle). | 941 | * code isn't prepared to handle). |
927 | */ | 942 | */ |
928 | break; | 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 | default: | 952 | default: |
930 | return -EBUSY; | 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 | if (ret) | 957 | if (ret) |
935 | return ret; | 958 | return ret; |
936 | 959 | ||
@@ -938,7 +961,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
938 | 961 | ||
939 | ieee80211_teardown_sdata(sdata->dev); | 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 | if (ret) | 965 | if (ret) |
943 | type = sdata->vif.type; | 966 | type = sdata->vif.type; |
944 | 967 | ||
@@ -957,7 +980,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
957 | 980 | ||
958 | ASSERT_RTNL(); | 981 | ASSERT_RTNL(); |
959 | 982 | ||
960 | if (type == sdata->vif.type) | 983 | if (type == ieee80211_vif_type_p2p(&sdata->vif)) |
961 | return 0; | 984 | return 0; |
962 | 985 | ||
963 | /* Setting ad-hoc mode on non-IBSS channel is not supported. */ | 986 | /* Setting ad-hoc mode on non-IBSS channel is not supported. */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 7fb114856977..18fdeca43d98 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -459,6 +459,21 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
459 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | 459 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
460 | BIT(IEEE80211_STYPE_ACTION >> 4), | 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 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 479 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ac205a33690f..c0368152b721 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2588,9 +2588,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2588 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) | 2588 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
2589 | return 0; | 2589 | return 0; |
2590 | break; | 2590 | break; |
2591 | case NL80211_IFTYPE_MONITOR: | 2591 | default: |
2592 | case NL80211_IFTYPE_UNSPECIFIED: | ||
2593 | case NUM_NL80211_IFTYPES: | ||
2594 | /* should never get here */ | 2592 | /* should never get here */ |
2595 | WARN_ON(1); | 2593 | WARN_ON(1); |
2596 | break; | 2594 | break; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9f21a69f0917..737f4267c335 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -474,16 +474,10 @@ void ieee80211_iterate_active_interfaces( | |||
474 | 474 | ||
475 | list_for_each_entry(sdata, &local->interfaces, list) { | 475 | list_for_each_entry(sdata, &local->interfaces, list) { |
476 | switch (sdata->vif.type) { | 476 | switch (sdata->vif.type) { |
477 | case NUM_NL80211_IFTYPES: | ||
478 | case NL80211_IFTYPE_UNSPECIFIED: | ||
479 | case NL80211_IFTYPE_MONITOR: | 477 | case NL80211_IFTYPE_MONITOR: |
480 | case NL80211_IFTYPE_AP_VLAN: | 478 | case NL80211_IFTYPE_AP_VLAN: |
481 | continue; | 479 | continue; |
482 | case NL80211_IFTYPE_AP: | 480 | default: |
483 | case NL80211_IFTYPE_STATION: | ||
484 | case NL80211_IFTYPE_ADHOC: | ||
485 | case NL80211_IFTYPE_WDS: | ||
486 | case NL80211_IFTYPE_MESH_POINT: | ||
487 | break; | 481 | break; |
488 | } | 482 | } |
489 | if (ieee80211_sdata_running(sdata)) | 483 | if (ieee80211_sdata_running(sdata)) |
@@ -508,16 +502,10 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
508 | 502 | ||
509 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 503 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
510 | switch (sdata->vif.type) { | 504 | switch (sdata->vif.type) { |
511 | case NUM_NL80211_IFTYPES: | ||
512 | case NL80211_IFTYPE_UNSPECIFIED: | ||
513 | case NL80211_IFTYPE_MONITOR: | 505 | case NL80211_IFTYPE_MONITOR: |
514 | case NL80211_IFTYPE_AP_VLAN: | 506 | case NL80211_IFTYPE_AP_VLAN: |
515 | continue; | 507 | continue; |
516 | case NL80211_IFTYPE_AP: | 508 | default: |
517 | case NL80211_IFTYPE_STATION: | ||
518 | case NL80211_IFTYPE_ADHOC: | ||
519 | case NL80211_IFTYPE_WDS: | ||
520 | case NL80211_IFTYPE_MESH_POINT: | ||
521 | break; | 509 | break; |
522 | } | 510 | } |
523 | if (ieee80211_sdata_running(sdata)) | 511 | if (ieee80211_sdata_running(sdata)) |
@@ -1193,6 +1181,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1193 | break; | 1181 | break; |
1194 | case NL80211_IFTYPE_UNSPECIFIED: | 1182 | case NL80211_IFTYPE_UNSPECIFIED: |
1195 | case NUM_NL80211_IFTYPES: | 1183 | case NUM_NL80211_IFTYPES: |
1184 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1185 | case NL80211_IFTYPE_P2P_GO: | ||
1196 | WARN_ON(1); | 1186 | WARN_ON(1); |
1197 | break; | 1187 | break; |
1198 | } | 1188 | } |