2013-05-21 01:33:33

by Bing Zhao

[permalink] [raw]
Subject: [PATCH 1/2] cfg80211/nl80211: rename packet pattern related structures and enums

From: Amitkumar Karwar <[email protected]>

Packet patterns provided by user are matched with received packets
for WoWLAN feature. Rename these structures and enums so that they
will be available for new feature.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
---
drivers/net/wireless/ath/ath9k/main.c | 2 +-
drivers/net/wireless/mwifiex/cfg80211.c | 3 +--
drivers/net/wireless/ti/wlcore/main.c | 10 ++++-----
include/net/cfg80211.h | 6 +++---
include/uapi/linux/nl80211.h | 36 ++++++++++++++++-----------------
net/wireless/nl80211.c | 34 +++++++++++++++----------------
6 files changed, 44 insertions(+), 47 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6963862..57e290e 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2123,7 +2123,7 @@ static void ath9k_wow_add_pattern(struct ath_softc *sc,
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_wow_pattern *wow_pattern = NULL;
- struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns;
+ struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
int mask_len;
s8 i = 0;

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index d3c8ece..7a06f51 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2250,8 +2250,7 @@ EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);

#ifdef CONFIG_PM
static bool
-mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat,
- s8 *byte_seq)
+mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq)
{
int j, k, valid_byte_cnt = 0;
bool dont_care_byte = false;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 953111a..db3653f 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1328,7 +1328,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl)

