Subject: Fix for ray driver and LINK0
To: None <chopps@netbsd.org>
From: Jason R Thorpe <thorpej@zembu.com>
List: port-alpha
Date: 04/20/2000 22:00:47
--6TrnltStXW4iwmi0
Content-Type: text/plain; charset=us-ascii

Hi folks...

I cooked up a fix for the "kernel crashes if you use LINK0 with the
ray driver" problem.  The problem is that when using the E2 encapsulation
mode that is required to communicate with the WebGear Windows driver,
the packet payload (i.e. the IP header, etc.) is unaligned.  This causes
an unaligned access fault when the IP layer attempts to process the
packet.

Note this bug only happens on systems where strict alignment is required,
e.g. Alpha and MIPS.

I cooked this up because I need to start using my WebGear cards in this
mode, but I haven't had a chance to test it yet.

Patch is attached; I'd like some feedback ASAP, as it will probably be
a few days before I get a chance to really try it out myself.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

--6TrnltStXW4iwmi0
Content-Type: text/plain; charset=us-ascii
Content-Description: if_ray.c patch
Content-Disposition: attachment; filename=foo

Index: if_ray.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pcmcia/if_ray.c,v
retrieving revision 1.18
diff -c -r1.18 if_ray.c
*** if_ray.c	2000/03/26 20:25:30	1.18
--- if_ray.c	2000/04/21 04:45:15
***************
*** 1357,1363 ****
  	struct ieee80211_frame *frame;
  	struct ether_header *eh;
  	struct mbuf *m;
! 	size_t pktlen, len, lenread;
  	bus_size_t bufp, ebufp, tmp;
  	struct ifnet *ifp;
  	u_int8_t *src, *d;
--- 1357,1363 ----
  	struct ieee80211_frame *frame;
  	struct ether_header *eh;
  	struct mbuf *m;
! 	size_t pktlen, fudge, len, lenread;
  	bus_size_t bufp, ebufp, tmp;
  	struct ifnet *ifp;
  	u_int8_t *src, *d;
***************
*** 1377,1382 ****
--- 1377,1394 ----
  	m = 0;
  	ifp = &sc->sc_if;
  
+ 	/*
+ 	 * If we're expecting the E2-in-802.11 encapsulation that the
+ 	 * WebGear Windows driver produces, fudge the packet forward
+ 	 * in the mbuf by 2 bytes so that the payload after the
+ 	 * Ethernet header will be aligned.  If we end up getting a
+ 	 * packet that's not of this type, we'll just drop it anyway.
+ 	 */
+ 	if (ifp->if_flags & IFF_LINK0)
+ 		fudge = 2;
+ 	else
+ 		fudge = 0;
+ 
  	/* it looks like at least with build 4 there is no CRC in length */
  	first = RAY_GET_INDEX(ccs);
  	pktlen = SRAM_READ_FIELD_2(sc, ccs, ray_cmd_rx, c_pktlen);
***************
*** 1401,1407 ****
  		ifp->if_ierrors++;
  		goto done;
  	}
! 	if (pktlen > MHLEN) {
  		/* XXX should allow chaining? */
  		MCLGET(m, M_DONTWAIT);
  		if ((m->m_flags & M_EXT) == 0) {
--- 1413,1419 ----
  		ifp->if_ierrors++;
  		goto done;
  	}
! 	if ((pktlen + fudge) > MHLEN) {
  		/* XXX should allow chaining? */
  		MCLGET(m, M_DONTWAIT);
  		if ((m->m_flags & M_EXT) == 0) {
***************
*** 1415,1420 ****
--- 1427,1433 ----
  	m->m_pkthdr.rcvif = ifp;
  	m->m_pkthdr.len = pktlen;
  	m->m_len = pktlen;
+ 	m->m_data += fudge;
  	d = mtod(m, u_int8_t *);
  
  	RAY_DPRINTF(("%s: recv ccs index %d\n", sc->sc_xname, first));

--6TrnltStXW4iwmi0--