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 b156bc6..425a91c 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 a9b220c..8ca1fe0 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 */