#ifdef CONFIG_PM
static int
-wl1271_validate_wowlan_pattern(struct cfg80211_wowlan_trig_pkt_pattern *p)
+wl1271_validate_wowlan_pattern(struct cfg80211_pkt_pattern *p)
{
int num_fields = 0, in_field = 0, fields_size = 0;
int i, pattern_len = 0;
@@ -1471,9 +1471,9 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
* Allocates an RX filter returned through f
* which needs to be freed using rx_filter_free()
*/
-static int wl1271_convert_wowlan_pattern_to_rx_filter(
- struct cfg80211_wowlan_trig_pkt_pattern *p,
- struct wl12xx_rx_filter **f)
+static int
+wl1271_convert_wowlan_pattern_to_rx_filter(struct cfg80211_pkt_pattern *p,
+ struct wl12xx_rx_filter **f)
{
int i, j, ret = 0;
struct wl12xx_rx_filter *filter;
@@ -1575,7 +1575,7 @@ static int wl1271_configure_wowlan(struct wl1271 *wl,

/* Translate WoWLAN patterns into filters */
for (i = 0; i < wow->n_patterns; i++) {
- struct cfg80211_wowlan_trig_pkt_pattern *p;
+ struct cfg80211_pkt_pattern *p;
struct wl12xx_rx_filter *filter = NULL;

p = &wow->patterns[i];
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 32a2f1b..4585b63 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1661,7 +1661,7 @@ struct cfg80211_pmksa {
};

/**
- * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern
+ * struct cfg80211_pkt_pattern - packet pattern
* @mask: bitmask where to match pattern and where to ignore bytes,
* one bit per byte, in same format as nl80211
* @pattern: bytes to match where bitmask is 1
@@ -1671,7 +1671,7 @@ struct cfg80211_pmksa {
* Internal note: @mask and @pattern are allocated in one chunk of
* memory, free @mask only!
*/
-struct cfg80211_wowlan_trig_pkt_pattern {
+struct cfg80211_pkt_pattern {
u8 *mask, *pattern;
int pattern_len;
int pkt_offset;
@@ -1733,7 +1733,7 @@ struct cfg80211_wowlan {
bool any, disconnect, magic_pkt, gtk_rekey_failure,
eap_identity_req, four_way_handshake,
rfkill_release;
- struct cfg80211_wowlan_trig_pkt_pattern *patterns;
+ struct cfg80211_pkt_pattern *patterns;
struct cfg80211_wowlan_tcp *tcp;
int n_patterns;
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 0632071..000dd1d 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3041,11 +3041,11 @@ enum nl80211_tx_power_setting {
};

/**
- * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute
- * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute
- * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has
+ * enum nl80211_packet_pattern_attr - packet pattern attribute
+ * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute
+ * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has
* a zero bit are ignored
- * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have
+ * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have
* a bit for each byte in the pattern. The lowest-order bit corresponds
* to the first byte of the pattern, but the bytes of the pattern are
* in a little-endian-like format, i.e. the 9th byte of the pattern
@@ -3056,23 +3056,23 @@ enum nl80211_tx_power_setting {
* Note that the pattern matching is done as though frames were not
* 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
* first (including SNAP header unpacking) and then matched.
- * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after
+ * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after
* these fixed number of bytes of received packet
- * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
- * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
+ * @NUM_NL80211_PKTPAT: number of attributes
+ * @MAX_NL80211_PKTPAT: max attribute number
*/
-enum nl80211_wowlan_packet_pattern_attr {
- __NL80211_WOWLAN_PKTPAT_INVALID,
- NL80211_WOWLAN_PKTPAT_MASK,
- NL80211_WOWLAN_PKTPAT_PATTERN,
- NL80211_WOWLAN_PKTPAT_OFFSET,
+enum nl80211_packet_pattern_attr {
+ __NL80211_PKTPAT_INVALID,
+ NL80211_PKTPAT_MASK,
+ NL80211_PKTPAT_PATTERN,
+ NL80211_PKTPAT_OFFSET,

- NUM_NL80211_WOWLAN_PKTPAT,
- MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
+ NUM_NL80211_PKTPAT,
+ MAX_NL80211_PKTPAT = NUM_NL80211_PKTPAT - 1,
};

/**
- * struct nl80211_wowlan_pattern_support - pattern support information
+ * struct nl80211_pattern_support - packet pattern support information
* @max_patterns: maximum number of patterns supported
* @min_pattern_len: minimum length of each pattern
* @max_pattern_len: maximum length of each pattern
@@ -3082,7 +3082,7 @@ enum nl80211_wowlan_packet_pattern_attr {
* that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
* capability information given by the kernel to userspace.
*/
-struct nl80211_wowlan_pattern_support {
+struct nl80211_pattern_support {
__u32 max_patterns;
__u32 min_pattern_len;
__u32 max_pattern_len;
@@ -3108,7 +3108,7 @@ struct nl80211_wowlan_pattern_support {
* pattern matching is done after the packet is converted to the MSDU.
*
* In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
- * carrying a &struct nl80211_wowlan_pattern_support.
+ * carrying a &struct nl80211_pattern_support.
*
* When reporting wakeup. it is a u32 attribute containing the 0-based
* index of the pattern that caused the wakeup, in the patterns passed
@@ -3265,7 +3265,7 @@ struct nl80211_wowlan_tcp_data_token_feature {
* @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a
* u32 attribute holding the maximum length
* @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for
- * feature advertising. The mask works like @NL80211_WOWLAN_PKTPAT_MASK
+ * feature advertising. The mask works like @NL80211_PKTPAT_MASK
* but on the TCP payload only.
* @NUM_NL80211_WOWLAN_TCP: number of TCP attributes
* @MAX_NL80211_WOWLAN_TCP: highest attribute number
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5f10f7a..5f640de 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1014,7 +1014,7 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
return -ENOBUFS;

if (dev->wiphy.wowlan.n_patterns) {
- struct nl80211_wowlan_pattern_support pat = {
+ struct nl80211_pattern_support pat = {
.max_patterns = dev->wiphy.wowlan.n_patterns,
.min_pattern_len = dev->wiphy.wowlan.pattern_min_len,
.max_pattern_len = dev->wiphy.wowlan.pattern_max_len,
@@ -7570,12 +7570,11 @@ static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
if (!nl_pat)
return -ENOBUFS;
pat_len = rdev->wowlan->patterns[i].pattern_len;
- if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
- DIV_ROUND_UP(pat_len, 8),
+ if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
rdev->wowlan->patterns[i].mask) ||
- nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
- pat_len, rdev->wowlan->patterns[i].pattern) ||
- nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
+ nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
+ rdev->wowlan->patterns[i].pattern) ||
+ nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
rdev->wowlan->patterns[i].pkt_offset))
return -ENOBUFS;
nla_nest_end(msg, nl_pat);
@@ -7915,7 +7914,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
struct nlattr *pat;
int n_patterns = 0;
int rem, pat_len, mask_len, pkt_offset;
- struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
+ struct nlattr *pat_tb[NUM_NL80211_PKTPAT];

nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
rem)
@@ -7934,26 +7933,25 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)

nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
rem) {
- nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT,
- nla_data(pat), nla_len(pat), NULL);
+ nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
+ nla_len(pat), NULL);
err = -EINVAL;
- if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
- !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
+ if (!pat_tb[NL80211_PKTPAT_MASK] ||
+ !pat_tb[NL80211_PKTPAT_PATTERN])
goto error;
- pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]);
+ pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
mask_len = DIV_ROUND_UP(pat_len, 8);
- if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) !=
- mask_len)
+ if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
goto error;
if (pat_len > wowlan->pattern_max_len ||
pat_len < wowlan->pattern_min_len)
goto error;

- if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
+ if (!pat_tb[NL80211_PKTPAT_OFFSET])
pkt_offset = 0;
else
pkt_offset = nla_get_u32(
- pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
+ pat_tb[NL80211_PKTPAT_OFFSET]);
if (pkt_offset > wowlan->max_pkt_offset)
goto error;
new_triggers.patterns[i].pkt_offset = pkt_offset;
@@ -7967,11 +7965,11 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
new_triggers.patterns[i].pattern =
new_triggers.patterns[i].mask + mask_len;
memcpy(new_triggers.patterns[i].mask,
- nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]),
+ nla_data(pat_tb[NL80211_PKTPAT_MASK]),
mask_len);
new_triggers.patterns[i].pattern_len = pat_len;
memcpy(new_triggers.patterns[i].pattern,
- nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
+ nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
pat_len);
i++;
}
--
1.8.0



