p54: include support for 2.13.24.0 USB LM87 Firmwares
authorChristian Lamparter <chunkeey@web.de>
Sat, 29 Nov 2008 21:35:43 +0000 (22:35 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 5 Dec 2008 14:35:44 +0000 (09:35 -0500)
Those firmwares are probably capable of reprogramming the device's eeprom.
We better support them officially, before all the accidents happen.

Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/p54/p54common.c
drivers/net/wireless/p54/p54common.h

index 6f7e82b56cbeee2370c34cca469b5b88439491e2..1b5627d4062eeebd31da91790c701ef38b635118 100644 (file)
@@ -739,7 +739,13 @@ static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
        if (!priv->eeprom)
                return ;
 
-       memcpy(priv->eeprom, eeprom->data, le16_to_cpu(eeprom->len));
+       if (priv->fw_var >= 0x509) {
+               memcpy(priv->eeprom, eeprom->v2.data,
+                      le16_to_cpu(eeprom->v2.len));
+       } else {
+               memcpy(priv->eeprom, eeprom->v1.data,
+                      le16_to_cpu(eeprom->v1.len));
+       }
 
        complete(&priv->eeprom_comp);
 }
@@ -940,12 +946,18 @@ int p54_read_eeprom(struct ieee80211_hw *dev)
        struct p54_hdr *hdr = NULL;
        struct p54_eeprom_lm86 *eeprom_hdr;
        struct sk_buff *skb;
-       size_t eeprom_size = 0x2020, offset = 0, blocksize;
+       size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
        int ret = -ENOMEM;
        void *eeprom = NULL;
 
-       skb = p54_alloc_skb(dev, 0x8000, sizeof(*hdr) + sizeof(*eeprom_hdr) +
-                           EEPROM_READBACK_LEN,
+       maxblocksize = EEPROM_READBACK_LEN;
+       if (priv->fw_var >= 0x509)
+               maxblocksize -= 0xc;
+       else
+               maxblocksize -= 0x4;
+
+       skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(*hdr) +
+                           sizeof(*eeprom_hdr) + maxblocksize,
                            P54_CONTROL_TYPE_EEPROM_READBACK, GFP_KERNEL);
        if (!skb)
                goto free;
@@ -957,12 +969,19 @@ int p54_read_eeprom(struct ieee80211_hw *dev)
                goto free;
 
        eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb,
-                    sizeof(*eeprom_hdr) + EEPROM_READBACK_LEN);
+                    sizeof(*eeprom_hdr) + maxblocksize);
 
        while (eeprom_size) {
-               blocksize = min(eeprom_size, (size_t)EEPROM_READBACK_LEN);
-               eeprom_hdr->offset = cpu_to_le16(offset);
-               eeprom_hdr->len = cpu_to_le16(blocksize);
+               blocksize = min(eeprom_size, maxblocksize);
+               if (priv->fw_var < 0x509) {
+                       eeprom_hdr->v1.offset = cpu_to_le16(offset);
+                       eeprom_hdr->v1.len = cpu_to_le16(blocksize);
+               } else {
+                       eeprom_hdr->v2.offset = cpu_to_le32(offset);
+                       eeprom_hdr->v2.len = cpu_to_le16(blocksize);
+                       eeprom_hdr->v2.magic2 = 0xf;
+                       memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4);
+               }
                priv->tx(dev, skb, 0);
 
                if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) {
index d292ffbec08cfc3037c01e14cb26d3aaf1932586..5a68fdae77305f31e3710e77c39d6f9a4114f72a 100644 (file)
@@ -246,9 +246,21 @@ struct memrecord {
 };
 
 struct p54_eeprom_lm86 {
-       __le16 offset;
-       __le16 len;
-       u8 data[0];
+       union {
+               struct {
+                       __le16 offset;
+                       __le16 len;
+                       u8 data[0];
+               } v1;
+               struct {
+                       __le32 offset;
+                       __le16 len;
+                       u8 magic2;
+                       u8 pad;
+                       u8 magic[4];
+                       u8 data[0];
+               } v2;
+       }  __attribute__ ((packed));
 } __attribute__ ((packed));
 
 enum p54_rx_decrypt_status {