Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Jun 2008 14:41:46 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 143118 for review
Message-ID:  <200806081441.m58Efkdv031845@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=143118

Change 143118 by hselasky@hselasky_laptop001 on 2008/06/08 14:41:43

	
	       Integrate ZYD USB WLAN driver @143078 separately, hence
	       there was a ton of changes to integrate after Sam & Co :-)
	       Some small bugs were found and corrected, for example
	some places the IEEE802.11 node was not freed when an
	error occurred, though the associated mbuf was freed.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/if_zyd.c#38 edit
.. //depot/projects/usb/src/sys/dev/usb/if_zydreg.h#15 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/if_zyd.c#38 (text+ko) ====

@@ -1,6 +1,6 @@
 /*	$OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $	*/
 /*	$NetBSD: if_zyd.c,v 1.7 2007/06/21 04:04:29 kiyohara Exp $	*/
-/*	$FreeBSD: src/sys/dev/usb/if_zyd.c,v 1.11 2007/12/01 08:53:03 kevlo Exp $	*/
+/*	$FreeBSD: src/sys/dev/usb/if_zyd.c,v 1.18 2008/06/07 18:38:02 sam Exp $	*/
 
 /*-
  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
@@ -20,7 +20,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/usb/if_zyd.c $");
+__FBSDID("$FreeBSD: src/sys/dev/usb/if_zyd.c,v 1.18 2008/06/07 18:38:02 sam Exp $");
 
 /*
  * ZyDAS ZD1211/ZD1211B USB WLAN driver
@@ -52,6 +52,7 @@
 #include <net80211/ieee80211_proto.h>
 #include <net80211/ieee80211_node.h>
 #include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_phy.h>
 
 #define	usbd_config_td_cc zyd_config_copy
 #define	usbd_config_td_softc zyd_softc
@@ -77,18 +78,12 @@
 SYSCTL_INT(_hw_usb_zyd, OID_AUTO, debug, CTLFLAG_RW, &zyd_debug, 0,
     "zyd debug level");
 #else
-#define	DPRINTF(...)
+#define	DPRINTF(...) do { } while (0)
 #endif
 
 #undef INDEXES
 #define	INDEXES(a) (sizeof(a) / sizeof((a)[0]))
 
-struct mq {				/* mini-queue */
-	struct mbuf *ifq_head;
-	struct mbuf *ifq_tail;
-	uint16_t ifq_len;
-};
-
 static device_probe_t zyd_probe;
 static device_attach_t zyd_attach;
 static device_detach_t zyd_detach;
@@ -103,7 +98,6 @@
 static usbd_callback_t zyd_bulk_write_callback;
 
 static usbd_config_td_command_t zyd_cfg_first_time_setup;
-static usbd_config_td_command_t zyd_cfg_set_run;
 static usbd_config_td_command_t zyd_cfg_update_promisc;
 static usbd_config_td_command_t zyd_cfg_set_chan;
 static usbd_config_td_command_t zyd_cfg_pre_init;
@@ -117,7 +111,6 @@
 static usbd_config_td_command_t zyd_cfg_amrr_timeout;
 
 static uint8_t zyd_plcp2ieee(uint8_t signal, uint8_t isofdm);
-static struct ieee80211_node *zyd_node_alloc_cb(struct ieee80211_node_table *nt);
 static void zyd_cfg_usbrequest(struct zyd_softc *sc, usb_device_request_t *req, uint8_t *data);
 static void zyd_cfg_usb_intr_read(struct zyd_softc *sc, void *data, uint32_t size);
 static void zyd_cfg_usb_intr_write(struct zyd_softc *sc, const void *data, uint16_t code, uint32_t size);
@@ -143,9 +136,6 @@
 static void zyd_cfg_set_mac_addr(struct zyd_softc *sc, const uint8_t *addr);
 static void zyd_cfg_switch_radio(struct zyd_softc *sc, uint8_t onoff);
 static void zyd_cfg_set_bssid(struct zyd_softc *sc, uint8_t *addr);
-static int zyd_media_change_cb(struct ifnet *ifp);
-static int zyd_newstate_cb(struct ieee80211com *ic, enum ieee80211_state nstate, int arg);
-static uint8_t zyd_plcp_signal(uint8_t rate);
 static void zyd_start_transfers(struct zyd_softc *sc);
 static void zyd_start_cb(struct ifnet *ifp);
 static void zyd_init_cb(void *arg);
@@ -157,6 +147,21 @@
 static void zyd_scan_end_cb(struct ieee80211com *ic);
 static void zyd_set_channel_cb(struct ieee80211com *ic);
 static void zyd_cfg_set_led(struct zyd_softc *sc, uint32_t which, uint8_t on);
