]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/orinoco.c
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6] / drivers / net / wireless / orinoco.c
index 77e93a2255308a5ce8a94f9b9cadfb0a179d2d1d..488ab06fb79f46e81061f75d72c872121f286ee5 100644 (file)
 #define DRIVER_NAME "orinoco"
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
 #include <linux/netdevice.h>
-#include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 #include <net/ieee80211.h>
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "hermes.h"
 #include "hermes_rid.h"
 #include "orinoco.h"
 
@@ -214,31 +202,32 @@ static struct {
 /********************************************************************/
 
 /* Used in Event handling.
- * We avoid nested structres as they break on ARM -- Moustafa */
+ * We avoid nested structures as they break on ARM -- Moustafa */
 struct hermes_tx_descriptor_802_11 {
        /* hermes_tx_descriptor */
-       u16 status;
-       u16 reserved1;
-       u16 reserved2;
-       u32 sw_support;
+       __le16 status;
+       __le16 reserved1;
+       __le16 reserved2;
+       __le32 sw_support;
        u8 retry_count;
        u8 tx_rate;
-       u16 tx_control;
+       __le16 tx_control;
 
-       /* ieee802_11_hdr */
-       u16 frame_ctl;
-       u16 duration_id;
+       /* ieee80211_hdr */
+       __le16 frame_ctl;
+       __le16 duration_id;
        u8 addr1[ETH_ALEN];
        u8 addr2[ETH_ALEN];
        u8 addr3[ETH_ALEN];
-       u16 seq_ctl;
+       __le16 seq_ctl;
        u8 addr4[ETH_ALEN];
-       u16 data_len;
+
+       __le16 data_len;
 
        /* ethhdr */
-       unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
-       unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
-       unsigned short  h_proto;                /* packet type ID field */
+       u8 h_dest[ETH_ALEN];    /* destination eth addr */
+       u8 h_source[ETH_ALEN];  /* source ether addr    */
+       __be16 h_proto;         /* packet type ID field */
 
        /* p8022_hdr */
        u8 dsap;
@@ -246,31 +235,31 @@ struct hermes_tx_descriptor_802_11 {
        u8 ctrl;
        u8 oui[3];
 
-       u16 ethertype;
+       __be16 ethertype;
 } __attribute__ ((packed));
 
 /* Rx frame header except compatibility 802.3 header */
 struct hermes_rx_descriptor {
        /* Control */
-       u16 status;
-       u32 time;
+       __le16 status;
+       __le32 time;
        u8 silence;
        u8 signal;
        u8 rate;
        u8 rxflow;
-       u32 reserved;
+       __le32 reserved;
 
        /* 802.11 header */
-       u16 frame_ctl;
-       u16 duration_id;
+       __le16 frame_ctl;
+       __le16 duration_id;
        u8 addr1[ETH_ALEN];
        u8 addr2[ETH_ALEN];
        u8 addr3[ETH_ALEN];
-       u16 seq_ctl;
+       __le16 seq_ctl;
        u8 addr4[ETH_ALEN];
 
        /* Data length */
-       u16 data_len;
+       __le16 data_len;
 } __attribute__ ((packed));
 
 /********************************************************************/
@@ -401,7 +390,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
                }
        } else {
                struct {
-                       u16 qual, signal, noise;
+                       __le16 qual, signal, noise;
                } __attribute__ ((packed)) cq;
 
                err = HERMES_READ_RECORD(hw, USER_BAP,
@@ -503,7 +492,11 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Length of the packet body */
        /* FIXME: what if the skb is smaller than this? */
-       len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
+       len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
+       skb = skb_padto(skb, len);
+       if (skb == NULL)
+               goto fail;
+       len -= ETH_HLEN;
 
        eh = (struct ethhdr *)skb->data;
 
@@ -549,14 +542,21 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
                        stats->tx_errors++;
                        goto fail;
                }
+               /* Actual xfer length - allow for padding */
+               len = ALIGN(data_len, 2);
+               if (len < ETH_ZLEN - ETH_HLEN)
+                       len = ETH_ZLEN - ETH_HLEN;
        } else { /* IEEE 802.3 frame */
                data_len = len + ETH_HLEN;
                data_off = HERMES_802_3_OFFSET;
                p = skb->data;
+               /* Actual xfer length - round up for odd length packets */
+               len = ALIGN(data_len, 2);
+               if (len < ETH_ZLEN)
+                       len = ETH_ZLEN;
        }
 
