From 9b9ad40a56a018846effad113454d147f7f11e9c Mon Sep 17 00:00:00 2001 From: blymn Date: Thu, 24 Jul 2008 13:04:00 +0000 Subject: [PATCH] * Add the BSS node during the auth phase so negotiation can occur * Make the adding of a node into a function instead of duplicating code --- sys/dev/pci/if_iwn.c | 166 ++++++++++++++++++++++++++++--------------- 1 file changed, 110 insertions(+), 56 deletions(-) diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index b61624c2192e..1fa34cc5148f 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwn.c,v 1.10 2008/05/10 12:56:28 degroote Exp $ */ +/* $NetBSD: if_iwn.c,v 1.11 2008/07/24 13:04:00 blymn Exp $ */ /*- * Copyright (c) 2007 @@ -18,7 +18,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.10 2008/05/10 12:56:28 degroote Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.11 2008/07/24 13:04:00 blymn Exp $"); /* @@ -144,7 +144,6 @@ static void iwn_notif_intr(struct iwn_softc *); static int iwn_intr(void *); static void iwn_read_eeprom(struct iwn_softc *); static void iwn_read_eeprom_channels(struct iwn_softc *, int); -static void iwn_print_power_group(struct iwn_softc *, int); static uint8_t iwn_plcp_signal(int); static int iwn_tx_data(struct iwn_softc *, struct mbuf *, struct ieee80211_node *, int); @@ -182,6 +181,8 @@ static int iwn_init(struct ifnet *); static void iwn_stop(struct ifnet *, int); static void iwn_fix_channel(struct ieee80211com *, struct mbuf *); static bool iwn_resume(device_t PMF_FN_PROTO); +static int iwn_add_node(struct iwn_softc *sc, + struct ieee80211_node *ni, bool broadcast, bool async); @@ -190,12 +191,16 @@ static bool iwn_resume(device_t PMF_FN_PROTO); #ifdef IWN_DEBUG #define DPRINTF(x) do { if (iwn_debug > 0) printf x; } while (0) #define DPRINTFN(n, x) do { if (iwn_debug >= (n)) printf x; } while (0) -int iwn_debug = 2; +int iwn_debug = 0; #else #define DPRINTF(x) #define DPRINTFN(n, x) #endif +#ifdef IWN_DEBUG +static void iwn_print_power_group(struct iwn_softc *, int); +#endif + CFATTACH_DECL_NEW(iwn, sizeof(struct iwn_softc), iwn_match, iwn_attach, iwn_detach, NULL); @@ -467,7 +472,6 @@ iwn_radiotap_attach(struct iwn_softc *sc) * Build a beacon frame that the firmware will broadcast periodically in * IBSS or HostAP modes. */ -#if 0 static int iwn_setup_beacon(struct iwn_softc *sc, struct ieee80211_node *ni) { @@ -538,7 +542,6 @@ iwn_setup_beacon(struct iwn_softc *sc, struct ieee80211_node *ni) return 0; } -#endif static int iwn_dma_contig_alloc(bus_dma_tag_t tag, struct iwn_dma_info *dma, void **kvap, @@ -976,6 +979,9 @@ iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) callout_stop(&sc->calib_to); + DPRINTF(("iwn_newstate: nstate = %d, ic->ic_state = %d\n", nstate, + ic->ic_state)); + switch (nstate) { case IEEE80211_S_SCAN: @@ -1414,6 +1420,7 @@ iwn_rx_intr(struct iwn_softc *sc, struct iwn_rx_desc *desc, len = le16toh(stat->len); } + DPRINTF(("rx packet len %d\n", len)); /* discard Rx frames with bad CRC early */ tail = (uint32_t *)(head + len); if ((le32toh(*tail) & IWN_RX_NOERROR) != IWN_RX_NOERROR) { @@ -1903,6 +1910,8 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, uint8_t type; int i, error, pad, rate, hdrlen, noack = 0; + DPRINTFN(5, ("iwn_tx_data entry\n")); + desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; @@ -1927,8 +1936,7 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, } /* pickup a rate */ - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT) { + if (type == IEEE80211_FC0_TYPE_MGT) { /* mgmt frames are sent at the lowest available bit-rate */ rate = ni->ni_rates.rs_rates[0]; } else { @@ -1972,17 +1980,24 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, tx->id = IEEE80211_IS_MULTICAST(wh->i_addr1) ? IWN_ID_BROADCAST : IWN_ID_BSS; + DPRINTFN(5, ("addr1: %x:%x:%x:%x:%x:%x, id = 0x%x\n", + wh->i_addr1[0], wh->i_addr1[1], wh->i_addr1[2], + wh->i_addr1[3], wh->i_addr1[4], wh->i_addr1[5], tx->id)); + if (type == IEEE80211_FC0_TYPE_MGT) { uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; /* tell h/w to set timestamp in probe responses */ - if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) + if ((subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) || + (subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ)) flags |= IWN_TX_INSERT_TSTAMP; if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ || - subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) + subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { + flags &= ~IWN_TX_NEED_RTS; + flags |= IWN_TX_NEED_CTS; tx->timeout = htole16(3); - else + } else tx->timeout = htole16(2); } else tx->timeout = htole16(0); @@ -1994,6 +2009,16 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, } else pad = 0; + if (type == IEEE80211_FC0_TYPE_CTL) { + uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + + /* tell h/w to set timestamp in probe responses */ + if (subtype == 0x0080) /* linux says this is "back request" */ + /* linux says (1 << 6) is IMM_BA_RSP_MASK */ + flags |= (IWN_TX_NEED_ACK | (1 << 6)); + } + + tx->flags = htole32(flags); tx->len = htole16(m0->m_pkthdr.len); tx->rate = iwn_plcp_signal(rate); @@ -2100,6 +2125,8 @@ iwn_start(struct ifnet *ifp) struct mbuf *m0; int ac; + DPRINTFN(5, ("iwn_start enter\n")); + /* * net80211 may still try to send management frames even if the * IFF_RUNNING flag is not set... @@ -3073,12 +3100,50 @@ iwn_send_sensitivity(struct iwn_softc *sc) return iwn_cmd(sc, IWN_SENSITIVITY, &cmd, sizeof cmd, 1); } +static int +iwn_add_node(struct iwn_softc *sc, struct ieee80211_node *ni, bool broadcast, + bool async) +{ + struct iwn_node_info node; + int error; + + error = 0; + + memset(&node, 0, sizeof node); + if (broadcast == true) { + IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr); + node.id = IWN_ID_BROADCAST; + DPRINTF(("adding broadcast node\n")); + } else { + IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr); + node.id = IWN_ID_BSS; + node.htflags = htole32(3 << IWN_AMDPU_SIZE_FACTOR_SHIFT | + 5 << IWN_AMDPU_DENSITY_SHIFT); + DPRINTF(("adding BSS node\n")); + } + + error = iwn_cmd(sc, IWN_CMD_ADD_NODE, &node, sizeof node, async); + if (error != 0) { + aprint_error_dev(sc->sc_dev, "could not add %s node\n", + (broadcast == 1)? "broadcast" : "BSS"); + return error; + } + DPRINTF(("setting MRR for node %d\n", node.id)); + if ((error = iwn_setup_node_mrr(sc, node.id, async)) != 0) { + aprint_error_dev(sc->sc_dev, + "could not setup MRR for %s node\n", + (broadcast == 1)? "broadcast" : "BSS"); + return error; + } + + return error; +} + static int iwn_auth(struct iwn_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = ic->ic_bss; - struct iwn_node_info node; int error; /* update adapter's configuration */ @@ -3121,21 +3186,24 @@ iwn_auth(struct iwn_softc *sc) * Reconfiguring clears the adapter's nodes table so we must * add the broadcast node again. */ - memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr); - node.id = IWN_ID_BROADCAST; - DPRINTF(("adding broadcast node\n")); - error = iwn_cmd(sc, IWN_CMD_ADD_NODE, &node, sizeof node, 1); - if (error != 0) { - aprint_error_dev(sc->sc_dev, "could not add broadcast node\n"); - return error; - } - DPRINTF(("setting MRR for node %d\n", node.id)); - if ((error = iwn_setup_node_mrr(sc, node.id, 1)) != 0) { - aprint_error_dev(sc->sc_dev, "could not setup MRR for broadcast node\n"); + if ((error = iwn_add_node(sc, ni, true, true)) != 0) + return error; + + /* add BSS node */ + if ((error = iwn_add_node(sc, ni, false, true)) != 0) + return error; + + if (ic->ic_opmode == IEEE80211_M_STA) { + /* fake a join to init the tx rate */ + iwn_newassoc(ni, 1); + } + + if ((error = iwn_init_sensitivity(sc)) != 0) { + aprint_error_dev(sc->sc_dev, "could not set sensitivity\n"); return error; } + return 0; } @@ -3147,7 +3215,6 @@ iwn_run(struct iwn_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = ic->ic_bss; - struct iwn_node_info node; int error; if (ic->ic_opmode == IEEE80211_M_MONITOR) { @@ -3174,7 +3241,8 @@ iwn_run(struct iwn_softc *sc) error = iwn_cmd(sc, IWN_CMD_CONFIGURE, &sc->config, sizeof (struct iwn_config), 1); if (error != 0) { - aprint_error_dev(sc->sc_dev, "could not update configuration\n"); + aprint_error_dev(sc->sc_dev, + "could not update configuration\n"); return error; } @@ -3185,22 +3253,7 @@ iwn_run(struct iwn_softc *sc) } /* add BSS node */ - memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr); - node.id = IWN_ID_BSS; - node.htflags = htole32(3 << IWN_AMDPU_SIZE_FACTOR_SHIFT | - 5 << IWN_AMDPU_DENSITY_SHIFT); - DPRINTF(("adding BSS node\n")); - error = iwn_cmd(sc, IWN_CMD_ADD_NODE, &node, sizeof node, 1); - if (error != 0) { - aprint_error_dev(sc->sc_dev, "could not add BSS node\n"); - return error; - } - DPRINTF(("setting MRR for node %d\n", node.id)); - if ((error = iwn_setup_node_mrr(sc, node.id, 1)) != 0) { - aprint_error_dev(sc->sc_dev, "could not setup MRR for node %d\n", node.id); - return error; - } + iwn_add_node(sc, ni, false, true); if (ic->ic_opmode == IEEE80211_M_STA) { /* fake a join to init the tx rate */ @@ -3217,6 +3270,20 @@ iwn_run(struct iwn_softc *sc) sc->calib_cnt = 0; callout_schedule(&sc->calib_to, hz / 2); + if (0 == 1) { /* XXX don't do the beacon - we get a firmware error + XXX when we try. Something is wrong with the + XXX setup of the frame. Just don't ever call + XXX the function but reference it to keep gcc happy + */ + /* now we are associated set up the beacon frame */ + if ((error = iwn_setup_beacon(sc, ni))) { + aprint_error_dev(sc->sc_dev, + "could not setup beacon frame\n"); + return error; + } + } + + /* link LED always on while associated */ iwn_set_led(sc, IWN_LED_LINK, 0, 1); @@ -3415,7 +3482,6 @@ iwn_config(struct iwn_softc *sc) struct ifnet *ifp = ic->ic_ifp; struct iwn_power power; struct iwn_bluetooth bluetooth; - struct iwn_node_info node; int error; /* set power mode */ @@ -3492,20 +3558,8 @@ iwn_config(struct iwn_softc *sc) } /* add broadcast node */ - memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr); - node.id = IWN_ID_BROADCAST; - DPRINTF(("adding broadcast node\n")); - error = iwn_cmd(sc, IWN_CMD_ADD_NODE, &node, sizeof node, 0); - if (error != 0) { - aprint_error_dev(sc->sc_dev, "could not add broadcast node\n"); + if ((error = iwn_add_node(sc, NULL, true, false)) != 0) return error; - } - DPRINTF(("setting MRR for node %d\n", node.id)); - if ((error = iwn_setup_node_mrr(sc, node.id, 0)) != 0) { - aprint_error_dev(sc->sc_dev, "could not setup MRR for node %d\n", node.id); - return error; - } if ((error = iwn_set_critical_temp(sc)) != 0) { aprint_error_dev(sc->sc_dev, "could not set critical temperature\n");