2013-05-22 18:46:55

by Bing Zhao

[permalink] [raw]
Subject: RE: [PATCH 2/2] cfg80211/nl80211: Add coalesce support

SGkgSm9oYW5uZXMsDQoNCj4gPiA+IEJlZm9yZSB5b3UgbWFrZSBhbnkgY2hhbmdlcyAoSSBkaWRu
J3QgZ2V0IGFyb3VuZCB0byBjb21tZW50aW5nIG9uIHlvdXINCj4gPiA+IHBhdGNoZXMgeWVzdGVy
ZGF5KSwgSSB0aGluayB5b3UgaGF2ZSB0byBiZSBtb3JlIGNhcmVmdWwgd2l0aCB0aGUgcmVuYW1l
cw0KPiA+ID4gdG8gbm90IGJyZWFrIHRoZSBBUEkuIFBsZWFzZSBwcm92aWRlIGRlZmluZXMgb3Ig
c28gdG8gbm90IGJyZWFrDQo+ID4gPiBjb21waWxhdGlvbiBpbiB0aGUgcmVuYW1lLg0KPiA+DQo+
ID4gIltQQVRDSCAxLzJdIGNmZzgwMjExL25sODAyMTE6IHJlbmFtZSBwYWNrZXQgcGF0dGVybiBy
ZWxhdGVkDQo+ID4gc3RydWN0dXJlcyBhbmQgZW51bXMiIHNob3VsZCBoYXZlIHRha2VuIGNhcmUg
b2YgdGhlIHJlbmFtZXMuIFBsZWFzZQ0KPiA+IGxldCBtZSBrbm93IGlmIEkgbWlzc2VkIGFueXRo
aW5nIGhlcmUuDQo+IA0KPiBJdCBkaWQgaW4gdGhlIGtlcm5lbCwgSSB3YXMgcmVmZXJyaW5nIHRv
IHRoZSBjaGFuZ2VzIGluIG5sODAyMTEuaCwgYXMNCj4gZmFyIGFzIEkgY2FuIHRlbGwgdGhvc2Ug
YnJlYWsgZXhpc3RpbmcgdXNlcnNwYWNlIHRvb2xzLiBZb3Ugc2hvdWxkIGJlDQo+IGFibGUgdG8g
Y29tcGlsZSB0b29scyBsaWtlIGl3IGFuZCB3cGFfc3VwcGxpY2FudCB3aXRoIHRoZSBuZXcgbmw4
MDIxMS5oDQo+IHdpdGhvdXQgY2hhbmdpbmcgYW55dGhpbmcgaW4gdGhlbS4NCg0KSSBzZWUuIFRo
YW5rcyBmb3IgeW91ciBoZWxwLg0KDQpSZWdhcmRzLA0KQmluZw0KDQo=

2013-05-21 01:33:09

by Bing Zhao

[permalink] [raw]
Subject: [PATCH 2/2] cfg80211/nl80211: Add coalesce support

From: Amitkumar Karwar <[email protected]>

Add set/get configuration support for packet coalesce.

This feature needs to be advertised during driver initialization.
Drivers can do required hardware settings based on user configuration.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
---
include/net/cfg80211.h | 51 +++++++++
include/uapi/linux/nl80211.h | 57 +++++++++-
net/wireless/core.c | 2 +
net/wireless/core.h | 22 ++++
net/wireless/nl80211.c | 265 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 394 insertions(+), 3 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4585b63..dcbf125 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1739,6 +1739,35 @@ struct cfg80211_wowlan {
};