-       /* Round up for odd length packets */
-       err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2),
+       err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len,
                                txfid, data_off);
        if (err) {
                printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
@@ -572,8 +572,9 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
                                txfid, NULL);
        if (err) {
                netif_start_queue(dev);
-               printk(KERN_ERR "%s: Error %d transmitting packet\n",
-                      dev->name, err);
+               if (net_ratelimit())
+                       printk(KERN_ERR "%s: Error %d transmitting packet\n",
+                               dev->name, err);
                stats->tx_errors++;
                goto fail;
        }
@@ -627,16 +628,17 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
        struct orinoco_private *priv = netdev_priv(dev);
        struct net_device_stats *stats = &priv->stats;
        u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+       u16 status;
        struct hermes_tx_descriptor_802_11 hdr;
        int err = 0;
 
        if (fid == DUMMY_FID)
                return; /* Nothing's really happened */
 
-       /* Read the frame header */
+       /* Read part of the frame header - we need status and addr1 */
        err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
-                              sizeof(struct hermes_tx_descriptor) +
-                              sizeof(struct ieee80211_hdr),
+                              offsetof(struct hermes_tx_descriptor_802_11,
+                                       addr2),
                               fid, 0);
 
        hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
@@ -656,8 +658,8 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
         * exceeded, because that's the only status that really mean
         * that this particular node went away.
         * Other errors means that *we* screwed up. - Jean II */
-       hdr.status = le16_to_cpu(hdr.status);
-       if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
+       status = le16_to_cpu(hdr.status);
+       if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
                union iwreq_data        wrqu;
 
                /* Copy 802.11 dest address.
@@ -1043,7 +1045,7 @@ static void orinoco_join_ap(struct net_device *dev)
        unsigned long flags;
        struct join_req {
                u8 bssid[ETH_ALEN];
-               u16 channel;
+               __le16 channel;
        } __attribute__ ((packed)) req;
        const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
        struct prism2_scan_apinfo *atom = NULL;
@@ -1058,7 +1060,7 @@ static void orinoco_join_ap(struct net_device *dev)
                return;
 
        if (orinoco_lock(priv, &flags) != 0)
-               goto out;
+               goto fail_lock;
 
        /* Sanity checks in case user changed something in the meantime */
        if (! priv->bssid_fixed)
@@ -1103,8 +1105,10 @@ static void orinoco_join_ap(struct net_device *dev)
                printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
 
  out:
-       kfree(buf);
        orinoco_unlock(priv, &flags);
+
+ fail_lock:
+       kfree(buf);
 }
 
 /* Send new BSSID to userspace */
@@ -1122,12 +1126,14 @@ static void orinoco_send_wevents(struct net_device *dev)
        err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
                              ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
        if (err != 0)
-               return;
+               goto out;
 
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 
        /* Send event to user space */
        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+
+ out:
        orinoco_unlock(priv, &flags);
 }
 
@@ -1136,8 +1142,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
        struct orinoco_private *priv = netdev_priv(dev);
        u16 infofid;
        struct {
-               u16 len;
-               u16 type;
+               __le16 len;
+               __le16 type;
        } __attribute__ ((packed)) info;
        int len, type;
        int err;
@@ -3913,7 +3919,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
                                                   HERMES_HOSTSCAN_SYMBOL_BCAST);
                        break;
                case FIRMWARE_TYPE_INTERSIL: {
-                       u16 req[3];
+                       __le16 req[3];
 
                        req[0] = cpu_to_le16(0x3fff);   /* All channels */
                        req[1] = cpu_to_le16(0x0001);   /* rate 1 Mbps */
@@ -3987,7 +3993,7 @@ static inline int orinoco_translate_scan(struct net_device *dev,
        case FIRMWARE_TYPE_INTERSIL:
                offset = 4;
                if (priv->has_hostscan) {
-                       atom_len = le16_to_cpup((u16 *)scan);
+                       atom_len = le16_to_cpup((__le16 *)scan);
                        /* Sanity check for atom_len */
                        if (atom_len < sizeof(struct prism2_scan_apinfo)) {
                                printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",