ARM patches for orinoco

Ben Greear greearb at candelatech.com
Tue Feb 26 16:41:33 EST 2002


The patch is attached.  Some of it you probably will not
want (the debug stuff).  The reset code doesn't actually
seem to help me, but it is no worse than the current state
(both of which are totally broken).  I think that a more
thorough reset (can you power the device down in software?)
might help rejuvinate the system...

The alignment pads and __attribute__ packed changes
actually seem to make it work on ARM w/out special
compilation hacks.  I think these should definately
go in...  In the future, you may want to design your
structures such that they are aligned to 4 byte boundaries,
internally too.  In other words, don't do this:

struct foo {
   char a;
   uint32 i;
   uint16 u;
   char a1;
};

But instead, perhaps do this:
struct foo {
   char a;
   char a1;
   uint16 u;
   uint32 i;
};

On the off chance that someone would like some traffic
generation software to help test their open-source network drivers, I
will be more than happy to give away licenses of the
LANforge program that my company makes, just ask.

Thanks,
Ben

-- 
Ben Greear <greearb at candelatech.com>       <Ben_Greear AT excite.com>
President of Candela Technologies Inc      http://www.candelatech.com
ScryMUD:  http://scry.wanfear.com     http://scry.wanfear.com/~greear

-------------- next part --------------
diff -u -r -N orinoco/hermes.h orinoco.dev/hermes.h
--- orinoco/hermes.h	Mon Feb 25 22:27:57 2002
+++ orinoco.dev/hermes.h	Mon Feb 25 22:26:42 2002
@@ -257,7 +257,7 @@
 	uint iobase;
 
 	u16 inten; /* Which interrupts should be enabled? */
-} hermes_t;
+}  __attribute__ ((packed)) hermes_t;
 
 typedef struct hermes_response {
 	u16 status, resp0, resp1, resp2;
diff -u -r -N orinoco/orinoco.c orinoco.dev/orinoco.c
--- orinoco/orinoco.c	Mon Feb 25 22:28:10 2002
+++ orinoco.dev/orinoco.c	Mon Feb 25 22:26:42 2002
@@ -309,6 +309,8 @@
 #include "orinoco.h"
 #include "ieee802_11.h"
 
+/* #define VERBOSE_DEBUG */
+
 /* Wireless extensions backwares compatibility */
 #ifndef SIOCIWFIRSTPRIV
 #define SIOCIWFIRSTPRIV		SIOCDEVPRIVATE
@@ -407,7 +409,7 @@
 	u8 ssap;
 	u8 ctrl;
 	u8 oui[3];
-};
+} __attribute__ ((packed));
 
 #define ENCAPS_OVERHEAD		(sizeof(struct p8022_hdr) + 2)
 
@@ -1326,7 +1342,21 @@
 		stats->rx_errors++;
 		goto drop;
 	}
-
+#ifdef VERBOSE_DEBUG
+        else {
+           int i = 0;
+           const unsigned char* dbg = (const unsigned char*)(&hdr);
+           printk("Packet received, hdr:\n");
+           for (i = 0; i<(sizeof(hdr)); i++) {
+              printk("%02hx ", (unsigned short)(dbg[i]));
+              if (((i + 1) % 16) == 0) {
+                 printk("\n");
+              }
+           }
+           printk("\n");
+        }
+#endif
+        
 	length = ntohs(hdr.len);
 	
 	/* Sanity check */
@@ -1394,11 +1426,46 @@
 		goto drop;
 	}
 
+#ifdef VERBOSE_DEBUG
+        if (1) {
+           int i = 0;
+           const unsigned char* dbg = (const unsigned char*)(skb->data);
+           printk("Packet received, data_len: %i  data_off: %i skb->len: %i skb->data:\n",
+                  data_len, data_off, skb->len);
+           printk("skb->protocol: 0x%x  skb->data addr: %p, hhl: %i\n",
+                  skb->protocol, skb->data, dev->hard_header_len);
+           for (i = 0; i<skb->len; i++) {
+              printk("%02hx ", (unsigned short)(dbg[i]));
+              if (((i + 1) % 16) == 0) {
+                 printk("\n");
+              }
+           }
+           printk("\n");
+        }
+#endif
+        
 	dev->last_rx = jiffies;
 	skb->dev = dev;
 	skb->protocol = eth_type_trans(skb, dev);
 	skb->ip_summed = CHECKSUM_NONE;
-	
+
+#ifdef VERBOSE_DEBUG
+        if (1) {
+           int i = 0;
+           const unsigned char* dbg = (const unsigned char*)(skb->data);
+           printk("After eth_type_trans, data_len: %i  data_off: %i skb->len: %i skb->data:\n",
+                  data_len, data_off, skb->len);
+           printk("skb->protocol: 0x%x  skb->data addr: %p\n", skb->protocol, skb->data);
+           for (i = 0; i<skb->len; i++) {
+              printk("%02hx ", (unsigned short)(dbg[i]));
+              if (((i + 1) % 16) == 0) {
+                 printk("\n");
+              }
+           }
+           printk("\n");
+        }
+#endif
+        
 	/* Process the wireless stats if needed */
 	orinoco_stat_gather(dev, skb, &desc);
 
@@ -1432,8 +1499,9 @@
 		       "(FID=%04X error %d)\n",
 		       dev->name, fid, err);
 	} else {
-		printk(KERN_INFO "%s: Tx error, status %d (FID=%04X)\n",
-		       dev->name, le16_to_cpu(desc.status), fid);
+		printk(KERN_INFO "%s: Tx error, status %d, retry_count: %d tx_rate: %d tx_control: %d (FID=%04X)\n",
+		       dev->name, le16_to_cpu(desc.status), (int)(desc.retry_count),
+                       (int)(desc.tx_rate), le16_to_cpu(desc.tx_control), fid);
 	}
 	
 	stats->tx_errors++;