/**
+ * struct cfg80211_coalesce_rules - Coalesce rule parameters
+ *
+ * This structure defines coalesce rule for the device.
+ * @delay: maximum coalescing delay in msecs.
+ * @condition: condition for packet coalescence.
+ * i.e. pattern 'match' or 'no match'
+ * @patterns: array of packet patterns
+ * @n_patterns: number of patterns
+ */
+struct cfg80211_coalesce_rules {
+ int delay;
+ u8 condition;
+ struct cfg80211_pkt_pattern *patterns;
+ int n_patterns;
+};
+
+/**
+ * struct cfg80211_coalesce - Packet coalescing settings
+ *
+ * This structure defines coalescing settings.
+ * @rules: array of coalesce rules
+ * @n_rules: number of rules
+ */
+struct cfg80211_coalesce {
+ struct cfg80211_coalesce_rules **rules;
+ int n_rules;
+};
+
+/**
* struct cfg80211_wowlan_wakeup - wakeup report
* @disconnect: woke up by getting disconnected
* @magic_pkt: woke up by receiving magic packet
@@ -2024,6 +2053,7 @@ struct cfg80211_update_ft_ies_params {
* driver can take the most appropriate actions.
* @crit_proto_stop: Indicates critical protocol no longer needs increased link
* reliability. This operation can not fail.
+ * @set_coalesce: Set coalesce parameters.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2259,6 +2289,8 @@ struct cfg80211_ops {
u16 duration);
void (*crit_proto_stop)(struct wiphy *wiphy,
struct wireless_dev *wdev);
+ int (*set_coalesce)(struct wiphy *wiphy,
+ struct cfg80211_coalesce_rules *rule);
};

/*
@@ -2483,6 +2515,23 @@ struct wiphy_wowlan_support {
};

/**
+ * struct wiphy_coalesce_support - coalesce support data
+ * @n_rules: maximum number of coalesce rules
+ * @n_patterns: number of supported patterns
+ * (see nl80211.h for the pattern definition)
+ * @pattern_max_len: maximum length of each pattern
+ * @pattern_min_len: minimum length of each pattern
+ * @max_pkt_offset: maximum Rx packet offset
+ */
+struct wiphy_coalesce_support {
+ int n_rules;
+ int n_patterns;
+ int pattern_max_len;
+ int pattern_min_len;
+ int max_pkt_offset;
+};
+
+/**
* struct wiphy - wireless hardware description
* @reg_notifier: the driver's regulatory notification callback,
* note that if your driver uses wiphy_apply_custom_regulatory()
@@ -2589,6 +2638,7 @@ struct wiphy_wowlan_support {
* 802.11-2012 8.4.2.29 for the defined fields.
* @extended_capabilities_mask: mask of the valid values
* @extended_capabilities_len: length of the extended capabilities
+ * @wiphy_coalesce_support coalesce: coalesce support information
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -2697,6 +2747,7 @@ struct wiphy {
const struct iw_handler_def *wext;
#endif

+ struct wiphy_coalesce_support coalesce;
char priv[0] __aligned(NETDEV_ALIGN);
};

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 000dd1d..3a6bffe 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -648,6 +648,10 @@
* @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
* return back to normal.
*
+ * @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules.
+ *
+ * @NL80211_CMD_SET_COALESCE: Add new coalesce rule.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -810,6 +814,9 @@ enum nl80211_commands {
NL80211_CMD_CRIT_PROTOCOL_START,
NL80211_CMD_CRIT_PROTOCOL_STOP,

+ NL80211_CMD_GET_COALESCE,
+ NL80211_CMD_SET_COALESCE,
+
/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
@@ -1431,6 +1438,8 @@ enum nl80211_commands {
* @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
* the connection should have increased reliability (u16).
*
+ * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1729,6 +1738,8 @@ enum nl80211_attrs {
NL80211_ATTR_CRIT_PROT_ID,
NL80211_ATTR_MAX_CRIT_PROT_DURATION,

+ NL80211_ATTR_COALESCE_RULE,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -3027,7 +3038,6 @@ enum nl80211_cqm_rssi_threshold_event {
NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
};

-
/**
* enum nl80211_tx_power_setting - TX power adjustment
* @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
@@ -3079,8 +3089,10 @@ enum nl80211_packet_pattern_attr {
* @max_pkt_offset: maximum Rx packet offset
*
* This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
- * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
- * capability information given by the kernel to userspace.
+ * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED or in
+ * %NL80211_ATTR_COALESCE_RULE_PKT_PATTERN when that is part of
+ * %NL80211_ATTR_COALESCE_RULE in the capability information given
+ * by the kernel to userspace.
*/
struct nl80211_pattern_support {
__u32 max_patterns;
@@ -3290,6 +3302,41 @@ enum nl80211_wowlan_tcp_attrs {
};

/**
+ * struct nl80211_coalesce_rule_support - coalesce rule support information
+ * @max_rules: maximum number of rules supported
+ * @pat: packet pattern support information
+ *
+ * This struct is carried in %NL80211_ATTR_COALESCE_RULE in the
+ * capability information given by the kernel to userspace.
+ */
+struct nl80211_coalesce_rule_support {
+ __u32 max_rules;
+ struct nl80211_pattern_support pat;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_attr_coalesce_rule - coalesce rule attribute
+ * @__NL80211_COALESCE_RULE_INVALID: invalid number for nested attribute
+ * @NL80211_ATTR_COALESCE_RULE_DELAY: delay in msecs used for packet coalescing
+ * @NL80211_ATTR_COALESCE_RULE_CONDITION: condition for packet coalescence.
+ * i.e. pattern 'match' or 'no match'
+ * @NL80211_ATTR_COALESCE_RULE_PKT_PATTERN: packet offset, pattern is matched
+ * after these fixed number of bytes of received packet
+ * @NUM_NL80211_ATTR_COALESCE_RULE: number of attributes
+ * @NL80211_ATTR_COALESCE_RULE_MAX: max attribute number
+ */
+enum nl80211_attr_coalesce_rule {
+ __NL80211_COALESCE_RULE_INVALID,
+ NL80211_ATTR_COALESCE_RULE_DELAY,
+ NL80211_ATTR_COALESCE_RULE_CONDITION,
+ NL80211_ATTR_COALESCE_RULE_PKT_PATTERN,
+
+ /* keep last */
+ NUM_NL80211_ATTR_COALESCE_RULE,
+ NL80211_ATTR_COALESCE_RULE_MAX = NUM_NL80211_ATTR_COALESCE_RULE - 1
+};
+
+/**
* enum nl80211_iface_limit_attrs - limit attributes
* @NL80211_IFACE_LIMIT_UNSPEC: (reserved)
* @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that
@@ -3569,6 +3616,9 @@ enum nl80211_ap_sme_features {
* Peering Management entity which may be implemented by registering for
* beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is
* still generated by the driver.
+ * @NL80211_FEATURE_PACKET_COALESCE: This driver support packet coalescing
+ * feature. Packets are buffered in firmware based on configured rules
+ * to reduce unwanted packet or interrupt to host.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3588,6 +3638,7 @@ enum nl80211_feature_flags {
NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14,
NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15,
NL80211_FEATURE_USERSPACE_MPM = 1 << 16,
+ NL80211_FEATURE_PACKET_COALESCE = 1 << 17,
};

/**
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 68f0c96..72a41da 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -737,6 +737,8 @@ void wiphy_unregister(struct wiphy *wiphy)
if (rdev->wowlan && rdev->ops->set_wakeup)
rdev_set_wakeup(rdev, false);
cfg80211_rdev_free_wowlan(rdev);
+
+ cfg80211_rdev_free_coalesce(rdev);
}
EXPORT_SYMBOL(wiphy_unregister);

diff --git a/net/wireless/core.h b/net/wireless/core.h
index fd35dae..a0feff6 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -91,6 +91,8 @@ struct cfg80211_registered_device {
/* netlink port which started critical protocol (0 means not started) */
u32 crit_proto_nlportid;

+ struct cfg80211_coalesce *coalesce;
+
/* 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);
@@ -119,6 +121,26 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
kfree(rdev->wowlan);
}

+static inline void
+cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
+{
+ int i, j;
+ struct cfg80211_coalesce_rules *rule;
+
+ if (!rdev->coalesce)
+ return;
+
+ for (i = 0; i < rdev->coalesce->n_rules; i++) {
+ rule = rdev->coalesce->rules[i];
+ for (j = 0; j < rule->n_patterns; j++)
+ kfree(rule->patterns[j].mask);
+ kfree(rule->patterns);
+ kfree(rule);
+ }
+ kfree(rdev->coalesce->rules);
+ kfree(rdev->coalesce);
+}
+
extern struct workqueue_struct *cfg80211_wq;
extern struct mutex cfg80211_mutex;
extern struct list_head cfg80211_rdev_list;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5f640de..8cfca0c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -432,6 +432,14 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
[NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
};

+/* policy for coalesce rule attributes */
+static const struct nla_policy
+nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
+ [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
+ [NL80211_ATTR_COALESCE_RULE_CONDITION] = { .type = NLA_U8 },
+ [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
+};
+
/* policy for GTK rekey offload attributes */
static const struct nla_policy
nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
@@ -1035,6 +1043,27 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
}
#endif

+static int nl80211_send_coalesce(struct sk_buff *msg,
+ struct cfg80211_registered_device *dev,
+ bool large)
+{
+ struct nl80211_coalesce_rule_support rule;
+
+ if (!dev->wiphy.coalesce.n_patterns || !dev->wiphy.coalesce.n_rules)
+ return 0;
+
+ rule.max_rules = dev->wiphy.coalesce.n_rules;
+ rule.pat.max_patterns = dev->wiphy.coalesce.n_patterns;
+ rule.pat.min_pattern_len = dev->wiphy.coalesce.pattern_min_len;
+ rule.pat.max_pattern_len = dev->wiphy.coalesce.pattern_max_len;
+ rule.pat.max_pkt_offset = dev->wiphy.coalesce.max_pkt_offset;
+
+ if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
+ return -ENOBUFS;
+
+ return 0;
+}
+
static int nl80211_send_band_rateinfo(struct sk_buff *msg,
struct ieee80211_supported_band *sband)
{
@@ -1546,6 +1575,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
dev->wiphy.vht_capa_mod_mask))
goto nla_put_failure;

+ (*split_start)++;
+ break;
+ case 10:
+ if (nl80211_send_coalesce(msg, dev, split))
+ goto nla_put_failure;
+
/* done */
*split_start = 0;
break;
@@ -8007,6 +8042,221 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
}
#endif