+static struct ieee80211vap *zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, int opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]);
+static void zyd_vap_delete(struct ieee80211vap *);
+static struct ieee80211_node *zyd_node_alloc_cb(struct ieee80211_node_table *);
+static void zyd_cfg_set_run(struct zyd_softc *sc, struct zyd_config_copy *cc);
+static void zyd_fill_write_queue(struct zyd_softc *sc);
+static void zyd_tx_clean_queue(struct zyd_softc *sc);
+static void zyd_tx_freem(struct mbuf *m);
+static void zyd_tx_mgt(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni);
+static struct ieee80211vap *zyd_get_vap(struct zyd_softc *sc);
+static void zyd_tx_data(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni);
+static int zyd_raw_xmit_cb(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params);
+static void zyd_setup_desc_and_tx(struct zyd_softc *sc, struct mbuf *m, uint16_t rate);
+static int zyd_newstate_cb(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg);
+static void zyd_cfg_amrr_start(struct zyd_softc *sc);
+static void zyd_update_mcast(struct ifnet *ifp);
 
 static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY;
 static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB;
@@ -346,16 +351,6 @@
 	}
 }
 
-/* ARGUSED */
-static struct ieee80211_node *
-zyd_node_alloc_cb(struct ieee80211_node_table *nt __unused)
-{
-	struct zyd_node *zn;
-
-	zn = malloc(sizeof(struct zyd_node), M_80211_NODE, M_WAITOK | M_ZERO);
-	return ((zn != NULL) ? (&zn->ni) : NULL);
-}
-
 /*
  * USB request basic wrapper
  */
@@ -461,8 +456,8 @@
 handle_notif_retrystatus:{
 
 		struct zyd_notif_retry *retry = (void *)(cmd->data);
-		struct ieee80211com *ic = &sc->sc_ic;
 		struct ifnet *ifp = sc->sc_ifp;
+		struct ieee80211vap *vap;
 		struct ieee80211_node *ni;
 
 		DPRINTF(sc, 0, "retry intr: rate=0x%x "
@@ -472,21 +467,21 @@
 		    retry->macaddr[5], le16toh(retry->count) & 0xff,
 		    le16toh(retry->count));
 
-		/*
-		 * Find the node to which the packet was sent and update its
-		 * retry statistics. In BSS mode, this node is the AP we're
-		 * associated to so no lookup is actually needed.
-		 */
-		if (ic->ic_opmode != IEEE80211_M_STA) {
-			ni = ieee80211_find_node(&ic->ic_sta, retry->macaddr);
-		} else {
-			ni = ic->ic_bss;
+		vap = zyd_get_vap(sc);
+		if ((vap != NULL) && (sc->sc_amrr_timer)) {
+			/*
+			 * Find the node to which the packet was sent
+			 * and update its retry statistics.  In BSS
+			 * mode, this node is the AP we're associated
+			 * to so no lookup is actually needed.
+			 */
+			ni = ieee80211_find_txnode(vap, retry->macaddr);
+			if (ni != NULL) {
+				ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn,
+				    IEEE80211_AMRR_FAILURE, 1);
+				ieee80211_free_node(ni);
+			}
 		}
-		if (ni == NULL) {
-			goto tr_setup;
-		}
-		((struct zyd_node *)ni)->amn.amn_retrycnt++;
-
 		if (retry->count & htole16(0x100)) {
 			ifp->if_oerrors++;	/* too many retries */
 		}
@@ -800,7 +795,7 @@
 }
 
 static void