@@ -1446,9 +1514,9 @@
 {
 	struct net_device *dev = &priv->ndev;
 	struct net_device_stats *stats = &priv->stats;
-/*  	u16 fid = hermes_read_regn(hw, TXCOMPLFID); */
 
-/*  	DEBUG(2, "%s: Transmit completed (FID=%04X)\n", priv->ndev.name, fid); */
+  	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+        /* printk("%s: Transmit completed (FID=%04X)\n", priv->ndev.name, fid); */
 
 	stats->tx_packets++;
 	netif_wake_queue(dev);
@@ -1621,6 +1689,26 @@
 
 	TRACE_ENTER("orinoco");
 
+        /* Maybe catch some alignment bugs on some architectures (ARM) */
+        if (sizeof(struct hermes_rx_descriptor) != 14) {
+           printk(KERN_ERR "FATAL: sizeof(struct hermes_rx_descriptor) != 14\n");
+        }
+        if (sizeof(struct hermes_tx_descriptor) != 14) {
+           printk(KERN_ERR "FATAL: sizeof(struct hermes_tx_descriptor) != 14\n");
+        }
+        if (sizeof(struct p8022_hdr) != 6) {
+           printk(KERN_ERR "FATAL: sizeof(struct p8022_hdr) != 6\n");
+        }
+        if (sizeof(struct hermes_idstring) != 34) {
+           printk(KERN_ERR "FATAL: sizeof(struct hermes_idstring) != 34\n");
+        }
+        if (sizeof(struct hermes_tallies_frame) != (23*2)) {
+           printk(KERN_ERR "FATAL: sizeof(struct hermes_tallies_frame) != (23*2)\n");
+         }
+        if (sizeof(struct header_struct) != 22) {
+           printk(KERN_ERR "FATAL: sizeof(struct header_struct) != 22)\n");
+        }
+        
 	orinoco_lock(priv);
 
 	/* Do standard firmware reset */
@@ -1896,7 +1984,7 @@
 
 	/* Length of the packet body */
 	/* FIXME: what if the skb is smaller than this? */
-	len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN);
+	len = max((int)(skb->len - ETH_HLEN), (int)(ETH_ZLEN));
 
 	eh = (struct ethhdr *)skb->data;
 
@@ -1906,11 +1994,34 @@
  	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
 	err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d writing Tx desciptor to BAP\n",
+		printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
 		       dev->name, err);
 		stats->tx_errors++;
+
+                if (err == -ETIMEDOUT) {
+                   if (++priv->timed_out_errors > MAX_ORINOCO_TIMEOUTS) {
+                      	printk("%s: Forcing reset due to %d timeouts!\n",
+                               dev->name, priv->timed_out_errors);
+                        printk("%s: tx_errors: %d  tx_bytes: %d  tx_pkts: %d rx_pkts: %d rx_bytes: %d\n",
+                               dev->name, stats->tx_errors, stats->tx_bytes, stats->tx_packets,
+                               stats->rx_packets, stats->rx_bytes);
+                        
+                        /* We need the xmit lock because it protects the
+                           multicast list which orinoco_reset() reads */
+                        /* Assuming we already have the lock since this is in
+                           the transmit method itself... --Ben */
+                        /* spin_lock_bh(&dev->xmit_lock); */
+                        orinoco_tx_timeout(dev);
+                        printk("Done with reset...\n");
+                        /* spin_unlock_bh(&dev->xmit_lock); */
+                        priv->timed_out_errors = 0;
+                   }
+                }
 		goto fail;
 	}
+        else {
+           priv->timed_out_errors = 0;
+        }
 
 	/* Encapsulate Ethernet-II frames */
 	if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
diff -u -r -N orinoco/orinoco.h orinoco.dev/orinoco.h
--- orinoco/orinoco.h	Mon Feb 25 22:28:15 2002
+++ orinoco.dev/orinoco.h	Mon Feb 25 22:26:43 2002
@@ -18,6 +18,11 @@
 #define ORINOCO_MAX_KEY_SIZE	14
 #define ORINOCO_MAX_KEYS	4
 
+#define MAX_ORINOCO_TIMEOUTS 3 /* How many times in a row must we get a timeout
+                                * while trying to transmit before we will reset
+                                * the card?
+                                */
+
 typedef struct orinoco_key {
 	u16 len;	/* always store little-endian */
 	char data[ORINOCO_MAX_KEY_SIZE];
@@ -45,6 +50,8 @@
 	/* Hardware control variables */
 	hermes_t hw;
 	u16 txfid;
+        u16 timed_out_errors; /* Count's TX timeout errors, acts
+                               * as a pad to 32-bit alignment for txfid too! */
 
 	/* Capabilities of the hardware/firmware */
 	int firmware_type;
@@ -58,18 +65,20 @@
 	int has_preamble;
 	int need_card_reset, broken_reset, broken_allocate;
 	u16 channel_mask;
+        u16 pad2;
 
 	/* Current configuration */
 	u32 iw_mode;
 	int port_type, allow_ibss;
 
 	u16 wep_on, wep_restrict, tx_key;
+        u16 pad3;
 	orinoco_keys_t keys;
 
 	int bitratemode;
 
- 	char nick[IW_ESSID_MAX_SIZE+1];
-	char desired_essid[IW_ESSID_MAX_SIZE+1];
+ 	char nick[IW_ESSID_MAX_SIZE+4];
+	char desired_essid[IW_ESSID_MAX_SIZE+4];
 	u16 frag_thresh, mwo_robust;
 	u16 channel;
 	u16 ap_density, rts_thresh;


More information about the wireless mailing list