+static int nl80211_send_coalesce_rules(struct sk_buff *msg,
+ struct cfg80211_registered_device *rdev)
+{
+ struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
+ int i, j, pat_len;
+ struct cfg80211_coalesce_rules *rule;
+
+ if (!rdev->coalesce->n_rules)
+ return 0;
+
+ nl_rules = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE);
+ if (!nl_rules)
+ return -ENOBUFS;
+
+ for (i = 0; i < rdev->coalesce->n_rules; i++) {
+ nl_rule = nla_nest_start(msg, i + 1);
+ if (!nl_rule)
+ return -ENOBUFS;
+
+ rule = rdev->coalesce->rules[i];
+ if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
+ rule->delay))
+ return -ENOBUFS;
+
+ if (nla_put_u8(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
+ rule->condition))
+ return -ENOBUFS;
+
+ nl_pats = nla_nest_start(msg,
+ NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
+ if (!nl_pats)
+ return -ENOBUFS;
+
+ for (j = 0; j < rule->n_patterns; j++) {
+ nl_pat = nla_nest_start(msg, j + 1);
+ if (!nl_pat)
+ return -ENOBUFS;
+ pat_len = rule->patterns[j].pattern_len;
+ if (nla_put(msg, NL80211_PKTPAT_MASK,
+ DIV_ROUND_UP(pat_len, 8),
+ rule->patterns[j].mask) ||
+ nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
+ rule->patterns[j].pattern) ||
+ nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
+ rule->patterns[j].pkt_offset))
+ return -ENOBUFS;
+ nla_nest_end(msg, nl_pat);
+ }
+ nla_nest_end(msg, nl_pats);
+ nla_nest_end(msg, nl_rule);
+ }
+ nla_nest_end(msg, nl_rules);
+
+ return 0;
+}
+
+static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct sk_buff *msg;
+ void *hdr;
+
+ if (!rdev->wiphy.coalesce.n_patterns || !rdev->wiphy.coalesce.n_rules)
+ return -EOPNOTSUPP;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
+ NL80211_CMD_GET_COALESCE);
+ if (!hdr)
+ goto nla_put_failure;
+
+ if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+ return genlmsg_reply(msg, info);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE];
+ struct wiphy_coalesce_support *coalesce = &rdev->wiphy.coalesce;
+ struct cfg80211_coalesce_rules new_rule = {};
+ struct cfg80211_coalesce_rules *nrule;
+ int err, i;
+
+ if (!(rdev->wiphy.features & NL80211_FEATURE_PACKET_COALESCE))
+ return -EOPNOTSUPP;
+ if (!rdev->ops->set_coalesce)
+ return -EOPNOTSUPP;
+
+ if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
+ cfg80211_rdev_free_coalesce(rdev);
+ rdev->coalesce = NULL;
+ rdev->ops->set_coalesce(&rdev->wiphy, NULL);
+ return 0;
+ }
+
+ if (!rdev->coalesce) {
+ rdev->coalesce = kzalloc(sizeof(*rdev->coalesce), GFP_KERNEL);
+ rdev->coalesce->rules = kcalloc(coalesce->n_rules,
+ sizeof(void *), GFP_KERNEL);
+ }
+
+ if (rdev->coalesce->n_rules >= coalesce->n_rules)
+ return -EOPNOTSUPP;
+
+ err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX,
+ nla_data(info->attrs[NL80211_ATTR_COALESCE_RULE]),
+ nla_len(info->attrs[NL80211_ATTR_COALESCE_RULE]),
+ nl80211_coalesce_policy);
+ if (err)
+ return err;
+
+ new_rule.delay = nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
+ new_rule.condition =
+ nla_get_u8(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
+
+ if (tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN]) {
+ struct nlattr *pat;
+ int n_patterns = 0;
+ int rem, pat_len, mask_len, pkt_offset;
+ struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
+
+ nla_for_each_nested(pat,
+ tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
+ rem)
+ n_patterns++;
+ if (n_patterns > coalesce->n_patterns)
+ return -EINVAL;
+
+ new_rule.patterns = kcalloc(n_patterns,
+ sizeof(new_rule.patterns[0]),
+ GFP_KERNEL);
+ if (!new_rule.patterns)
+ return -ENOMEM;
+
+ new_rule.n_patterns = n_patterns;
+ i = 0;
+
+ nla_for_each_nested(pat,
+ tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
+ rem) {
+ nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
+ nla_len(pat), NULL);
+ err = -EINVAL;
+ if (!pat_tb[NL80211_PKTPAT_MASK] ||
+ !pat_tb[NL80211_PKTPAT_PATTERN])
+ goto error;
+ pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
+ mask_len = DIV_ROUND_UP(pat_len, 8);
+ if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) !=
+ mask_len)
+ goto error;
+ if (pat_len > coalesce->pattern_max_len ||
+ pat_len < coalesce->pattern_min_len)
+ goto error;
+
+ if (!pat_tb[NL80211_PKTPAT_OFFSET])
+ pkt_offset = 0;
+ else
+ pkt_offset = nla_get_u32(
+ pat_tb[NL80211_PKTPAT_OFFSET]);
+ if (pkt_offset > coalesce->max_pkt_offset)
+ goto error;
+ new_rule.patterns[i].pkt_offset = pkt_offset;
+
+ new_rule.patterns[i].mask =
+ kmalloc(mask_len + pat_len, GFP_KERNEL);
+ if (!new_rule.patterns[i].mask) {
+ err = -ENOMEM;
+ goto error;
+ }
+ new_rule.patterns[i].pattern =
+ new_rule.patterns[i].mask + mask_len;
+ memcpy(new_rule.patterns[i].mask,
+ nla_data(pat_tb[NL80211_PKTPAT_MASK]),
+ mask_len);
+ new_rule.patterns[i].pattern_len = pat_len;
+ memcpy(new_rule.patterns[i].pattern,
+ nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
+ pat_len);
+ i++;
+ }
+ }
+
+ nrule = kmemdup(&new_rule, sizeof(new_rule), GFP_KERNEL);
+ if (!nrule) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ err = rdev->ops->set_coalesce(&rdev->wiphy, nrule);
+ if (err)
+ goto error;
+
+ rdev->coalesce->rules[rdev->coalesce->n_rules++] = nrule;
+
+ return 0;
+
+error:
+ for (i = 0; i < new_rule.n_patterns; i++)
+ kfree(new_rule.patterns[i].mask);
+ kfree(new_rule.patterns);
+ return err;
+}
+
static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9026,6 +9276,21 @@ static struct genl_ops nl80211_ops[] = {
.flags = GENL_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_GET_COALESCE,
+ .doit = nl80211_get_coalesce,
+ .policy = nl80211_policy,
+ .internal_flags = NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_SET_COALESCE,
+ .doit = nl80211_set_coalesce,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL,
}
};

