Commit 2ca27bcf authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

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: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 074ac8df
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -595,7 +595,8 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
					struct ieee80211_vif *vif)
{
	wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
		    __func__, vif->type, vif->addr);
		    __func__, ieee80211_vif_type_p2p(vif),
		    vif->addr);
	hwsim_set_magic(vif);
	return 0;
}
@@ -603,11 +604,14 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,

static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,
					   struct ieee80211_vif *vif,
					   enum nl80211_iftype newtype)
					   enum nl80211_iftype newtype,
					   bool newp2p)
{
	newtype = ieee80211_iftype_p2p(newtype, newp2p);
	wiphy_debug(hw->wiphy,
		    "%s (old type=%d, new type=%d, mac_addr=%pM)\n",
		    __func__, vif->type, newtype, vif->addr);
		    __func__, ieee80211_vif_type_p2p(vif),
		    newtype, vif->addr);
	hwsim_check_magic(vif);

	return 0;
@@ -617,7 +621,8 @@ static void mac80211_hwsim_remove_interface(
	struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
	wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
		    __func__, vif->type, vif->addr);
		    __func__, ieee80211_vif_type_p2p(vif),
		    vif->addr);
	hwsim_check_magic(vif);
	hwsim_clear_magic(vif);
}
@@ -1310,6 +1315,8 @@ static int __init init_mac80211_hwsim(void)
		hw->wiphy->interface_modes =
			BIT(NL80211_IFTYPE_STATION) |
			BIT(NL80211_IFTYPE_AP) |
			BIT(NL80211_IFTYPE_P2P_CLIENT) |
			BIT(NL80211_IFTYPE_P2P_GO) |
			BIT(NL80211_IFTYPE_ADHOC) |
			BIT(NL80211_IFTYPE_MESH_POINT);

+26 −1
Original line number Diff line number Diff line
@@ -769,6 +769,8 @@ struct ieee80211_channel_switch {
 * @bss_conf: BSS configuration for this interface, either our own
 *	or the BSS we're associated to
 * @addr: address of this interface
 * @p2p: indicates whether this AP or STA interface is a p2p
 *	interface, i.e. a GO or p2p-sta respectively
 * @drv_priv: data area for driver use, will always be aligned to
 *	sizeof(void *).
 */
@@ -776,6 +778,7 @@ struct ieee80211_vif {
	enum nl80211_iftype type;
	struct ieee80211_bss_conf bss_conf;
	u8 addr[ETH_ALEN];
	bool p2p;
	/* must be last */
	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
};
@@ -1701,7 +1704,7 @@ struct ieee80211_ops {
			     struct ieee80211_vif *vif);
	int (*change_interface)(struct ieee80211_hw *hw,
				struct ieee80211_vif *vif,
				enum nl80211_iftype new_type);
				enum nl80211_iftype new_type, bool p2p);
	void (*remove_interface)(struct ieee80211_hw *hw,
				 struct ieee80211_vif *vif);
	int (*config)(struct ieee80211_hw *hw, u32 changed);
@@ -2721,4 +2724,26 @@ conf_is_ht(struct ieee80211_conf *conf)
	return conf->channel_type != NL80211_CHAN_NO_HT;
}

static inline enum nl80211_iftype
ieee80211_iftype_p2p(enum nl80211_iftype type, bool p2p)
{
	if (p2p) {
		switch (type) {
		case NL80211_IFTYPE_STATION:
			return NL80211_IFTYPE_P2P_CLIENT;
		case NL80211_IFTYPE_AP:
			return NL80211_IFTYPE_P2P_GO;
		default:
			break;
		}
	}
	return type;
}

static inline enum nl80211_iftype
ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
{
	return ieee80211_iftype_p2p(vif->type, vif->p2p);
}

#endif /* MAC80211_H */
+18 −7
Original line number Diff line number Diff line
@@ -1151,15 +1151,26 @@ static int ieee80211_scan(struct wiphy *wiphy,
			  struct net_device *dev,
			  struct cfg80211_scan_request *req)
{
	struct ieee80211_sub_if_data *sdata;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
	    sdata->vif.type != NL80211_IFTYPE_ADHOC &&
	    sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
	    (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon))
	switch (ieee80211_vif_type_p2p(&sdata->vif)) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_MESH_POINT:
	case NL80211_IFTYPE_P2P_CLIENT:
		break;
	case NL80211_IFTYPE_P2P_GO:
		if (sdata->local->ops->hw_scan)
			break;
		/* FIXME: implement NoA while scanning in software */
		return -EOPNOTSUPP;
	case NL80211_IFTYPE_AP:
		if (sdata->u.ap.beacon)
			return -EOPNOTSUPP;
		break;
	default:
		return -EOPNOTSUPP;
	}

	return ieee80211_request_scan(sdata, req);
}
+3 −3
Original line number Diff line number Diff line
@@ -56,14 +56,14 @@ static inline int drv_add_interface(struct ieee80211_local *local,

static inline int drv_change_interface(struct ieee80211_local *local,
				       struct ieee80211_sub_if_data *sdata,
				       enum nl80211_iftype type)
				       enum nl80211_iftype type, bool p2p)
{
	int ret;

	might_sleep();

	trace_drv_change_interface(local, sdata, type);
	ret = local->ops->change_interface(&local->hw, &sdata->vif, type);
	trace_drv_change_interface(local, sdata, type, p2p);
	ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
	trace_drv_return_int(local, ret);
	return ret;
}
+13 −8
Original line number Diff line number Diff line
@@ -26,11 +26,13 @@ static inline void trace_ ## name(proto) {}
#define STA_PR_ARG	__entry->sta_addr

#define VIF_ENTRY	__field(enum nl80211_iftype, vif_type) __field(void *, sdata)	\
			__field(bool, p2p)						\
			__string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>")
#define VIF_ASSIGN	__entry->vif_type = sdata->vif.type; __entry->sdata = sdata;	\
			__entry->p2p = sdata->vif.p2p;					\
			__assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>")
#define VIF_PR_FMT	" vif:%s(%d)"
#define VIF_PR_ARG	__get_str(vif_name), __entry->vif_type
#define VIF_PR_FMT	" vif:%s(%d%s)"
#define VIF_PR_ARG	__get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""

/*
 * Tracing for driver callbacks.
@@ -139,25 +141,28 @@ TRACE_EVENT(drv_add_interface,
TRACE_EVENT(drv_change_interface,
	TP_PROTO(struct ieee80211_local *local,
		 struct ieee80211_sub_if_data *sdata,
		 enum nl80211_iftype type),
		 enum nl80211_iftype type, bool p2p),

	TP_ARGS(local, sdata, type),
	TP_ARGS(local, sdata, type, p2p),

	TP_STRUCT__entry(
		LOCAL_ENTRY
		VIF_ENTRY
		__field(u32, new_type)
		__field(bool, new_p2p)
	),

	TP_fast_assign(
		LOCAL_ASSIGN;
		VIF_ASSIGN;
		__entry->new_type = type;
		__entry->new_p2p = p2p;
	),

	TP_printk(
		LOCAL_PR_FMT  VIF_PR_FMT " new type:%d",
		LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type
		LOCAL_PR_FMT  VIF_PR_FMT " new type:%d%s",
		LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type,
		__entry->new_p2p ? "/p2p" : ""
	)
);

Loading