airo endianness bug: cap_rid.extSoftCap
[cascardo/linux.git] / drivers / net / wireless / airo.c
index ee1cc14..68c5e54 100644 (file)
@@ -241,8 +241,8 @@ static int proc_perm = 0644;
 
 MODULE_AUTHOR("Benjamin Reed");
 MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \
-                   cards.  Direct support for ISA/PCI/MPI cards and support \
-                  for PCMCIA when used with airo_cs.");
+cards.  Direct support for ISA/PCI/MPI cards and support \
+for PCMCIA when used with airo_cs.");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
 module_param_array(io, int, NULL, 0);
@@ -2032,7 +2032,7 @@ static int mpi_send_packet (struct net_device *dev)
 
        /* get a packet to send */
 
-       if ((skb = skb_dequeue(&ai->txq)) == 0) {
+       if ((skb = skb_dequeue(&ai->txq)) == NULL) {
                airo_print_err(dev->name,
                        "%s: Dequeue'd zero in send_packet()",
                        __FUNCTION__);
@@ -2481,7 +2481,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
 
 EXPORT_SYMBOL(stop_airo_card);
 
-static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
+static int wll_header_parse(const struct sk_buff *skb, unsigned char *haddr)
 {
        memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN);
        return ETH_ALEN;
@@ -2696,14 +2696,13 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
        return rc;
 }
 
+static const struct header_ops airo_header_ops = {
+       .parse = wll_header_parse,
+};
+
 static void wifi_setup(struct net_device *dev)
 {
-       dev->hard_header        = NULL;
-       dev->rebuild_header     = NULL;
-       dev->hard_header_cache  = NULL;
-       dev->header_cache_update= NULL;
-
-       dev->hard_header_parse  = wll_header_parse;
+       dev->header_ops = &airo_header_ops;
        dev->hard_start_xmit = &airo_start_xmit11;
        dev->get_stats = &airo_get_stats;
        dev->set_mac_address = &airo_set_mac_address;
@@ -2821,6 +2820,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        struct net_device *dev;
        struct airo_info *ai;
        int i, rc;
+       DECLARE_MAC_BUF(mac);
 
        /* Create the network device object. */
        dev = alloc_netdev(sizeof(*ai), "", ether_setup);
@@ -2870,7 +2870,6 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        dev->base_addr = port;
 
        SET_NETDEV_DEV(dev, dmdev);
-       SET_MODULE_OWNER(dev);
 
        reset_card (dev, 1);
        msleep(400);
@@ -2924,9 +2923,8 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                goto err_out_reg;
 
        set_bit(FLAG_REGISTERED,&ai->flags);
-       airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
-               dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-               dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
+       airo_print_info(dev->name, "MAC enabled %s",
+                       print_mac(mac, dev->dev_addr));
 
        /* Allocate the transmit buffers */
        if (probe && !test_bit(FLAG_MPI,&ai->flags))
@@ -2983,6 +2981,7 @@ int reset_airo_card( struct net_device *dev )
 {
        int i;
        struct airo_info *ai = dev->priv;
+       DECLARE_MAC_BUF(mac);
 
        if (reset_card (dev, 1))
                return -1;
@@ -2991,9 +2990,8 @@ int reset_airo_card( struct net_device *dev )
                airo_print_err(dev->name, "MAC could not be enabled");
                return -1;
        }
-       airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
-                       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-                       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+       airo_print_info(dev->name, "MAC enabled %s",
+                       print_mac(mac, dev->dev_addr));
        /* Allocate the transmit buffers if needed */
        if (!test_bit(FLAG_MPI,&ai->flags))
                for( i = 0; i < MAX_FIDS; i++ )
@@ -3179,8 +3177,24 @@ static int airo_thread(void *data) {
        return 0;
 }
 
-static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
-       struct net_device *dev = (struct net_device *)dev_id;
+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;
        u16 status;
        u16 fid;
        struct airo_info *apriv = dev->priv;
@@ -3331,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;
 
@@ -3678,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;
@@ -3708,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 ) {
@@ -3862,7 +3847,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
                ai->config.authType = AUTH_OPEN;
                ai->config.modulation = MOD_CCK;
 
-               if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) &&
+               if ((cap_rid.len>=sizeof(cap_rid)) &&
+                   (cap_rid.extSoftCap & cpu_to_le16(1)) &&
                    (micsetup(ai) == SUCCESS)) {
                        ai->config.opmode |= MODE_MIC;
                        set_bit(FLAG_MIC_CAPABLE, &ai->flags);
@@ -4366,31 +4352,13 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
        Cmd cmd;
        Resp rsp;
        int hdrlen;
-       struct {
-               u8 addr4[ETH_ALEN];
-               u16 gaplen;
-               u8 gap[6];
-       } gap;
+       static u8 tail[(30-10) + 2 + 6] = {[30-10] = 6};
+       /* padding of header to full size + le16 gaplen (6) + gaplen bytes */
        u16 txFid = len;
        len >>= 16;
-       gap.gaplen = 6;
 
-       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);
@@ -4406,8 +4374,7 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
        bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
        if (bap_setup(ai, txFid, 0x0014, BAP1) != SUCCESS) return ERROR;
        bap_write(ai, (const u16*)pPacket, hdrlen, BAP1);
-       bap_write(ai, hdrlen == 30 ?
-               (const u16*)&gap.gaplen : (const u16*)&gap, 38 - hdrlen, BAP1);
+       bap_write(ai, (u16 *)(tail + (hdrlen - 10)), 38 - hdrlen, BAP1);
 
        bap_write(ai, (const u16*)(pPacket + hdrlen), len - hdrlen, BAP1);
        // issue the transmit command
@@ -5427,6 +5394,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
        int i;
        char *ptr;
        APListRid APList_rid;
+       DECLARE_MAC_BUF(mac);
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
@@ -5450,13 +5418,8 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
 // We end when we find a zero MAC
                if ( !*(int*)APList_rid.ap[i] &&
                     !*(int*)&APList_rid.ap[i][2]) break;
-               ptr += sprintf(ptr, "%02x:%02x:%02x:%02x:%02x:%02x\n",
-                              (int)APList_rid.ap[i][0],
-                              (int)APList_rid.ap[i][1],
-                              (int)APList_rid.ap[i][2],
-                              (int)APList_rid.ap[i][3],
-                              (int)APList_rid.ap[i][4],
-                              (int)APList_rid.ap[i][5]);
+               ptr += sprintf(ptr, "%s\n",
+                              print_mac(mac, APList_rid.ap[i]));
        }
        if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
 
