diff options
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 92 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 16 | ||||
-rw-r--r-- | drivers/net/wireless/hostap/hostap_ioctl.c | 4 | ||||
-rw-r--r-- | include/net/ieee80211softmac.h | 5 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_assoc.c | 20 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_module.c | 2 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_wx.c | 27 |
9 files changed, 133 insertions, 49 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 4e1e8175eb6d..d6a8e5b434ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -421,6 +421,14 @@ L: linux-hams@vger.kernel.org | |||
421 | W: http://www.baycom.org/~tom/ham/ham.html | 421 | W: http://www.baycom.org/~tom/ham/ham.html |
422 | S: Maintained | 422 | S: Maintained |
423 | 423 | ||
424 | BCM43XX WIRELESS DRIVER | ||
425 | P: Michael Buesch | ||
426 | M: mb@bu3sch.de | ||
427 | P: Stefano Brivio | ||
428 | M: st3@riseup.net | ||
429 | W: http://bcm43xx.berlios.de/ | ||
430 | S: Maintained | ||
431 | |||
424 | BEFS FILE SYSTEM | 432 | BEFS FILE SYSTEM |
425 | P: Sergey S. Kostyliov | 433 | P: Sergey S. Kostyliov |
426 | M: rathamahata@php4.ru | 434 | M: rathamahata@php4.ru |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 2d520e4b0276..b7d77638ba8c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h | |||
@@ -213,6 +213,14 @@ static inline | |||
213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) | 213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) |
214 | { | 214 | { |
215 | } | 215 | } |
216 | static inline | ||
217 | void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) | ||
218 | { | ||
219 | } | ||
220 | static inline | ||
221 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) | ||
222 | { | ||
223 | } | ||
216 | 224 | ||
217 | #endif /* CONFIG_BCM43XX_DMA */ | 225 | #endif /* CONFIG_BCM43XX_DMA */ |
218 | #endif /* BCM43xx_DMA_H_ */ | 226 | #endif /* BCM43xx_DMA_H_ */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index c59ddd40680d..0aa1bd269a25 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "bcm43xx_pio.h" | 27 | #include "bcm43xx_pio.h" |
28 | #include "bcm43xx_main.h" | 28 | #include "bcm43xx_main.h" |
29 | #include "bcm43xx_xmit.h" | 29 | #include "bcm43xx_xmit.h" |
30 | #include "bcm43xx_power.h" | ||
30 | 31 | ||
31 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
32 | 33 | ||
@@ -44,10 +45,10 @@ static void tx_octet(struct bcm43xx_pioqueue *queue, | |||
44 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 45 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
45 | octet); | 46 | octet); |
46 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 47 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
47 | BCM43xx_PIO_TXCTL_WRITEHI); | 48 | BCM43xx_PIO_TXCTL_WRITELO); |
48 | } else { | 49 | } else { |
49 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 50 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
50 | BCM43xx_PIO_TXCTL_WRITEHI); | 51 | BCM43xx_PIO_TXCTL_WRITELO); |
51 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 52 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
52 | octet); | 53 | octet); |
53 | } | 54 | } |
@@ -103,7 +104,7 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
103 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 104 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
104 | skb->data[skb->len - 1]); | 105 | skb->data[skb->len - 1]); |
105 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 106 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
106 | BCM43xx_PIO_TXCTL_WRITEHI | | 107 | BCM43xx_PIO_TXCTL_WRITELO | |
107 | BCM43xx_PIO_TXCTL_COMPLETE); | 108 | BCM43xx_PIO_TXCTL_COMPLETE); |
108 | } else { | 109 | } else { |
109 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 110 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
@@ -112,9 +113,10 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
112 | } | 113 | } |
113 | 114 | ||
114 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | 115 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, |
115 | int packetindex) | 116 | struct bcm43xx_pio_txpacket *packet) |
116 | { | 117 | { |
117 | u16 cookie = 0x0000; | 118 | u16 cookie = 0x0000; |
119 | int packetindex; | ||
118 | 120 | ||
119 | /* We use the upper 4 bits for the PIO | 121 | /* We use the upper 4 bits for the PIO |
120 | * controller ID and the lower 12 bits | 122 | * controller ID and the lower 12 bits |
@@ -135,6 +137,7 @@ static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | |||
135 | default: | 137 | default: |
136 | assert(0); | 138 | assert(0); |
137 | } | 139 | } |
140 | packetindex = pio_txpacket_getindex(packet); | ||
138 | assert(((u16)packetindex & 0xF000) == 0x0000); | 141 | assert(((u16)packetindex & 0xF000) == 0x0000); |
139 | cookie |= (u16)packetindex; | 142 | cookie |= (u16)packetindex; |
140 | 143 | ||
@@ -184,7 +187,7 @@ static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, | |||
184 | bcm43xx_generate_txhdr(queue->bcm, | 187 | bcm43xx_generate_txhdr(queue->bcm, |
185 | &txhdr, skb->data, skb->len, | 188 | &txhdr, skb->data, skb->len, |
186 | (packet->xmitted_frags == 0), | 189 | (packet->xmitted_frags == 0), |
187 | generate_cookie(queue, pio_txpacket_getindex(packet))); | 190 | generate_cookie(queue, packet)); |
188 | 191 | ||
189 | tx_start(queue); | 192 | tx_start(queue); |
190 | octets = skb->len + sizeof(txhdr); | 193 | octets = skb->len + sizeof(txhdr); |
@@ -241,7 +244,7 @@ static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) | |||
241 | queue->tx_devq_packets++; | 244 | queue->tx_devq_packets++; |
242 | queue->tx_devq_used += octets; | 245 | queue->tx_devq_used += octets; |
243 | 246 | ||
244 | assert(packet->xmitted_frags <= packet->txb->nr_frags); | 247 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
245 | packet->xmitted_frags++; | 248 | packet->xmitted_frags++; |
246 | packet->xmitted_octets += octets; | 249 | packet->xmitted_octets += octets; |
247 | } | 250 | } |
@@ -257,8 +260,14 @@ static void tx_tasklet(unsigned long d) | |||
257 | unsigned long flags; | 260 | unsigned long flags; |
258 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; | 261 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; |
259 | int err; | 262 | int err; |
263 | u16 txctl; | ||
260 | 264 | ||
261 | bcm43xx_lock_mmio(bcm, flags); | 265 | bcm43xx_lock_mmio(bcm, flags); |
266 | |||
267 | txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
268 | if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) | ||
269 | goto out_unlock; | ||
270 | |||
262 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { | 271 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { |
263 | assert(packet->xmitted_frags < packet->txb->nr_frags); | 272 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
264 | if (packet->xmitted_frags == 0) { | 273 | if (packet->xmitted_frags == 0) { |
@@ -288,6 +297,7 @@ static void tx_tasklet(unsigned long d) | |||
288 | next_packet: | 297 | next_packet: |
289 | continue; | 298 | continue; |
290 | } | 299 | } |
300 | out_unlock: | ||
291 | bcm43xx_unlock_mmio(bcm, flags); | 301 | bcm43xx_unlock_mmio(bcm, flags); |
292 | } | 302 | } |
293 | 303 | ||
@@ -330,12 +340,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, | |||
330 | (unsigned long)queue); | 340 | (unsigned long)queue); |
331 | 341 | ||
332 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); | 342 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); |
333 | value |= BCM43xx_SBF_XFER_REG_BYTESWAP; | 343 | value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP; |
334 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); | 344 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); |
335 | 345 | ||
336 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); | 346 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); |
347 | if (qsize == 0) { | ||
348 | printk(KERN_ERR PFX "ERROR: This card does not support PIO " | ||
349 | "operation mode. Please use DMA mode " | ||
350 | "(module parameter pio=0).\n"); | ||
351 | goto err_freequeue; | ||
352 | } | ||
337 | if (qsize <= BCM43xx_PIO_TXQADJUST) { | 353 | if (qsize <= BCM43xx_PIO_TXQADJUST) { |
338 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize); | 354 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", |
355 | qsize); | ||
339 | goto err_freequeue; | 356 | goto err_freequeue; |
340 | } | 357 | } |
341 | qsize -= BCM43xx_PIO_TXQADJUST; | 358 | qsize -= BCM43xx_PIO_TXQADJUST; |
@@ -444,15 +461,10 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
444 | { | 461 | { |
445 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; | 462 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; |
446 | struct bcm43xx_pio_txpacket *packet; | 463 | struct bcm43xx_pio_txpacket *packet; |
447 | u16 tmp; | ||
448 | 464 | ||
449 | assert(!queue->tx_suspended); | 465 | assert(!queue->tx_suspended); |
450 | assert(!list_empty(&queue->txfree)); | 466 | assert(!list_empty(&queue->txfree)); |
451 | 467 | ||
452 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
453 | if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) | ||
454 | return -EBUSY; | ||
455 | |||
456 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); | 468 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); |
457 | packet->txb = txb; | 469 | packet->txb = txb; |
458 | packet->xmitted_frags = 0; | 470 | packet->xmitted_frags = 0; |
@@ -462,7 +474,7 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
462 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); | 474 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); |
463 | 475 | ||
464 | /* Suspend TX, if we are out of packets in the "free" queue. */ | 476 | /* Suspend TX, if we are out of packets in the "free" queue. */ |
465 | if (unlikely(list_empty(&queue->txfree))) { | 477 | if (list_empty(&queue->txfree)) { |
466 | netif_stop_queue(queue->bcm->net_dev); | 478 | netif_stop_queue(queue->bcm->net_dev); |
467 | queue->tx_suspended = 1; | 479 | queue->tx_suspended = 1; |
468 | } | 480 | } |
@@ -480,15 +492,15 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
480 | 492 | ||
481 | queue = parse_cookie(bcm, status->cookie, &packet); | 493 | queue = parse_cookie(bcm, status->cookie, &packet); |
482 | assert(queue); | 494 | assert(queue); |
483 | //TODO | 495 | |
484 | if (!queue) | ||
485 | return; | ||
486 | free_txpacket(packet, 1); | 496 | free_txpacket(packet, 1); |
487 | if (unlikely(queue->tx_suspended)) { | 497 | if (queue->tx_suspended) { |
488 | queue->tx_suspended = 0; | 498 | queue->tx_suspended = 0; |
489 | netif_wake_queue(queue->bcm->net_dev); | 499 | netif_wake_queue(queue->bcm->net_dev); |
490 | } | 500 | } |
491 | /* If there are packets on the txqueue, poke the tasklet. */ | 501 | /* If there are packets on the txqueue, poke the tasklet |
502 | * to transmit them. | ||
503 | */ | ||
492 | if (!list_empty(&queue->txqueue)) | 504 | if (!list_empty(&queue->txqueue)) |
493 | tasklet_schedule(&queue->txtask); | 505 | tasklet_schedule(&queue->txtask); |
494 | } | 506 | } |
@@ -519,12 +531,9 @@ void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | |||
519 | int i, preamble_readwords; | 531 | int i, preamble_readwords; |
520 | struct sk_buff *skb; | 532 | struct sk_buff *skb; |
521 | 533 | ||
522 | return; | ||
523 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); | 534 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); |
524 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { | 535 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) |
525 | dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk. | ||
526 | return; | 536 | return; |
527 | } | ||
528 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, | 537 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, |
529 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); | 538 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); |
530 | 539 | ||
@@ -538,8 +547,7 @@ return; | |||
538 | return; | 547 | return; |
539 | data_ready: | 548 | data_ready: |
540 | 549 | ||
541 | //FIXME: endianess in this function. | 550 | len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
542 | len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | ||
543 | if (unlikely(len > 0x700)) { | 551 | if (unlikely(len > 0x700)) { |
544 | pio_rx_error(queue, 0, "len > 0x700"); | 552 | pio_rx_error(queue, 0, "len > 0x700"); |
545 | return; | 553 | return; |
@@ -555,7 +563,7 @@ data_ready: | |||
555 | preamble_readwords = 18 / sizeof(u16); | 563 | preamble_readwords = 18 / sizeof(u16); |
556 | for (i = 0; i < preamble_readwords; i++) { | 564 | for (i = 0; i < preamble_readwords; i++) { |
557 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 565 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
558 | preamble[i + 1] = cpu_to_be16(tmp);//FIXME? | 566 | preamble[i + 1] = cpu_to_le16(tmp); |
559 | } | 567 | } |
560 | rxhdr = (struct bcm43xx_rxhdr *)preamble; | 568 | rxhdr = (struct bcm43xx_rxhdr *)preamble; |
561 | rxflags2 = le16_to_cpu(rxhdr->flags2); | 569 | rxflags2 = le16_to_cpu(rxhdr->flags2); |
@@ -591,16 +599,40 @@ data_ready: | |||
591 | } | 599 | } |
592 | skb_put(skb, len); | 600 | skb_put(skb, len); |
593 | for (i = 0; i < len - 1; i += 2) { | 601 | for (i = 0; i < len - 1; i += 2) { |
594 | tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | 602 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
595 | *((u16 *)(skb->data + i)) = tmp; | 603 | *((u16 *)(skb->data + i)) = cpu_to_le16(tmp); |
596 | } | 604 | } |
597 | if (len % 2) { | 605 | if (len % 2) { |
598 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 606 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
599 | skb->data[len - 1] = (tmp & 0x00FF); | 607 | skb->data[len - 1] = (tmp & 0x00FF); |
608 | /* The specs say the following is required, but | ||
609 | * it is wrong and corrupts the PLCP. If we don't do | ||
610 | * this, the PLCP seems to be correct. So ifdef it out for now. | ||
611 | */ | ||
612 | #if 0 | ||
600 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) | 613 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) |
601 | skb->data[0x20] = (tmp & 0xFF00) >> 8; | 614 | skb->data[2] = (tmp & 0xFF00) >> 8; |
602 | else | 615 | else |
603 | skb->data[0x1E] = (tmp & 0xFF00) >> 8; | 616 | skb->data[0] = (tmp & 0xFF00) >> 8; |
617 | #endif | ||
604 | } | 618 | } |
619 | skb_trim(skb, len - IEEE80211_FCS_LEN); | ||
605 | bcm43xx_rx(queue->bcm, skb, rxhdr); | 620 | bcm43xx_rx(queue->bcm, skb, rxhdr); |
606 | } | 621 | } |
622 | |||
623 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
624 | { | ||
625 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1); | ||
626 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
627 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
628 | | BCM43xx_PIO_TXCTL_SUSPEND); | ||
629 | } | ||
630 | |||
631 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
632 | { | ||
633 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
634 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
635 | & ~BCM43xx_PIO_TXCTL_SUSPEND); | ||
636 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); | ||
637 | tasklet_schedule(&queue->txtask); | ||
638 | } | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index 970627bc1769..dfc78209e3a3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h | |||
@@ -14,8 +14,8 @@ | |||
14 | #define BCM43xx_PIO_RXCTL 0x08 | 14 | #define BCM43xx_PIO_RXCTL 0x08 |
15 | #define BCM43xx_PIO_RXDATA 0x0A | 15 | #define BCM43xx_PIO_RXDATA 0x0A |
16 | 16 | ||
17 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0) | 17 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 0) |
18 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 1) | 18 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1) |
19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) | 19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) |
20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) | 20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) |
21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) | 21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) |
@@ -95,6 +95,7 @@ void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, | |||
95 | u16 offset, u16 value) | 95 | u16 offset, u16 value) |
96 | { | 96 | { |
97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); | 97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); |
98 | mmiowb(); | ||
98 | } | 99 | } |
99 | 100 | ||
100 | 101 | ||
@@ -107,6 +108,9 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
107 | struct bcm43xx_xmitstatus *status); | 108 | struct bcm43xx_xmitstatus *status); |
108 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); | 109 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); |
109 | 110 | ||
111 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); | ||
112 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); | ||
113 | |||
110 | #else /* CONFIG_BCM43XX_PIO */ | 114 | #else /* CONFIG_BCM43XX_PIO */ |
111 | 115 | ||
112 | static inline | 116 | static inline |
@@ -133,6 +137,14 @@ static inline | |||
133 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | 137 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) |
134 | { | 138 | { |
135 | } | 139 | } |
140 | static inline | ||
141 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
142 | { | ||
143 | } | ||
144 | static inline | ||
145 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
146 | { | ||
147 | } | ||
136 | 148 | ||
137 | #endif /* CONFIG_BCM43XX_PIO */ | 149 | #endif /* CONFIG_BCM43XX_PIO */ |
138 | #endif /* BCM43xx_PIO_H_ */ | 150 | #endif /* BCM43xx_PIO_H_ */ |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 8b37e824dfcb..8399de581893 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -1860,7 +1860,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1860 | memset(&iwe, 0, sizeof(iwe)); | 1860 | memset(&iwe, 0, sizeof(iwe)); |
1861 | iwe.cmd = SIOCGIWFREQ; | 1861 | iwe.cmd = SIOCGIWFREQ; |
1862 | if (scan) { | 1862 | if (scan) { |
1863 | chan = scan->chid; | 1863 | chan = le16_to_cpu(scan->chid); |
1864 | } else if (bss) { | 1864 | } else if (bss) { |
1865 | chan = bss->chan; | 1865 | chan = bss->chan; |
1866 | } else { | 1866 | } else { |
@@ -1868,7 +1868,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1868 | } | 1868 | } |
1869 | 1869 | ||
1870 | if (chan > 0) { | 1870 | if (chan > 0) { |
1871 | iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000; | 1871 | iwe.u.freq.m = freq_list[chan - 1] * 100000; |
1872 | iwe.u.freq.e = 1; | 1872 | iwe.u.freq.e = 1; |
1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, |
1874 | IW_EV_FREQ_LEN); | 1874 | IW_EV_FREQ_LEN); |
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h index 6b3693f05ca0..b1ebfbae397f 100644 --- a/include/net/ieee80211softmac.h +++ b/include/net/ieee80211softmac.h | |||
@@ -96,10 +96,13 @@ struct ieee80211softmac_assoc_info { | |||
96 | * | 96 | * |
97 | * bssvalid is true if we found a matching network | 97 | * bssvalid is true if we found a matching network |
98 | * and saved it's BSSID into the bssid above. | 98 | * and saved it's BSSID into the bssid above. |
99 | * | ||
100 | * bssfixed is used for SIOCSIWAP. | ||
99 | */ | 101 | */ |
100 | u8 static_essid:1, | 102 | u8 static_essid:1, |
101 | associating:1, | 103 | associating:1, |
102 | bssvalid:1; | 104 | bssvalid:1, |
105 | bssfixed:1; | ||
103 | 106 | ||
104 | /* Scan retries remaining */ | 107 | /* Scan retries remaining */ |
105 | int scan_retry; | 108 | int scan_retry; |
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index 4498023841dc..fb79ce7d6439 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c | |||
@@ -144,6 +144,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne | |||
144 | if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) | 144 | if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) |
145 | return 0; | 145 | return 0; |
146 | 146 | ||
147 | /* assume that users know what they're doing ... | ||
148 | * (note we don't let them select a net we're incompatible with) */ | ||
149 | if (mac->associnfo.bssfixed) { | ||
150 | return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN); | ||
151 | } | ||
152 | |||
147 | /* if 'ANY' network requested, take any that doesn't have privacy enabled */ | 153 | /* if 'ANY' network requested, take any that doesn't have privacy enabled */ |
148 | if (mac->associnfo.req_essid.len == 0 | 154 | if (mac->associnfo.req_essid.len == 0 |
149 | && !(net->capability & WLAN_CAPABILITY_PRIVACY)) | 155 | && !(net->capability & WLAN_CAPABILITY_PRIVACY)) |
@@ -176,7 +182,7 @@ ieee80211softmac_assoc_work(void *d) | |||
176 | ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); | 182 | ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); |
177 | 183 | ||
178 | /* try to find the requested network in our list, if we found one already */ | 184 | /* try to find the requested network in our list, if we found one already */ |
179 | if (mac->associnfo.bssvalid) | 185 | if (mac->associnfo.bssvalid || mac->associnfo.bssfixed) |
180 | found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); | 186 | found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); |
181 | 187 | ||
182 | /* Search the ieee80211 networks for this network if we didn't find it by bssid, | 188 | /* Search the ieee80211 networks for this network if we didn't find it by bssid, |
@@ -241,19 +247,25 @@ ieee80211softmac_assoc_work(void *d) | |||
241 | if (ieee80211softmac_start_scan(mac)) | 247 | if (ieee80211softmac_start_scan(mac)) |
242 | dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); | 248 | dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); |
243 | return; | 249 | return; |
244 | } | 250 | } else { |
245 | else { | ||
246 | spin_lock_irqsave(&mac->lock, flags); | 251 | spin_lock_irqsave(&mac->lock, flags); |
247 | mac->associnfo.associating = 0; | 252 | mac->associnfo.associating = 0; |
248 | mac->associated = 0; | 253 | mac->associated = 0; |
249 | spin_unlock_irqrestore(&mac->lock, flags); | 254 | spin_unlock_irqrestore(&mac->lock, flags); |
250 | 255 | ||
251 | dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); | 256 | dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); |
257 | /* reset the retry counter for the next user request since we | ||
258 | * break out and don't reschedule ourselves after this point. */ | ||
259 | mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; | ||
252 | ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); | 260 | ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); |
253 | return; | 261 | return; |
254 | } | 262 | } |
255 | } | 263 | } |
256 | 264 | ||
265 | /* reset the retry counter for the next user request since we | ||
266 | * now found a net and will try to associate to it, but not | ||
267 | * schedule this function again. */ | ||
268 | mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; | ||
257 | mac->associnfo.bssvalid = 1; | 269 | mac->associnfo.bssvalid = 1; |
258 | memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); | 270 | memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); |
259 | /* copy the ESSID for displaying it */ | 271 | /* copy the ESSID for displaying it */ |
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index 60f06a31f0d1..be83bdc1644a 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c | |||
@@ -45,6 +45,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) | |||
45 | softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; | 45 | softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; |
46 | softmac->scaninfo = NULL; | 46 | softmac->scaninfo = NULL; |
47 | 47 | ||
48 | softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; | ||
49 | |||
48 | /* TODO: initialise all the other callbacks in the ieee struct | 50 | /* TODO: initialise all the other callbacks in the ieee struct |
49 | * (once they're written) | 51 | * (once they're written) |
50 | */ | 52 | */ |
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 00f0d4f71897..27edb2b5581a 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c | |||
@@ -27,7 +27,8 @@ | |||
27 | #include "ieee80211softmac_priv.h" | 27 | #include "ieee80211softmac_priv.h" |
28 | 28 | ||
29 | #include <net/iw_handler.h> | 29 | #include <net/iw_handler.h> |
30 | 30 | /* for is_broadcast_ether_addr and is_zero_ether_addr */ | |
31 | #include <linux/etherdevice.h> | ||
31 | 32 | ||
32 | int | 33 | int |
33 | ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, | 34 | ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, |
@@ -83,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, | |||
83 | sm->associnfo.static_essid = 1; | 84 | sm->associnfo.static_essid = 1; |
84 | } | 85 | } |
85 | } | 86 | } |
86 | sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; | ||
87 | 87 | ||
88 | /* set our requested ESSID length. | 88 | /* set our requested ESSID length. |
89 | * If applicable, we have already copied the data in */ | 89 | * If applicable, we have already copied the data in */ |
@@ -310,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, | |||
310 | char *extra) | 310 | char *extra) |
311 | { | 311 | { |
312 | struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); | 312 | struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); |
313 | static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
314 | static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
315 | unsigned long flags; | 313 | unsigned long flags; |
316 | 314 | ||
317 | /* sanity check */ | 315 | /* sanity check */ |
@@ -320,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, | |||
320 | } | 318 | } |
321 | 319 | ||
322 | spin_lock_irqsave(&mac->lock, flags); | 320 | spin_lock_irqsave(&mac->lock, flags); |
323 | if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || | 321 | if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { |
324 | !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { | 322 | /* the bssid we have is not to be fixed any longer, |
325 | schedule_work(&mac->associnfo.work); | 323 | * and we should reassociate to the best AP. */ |
326 | goto out; | 324 | mac->associnfo.bssfixed = 0; |
325 | /* force reassociation */ | ||
326 | mac->associnfo.bssvalid = 0; | ||
327 | if (mac->associated) | ||
328 | schedule_work(&mac->associnfo.work); | ||
329 | } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { | ||
330 | /* the bssid we have is no longer fixed */ | ||
331 | mac->associnfo.bssfixed = 0; | ||
327 | } else { | 332 | } else { |
328 | if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { | 333 | if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { |
329 | if (mac->associnfo.associating || mac->associated) { | 334 | if (mac->associnfo.associating || mac->associated) { |
@@ -333,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, | |||
333 | } else { | 338 | } else { |
334 | /* copy new value in data->ap_addr.sa_data to bssid */ | 339 | /* copy new value in data->ap_addr.sa_data to bssid */ |
335 | memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); | 340 | memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); |
336 | } | 341 | } |
342 | /* tell the other code that this bssid should be used no matter what */ | ||
343 | mac->associnfo.bssfixed = 1; | ||
337 | /* queue associate if new bssid or (old one again and not associated) */ | 344 | /* queue associate if new bssid or (old one again and not associated) */ |
338 | schedule_work(&mac->associnfo.work); | 345 | schedule_work(&mac->associnfo.work); |
339 | } | 346 | } |
340 | 347 | ||
341 | out: | 348 | out: |
342 | spin_unlock_irqrestore(&mac->lock, flags); | 349 | spin_unlock_irqrestore(&mac->lock, flags); |
343 | return 0; | 350 | return 0; |
344 | } | 351 | } |