Search Linux Wireless

[PATCH 5/7] wl12xx: Add rx data filter commands

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Pontus Fuchs <pontus.fuchs@xxxxxxxxx>

Add acx command, structs and definitions needed for the rx data
filter commands.

Signed-off-by: Pontus Fuchs <pontus.fuchs@xxxxxxxxx>
Signed-off-by: Ido Reis <idor@xxxxxx>
Signed-off-by: Eliad Peller <eliad@xxxxxxxxxx>
---
 drivers/net/wireless/wl12xx/acx.c    |   90 ++++++++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/acx.h    |   42 ++++++++++++++++
 drivers/net/wireless/wl12xx/wl12xx.h |   15 ++++++
 3 files changed, 147 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index bc96db0..05bd79c 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1740,3 +1740,93 @@ out:
 	return ret;
 
 }
+
+int wl1271_acx_toggle_rx_data_filter(struct wl1271 *wl, bool enable,
+				     u8 default_action)
+{
+	struct acx_rx_data_filter_state *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx toggle rx data filter en: %d act: %d",
+		     enable, default_action);
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->enable = enable ? 1 : 0;
+	acx->default_action = default_action;
+
+	ret = wl1271_cmd_configure(wl, ACX_ENABLE_RX_DATA_FILTER, acx,
+				   sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("toggling rx data filter failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1271_acx_set_rx_data_filter(struct wl1271 *wl, bool add, u8 index,
+				  u8 action, u8 *pattern, u8 length, u16 offset)
+{
+	struct acx_rx_data_filter_cfg *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx set rx data filter add: %d idx: %d "
+		     "act: %d pat_len: %d offset: %d", add, index, action,
+		     length, offset);
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (index >= WL1271_MAX_RX_DATA_FILTERS ||
+	    length > WL1271_RX_DATA_FILTER_MAX_PATTERN_SIZE ||
+	    (add && !pattern)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	acx->add_filter = add ? 1 : 0;
+	acx->index = index;
+	acx->num_fields = 1;
+	acx->action = action;
+
+	if (add) {
+		/* pattern description */
+		acx->length = length;
+		memcpy(acx->pattern, pattern, length);
+
+		if (offset + length <= WL1271_RX_DATA_FILTER_ETH_HEADER_SIZE) {
+			acx->flag = WL1271_RX_DATA_FILTER_FLAG_ETHERNET_HEADER;
+			acx->offset = cpu_to_le16(offset);
+		} else if (offset >= WL1271_RX_DATA_FILTER_ETH_HEADER_SIZE) {
+			acx->flag = WL1271_RX_DATA_FILTER_FLAG_IP_HEADER;
+			acx->offset = cpu_to_le16(offset -
+				      WL1271_RX_DATA_FILTER_ETH_HEADER_SIZE);
+		} else {
+			wl1271_error("header boundry crossing filters not "
+				     "supported currently");
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	ret = wl1271_cmd_configure(wl, ACX_SET_RX_DATA_FILTER, acx,
+				   sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("setting rx data filter failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index a28fc04..d68cfd2 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1152,6 +1152,43 @@ struct wl12xx_acx_config_hangover {
 	u8 padding[2];
 } __packed;
 
+
+struct acx_rx_data_filter_state {
+	struct acx_header header;
+	u8 enable;
+
+	/* action of type FILTER_XXX */
+	u8 default_action;
+	u8 pad[2];
+} __packed;
+
+
+struct acx_rx_data_filter_cfg {
+	struct acx_header header;
+
+	u8 add_filter;
+
+	/* range 0 - MAX_DATA_FILTERS */
+	u8 index;
+
+	/* action of type FILTER_XXX */
+	u8 action;
+
+	/* number of fields in this filter */
+	u8 num_fields;
+
+	/*
+	 * currently we only support a single filtering field in the driver, so
+	 * spell it out directly here
+	 */
+
+	/* The offset is taken from the start of the first MAC addr */
+	__le16 offset;
+	u8 length;
+	u8 flag;
+	u8 pattern[WL1271_RX_DATA_FILTER_MAX_PATTERN_SIZE];
+} __packed;
+
 enum {
 	ACX_WAKE_UP_CONDITIONS           = 0x0000,
 	ACX_MEM_CFG                      = 0x0001,
@@ -1310,5 +1347,10 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 int wl1271_acx_fm_coex(struct wl1271 *wl);
 int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
 int wl12xx_acx_config_hangover(struct wl1271 *wl);
+int wl1271_acx_toggle_rx_data_filter(struct wl1271 *wl, bool enable,
+				     u8 default_action);
+int wl1271_acx_set_rx_data_filter(struct wl1271 *wl, bool add, u8 index,
+				  u8 action, u8 *pattern, u8 length,
+				  u16 offset);
 
 #endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 1463341..d29de3f 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -277,6 +277,21 @@ struct wl1271_link {
 	u8 ba_bitmap;
 };
 
+#define WL1271_MAX_RX_DATA_FILTERS 4
+#define WL1271_MAX_RX_DATA_FILTER_SIZE 98
+#define WL1271_RX_DATA_FILTER_MAX_FIELD_PATTERNS 8
+#define WL1271_RX_DATA_FILTER_MAX_PATTERN_SIZE 64
+#define WL1271_RX_DATA_FILTER_ETH_HEADER_SIZE 14
+
+#define WL1271_RX_DATA_FILTER_FLAG_IP_HEADER           0
+#define WL1271_RX_DATA_FILTER_FLAG_ETHERNET_HEADER     2
+
+enum rx_data_filter_action {
+	FILTER_DROP = 0,
+	FILTER_SIGNAL = 1,
+	FILTER_FW_HANDLE = 2
+};
+
 struct wl1271 {
 	struct ieee80211_hw *hw;
 	bool mac80211_registered;
-- 
1.7.6.401.g6a319

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux