prism2_rx (hostap_hw.c) patch
Lubomir Gelo
lgelo
Tue Jun 17 02:47:12 PDT 2003
Hostap 0.0.3 introduced bug in prism2_rx (hostap_hw.c) in calculating
size for dev_alloc_skb. Driver hangs in monitor mode if frame of
certain length is received. Verified with gcc-2.95 and gcc-3.3 and
secondary FW 1.4.9 and 1.5.6.
Simple cast to u16 should help, but patch for cleaner (IMHO)
implementation follows.
LG
-------------- next part --------------
--- hostap_hw.c.orig 2003-05-23 04:40:58.000000000 +0200
+++ hostap_hw.c 2003-06-17 11:20:25.000000000 +0200
@@ -2129,7 +2129,7 @@
{
struct net_device *dev = local->dev;
int res, rx_pending = 0;
- u16 len, alloc_len, rxfid, status, macport;
+ u16 data_len, hdr_len, rxfid, status, macport;
struct net_device_stats *stats;
struct hfa384x_rx_frame rxdesc;
struct sk_buff *skb = NULL;
@@ -2163,7 +2163,8 @@
goto rx_dropped;
}
- len = le16_to_cpu(rxdesc.data_len);
+ data_len = le16_to_cpu(rxdesc.data_len);
+ hdr_len = sizeof(rxdesc);
status = le16_to_cpu(rxdesc.status);
macport = (status >> 8) & 0x07;
@@ -2171,17 +2172,20 @@
* seems to sometimes pass frames (e.g., ctrl::ack) with signed and
* negative value, so allow also values 65522 .. 65534 (-14 .. -2) for
* macport 7 */
- if ((len & 0x8000) &&
- (macport != 7 || ((len < (u16) -14) && len != 0xffff))) {
+ if (data_len > 2312){
+ if (macport == 7 && (data_len >= (u16) -14) && data_len != 0xffff ) {
+ data_len = 0;
+ hdr_len = data_len+(u16)sizeof(rxdesc);
+ } else {
spin_unlock(&local->baplock);
printk(KERN_DEBUG "%s: Received frame with invalid length "
- "0x%04x\n", dev->name, len);
+ "0x%04x\n", dev->name, data_len);
hostap_dump_rx_header(dev->name, &rxdesc);
goto rx_dropped;
+ }
}
- alloc_len = len + sizeof(rxdesc);
- skb = dev_alloc_skb(alloc_len);
+ skb = dev_alloc_skb(hdr_len+data_len);
if (!skb) {
spin_unlock(&local->baplock);
printk(KERN_DEBUG "%s: RX failed to allocate skb\n",
@@ -2189,11 +2193,10 @@
goto rx_dropped;
}
skb->dev = dev;
- memcpy(skb_put(skb, sizeof(rxdesc)), &rxdesc,
- alloc_len < sizeof(rxdesc) ? alloc_len : sizeof(rxdesc));
+ memcpy(skb_put(skb, hdr_len), &rxdesc, hdr_len);
#if defined(PRISM2_PCI) && defined(PRISM2_BUS_MASTER)
- if (!(len & 0x8000) && len >= local->bus_master_threshold_rx) {
+ if (data_len && data_len >= local->bus_master_threshold_rx) {
unsigned long addr;
hfa384x_events_no_bap1(dev);
@@ -2201,13 +2204,13 @@
local->rx_skb = skb;
/* Internal BAP0 offset points to the byte following rxdesc;
* copy rest of the data using bus master */
- addr = virt_to_phys(skb_put(skb, len));
+ addr = virt_to_phys(skb_put(skb, data_len));
HFA384X_OUTW((addr & 0xffff0000) >> 16,
HFA384X_PCI_M0_ADDRH_OFF);
HFA384X_OUTW(addr & 0x0000ffff, HFA384X_PCI_M0_ADDRL_OFF);
- if (len & 1)
- len++;
- HFA384X_OUTW(len / 2, HFA384X_PCI_M0_LEN_OFF);
+ if (data_len & 1)
+ data_len++;
+ HFA384X_OUTW(data_len / 2, HFA384X_PCI_M0_LEN_OFF);
HFA384X_OUTW(HFA384X_PCI_CTL_FROM_BAP, HFA384X_PCI_M0_CTL_OFF);
/* pci_bus_m1 event will be generated when data transfer is
@@ -2222,9 +2225,8 @@
} else
#endif /* PRISM2_PCI and PRISM2_BUS_MASTER */
{
- if (!(len & 0x8000))
- res = hfa384x_from_bap(dev, BAP0, skb_put(skb, len),
- len);
+ if (data_len)
+ res = hfa384x_from_bap(dev, BAP0, skb_put(skb, data_len), data_len);
spin_unlock(&local->baplock);
if (res) {
printk(KERN_DEBUG "%s: RX failed to read "
More information about the Hostap
mailing list