Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a1d3abc authored by Shahar Levi's avatar Shahar Levi Committed by Luciano Coelho
Browse files

wl12xx: Add support to RX packets payload alignment



In case of QoS packets the packet payload isn't aligned to
4 bytes. In that case the mac80211 layer take care of that
via memmove() in ieee80211_deliver_skb().
Add support of copy packets from aggregation buffer to the
skbs with packet payload aligned care. In case of QoS packets
copy the packets in offset of 2 bytes guarantee payload aligned
to 4 bytes.

Signed-off-by: default avatarShahar Levi <shahar_levi@ti.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent f612cedf
Loading
Loading
Loading
Loading
+31 −8
Original line number Original line Diff line number Diff line
@@ -44,6 +44,14 @@ static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
		RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
		RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
}
}


static bool wl1271_rx_get_unaligned(struct wl1271_fw_common_status *status,
				    u32 drv_rx_counter)
{
	/* Convert the value to bool */
	return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
		RX_BUF_UNALIGNED_PAYLOAD);
}

static void wl1271_rx_status(struct wl1271 *wl,
static void wl1271_rx_status(struct wl1271 *wl,
			     struct wl1271_rx_descriptor *desc,
			     struct wl1271_rx_descriptor *desc,
			     struct ieee80211_rx_status *status,
			     struct ieee80211_rx_status *status,
@@ -89,7 +97,8 @@ static void wl1271_rx_status(struct wl1271 *wl,
	}
	}
}
}


static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
				 bool unaligned)
{
{
	struct wl1271_rx_descriptor *desc;
	struct wl1271_rx_descriptor *desc;
	struct sk_buff *skb;
	struct sk_buff *skb;
@@ -97,6 +106,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
	u8 *buf;
	u8 *buf;
	u8 beacon = 0;
	u8 beacon = 0;
	u8 is_data = 0;
	u8 is_data = 0;
	u8 reserved = unaligned ? NET_IP_ALIGN : 0;


	/*
	/*
	 * In PLT mode we seem to get frames and mac80211 warns about them,
	 * In PLT mode we seem to get frames and mac80211 warns about them,
@@ -131,17 +141,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
		return -EINVAL;
		return -EINVAL;
	}
	}


	skb = __dev_alloc_skb(length, GFP_KERNEL);
	/* skb length not included rx descriptor */
	skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL);
	if (!skb) {
	if (!skb) {
		wl1271_error("Couldn't allocate RX frame");
		wl1271_error("Couldn't allocate RX frame");
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	buf = skb_put(skb, length);
	/* reserve the unaligned payload(if any) */
	memcpy(buf, data, length);
	skb_reserve(skb, reserved);

	buf = skb_put(skb, length - sizeof(*desc));


	/* now we pull the descriptor out of the buffer */
	/*
	skb_pull(skb, sizeof(*desc));
	 * Copy packets from aggregation buffer to the skbs without rx
	 * descriptor and with packet payload aligned care. In case of unaligned
	 * packets copy the packets in offset of 2 bytes guarantee IP header
	 * payload aligned to 4 bytes.
	 */
	memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));


	hdr = (struct ieee80211_hdr *)skb->data;
	hdr = (struct ieee80211_hdr *)skb->data;
	if (ieee80211_is_beacon(hdr->frame_control))
	if (ieee80211_is_beacon(hdr->frame_control))
@@ -175,6 +193,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
	u32 pkt_offset;
	u32 pkt_offset;
	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
	bool had_data = false;
	bool had_data = false;
	bool unaligned = false;


	while (drv_rx_counter != fw_rx_counter) {
	while (drv_rx_counter != fw_rx_counter) {
		buf_size = 0;
		buf_size = 0;
@@ -222,6 +241,10 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
		while (pkt_offset < buf_size) {
		while (pkt_offset < buf_size) {
			pkt_length = wl1271_rx_get_buf_size(status,
			pkt_length = wl1271_rx_get_buf_size(status,
					drv_rx_counter);
					drv_rx_counter);

			unaligned = wl1271_rx_get_unaligned(status,
					drv_rx_counter);

			/*
			/*
			 * the handle data call can only fail in memory-outage
			 * the handle data call can only fail in memory-outage
			 * conditions, in that case the received frame will just
			 * conditions, in that case the received frame will just
@@ -229,7 +252,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
			 */
			 */
			if (wl1271_rx_handle_data(wl,
			if (wl1271_rx_handle_data(wl,
						  wl->aggr_buf + pkt_offset,
						  wl->aggr_buf + pkt_offset,
						  pkt_length) == 1)
						  pkt_length, unaligned) == 1)
				had_data = true;
				had_data = true;


			wl->rx_counter++;
			wl->rx_counter++;
+5 −3
Original line number Original line Diff line number Diff line
@@ -96,6 +96,8 @@
#define RX_MEM_BLOCK_MASK            0xFF
#define RX_MEM_BLOCK_MASK            0xFF
#define RX_BUF_SIZE_MASK             0xFFF00
#define RX_BUF_SIZE_MASK             0xFFF00
#define RX_BUF_SIZE_SHIFT_DIV        6
#define RX_BUF_SIZE_SHIFT_DIV        6
/* If set, the start of IP payload is not 4 bytes aligned */
#define RX_BUF_UNALIGNED_PAYLOAD     BIT(20)


enum {
enum {
	WL12XX_RX_CLASS_UNKNOWN,
	WL12XX_RX_CLASS_UNKNOWN,