wlcore: add RX filters util functions
authorEyal Shapira <eyal@wizery.com>
Wed, 14 Mar 2012 04:32:07 +0000 (06:32 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 15 May 2012 21:53:23 +0000 (17:53 -0400)
This is prep work for the support of wowlan patterns
using the FW data rx filters mechanism.
Added an rx filter struct and some util functions
required to manipulate it.

Signed-off-by: Eyal Shapira <eyal@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/wl12xx.h

index b156bc666086d22e73da12ebd3d359c1adb29eba..425a91c48202dcc7a5188cc55e7d7af4b0dabc7b 100644 (file)
@@ -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)
 {
index a9b220c43e54c91400c392e7f1d6b777a9ec2c7e..8ca1fe0d8eb91c5c7de2e847149e691681aa42f0 100644 (file)
@@ -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 */