-zyd_bulk_read_callback_sub(struct usbd_xfer *xfer, struct mq *mq,
+zyd_bulk_read_callback_sub(struct usbd_xfer *xfer, struct zyd_ifq *mq,
     uint32_t offset, uint16_t len)
 {
 	enum {
@@ -853,7 +848,7 @@
 	usbd_copy_out(xfer->frbuffers, offset +
 	    sizeof(plcp), m->m_data, len);
 
-	if (bpf_peers_present(sc->sc_drvbpf)) {
+	if (bpf_peers_present(ifp->if_bpf)) {
 		struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap;
 
 		tap->wr_flags = 0;
@@ -867,7 +862,7 @@
 		tap->wr_antsignal = stat.rssi + -95;
 		tap->wr_antnoise = -95;	/* XXX */
 
-		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
+		bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m);
 	}
 	if (sizeof(m->m_hdr.pad) > 0) {
 		m->m_hdr.pad[0] = stat.rssi;	/* XXX hack */
@@ -881,16 +876,17 @@
 zyd_bulk_read_callback(struct usbd_xfer *xfer)
 {
 	struct zyd_softc *sc = xfer->priv_sc;
-	struct ieee80211com *ic = &(sc->sc_ic);
-	struct ifnet *ifp = ic->ic_ifp;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ieee80211_node *ni;
 	struct zyd_rx_desc rx_desc;
-	struct mq mq = {NULL, NULL, 0};
+	struct zyd_ifq mq = {NULL, NULL, 0};
 	struct mbuf *m;
 	uint32_t offset;
 	uint16_t len16;
 	uint8_t x;
 	uint8_t rssi;
+	int8_t nf;
 
 	switch (USBD_GET_STATE(xfer)) {
 	case USBD_ST_TRANSFERRED:
@@ -964,12 +960,20 @@
 
 				rssi = m->m_hdr.pad[0];	/* XXX hack */
 
-				ni = ieee80211_find_rxnode(ic, mtod(m, void *));
-				ieee80211_input(ic, m, ni, (rssi > 63) ?
-				    127 : (2 * rssi), -95 /* XXX */ , 0);
+				rssi = (rssi > 63) ? 127 : 2 * rssi;
+				nf = -95;	/* XXX */
 
-				/* node is no longer needed */
-				ieee80211_free_node(ni);
+				ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *));
+				if (ni != NULL) {
+					if (ieee80211_input(ni, m, rssi, nf, 0)) {
+						/* ignore */
+					}
+					ieee80211_free_node(ni);
+				} else {
+					if (ieee80211_input_all(ic, m, rssi, nf, 0)) {
+						/* ignore */
+					}
+				}
 			}
 
 			mtx_lock(&(sc->sc_mtx));
@@ -1904,13 +1908,23 @@
 zyd_cfg_first_time_setup(struct zyd_softc *sc,
     struct zyd_config_copy *cc, uint16_t refcount)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ieee80211com *ic;
 	struct ifnet *ifp;
 	const uint8_t *fw_ptr;
 	uint32_t fw_len;
-	uint32_t bands;
+	uint8_t bands;
 	usbd_status_t err;
 
+	/* setup RX tap header */
+	sc->sc_rxtap_len = sizeof(sc->sc_rxtap);
+	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
+	sc->sc_rxtap.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT);
+
+	/* setup TX tap header */
+	sc->sc_txtap_len = sizeof(sc->sc_txtap);
+	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
+	sc->sc_txtap.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT);
+
 	if (sc->sc_mac_rev == ZYD_ZD1211) {
 		fw_ptr = zd1211_firmware;
 		fw_len = sizeof(zd1211_firmware);
@@ -1953,7 +1967,7 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
-	ifp = if_alloc(IFT_ETHER);
+	ifp = if_alloc(IFT_IEEE80211);
 
 	mtx_lock(&(sc->sc_mtx));
 
@@ -1964,6 +1978,7 @@
 	}
 	sc->sc_evilhack = ifp;
 	sc->sc_ifp = ifp;
+	ic = ifp->if_l2com;
 
 	ifp->if_softc = sc;
 	if_initname(ifp, "zyd", sc->sc_unit);
@@ -1980,11 +1995,11 @@
 	ic->ic_ifp = ifp;
 	ic->ic_phytype = IEEE80211_T_OFDM;
 	ic->ic_opmode = IEEE80211_M_STA;
-	ic->ic_state = IEEE80211_S_INIT;
 
 	/* Set device capabilities */
 	ic->ic_caps =
-	    IEEE80211_C_MONITOR		/* monitor mode */
+	    IEEE80211_C_STA		/* station mode supported */
+	    | IEEE80211_C_MONITOR	/* monitor mode */
 	    | IEEE80211_C_SHPREAMBLE	/* short preamble supported */
 	    | IEEE80211_C_SHSLOT	/* short slot time supported */
 	    | IEEE80211_C_BGSCAN	/* capable of bg scanning */
@@ -1994,7 +2009,7 @@
 	bands = 0;
 	setbit(&bands, IEEE80211_MODE_11B);
 	setbit(&bands, IEEE80211_MODE_11G);
-	ieee80211_init_channels(ic, 0, CTRY_DEFAULT, bands, 0, 1);
+	ieee80211_init_channels(ic, NULL, &bands);
 
 	mtx_unlock(&(sc->sc_mtx));
 
@@ -2003,42 +2018,26 @@
 	mtx_lock(&(sc->sc_mtx));
 
 	ic->ic_node_alloc = &zyd_node_alloc_cb;
+	ic->ic_raw_xmit = &zyd_raw_xmit_cb;
 	ic->ic_newassoc = &zyd_newassoc_cb;
 
-	/* enable s/w bmiss handling in sta mode */
-	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;
 	ic->ic_scan_start = &zyd_scan_start_cb;
 	ic->ic_scan_end = &zyd_scan_end_cb;
 	ic->ic_set_channel = &zyd_set_channel_cb;
+	ic->ic_vap_create = &zyd_vap_create;
+	ic->ic_vap_delete = &zyd_vap_delete;
+	ic->ic_update_mcast = zyd_update_mcast;
 
-	/* override state transition machine */
-	sc->sc_newstate = ic->ic_newstate;
-	ic->ic_newstate = &zyd_newstate_cb;
+	sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
 
 	mtx_unlock(&(sc->sc_mtx));
 
-	/* setup ifmedia interface */
-	ieee80211_media_init(ic, &zyd_media_change_cb, &ieee80211_media_status);
-
-	/* setup automatic rate adjustment */
-	ieee80211_amrr_init(&sc->sc_amrr, ic,
-	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
-	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD);
-
-	bpfattach2(ifp, DLT_IEEE802_11_RADIO,
+	bpfattach(ifp, DLT_IEEE802_11_RADIO,
 	    sizeof(struct ieee80211_frame) +
-	    sizeof(sc->sc_txtap), &sc->sc_drvbpf);
+	    sizeof(sc->sc_txtap));
 
 	mtx_lock(&(sc->sc_mtx));
 
-	sc->sc_rxtap_len = sizeof(sc->sc_rxtap);
-	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
-	sc->sc_rxtap.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT);
-
-	sc->sc_txtap_len = sizeof(sc->sc_txtap);
-	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
-	sc->sc_txtap.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT);
-
 	if (bootverbose) {
 		ieee80211_announce(ic);
 	}