--
1.8.0


2013-05-22 18:09:31

by Bing Zhao

[permalink] [raw]
Subject: RE: [PATCH 2/2] cfg80211/nl80211: Add coalesce support

SGkgSm9oYW5uZXMsDQoNCj4gPiAicGFja2V0IGNvYWxlc2NlIiB3aWxsIHJldXNlIHRoZSBwYXR0
ZXJuIHN0cnVjdHVyZSAoYW5kIGl0cyBlbnVtIGRlZmluaXRpb25zKSBkZWZpbmVkIGZvcg0KPiA+
IFdvV0xBTi4gSXQncyByZW5hbWVkIHNvIHRoYXQgYm90aCBXb1dMQU4gYW5kIENvYWxlc2NlIGNh
biBtYWtlIHVzZSBvZiBpdC4NCj4gDQo+IEJlZm9yZSB5b3UgbWFrZSBhbnkgY2hhbmdlcyAoSSBk
aWRuJ3QgZ2V0IGFyb3VuZCB0byBjb21tZW50aW5nIG9uIHlvdXINCj4gcGF0Y2hlcyB5ZXN0ZXJk
YXkpLCBJIHRoaW5rIHlvdSBoYXZlIHRvIGJlIG1vcmUgY2FyZWZ1bCB3aXRoIHRoZSByZW5hbWVz
DQo+IHRvIG5vdCBicmVhayB0aGUgQVBJLiBQbGVhc2UgcHJvdmlkZSBkZWZpbmVzIG9yIHNvIHRv
IG5vdCBicmVhaw0KPiBjb21waWxhdGlvbiBpbiB0aGUgcmVuYW1lLg0KDQoiW1BBVENIIDEvMl0g
Y2ZnODAyMTEvbmw4MDIxMTogcmVuYW1lIHBhY2tldCBwYXR0ZXJuIHJlbGF0ZWQgc3RydWN0dXJl
cyBhbmQgZW51bXMiIHNob3VsZCBoYXZlIHRha2VuIGNhcmUgb2YgdGhlIHJlbmFtZXMuIFBsZWFz
ZSBsZXQgbWUga25vdyBpZiBJIG1pc3NlZCBhbnl0aGluZyBoZXJlLg0KDQpPZiBjb3Vyc2UgdGhl
IGRvY3VtZW50YXRpb24gYXMgTHVpcyBjb21tZW50ZWQgd2lsbCBiZSBhZGRlZCBpbiB2MiBzZXJp
ZXMuDQoNClRoYW5rcywNCkJpbmcNCg==

