* [PATCH] p54usb: support LM87 firmwares
@ 2008-09-02 19:39 Christian Lamparter
2008-09-02 23:14 ` Tomas Winkler
0 siblings, 1 reply; 11+ messages in thread
From: Christian Lamparter @ 2008-09-02 19:39 UTC (permalink / raw)
To: linux-wireless; +Cc: John W Linville, Larry Finger
This patch adds the necessary changes to support LM87 firmwares.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
---
John,
this one should go into wireless-next.
---
diff -Nurp a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
--- a/drivers/net/wireless/p54/p54common.c 2008-09-01 22:25:35.000000000 +0200
+++ b/drivers/net/wireless/p54/p54common.c 2008-09-02 21:29:47.000000000 +0200
@@ -93,7 +93,10 @@ int p54_parse_firmware(struct ieee80211_
u32 code = le32_to_cpu(bootrec->code);
switch (code) {
case BR_CODE_COMPONENT_ID:
- switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
+ priv->fw_interface =
+ be32_to_cpu(*(__be32 *)bootrec->data);
+
+ switch (priv->fw_interface) {
case FW_FMAC:
printk(KERN_INFO "p54: FreeMAC firmware\n");
break;
@@ -104,7 +107,7 @@ int p54_parse_firmware(struct ieee80211_
printk(KERN_INFO "p54: LM86 firmware\n");
break;
case FW_LM87:
- printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
+ printk(KERN_INFO "p54: LM87 firmware\n");
break;
default:
printk(KERN_INFO "p54: unknown firmware\n");
diff -Nurp a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
--- a/drivers/net/wireless/p54/p54common.h 2008-09-01 01:56:53.000000000 +0200
+++ b/drivers/net/wireless/p54/p54common.h 2008-09-02 19:39:10.000000000 +0200
@@ -50,11 +50,6 @@ struct bootrec_desc {
#define BR_CODE_END_OF_BRA 0xFF0000FF
#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
-#define FW_FMAC 0x464d4143
-#define FW_LM86 0x4c4d3836
-#define FW_LM87 0x4c4d3837
-#define FW_LM20 0x4c4d3230
-
/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
struct pda_entry {
diff -Nurp a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
--- a/drivers/net/wireless/p54/p54.h 2008-09-01 02:20:25.000000000 +0200
+++ b/drivers/net/wireless/p54/p54.h 2008-09-02 19:39:26.000000000 +0200
@@ -42,6 +42,11 @@ struct p54_control_hdr {
#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
+#define FW_FMAC 0x464d4143
+#define FW_LM86 0x4c4d3836
+#define FW_LM87 0x4c4d3837
+#define FW_LM20 0x4c4d3230
+
struct p54_common {
u32 rx_start;
u32 rx_end;
@@ -68,6 +73,7 @@ struct p54_common {
unsigned int tx_hdr_len;
void *cached_vdcf;
unsigned int fw_var;
+ unsigned int fw_interface;
struct ieee80211_tx_queue_stats tx_stats[8];
void *eeprom;
struct completion eeprom_comp;
diff -Nurp a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
--- a/drivers/net/wireless/p54/p54usb.c 2008-09-01 22:23:46.000000000 +0200
+++ b/drivers/net/wireless/p54/p54usb.c 2008-09-02 21:28:36.000000000 +0200
@@ -91,8 +91,13 @@ static void p54u_rx_cb(struct urb *urb)
skb_unlink(skb, &priv->rx_queue);
skb_put(skb, urb->actual_length);
- if (!priv->hw_type)
- skb_pull(skb, sizeof(struct net2280_tx_hdr));
+
+ if (priv->hw_type == P54U_NET2280)
+ skb_pull(skb, priv->common.tx_hdr_len);
+ if (priv->common.fw_interface == FW_LM87) {
+ skb_pull(skb, 4);
+ skb_put(skb, 4);
+ }
if (p54_rx(dev, skb)) {
skb = dev_alloc_skb(priv->common.rx_mtu + 32);
@@ -109,9 +114,12 @@ static void p54u_rx_cb(struct urb *urb)
urb->context = skb;
skb_queue_tail(&priv->rx_queue, skb);
} else {
- if (!priv->hw_type)
- skb_push(skb, sizeof(struct net2280_tx_hdr));
-
+ if (priv->hw_type == P54U_NET2280)
+ skb_push(skb, priv->common.tx_hdr_len);
+ if (priv->common.fw_interface == FW_LM87) {
+ skb_push(skb, 4);
+ skb_put(skb, 4);
+ }
skb_reset_tail_pointer(skb);
skb_trim(skb, 0);
if (urb->transfer_buffer != skb_tail_pointer(skb)) {
@@ -210,6 +218,42 @@ static void p54u_tx_3887(struct ieee8021
usb_submit_urb(data_urb, GFP_ATOMIC);
}
+__le32 p54u_lm87_chksum(const u32 *data, size_t length)
+{
+ __le32 chk = 0;
+
+ length >>= 2;
+ while (length--) {
+ chk ^= cpu_to_le32(*data++);
+ chk = (chk >> 5) ^ (chk << 3);
+ }
+
+ return chk;
+}
+
+static void p54u_tx_lm87(struct ieee80211_hw *dev,
+ struct p54_control_hdr *data,
+ size_t len, int free_on_tx)
+{
+ struct p54u_priv *priv = dev->priv;
+ struct urb *data_urb;
+ struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr);
+
+ data_urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!data_urb)
+ return;
+
+ hdr->chksum = p54u_lm87_chksum((u32 *)data, len);
+ hdr->device_addr = data->req_id;
+
+ usb_fill_bulk_urb(data_urb, priv->udev,
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
+ len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb,
+ dev);
+
+ usb_submit_urb(data_urb, GFP_ATOMIC);
+}
+
static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
size_t len, int free_on_tx)
{
@@ -776,21 +820,23 @@ static int __devinit p54u_probe(struct u
}
}
priv->common.open = p54u_open;
-
+ priv->common.stop = p54u_stop;
if (recognized_pipes < P54U_PIPE_NUMBER) {
priv->hw_type = P54U_3887;
- priv->common.tx = p54u_tx_3887;
+ err = p54u_upload_firmware_3887(dev);
+ if (priv->common.fw_interface == FW_LM87) {
+ dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
+ priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
+ priv->common.tx = p54u_tx_lm87;
+ } else
+ priv->common.tx = p54u_tx_3887;
} else {
+ priv->hw_type = P54U_NET2280;
dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
priv->common.tx = p54u_tx_net2280;
- }
- priv->common.stop = p54u_stop;
-
- if (priv->hw_type)
- err = p54u_upload_firmware_3887(dev);
- else
err = p54u_upload_firmware_net2280(dev);
+ }
if (err)
goto err_free_dev;
diff -Nurp a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
--- a/drivers/net/wireless/p54/p54usb.h 2008-09-01 01:56:53.000000000 +0200
+++ b/drivers/net/wireless/p54/p54usb.h 2008-09-02 19:23:52.000000000 +0200
@@ -72,6 +72,11 @@ struct net2280_tx_hdr {
u8 padding[8];
} __attribute__((packed));
+struct lm87_tx_hdr {
+ __le32 device_addr;
+ __le32 chksum;
+} __attribute__((packed));
+
/* Some flags for the isl hardware registers controlling DMA inside the
* chip */
#define ISL38XX_DMA_STATUS_DONE 0x00000001
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH] p54usb: support LM87 firmwares 2008-09-02 19:39 [PATCH] p54usb: support LM87 firmwares Christian Lamparter @ 2008-09-02 23:14 ` Tomas Winkler 2008-09-03 0:00 ` Christian Lamparter 0 siblings, 1 reply; 11+ messages in thread From: Tomas Winkler @ 2008-09-02 23:14 UTC (permalink / raw) To: Christian Lamparter; +Cc: linux-wireless, John W Linville, Larry Finger On Tue, Sep 2, 2008 at 10:39 PM, Christian Lamparter <chunkeey@web.de> wrote: > This patch adds the necessary changes to support LM87 firmwares. > > Signed-off-by: Christian Lamparter <chunkeey@web.de> > --- > John, > > this one should go into wireless-next. > --- > diff -Nurp a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c > --- a/drivers/net/wireless/p54/p54common.c 2008-09-01 22:25:35.000000000 +0200 > +++ b/drivers/net/wireless/p54/p54common.c 2008-09-02 21:29:47.000000000 +0200 > @@ -93,7 +93,10 @@ int p54_parse_firmware(struct ieee80211_ > u32 code = le32_to_cpu(bootrec->code); > switch (code) { > case BR_CODE_COMPONENT_ID: > - switch (be32_to_cpu(*(__be32 *)bootrec->data)) { > + priv->fw_interface = > + be32_to_cpu(*(__be32 *)bootrec->data); what about be32_to_cpup? Tomas ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] p54usb: support LM87 firmwares 2008-09-02 23:14 ` Tomas Winkler @ 2008-09-03 0:00 ` Christian Lamparter 2008-09-04 1:44 ` Pavel Roskin 0 siblings, 1 reply; 11+ messages in thread From: Christian Lamparter @ 2008-09-03 0:00 UTC (permalink / raw) To: Tomas Winkler; +Cc: linux-wireless, John W Linville, Larry Finger On Wednesday 03 September 2008 01:14:12 Tomas Winkler wrote: > > diff -Nurp a/drivers/net/wireless/p54/p54common.c > > b/drivers/net/wireless/p54/p54common.c --- > > a/drivers/net/wireless/p54/p54common.c 2008-09-01 22:25:35.000000000 > > +0200 +++ b/drivers/net/wireless/p54/p54common.c 2008-09-02 > > 21:29:47.000000000 +0200 @@ -93,7 +93,10 @@ int p54_parse_firmware(struct > > ieee80211_ > > u32 code = le32_to_cpu(bootrec->code); > > switch (code) { > > case BR_CODE_COMPONENT_ID: > > - switch (be32_to_cpu(*(__be32 *)bootrec->data)) { > > + priv->fw_interface = > > + be32_to_cpu(*(__be32 *)bootrec->data); > > what about be32_to_cpup? > Tomas whats the main difference between be32_to_cpu vs be32_to_cpus vs be32_to_cpup? Does the extra p just stand for something like "pointer"? hmm, if yes, >>*<<(__be32 *)bootrec->data. if no, please tell me more about it ;-). Regards, Chr ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] p54usb: support LM87 firmwares 2008-09-03 0:00 ` Christian Lamparter @ 2008-09-04 1:44 ` Pavel Roskin 2008-09-04 10:29 ` [PATCH v2] " Christian Lamparter 0 siblings, 1 reply; 11+ messages in thread From: Pavel Roskin @ 2008-09-04 1:44 UTC (permalink / raw) To: Christian Lamparter Cc: Tomas Winkler, linux-wireless, John W Linville, Larry Finger On Wed, 2008-09-03 at 02:00 +0200, Christian Lamparter wrote: > whats the main difference between be32_to_cpu vs be32_to_cpus vs be32_to_cpup? > Does the extra p just stand for something like "pointer"? Yes. See include/linux/byteorder/generic.h > > hmm, > if yes, >>*<<(__be32 *)bootrec->data. > if no, please tell me more about it ;-). The pointer versions take the pointer. They do the cast and the dereference for you. The cast in your code should be unnecessary. The in-situ version don't return anything; they put the result into the original variable. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2] p54usb: support LM87 firmwares 2008-09-04 1:44 ` Pavel Roskin @ 2008-09-04 10:29 ` Christian Lamparter 2008-09-06 22:57 ` Larry Finger 0 siblings, 1 reply; 11+ messages in thread From: Christian Lamparter @ 2008-09-04 10:29 UTC (permalink / raw) To: linux-wireless; +Cc: John W Linville, Pavel Roskin, Larry Finger, Tomas Winkler This patch adds the necessary changes to support LM87 firmwares. Signed-off-by: Christian Lamparter <chunkeey@web.de> --- as you can see, the *(__be32 *) cast is now gone ;-) --- diff -Nurp a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c --- a/drivers/net/wireless/p54/p54common.c 2008-09-01 22:25:35.000000000 +0200 +++ b/drivers/net/wireless/p54/p54common.c 2008-09-04 12:02:51.000000000 +0200 @@ -93,7 +93,8 @@ int p54_parse_firmware(struct ieee80211_ u32 code = le32_to_cpu(bootrec->code); switch (code) { case BR_CODE_COMPONENT_ID: - switch (be32_to_cpu(*(__be32 *)bootrec->data)) { + priv->fw_interface = be32_to_cpup(bootrec->data); + switch (priv->fw_interface) { case FW_FMAC: printk(KERN_INFO "p54: FreeMAC firmware\n"); break; @@ -104,7 +105,7 @@ int p54_parse_firmware(struct ieee80211_ printk(KERN_INFO "p54: LM86 firmware\n"); break; case FW_LM87: - printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n"); + printk(KERN_INFO "p54: LM87 firmware\n"); break; default: printk(KERN_INFO "p54: unknown firmware\n"); diff -Nurp a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h --- a/drivers/net/wireless/p54/p54common.h 2008-09-01 01:56:53.000000000 +0200 +++ b/drivers/net/wireless/p54/p54common.h 2008-09-02 19:39:10.000000000 +0200 @@ -50,11 +50,6 @@ struct bootrec_desc { #define BR_CODE_END_OF_BRA 0xFF0000FF #define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF -#define FW_FMAC 0x464d4143 -#define FW_LM86 0x4c4d3836 -#define FW_LM87 0x4c4d3837 -#define FW_LM20 0x4c4d3230 - /* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */ struct pda_entry { diff -Nurp a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h --- a/drivers/net/wireless/p54/p54.h 2008-09-01 02:20:25.000000000 +0200 +++ b/drivers/net/wireless/p54/p54.h 2008-09-02 19:39:26.000000000 +0200 @@ -42,6 +42,11 @@ struct p54_control_hdr { #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 +#define FW_FMAC 0x464d4143 +#define FW_LM86 0x4c4d3836 +#define FW_LM87 0x4c4d3837 +#define FW_LM20 0x4c4d3230 + struct p54_common { u32 rx_start; u32 rx_end; @@ -68,6 +73,7 @@ struct p54_common { unsigned int tx_hdr_len; void *cached_vdcf; unsigned int fw_var; + unsigned int fw_interface; struct ieee80211_tx_queue_stats tx_stats[8]; void *eeprom; struct completion eeprom_comp; diff -Nurp a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c --- a/drivers/net/wireless/p54/p54usb.c 2008-09-01 22:23:46.000000000 +0200 +++ b/drivers/net/wireless/p54/p54usb.c 2008-09-02 21:28:36.000000000 +0200 @@ -91,8 +91,13 @@ static void p54u_rx_cb(struct urb *urb) skb_unlink(skb, &priv->rx_queue); skb_put(skb, urb->actual_length); - if (!priv->hw_type) - skb_pull(skb, sizeof(struct net2280_tx_hdr)); + + if (priv->hw_type == P54U_NET2280) + skb_pull(skb, priv->common.tx_hdr_len); + if (priv->common.fw_interface == FW_LM87) { + skb_pull(skb, 4); + skb_put(skb, 4); + } if (p54_rx(dev, skb)) { skb = dev_alloc_skb(priv->common.rx_mtu + 32); @@ -109,9 +114,12 @@ static void p54u_rx_cb(struct urb *urb) urb->context = skb; skb_queue_tail(&priv->rx_queue, skb); } else { - if (!priv->hw_type) - skb_push(skb, sizeof(struct net2280_tx_hdr)); - + if (priv->hw_type == P54U_NET2280) + skb_push(skb, priv->common.tx_hdr_len); + if (priv->common.fw_interface == FW_LM87) { + skb_push(skb, 4); + skb_put(skb, 4); + } skb_reset_tail_pointer(skb); skb_trim(skb, 0); if (urb->transfer_buffer != skb_tail_pointer(skb)) { @@ -210,6 +218,42 @@ static void p54u_tx_3887(struct ieee8021 usb_submit_urb(data_urb, GFP_ATOMIC); } +__le32 p54u_lm87_chksum(const u32 *data, size_t length) +{ + __le32 chk = 0; + + length >>= 2; + while (length--) { + chk ^= cpu_to_le32(*data++); + chk = (chk >> 5) ^ (chk << 3); + } + + return chk; +} + +static void p54u_tx_lm87(struct ieee80211_hw *dev, + struct p54_control_hdr *data, + size_t len, int free_on_tx) +{ + struct p54u_priv *priv = dev->priv; + struct urb *data_urb; + struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr); + + data_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!data_urb) + return; + + hdr->chksum = p54u_lm87_chksum((u32 *)data, len); + hdr->device_addr = data->req_id; + + usb_fill_bulk_urb(data_urb, priv->udev, + usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, + len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, + dev); + + usb_submit_urb(data_urb, GFP_ATOMIC); +} + static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, size_t len, int free_on_tx) { @@ -776,21 +820,23 @@ static int __devinit p54u_probe(struct u } } priv->common.open = p54u_open; - + priv->common.stop = p54u_stop; if (recognized_pipes < P54U_PIPE_NUMBER) { priv->hw_type = P54U_3887; - priv->common.tx = p54u_tx_3887; + err = p54u_upload_firmware_3887(dev); + if (priv->common.fw_interface == FW_LM87) { + dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); + priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); + priv->common.tx = p54u_tx_lm87; + } else + priv->common.tx = p54u_tx_3887; } else { + priv->hw_type = P54U_NET2280; dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); priv->common.tx = p54u_tx_net2280; - } - priv->common.stop = p54u_stop; - - if (priv->hw_type) - err = p54u_upload_firmware_3887(dev); - else err = p54u_upload_firmware_net2280(dev); + } if (err) goto err_free_dev; diff -Nurp a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h --- a/drivers/net/wireless/p54/p54usb.h 2008-09-01 01:56:53.000000000 +0200 +++ b/drivers/net/wireless/p54/p54usb.h 2008-09-02 19:23:52.000000000 +0200 @@ -72,6 +72,11 @@ struct net2280_tx_hdr { u8 padding[8]; } __attribute__((packed)); +struct lm87_tx_hdr { + __le32 device_addr; + __le32 chksum; +} __attribute__((packed)); + /* Some flags for the isl hardware registers controlling DMA inside the * chip */ #define ISL38XX_DMA_STATUS_DONE 0x00000001 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] p54usb: support LM87 firmwares 2008-09-04 10:29 ` [PATCH v2] " Christian Lamparter @ 2008-09-06 22:57 ` Larry Finger 2008-09-06 23:19 ` Chr 0 siblings, 1 reply; 11+ messages in thread From: Larry Finger @ 2008-09-06 22:57 UTC (permalink / raw) To: Christian Lamparter Cc: linux-wireless, John W Linville, Pavel Roskin, Tomas Winkler Christian Lamparter wrote: > This patch adds the necessary changes to support LM87 firmwares. > Do you have a URL for the LM87 firmware? After this patch was added, I tried the 2.5.11.0.arm and 2.13.1.0.arm files, but only the old 2.5.8.0 works. That is the one with the 'ping -s 1400' problem. Larry ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] p54usb: support LM87 firmwares 2008-09-06 22:57 ` Larry Finger @ 2008-09-06 23:19 ` Chr 2008-09-06 23:33 ` Larry Finger 0 siblings, 1 reply; 11+ messages in thread From: Chr @ 2008-09-06 23:19 UTC (permalink / raw) To: Larry Finger; +Cc: linux-wireless, John W Linville, Pavel Roskin, Tomas Winkler On Sunday 07 September 2008 00:57:35 Larry Finger wrote: > Christian Lamparter wrote: > > This patch adds the necessary changes to support LM87 firmwares. > > Do you have a URL for the LM87 firmware? After this patch was added, I > tried the 2.5.11.0.arm and 2.13.1.0.arm files, but only the old > 2.5.8.0 works. That is the one with the 'ping -s 1400' problem. > Yes But, for newer firmwares you'll need "p54: better firmware support" (cc4b0cbf4ab) as well. This changes were merged about 25-26 hours ago into wireless-testing, the only thing that isn't in yet is 802.11a support.... the LM87 firmware is this one: http://daemonizer.de/prism54/prism54-fw/fw-usb/2.13.1.0.arm.1 This link can be found on the driver's site too: http://linuxwireless.org/en/users/Drivers/p54 Regards, Chr ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] p54usb: support LM87 firmwares 2008-09-06 23:19 ` Chr @ 2008-09-06 23:33 ` Larry Finger 2008-09-07 0:25 ` Chr 0 siblings, 1 reply; 11+ messages in thread From: Larry Finger @ 2008-09-06 23:33 UTC (permalink / raw) To: Chr; +Cc: linux-wireless, John W Linville, Pavel Roskin, Tomas Winkler Chr wrote: > But, for newer firmwares you'll need "p54: better firmware support" (cc4b0cbf4ab) > as well. This changes were merged about 25-26 hours ago into wireless-testing, > the only thing that isn't in yet is 802.11a support.... > > the LM87 firmware is this one: > http://daemonizer.de/prism54/prism54-fw/fw-usb/2.13.1.0.arm.1 > > This link can be found on the driver's site too: > http://linuxwireless.org/en/users/Drivers/p54 Thanks. That one fixed the ping problem. I had the latest wireless-testing, and have added the patches you posted earlier today. Thanks, Larry ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] p54usb: support LM87 firmwares 2008-09-06 23:33 ` Larry Finger @ 2008-09-07 0:25 ` Chr 2008-09-07 0:32 ` Larry Finger 0 siblings, 1 reply; 11+ messages in thread From: Chr @ 2008-09-07 0:25 UTC (permalink / raw) To: linux-wireless; +Cc: Larry Finger, John W Linville, Pavel Roskin, Tomas Winkler On Sunday 07 September 2008 01:33:29 Larry Finger wrote: > Chr wrote: > > But, for newer firmwares you'll need "p54: better firmware support" > > (cc4b0cbf4ab) as well. This changes were merged about 25-26 hours ago > > into wireless-testing, the only thing that isn't in yet is 802.11a > > support.... > > > > the LM87 firmware is this one: > > http://daemonizer.de/prism54/prism54-fw/fw-usb/2.13.1.0.arm.1 > > > > This link can be found on the driver's site too: > > http://linuxwireless.org/en/users/Drivers/p54 > > Thanks. That one fixed the ping problem. I had the latest > wireless-testing, and have added the patches you posted earlier today. > Well, since you already do some testing here. Want more? ;-) I will be off for about 4-5 weeks and it would be very nice if someone with lots of broadcom hardware can test if the p54 works ADHOC & AP mode with them. i've already (successfully) tested Intel's 2915 & 4965, several atheros chipsets and another prism54 on different operating systems. But there could be problems with some broadcom chips. Regards, Chr --- diff -Nurp a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c --- a/drivers/net/wireless/p54/p54common.c 2008-09-06 14:09:16.000000000 +0200 +++ b/drivers/net/wireless/p54/p54common.c 2008-09-07 02:04:31.000000000 +0200 @@ -589,10 +589,19 @@ static void p54_rx_frame_sent(struct iee else info->status.excessive_retries = 1; } + if (payload->status & 0x04) + info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + info->status.retry_count = payload->retries - 1; info->status.retry_count = payload->retries - 1; info->status.ack_signal = p54_rssi_to_dbm(dev, le16_to_cpu(payload->ack_rssi)); skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + struct ieee80211_hdr *ieee80211hdr = + (struct ieee80211_hdr *)entry->data; + ieee80211hdr->seq_ctrl |= + cpu_to_le16(payload->seq); + } ieee80211_tx_status_irqsafe(dev, entry); goto out; } else @@ -803,25 +812,130 @@ free: } EXPORT_SYMBOL_GPL(p54_read_eeprom); +static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr) +{ + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr; + struct p54_tx_control_sta_unlock *sta; + + if (is_multicast_ether_addr(addr)) + return 0; + + hdr = kmalloc(sizeof(*hdr) + sizeof(*sta) + + priv->tx_hdr_len, GFP_ATOMIC); + if (!hdr) + return -ENOMEM; + + hdr = (void *)hdr + priv->tx_hdr_len; + hdr->magic1 = cpu_to_le16(0x8001); + hdr->len = cpu_to_le16(sizeof(*sta)); + hdr->type = cpu_to_le16(P54_CONTROL_TYPE_PSM_STA_UNLOCK); + p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*sta)); + + sta = (struct p54_tx_control_sta_unlock *) hdr->data; + memcpy(sta->addr, addr, ETH_ALEN); + + priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*sta), 1); + + return 0; +} + +static int p54_set_tim(struct ieee80211_hw *dev, int aid, int set) +{ + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr; + struct p54_tx_control_tim *tim; + + hdr = kmalloc(sizeof(*hdr) + sizeof(*tim) + + priv->tx_hdr_len, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + hdr = (void *)hdr + priv->tx_hdr_len; + hdr->magic1 = cpu_to_le16(0x8001); + hdr->len = cpu_to_le16(sizeof(*tim)); + hdr->type = cpu_to_le16(P54_CONTROL_TYPE_TIM); + p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*tim)); + + tim = (struct p54_tx_control_tim *) hdr->data; + tim->count = 1; + tim->entry[0] = cpu_to_le16(set ? (aid | 0x8000) : aid); + + priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*tim), 1); + + return 0; +} + +static int p54_tx_fill_header(struct ieee80211_hw *dev, + struct ieee80211_hdr *hdr, struct ieee80211_tx_info *info, + u8 *queue, u16 *flags, u16 *aid) +{ + struct p54_common *priv = dev->priv; + u16 fc = le16_to_cpu(hdr->frame_control); + int ret = 1; + + if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_PROBE_RESP: + *aid = 0; + *queue = 2; + *flags = 0x22; + return 0; + case IEEE80211_STYPE_BEACON: + *aid = 0; + *queue = 0; + *flags = 0x02; + return 0; + default: + *queue = 2; + ret = 0; + } + else + *queue += 4; + + if (is_multicast_ether_addr(hdr->addr1)) { + *queue = 3; + *aid = 0; + return 0; + } + + if (priv->mode != IEEE80211_IF_TYPE_STA) { + *aid = info->control.aid; + if (!info->control.aid) + *flags = 0x20; + } else + *aid = 1; + + return ret; +} + static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_queue_stats *current_queue; + struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; struct p54_common *priv = dev->priv; struct p54_control_hdr *hdr; - struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; struct p54_tx_control_allocdata *txhdr; size_t padding, len; - u8 rate; - u8 cts_rate = 0x20; + u16 aid, hdr_flags = 0x0000; + u8 queue, rate, cts_rate = 0x20; + + queue = skb_get_queue_mapping(skb); - current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; - if (unlikely(current_queue->len > current_queue->limit)) - return NETDEV_TX_BUSY; - current_queue->len++; - current_queue->count++; - if (current_queue->len == current_queue->limit) - ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); + if (likely(p54_tx_fill_header(dev, ieee80211hdr, info, + &queue, &hdr_flags, &aid))) { + current_queue = &priv->tx_stats[queue]; + if (unlikely(current_queue->len > current_queue->limit)) + return NETDEV_TX_BUSY; + current_queue->len++; + current_queue->count++; + if (current_queue->len == current_queue->limit) + ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); + } + + if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) + p54_sta_unlock(dev, ieee80211hdr->addr1); padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; len = skb->len; @@ -831,13 +945,12 @@ static int p54_tx(struct ieee80211_hw *d hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr)); if (padding) - hdr->magic1 = cpu_to_le16(0x4010); - else - hdr->magic1 = cpu_to_le16(0x0010); + hdr_flags = 0x4000; + + hdr->magic1 = cpu_to_le16(hdr_flags); hdr->len = cpu_to_le16(len); - hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); + hdr->type = cpu_to_le16(aid); hdr->retry1 = hdr->retry2 = info->control.retry_limit; - /* TODO: add support for alternate retry TX rates */ rate = ieee80211_get_tx_rate(dev, info)->hw_value; if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) { @@ -854,7 +967,7 @@ static int p54_tx(struct ieee80211_hw *d memset(txhdr->rateset, rate, 8); txhdr->key_type = 0; txhdr->key_len = 0; - txhdr->hw_queue = skb_get_queue_mapping(skb) + 4; + txhdr->hw_queue = queue; txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? 2 : info->antenna_sel_tx - 1; txhdr->output_power = priv->output_power; @@ -870,17 +983,12 @@ static int p54_tx(struct ieee80211_hw *d * patch places the sequence number in the hardware state, which * limits us to a single virtual state. */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - priv->seqno += 0x10; - ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno); - } /* modifies skb->cb and with it info, so must be last! */ p54_assign_address(dev, skb, hdr, skb->len); priv->tx(dev, hdr, skb->len, 0); return 0; + } static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type, @@ -1170,6 +1278,9 @@ static int p54_add_interface(struct ieee switch (conf->type) { case IEEE80211_IF_TYPE_STA: + case IEEE80211_IF_TYPE_AP: + case IEEE80211_IF_TYPE_MNTR: + case IEEE80211_IF_TYPE_IBSS: priv->mode = conf->type; break; default: @@ -1184,6 +1295,15 @@ static int p54_add_interface(struct ieee case IEEE80211_IF_TYPE_STA: p54_set_filter(dev, 1, NULL); break; + case IEEE80211_IF_TYPE_IBSS: + p54_set_filter(dev, 0x02, NULL); + break; + case IEEE80211_IF_TYPE_MNTR: + p54_set_filter(dev, 0x10, NULL); + break; + case IEEE80211_IF_TYPE_AP: + p54_set_filter(dev, 0x04, NULL); + break; default: BUG(); /* impossible */ break; @@ -1211,25 +1331,114 @@ static int p54_config(struct ieee80211_h mutex_lock(&priv->conf_mutex); priv->rx_antenna = (conf->antenna_sel_rx == 0) ? 2 : conf->antenna_sel_tx - 1; - priv->output_power = conf->power_level << 2; + priv->output_power = (conf->power_level << 2) & ~0x80; ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); p54_set_vdcf(dev); mutex_unlock(&priv->conf_mutex); return ret; } +static void p54_beacon_tim(struct sk_buff *skb) +{ + /* + * the good excuse for this mess is ... the firmware. + * The dummy TIM MUST be at the end of the beacon frame, + * because it'll be overwritten! + */ + + struct ieee80211_mgmt *mgmt = (void *)skb->data; + u8 *pos, *end; + + if (skb->len <= sizeof(mgmt)) + return ; + + pos = (u8 *)mgmt->u.beacon.variable; + end = skb->data + skb->len; + while (pos < end) { + if (pos + 2 + pos[1] > end) { + printk(KERN_ERR "p54: parsing beacon failed\n"); + return; + } + + if (pos[0] == WLAN_EID_TIM) { + u8 dtim_len = pos[1]; + u8 *next = pos + 2 + dtim_len; + + memmove(pos, next, end - next); + + if (dtim_len > 3) + skb_trim(skb, skb->len - (dtim_len - 3)); + if (dtim_len < 3) + skb_put(skb, skb->len + (3 - dtim_len)); + + pos = end - (dtim_len + 2); + + /* add the dummy at the end */ + pos[0] = WLAN_EID_TIM; + pos[1] = 3; + pos[2] = 0; + pos[3] = 1; /* FIX MAC80211: get the real dtim period + from the bss struct... */ + pos[4] = 0; + return ; + } + pos += 2 + pos[1]; + } +} + +static int p54_beacon_update(struct ieee80211_hw *dev, + struct ieee80211_vif *vif) +{ + struct p54_common *priv = dev->priv; + struct sk_buff *beacon = ieee80211_beacon_get(dev, vif); + + if (!beacon) + return -ENOMEM; + + p54_beacon_tim(beacon); + p54_tx(dev, beacon); + priv->tsf_high32 = 0; + priv->tsf_low32 = 0; + + return 0; +} + static int p54_config_interface(struct ieee80211_hw *dev, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) { struct p54_common *priv = dev->priv; + int ret = 0; - mutex_lock(&priv->conf_mutex); - p54_set_filter(dev, 0, conf->bssid); - p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - mutex_unlock(&priv->conf_mutex); - return 0; + switch (priv->mode) { + case IEEE80211_IF_TYPE_STA: + mutex_lock(&priv->conf_mutex); + memcpy(priv->bssid, conf->bssid, ETH_ALEN); + p54_set_filter(dev, 0x1, conf->bssid); + p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); + mutex_unlock(&priv->conf_mutex); + break; + case IEEE80211_IF_TYPE_AP: + case IEEE80211_IF_TYPE_IBSS: + mutex_lock(&priv->conf_mutex); + memcpy(priv->bssid, conf->bssid, ETH_ALEN); + p54_set_freq(dev, dev->conf.channel->center_freq); + p54_set_filter(dev, priv->filter_type, priv->bssid); + mutex_unlock(&priv->conf_mutex); + + if (conf->changed & IEEE80211_IFCC_BEACON) { + ret = p54_beacon_update(dev, vif); + if (ret) + return ret; + + mutex_lock(&priv->conf_mutex); + p54_set_vdcf(dev); + mutex_unlock(&priv->conf_mutex); + } + break; + } + + return ret; } static void p54_configure_filter(struct ieee80211_hw *dev, @@ -1366,6 +1575,7 @@ static const struct ieee80211_ops p54_op .config_interface = p54_config_interface, .configure_filter = p54_configure_filter, .conf_tx = p54_conf_tx, + .set_tim = p54_set_tim, .get_stats = p54_get_stats, .get_tx_stats = p54_get_tx_stats }; diff -Nurp a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h --- a/drivers/net/wireless/p54/p54common.h 2008-09-06 13:57:06.000000000 +0200 +++ b/drivers/net/wireless/p54/p54common.h 2008-09-07 01:55:21.000000000 +0200 @@ -321,4 +321,15 @@ struct p54_tx_control_xbow_synth { u32 padding[5]; } __attribute__ ((packed)); +struct p54_tx_control_sta_unlock { + u8 addr[ETH_ALEN]; + u16 padding; +} __attribute__ ((packed)); + +struct p54_tx_control_tim { + u8 count; + u8 unalloc0[3]; + __le16 entry[8]; +} __attribute__ ((packed)); + #endif /* P54COMMON_H */ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] p54usb: support LM87 firmwares 2008-09-07 0:25 ` Chr @ 2008-09-07 0:32 ` Larry Finger 2008-09-07 0:56 ` Christian Lamparter 0 siblings, 1 reply; 11+ messages in thread From: Larry Finger @ 2008-09-07 0:32 UTC (permalink / raw) To: Chr; +Cc: linux-wireless, John W Linville, Pavel Roskin, Tomas Winkler Chr wrote: > On Sunday 07 September 2008 01:33:29 Larry Finger wrote: >> Chr wrote: >>> But, for newer firmwares you'll need "p54: better firmware support" >>> (cc4b0cbf4ab) as well. This changes were merged about 25-26 hours ago >>> into wireless-testing, the only thing that isn't in yet is 802.11a >>> support.... >>> >>> the LM87 firmware is this one: >>> http://daemonizer.de/prism54/prism54-fw/fw-usb/2.13.1.0.arm.1 >>> >>> This link can be found on the driver's site too: >>> http://linuxwireless.org/en/users/Drivers/p54 >> Thanks. That one fixed the ping problem. I had the latest >> wireless-testing, and have added the patches you posted earlier today. >> > Well, since you already do some testing here. Want more? ;-) > > I will be off for about 4-5 weeks and it would be very nice if someone with lots of broadcom > hardware can test if the p54 works ADHOC & AP mode with them. > > i've already (successfully) tested Intel's 2915 & 4965, several atheros chipsets and another prism54 > on different operating systems. > > But there could be problems with some broadcom chips. I'll see what I can do. After loading the new firmware, p54usb crapped out after the following message was logged: phy9: not handling 0x02 type control frame After this, I had to unload and reload the driver. I have not yet had time to check on it. Larry ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] p54usb: support LM87 firmwares 2008-09-07 0:32 ` Larry Finger @ 2008-09-07 0:56 ` Christian Lamparter 0 siblings, 0 replies; 11+ messages in thread From: Christian Lamparter @ 2008-09-07 0:56 UTC (permalink / raw) To: Larry Finger; +Cc: linux-wireless, John W Linville, Pavel Roskin, Tomas Winkler [-- Attachment #1: Type: text/plain, Size: 1903 bytes --] On Sunday 07 September 2008 02:32:56 Larry Finger wrote: > Chr wrote: > > On Sunday 07 September 2008 01:33:29 Larry Finger wrote: > >> Chr wrote: > >>> But, for newer firmwares you'll need "p54: better firmware support" > >>> (cc4b0cbf4ab) as well. This changes were merged about 25-26 hours ago > >>> into wireless-testing, the only thing that isn't in yet is 802.11a > >>> support.... > >>> > >>> the LM87 firmware is this one: > >>> http://daemonizer.de/prism54/prism54-fw/fw-usb/2.13.1.0.arm.1 > >>> > >>> This link can be found on the driver's site too: > >>> http://linuxwireless.org/en/users/Drivers/p54 > >> > >> Thanks. That one fixed the ping problem. I had the latest > >> wireless-testing, and have added the patches you posted earlier today. > > > > Well, since you already do some testing here. Want more? ;-) > > > > I will be off for about 4-5 weeks and it would be very nice if someone > > with lots of broadcom hardware can test if the p54 works ADHOC & AP mode > > with them. > > > > i've already (successfully) tested Intel's 2915 & 4965, several atheros > > chipsets and another prism54 on different operating systems. > > > > But there could be problems with some broadcom chips. > > I'll see what I can do. > > After loading the new firmware, p54usb crapped out after the following > message was logged: > > phy9: not handling 0x02 type control frame > > After this, I had to unload and reload the driver. I have not yet had > time to check on it. > Do you have a big-endian machine by accident? Anyway control flags with 0x02 is some sort of scanning trap... These packages can be produces easily by setting chan->flags = 2 (or 4,6?) and setting the dwell timers as well in p54_set_freq. Since we don't do this, is there any chance you can hexdump the unknown/corrupted frames? and as a last shot: try another firmware, maybe this one works better for you. Regards, Chr [-- Attachment #2: 2.13.3.lm87.arm --] [-- Type: application/octet-stream, Size: 29092 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-09-07 0:53 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-09-02 19:39 [PATCH] p54usb: support LM87 firmwares Christian Lamparter 2008-09-02 23:14 ` Tomas Winkler 2008-09-03 0:00 ` Christian Lamparter 2008-09-04 1:44 ` Pavel Roskin 2008-09-04 10:29 ` [PATCH v2] " Christian Lamparter 2008-09-06 22:57 ` Larry Finger 2008-09-06 23:19 ` Chr 2008-09-06 23:33 ` Larry Finger 2008-09-07 0:25 ` Chr 2008-09-07 0:32 ` Larry Finger 2008-09-07 0:56 ` Christian Lamparter
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).