@@ -2065,8 +2064,8 @@
 
 	zyd_cfg_pre_stop(sc, NULL, 0);
 
-	ic = &(sc->sc_ic);
-	ifp = ic->ic_ifp;
+	ifp = sc->sc_ifp;
+	ic = ifp->if_l2com;
 
 	mtx_unlock(&(sc->sc_mtx));
 
@@ -2090,38 +2089,52 @@
 	return (0);
 }
 
-static int
-zyd_media_change_cb(struct ifnet *ifp)
+static void
+zyd_cfg_newstate(struct zyd_softc *sc,
+    struct zyd_config_copy *cc, uint16_t refcount)
 {
-	struct zyd_softc *sc = ifp->if_softc;
-	int error;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+	struct zyd_vap *uvp = ZYD_VAP(vap);
+	enum ieee80211_state ostate;
+	enum ieee80211_state nstate;
+	int arg;
+
+	ostate = vap->iv_state;
+	nstate = sc->sc_ns_state;
+	arg = sc->sc_ns_arg;
+
+	switch (nstate) {
+	case IEEE80211_S_INIT:
+		if (ostate == IEEE80211_S_RUN) {
+			/* do nothing */
+		}
+		break;
 
-	mtx_lock(&(sc->sc_mtx));
+	case IEEE80211_S_RUN:
+		zyd_cfg_set_run(sc, cc);
+		break;
 
-	error = ieee80211_media_change(ifp);
-	if (error != ENETRESET) {
-		goto done;
-	} else {
-		error = 0;
+	default:
+		break;
 	}
 
-	if ((ifp->if_flags & IFF_UP) &&
-	    (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-		usbd_config_td_queue_command
-		    (&(sc->sc_config_td), &zyd_cfg_pre_init,
-		    &zyd_cfg_init, 0, 0);
-	}
-done:
 	mtx_unlock(&(sc->sc_mtx));
-
-	return (error);
+	IEEE80211_LOCK(ic);
+	uvp->newstate(vap, nstate, arg);
+	if (vap->iv_newstate_cb != NULL)
+		vap->iv_newstate_cb(vap, nstate, arg);
+	IEEE80211_UNLOCK(ic);
+	mtx_lock(&(sc->sc_mtx));
+	return;
 }
 
 static void
 zyd_cfg_set_run(struct zyd_softc *sc,
-    struct zyd_config_copy *cc, uint16_t refcount)
+    struct zyd_config_copy *cc)
 {
-	zyd_cfg_set_chan(sc, cc, refcount);
+	zyd_cfg_set_chan(sc, cc, 0);
 
 	if (cc->ic_opmode != IEEE80211_M_MONITOR) {
 		/* turn link LED on */
@@ -2130,61 +2143,43 @@
 		/* make data LED blink upon Tx */
 		zyd_cfg_write32(sc, sc->sc_firmware_base + ZYD_FW_LINK_STATUS, 1);
 
-		zyd_cfg_set_bssid(sc, cc->ic_bss.ni_bssid);
+		zyd_cfg_set_bssid(sc, cc->iv_bss.ni_bssid);
 	}
-	return;
-}
-
-static void
-zyd_cfg_pre_set_run(struct zyd_softc *sc,
-    struct zyd_config_copy *cc, uint16_t refcount)
-{
-	struct ieee80211com *ic = &(sc->sc_ic);
-
-	/* immediate configuration */
-
-	zyd_config_copy(sc, cc, 0);
-
-	/* enable automatic rate adaptation in STA mode */
-	if ((ic->ic_opmode == IEEE80211_M_STA) &&
-	    (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)) {
-		/* fake a join to init the tx rate */
-		zyd_newassoc_cb(ic->ic_bss, 1);
+	if (cc->iv_bss.fixed_rate_none) {
+		/* enable automatic rate adaptation */
+		zyd_cfg_amrr_start(sc);
 	}
 	return;
 }
 
 static int
-zyd_newstate_cb(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
+zyd_newstate_cb(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 {
+	struct ieee80211com *ic = vap->iv_ic;
 	struct zyd_softc *sc = ic->ic_ifp->if_softc;
 
+	DPRINTF(sc, 0, "setting new state: %d\n", nstate);
+
 	mtx_lock(&(sc->sc_mtx));
 
-	DPRINTF(sc, 0, "setting new state %d\n", nstate);
-
-	/* set new state first! */
-	(sc->sc_newstate) (ic, nstate, arg);
+	/* store next state */
+	sc->sc_ns_state = nstate;
+	sc->sc_ns_arg = arg;
 
 	/* stop timers */
-
 	sc->sc_amrr_timer = 0;
 
-	switch (nstate) {
-	case IEEE80211_S_RUN:
-		usbd_config_td_queue_command
-		    (&(sc->sc_config_td), &zyd_cfg_pre_set_run,
-		    &zyd_cfg_set_run, 0, 0);
-		break;
-	default:
-		break;
-	}
+	/*
+	 * USB configuration can only be done from the USB configuration
+	 * thread:
+	 */
+	usbd_config_td_queue_command
+	    (&(sc->sc_config_td), &zyd_config_copy,
+	    &zyd_cfg_newstate, 0, 0);
 
-	sc->sc_newstate(ic, nstate, -1);
-
 	mtx_unlock(&(sc->sc_mtx));
 
-	return (0);
+	return EINPROGRESS;
 }
 
 static void
@@ -2218,7 +2213,7 @@
 	;				/* fix for indent */
 
 	switch (rate) {
-		/* CCK rates */
+		/* CCK rates (NB: not IEEE std, device-specific) */
 	case 2:
 		return (0x0);
 	case 4:
@@ -2246,7 +2241,7 @@
 	case 108:
 		return (0xc);
 
-		/* unsupported rates (should not get there) */
+		/* XXX unsupported/unknown rate */
 	default:
 		return (0xff);
 	}
@@ -2259,6 +2254,8 @@
 
 	mtx_lock(&(sc->sc_mtx));
 
+	sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
+
 	usbd_config_td_queue_command
 	    (&(sc->sc_config_td), &zyd_config_copy, func, 0, 0);
 
@@ -2304,7 +2301,7 @@
 zyd_cfg_scan_end(struct zyd_softc *sc,
     struct zyd_config_copy *cc, uint16_t refcount)
 {
-	zyd_cfg_set_bssid(sc, cc->ic_bss.ni_bssid);
+	zyd_cfg_set_bssid(sc, cc->iv_bss.ni_bssid);
 	return;
 }
 
@@ -2370,8 +2367,8 @@
 zyd_cfg_pre_init(struct zyd_softc *sc,
     struct zyd_config_copy *cc, uint16_t refcount)
 {
-	struct ieee80211com *ic = &(sc->sc_ic);
-	struct ifnet *ifp = sc->sc_ic.ic_ifp;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 
 	zyd_cfg_pre_stop(sc, cc, 0);
 
@@ -2381,13 +2378,6 @@
 
 	IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
 
-	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
-		if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) {
-			ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
-		}
-	} else {
-		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
-	}
 	return;
 }
 
@@ -2455,17 +2445,13 @@
 zyd_cfg_pre_stop(struct zyd_softc *sc,
     struct zyd_config_copy *cc, uint16_t refcount)
 {
-	struct ieee80211com *ic = &(sc->sc_ic);
-	struct ifnet *ifp = ic->ic_ifp;
+	struct ifnet *ifp = sc->sc_ifp;
 
 	if (cc) {
 		/* copy the needed configuration */
 		zyd_config_copy(sc, cc, refcount);
 	}
 	if (ifp) {
-
-		ieee80211_new_state(ic, IEEE80211_S_INIT, -1);	/* free all nodes */
-
 		/* clear flags */
 		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 	}
@@ -2479,14 +2465,9 @@
 	usbd_transfer_stop(sc->sc_xfer[ZYD_TR_BULK_DT_RD]);
 	usbd_transfer_stop(sc->sc_xfer[ZYD_TR_BULK_CS_WR]);
 	usbd_transfer_stop(sc->sc_xfer[ZYD_TR_BULK_CS_RD]);
-#if 0
-	/* clean up beacon transmission */
-	if (sc->sc_bcn_mbuf) {
-		m_freem(sc->sc_bcn_mbuf);
-		sc->sc_bcn_mbuf = NULL;
-		sc->sc_flags &= ~ZYD_FLAG_SEND_BCN_FRAME;
-	}
-#endif
+
+	/* clean up transmission */
+	zyd_tx_clean_queue(sc);
 	return;
 }
 
@@ -2509,6 +2490,21 @@
 }
 
 static void
+zyd_update_mcast(struct ifnet *ifp)
+{
+	struct zyd_softc *sc = ifp->if_softc;
+
+	mtx_lock(&(sc->sc_mtx));
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+		usbd_config_td_queue_command
+		    (&(sc->sc_config_td), &zyd_config_copy,
+		    &zyd_cfg_update_promisc, 0, 0);
+	}
+	mtx_unlock(&(sc->sc_mtx));
+	return;
+}
+
+static void
 zyd_cfg_set_rxfilter(struct zyd_softc *sc,
     struct zyd_config_copy *cc, uint16_t refcount)
 {
@@ -2569,9 +2565,7 @@
 	struct zyd_softc *sc = ifp->if_softc;
 
 	mtx_lock(&(sc->sc_mtx));
-
-	zyd_start_transfers(sc);
-
+	usbd_transfer_start(sc->sc_xfer[ZYD_TR_BULK_DT_WR]);
 	mtx_unlock(&(sc->sc_mtx));
 
 	return;
@@ -2591,156 +2585,112 @@
 	return;
 }
 