2013-05-22 08:12:33

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 2/2] cfg80211/nl80211: Add coalesce support

On Tue, 2013-05-21 at 16:59 -0700, Bing Zhao wrote:

> "packet coalesce" will reuse the pattern structure (and its enum definitions) defined for
> WoWLAN. It's renamed so that both WoWLAN and Coalesce can make use of it.

Before you make any changes (I didn't get around to commenting on your
patches yesterday), I think you have to be more careful with the renames
to not break the API. Please provide defines or so to not break
compilation in the rename.

johannes


2013-05-22 00:02:46

by Bing Zhao

[permalink] [raw]
Subject: RE: [PATCH 2/2] cfg80211/nl80211: Add coalesce support

Hi Luis,

Thanks for your comments.

> > From: Amitkumar Karwar <[email protected]>
> >
> > Add set/get configuration support for packet coalesce.
> >
> > This feature needs to be advertised during driver initialization.
> > Drivers can do required hardware settings based on user configuration.
> >
> > Signed-off-by: Amitkumar Karwar <[email protected]>
> > Signed-off-by: Bing Zhao <[email protected]>
>
> I see nothing documenting clearly what this "coalesce" does.
> Can you elaborate quite a bit both on the commit log and also
> the documentation on nl80211.h what this is exactly?

