summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/airo.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2007-12-19 22:38:33 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 15:08:50 -0800
commit0300b3321d9ed73a0c3f575f2df250c577852356 (patch)
treef08a833e60d4276fabbd79a20361acec740fa725 /drivers/net/wireless/airo.c
parent851b3e5e3de0feea7bfee634f99a940648de58c8 (diff)
downloadlinux-0300b3321d9ed73a0c3f575f2df250c577852356.tar.gz
linux-0300b3321d9ed73a0c3f575f2df250c577852356.tar.bz2
linux-0300b3321d9ed73a0c3f575f2df250c577852356.zip
airo: bug in airo_interrupt() handling on incoming 802.11
On big-endian we end up with swapped first two bytes in packet, due to earlier conversion to host-endian and forgotten conversion back. The code we calculated that host-endian for had been duplicated several time - it finds the 802.11 MAC header length by the first two bytes of packet; taken into a new helper (header_len(__le16 ctl)). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/airo.c')
-rw-r--r--drivers/net/wireless/airo.c74
1 files changed, 23 insertions, 51 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 6d4cc684afa6..9d3f3357b6e1 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -3177,6 +3177,21 @@ static int airo_thread(void *data) {
return 0;
}
+static int header_len(__le16 ctl)
+{
+ u16 fc = le16_to_cpu(ctl);
+ switch (fc & 0xc) {
+ case 4:
+ if ((fc & 0xe0) == 0xc0)
+ return 10; /* one-address control packet */
+ return 16; /* two-address control packet */
+ case 8:
+ if ((fc & 0x300) == 0x300)
+ return 30; /* WDS packet */
+ }
+ return 24;
+}
+
static irqreturn_t airo_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
@@ -3330,23 +3345,8 @@ static irqreturn_t airo_interrupt(int irq, void *dev_id)
goto badrx;
if (test_bit(FLAG_802_11, &apriv->flags)) {
- bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0);
- fc = le16_to_cpu(fc);
- switch (fc & 0xc) {
- case 4:
- if ((fc & 0xe0) == 0xc0)
- hdrlen = 10;
- else
- hdrlen = 16;
- break;
- case 8:
- if ((fc&0x300)==0x300){
- hdrlen = 30;
- break;
- }
- default:
- hdrlen = 24;
- }
+ bap_read (apriv, &fc, sizeof(fc), BAP0);
+ hdrlen = header_len(fc);
} else
hdrlen = ETH_ALEN * 2;
@@ -3677,7 +3677,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
{
RxFid rxd;
struct sk_buff *skb = NULL;
- u16 fc, len, hdrlen = 0;
+ u16 len, hdrlen = 0;
+ __le16 fc;
#pragma pack(1)
struct {
u16 status, len;
@@ -3707,23 +3708,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
if (len == 0)
goto badrx;
- memcpy ((char *)&fc, ptr, sizeof(fc));
- fc = le16_to_cpu(fc);
- switch (fc & 0xc) {
- case 4:
- if ((fc & 0xe0) == 0xc0)
- hdrlen = 10;
- else
- hdrlen = 16;
- break;
- case 8:
- if ((fc&0x300)==0x300){
- hdrlen = 30;
- break;
- }
- default:
- hdrlen = 24;
- }
+ fc = get_unaligned((__le16 *)ptr);
+ hdrlen = header_len(fc);
skb = dev_alloc_skb( len + hdrlen + 2 );
if ( !skb ) {
@@ -4370,22 +4356,8 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
u16 txFid = len;
len >>= 16;
- fc = le16_to_cpu(*(const u16*)pPacket);
- switch (fc & 0xc) {
- case 4:
- if ((fc & 0xe0) == 0xc0)
- hdrlen = 10;
- else
- hdrlen = 16;
- break;
- case 8:
- if ((fc&0x300)==0x300){
- hdrlen = 30;
- break;
- }
- default:
- hdrlen = 24;
- }
+ fc = *(__le16*)pPacket;
+ hdrlen = header_len(fc);
if (len < hdrlen) {
airo_print_warn(ai->dev->name, "Short packet %d", len);