zd1211rw: Fix alignment problems
authorUlrich Kunitz <kune@deine-taler.de>
Sat, 1 Dec 2007 10:26:05 +0000 (11:26 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 17 Dec 2007 22:01:39 +0000 (17:01 -0500)
Shaddy Baddah found an alignment problem with zd1211rw driver at
2007-11-19. This patch fixes it, it is based on the patch proposed by
Herbert Xu. The alignment 4 has been the agreed value on the
linux-wireless mailing list.

Notify that the problem does only affect the old zd1211rw softmac
driver and not the zd1211rw-mac80211 driver. Daniel Drake has
already provided a patch for the replacement of the softmac
driver, which this patch will break.

Signed-off-by: Ulrich Kunitz <kune@deine-taler.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/zd1211rw/zd_mac.c

index a903645e157a70b62111f26f7159fd4b02bf137a..5298a8bf11298496fa2496544355ef29649a9e89 100644 (file)
@@ -1130,6 +1130,8 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
        __skb_trim(skb, skb->len -
                        (IEEE80211_FCS_LEN + sizeof(struct rx_status)));
 
+       ZD_ASSERT(IS_ALIGNED((unsigned long)skb->data, 4));
+
        update_qual_rssi(mac, skb->data, skb->len, stats.signal,
                         status->signal_strength);
 
@@ -1166,15 +1168,19 @@ static void do_rx(unsigned long mac_ptr)
 int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
 {
        struct sk_buff *skb;
+       unsigned int reserved =
+               ALIGN(max_t(unsigned int,
+                           sizeof(struct zd_rt_hdr), ZD_PLCP_HEADER_SIZE), 4) -
+               ZD_PLCP_HEADER_SIZE;
 
-       skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
+       skb = dev_alloc_skb(reserved + length);
        if (!skb) {
                struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
                dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
                ieee->stats.rx_dropped++;
                return -ENOMEM;
        }
-       skb_reserve(skb, sizeof(struct zd_rt_hdr));
+       skb_reserve(skb, reserved);
        memcpy(__skb_put(skb, length), buffer, length);
        skb_queue_tail(&mac->rx_queue, skb);
        tasklet_schedule(&mac->rx_tasklet);