@@ -5475,6 +5438,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
        int rc;
        /* If doLoseSync is not 1, we won't do a Lose Sync */
        int doLoseSync = -1;
+       DECLARE_MAC_BUF(mac);
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
@@ -5511,13 +5475,8 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
            we have to add a spin lock... */
        rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
        while(rc == 0 && BSSList_rid.index != 0xffff) {
-               ptr += sprintf(ptr, "%02x:%02x:%02x:%02x:%02x:%02x %*s rssi = %d",
-                               (int)BSSList_rid.bssid[0],
-                               (int)BSSList_rid.bssid[1],
-                               (int)BSSList_rid.bssid[2],
-                               (int)BSSList_rid.bssid[3],
-                               (int)BSSList_rid.bssid[4],
-                               (int)BSSList_rid.bssid[5],
+               ptr += sprintf(ptr, "%s %*s rssi = %d",
+                              print_mac(mac, BSSList_rid.bssid),
                                (int)BSSList_rid.ssidLen,
                                BSSList_rid.ssid,
                                (int)BSSList_rid.dBm);
@@ -6417,9 +6376,8 @@ static int airo_set_encode(struct net_device *dev,
                        set_wep_key(local, index, NULL, 0, perm, 1);
                } else
                        /* Don't complain if only change the mode */
-                       if(!dwrq->flags & IW_ENCODE_MODE) {
+                       if (!(dwrq->flags & IW_ENCODE_MODE))
                                return -EINVAL;
-                       }
        }
        /* Read the flags */
        if(dwrq->flags & IW_ENCODE_DISABLED)
@@ -7254,6 +7212,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
        char *                  current_val;    /* For rates */
        int                     i;
        char *          buf;
+       u16 dBm;
 
        /* First entry *MUST* be the AP MAC address */
        iwe.cmd = SIOCGIWAP;
@@ -7292,16 +7251,18 @@ static inline char *airo_translate_scan(struct net_device *dev,
        iwe.u.freq.e = 1;
        current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
 
+       dBm = le16_to_cpu(bss->dBm);
+
        /* Add quality statistics */
        iwe.cmd = IWEVQUAL;
        if (ai->rssi) {
-               iwe.u.qual.level = 0x100 - bss->dBm;
-               iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
+               iwe.u.qual.level = 0x100 - dBm;
+               iwe.u.qual.qual = airo_dbm_to_pct(ai->rssi, dBm);
                iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
                                | IW_QUAL_LEVEL_UPDATED
                                | IW_QUAL_DBM;
        } else {
-               iwe.u.qual.level = (bss->dBm + 321) / 2;
+               iwe.u.qual.level = (dBm + 321) / 2;
                iwe.u.qual.qual = 0;
                iwe.u.qual.updated = IW_QUAL_QUAL_INVALID
                                | IW_QUAL_LEVEL_UPDATED
@@ -7579,9 +7540,9 @@ static const iw_handler           airo_private_handler[] =
 
 static const struct iw_handler_def     airo_handler_def =
 {
-       .num_standard   = sizeof(airo_handler)/sizeof(iw_handler),
-       .num_private    = sizeof(airo_private_handler)/sizeof(iw_handler),
-       .num_private_args = sizeof(airo_private_args)/sizeof(struct iw_priv_args),
+       .num_standard   = ARRAY_SIZE(airo_handler),
+       .num_private    = ARRAY_SIZE(airo_private_handler),
+       .num_private_args = ARRAY_SIZE(airo_private_args),
        .standard       = airo_handler,
        .private        = airo_private_handler,
        .private_args   = airo_private_args,