-/*------------------------------------------------------------------------*
- * zyd_bulk_write_callback - data write "thread"
- *
- * Returns:
- *    0: Success
- * Else: Error
- *------------------------------------------------------------------------*/
-static uint8_t
-zyd_bulk_write_callback_sub(struct usbd_xfer *xfer, struct mbuf *m,
-    struct ieee80211_node *ni, uint8_t flags, uint16_t rate)
+/*
+ * We assume that "m->m_pkthdr.rcvif" is pointing to the "ni" that
+ * should be freed, when "zyd_setup_desc_and_tx" is called.
+ */
+static void
+zyd_setup_desc_and_tx(struct zyd_softc *sc, struct mbuf *m,
+    uint16_t rate)
 {
-	struct zyd_softc *sc = xfer->priv_sc;
-	struct ieee80211com *ic = &(sc->sc_ic);
-	struct ieee80211_frame *wh;
-	struct ieee80211_key *k;
-	struct zyd_tx_desc tx_desc;
-	uint16_t temp_len;
-	uint16_t pkt_len;
-	uint16_t rem_len;
-	uint8_t type;
-	uint8_t sub_type;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+	struct mbuf *mm;
+	enum ieee80211_phytype phytype;
+	uint16_t len;
+	uint16_t totlen;
+	uint16_t pktlen;
+	uint8_t remainder;
 
-	wh = mtod(m, struct ieee80211_frame *);
-
-	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
-		k = ieee80211_crypto_encap(ic, ni, m);
-		if (k == NULL) {
-			return (1);
-		}
-		/*
-		 * packet header may have moved, reset our
-		 * local pointer
-		 */
-		wh = mtod(m, struct ieee80211_frame *);
+	if (sc->sc_tx_queue.ifq_len >= IFQ_MAXLEN) {
+		/* free packet */
+		zyd_tx_freem(m);
+		ifp->if_oerrors++;
+		return;
 	}
-	bzero(&tx_desc, sizeof(tx_desc));
-
-	temp_len = m->m_pkthdr.len + IEEE80211_CRC_LEN;
-
-	/* fill Tx descriptor */
-	tx_desc.len = htole16(temp_len);
-
-	/* decode some fields from the outgoing frame */
-	type = (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
-	sub_type = (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
-
-	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
-
-		if (type == IEEE80211_FC0_TYPE_DATA) {
-
-			flags |= ZYD_TX_FLAG_BACKOFF;
-
-			/*
-			 * multicast frames are not sent at OFDM rates in
-			 * 802.11b/g
-			 */
-			if (temp_len > ic->ic_rtsthreshold) {
-				flags |= ZYD_TX_FLAG_RTS;
-			} else if (ZYD_RATE_IS_OFDM(rate) &&
-			    (ic->ic_flags & IEEE80211_F_USEPROT)) {
-				if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
-					flags |= ZYD_TX_FLAG_CTS_TO_SELF;
-				else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
-					flags |= ZYD_TX_FLAG_RTS;
-			}
-		}
-	} else {
-		rate = ic->ic_mcast_rate;
-		flags |= ZYD_TX_FLAG_MULTICAST;
+	if (!((sc->sc_flags & ZYD_FLAG_LL_READY) &&
+	    (sc->sc_flags & ZYD_FLAG_HL_READY))) {
+		/* free packet */
+		zyd_tx_freem(m);
+		ifp->if_oerrors++;
+		return;
 	}
+	if (rate < 2) {
+		DPRINTF(sc, 0, "rate < 2!\n");
 
-	if ((type == IEEE80211_FC0_TYPE_CTL) &&
-	    (sub_type == IEEE80211_FC0_SUBTYPE_PS_POLL)) {
-		flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL);
+		/* avoid division by zero */
+		rate = 2;
 	}
-	tx_desc.flags = flags;
-	tx_desc.phy = zyd_plcp_signal(rate);
-	if (ZYD_RATE_IS_OFDM(rate)) {
-		tx_desc.phy |= ZYD_TX_PHY_OFDM;
-		if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
-			tx_desc.phy |= ZYD_TX_PHY_5GHZ;
-	} else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
-		tx_desc.phy |= ZYD_TX_PHY_SHPREAMBLE;
-
-	/* actual transmit length */
-	pkt_len = sizeof(struct zyd_tx_desc) + ZYD_HW_PADDING;
-	if (sc->sc_mac_rev == ZYD_ZD1211)
-		pkt_len += temp_len;
-	tx_desc.pktlen = htole16(pkt_len);
-
-	if (rate == 0) {
-		DPRINTF(sc, -1, "rate is zero!\n");
-		tx_desc.plcp_length = 0;
-	} else {
-		tx_desc.plcp_length = ((16 * temp_len) + rate - 1) / rate;
-	}
-	tx_desc.plcp_service = 0;
-	if (rate == 22) {
-		rem_len = (16 * temp_len) % 22;
-		if ((rem_len > 0) && (rem_len < 7)) {
-			tx_desc.plcp_service |= ZYD_PLCP_LENGEXT;
-		}
-	}
 	ic->ic_lastdata = ticks;
 
-	if (bpf_peers_present(sc->sc_drvbpf)) {
-		struct zyd_tx_radiotap_header *tap = &sc->sc_txtap;
+	if (bpf_peers_present(ifp->if_bpf)) {
+		struct zyd_tx_radiotap_header *tap = &(sc->sc_txtap);
 
 		tap->wt_flags = 0;
 		tap->wt_rate = rate;
 		tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
 		tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
 
-		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m);
+		bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m);
 	}
-	usbd_copy_in(xfer->frbuffers, 0, &(tx_desc), sizeof(tx_desc));
+	len = m->m_pkthdr.len;
+	totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
+	phytype = ieee80211_rate2phytype(sc->sc_rates, rate);
 
-	usbd_m_copy_in(xfer->frbuffers, sizeof(tx_desc),
-	    m, 0, m->m_pkthdr.len);
+	sc->sc_tx_desc.len = htole16(totlen);
+	sc->sc_tx_desc.phy = zyd_plcp_signal(rate);
+	if (phytype == IEEE80211_T_OFDM) {
+		sc->sc_tx_desc.phy |= ZYD_TX_PHY_OFDM;
+		if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
+			sc->sc_tx_desc.phy |= ZYD_TX_PHY_5GHZ;
+	} else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
+		sc->sc_tx_desc.phy |= ZYD_TX_PHY_SHPREAMBLE;
 
-	/* compute transfer length */
-	temp_len = (sizeof(tx_desc) + m->m_pkthdr.len);
+	/* actual transmit length (XXX why +10?) */
+	pktlen = sizeof(struct zyd_tx_desc) + 10;
+	if (sc->sc_mac_rev == ZYD_ZD1211)
+		pktlen += totlen;
+	sc->sc_tx_desc.pktlen = htole16(pktlen);
 
-	DPRINTF(sc, 10, "sending frame len=%u rate=%u xferlen=%u\n",
-	    m->m_pkthdr.len, rate, temp_len);
+	sc->sc_tx_desc.plcp_length = ((16 * totlen) + rate - 1) / rate;
+	sc->sc_tx_desc.plcp_service = 0;
+	if (rate == 22) {
+		remainder = (16 * totlen) % 22;
+		if ((remainder != 0) && (remainder < 7))
+			sc->sc_tx_desc.plcp_service |= ZYD_PLCP_LENGEXT;
+	}
+	if (sizeof(sc->sc_tx_desc) > MHLEN) {
+		DPRINTF(sc, 0, "No room for header structure!\n");
+		zyd_tx_freem(m);
+		return;
+	}
+	mm = m_gethdr(M_NOWAIT, MT_DATA);
+	if (mm == NULL) {
+		DPRINTF(sc, 0, "Could not allocate header mbuf!\n");
+		zyd_tx_freem(m);
+		return;
+	}
+	bcopy(&(sc->sc_tx_desc), mm->m_data, sizeof(sc->sc_tx_desc));
+	mm->m_len = sizeof(sc->sc_tx_desc);
 
-	if (m->m_flags & M_TXCB) {
-		ieee80211_process_callback(ni, m, 0);
-	}
-	xfer->frlengths[0] = temp_len;
+	mm->m_next = m;
+	mm->m_pkthdr.len = mm->m_len + m->m_pkthdr.len;
+	mm->m_pkthdr.rcvif = NULL;
 
-	m_freem(m);
+	/* start write transfer, if not started */
+	_IF_ENQUEUE(&(sc->sc_tx_queue), mm);
 
-	if (ni) {
-		ieee80211_free_node(ni);
-	}
-	usbd_start_hardware(xfer);
-	return (0);
+	usbd_transfer_start(sc->sc_xfer[0]);
+	return;
 }
 
 static void
 zyd_bulk_write_callback(struct usbd_xfer *xfer)
 {
 	struct zyd_softc *sc = xfer->priv_sc;
-	struct ieee80211com *ic = &(sc->sc_ic);
-	struct ifnet *ifp = sc->sc_ic.ic_ifp;
-	struct ieee80211_node *ni = NULL;
-	struct ether_header *eh;
-	struct mbuf *m = NULL;
-	uint8_t rate;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct mbuf *m;
+	uint16_t temp_len;
 
 	DPRINTF(sc, 0, "\n");
 
@@ -2751,7 +2701,6 @@
 		ifp->if_opackets++;
 
 	case USBD_ST_SETUP:
-tr_setup:
 		if (sc->sc_flags & ZYD_FLAG_BULK_WRITE_STALL) {
 			usbd_transfer_start(sc->sc_xfer[ZYD_TR_BULK_CS_WR]);
 			DPRINTF(sc, 10, "write stalled\n");
@@ -2764,106 +2713,34 @@
 			DPRINTF(sc, 10, "wait command\n");
 			break;
 		}
-#if 0
-		if (sc->sc_flags & ZYD_FLAG_SEND_BCN_FRAME) {
-			sc->sc_flags &= ~ZYD_FLAG_SEND_BCN_FRAME;
+		zyd_fill_write_queue(sc);
 
-			m = sc->sc_bcn_mbuf;
-			sc->sc_bcn_mbuf = NULL;
+		_IF_DEQUEUE(&(sc->sc_tx_queue), m);
 
-			if (zyd_bulk_write_callback_sub
-			    (xfer, m, NULL, sc->sc_bcn_flags, sc->sc_bcn_rate)) {
-				goto error;
-			}
-			break;
-		}
-#endif
-
-		IF_DEQUEUE(&(ic->ic_mgtq), m);
-
 		if (m) {
-
-			ni = (void *)m->m_pkthdr.rcvif;
-			m->m_pkthdr.rcvif = NULL;
-
-			if (bpf_peers_present(ic->ic_rawbpf)) {
-				bpf_mtap(ic->ic_rawbpf, m);
+			if (m->m_pkthdr.len > ZYD_MAX_TXBUFSZ) {
+				DPRINTF(sc, -1, "data overflow, %u bytes\n",
+				    m->m_pkthdr.len);
+				m->m_pkthdr.len = ZYD_MAX_TXBUFSZ;
 			}
-			rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
+			usbd_m_copy_in(xfer->frbuffers, 0,
+			    m, 0, m->m_pkthdr.len);
 
-			if (zyd_bulk_write_callback_sub(xfer, m,
-			    ni, 0, rate)) {
-				goto error;
-			}
-			break;
-		}
-		if (ic->ic_state != IEEE80211_S_RUN) {
-			break;
-		}
-		IFQ_DEQUEUE(&ifp->if_snd, m);
+			/* get transfer length */
+			temp_len = m->m_pkthdr.len;
 
-		if (m) {
+			DPRINTF(sc, 10, "sending frame len=%u xferlen=%u\n",
+			    m->m_pkthdr.len, temp_len);
 
-			/*
-                         * Cancel any background scan.
-                         */
-			if (ic->ic_flags & IEEE80211_F_SCAN) {
-				ieee80211_cancel_scan(ic);
-			}
-			if (m->m_len < sizeof(struct ether_header)) {
-				m = m_pullup(m, sizeof(struct ether_header));
+			xfer->frlengths[0] = temp_len;
 
-				if (m == NULL) {
-					goto error;
-				}
-			}
-			eh = mtod(m, struct ether_header *);
-			ni = ieee80211_find_txnode(ic, eh->ether_dhost);
-			if (ni == NULL) {
-				goto error;
-			}
-			BPF_MTAP(ifp, m);
+			usbd_start_hardware(xfer);
 
-			m = ieee80211_encap(ic, m, ni);
-
-			if (m == NULL) {
-				goto error;
-			}
-			if (bpf_peers_present(ic->ic_rawbpf)) {
-				bpf_mtap(ic->ic_rawbpf, m);
-			}
-			if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
-				rate = ic->ic_fixed_rate;
-			else
-				rate = ni->ni_rates.rs_rates[ni->ni_txrate];
-
-			rate &= IEEE80211_RATE_VAL;
-
-			if (zyd_bulk_write_callback_sub(xfer, m,
-			    ni, 0, rate)) {

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200806081441.m58Efkdv031845>