summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c78
-rw-r--r--drivers/net/wireless/ti/wlcore/wl12xx.h28
2 files changed, 106 insertions, 0 deletions
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index b156bc666086..425a91c48202 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1261,6 +1261,84 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl)
#ifdef CONFIG_PM
+struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void)
+{
+ return kzalloc(sizeof(struct wl12xx_rx_filter), GFP_KERNEL);
+}
+
+void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter)
+{
+ int i;
+
+ if (filter == NULL)
+ return;
+
+ for (i = 0; i < filter->num_fields; i++)
+ kfree(filter->fields[i].pattern);
+
+ kfree(filter);
+}
+
+int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
+ u16 offset, u8 flags,
+ u8 *pattern, u8 len)
+{
+ struct wl12xx_rx_filter_field *field;
+
+ if (filter->num_fields == WL1271_RX_FILTER_MAX_FIELDS) {
+ wl1271_warning("Max fields per RX filter. can't alloc another");
+ return -EINVAL;
+ }
+
+ field = &filter->fields[filter->num_fields];
+
+ field->pattern = kzalloc(len, GFP_KERNEL);
+ if (!field->pattern) {
+ wl1271_warning("Failed to allocate RX filter pattern");
+ return -ENOMEM;
+ }
+
+ filter->num_fields++;
+
+ field->offset = cpu_to_le16(offset);
+ field->flags = flags;
+ field->len = len;
+ memcpy(field->pattern, pattern, len);
+
+ return 0;
+}
+
+int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter)
+{
+ int i, fields_size = 0;
+
+ for (i = 0; i < filter->num_fields; i++)
+ fields_size += filter->fields[i].len +
+ sizeof(struct wl12xx_rx_filter_field) -
+ sizeof(u8 *);
+
+ return fields_size;
+}
+
+void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
+ u8 *buf)
+{
+ int i;
+ struct wl12xx_rx_filter_field *field;
+
+ for (i = 0; i < filter->num_fields; i++) {
+ field = (struct wl12xx_rx_filter_field *)buf;
+
+ field->offset = filter->fields[i].offset;
+ field->flags = filter->fields[i].flags;
+ field->len = filter->fields[i].len;
+
+ memcpy(&field->pattern, filter->fields[i].pattern, field->len);
+ buf += sizeof(struct wl12xx_rx_filter_field) -
+ sizeof(u8 *) + field->len;
+ }
+}
+
static int wl1271_configure_suspend_sta(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
{
diff --git a/drivers/net/wireless/ti/wlcore/wl12xx.h b/drivers/net/wireless/ti/wlcore/wl12xx.h
index a9b220c43e54..8ca1fe0d8eb9 100644
--- a/drivers/net/wireless/ti/wlcore/wl12xx.h
+++ b/drivers/net/wireless/ti/wlcore/wl12xx.h
@@ -279,6 +279,26 @@ struct wl1271_link {
u8 ba_bitmap;
};
+#define WL1271_RX_FILTER_MAX_FIELDS 8
+enum rx_filter_action {
+ FILTER_DROP = 0,
+ FILTER_SIGNAL = 1,
+ FILTER_FW_HANDLE = 2
+};
+
+struct wl12xx_rx_filter_field {
+ __le16 offset;
+ u8 len;
+ u8 flags;
+ u8 *pattern;
+} __packed;
+
+struct wl12xx_rx_filter {
+ u8 action;
+ int num_fields;
+ struct wl12xx_rx_filter_field fields[WL1271_RX_FILTER_MAX_FIELDS];
+};
+
struct wl1271_station {
u8 hlid;
};
@@ -439,6 +459,14 @@ int wl1271_plt_stop(struct wl1271 *wl);
int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_queue_recovery_work(struct wl1271 *wl);
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
+int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
+ u16 offset, u8 flags,
+ u8 *pattern, u8 len);
+void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter);
+struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void);
+int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter);
+void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter,
+ u8 *buf);
#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */