Commit 2ca27bcff7127da1aa7dd39cd2a6f7cb187e327f

Authored by Johannes Berg
Committed by John W. Linville
1 parent 074ac8df9f

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 */
... ... @@ -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. */
... ... @@ -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,
... ... @@ -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;
... ... @@ -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 }