* [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space
@ 2013-04-18 13:49 Arend van Spriel
2013-04-18 13:49 ` [PATCH 2/3] brcmfmac: allow scanning to be suppressed in the driver Arend van Spriel
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Arend van Spriel @ 2013-04-18 13:49 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Arend van Spriel
Some protocols need a more reliable connection to complete
successful in reasonable time. This patch adds a user-space
API to indicate the wireless driver that a critical protocol
is about to commence and when it is done, using nl80211 primitives
NL80211_CMD_CRIT_PROTOCOL_START and NL80211_CRIT_PROTOCOL_STOP.
There can be only on critical protocol session started per
registered cfg80211 device.
The driver can support this by implementing the cfg80211 callbacks
.crit_proto_start() and .crit_proto_stop(). Examples of protocols
that can benefit from this are DHCP, EAPOL, APIPA. Exactly how the
link can/should be made more reliable is up to the driver. Things
to consider are avoid scanning, no multi-channel operations, and
alter coexistence schemes.
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
Hi Johannes,
Not sure whether you made the minor fixes already as you offered
to do so. I saw the change pop-up in your repo a couple of nights
ago, but it disappeared the next morning after another fetch.
I also made related changes in our brcmfmac driver. Can you take
them through your tree as well.
Regards,
Arend
Changelog:
----------
V7:
- remove crit_proto_started field from wireless_dev.
- remove CRIT_PROTO_STOPPED_EVENT definition.
- allow always calling cfg80211_crit_proto_stopped().
V6:
- added crit_proto_stopped event message.
- use nlportid as flag for critical protocol being active.
- return error when duration is over specified limit.
- remove logic from rdev_* inline wrappers.
- added more documentation.
- some renaming of identifiers.
V5:
- change return type for .crit_prot_stop() to void.
- correct limiting the duration.
V4:
- added cfg80211_crit_proto_stopped() for drivers to use.
- added back protocol identifier for drivers to use.
- reject starting critical protocol session when already started.
- critical protocol session tracked per registered device.
V3:
- remove protocol identifier.
- remove delayed work from cfg80211.
- guard maximum limit for duration.
- do .crit_proto_stop() upon netlink socket release.
V2:
- subject changed. Below previous subject is given for reference:
[RFC] cfg80211: configuration of Bluetooth coexistence mode
- introduced dedicated nl80211 API.
V1:
- initial proposal.
---
include/net/cfg80211.h | 23 +++++++++
include/uapi/linux/nl80211.h | 39 ++++++++++++++
net/wireless/core.h | 3 ++
net/wireless/mlme.c | 5 ++
net/wireless/nl80211.c | 117 ++++++++++++++++++++++++++++++++++++++++++
net/wireless/rdev-ops.h | 24 ++++++++-
net/wireless/trace.h | 35 +++++++++++++
7 files changed, 245 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index dff96d8..26b5b69 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2002,6 +2002,12 @@ struct cfg80211_update_ft_ies_params {
* @update_ft_ies: Provide updated Fast BSS Transition information to the
* driver. If the SME is in the driver/firmware, this information can be
* used in building Authentication and Reassociation Request frames.
+ *
+ * @crit_proto_start: Indicates a critical protocol needs more link reliability
+ * for a given duration (milliseconds). The protocol is provided so the
+ * driver can take the most appropriate actions.
+ * @crit_proto_stop: Indicates critical protocol no longer needs increased link
+ * reliability. This operation can not fail.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2231,6 +2237,12 @@ struct cfg80211_ops {
struct cfg80211_chan_def *chandef);
int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_ft_ies_params *ftie);
+ int (*crit_proto_start)(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol,
+ u16 duration);
+ void (*crit_proto_stop)(struct wiphy *wiphy,
+ struct wireless_dev *wdev);
};
/*
@@ -4137,6 +4149,17 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
struct cfg80211_wowlan_wakeup *wakeup,
gfp_t gfp);
+/**
+ * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver.
+ *
+ * @wdev: the wireless device for which critical protocol is stopped.
+ *
+ * This function can be called by the driver to indicate it has reverted
+ * operation back to normal. One reason could be that the duration given
+ * by .crit_proto_start() has expired.
+ */
+void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 79da871..d1e48b5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -639,6 +639,13 @@
* with the relevant Information Elements. This event is used to report
* received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
*
+ * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running
+ * a critical protocol that needs more reliability in the connection to
+ * complete.
+ *
+ * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
+ * return back to normal.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -798,6 +805,9 @@ enum nl80211_commands {
NL80211_CMD_UPDATE_FT_IES,
NL80211_CMD_FT_EVENT,
+ NL80211_CMD_CRIT_PROTOCOL_START,
+ NL80211_CMD_CRIT_PROTOCOL_STOP,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1414,6 +1424,11 @@ enum nl80211_commands {
* @NL80211_ATTR_IE_RIC: Resource Information Container Information
* Element
*
+ * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased
+ * reliability, see &enum nl80211_crit_proto_id (u16).
+ * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
+ * the connection should have increased reliability (u16).
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1709,6 +1724,9 @@ enum nl80211_attrs {
NL80211_ATTR_MDID,
NL80211_ATTR_IE_RIC,
+ NL80211_ATTR_CRIT_PROT_ID,
+ NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3682,4 +3700,25 @@ enum nl80211_protocol_features {
NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0,
};
+/**
+ * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers
+ *
+ * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified.
+ * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol.
+ * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol.
+ * @NL80211_CRIT_PROTO_APIPA: APIPA protocol.
+ * @NUM_NL80211_CRIT_PROTO: must be kept last.
+ */
+enum nl80211_crit_proto_id {
+ NL80211_CRIT_PROTO_UNSPEC,
+ NL80211_CRIT_PROTO_DHCP,
+ NL80211_CRIT_PROTO_EAPOL,
+ NL80211_CRIT_PROTO_APIPA,
+ /* add other protocols before this one */
+ NUM_NL80211_CRIT_PROTO
+};
+
+/* maximum duration for critical protocol measures */
+#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */
+
#endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/core.h b/net/wireless/core.h
index d5d06fd..eac5308 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -88,6 +88,9 @@ struct cfg80211_registered_device {
struct delayed_work dfs_update_channels_wk;
+ /* netlink port which started critical protocol (0 means not started) */
+ u32 crit_proto_nlportid;
+
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
struct wiphy wiphy __aligned(NETDEV_ALIGN);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 390198b..0c7b7dd 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -648,6 +648,11 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
spin_unlock_bh(&wdev->mgmt_registrations_lock);
+ if (nlportid && rdev->crit_proto_nlportid == nlportid) {
+ rdev->crit_proto_nlportid = 0;
+ rdev_crit_proto_stop(rdev, wdev);
+ }
+
if (nlportid == wdev->ap_unexpected_nlportid)
wdev->ap_unexpected_nlportid = 0;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f924d45..96ba1eb 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1417,6 +1417,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
}
CMD(start_p2p_device, START_P2P_DEVICE);
CMD(set_mcast_rate, SET_MCAST_RATE);
+ if (split) {
+ CMD(crit_proto_start, CRIT_PROTOCOL_START);
+ CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
+ }
#ifdef CONFIG_NL80211_TESTMODE
CMD(testmode_cmd, TESTMODE);
@@ -8196,6 +8200,64 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
return rdev_update_ft_ies(rdev, dev, &ft_params);
}
+static int nl80211_crit_protocol_start(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+ enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
+ u16 duration;
+ int ret;
+
+ if (!rdev->ops->crit_proto_start)
+ return -EOPNOTSUPP;
+
+ if (WARN_ON(!rdev->ops->crit_proto_stop))
+ return -EINVAL;
+
+ if (rdev->crit_proto_nlportid)
+ return -EBUSY;
+
+ /* determine protocol if provided */
+ if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
+ proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
+
+ if (proto >= NUM_NL80211_CRIT_PROTO)
+ return -EINVAL;
+
+ /* timeout must be provided */
+ if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
+ return -EINVAL;
+
+ duration =
+ nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
+
+ if (duration > NL80211_CRIT_PROTO_MAX_DURATION)
+ return -ERANGE;
+
+ ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
+ if (!ret)
+ rdev->crit_proto_nlportid = info->snd_portid;
+
+ return ret;
+}
+
+static int nl80211_crit_protocol_stop(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+
+ if (!rdev->ops->crit_proto_stop)
+ return -EOPNOTSUPP;
+
+ if (rdev->crit_proto_nlportid) {
+ rdev->crit_proto_nlportid = 0;
+ rdev_crit_proto_stop(rdev, wdev);
+ }
+ return 0;
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -8885,6 +8947,22 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
+ .doit = nl80211_crit_protocol_start,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
+ .doit = nl80211_crit_protocol_stop,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ }
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -10630,6 +10708,45 @@ void cfg80211_ft_event(struct net_device *netdev,
}
EXPORT_SYMBOL(cfg80211_ft_event);
+void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
+{
+ struct cfg80211_registered_device *rdev;
+ struct sk_buff *msg;
+ void *hdr;
+ u32 nlportid;
+
+ rdev = wiphy_to_dev(wdev->wiphy);
+ if (!rdev->crit_proto_nlportid)
+ return;
+
+ nlportid = rdev->crit_proto_nlportid;
+ rdev->crit_proto_nlportid = 0;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
+ if (!hdr)
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
+ return;
+
+ nla_put_failure:
+ if (hdr)
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
+}
+EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
+
/* initialisation/exit functions */
int nl80211_init(void)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index d77e1c1..9f15f0a 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -875,7 +875,7 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev,
trace_rdev_stop_p2p_device(&rdev->wiphy, wdev);
rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
trace_rdev_return_void(&rdev->wiphy);
-}
+}
static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
struct net_device *dev,
@@ -901,4 +901,26 @@ static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int rdev_crit_proto_start(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol,
+ u16 duration)
+{
+ int ret;
+
+ trace_rdev_crit_proto_start(&rdev->wiphy, wdev, protocol, duration);
+ ret = rdev->ops->crit_proto_start(&rdev->wiphy, wdev,
+ protocol, duration);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ trace_rdev_crit_proto_stop(&rdev->wiphy, wdev);
+ rdev->ops->crit_proto_stop(&rdev->wiphy, wdev);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index ccadef2..499c982 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1805,6 +1805,41 @@ TRACE_EVENT(rdev_update_ft_ies,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md)
);
+TRACE_EVENT(rdev_crit_proto_start,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol, u16 duration),
+ TP_ARGS(wiphy, wdev, protocol, duration),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u16, proto)
+ __field(u16, duration)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->proto = protocol;
+ __entry->duration = duration;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", proto=%x, duration=%u",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->proto, __entry->duration)
+);
+
+TRACE_EVENT(rdev_crit_proto_stop,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
+ WIPHY_PR_ARG, WDEV_PR_ARG)
+);
+
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 2/3] brcmfmac: allow scanning to be suppressed in the driver 2013-04-18 13:49 [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Arend van Spriel @ 2013-04-18 13:49 ` Arend van Spriel 2013-04-18 13:49 ` [PATCH 3/3] brcmfmac: support critical protocol API for DHCP Arend van Spriel ` (2 subsequent siblings) 3 siblings, 0 replies; 8+ messages in thread From: Arend van Spriel @ 2013-04-18 13:49 UTC (permalink / raw) To: Johannes Berg; +Cc: linux-wireless, Arend van Spriel During the DHCP protocol exchange it is benificial to suppress scan requests which may decrease time to complete DHCP protocol. Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 10 ++++++++++ drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 2af9c0f..ccf47a1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -904,6 +904,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, cfg->scan_status); return -EAGAIN; } + if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { + brcmf_err("Scanning suppressed: status (%lu)\n", + cfg->scan_status); + return -EAGAIN; + } if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state); return -EAGAIN; @@ -3058,6 +3063,11 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); return -EAGAIN; } + if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { + brcmf_err("Scanning suppressed: status (%lu)\n", + cfg->scan_status); + return -EAGAIN; + } if (!request || !request->n_ssids || !request->n_match_sets) { brcmf_err("Invalid sched scan req!! n_ssids:%d\n", diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 8b5d498..db531e1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -74,14 +74,16 @@ /** - * enum brcmf_scan_status - dongle scan status + * enum brcmf_scan_status - scan engine status * * @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle. * @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle. + * @BRCMF_SCAN_STATUS_SUPPRESS: scanning is suppressed in driver. */ enum brcmf_scan_status { BRCMF_SCAN_STATUS_BUSY, BRCMF_SCAN_STATUS_ABORT, + BRCMF_SCAN_STATUS_SUPPRESS, }; /** -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] brcmfmac: support critical protocol API for DHCP 2013-04-18 13:49 [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Arend van Spriel 2013-04-18 13:49 ` [PATCH 2/3] brcmfmac: allow scanning to be suppressed in the driver Arend van Spriel @ 2013-04-18 13:49 ` Arend van Spriel 2013-04-22 13:49 ` [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Johannes Berg 2013-05-23 18:30 ` Dan Williams 3 siblings, 0 replies; 8+ messages in thread From: Arend van Spriel @ 2013-04-18 13:49 UTC (permalink / raw) To: Johannes Berg; +Cc: linux-wireless, Piotr Haber, Arend van Spriel From: Piotr Haber <phaber@broadcom.com> Adds support for the critical protocol API provided by nl80211 which gives Wifi traffic priority over a Bluetooth (e)SCO connection and disables scanning during DCHP negotiation. Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Piotr Haber <phaber@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> --- drivers/net/wireless/brcm80211/brcmfmac/Makefile | 3 +- drivers/net/wireless/brcm80211/brcmfmac/btcoex.c | 498 ++++++++++++++++++++ drivers/net/wireless/brcm80211/brcmfmac/btcoex.h | 29 ++ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 46 ++ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | 2 + 5 files changed, 577 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/btcoex.c create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/btcoex.h diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 756e19f..73112e4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -29,7 +29,8 @@ brcmfmac-objs += \ p2p.o \ dhd_cdc.o \ dhd_common.o \ - dhd_linux.o + dhd_linux.o \ + btcoex.o brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ dhd_sdio.o \ bcmsdh.o \ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c new file mode 100644 index 0000000..1a21736 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2013 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <linux/slab.h> +#include <linux/netdevice.h> +#include <net/cfg80211.h> + +#include <brcmu_wifi.h> +#include <brcmu_utils.h> +#include <defs.h> +#include <dhd.h> +#include <dhd_dbg.h> +#include "fwil.h" +#include "fwil_types.h" +#include "btcoex.h" +#include "p2p.h" +#include "wl_cfg80211.h" + +/* T1 start SCO/eSCO priority suppression */ +#define BRCMF_BTCOEX_OPPR_WIN_TIME 2000 + +/* BT registers values during DHCP */ +#define BRCMF_BT_DHCP_REG50 0x8022 +#define BRCMF_BT_DHCP_REG51 0 +#define BRCMF_BT_DHCP_REG64 0 +#define BRCMF_BT_DHCP_REG65 0 +#define BRCMF_BT_DHCP_REG71 0 +#define BRCMF_BT_DHCP_REG66 0x2710 +#define BRCMF_BT_DHCP_REG41 0x33 +#define BRCMF_BT_DHCP_REG68 0x190 + +/* number of samples for SCO detection */ +#define BRCMF_BT_SCO_SAMPLES 12 + +/** +* enum brcmf_btcoex_state - BT coex DHCP state machine states +* @BRCMF_BT_DHCP_IDLE: DCHP is idle +* @BRCMF_BT_DHCP_START: DHCP started, wait before +* boosting wifi priority +* @BRCMF_BT_DHCP_OPPR_WIN: graceful DHCP opportunity ended, +* boost wifi priority +* @BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT: wifi priority boost end, +* restore defaults +*/ +enum brcmf_btcoex_state { + BRCMF_BT_DHCP_IDLE, + BRCMF_BT_DHCP_START, + BRCMF_BT_DHCP_OPPR_WIN, + BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT +}; + +/** + * struct brcmf_btcoex_info - BT coex related information + * @vif: interface for which request was done. + * @timer: timer for DHCP state machine + * @timeout: configured timeout. + * @timer_on: DHCP timer active + * @dhcp_done: DHCP finished before T1/T2 timer expiration + * @bt_state: DHCP state machine state + * @work: DHCP state machine work + * @cfg: driver private data for cfg80211 interface + * @reg66: saved value of btc_params 66 + * @reg41: saved value of btc_params 41 + * @reg68: saved value of btc_params 68 + * @saved_regs_part1: flag indicating regs 66,41,68 + * have been saved + * @reg51: saved value of btc_params 51 + * @reg64: saved value of btc_params 64 + * @reg65: saved value of btc_params 65 + * @reg71: saved value of btc_params 71 + * @saved_regs_part1: flag indicating regs 50,51,64,65,71 + * have been saved + */ +struct brcmf_btcoex_info { + struct brcmf_cfg80211_vif *vif; + struct timer_list timer; + u16 timeout; + bool timer_on; + bool dhcp_done; + enum brcmf_btcoex_state bt_state; + struct work_struct work; + struct brcmf_cfg80211_info *cfg; + u32 reg66; + u32 reg41; + u32 reg68; + bool saved_regs_part1; + u32 reg50; + u32 reg51; + u32 reg64; + u32 reg65; + u32 reg71; + bool saved_regs_part2; +}; + +/** + * brcmf_btcoex_params_write() - write btc_params firmware variable + * @ifp: interface + * @addr: btc_params register number + * @data: data to write + */ +static s32 brcmf_btcoex_params_write(struct brcmf_if *ifp, u32 addr, u32 data) +{ + struct { + __le32 addr; + __le32 data; + } reg_write; + + reg_write.addr = cpu_to_le32(addr); + reg_write.data = cpu_to_le32(data); + return brcmf_fil_iovar_data_set(ifp, "btc_params", + ®_write, sizeof(reg_write)); +} + +/** + * brcmf_btcoex_params_read() - read btc_params firmware variable + * @ifp: interface + * @addr: btc_params register number + * @data: read data + */ +static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data) +{ + *data = addr; + + return brcmf_fil_iovar_int_get(ifp, "btc_params", data); +} + +/** + * brcmf_btcoex_boost_wifi() - control BT SCO/eSCO parameters + * @btci: BT coex info + * @trump_sco: + * true - set SCO/eSCO parameters for compatibility + * during DHCP window + * false - restore saved parameter values + * + * Enhanced BT COEX settings for eSCO compatibility during DHCP window + */ +static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci, + bool trump_sco) +{ + struct brcmf_if *ifp = btci->cfg->pub->iflist[0]; + + if (trump_sco && !btci->saved_regs_part2) { + /* this should reduce eSCO agressive + * retransmit w/o breaking it + */ + + /* save current */ + brcmf_dbg(TRACE, "new SCO/eSCO coex algo {save & override}\n"); + brcmf_btcoex_params_read(ifp, 50, &btci->reg50); + brcmf_btcoex_params_read(ifp, 51, &btci->reg51); + brcmf_btcoex_params_read(ifp, 64, &btci->reg64); + brcmf_btcoex_params_read(ifp, 65, &btci->reg65); + brcmf_btcoex_params_read(ifp, 71, &btci->reg71); + + btci->saved_regs_part2 = true; + brcmf_dbg(TRACE, + "saved bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n", + btci->reg50, btci->reg51, btci->reg64, + btci->reg65, btci->reg71); + + /* pacify the eSco */ + brcmf_btcoex_params_write(ifp, 50, BRCMF_BT_DHCP_REG50); + brcmf_btcoex_params_write(ifp, 51, BRCMF_BT_DHCP_REG51); + brcmf_btcoex_params_write(ifp, 64, BRCMF_BT_DHCP_REG64); + brcmf_btcoex_params_write(ifp, 65, BRCMF_BT_DHCP_REG65); + brcmf_btcoex_params_write(ifp, 71, BRCMF_BT_DHCP_REG71); + + } else if (btci->saved_regs_part2) { + /* restore previously saved bt params */ + brcmf_dbg(TRACE, "Do new SCO/eSCO coex algo {restore}\n"); + brcmf_btcoex_params_write(ifp, 50, btci->reg50); + brcmf_btcoex_params_write(ifp, 51, btci->reg51); + brcmf_btcoex_params_write(ifp, 64, btci->reg64); + brcmf_btcoex_params_write(ifp, 65, btci->reg65); + brcmf_btcoex_params_write(ifp, 71, btci->reg71); + + brcmf_dbg(TRACE, + "restored bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n", + btci->reg50, btci->reg51, btci->reg64, + btci->reg65, btci->reg71); + + btci->saved_regs_part2 = false; + } else { + brcmf_err("attempted to restore not saved BTCOEX params\n"); + } +} + +/** + * brcmf_btcoex_is_sco_active() - check if SCO/eSCO is active + * @ifp: interface + * + * return: true if SCO/eSCO session is active + */ +static bool brcmf_btcoex_is_sco_active(struct brcmf_if *ifp) +{ + int ioc_res = 0; + bool res = false; + int sco_id_cnt = 0; + u32 param27; + int i; + + for (i = 0; i < BRCMF_BT_SCO_SAMPLES; i++) { + ioc_res = brcmf_btcoex_params_read(ifp, 27, ¶m27); + + if (ioc_res < 0) { + brcmf_err("ioc read btc params error\n"); + break; + } + + brcmf_dbg(TRACE, "sample[%d], btc_params 27:%x\n", i, param27); + + if ((param27 & 0x6) == 2) { /* count both sco & esco */ + sco_id_cnt++; + } + + if (sco_id_cnt > 2) { + brcmf_dbg(TRACE, + "sco/esco detected, pkt id_cnt:%d samples:%d\n", + sco_id_cnt, i); + res = true; + break; + } + } + brcmf_dbg(TRACE, "exit: result=%d\n", res); + return res; +} + +/** + * btcmf_btcoex_save_part1() - save first step parameters. + */ +static void btcmf_btcoex_save_part1(struct brcmf_btcoex_info *btci) +{ + struct brcmf_if *ifp = btci->vif->ifp; + + if (!btci->saved_regs_part1) { + /* Retrieve and save original reg value */ + brcmf_btcoex_params_read(ifp, 66, &btci->reg66); + brcmf_btcoex_params_read(ifp, 41, &btci->reg41); + brcmf_btcoex_params_read(ifp, 68, &btci->reg68); + btci->saved_regs_part1 = true; + brcmf_dbg(TRACE, + "saved btc_params regs (66,41,68) 0x%x 0x%x 0x%x\n", + btci->reg66, btci->reg41, + btci->reg68); + } +} + +/** + * brcmf_btcoex_restore_part1() - restore first step parameters. + */ +static void brcmf_btcoex_restore_part1(struct brcmf_btcoex_info *btci) +{ + struct brcmf_if *ifp; + + if (btci->saved_regs_part1) { + btci->saved_regs_part1 = false; + ifp = btci->vif->ifp; + brcmf_btcoex_params_write(ifp, 66, btci->reg66); + brcmf_btcoex_params_write(ifp, 41, btci->reg41); + brcmf_btcoex_params_write(ifp, 68, btci->reg68); + brcmf_dbg(TRACE, + "restored btc_params regs {66,41,68} 0x%x 0x%x 0x%x\n", + btci->reg66, btci->reg41, + btci->reg68); + } +} + +/** + * brcmf_btcoex_timerfunc() - BT coex timer callback + */ +static void brcmf_btcoex_timerfunc(ulong data) +{ + struct brcmf_btcoex_info *bt_local = (struct brcmf_btcoex_info *)data; + brcmf_dbg(TRACE, "enter\n"); + + bt_local->timer_on = false; + schedule_work(&bt_local->work); +} + +/** + * brcmf_btcoex_handler() - BT coex state machine work handler + * @work: work + */ +static void brcmf_btcoex_handler(struct work_struct *work) +{ + struct brcmf_btcoex_info *btci; + btci = container_of(work, struct brcmf_btcoex_info, work); + if (btci->timer_on) { + btci->timer_on = false; + del_timer_sync(&btci->timer); + } + + switch (btci->bt_state) { + case BRCMF_BT_DHCP_START: + /* DHCP started provide OPPORTUNITY window + to get DHCP address + */ + brcmf_dbg(TRACE, "DHCP started\n"); + btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN; + if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME) { + mod_timer(&btci->timer, btci->timer.expires); + } else { + btci->timeout -= BRCMF_BTCOEX_OPPR_WIN_TIME; + mod_timer(&btci->timer, + jiffies + + msecs_to_jiffies(BRCMF_BTCOEX_OPPR_WIN_TIME)); + } + btci->timer_on = true; + break; + + case BRCMF_BT_DHCP_OPPR_WIN: + if (btci->dhcp_done) { + brcmf_dbg(TRACE, "DHCP done before T1 expiration\n"); + goto idle; + } + + /* DHCP is not over yet, start lowering BT priority */ + brcmf_dbg(TRACE, "DHCP T1:%d expired\n", + BRCMF_BTCOEX_OPPR_WIN_TIME); + brcmf_btcoex_boost_wifi(btci, true); + + btci->bt_state = BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT; + mod_timer(&btci->timer, + jiffies + msecs_to_jiffies(btci->timeout)); + btci->timer_on = true; + break; + + case BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT: + if (btci->dhcp_done) + brcmf_dbg(TRACE, "DHCP done before T2 expiration\n"); + else + brcmf_dbg(TRACE, "DHCP T2:%d expired\n", + BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT); + + goto idle; + + default: + brcmf_err("invalid state=%d !!!\n", btci->bt_state); + goto idle; + } + + return; + +idle: + btci->bt_state = BRCMF_BT_DHCP_IDLE; + btci->timer_on = false; + brcmf_btcoex_boost_wifi(btci, false); + cfg80211_crit_proto_stopped(&btci->vif->wdev, GFP_KERNEL); + brcmf_btcoex_restore_part1(btci); + btci->vif = NULL; +} + +/** + * brcmf_btcoex_attach() - initialize BT coex data + * @cfg: driver private cfg80211 data + * + * return: 0 on success + */ +int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg) +{ + struct brcmf_btcoex_info *btci = NULL; + brcmf_dbg(TRACE, "enter\n"); + + btci = kmalloc(sizeof(struct brcmf_btcoex_info), GFP_KERNEL); + if (!btci) + return -ENOMEM; + + btci->bt_state = BRCMF_BT_DHCP_IDLE; + + /* Set up timer for BT */ + btci->timer_on = false; + btci->timeout = BRCMF_BTCOEX_OPPR_WIN_TIME; + init_timer(&btci->timer); + btci->timer.data = (ulong)btci; + btci->timer.function = brcmf_btcoex_timerfunc; + btci->cfg = cfg; + btci->saved_regs_part1 = false; + btci->saved_regs_part2 = false; + + INIT_WORK(&btci->work, brcmf_btcoex_handler); + + cfg->btcoex = btci; + return 0; +} + +/** + * brcmf_btcoex_detach - clean BT coex data + * @cfg: driver private cfg80211 data + */ +void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg) +{ + brcmf_dbg(TRACE, "enter\n"); + + if (!cfg->btcoex) + return; + + if (cfg->btcoex->timer_on) { + cfg->btcoex->timer_on = false; + del_timer_sync(&cfg->btcoex->timer); + } + + cancel_work_sync(&cfg->btcoex->work); + + brcmf_btcoex_boost_wifi(cfg->btcoex, false); + brcmf_btcoex_restore_part1(cfg->btcoex); + + kfree(cfg->btcoex); + cfg->btcoex = NULL; +} + +static void brcmf_btcoex_dhcp_start(struct brcmf_btcoex_info *btci) +{ + struct brcmf_if *ifp = btci->vif->ifp; + + btcmf_btcoex_save_part1(btci); + /* set new regs values */ + brcmf_btcoex_params_write(ifp, 66, BRCMF_BT_DHCP_REG66); + brcmf_btcoex_params_write(ifp, 41, BRCMF_BT_DHCP_REG41); + brcmf_btcoex_params_write(ifp, 68, BRCMF_BT_DHCP_REG68); + btci->dhcp_done = false; + btci->bt_state = BRCMF_BT_DHCP_START; + schedule_work(&btci->work); + brcmf_dbg(TRACE, "enable BT DHCP Timer\n"); +} + +static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci) +{ + /* Stop any bt timer because DHCP session is done */ + btci->dhcp_done = true; + if (btci->timer_on) { + brcmf_dbg(TRACE, "disable BT DHCP Timer\n"); + btci->timer_on = false; + del_timer_sync(&btci->timer); + + /* schedule worker if transition to IDLE is needed */ + if (btci->bt_state != BRCMF_BT_DHCP_IDLE) { + brcmf_dbg(TRACE, "bt_state:%d\n", + btci->bt_state); + schedule_work(&btci->work); + } + } else { + /* Restore original values */ + brcmf_btcoex_restore_part1(btci); + } +} + +/** + * brcmf_btcoex_set_mode - set BT coex mode + * @cfg: driver private cfg80211 data + * @mode: Wifi-Bluetooth coexistence mode + * + * return: 0 on success + */ +int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif, + enum brcmf_btcoex_mode mode, u16 duration) +{ + struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy); + struct brcmf_btcoex_info *btci = cfg->btcoex; + struct brcmf_if *ifp = cfg->pub->iflist[0]; + + switch (mode) { + case BRCMF_BTCOEX_DISABLED: + brcmf_dbg(TRACE, "DHCP session starts\n"); + if (btci->bt_state != BRCMF_BT_DHCP_IDLE) + return -EBUSY; + /* Start BT timer only for SCO connection */ + if (brcmf_btcoex_is_sco_active(ifp)) { + btci->timeout = duration; + btci->vif = vif; + brcmf_btcoex_dhcp_start(btci); + } + break; + + case BRCMF_BTCOEX_ENABLED: + brcmf_dbg(TRACE, "DHCP session ends\n"); + if (btci->bt_state != BRCMF_BT_DHCP_IDLE && + vif == btci->vif) { + brcmf_btcoex_dhcp_end(btci); + } + break; + default: + brcmf_dbg(TRACE, "Unknown mode, ignored\n"); + } + return 0; +} + diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h new file mode 100644 index 0000000..19647c6 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef WL_BTCOEX_H_ +#define WL_BTCOEX_H_ + +enum brcmf_btcoex_mode { + BRCMF_BTCOEX_DISABLED, + BRCMF_BTCOEX_ENABLED +}; + +int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg); +void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg); +int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif, + enum brcmf_btcoex_mode mode, u16 duration); + +#endif /* WL_BTCOEX_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index ccf47a1..7f73cc4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -28,6 +28,7 @@ #include "dhd_dbg.h" #include "fwil_types.h" #include "p2p.h" +#include "btcoex.h" #include "wl_cfg80211.h" #include "fwil.h" @@ -1102,6 +1103,7 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); s32 err = 0; brcmf_dbg(TRACE, "Enter\n"); @@ -1115,6 +1117,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); } clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); + clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); + brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0); brcmf_dbg(TRACE, "Exit\n"); } @@ -4051,6 +4055,39 @@ exit: return err; } +static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_crit_proto_id proto, + u16 duration) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_vif *vif; + + vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); + + /* only DHCP support for now */ + if (proto != NL80211_CRIT_PROTO_DHCP) + return -EINVAL; + + /* suppress and abort scanning */ + set_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); + brcmf_abort_scanning(cfg); + + return brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_DISABLED, duration); +} + +static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_vif *vif; + + vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); + + brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0); + clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); +} + static struct cfg80211_ops wl_cfg80211_ops = { .add_virtual_intf = brcmf_cfg80211_add_iface, .del_virtual_intf = brcmf_cfg80211_del_iface, @@ -4085,6 +4122,8 @@ static struct cfg80211_ops wl_cfg80211_ops = { .mgmt_tx = brcmf_cfg80211_mgmt_tx, .remain_on_channel = brcmf_p2p_remain_on_channel, .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel, + .crit_proto_start = brcmf_cfg80211_crit_proto_start, + .crit_proto_stop = brcmf_cfg80211_crit_proto_stop, #ifdef CONFIG_NL80211_TESTMODE .testmode_cmd = brcmf_cfg80211_testmode #endif @@ -4823,6 +4862,12 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, brcmf_err("P2P initilisation failed (%d)\n", err); goto cfg80211_p2p_attach_out; } + err = brcmf_btcoex_attach(cfg); + if (err) { + brcmf_err("BT-coex initialisation failed (%d)\n", err); + brcmf_p2p_detach(&cfg->p2p); + goto cfg80211_p2p_attach_out; + } return cfg; @@ -4841,6 +4886,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) struct brcmf_cfg80211_vif *tmp; wl_deinit_priv(cfg); + brcmf_btcoex_detach(cfg); list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) { brcmf_free_vif(vif); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index db531e1..20dbed1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -349,6 +349,7 @@ struct brcmf_cfg80211_vif_event { * @wiphy: wiphy object for cfg80211 interface. * @conf: dongle configuration. * @p2p: peer-to-peer specific information. + * @btcoex: Bluetooth coexistence information. * @scan_request: cfg80211 scan request object. * @usr_sync: mainly for dongle up/down synchronization. * @bss_list: bss_list holding scanned ap information. @@ -382,6 +383,7 @@ struct brcmf_cfg80211_info { struct wiphy *wiphy; struct brcmf_cfg80211_conf *conf; struct brcmf_p2p_info p2p; + struct brcmf_btcoex_info *btcoex; struct cfg80211_scan_request *scan_request; struct mutex usr_sync; struct brcmf_scan_results *bss_list; -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space 2013-04-18 13:49 [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Arend van Spriel 2013-04-18 13:49 ` [PATCH 2/3] brcmfmac: allow scanning to be suppressed in the driver Arend van Spriel 2013-04-18 13:49 ` [PATCH 3/3] brcmfmac: support critical protocol API for DHCP Arend van Spriel @ 2013-04-22 13:49 ` Johannes Berg 2013-04-23 7:31 ` Arend van Spriel 2013-05-23 18:30 ` Dan Williams 3 siblings, 1 reply; 8+ messages in thread From: Johannes Berg @ 2013-04-22 13:49 UTC (permalink / raw) To: Arend van Spriel; +Cc: linux-wireless On Thu, 2013-04-18 at 15:49 +0200, Arend van Spriel wrote: > Some protocols need a more reliable connection to complete > successful in reasonable time. This patch adds a user-space > API to indicate the wireless driver that a critical protocol > is about to commence and when it is done, using nl80211 primitives > NL80211_CMD_CRIT_PROTOCOL_START and NL80211_CRIT_PROTOCOL_STOP. > > There can be only on critical protocol session started per > registered cfg80211 device. > > The driver can support this by implementing the cfg80211 callbacks > .crit_proto_start() and .crit_proto_stop(). Examples of protocols > that can benefit from this are DHCP, EAPOL, APIPA. Exactly how the > link can/should be made more reliable is up to the driver. Things > to consider are avoid scanning, no multi-channel operations, and > alter coexistence schemes. Applied. johannes ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space 2013-04-22 13:49 ` [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Johannes Berg @ 2013-04-23 7:31 ` Arend van Spriel 2013-04-23 7:48 ` Johannes Berg 0 siblings, 1 reply; 8+ messages in thread From: Arend van Spriel @ 2013-04-23 7:31 UTC (permalink / raw) To: Johannes Berg; +Cc: linux-wireless On 04/22/2013 03:49 PM, Johannes Berg wrote: > On Thu, 2013-04-18 at 15:49 +0200, Arend van Spriel wrote: >> Some protocols need a more reliable connection to complete >> successful in reasonable time. This patch adds a user-space >> API to indicate the wireless driver that a critical protocol >> is about to commence and when it is done, using nl80211 primitives >> NL80211_CMD_CRIT_PROTOCOL_START and NL80211_CRIT_PROTOCOL_STOP. >> >> There can be only on critical protocol session started per >> registered cfg80211 device. >> >> The driver can support this by implementing the cfg80211 callbacks >> .crit_proto_start() and .crit_proto_stop(). Examples of protocols >> that can benefit from this are DHCP, EAPOL, APIPA. Exactly how the >> link can/should be made more reliable is up to the driver. Things >> to consider are avoid scanning, no multi-channel operations, and >> alter coexistence schemes. > > Applied. Thanks, I do not see the brcmfmac patches so I guess you dropped those, right. They probably did not apply after merging wireless-next. I will rebase and submit them to John. Regards, Arend ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space 2013-04-23 7:31 ` Arend van Spriel @ 2013-04-23 7:48 ` Johannes Berg 0 siblings, 0 replies; 8+ messages in thread From: Johannes Berg @ 2013-04-23 7:48 UTC (permalink / raw) To: Arend van Spriel; +Cc: linux-wireless On Tue, 2013-04-23 at 09:31 +0200, Arend van Spriel wrote: > > Applied. > > Thanks, > > I do not see the brcmfmac patches so I guess you dropped those, right. > They probably did not apply after merging wireless-next. I will rebase > and submit them to John. Yes, I'm not going to take them. johannes ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space 2013-04-18 13:49 [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Arend van Spriel ` (2 preceding siblings ...) 2013-04-22 13:49 ` [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Johannes Berg @ 2013-05-23 18:30 ` Dan Williams 2013-05-24 16:43 ` Arend van Spriel 3 siblings, 1 reply; 8+ messages in thread From: Dan Williams @ 2013-05-23 18:30 UTC (permalink / raw) To: Arend van Spriel; +Cc: Johannes Berg, linux-wireless On Thu, 2013-04-18 at 15:49 +0200, Arend van Spriel wrote: > Some protocols need a more reliable connection to complete > successful in reasonable time. This patch adds a user-space > API to indicate the wireless driver that a critical protocol > is about to commence and when it is done, using nl80211 primitives > NL80211_CMD_CRIT_PROTOCOL_START and NL80211_CRIT_PROTOCOL_STOP. > > There can be only on critical protocol session started per > registered cfg80211 device. Ok, so while implementing support for this in NetworkManager, I ran into a few questions some issues. 1) Why have a new attribute? Why not just use NL80211_ATTR_DURATION like all the other commands do? 2) Why have a restriction on a single critical protocol at a time? Even if this is the case *now*, just for sake of time, we should pass the protocol to the _STOP command to allow for multiples in the future. Yeah, you won't have EAPOL running at the same time as DHCP, but think about it from userspace's perspective: a) process A starts critical protocol like EAPOL b) process A forgets to stop critical protocol c) process B starts critical protocol DHCP, oops, error! d) process B has to clear old critical protocol e) process B starts critical protocol DHCP f) process A realizes it forgot (b) and stops protocol I think there's a lot of opportunity for races here. This would at least be reduced if the START/STOP commands were paired for a specific protocol, and if something requested a STOP for a protocol that's currently not started, it was rejected. Better yet, why not just have an internal array of all the protocols with their max duration and start time, and the stack manages when each protocol gets stopped? (unless you think drivers will have different behavior on a per-protocol basis, eg they'd do something different with DHCP than with EAPOL...?) Dan > The driver can support this by implementing the cfg80211 callbacks > .crit_proto_start() and .crit_proto_stop(). Examples of protocols > that can benefit from this are DHCP, EAPOL, APIPA. Exactly how the > link can/should be made more reliable is up to the driver. Things > to consider are avoid scanning, no multi-channel operations, and > alter coexistence schemes. > > Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> > Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> > Signed-off-by: Arend van Spriel <arend@broadcom.com> > --- > Hi Johannes, > > Not sure whether you made the minor fixes already as you offered > to do so. I saw the change pop-up in your repo a couple of nights > ago, but it disappeared the next morning after another fetch. > > I also made related changes in our brcmfmac driver. Can you take > them through your tree as well. > > Regards, > Arend > > Changelog: > ---------- > V7: > - remove crit_proto_started field from wireless_dev. > - remove CRIT_PROTO_STOPPED_EVENT definition. > - allow always calling cfg80211_crit_proto_stopped(). > V6: > - added crit_proto_stopped event message. > - use nlportid as flag for critical protocol being active. > - return error when duration is over specified limit. > - remove logic from rdev_* inline wrappers. > - added more documentation. > - some renaming of identifiers. > V5: > - change return type for .crit_prot_stop() to void. > - correct limiting the duration. > V4: > - added cfg80211_crit_proto_stopped() for drivers to use. > - added back protocol identifier for drivers to use. > - reject starting critical protocol session when already started. > - critical protocol session tracked per registered device. > V3: > - remove protocol identifier. > - remove delayed work from cfg80211. > - guard maximum limit for duration. > - do .crit_proto_stop() upon netlink socket release. > V2: > - subject changed. Below previous subject is given for reference: > [RFC] cfg80211: configuration of Bluetooth coexistence mode > - introduced dedicated nl80211 API. > V1: > - initial proposal. > --- > include/net/cfg80211.h | 23 +++++++++ > include/uapi/linux/nl80211.h | 39 ++++++++++++++ > net/wireless/core.h | 3 ++ > net/wireless/mlme.c | 5 ++ > net/wireless/nl80211.c | 117 ++++++++++++++++++++++++++++++++++++++++++ > net/wireless/rdev-ops.h | 24 ++++++++- > net/wireless/trace.h | 35 +++++++++++++ > 7 files changed, 245 insertions(+), 1 deletion(-) > > diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h > index dff96d8..26b5b69 100644 > --- a/include/net/cfg80211.h > +++ b/include/net/cfg80211.h > @@ -2002,6 +2002,12 @@ struct cfg80211_update_ft_ies_params { > * @update_ft_ies: Provide updated Fast BSS Transition information to the > * driver. If the SME is in the driver/firmware, this information can be > * used in building Authentication and Reassociation Request frames. > + * > + * @crit_proto_start: Indicates a critical protocol needs more link reliability > + * for a given duration (milliseconds). The protocol is provided so the > + * driver can take the most appropriate actions. > + * @crit_proto_stop: Indicates critical protocol no longer needs increased link > + * reliability. This operation can not fail. > */ > struct cfg80211_ops { > int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); > @@ -2231,6 +2237,12 @@ struct cfg80211_ops { > struct cfg80211_chan_def *chandef); > int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, > struct cfg80211_update_ft_ies_params *ftie); > + int (*crit_proto_start)(struct wiphy *wiphy, > + struct wireless_dev *wdev, > + enum nl80211_crit_proto_id protocol, > + u16 duration); > + void (*crit_proto_stop)(struct wiphy *wiphy, > + struct wireless_dev *wdev); > }; > > /* > @@ -4137,6 +4149,17 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, > struct cfg80211_wowlan_wakeup *wakeup, > gfp_t gfp); > > +/** > + * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver. > + * > + * @wdev: the wireless device for which critical protocol is stopped. > + * > + * This function can be called by the driver to indicate it has reverted > + * operation back to normal. One reason could be that the duration given > + * by .crit_proto_start() has expired. > + */ > +void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp); > + > /* Logging, debugging and troubleshooting/diagnostic helpers. */ > > /* wiphy_printk helpers, similar to dev_printk */ > diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h > index 79da871..d1e48b5 100644 > --- a/include/uapi/linux/nl80211.h > +++ b/include/uapi/linux/nl80211.h > @@ -639,6 +639,13 @@ > * with the relevant Information Elements. This event is used to report > * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). > * > + * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running > + * a critical protocol that needs more reliability in the connection to > + * complete. > + * > + * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can > + * return back to normal. > + * > * @NL80211_CMD_MAX: highest used command number > * @__NL80211_CMD_AFTER_LAST: internal use > */ > @@ -798,6 +805,9 @@ enum nl80211_commands { > NL80211_CMD_UPDATE_FT_IES, > NL80211_CMD_FT_EVENT, > > + NL80211_CMD_CRIT_PROTOCOL_START, > + NL80211_CMD_CRIT_PROTOCOL_STOP, > + > /* add new commands above here */ > > /* used to define NL80211_CMD_MAX below */ > @@ -1414,6 +1424,11 @@ enum nl80211_commands { > * @NL80211_ATTR_IE_RIC: Resource Information Container Information > * Element > * > + * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased > + * reliability, see &enum nl80211_crit_proto_id (u16). > + * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which > + * the connection should have increased reliability (u16). > + * > * @NL80211_ATTR_MAX: highest attribute number currently defined > * @__NL80211_ATTR_AFTER_LAST: internal use > */ > @@ -1709,6 +1724,9 @@ enum nl80211_attrs { > NL80211_ATTR_MDID, > NL80211_ATTR_IE_RIC, > > + NL80211_ATTR_CRIT_PROT_ID, > + NL80211_ATTR_MAX_CRIT_PROT_DURATION, > + > /* add attributes here, update the policy in nl80211.c */ > > __NL80211_ATTR_AFTER_LAST, > @@ -3682,4 +3700,25 @@ enum nl80211_protocol_features { > NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0, > }; > > +/** > + * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers > + * > + * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified. > + * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol. > + * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol. > + * @NL80211_CRIT_PROTO_APIPA: APIPA protocol. > + * @NUM_NL80211_CRIT_PROTO: must be kept last. > + */ > +enum nl80211_crit_proto_id { > + NL80211_CRIT_PROTO_UNSPEC, > + NL80211_CRIT_PROTO_DHCP, > + NL80211_CRIT_PROTO_EAPOL, > + NL80211_CRIT_PROTO_APIPA, > + /* add other protocols before this one */ > + NUM_NL80211_CRIT_PROTO > +}; > + > +/* maximum duration for critical protocol measures */ > +#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */ > + > #endif /* __LINUX_NL80211_H */ > diff --git a/net/wireless/core.h b/net/wireless/core.h > index d5d06fd..eac5308 100644 > --- a/net/wireless/core.h > +++ b/net/wireless/core.h > @@ -88,6 +88,9 @@ struct cfg80211_registered_device { > > struct delayed_work dfs_update_channels_wk; > > + /* netlink port which started critical protocol (0 means not started) */ > + u32 crit_proto_nlportid; > + > /* must be last because of the way we do wiphy_priv(), > * and it should at least be aligned to NETDEV_ALIGN */ > struct wiphy wiphy __aligned(NETDEV_ALIGN); > diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c > index 390198b..0c7b7dd 100644 > --- a/net/wireless/mlme.c > +++ b/net/wireless/mlme.c > @@ -648,6 +648,11 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) > > spin_unlock_bh(&wdev->mgmt_registrations_lock); > > + if (nlportid && rdev->crit_proto_nlportid == nlportid) { > + rdev->crit_proto_nlportid = 0; > + rdev_crit_proto_stop(rdev, wdev); > + } > + > if (nlportid == wdev->ap_unexpected_nlportid) > wdev->ap_unexpected_nlportid = 0; > } > diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c > index f924d45..96ba1eb 100644 > --- a/net/wireless/nl80211.c > +++ b/net/wireless/nl80211.c > @@ -1417,6 +1417,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, > } > CMD(start_p2p_device, START_P2P_DEVICE); > CMD(set_mcast_rate, SET_MCAST_RATE); > + if (split) { > + CMD(crit_proto_start, CRIT_PROTOCOL_START); > + CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); > + } > > #ifdef CONFIG_NL80211_TESTMODE > CMD(testmode_cmd, TESTMODE); > @@ -8196,6 +8200,64 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info) > return rdev_update_ft_ies(rdev, dev, &ft_params); > } > > +static int nl80211_crit_protocol_start(struct sk_buff *skb, > + struct genl_info *info) > +{ > + struct cfg80211_registered_device *rdev = info->user_ptr[0]; > + struct wireless_dev *wdev = info->user_ptr[1]; > + enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC; > + u16 duration; > + int ret; > + > + if (!rdev->ops->crit_proto_start) > + return -EOPNOTSUPP; > + > + if (WARN_ON(!rdev->ops->crit_proto_stop)) > + return -EINVAL; > + > + if (rdev->crit_proto_nlportid) > + return -EBUSY; > + > + /* determine protocol if provided */ > + if (info->attrs[NL80211_ATTR_CRIT_PROT_ID]) > + proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]); > + > + if (proto >= NUM_NL80211_CRIT_PROTO) > + return -EINVAL; > + > + /* timeout must be provided */ > + if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]) > + return -EINVAL; > + > + duration = > + nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]); > + > + if (duration > NL80211_CRIT_PROTO_MAX_DURATION) > + return -ERANGE; > + > + ret = rdev_crit_proto_start(rdev, wdev, proto, duration); > + if (!ret) > + rdev->crit_proto_nlportid = info->snd_portid; > + > + return ret; > +} > + > +static int nl80211_crit_protocol_stop(struct sk_buff *skb, > + struct genl_info *info) > +{ > + struct cfg80211_registered_device *rdev = info->user_ptr[0]; > + struct wireless_dev *wdev = info->user_ptr[1]; > + > + if (!rdev->ops->crit_proto_stop) > + return -EOPNOTSUPP; > + > + if (rdev->crit_proto_nlportid) { > + rdev->crit_proto_nlportid = 0; > + rdev_crit_proto_stop(rdev, wdev); > + } > + return 0; > +} > + > #define NL80211_FLAG_NEED_WIPHY 0x01 > #define NL80211_FLAG_NEED_NETDEV 0x02 > #define NL80211_FLAG_NEED_RTNL 0x04 > @@ -8885,6 +8947,22 @@ static struct genl_ops nl80211_ops[] = { > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > NL80211_FLAG_NEED_RTNL, > }, > + { > + .cmd = NL80211_CMD_CRIT_PROTOCOL_START, > + .doit = nl80211_crit_protocol_start, > + .policy = nl80211_policy, > + .flags = GENL_ADMIN_PERM, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > + NL80211_FLAG_NEED_RTNL, > + }, > + { > + .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP, > + .doit = nl80211_crit_protocol_stop, > + .policy = nl80211_policy, > + .flags = GENL_ADMIN_PERM, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > + NL80211_FLAG_NEED_RTNL, > + } > }; > > static struct genl_multicast_group nl80211_mlme_mcgrp = { > @@ -10630,6 +10708,45 @@ void cfg80211_ft_event(struct net_device *netdev, > } > EXPORT_SYMBOL(cfg80211_ft_event); > > +void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp) > +{ > + struct cfg80211_registered_device *rdev; > + struct sk_buff *msg; > + void *hdr; > + u32 nlportid; > + > + rdev = wiphy_to_dev(wdev->wiphy); > + if (!rdev->crit_proto_nlportid) > + return; > + > + nlportid = rdev->crit_proto_nlportid; > + rdev->crit_proto_nlportid = 0; > + > + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); > + if (!msg) > + return; > + > + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP); > + if (!hdr) > + goto nla_put_failure; > + > + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || > + nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) > + goto nla_put_failure; > + > + genlmsg_end(msg, hdr); > + > + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); > + return; > + > + nla_put_failure: > + if (hdr) > + genlmsg_cancel(msg, hdr); > + nlmsg_free(msg); > + > +} > +EXPORT_SYMBOL(cfg80211_crit_proto_stopped); > + > /* initialisation/exit functions */ > > int nl80211_init(void) > diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h > index d77e1c1..9f15f0a 100644 > --- a/net/wireless/rdev-ops.h > +++ b/net/wireless/rdev-ops.h > @@ -875,7 +875,7 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev, > trace_rdev_stop_p2p_device(&rdev->wiphy, wdev); > rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); > trace_rdev_return_void(&rdev->wiphy); > -} > +} > > static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev, > struct net_device *dev, > @@ -901,4 +901,26 @@ static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev, > return ret; > } > > +static inline int rdev_crit_proto_start(struct cfg80211_registered_device *rdev, > + struct wireless_dev *wdev, > + enum nl80211_crit_proto_id protocol, > + u16 duration) > +{ > + int ret; > + > + trace_rdev_crit_proto_start(&rdev->wiphy, wdev, protocol, duration); > + ret = rdev->ops->crit_proto_start(&rdev->wiphy, wdev, > + protocol, duration); > + trace_rdev_return_int(&rdev->wiphy, ret); > + return ret; > +} > + > +static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev, > + struct wireless_dev *wdev) > +{ > + trace_rdev_crit_proto_stop(&rdev->wiphy, wdev); > + rdev->ops->crit_proto_stop(&rdev->wiphy, wdev); > + trace_rdev_return_void(&rdev->wiphy); > +} > + > #endif /* __CFG80211_RDEV_OPS */ > diff --git a/net/wireless/trace.h b/net/wireless/trace.h > index ccadef2..499c982 100644 > --- a/net/wireless/trace.h > +++ b/net/wireless/trace.h > @@ -1805,6 +1805,41 @@ TRACE_EVENT(rdev_update_ft_ies, > WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md) > ); > > +TRACE_EVENT(rdev_crit_proto_start, > + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, > + enum nl80211_crit_proto_id protocol, u16 duration), > + TP_ARGS(wiphy, wdev, protocol, duration), > + TP_STRUCT__entry( > + WIPHY_ENTRY > + WDEV_ENTRY > + __field(u16, proto) > + __field(u16, duration) > + ), > + TP_fast_assign( > + WIPHY_ASSIGN; > + WDEV_ASSIGN; > + __entry->proto = protocol; > + __entry->duration = duration; > + ), > + TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", proto=%x, duration=%u", > + WIPHY_PR_ARG, WDEV_PR_ARG, __entry->proto, __entry->duration) > +); > + > +TRACE_EVENT(rdev_crit_proto_stop, > + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), > + TP_ARGS(wiphy, wdev), > + TP_STRUCT__entry( > + WIPHY_ENTRY > + WDEV_ENTRY > + ), > + TP_fast_assign( > + WIPHY_ASSIGN; > + WDEV_ASSIGN; > + ), > + TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, > + WIPHY_PR_ARG, WDEV_PR_ARG) > +); > + > /************************************************************* > * cfg80211 exported functions traces * > *************************************************************/ ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space 2013-05-23 18:30 ` Dan Williams @ 2013-05-24 16:43 ` Arend van Spriel 0 siblings, 0 replies; 8+ messages in thread From: Arend van Spriel @ 2013-05-24 16:43 UTC (permalink / raw) To: Dan Williams; +Cc: Johannes Berg, linux-wireless On 05/23/2013 08:30 PM, Dan Williams wrote: > On Thu, 2013-04-18 at 15:49 +0200, Arend van Spriel wrote: >> Some protocols need a more reliable connection to complete >> successful in reasonable time. This patch adds a user-space >> API to indicate the wireless driver that a critical protocol >> is about to commence and when it is done, using nl80211 primitives >> NL80211_CMD_CRIT_PROTOCOL_START and NL80211_CRIT_PROTOCOL_STOP. >> >> There can be only on critical protocol session started per >> registered cfg80211 device. > > Ok, so while implementing support for this in NetworkManager, I ran into > a few questions some issues. Hi Dan, Thanks for your feedback. > 1) Why have a new attribute? Why not just use NL80211_ATTR_DURATION > like all the other commands do? I guess it was overlooked. The only difference is that this attribute is u32. I have not problem changing it. > 2) Why have a restriction on a single critical protocol at a time? Even > if this is the case *now*, just for sake of time, we should pass the > protocol to the _STOP command to allow for multiples in the future. > > Yeah, you won't have EAPOL running at the same time as DHCP, but think > about it from userspace's perspective: > > a) process A starts critical protocol like EAPOL > b) process A forgets to stop critical protocol > c) process B starts critical protocol DHCP, oops, error! > d) process B has to clear old critical protocol > e) process B starts critical protocol DHCP > f) process A realizes it forgot (b) and stops protocol > > I think there's a lot of opportunity for races here. This would at > least be reduced if the START/STOP commands were paired for a specific > protocol, and if something requested a STOP for a protocol that's > currently not started, it was rejected. I guess you are right if the processes mentioned above share the same netlink socket. That is why the netlink portid is used as a flag that a critical protocol has been started. Just scrolled down and found we are not checking the portid in nl80211_crit_proto_stop(). That needs to be fixed or .... we should reconsider based on your feedback. I am not fully convinced there will be a need for multiple protocols. > Better yet, why not just have an internal array of all the protocols > with their max duration and start time, and the stack manages when each > protocol gets stopped? (unless you think drivers will have different > behavior on a per-protocol basis, eg they'd do something different with > DHCP than with EAPOL...?) Not sure if I understand. Does 'start time' mean a fixed time after link being established. The whole idea was that user-space tools would know when a protocol would complete. I do not see how putting static numbers into an array would be 'better yet'. Regards, Arend >> The driver can support this by implementing the cfg80211 callbacks >> .crit_proto_start() and .crit_proto_stop(). Examples of protocols >> that can benefit from this are DHCP, EAPOL, APIPA. Exactly how the >> link can/should be made more reliable is up to the driver. Things >> to consider are avoid scanning, no multi-channel operations, and >> alter coexistence schemes. >> >> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> >> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> >> Signed-off-by: Arend van Spriel <arend@broadcom.com> >> --- >> Hi Johannes, >> >> Not sure whether you made the minor fixes already as you offered >> to do so. I saw the change pop-up in your repo a couple of nights >> ago, but it disappeared the next morning after another fetch. >> >> I also made related changes in our brcmfmac driver. Can you take >> them through your tree as well. >> >> Regards, >> Arend >> >> Changelog: >> ---------- >> V7: >> - remove crit_proto_started field from wireless_dev. >> - remove CRIT_PROTO_STOPPED_EVENT definition. >> - allow always calling cfg80211_crit_proto_stopped(). >> V6: >> - added crit_proto_stopped event message. >> - use nlportid as flag for critical protocol being active. >> - return error when duration is over specified limit. >> - remove logic from rdev_* inline wrappers. >> - added more documentation. >> - some renaming of identifiers. >> V5: >> - change return type for .crit_prot_stop() to void. >> - correct limiting the duration. >> V4: >> - added cfg80211_crit_proto_stopped() for drivers to use. >> - added back protocol identifier for drivers to use. >> - reject starting critical protocol session when already started. >> - critical protocol session tracked per registered device. >> V3: >> - remove protocol identifier. >> - remove delayed work from cfg80211. >> - guard maximum limit for duration. >> - do .crit_proto_stop() upon netlink socket release. >> V2: >> - subject changed. Below previous subject is given for reference: >> [RFC] cfg80211: configuration of Bluetooth coexistence mode >> - introduced dedicated nl80211 API. >> V1: >> - initial proposal. >> --- >> include/net/cfg80211.h | 23 +++++++++ >> include/uapi/linux/nl80211.h | 39 ++++++++++++++ >> net/wireless/core.h | 3 ++ >> net/wireless/mlme.c | 5 ++ >> net/wireless/nl80211.c | 117 ++++++++++++++++++++++++++++++++++++++++++ >> net/wireless/rdev-ops.h | 24 ++++++++- >> net/wireless/trace.h | 35 +++++++++++++ >> 7 files changed, 245 insertions(+), 1 deletion(-) >> >> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h >> index dff96d8..26b5b69 100644 >> --- a/include/net/cfg80211.h >> +++ b/include/net/cfg80211.h >> @@ -2002,6 +2002,12 @@ struct cfg80211_update_ft_ies_params { >> * @update_ft_ies: Provide updated Fast BSS Transition information to the >> * driver. If the SME is in the driver/firmware, this information can be >> * used in building Authentication and Reassociation Request frames. >> + * >> + * @crit_proto_start: Indicates a critical protocol needs more link reliability >> + * for a given duration (milliseconds). The protocol is provided so the >> + * driver can take the most appropriate actions. >> + * @crit_proto_stop: Indicates critical protocol no longer needs increased link >> + * reliability. This operation can not fail. >> */ >> struct cfg80211_ops { >> int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); >> @@ -2231,6 +2237,12 @@ struct cfg80211_ops { >> struct cfg80211_chan_def *chandef); >> int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, >> struct cfg80211_update_ft_ies_params *ftie); >> + int (*crit_proto_start)(struct wiphy *wiphy, >> + struct wireless_dev *wdev, >> + enum nl80211_crit_proto_id protocol, >> + u16 duration); >> + void (*crit_proto_stop)(struct wiphy *wiphy, >> + struct wireless_dev *wdev); >> }; >> >> /* >> @@ -4137,6 +4149,17 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, >> struct cfg80211_wowlan_wakeup *wakeup, >> gfp_t gfp); >> >> +/** >> + * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver. >> + * >> + * @wdev: the wireless device for which critical protocol is stopped. >> + * >> + * This function can be called by the driver to indicate it has reverted >> + * operation back to normal. One reason could be that the duration given >> + * by .crit_proto_start() has expired. >> + */ >> +void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp); >> + >> /* Logging, debugging and troubleshooting/diagnostic helpers. */ >> >> /* wiphy_printk helpers, similar to dev_printk */ >> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h >> index 79da871..d1e48b5 100644 >> --- a/include/uapi/linux/nl80211.h >> +++ b/include/uapi/linux/nl80211.h >> @@ -639,6 +639,13 @@ >> * with the relevant Information Elements. This event is used to report >> * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). >> * >> + * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running >> + * a critical protocol that needs more reliability in the connection to >> + * complete. >> + * >> + * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can >> + * return back to normal. >> + * >> * @NL80211_CMD_MAX: highest used command number >> * @__NL80211_CMD_AFTER_LAST: internal use >> */ >> @@ -798,6 +805,9 @@ enum nl80211_commands { >> NL80211_CMD_UPDATE_FT_IES, >> NL80211_CMD_FT_EVENT, >> >> + NL80211_CMD_CRIT_PROTOCOL_START, >> + NL80211_CMD_CRIT_PROTOCOL_STOP, >> + >> /* add new commands above here */ >> >> /* used to define NL80211_CMD_MAX below */ >> @@ -1414,6 +1424,11 @@ enum nl80211_commands { >> * @NL80211_ATTR_IE_RIC: Resource Information Container Information >> * Element >> * >> + * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased >> + * reliability, see &enum nl80211_crit_proto_id (u16). >> + * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which >> + * the connection should have increased reliability (u16). >> + * >> * @NL80211_ATTR_MAX: highest attribute number currently defined >> * @__NL80211_ATTR_AFTER_LAST: internal use >> */ >> @@ -1709,6 +1724,9 @@ enum nl80211_attrs { >> NL80211_ATTR_MDID, >> NL80211_ATTR_IE_RIC, >> >> + NL80211_ATTR_CRIT_PROT_ID, >> + NL80211_ATTR_MAX_CRIT_PROT_DURATION, >> + >> /* add attributes here, update the policy in nl80211.c */ >> >> __NL80211_ATTR_AFTER_LAST, >> @@ -3682,4 +3700,25 @@ enum nl80211_protocol_features { >> NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0, >> }; >> >> +/** >> + * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers >> + * >> + * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified. >> + * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol. >> + * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol. >> + * @NL80211_CRIT_PROTO_APIPA: APIPA protocol. >> + * @NUM_NL80211_CRIT_PROTO: must be kept last. >> + */ >> +enum nl80211_crit_proto_id { >> + NL80211_CRIT_PROTO_UNSPEC, >> + NL80211_CRIT_PROTO_DHCP, >> + NL80211_CRIT_PROTO_EAPOL, >> + NL80211_CRIT_PROTO_APIPA, >> + /* add other protocols before this one */ >> + NUM_NL80211_CRIT_PROTO >> +}; >> + >> +/* maximum duration for critical protocol measures */ >> +#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */ >> + >> #endif /* __LINUX_NL80211_H */ >> diff --git a/net/wireless/core.h b/net/wireless/core.h >> index d5d06fd..eac5308 100644 >> --- a/net/wireless/core.h >> +++ b/net/wireless/core.h >> @@ -88,6 +88,9 @@ struct cfg80211_registered_device { >> >> struct delayed_work dfs_update_channels_wk; >> >> + /* netlink port which started critical protocol (0 means not started) */ >> + u32 crit_proto_nlportid; >> + >> /* must be last because of the way we do wiphy_priv(), >> * and it should at least be aligned to NETDEV_ALIGN */ >> struct wiphy wiphy __aligned(NETDEV_ALIGN); >> diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c >> index 390198b..0c7b7dd 100644 >> --- a/net/wireless/mlme.c >> +++ b/net/wireless/mlme.c >> @@ -648,6 +648,11 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) >> >> spin_unlock_bh(&wdev->mgmt_registrations_lock); >> >> + if (nlportid && rdev->crit_proto_nlportid == nlportid) { >> + rdev->crit_proto_nlportid = 0; >> + rdev_crit_proto_stop(rdev, wdev); >> + } >> + >> if (nlportid == wdev->ap_unexpected_nlportid) >> wdev->ap_unexpected_nlportid = 0; >> } >> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c >> index f924d45..96ba1eb 100644 >> --- a/net/wireless/nl80211.c >> +++ b/net/wireless/nl80211.c >> @@ -1417,6 +1417,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, >> } >> CMD(start_p2p_device, START_P2P_DEVICE); >> CMD(set_mcast_rate, SET_MCAST_RATE); >> + if (split) { >> + CMD(crit_proto_start, CRIT_PROTOCOL_START); >> + CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); >> + } >> >> #ifdef CONFIG_NL80211_TESTMODE >> CMD(testmode_cmd, TESTMODE); >> @@ -8196,6 +8200,64 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info) >> return rdev_update_ft_ies(rdev, dev, &ft_params); >> } >> >> +static int nl80211_crit_protocol_start(struct sk_buff *skb, >> + struct genl_info *info) >> +{ >> + struct cfg80211_registered_device *rdev = info->user_ptr[0]; >> + struct wireless_dev *wdev = info->user_ptr[1]; >> + enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC; >> + u16 duration; >> + int ret; >> + >> + if (!rdev->ops->crit_proto_start) >> + return -EOPNOTSUPP; >> + >> + if (WARN_ON(!rdev->ops->crit_proto_stop)) >> + return -EINVAL; >> + >> + if (rdev->crit_proto_nlportid) >> + return -EBUSY; >> + >> + /* determine protocol if provided */ >> + if (info->attrs[NL80211_ATTR_CRIT_PROT_ID]) >> + proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]); >> + >> + if (proto >= NUM_NL80211_CRIT_PROTO) >> + return -EINVAL; >> + >> + /* timeout must be provided */ >> + if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]) >> + return -EINVAL; >> + >> + duration = >> + nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]); >> + >> + if (duration > NL80211_CRIT_PROTO_MAX_DURATION) >> + return -ERANGE; >> + >> + ret = rdev_crit_proto_start(rdev, wdev, proto, duration); >> + if (!ret) >> + rdev->crit_proto_nlportid = info->snd_portid; >> + >> + return ret; >> +} >> + >> +static int nl80211_crit_protocol_stop(struct sk_buff *skb, >> + struct genl_info *info) >> +{ >> + struct cfg80211_registered_device *rdev = info->user_ptr[0]; >> + struct wireless_dev *wdev = info->user_ptr[1]; >> + >> + if (!rdev->ops->crit_proto_stop) >> + return -EOPNOTSUPP; >> + >> + if (rdev->crit_proto_nlportid) { >> + rdev->crit_proto_nlportid = 0; >> + rdev_crit_proto_stop(rdev, wdev); >> + } >> + return 0; >> +} >> + >> #define NL80211_FLAG_NEED_WIPHY 0x01 >> #define NL80211_FLAG_NEED_NETDEV 0x02 >> #define NL80211_FLAG_NEED_RTNL 0x04 >> @@ -8885,6 +8947,22 @@ static struct genl_ops nl80211_ops[] = { >> .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | >> NL80211_FLAG_NEED_RTNL, >> }, >> + { >> + .cmd = NL80211_CMD_CRIT_PROTOCOL_START, >> + .doit = nl80211_crit_protocol_start, >> + .policy = nl80211_policy, >> + .flags = GENL_ADMIN_PERM, >> + .internal_flags = NL80211_FLAG_NEED_WDEV_UP | >> + NL80211_FLAG_NEED_RTNL, >> + }, >> + { >> + .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP, >> + .doit = nl80211_crit_protocol_stop, >> + .policy = nl80211_policy, >> + .flags = GENL_ADMIN_PERM, >> + .internal_flags = NL80211_FLAG_NEED_WDEV_UP | >> + NL80211_FLAG_NEED_RTNL, >> + } >> }; >> >> static struct genl_multicast_group nl80211_mlme_mcgrp = { >> @@ -10630,6 +10708,45 @@ void cfg80211_ft_event(struct net_device *netdev, >> } >> EXPORT_SYMBOL(cfg80211_ft_event); >> >> +void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp) >> +{ >> + struct cfg80211_registered_device *rdev; >> + struct sk_buff *msg; >> + void *hdr; >> + u32 nlportid; >> + >> + rdev = wiphy_to_dev(wdev->wiphy); >> + if (!rdev->crit_proto_nlportid) >> + return; >> + >> + nlportid = rdev->crit_proto_nlportid; >> + rdev->crit_proto_nlportid = 0; >> + >> + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); >> + if (!msg) >> + return; >> + >> + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP); >> + if (!hdr) >> + goto nla_put_failure; >> + >> + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || >> + nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) >> + goto nla_put_failure; >> + >> + genlmsg_end(msg, hdr); >> + >> + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); >> + return; >> + >> + nla_put_failure: >> + if (hdr) >> + genlmsg_cancel(msg, hdr); >> + nlmsg_free(msg); >> + >> +} >> +EXPORT_SYMBOL(cfg80211_crit_proto_stopped); >> + >> /* initialisation/exit functions */ >> >> int nl80211_init(void) >> diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h >> index d77e1c1..9f15f0a 100644 >> --- a/net/wireless/rdev-ops.h >> +++ b/net/wireless/rdev-ops.h >> @@ -875,7 +875,7 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev, >> trace_rdev_stop_p2p_device(&rdev->wiphy, wdev); >> rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); >> trace_rdev_return_void(&rdev->wiphy); >> -} >> +} >> >> static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev, >> struct net_device *dev, >> @@ -901,4 +901,26 @@ static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev, >> return ret; >> } >> >> +static inline int rdev_crit_proto_start(struct cfg80211_registered_device *rdev, >> + struct wireless_dev *wdev, >> + enum nl80211_crit_proto_id protocol, >> + u16 duration) >> +{ >> + int ret; >> + >> + trace_rdev_crit_proto_start(&rdev->wiphy, wdev, protocol, duration); >> + ret = rdev->ops->crit_proto_start(&rdev->wiphy, wdev, >> + protocol, duration); >> + trace_rdev_return_int(&rdev->wiphy, ret); >> + return ret; >> +} >> + >> +static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev, >> + struct wireless_dev *wdev) >> +{ >> + trace_rdev_crit_proto_stop(&rdev->wiphy, wdev); >> + rdev->ops->crit_proto_stop(&rdev->wiphy, wdev); >> + trace_rdev_return_void(&rdev->wiphy); >> +} >> + >> #endif /* __CFG80211_RDEV_OPS */ >> diff --git a/net/wireless/trace.h b/net/wireless/trace.h >> index ccadef2..499c982 100644 >> --- a/net/wireless/trace.h >> +++ b/net/wireless/trace.h >> @@ -1805,6 +1805,41 @@ TRACE_EVENT(rdev_update_ft_ies, >> WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md) >> ); >> >> +TRACE_EVENT(rdev_crit_proto_start, >> + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, >> + enum nl80211_crit_proto_id protocol, u16 duration), >> + TP_ARGS(wiphy, wdev, protocol, duration), >> + TP_STRUCT__entry( >> + WIPHY_ENTRY >> + WDEV_ENTRY >> + __field(u16, proto) >> + __field(u16, duration) >> + ), >> + TP_fast_assign( >> + WIPHY_ASSIGN; >> + WDEV_ASSIGN; >> + __entry->proto = protocol; >> + __entry->duration = duration; >> + ), >> + TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", proto=%x, duration=%u", >> + WIPHY_PR_ARG, WDEV_PR_ARG, __entry->proto, __entry->duration) >> +); >> + >> +TRACE_EVENT(rdev_crit_proto_stop, >> + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), >> + TP_ARGS(wiphy, wdev), >> + TP_STRUCT__entry( >> + WIPHY_ENTRY >> + WDEV_ENTRY >> + ), >> + TP_fast_assign( >> + WIPHY_ASSIGN; >> + WDEV_ASSIGN; >> + ), >> + TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, >> + WIPHY_PR_ARG, WDEV_PR_ARG) >> +); >> + >> /************************************************************* >> * cfg80211 exported functions traces * >> *************************************************************/ > > > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-05-24 17:02 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-04-18 13:49 [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Arend van Spriel 2013-04-18 13:49 ` [PATCH 2/3] brcmfmac: allow scanning to be suppressed in the driver Arend van Spriel 2013-04-18 13:49 ` [PATCH 3/3] brcmfmac: support critical protocol API for DHCP Arend van Spriel 2013-04-22 13:49 ` [PATCH V7 1/3] cfg80211: introduce critical protocol indication from user-space Johannes Berg 2013-04-23 7:31 ` Arend van Spriel 2013-04-23 7:48 ` Johannes Berg 2013-05-23 18:30 ` Dan Williams 2013-05-24 16:43 ` Arend van Spriel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).