will add the documentations in v2.

> It would also be good for you to express on your previous patch why
> you want the rename.

"packet coalesce" will reuse the pattern structure (and its enum definitions) defined for
WoWLAN. It's renamed so that both WoWLAN and Coalesce can make use of it.

More elaborations will be added in v2 series.

>
> If you add this also can you please be sure to update the wiki
> for iw to document support for this?

Sure. It will be done as soon as the iw patches are merged.

Thanks,
Bing

>
> Luis

2013-05-22 18:23:42

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 2/2] cfg80211/nl80211: Add coalesce support


> > Before you make any changes (I didn't get around to commenting on your
> > patches yesterday), I think you have to be more careful with the renames
> > to not break the API. Please provide defines or so to not break
> > compilation in the rename.
>
> "[PATCH 1/2] cfg80211/nl80211: rename packet pattern related
> structures and enums" should have taken care of the renames. Please
> let me know if I missed anything here.

It did in the kernel, I was referring to the changes in nl80211.h, as
far as I can tell those break existing userspace tools. You should be
able to compile tools like iw and wpa_supplicant with the new nl80211.h
without changing anything in them.

johannes


2013-05-21 23:23:07

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 2/2] cfg80211/nl80211: Add coalesce support

On Mon, May 20, 2013 at 06:31:58PM -0700, Bing Zhao wrote:
> From: Amitkumar Karwar <[email protected]>
>
> Add set/get configuration support for packet coalesce.
>
> This feature needs to be advertised during driver initialization.
> Drivers can do required hardware settings based on user configuration.
>
> Signed-off-by: Amitkumar Karwar <[email protected]>
> Signed-off-by: Bing Zhao <[email protected]>

I see nothing documenting clearly what this "coalesce" does.
Can you elaborate quite a bit both on the commit log and also
the documentation on nl80211.h what this is exactly? It would
also be good for you to express on your previous patch why
you want the rename.

If you add this also can you please be sure to update the wiki
for iw to document support for this?

Luis