diff --git a/[refs] b/[refs] index 2483a665967f..a112a46985f9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8c95b4773dd8d0415269ffad7301ef96d75be8ee +refs/heads/master: 4d64e718b46f4eedaf0379e0150de4d28b06b916 diff --git a/trunk/drivers/net/mv643xx_eth.c b/trunk/drivers/net/mv643xx_eth.c index d65cadef4d22..06e024f5d68b 100644 --- a/trunk/drivers/net/mv643xx_eth.c +++ b/trunk/drivers/net/mv643xx_eth.c @@ -1741,23 +1741,22 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) BUG_ON(netif_queue_stopped(dev)); BUG_ON(skb == NULL); + if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) { + stats->tx_dropped++; + printk(KERN_DEBUG "%s: failed to linearize tiny " + "unaligned fragment\n", dev->name); + return 1; + } + + spin_lock_irqsave(&mp->lock, flags); + if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) { printk(KERN_ERR "%s: transmit with queue full\n", dev->name); netif_stop_queue(dev); + spin_unlock_irqrestore(&mp->lock, flags); return 1; } - if (has_tiny_unaligned_frags(skb)) { - if (__skb_linearize(skb)) { - stats->tx_dropped++; - printk(KERN_DEBUG "%s: failed to linearize tiny " - "unaligned fragment\n", dev->name); - return 1; - } - } - - spin_lock_irqsave(&mp->lock, flags); - eth_tx_submit_descs_for_skb(mp, skb); stats->tx_bytes += skb->len; stats->tx_packets++; diff --git a/trunk/drivers/net/wireless/ath5k/ath5k.h b/trunk/drivers/net/wireless/ath5k/ath5k.h index ba35c30d203c..b21830771ea5 100644 --- a/trunk/drivers/net/wireless/ath5k/ath5k.h +++ b/trunk/drivers/net/wireless/ath5k/ath5k.h @@ -142,7 +142,6 @@ enum ath5k_radio { AR5K_RF5112 = 2, AR5K_RF2413 = 3, AR5K_RF5413 = 4, - AR5K_RF2425 = 5, }; /* @@ -450,6 +449,14 @@ struct ath5k_rx_status { #define AR5K_RXKEYIX_INVALID ((u8) - 1) #define AR5K_TXKEYIX_INVALID ((u32) - 1) +struct ath5k_mib_stats { + u32 ackrcv_bad; + u32 rts_bad; + u32 rts_good; + u32 fcs_bad; + u32 beacons; +}; + /**************************\ BEACON TIMERS DEFINITIONS @@ -1062,7 +1069,6 @@ extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask); -extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); /* EEPROM access functions */ extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain); /* Protocol Control Unit Functions */ @@ -1091,6 +1097,7 @@ extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_be extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); #endif +extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics); /* ACK bit rate */ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); /* ACK/CTS Timeouts */ diff --git a/trunk/drivers/net/wireless/ath5k/base.c b/trunk/drivers/net/wireless/ath5k/base.c index e18305b781c9..8862d245c82b 100644 --- a/trunk/drivers/net/wireless/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath5k/base.c @@ -126,7 +126,6 @@ static struct ath5k_srev_name srev_names[] = { { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 }, { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 }, { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 }, - { "2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425 }, { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN }, { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, @@ -2342,8 +2341,7 @@ ath5k_init(struct ath5k_softc *sc) * Enable interrupts. */ sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL | - AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL | - AR5K_INT_MIB; + AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL; ath5k_hw_set_intr(sc->ah, sc->imask); /* Set ack to be sent at low bit-rates */ @@ -2523,11 +2521,7 @@ ath5k_intr(int irq, void *dev_id) if (status & AR5K_INT_BMISS) { } if (status & AR5K_INT_MIB) { - /* - * These stats are also used for ANI i think - * so how about updating them more often ? - */ - ath5k_hw_update_mib_counters(ah, &sc->ll_stats); + /* TODO */ } } } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); @@ -3020,10 +3014,6 @@ ath5k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - - /* Force update */ - ath5k_hw_update_mib_counters(ah, &sc->ll_stats); memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); diff --git a/trunk/drivers/net/wireless/ath5k/hw.c b/trunk/drivers/net/wireless/ath5k/hw.c index 87e782291a01..ff579a223621 100644 --- a/trunk/drivers/net/wireless/ath5k/hw.c +++ b/trunk/drivers/net/wireless/ath5k/hw.c @@ -119,70 +119,12 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, Attach/Detach Functions \***************************************/ -/* - * Power On Self Test helper function - */ -static int ath5k_hw_post(struct ath5k_hw *ah) -{ - - int i, c; - u16 cur_reg; - u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)}; - u32 var_pattern; - u32 static_pattern[4] = { - 0x55555555, 0xaaaaaaaa, - 0x66666666, 0x99999999 - }; - u32 init_val; - u32 cur_val; - - for (c = 0; c < 2; c++) { - - cur_reg = regs[c]; - init_val = ath5k_hw_reg_read(ah, cur_reg); - - for (i = 0; i < 256; i++) { - var_pattern = i << 16 | i; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - cur_val = ath5k_hw_reg_read(ah, cur_reg); - - if (cur_val != var_pattern) { - ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); - return -EAGAIN; - } - - /* Found on ndiswrapper dumps */ - var_pattern = 0x0039080f; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - } - - for (i = 0; i < 4; i++) { - var_pattern = static_pattern[i]; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - cur_val = ath5k_hw_reg_read(ah, cur_reg); - - if (cur_val != var_pattern) { - ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); - return -EAGAIN; - } - - /* Found on ndiswrapper dumps */ - var_pattern = 0x003b080f; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - } - } - - return 0; - -} - /* * Check if the device is supported and initialize the needed structs */ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) { struct ath5k_hw *ah; - struct pci_dev *pdev = sc->pdev; u8 mac[ETH_ALEN]; int ret; u32 srev; @@ -262,19 +204,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) CHANNEL_2GHZ); /* Return on unsuported chips (unsupported eeprom etc) */ - if ((srev >= AR5K_SREV_VER_AR5416) && - (srev < AR5K_SREV_VER_AR2425)) { + if(srev >= AR5K_SREV_VER_AR5416){ ATH5K_ERR(sc, "Device not yet supported.\n"); ret = -ENODEV; goto err_free; - } else if (srev == AR5K_SREV_VER_AR2425) { - ATH5K_WARN(sc, "Support for RF2425 is under development.\n"); } /* Identify single chip solutions */ - if (((srev <= AR5K_SREV_VER_AR5414) && - (srev >= AR5K_SREV_VER_AR2413)) || - (srev == AR5K_SREV_VER_AR2425)) { + if((srev <= AR5K_SREV_VER_AR5414) && + (srev >= AR5K_SREV_VER_AR2413)) { ah->ah_single_chip = true; } else { ah->ah_single_chip = false; @@ -303,65 +241,22 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { ah->ah_radio = AR5K_RF2413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { + } else { ah->ah_radio = AR5K_RF5413; if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 && ah->ah_mac_srev >= AR5K_SREV_VER_AR2424) ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; + else if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2425) + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; else ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - /* - * Register returns 0x4 for radio revision - * so ath5k_hw_radio_revision doesn't parse the value - * correctly. For now we are based on mac's srev to - * identify RF2425 radio. - */ - } else if (srev == AR5K_SREV_VER_AR2425) { - ah->ah_radio = AR5K_RF2425; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; - } - ah->ah_phy = AR5K_PHY(0); - /* - * Identify AR5212-based PCI-E cards - * And write some initial settings. - * - * (doing a "strings" on ndis driver - * -ar5211.sys- reveals the following - * pci-e related functions: - * - * pcieClockReq - * pcieRxErrNotify - * pcieL1SKPEnable - * pcieAspm - * pcieDisableAspmOnRfWake - * pciePowerSaveEnable - * - * I guess these point to ClockReq but - * i'm not sure.) - */ - if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { - ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080); - ath5k_hw_reg_write(ah, 0x24924924, 0x4080); - ath5k_hw_reg_write(ah, 0x28000039, 0x4080); - ath5k_hw_reg_write(ah, 0x53160824, 0x4080); - ath5k_hw_reg_write(ah, 0xe5980579, 0x4080); - ath5k_hw_reg_write(ah, 0x001defff, 0x4080); - ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080); - ath5k_hw_reg_write(ah, 0xbe105554, 0x4080); - ath5k_hw_reg_write(ah, 0x000e3007, 0x4080); - ath5k_hw_reg_write(ah, 0x00000000, 0x4084); } - /* - * POST - */ - ret = ath5k_hw_post(ah); - if (ret) - goto err_free; + ah->ah_phy = AR5K_PHY(0); /* * Get card capabilities, values, ... @@ -496,7 +391,7 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND | bus_flags); if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); + ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n"); return -EIO; } @@ -760,8 +655,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, if (ah->ah_radio != AR5K_RF5111 && ah->ah_radio != AR5K_RF5112 && ah->ah_radio != AR5K_RF5413 && - ah->ah_radio != AR5K_RF2413 && - ah->ah_radio != AR5K_RF2425) { + ah->ah_radio != AR5K_RF2413) { ATH5K_ERR(ah->ah_sc, "invalid phy radio: %u\n", ah->ah_radio); return -EINVAL; @@ -2955,19 +2849,15 @@ int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) * Update mib counters (statistics) */ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, - struct ieee80211_low_level_stats *stats) + struct ath5k_mib_stats *statistics) { ATH5K_TRACE(ah->ah_sc); - /* Read-And-Clear */ - stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); - stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); - stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); - stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); - - /* XXX: Should we use this to track beacon count ? - * -we read it anyway to clear the register */ - ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); + statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); + statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); + statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK); + statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); + statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); /* Reset profile count registers on 5212*/ if (ah->ah_version == AR5K_AR5212) { @@ -3068,16 +2958,8 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); - /* - * Set NULL encryption on AR5212+ - * - * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) - * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 - * - * Note2: Windows driver (ndiswrapper) sets this to - * 0x00000714 instead of 0x00000007 - */ - if (ah->ah_version > AR5K_AR5211) + /* Set NULL encryption on non-5210*/ + if (ah->ah_version != AR5K_AR5210) ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, AR5K_KEYTABLE_TYPE(entry)); diff --git a/trunk/drivers/net/wireless/ath5k/initvals.c b/trunk/drivers/net/wireless/ath5k/initvals.c index 04c84e9da89d..fdbab2f08178 100644 --- a/trunk/drivers/net/wireless/ath5k/initvals.c +++ b/trunk/drivers/net/wireless/ath5k/initvals.c @@ -1282,213 +1282,6 @@ static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, }; -/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ -/* XXX: No dumps for turbog yet, so turbog is the same with g here with some - * minor tweaking based on dumps from other chips */ -static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { - { AR5K_TXCFG, - /* g gTurbo */ - { 0x00000015, 0x00000015 } }, - { AR5K_USEC_5211, - { 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003 } }, - { AR5K_PHY(10), - { 0x0a020001, 0x0a020001 } }, - { AR5K_PHY(13), - { 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY(14), - { 0x0000000b, 0x0000000b } }, - { AR5K_PHY(17), - { 0x13721422, 0x13721422 } }, - { AR5K_PHY(18), - { 0x00199a65, 0x00199a65 } }, - { AR5K_PHY(20), - { 0x0c98b0da, 0x0c98b0da } }, - { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e } }, - { AR5K_PHY(27), - { 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000 } }, - { AR5K_PHY(642), - { 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x0052c140, 0x0052c140 } }, - { 0xa21c, - { 0x1883800a, 0x1883800a } }, - { 0xa324, - { 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa328, - { 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa32c, - { 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa330, - { 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa334, - { 0xa7cfa7cf, 0xa7cfa7cf } }, - { AR5K_DCU_FP, - { 0x000003e0, 0x000003e0 } }, - { 0x8060, - { 0x0000000f, 0x0000000f } }, - { 0x809c, - { 0x00000000, 0x00000000 } }, - { 0x80a0, - { 0x00000000, 0x00000000 } }, - { 0x8118, - { 0x00000000, 0x00000000 } }, - { 0x811c, - { 0x00000000, 0x00000000 } }, - { 0x8120, - { 0x00000000, 0x00000000 } }, - { 0x8124, - { 0x00000000, 0x00000000 } }, - { 0x8128, - { 0x00000000, 0x00000000 } }, - { 0x812c, - { 0x00000000, 0x00000000 } }, - { 0x8130, - { 0x00000000, 0x00000000 } }, - { 0x8134, - { 0x00000000, 0x00000000 } }, - { 0x8138, - { 0x00000000, 0x00000000 } }, - { 0x813c, - { 0x00000000, 0x00000000 } }, - { 0x8140, - { 0x800003f9, 0x800003f9 } }, - { 0x8144, - { 0x00000000, 0x00000000 } }, - { AR5K_PHY_AGC, - { 0x00000000, 0x00000000 } }, - { AR5K_PHY(11), - { 0x0000a000, 0x0000a000 } }, - { AR5K_PHY(15), - { 0x00200400, 0x00200400 } }, - { AR5K_PHY(19), - { 0x1284233c, 0x1284233c } }, - { AR5K_PHY_SCR, - { 0x0000001f, 0x0000001f } }, - { AR5K_PHY_SLMT, - { 0x00000080, 0x00000080 } }, - { AR5K_PHY_SCAL, - { 0x0000000e, 0x0000000e } }, - { AR5K_PHY(86), - { 0x00081fff, 0x00081fff } }, - { AR5K_PHY(96), - { 0x00000000, 0x00000000 } }, - { AR5K_PHY(97), - { 0x02800000, 0x02800000 } }, - { AR5K_PHY(104), - { 0x00000000, 0x00000000 } }, - { AR5K_PHY(119), - { 0xfebadbe8, 0xfebadbe8 } }, - { AR5K_PHY(120), - { 0x00000000, 0x00000000 } }, - { AR5K_PHY(121), - { 0xaaaaaaaa, 0xaaaaaaaa } }, - { AR5K_PHY(122), - { 0x3c466478, 0x3c466478 } }, - { AR5K_PHY(123), - { 0x000000aa, 0x000000aa } }, - { AR5K_PHY_SCLOCK, - { 0x0000000c, 0x0000000c } }, - { AR5K_PHY_SDELAY, - { 0x000000ff, 0x000000ff } }, - { AR5K_PHY_SPENDING, - { 0x00000014, 0x00000014 } }, - { 0xa228, - { 0x000009b5, 0x000009b5 } }, - { AR5K_PHY_TXPOWER_RATE3, - { 0x20202020, 0x20202020 } }, - { AR5K_PHY_TXPOWER_RATE4, - { 0x20202020, 0x20202020 } }, - { 0xa23c, - { 0x93c889af, 0x93c889af } }, - { 0xa24c, - { 0x00000001, 0x00000001 } }, - { 0xa250, - { 0x0000a000, 0x0000a000 } }, - { 0xa254, - { 0x00000000, 0x00000000 } }, - { 0xa258, - { 0x0cc75380, 0x0cc75380 } }, - { 0xa25c, - { 0x0f0f0f01, 0x0f0f0f01 } }, - { 0xa260, - { 0x5f690f01, 0x5f690f01 } }, - { 0xa264, - { 0x00418a11, 0x00418a11 } }, - { 0xa268, - { 0x00000000, 0x00000000 } }, - { 0xa26c, - { 0x0c30c166, 0x0c30c166 } }, - { 0xa270, - { 0x00820820, 0x00820820 } }, - { 0xa274, - { 0x081a3caa, 0x081a3caa } }, - { 0xa278, - { 0x1ce739ce, 0x1ce739ce } }, - { 0xa27c, - { 0x051701ce, 0x051701ce } }, - { 0xa300, - { 0x16010000, 0x16010000 } }, - { 0xa304, - { 0x2c032402, 0x2c032402 } }, - { 0xa308, - { 0x48433e42, 0x48433e42 } }, - { 0xa30c, - { 0x5a0f500b, 0x5a0f500b } }, - { 0xa310, - { 0x6c4b624a, 0x6c4b624a } }, - { 0xa314, - { 0x7e8b748a, 0x7e8b748a } }, - { 0xa318, - { 0x96cf8ccb, 0x96cf8ccb } }, - { 0xa31c, - { 0xa34f9d0f, 0xa34f9d0f } }, - { 0xa320, - { 0xa7cfa58f, 0xa7cfa58f } }, - { 0xa348, - { 0x3fffffff, 0x3fffffff } }, - { 0xa34c, - { 0x3fffffff, 0x3fffffff } }, - { 0xa350, - { 0x3fffffff, 0x3fffffff } }, - { 0xa354, - { 0x0003ffff, 0x0003ffff } }, - { 0xa358, - { 0x79a8aa1f, 0x79a8aa1f } }, - { 0xa35c, - { 0x066c420f, 0x066c420f } }, - { 0xa360, - { 0x0f282207, 0x0f282207 } }, - { 0xa364, - { 0x17601685, 0x17601685 } }, - { 0xa368, - { 0x1f801104, 0x1f801104 } }, - { 0xa36c, - { 0x37a00c03, 0x37a00c03 } }, - { 0xa370, - { 0x3fc40883, 0x3fc40883 } }, - { 0xa374, - { 0x57c00803, 0x57c00803 } }, - { 0xa378, - { 0x5fd80682, 0x5fd80682 } }, - { 0xa37c, - { 0x7fe00482, 0x7fe00482 } }, - { 0xa380, - { 0x7f3c7bba, 0x7f3c7bba } }, - { 0xa384, - { 0xf3307ff0, 0xf3307ff0 } }, -}; - /* * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) @@ -1749,34 +1542,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ARRAY_SIZE(rf5112_ini_bbgain), rf5112_ini_bbgain, change_channel); - } else if (ah->ah_radio == AR5K_RF2425) { - - if (mode < 2) { - ATH5K_ERR(ah->ah_sc, - "unsupported channel mode: %d\n", mode); - return -EINVAL; - } - - /* Map b to g */ - if (mode == 2) - mode = 0; - else - mode = mode - 3; - - /* Override a setting from ar5212_ini */ - ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648)); - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf2425_ini_mode_end), - rf2425_ini_mode_end, mode); - - /* Baseband gain table */ - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - } - /* For AR5211 */ } else if (ah->ah_version == AR5K_AR5211) { diff --git a/trunk/drivers/net/wireless/ath5k/phy.c b/trunk/drivers/net/wireless/ath5k/phy.c index afd8689e5c03..890ecce8bedc 100644 --- a/trunk/drivers/net/wireless/ath5k/phy.c +++ b/trunk/drivers/net/wireless/ath5k/phy.c @@ -669,7 +669,6 @@ static const struct ath5k_ini_rf rfregs_5413[] = { /* RF2413/2414 mode-specific init registers */ static const struct ath5k_ini_rf rfregs_2413[] = { { 1, AR5K_RF_BUFFER_CONTROL_4, - /* mode b mode g mode gTurbo */ { 0x00000020, 0x00000020, 0x00000020 } }, { 2, AR5K_RF_BUFFER_CONTROL_3, { 0x02001408, 0x02001408, 0x02001408 } }, @@ -737,83 +736,6 @@ static const struct ath5k_ini_rf rfregs_2413[] = { { 0x0000000e, 0x0000000e, 0x0000000e } }, }; -/* RF2425 mode-specific init registers */ -static const struct ath5k_ini_rf rfregs_2425[] = { - { 1, AR5K_RF_BUFFER_CONTROL_4, - /* mode g mode gTurbo */ - { 0x00000020, 0x00000020 } }, - { 2, AR5K_RF_BUFFER_CONTROL_3, - { 0x02001408, 0x02001408 } }, - { 3, AR5K_RF_BUFFER_CONTROL_6, - { 0x00e020c0, 0x00e020c0 } }, - { 6, AR5K_RF_BUFFER, - { 0x10000000, 0x10000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x002a0000, 0x002a0000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00100000, 0x00100000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00020000, 0x00020000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00730000, 0x00730000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00f80000, 0x00f80000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00e70000, 0x00e70000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00140000, 0x00140000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00910040, 0x00910040 } }, - { 6, AR5K_RF_BUFFER, - { 0x0007001a, 0x0007001a } }, - { 6, AR5K_RF_BUFFER, - { 0x00410000, 0x00410000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00810060, 0x00810060 } }, - { 6, AR5K_RF_BUFFER, - { 0x00020803, 0x00020803 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00000000, 0x00000000 } }, - { 6, AR5K_RF_BUFFER, - { 0x00001660, 0x00001660 } }, - { 6, AR5K_RF_BUFFER, - { 0x00001688, 0x00001688 } }, - { 6, AR5K_RF_BUFFER_CONTROL_1, - { 0x00000001, 0x00000001 } }, - { 7, AR5K_RF_BUFFER, - { 0x00006400, 0x00006400 } }, - { 7, AR5K_RF_BUFFER, - { 0x00000800, 0x00000800 } }, - { 7, AR5K_RF_BUFFER_CONTROL_2, - { 0x0000000e, 0x0000000e } }, -}; - /* Initial RF Gain settings for RF5112 */ static const struct ath5k_ini_rfgain rfgain_5112[] = { /* 5Ghz 2Ghz */ @@ -1426,8 +1348,7 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, } /* - * Initialize RF5413/5414 and future chips - * (until we come up with a better solution) + * Initialize RF5413/5414 */ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode) @@ -1441,41 +1362,19 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, rf = ah->ah_rf_banks; - switch (ah->ah_radio) { - case AR5K_RF5413: + if (ah->ah_radio == AR5K_RF5413) { rf_ini = rfregs_5413; rf_size = ARRAY_SIZE(rfregs_5413); - break; - case AR5K_RF2413: + } else if (ah->ah_radio == AR5K_RF2413) { rf_ini = rfregs_2413; rf_size = ARRAY_SIZE(rfregs_2413); - if (mode < 2) { ATH5K_ERR(ah->ah_sc, "invalid channel mode: %i\n", mode); return -EINVAL; } - mode = mode - 2; - break; - case AR5K_RF2425: - rf_ini = rfregs_2425; - rf_size = ARRAY_SIZE(rfregs_2425); - - if (mode < 2) { - ATH5K_ERR(ah->ah_sc, - "invalid channel mode: %i\n", mode); - return -EINVAL; - } - - /* Map b to g */ - if (mode == 2) - mode = 0; - else - mode = mode - 3; - - break; - default: + } else { return -EINVAL; } @@ -1540,10 +1439,6 @@ int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, ah->ah_rf_banks_size = sizeof(rfregs_2413); func = ath5k_hw_rf5413_rfregs; break; - case AR5K_RF2425: - ah->ah_rf_banks_size = sizeof(rfregs_2425); - func = ath5k_hw_rf5413_rfregs; - break; default: return -EINVAL; } @@ -1587,11 +1482,6 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) size = ARRAY_SIZE(rfgain_2413); freq = 0; /* only 2Ghz */ break; - case AR5K_RF2425: - ath5k_rfg = rfgain_2413; - size = ARRAY_SIZE(rfgain_2413); - freq = 0; /* only 2Ghz */ - break; default: return -EINVAL; } @@ -2291,11 +2181,8 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, * transmit anything if we call * this funtion, so we skip it * until we fix txpower. - * - * XXX: Assume same for RF2425 - * to be safe. */ - if ((ah->ah_radio == AR5K_RF2413) || (ah->ah_radio == AR5K_RF2425)) + if (ah->ah_radio == AR5K_RF2413) return 0; /* Reset TX power values */ diff --git a/trunk/drivers/net/wireless/ath5k/regdom.c b/trunk/drivers/net/wireless/ath5k/regdom.c new file mode 100644 index 000000000000..e851957dacfd --- /dev/null +++ b/trunk/drivers/net/wireless/ath5k/regdom.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2004, 2005 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Basic regulation domain extensions for the IEEE 802.11 stack + */ + +#include +#include + +#include "regdom.h" + +static const struct ath5k_regdommap { + enum ath5k_regdom dmn; + enum ath5k_regdom dmn5; + enum ath5k_regdom dmn2; +} r_map[] = { + { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG }, + { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD }, + { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB }, + { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC }, + { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA }, + { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD }, + { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA }, + { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD }, + { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC }, + { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 }, + { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD }, + { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD }, + { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD }, + { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD }, + { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD }, + { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD }, + { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC }, + { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD }, + { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD }, + { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 }, + { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA }, + { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA }, + { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD }, + { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA }, + { DMN_APL_NULL, DMN_APL1, DMN_NULL }, + { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD }, + { DMN_APL2_APLC, DMN_APL2, DMN_WORLD }, + { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD }, + { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA }, + { DMN_APL2_APLD, DMN_APL2, DMN_APLD }, + { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA }, + { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA }, + { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD }, + { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA }, + { DMN_APL1_APLA, DMN_APL1, DMN_WORLD }, + { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC }, + { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC }, + { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD }, + { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD }, + { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD }, + { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD }, + { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD }, + { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD }, + { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD }, + { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD }, + { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD }, + { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD }, + { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD }, + { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD }, +}; + +enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(r_map); i++) { + if (r_map[i].dmn == dmn) { + if (mhz >= 2000 && mhz <= 3000) + return r_map[i].dmn2; + if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN && + mhz <= IEEE80211_CHANNELS_5GHZ_MAX) + return r_map[i].dmn5; + } + } + + return DMN_DEBUG; +} + +u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee) +{ + u32 regdomain = (u32)ieee; + + /* + * Use the default regulation domain if the value is empty + * or not supported by the net80211 regulation code. + */ + if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) == + DMN_DEBUG) + return (u16)AR5K_TUNE_REGDOMAIN; + + /* It is supported, just return the value */ + return regdomain; +} + +enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain) +{ + enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain; + + return ieee; +} + diff --git a/trunk/drivers/net/wireless/ath5k/regdom.h b/trunk/drivers/net/wireless/ath5k/regdom.h new file mode 100644 index 000000000000..f7d3c66e594e --- /dev/null +++ b/trunk/drivers/net/wireless/ath5k/regdom.h @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2004, 2005 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _IEEE80211_REGDOMAIN_H_ +#define _IEEE80211_REGDOMAIN_H_ + +#include + +/* Default regulation domain if stored value EEPROM value is invalid */ +#define AR5K_TUNE_REGDOMAIN DMN_FCC2_FCCA /* Canada */ +#define AR5K_TUNE_CTRY CTRY_DEFAULT + + +enum ath5k_regdom { + DMN_DEFAULT = 0x00, + DMN_NULL_WORLD = 0x03, + DMN_NULL_ETSIB = 0x07, + DMN_NULL_ETSIC = 0x08, + DMN_FCC1_FCCA = 0x10, + DMN_FCC1_WORLD = 0x11, + DMN_FCC2_FCCA = 0x20, + DMN_FCC2_WORLD = 0x21, + DMN_FCC2_ETSIC = 0x22, + DMN_FRANCE_NULL = 0x31, + DMN_FCC3_FCCA = 0x3A, + DMN_ETSI1_WORLD = 0x37, + DMN_ETSI3_ETSIA = 0x32, + DMN_ETSI2_WORLD = 0x35, + DMN_ETSI3_WORLD = 0x36, + DMN_ETSI4_WORLD = 0x30, + DMN_ETSI4_ETSIC = 0x38, + DMN_ETSI5_WORLD = 0x39, + DMN_ETSI6_WORLD = 0x34, + DMN_ETSI_NULL = 0x33, + DMN_MKK1_MKKA = 0x40, + DMN_MKK1_MKKB = 0x41, + DMN_APL4_WORLD = 0x42, + DMN_MKK2_MKKA = 0x43, + DMN_APL_NULL = 0x44, + DMN_APL2_WORLD = 0x45, + DMN_APL2_APLC = 0x46, + DMN_APL3_WORLD = 0x47, + DMN_MKK1_FCCA = 0x48, + DMN_APL2_APLD = 0x49, + DMN_MKK1_MKKA1 = 0x4A, + DMN_MKK1_MKKA2 = 0x4B, + DMN_APL1_WORLD = 0x52, + DMN_APL1_FCCA = 0x53, + DMN_APL1_APLA = 0x54, + DMN_APL1_ETSIC = 0x55, + DMN_APL2_ETSIC = 0x56, + DMN_APL5_WORLD = 0x58, + DMN_WOR0_WORLD = 0x60, + DMN_WOR1_WORLD = 0x61, + DMN_WOR2_WORLD = 0x62, + DMN_WOR3_WORLD = 0x63, + DMN_WOR4_WORLD = 0x64, + DMN_WOR5_ETSIC = 0x65, + DMN_WOR01_WORLD = 0x66, + DMN_WOR02_WORLD = 0x67, + DMN_EU1_WORLD = 0x68, + DMN_WOR9_WORLD = 0x69, + DMN_WORA_WORLD = 0x6A, + + DMN_APL1 = 0xf0000001, + DMN_APL2 = 0xf0000002, + DMN_APL3 = 0xf0000004, + DMN_APL4 = 0xf0000008, + DMN_APL5 = 0xf0000010, + DMN_ETSI1 = 0xf0000020, + DMN_ETSI2 = 0xf0000040, + DMN_ETSI3 = 0xf0000080, + DMN_ETSI4 = 0xf0000100, + DMN_ETSI5 = 0xf0000200, + DMN_ETSI6 = 0xf0000400, + DMN_ETSIA = 0xf0000800, + DMN_ETSIB = 0xf0001000, + DMN_ETSIC = 0xf0002000, + DMN_FCC1 = 0xf0004000, + DMN_FCC2 = 0xf0008000, + DMN_FCC3 = 0xf0010000, + DMN_FCCA = 0xf0020000, + DMN_APLD = 0xf0040000, + DMN_MKK1 = 0xf0080000, + DMN_MKK2 = 0xf0100000, + DMN_MKKA = 0xf0200000, + DMN_NULL = 0xf0400000, + DMN_WORLD = 0xf0800000, + DMN_DEBUG = 0xf1000000 /* used for debugging */ +}; + +#define IEEE80211_DMN(_d) ((_d) & ~0xf0000000) + +enum ath5k_countrycode { + CTRY_DEFAULT = 0, /* Default domain (NA) */ + CTRY_ALBANIA = 8, /* Albania */ + CTRY_ALGERIA = 12, /* Algeria */ + CTRY_ARGENTINA = 32, /* Argentina */ + CTRY_ARMENIA = 51, /* Armenia */ + CTRY_AUSTRALIA = 36, /* Australia */ + CTRY_AUSTRIA = 40, /* Austria */ + CTRY_AZERBAIJAN = 31, /* Azerbaijan */ + CTRY_BAHRAIN = 48, /* Bahrain */ + CTRY_BELARUS = 112, /* Belarus */ + CTRY_BELGIUM = 56, /* Belgium */ + CTRY_BELIZE = 84, /* Belize */ + CTRY_BOLIVIA = 68, /* Bolivia */ + CTRY_BRAZIL = 76, /* Brazil */ + CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */ + CTRY_BULGARIA = 100, /* Bulgaria */ + CTRY_CANADA = 124, /* Canada */ + CTRY_CHILE = 152, /* Chile */ + CTRY_CHINA = 156, /* People's Republic of China */ + CTRY_COLOMBIA = 170, /* Colombia */ + CTRY_COSTA_RICA = 188, /* Costa Rica */ + CTRY_CROATIA = 191, /* Croatia */ + CTRY_CYPRUS = 196, /* Cyprus */ + CTRY_CZECH = 203, /* Czech Republic */ + CTRY_DENMARK = 208, /* Denmark */ + CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */ + CTRY_ECUADOR = 218, /* Ecuador */ + CTRY_EGYPT = 818, /* Egypt */ + CTRY_EL_SALVADOR = 222, /* El Salvador */ + CTRY_ESTONIA = 233, /* Estonia */ + CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */ + CTRY_FINLAND = 246, /* Finland */ + CTRY_FRANCE = 250, /* France */ + CTRY_FRANCE2 = 255, /* France2 */ + CTRY_GEORGIA = 268, /* Georgia */ + CTRY_GERMANY = 276, /* Germany */ + CTRY_GREECE = 300, /* Greece */ + CTRY_GUATEMALA = 320, /* Guatemala */ + CTRY_HONDURAS = 340, /* Honduras */ + CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */ + CTRY_HUNGARY = 348, /* Hungary */ + CTRY_ICELAND = 352, /* Iceland */ + CTRY_INDIA = 356, /* India */ + CTRY_INDONESIA = 360, /* Indonesia */ + CTRY_IRAN = 364, /* Iran */ + CTRY_IRAQ = 368, /* Iraq */ + CTRY_IRELAND = 372, /* Ireland */ + CTRY_ISRAEL = 376, /* Israel */ + CTRY_ITALY = 380, /* Italy */ + CTRY_JAMAICA = 388, /* Jamaica */ + CTRY_JAPAN = 392, /* Japan */ + CTRY_JAPAN1 = 393, /* Japan (JP1) */ + CTRY_JAPAN2 = 394, /* Japan (JP0) */ + CTRY_JAPAN3 = 395, /* Japan (JP1-1) */ + CTRY_JAPAN4 = 396, /* Japan (JE1) */ + CTRY_JAPAN5 = 397, /* Japan (JE2) */ + CTRY_JORDAN = 400, /* Jordan */ + CTRY_KAZAKHSTAN = 398, /* Kazakhstan */ + CTRY_KENYA = 404, /* Kenya */ + CTRY_KOREA_NORTH = 408, /* North Korea */ + CTRY_KOREA_ROC = 410, /* South Korea */ + CTRY_KOREA_ROC2 = 411, /* South Korea */ + CTRY_KUWAIT = 414, /* Kuwait */ + CTRY_LATVIA = 428, /* Latvia */ + CTRY_LEBANON = 422, /* Lebanon */ + CTRY_LIBYA = 434, /* Libya */ + CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */ + CTRY_LITHUANIA = 440, /* Lithuania */ + CTRY_LUXEMBOURG = 442, /* Luxembourg */ + CTRY_MACAU = 446, /* Macau */ + CTRY_MACEDONIA = 807, /* Republic of Macedonia */ + CTRY_MALAYSIA = 458, /* Malaysia */ + CTRY_MEXICO = 484, /* Mexico */ + CTRY_MONACO = 492, /* Principality of Monaco */ + CTRY_MOROCCO = 504, /* Morocco */ + CTRY_NETHERLANDS = 528, /* Netherlands */ + CTRY_NEW_ZEALAND = 554, /* New Zealand */ + CTRY_NICARAGUA = 558, /* Nicaragua */ + CTRY_NORWAY = 578, /* Norway */ + CTRY_OMAN = 512, /* Oman */ + CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */ + CTRY_PANAMA = 591, /* Panama */ + CTRY_PARAGUAY = 600, /* Paraguay */ + CTRY_PERU = 604, /* Peru */ + CTRY_PHILIPPINES = 608, /* Republic of the Philippines */ + CTRY_POLAND = 616, /* Poland */ + CTRY_PORTUGAL = 620, /* Portugal */ + CTRY_PUERTO_RICO = 630, /* Puerto Rico */ + CTRY_QATAR = 634, /* Qatar */ + CTRY_ROMANIA = 642, /* Romania */ + CTRY_RUSSIA = 643, /* Russia */ + CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */ + CTRY_SINGAPORE = 702, /* Singapore */ + CTRY_SLOVAKIA = 703, /* Slovak Republic */ + CTRY_SLOVENIA = 705, /* Slovenia */ + CTRY_SOUTH_AFRICA = 710, /* South Africa */ + CTRY_SPAIN = 724, /* Spain */ + CTRY_SRI_LANKA = 728, /* Sri Lanka */ + CTRY_SWEDEN = 752, /* Sweden */ + CTRY_SWITZERLAND = 756, /* Switzerland */ + CTRY_SYRIA = 760, /* Syria */ + CTRY_TAIWAN = 158, /* Taiwan */ + CTRY_THAILAND = 764, /* Thailand */ + CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */ + CTRY_TUNISIA = 788, /* Tunisia */ + CTRY_TURKEY = 792, /* Turkey */ + CTRY_UAE = 784, /* U.A.E. */ + CTRY_UKRAINE = 804, /* Ukraine */ + CTRY_UNITED_KINGDOM = 826, /* United Kingdom */ + CTRY_UNITED_STATES = 840, /* United States */ + CTRY_URUGUAY = 858, /* Uruguay */ + CTRY_UZBEKISTAN = 860, /* Uzbekistan */ + CTRY_VENEZUELA = 862, /* Venezuela */ + CTRY_VIET_NAM = 704, /* Viet Nam */ + CTRY_YEMEN = 887, /* Yemen */ + CTRY_ZIMBABWE = 716, /* Zimbabwe */ +}; + +#define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */ +#define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */ +#define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */ +#define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */ + +struct ath5k_regchannel { + u16 chan; + enum ath5k_regdom domain; + u32 mode; +}; + +#define IEEE80211_CHANNELS_2GHZ { \ +/*2412*/ { 1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2417*/ { 2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2422*/ { 3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2427*/ { 4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2432*/ { 5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2437*/ { 6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2442*/ { 7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2447*/ { 8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2452*/ { 9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2457*/ { 10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2462*/ { 11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2467*/ { 12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2472*/ { 13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ + \ +/*2432*/ { 5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2437*/ { 6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*2442*/ { 7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \ + \ +/*2412*/ { 1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2417*/ { 2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2422*/ { 3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2427*/ { 4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2432*/ { 5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2437*/ { 6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*2442*/ { 7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2447*/ { 8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2452*/ { 9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2457*/ { 10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2462*/ { 11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2467*/ { 12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2472*/ { 13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ + \ +/*2412*/ { 1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2417*/ { 2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2422*/ { 3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2427*/ { 4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2432*/ { 5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2437*/ { 6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*2442*/ { 7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2447*/ { 8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2452*/ { 9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2457*/ { 10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2462*/ { 11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ + \ +/*2412*/ { 1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2417*/ { 2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2422*/ { 3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2427*/ { 4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2432*/ { 5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2437*/ { 6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2442*/ { 7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2447*/ { 8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2452*/ { 9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2457*/ { 10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2462*/ { 11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2467*/ { 12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2472*/ { 13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2484*/ { 14, DMN_MKKA, CHANNEL_CCK }, \ + \ +/*2412*/ { 1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2417*/ { 2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2422*/ { 3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2427*/ { 4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2432*/ { 5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2437*/ { 6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*2442*/ { 7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2447*/ { 8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2452*/ { 9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2457*/ { 10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2462*/ { 11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2467*/ { 12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +/*2472*/ { 13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ +} + +#define IEEE80211_CHANNELS_5GHZ { \ +/*5745*/ { 149, DMN_APL1, CHANNEL_OFDM }, \ +/*5765*/ { 153, DMN_APL1, CHANNEL_OFDM }, \ +/*5785*/ { 157, DMN_APL1, CHANNEL_OFDM }, \ +/*5805*/ { 161, DMN_APL1, CHANNEL_OFDM }, \ +/*5825*/ { 165, DMN_APL1, CHANNEL_OFDM }, \ + \ +/*5745*/ { 149, DMN_APL2, CHANNEL_OFDM }, \ +/*5765*/ { 153, DMN_APL2, CHANNEL_OFDM }, \ +/*5785*/ { 157, DMN_APL2, CHANNEL_OFDM }, \ +/*5805*/ { 161, DMN_APL2, CHANNEL_OFDM }, \ + \ +/*5280*/ { 56, DMN_APL3, CHANNEL_OFDM }, \ +/*5300*/ { 60, DMN_APL3, CHANNEL_OFDM }, \ +/*5320*/ { 64, DMN_APL3, CHANNEL_OFDM }, \ +/*5745*/ { 149, DMN_APL3, CHANNEL_OFDM }, \ +/*5765*/ { 153, DMN_APL3, CHANNEL_OFDM }, \ +/*5785*/ { 157, DMN_APL3, CHANNEL_OFDM }, \ +/*5805*/ { 161, DMN_APL3, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_APL4, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_APL4, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_APL4, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_APL4, CHANNEL_OFDM }, \ +/*5745*/ { 149, DMN_APL4, CHANNEL_OFDM }, \ +/*5765*/ { 153, DMN_APL4, CHANNEL_OFDM }, \ +/*5785*/ { 157, DMN_APL4, CHANNEL_OFDM }, \ +/*5805*/ { 161, DMN_APL4, CHANNEL_OFDM }, \ +/*5825*/ { 165, DMN_APL4, CHANNEL_OFDM }, \ + \ +/*5745*/ { 149, DMN_APL5, CHANNEL_OFDM }, \ +/*5765*/ { 153, DMN_APL5, CHANNEL_OFDM }, \ +/*5785*/ { 157, DMN_APL5, CHANNEL_OFDM }, \ +/*5805*/ { 161, DMN_APL5, CHANNEL_OFDM }, \ +/*5825*/ { 165, DMN_APL5, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5260*/ { 52, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5280*/ { 56, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5300*/ { 60, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5320*/ { 64, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM }, \ +/*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_ETSI2, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_ETSI2, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_ETSI2, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_ETSI2, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_ETSI3, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_ETSI3, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_ETSI3, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_ETSI3, CHANNEL_OFDM }, \ +/*5260*/ { 52, DMN_ETSI3, CHANNEL_OFDM }, \ +/*5280*/ { 56, DMN_ETSI3, CHANNEL_OFDM }, \ +/*5300*/ { 60, DMN_ETSI3, CHANNEL_OFDM }, \ +/*5320*/ { 64, DMN_ETSI3, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_ETSI4, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_ETSI4, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_ETSI4, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_ETSI4, CHANNEL_OFDM }, \ +/*5260*/ { 52, DMN_ETSI4, CHANNEL_OFDM }, \ +/*5280*/ { 56, DMN_ETSI4, CHANNEL_OFDM }, \ +/*5300*/ { 60, DMN_ETSI4, CHANNEL_OFDM }, \ +/*5320*/ { 64, DMN_ETSI4, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_ETSI5, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_ETSI5, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_ETSI5, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_ETSI5, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5260*/ { 52, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5280*/ { 56, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM }, \ +/*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_FCC1, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_FCC1, CHANNEL_OFDM }, \ +/*5210*/ { 42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5220*/ { 44, DMN_FCC1, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_FCC1, CHANNEL_OFDM }, \ +/*5250*/ { 50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5260*/ { 52, DMN_FCC1, CHANNEL_OFDM }, \ +/*5280*/ { 56, DMN_FCC1, CHANNEL_OFDM }, \ +/*5290*/ { 58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5300*/ { 60, DMN_FCC1, CHANNEL_OFDM }, \ +/*5320*/ { 64, DMN_FCC1, CHANNEL_OFDM }, \ +/*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM }, \ +/*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM }, \ +/*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM }, \ +/*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM }, \ +/*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_FCC2, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_FCC2, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_FCC2, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_FCC2, CHANNEL_OFDM }, \ +/*5260*/ { 52, DMN_FCC2, CHANNEL_OFDM }, \ +/*5280*/ { 56, DMN_FCC2, CHANNEL_OFDM }, \ +/*5300*/ { 60, DMN_FCC2, CHANNEL_OFDM }, \ +/*5320*/ { 64, DMN_FCC2, CHANNEL_OFDM }, \ +/*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM }, \ +/*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM }, \ +/*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM }, \ +/*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM }, \ +/*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_FCC3, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_FCC3, CHANNEL_OFDM }, \ +/*5210*/ { 42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5220*/ { 44, DMN_FCC3, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_FCC3, CHANNEL_OFDM }, \ +/*5250*/ { 50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5260*/ { 52, DMN_FCC3, CHANNEL_OFDM }, \ +/*5280*/ { 56, DMN_FCC3, CHANNEL_OFDM }, \ +/*5290*/ { 58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5300*/ { 60, DMN_FCC3, CHANNEL_OFDM }, \ +/*5320*/ { 64, DMN_FCC3, CHANNEL_OFDM }, \ +/*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM }, \ +/*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM }, \ +/*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM }, \ +/*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM }, \ +/*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM }, \ +/*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM }, \ +/*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM }, \ +/*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM }, \ +/*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM }, \ +/*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM }, \ +/*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM }, \ +/*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM }, \ +/*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM }, \ +/*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM }, \ +/*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ +/*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM }, \ +/*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM }, \ + \ +/*5170*/ { 34, DMN_MKK1, CHANNEL_OFDM }, \ +/*5190*/ { 38, DMN_MKK1, CHANNEL_OFDM }, \ +/*5210*/ { 42, DMN_MKK1, CHANNEL_OFDM }, \ +/*5230*/ { 46, DMN_MKK1, CHANNEL_OFDM }, \ + \ +/*5040*/ { 8, DMN_MKK2, CHANNEL_OFDM }, \ +/*5060*/ { 12, DMN_MKK2, CHANNEL_OFDM }, \ +/*5080*/ { 16, DMN_MKK2, CHANNEL_OFDM }, \ +/*5170*/ { 34, DMN_MKK2, CHANNEL_OFDM }, \ +/*5190*/ { 38, DMN_MKK2, CHANNEL_OFDM }, \ +/*5210*/ { 42, DMN_MKK2, CHANNEL_OFDM }, \ +/*5230*/ { 46, DMN_MKK2, CHANNEL_OFDM }, \ + \ +/*5180*/ { 36, DMN_WORLD, CHANNEL_OFDM }, \ +/*5200*/ { 40, DMN_WORLD, CHANNEL_OFDM }, \ +/*5220*/ { 44, DMN_WORLD, CHANNEL_OFDM }, \ +/*5240*/ { 48, DMN_WORLD, CHANNEL_OFDM }, \ +} + +enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16); +u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee); +enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain); + +#endif diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index cf5c046c9fa8..345c34bdae9a 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -2343,13 +2343,6 @@ static void b43_mac_suspend(struct b43_wldev *dev) & ~B43_MACCTL_ENABLED); /* force pci to flush the write */ b43_read32(dev, B43_MMIO_MACCTL); - for (i = 35; i; i--) { - tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); - if (tmp & B43_IRQ_MAC_SUSPENDED) - goto out; - udelay(10); - } - /* Hm, it seems this will take some time. Use msleep(). */ for (i = 40; i; i--) { tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); if (tmp & B43_IRQ_MAC_SUSPENDED) diff --git a/trunk/drivers/net/wireless/b43legacy/b43legacy.h b/trunk/drivers/net/wireless/b43legacy/b43legacy.h index ded3cd31b3df..242b8ad4e33c 100644 --- a/trunk/drivers/net/wireless/b43legacy/b43legacy.h +++ b/trunk/drivers/net/wireless/b43legacy/b43legacy.h @@ -97,7 +97,6 @@ #define B43legacy_MMIO_RADIO_HWENABLED_LO 0x49A #define B43legacy_MMIO_GPIO_CONTROL 0x49C #define B43legacy_MMIO_GPIO_MASK 0x49E -#define B43legacy_MMIO_TSF_CFP_PRETBTT 0x612 #define B43legacy_MMIO_TSF_0 0x632 /* core rev < 3 only */ #define B43legacy_MMIO_TSF_1 0x634 /* core rev < 3 only */ #define B43legacy_MMIO_TSF_2 0x636 /* core rev < 3 only */ @@ -150,8 +149,6 @@ #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ #define B43legacy_SHM_SH_UCODEDATE 0x0004 /* Microcode date */ #define B43legacy_SHM_SH_UCODETIME 0x0006 /* Microcode time */ -#define B43legacy_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */ -#define B43legacy_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */ #define B43legacy_UCODEFLAGS_OFFSET 0x005E diff --git a/trunk/drivers/net/wireless/b43legacy/main.c b/trunk/drivers/net/wireless/b43legacy/main.c index 2422a5dab1d2..f518e796bdec 100644 --- a/trunk/drivers/net/wireless/b43legacy/main.c +++ b/trunk/drivers/net/wireless/b43legacy/main.c @@ -3005,34 +3005,6 @@ static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev, b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); } -static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, - bool idle) { - u16 pu_delay = 1050; - - if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle) - pu_delay = 500; - if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) - pu_delay = max(pu_delay, (u16)2400); - - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_SPUWKUP, pu_delay); -} - -/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */ -static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev) -{ - u16 pretbtt; - - /* The time value is in microseconds. */ - if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) - pretbtt = 2; - else - pretbtt = 250; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_PRETBTT, pretbtt); - b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt); -} - /* Shutdown a wireless core */ /* Locking: wl->mutex */ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) @@ -3219,7 +3191,9 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) if (err) goto err_chip_exit; - b43legacy_set_synth_pu_delay(dev, 1); + b43legacy_write16(dev, 0x0612, 0x0050); + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0416, 0x0050); + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ b43legacy_upload_card_macaddress(dev); @@ -3275,8 +3249,6 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, spin_lock_irqsave(&wl->irq_lock, flags); b43legacy_adjust_opmode(dev); - b43legacy_set_pretbtt(dev); - b43legacy_set_synth_pu_delay(dev, 0); b43legacy_upload_card_macaddress(dev); spin_unlock_irqrestore(&wl->irq_lock, flags); diff --git a/trunk/drivers/net/wireless/iwlwifi/Kconfig b/trunk/drivers/net/wireless/iwlwifi/Kconfig index f844b738d34e..bcaa61b7c563 100644 --- a/trunk/drivers/net/wireless/iwlwifi/Kconfig +++ b/trunk/drivers/net/wireless/iwlwifi/Kconfig @@ -6,7 +6,7 @@ config IWLWIFI_LEDS bool default n -config IWLWIFI_RFKILL +config IWLCORE_RFKILL boolean "IWLWIFI RF kill support" depends on IWLCORE select RFKILL diff --git a/trunk/drivers/net/wireless/iwlwifi/Makefile b/trunk/drivers/net/wireless/iwlwifi/Makefile index 4f3e88b12e3a..2751e8aa97d7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/Makefile +++ b/trunk/drivers/net/wireless/iwlwifi/Makefile @@ -1,13 +1,26 @@ -obj-$(CONFIG_IWLCORE) := iwlcore.o -iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o -iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o -iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o -iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o +obj-$(CONFIG_IWLCORE) += iwlcore.o +iwlcore-objs = iwl-core.o iwl-eeprom.o iwl-hcmd.o + +ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y) + iwlcore-objs += iwl-debugfs.o +endif + +ifeq ($(CONFIG_IWLWIFI_LEDS),y) + iwlcore-objs += iwl-led.o +endif + +ifeq ($(CONFIG_IWLCORE_RFKILL),y) + iwlcore-objs += iwl-rfkill.o +endif obj-$(CONFIG_IWL3945) += iwl3945.o -iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o -iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o +iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o + +ifeq ($(CONFIG_IWL3945_LEDS),y) + iwl3945-objs += iwl-3945-led.o +endif + obj-$(CONFIG_IWL4965) += iwl4965.o -iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o +iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index ad612a8719f4..368da9852aab 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -456,7 +456,7 @@ struct iwl3945_eeprom { /* Size of uCode instruction memory in bootstrap state machine */ #define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE -#define IWL39_MAX_NUM_QUEUES 8 +#define IWL_MAX_NUM_QUEUES 8 static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h b/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h index 45c1c5533bf0..3dc7f0fbf02f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -687,8 +687,6 @@ enum { #endif -#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES - struct iwl3945_priv { /* ieee device used by generic ieee processing code */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/trunk/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 3bcd107e2d71..7e36ecb27575 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -84,9 +84,6 @@ enum { REPLY_REMOVE_STA = 0x19, /* not used */ REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ - /* Security */ - REPLY_WEPKEY = 0x20, - /* RX, TX, LEDs */ REPLY_TX = 0x1c, REPLY_RATE_SCALE = 0x47, /* 3945 only */ @@ -269,10 +266,11 @@ struct iwl_cmd_header { * 10 B active, A inactive * 11 Both active */ -#define RATE_MCS_ANT_POS 14 -#define RATE_MCS_ANT_A_MSK 0x04000 -#define RATE_MCS_ANT_B_MSK 0x08000 -#define RATE_MCS_ANT_AB_MSK 0x0C000 +#define RATE_MCS_ANT_A_POS 14 +#define RATE_MCS_ANT_B_POS 15 +#define RATE_MCS_ANT_A_MSK 0x4000 +#define RATE_MCS_ANT_B_MSK 0x8000 +#define RATE_MCS_ANT_AB_MSK 0xc000 /** @@ -852,30 +850,6 @@ struct iwl4965_add_sta_resp { u8 status; /* ADD_STA_* */ } __attribute__ ((packed)); -/* - * REPLY_WEP_KEY = 0x20 - */ -struct iwl_wep_key { - u8 key_index; - u8 key_offset; - u8 reserved1[2]; - u8 key_size; - u8 reserved2[3]; - u8 key[16]; -} __attribute__ ((packed)); - -struct iwl_wep_cmd { - u8 num_keys; - u8 global_key_type; - u8 flags; - u8 reserved; - struct iwl_wep_key key[0]; -} __attribute__ ((packed)); - -#define WEP_KEY_WEP_TYPE 1 -#define WEP_KEYS_MAX 4 -#define WEP_INVALID_OFFSET 0xff -#define WEP_KEY_LEN_128 13 /****************************************************************************** * (4) @@ -1413,11 +1387,11 @@ struct iwl4965_txpowertable_cmd { /** - * struct iwl_link_qual_general_params + * struct iwl4965_link_qual_general_params * * Used in REPLY_TX_LINK_QUALITY_CMD */ -struct iwl_link_qual_general_params { +struct iwl4965_link_qual_general_params { u8 flags; /* No entries at or above this (driver chosen) index contain MIMO */ @@ -1444,11 +1418,11 @@ struct iwl_link_qual_general_params { } __attribute__ ((packed)); /** - * struct iwl_link_qual_agg_params + * struct iwl4965_link_qual_agg_params * * Used in REPLY_TX_LINK_QUALITY_CMD */ -struct iwl_link_qual_agg_params { +struct iwl4965_link_qual_agg_params { /* Maximum number of uSec in aggregation. * Driver should set this to 4000 (4 milliseconds). */ @@ -1658,14 +1632,14 @@ struct iwl_link_qual_agg_params { * legacy), and then repeat the search process. * */ -struct iwl_link_quality_cmd { +struct iwl4965_link_quality_cmd { /* Index of destination/recipient station in uCode's station table */ u8 sta_id; u8 reserved1; __le16 control; /* not used */ - struct iwl_link_qual_general_params general_params; - struct iwl_link_qual_agg_params agg_params; + struct iwl4965_link_qual_general_params general_params; + struct iwl4965_link_qual_agg_params agg_params; /* * Rate info; when using rate-scaling, Tx command's initial_rate_index diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 1a66b508a8ea..de7bac149723 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -1385,10 +1385,10 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags) * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array * in DRAM containing 256 Transmit Frame Descriptors (TFDs). */ -#define IWL4965_MAX_WIN_SIZE 64 -#define IWL4965_QUEUE_SIZE 256 -#define IWL4965_NUM_FIFOS 7 -#define IWL4965_MAX_NUM_QUEUES 16 +#define IWL4965_MAX_WIN_SIZE 64 +#define IWL4965_QUEUE_SIZE 256 +#define IWL4965_NUM_FIFOS 7 +#define IWL_MAX_NUM_QUEUES 16 /** @@ -1553,30 +1553,30 @@ struct iwl4965_sched_queue_byte_cnt_tbl { */ struct iwl4965_shared { struct iwl4965_sched_queue_byte_cnt_tbl - queues_byte_cnt_tbls[IWL4965_MAX_NUM_QUEUES]; - __le32 rb_closed; + queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES]; + __le32 val0; /* __le32 rb_closed_stts_rb_num:12; */ #define IWL_rb_closed_stts_rb_num_POS 0 #define IWL_rb_closed_stts_rb_num_LEN 12 -#define IWL_rb_closed_stts_rb_num_SYM rb_closed +#define IWL_rb_closed_stts_rb_num_SYM val0 /* __le32 rsrv1:4; */ /* __le32 rb_closed_stts_rx_frame_num:12; */ #define IWL_rb_closed_stts_rx_frame_num_POS 16 #define IWL_rb_closed_stts_rx_frame_num_LEN 12 -#define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed +#define IWL_rb_closed_stts_rx_frame_num_SYM val0 /* __le32 rsrv2:4; */ - __le32 frm_finished; + __le32 val1; /* __le32 frame_finished_stts_rb_num:12; */ #define IWL_frame_finished_stts_rb_num_POS 0 #define IWL_frame_finished_stts_rb_num_LEN 12 -#define IWL_frame_finished_stts_rb_num_SYM frm_finished +#define IWL_frame_finished_stts_rb_num_SYM val1 /* __le32 rsrv3:4; */ /* __le32 frame_finished_stts_rx_frame_num:12; */ #define IWL_frame_finished_stts_rx_frame_num_POS 16 #define IWL_frame_finished_stts_rx_frame_num_LEN 12 -#define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished +#define IWL_frame_finished_stts_rx_frame_num_SYM val1 /* __le32 rsrv4:4; */ __le32 padding1; /* so that allocation will be aligned to 16B */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index b608e1ca8b40..315b0433801e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -150,7 +150,7 @@ struct iwl4965_lq_sta { u16 active_mimo_rate; u16 active_rate_basic; - struct iwl_link_quality_cmd lq; + struct iwl4965_link_quality_cmd lq; struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ #ifdef CONFIG_IWL4965_HT struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT]; @@ -173,7 +173,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, struct sta_info *sta); static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, struct iwl4965_rate *tx_mcs, - struct iwl_link_quality_cmd *tbl); + struct iwl4965_link_quality_cmd *tbl); #ifdef CONFIG_MAC80211_DEBUGFS @@ -230,11 +230,58 @@ static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 }; +static int iwl4965_lq_sync_callback(struct iwl_priv *priv, + struct iwl_cmd *cmd, struct sk_buff *skb) +{ + /*We didn't cache the SKB; let the caller free it */ + return 1; +} + static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags) { return (u8)(rate_n_flags & 0xFF); } +static int rs_send_lq_cmd(struct iwl_priv *priv, + struct iwl4965_link_quality_cmd *lq, u8 flags) +{ +#ifdef CONFIG_IWLWIFI_DEBUG + int i; +#endif + struct iwl_host_cmd cmd = { + .id = REPLY_TX_LINK_QUALITY_CMD, + .len = sizeof(struct iwl4965_link_quality_cmd), + .meta.flags = flags, + .data = lq, + }; + + if ((lq->sta_id == 0xFF) && + (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) + return -EINVAL; + + if (lq->sta_id == 0xFF) + lq->sta_id = IWL_AP_ID; + + IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id); + IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n", + lq->general_params.single_stream_ant_msk, + lq->general_params.dual_stream_ant_msk); +#ifdef CONFIG_IWLWIFI_DEBUG + for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) + IWL_DEBUG_RATE("lq index %d 0x%X\n", + i, lq->rs_table[i].rate_n_flags); +#endif + + if (flags & CMD_ASYNC) + cmd.meta.u.callback = iwl4965_lq_sync_callback; + + if (iwl_is_associated(priv) && priv->assoc_station_added && + priv->lq_mngr.lq_ready) + return iwl_send_cmd(priv, &cmd); + + return 0; +} + static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) { window->data = 0; @@ -772,7 +819,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, u8 retries; int rs_index, index = 0; struct iwl4965_lq_sta *lq_sta; - struct iwl_link_quality_cmd *table; + struct iwl4965_link_quality_cmd *table; struct sta_info *sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct iwl_priv *priv = (struct iwl_priv *)priv_rate; @@ -1832,7 +1879,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (update_lq) { rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); } goto out; @@ -1997,7 +2044,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (update_lq) { rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); } /* Should we stay with this modulation mode, or search for a new one? */ @@ -2037,7 +2084,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, tbl->current_rate.rate_n_flags, index); rs_fill_link_cmd(lq_sta, &tbl->current_rate, &lq_sta->lq); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); } /* If the "active" (non-search) mode was legacy, @@ -2150,7 +2197,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags; rs_get_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); out: return; } @@ -2345,7 +2392,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, struct iwl4965_rate *tx_mcs, - struct iwl_link_quality_cmd *lq_cmd) + struct iwl4965_link_quality_cmd *lq_cmd) { int index = 0; int rate_idx; @@ -2544,7 +2591,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, if (lq_sta->dbg_fixed.rate_n_flags) { rs_fill_link_cmd(lq_sta, &lq_sta->dbg_fixed, &lq_sta->lq); - iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); + rs_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); } return count; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c index 17f629fb96ff..472ca3d7e034 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -46,7 +46,7 @@ /* module parameters */ static struct iwl_mod_params iwl4965_mod_params = { - .num_of_queues = IWL4965_MAX_NUM_QUEUES, + .num_of_queues = IWL_MAX_NUM_QUEUES, .enable_qos = 1, .amsdu_size_8K = 1, /* the rest are 0 by default */ @@ -114,151 +114,6 @@ static const u16 default_tid_to_tx_fifo[] = { #endif /*CONFIG_IWL4965_HT */ -/* check contents of special bootstrap uCode SRAM */ -static int iwl4965_verify_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - u32 reg; - u32 val; - - IWL_DEBUG_INFO("Begin verify bsm\n"); - - /* verify BSM SRAM contents */ - val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); - for (reg = BSM_SRAM_LOWER_BOUND; - reg < BSM_SRAM_LOWER_BOUND + len; - reg += sizeof(u32), image++) { - val = iwl_read_prph(priv, reg); - if (val != le32_to_cpu(*image)) { - IWL_ERROR("BSM uCode verification failed at " - "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", - BSM_SRAM_LOWER_BOUND, - reg - BSM_SRAM_LOWER_BOUND, len, - val, le32_to_cpu(*image)); - return -EIO; - } - } - - IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); - - return 0; -} - -/** - * iwl4965_load_bsm - Load bootstrap instructions - * - * BSM operation: - * - * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program - * in special SRAM that does not power down during RFKILL. When powering back - * up after power-saving sleeps (or during initial uCode load), the BSM loads - * the bootstrap program into the on-board processor, and starts it. - * - * The bootstrap program loads (via DMA) instructions and data for a new - * program from host DRAM locations indicated by the host driver in the - * BSM_DRAM_* registers. Once the new program is loaded, it starts - * automatically. - * - * When initializing the NIC, the host driver points the BSM to the - * "initialize" uCode image. This uCode sets up some internal data, then - * notifies host via "initialize alive" that it is complete. - * - * The host then replaces the BSM_DRAM_* pointer values to point to the - * normal runtime uCode instructions and a backup uCode data cache buffer - * (filled initially with starting data values for the on-board processor), - * then triggers the "initialize" uCode to load and launch the runtime uCode, - * which begins normal operation. - * - * When doing a power-save shutdown, runtime uCode saves data SRAM into - * the backup data cache in DRAM before SRAM is powered down. - * - * When powering back up, the BSM loads the bootstrap program. This reloads - * the runtime uCode instructions and the backup data cache into SRAM, - * and re-launches the runtime uCode from where it left off. - */ -static int iwl4965_load_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - dma_addr_t pinst; - dma_addr_t pdata; - u32 inst_len; - u32 data_len; - int i; - u32 done; - u32 reg_offset; - int ret; - - IWL_DEBUG_INFO("Begin load bsm\n"); - - /* make sure bootstrap program is no larger than BSM's SRAM size */ - if (len > IWL_MAX_BSM_SIZE) - return -EINVAL; - - /* Tell bootstrap uCode where to find the "Initialize" uCode - * in host DRAM ... host DRAM physical address bits 35:4 for 4965. - * NOTE: iwl4965_initialize_alive_start() will replace these values, - * after the "initialize" uCode has run, to point to - * runtime/protocol instructions and backup data cache. */ - pinst = priv->ucode_init.p_addr >> 4; - pdata = priv->ucode_init_data.p_addr >> 4; - inst_len = priv->ucode_init.len; - data_len = priv->ucode_init_data.len; - - ret = iwl_grab_nic_access(priv); - if (ret) - return ret; - - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); - iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); - - /* Fill BSM memory with bootstrap instructions */ - for (reg_offset = BSM_SRAM_LOWER_BOUND; - reg_offset < BSM_SRAM_LOWER_BOUND + len; - reg_offset += sizeof(u32), image++) - _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); - - ret = iwl4965_verify_bsm(priv); - if (ret) { - iwl_release_nic_access(priv); - return ret; - } - - /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ - iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); - iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND); - iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); - - /* Load bootstrap code into instruction SRAM now, - * to prepare to load "initialize" uCode */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START); - - /* Wait for load of bootstrap uCode to finish */ - for (i = 0; i < 100; i++) { - done = iwl_read_prph(priv, BSM_WR_CTRL_REG); - if (!(done & BSM_WR_CTRL_REG_BIT_START)) - break; - udelay(10); - } - if (i < 100) - IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); - else { - IWL_ERROR("BSM write did not complete!\n"); - return -EIO; - } - - /* Enable future boot loads whenever power management unit triggers it - * (e.g. when powering back up after power-save shutdown) */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); - - iwl_release_nic_access(priv); - - return 0; -} - static int iwl4965_init_drv(struct iwl_priv *priv) { int ret; @@ -274,18 +129,6 @@ static int iwl4965_init_drv(struct iwl_priv *priv) spin_lock_init(&priv->hcmd_lock); spin_lock_init(&priv->lq_mngr.lock); - priv->shared_virt = pci_alloc_consistent(priv->pci_dev, - sizeof(struct iwl4965_shared), - &priv->shared_phys); - - if (!priv->shared_virt) { - ret = -ENOMEM; - goto err; - } - - memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared)); - - for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); @@ -410,7 +253,7 @@ void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, int rate_index; control->antenna_sel_tx = - ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS); + ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_A_POS); if (rate_n_flags & RATE_MCS_HT_MSK) control->flags |= IEEE80211_TXCTL_OFDM_HT; if (rate_n_flags & RATE_MCS_GF_MSK) @@ -504,10 +347,10 @@ u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *addr) start = IWL_STA_ID; if (is_broadcast_ether_addr(addr)) - return priv->hw_params.bcast_sta_id; + return priv->hw_setting.bcast_sta_id; spin_lock_irqsave(&priv->sta_lock, flags); - for (i = start; i < priv->hw_params.max_stations; i++) + for (i = start; i < priv->hw_setting.max_stations; i++) if ((priv->stations[i].used) && (!compare_ether_addr (priv->stations[i].sta.sta.addr, addr))) { @@ -558,15 +401,15 @@ static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) { - int ret; + int rc; unsigned long flags; unsigned int rb_size; spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { + rc = iwl_grab_nic_access(priv); + if (rc) { spin_unlock_irqrestore(&priv->lock, flags); - return ret; + return rc; } if (priv->cfg->mod_params->amsdu_size_8K) @@ -586,15 +429,15 @@ static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) /* Tell device where in DRAM to update its Rx status */ iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, - (priv->shared_phys + - offsetof(struct iwl4965_shared, rb_closed)) >> 4); + (priv->hw_setting.shared_phys + + offsetof(struct iwl4965_shared, val0)) >> 4); /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | rb_size | - /* 0x10 << 4 | */ + /*0x10 << 4 | */ (RX_QUEUE_SIZE_LOG << FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); @@ -702,7 +545,7 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) /* Alloc and init all (default 16) Tx queues, * including the command queue (#4) */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num, @@ -908,7 +751,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) unsigned long flags; /* Stop each Tx DMA channel, and wait for it to be idle */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { spin_lock_irqsave(&priv->lock, flags); if (iwl_grab_nic_access(priv)) { spin_unlock_irqrestore(&priv->lock, flags); @@ -976,21 +819,40 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv) /** * iwl4965_bg_statistics_periodic - Timer callback to queue statistics * - * This callback is provided in order to send a statistics request. + * This callback is provided in order to queue the statistics_work + * in work_queue context (v. softirq) * * This timer function is continually reset to execute within * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION * was received. We need to ensure we receive the statistics in order - * to update the temperature used for calibrating the TXPOWER. + * to update the temperature used for calibrating the TXPOWER. However, + * we can't send the statistics command from softirq context (which + * is the context which timers run at) so we have to queue off the + * statistics_work to actually send the command to the hardware. */ static void iwl4965_bg_statistics_periodic(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; + queue_work(priv->workqueue, &priv->statistics_work); +} + +/** + * iwl4965_bg_statistics_work - Send the statistics request to the hardware. + * + * This is queued by iwl4965_bg_statistics_periodic. + */ +static void iwl4965_bg_statistics_work(struct work_struct *work) +{ + struct iwl_priv *priv = container_of(work, struct iwl_priv, + statistics_work); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - iwl_send_statistics_request(priv, CMD_ASYNC); + mutex_lock(&priv->mutex); + iwl4965_send_statistics_request(priv); + mutex_unlock(&priv->mutex); } #define CT_LIMIT_CONST 259 @@ -1954,19 +1816,19 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl_write_targ_mem(priv, a, 0); for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4) iwl_write_targ_mem(priv, a, 0); - for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) + for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4) iwl_write_targ_mem(priv, a, 0); /* Tel 4965 where to find Tx byte count tables */ iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, - (priv->shared_phys + + (priv->hw_setting.shared_phys + offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10); /* Disable chain mode for all queues */ iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); /* Initialize each Tx queue (including the command queue) */ - for (i = 0; i < priv->hw_params.max_txq_num; i++) { + for (i = 0; i < priv->hw_setting.max_txq_num; i++) { /* TFD circular buffer read/write indexes */ iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0); @@ -1989,7 +1851,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) } iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK, - (1 << priv->hw_params.max_txq_num) - 1); + (1 << priv->hw_setting.max_txq_num) - 1); /* Activate all Tx DMA/FIFO channels */ iwl_write_prph(priv, IWL49_SCD_TXFACT, @@ -2007,45 +1869,55 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); - /* Ask for statistics now, the uCode will send statistics notification - * periodically after association */ - iwl_send_statistics_request(priv, CMD_ASYNC); return ret; } /** - * iwl4965_hw_set_hw_params + * iwl4965_hw_set_hw_setting * * Called when initializing driver */ -int iwl4965_hw_set_hw_params(struct iwl_priv *priv) +int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) { + int ret = 0; - if ((priv->cfg->mod_params->num_of_queues > IWL4965_MAX_NUM_QUEUES) || + if ((priv->cfg->mod_params->num_of_queues > IWL_MAX_NUM_QUEUES) || (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL4965_MAX_NUM_QUEUES); - return -EINVAL; + IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); + ret = -EINVAL; + goto out; + } + + /* Allocate area for Tx byte count tables and Rx queue status */ + priv->hw_setting.shared_virt = + pci_alloc_consistent(priv->pci_dev, + sizeof(struct iwl4965_shared), + &priv->hw_setting.shared_phys); + + if (!priv->hw_setting.shared_virt) { + ret = -ENOMEM; + goto out; } - priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; - priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); - priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; - priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; + memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared)); + + priv->hw_setting.max_txq_num = priv->cfg->mod_params->num_of_queues; + priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); + priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE; + priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG; if (priv->cfg->mod_params->amsdu_size_8K) - priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; + priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K; else - priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; - priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; - priv->hw_params.max_stations = IWL4965_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; + priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K; + priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256; + priv->hw_setting.max_stations = IWL4965_STATION_COUNT; + priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID; - priv->hw_params.tx_chains_num = 2; - priv->hw_params.rx_chains_num = 2; - priv->hw_params.valid_tx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX); - priv->hw_params.valid_rx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX); + priv->hw_setting.tx_ant_num = 2; - return 0; +out: + return ret; } /** @@ -2058,7 +1930,7 @@ void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv) int txq_id; /* Tx queues */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) iwl4965_tx_queue_free(priv, &priv->txq[txq_id]); /* Keep-warm buffer */ @@ -2884,46 +2756,6 @@ int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv) return ret; } -static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) -{ - int ret = 0; - struct iwl4965_rxon_assoc_cmd rxon_assoc; - const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_ht_single_stream_basic_rates == - rxon2->ofdm_ht_single_stream_basic_rates) && - (rxon1->ofdm_ht_dual_stream_basic_rates == - rxon2->ofdm_ht_dual_stream_basic_rates) && - (rxon1->rx_chain == rxon2->rx_chain) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; - rxon_assoc.reserved = 0; - rxon_assoc.ofdm_ht_single_stream_basic_rates = - priv->staging_rxon.ofdm_ht_single_stream_basic_rates; - rxon_assoc.ofdm_ht_dual_stream_basic_rates = - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; - - ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, - sizeof(rxon_assoc), &rxon_assoc, NULL); - if (ret) - return ret; - - return ret; -} - - int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) { int rc; @@ -3037,8 +2869,9 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, int iwl4965_hw_get_rx_read(struct iwl_priv *priv) { - struct iwl4965_shared *s = priv->shared_virt; - return le32_to_cpu(s->rb_closed) & 0xFFF; + struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt; + + return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num); } int iwl4965_hw_get_temperature(struct iwl_priv *priv) @@ -3055,7 +2888,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, tx_beacon_cmd = &frame->u.beacon; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; + tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; frame_size = iwl4965_fill_beacon_frame(priv, @@ -3163,15 +2996,17 @@ static void iwl4965_hw_card_show_info(struct iwl_priv *priv) #define IWL_TX_DELIMITER_SIZE 4 /** - * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array + * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array */ -static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl4965_tx_queue *txq, - u16 byte_cnt) +int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, + struct iwl4965_tx_queue *txq, u16 byte_cnt) { int len; int txq_id = txq->q.id; - struct iwl4965_shared *shared_data = priv->shared_virt; + struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt; + + if (txq->need_update == 0) + return 0; len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; @@ -3184,6 +3019,8 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr], byte_cnt, len); + + return 0; } /** @@ -3663,7 +3500,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, rx_start->byte_count = amsdu->byte_count; rx_end = (__le32 *) (((u8 *) hdr) + len); } - if (len > priv->hw_params.max_pkt_size || len < 16) { + if (len > priv->hw_setting.max_pkt_size || len < 16) { IWL_WARNING("byte count out of range [16,4K] : %d\n", len); return; } @@ -3691,7 +3528,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, stats->flag = 0; hdr = (struct ieee80211_hdr *)rxb->skb->data; - if (!priv->cfg->mod_params->sw_crypto) + if (priv->cfg->mod_params->hw_crypto) iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); if (priv->add_radiotap) @@ -4362,7 +4199,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv, * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - if (scd_flow >= priv->hw_params.max_txq_num) { + if (scd_flow >= ARRAY_SIZE(priv->txq)) { IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); return; } @@ -4524,7 +4361,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) { int i, r; - struct iwl_link_quality_cmd link_cmd = { + struct iwl4965_link_quality_cmd link_cmd = { .reserved1 = 0, }; u16 rate_flags; @@ -4558,7 +4395,7 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000); /* Update the rate scaling for control frame Tx to AP */ - link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; + link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_setting.bcast_sta_id; iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), &link_cmd, NULL); @@ -4747,7 +4584,7 @@ static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv) { int txq_id; - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) return txq_id; return -1; @@ -4930,6 +4767,7 @@ void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv) void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv) { INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); + INIT_WORK(&priv->statistics_work, iwl4965_bg_statistics_work); #ifdef CONFIG_IWL4965_SENSITIVITY INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work); #endif @@ -4945,23 +4783,12 @@ void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->init_alive_start); } - -static struct iwl_hcmd_ops iwl4965_hcmd = { - .rxon_assoc = iwl4965_send_rxon_assoc, -}; - static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .enqueue_hcmd = iwl4965_enqueue_hcmd, }; static struct iwl_lib_ops iwl4965_lib = { .init_drv = iwl4965_init_drv, - .set_hw_params = iwl4965_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, - .hw_nic_init = iwl4965_hw_nic_init, - .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, - .alive_notify = iwl4965_alive_notify, - .load_ucode = iwl4965_load_bsm, .eeprom_ops = { .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, @@ -4972,11 +4799,10 @@ static struct iwl_lib_ops iwl4965_lib = { static struct iwl_ops iwl4965_ops = { .lib = &iwl4965_lib, - .hcmd = &iwl4965_hcmd, .utils = &iwl4965_hcmd_utils, }; -struct iwl_cfg iwl4965_agn_cfg = { +static struct iwl_cfg iwl4965_agn_cfg = { .name = "4965AGN", .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, @@ -4984,12 +4810,21 @@ struct iwl_cfg iwl4965_agn_cfg = { .mod_params = &iwl4965_mod_params, }; +struct pci_device_id iwl4965_hw_card_ids[] = { + {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, + {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids); + module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(disable, iwl4965_mod_params.disable, int, 0444); MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); -module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); -MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n"); +module_param_named(hwcrypto, iwl4965_mod_params.hw_crypto, int, 0444); +MODULE_PARM_DESC(hwcrypto, + "using hardware crypto engine (default 0 [software])\n"); module_param_named(debug, iwl4965_mod_params.debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); module_param_named( diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.h b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.h index 9ed13cb0a2a9..65e536782706 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -36,6 +36,9 @@ #include #include +/* Hardware specific file defines the PCI IDs table for that hardware module */ +extern struct pci_device_id iwl4965_hw_card_ids[]; + #define DRV_NAME "iwl4965" #include "iwl-rfkill.h" #include "iwl-eeprom.h" @@ -45,9 +48,6 @@ #include "iwl-debug.h" #include "iwl-led.h" -/* configuration for the iwl4965 */ -extern struct iwl_cfg iwl4965_agn_cfg; - /* Change firmware file name, using "-" and incrementing number, * *only* when uCode interface or architecture changes so that it * is not compatible with earlier drivers. @@ -461,7 +461,6 @@ struct iwl4965_tid_data { struct iwl4965_hw_key { enum ieee80211_key_alg alg; int keylen; - u8 keyidx; struct ieee80211_key_conf *conf; u8 key[32]; }; @@ -567,7 +566,7 @@ struct iwl4965_ibss_seq { }; /** - * struct iwl_hw_params + * struct iwl4965_driver_hw_info * @max_txq_num: Max # Tx queues supported * @tx_cmd_len: Size of Tx command (but not including frame itself) * @tx_ant_num: Number of TX antennas @@ -576,20 +575,21 @@ struct iwl4965_ibss_seq { * @max_rxq_log: Log-base-2 of max_rxq_size * @max_stations: * @bcast_sta_id: + * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status + * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status */ -struct iwl_hw_params { +struct iwl4965_driver_hw_info { u16 max_txq_num; u16 tx_cmd_len; - u8 tx_chains_num; - u8 rx_chains_num; - u8 valid_tx_ant; - u8 valid_rx_ant; + u16 tx_ant_num; u16 max_rxq_size; - u16 max_rxq_log; u32 rx_buf_size; u32 max_pkt_size; + u16 max_rxq_log; u8 max_stations; u8 bcast_sta_id; + void *shared_virt; + dma_addr_t shared_phys; }; #define HT_SHORT_GI_20MHZ_ONLY (1 << 0) @@ -641,6 +641,7 @@ extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, const u8 *dest, int left); extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q); +extern int iwl4965_send_statistics_request(struct iwl_priv *priv); extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, u32 decrypt_res, struct ieee80211_rx_status *stats); @@ -678,7 +679,7 @@ extern void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv); extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv); extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); -extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv); +extern int iwl4965_hw_set_hw_setting(struct iwl_priv *priv); extern int iwl4965_hw_nic_init(struct iwl_priv *priv); extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv); extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv); @@ -941,8 +942,6 @@ enum { #endif -#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ - struct iwl_priv { /* ieee device used by generic ieee processing code */ @@ -1034,7 +1033,7 @@ struct iwl_priv { * 4965's initialize alive response contains some calibration data. */ struct iwl4965_init_alive_resp card_alive_init; struct iwl4965_alive_resp card_alive; -#ifdef CONFIG_IWLWIFI_RFKILL +#ifdef CONFIG_IWLCORE_RFKILL struct iwl_rfkill_mngr rfkill_mngr; #endif @@ -1113,10 +1112,6 @@ struct iwl_priv { spinlock_t sta_lock; int num_stations; struct iwl4965_station_entry stations[IWL_STATION_COUNT]; - struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; - u8 default_wep_key; - u8 key_mapping_key; - unsigned long ucode_key_table; /* Indication if ieee80211_ops->open has been called */ u8 is_open; @@ -1147,14 +1142,9 @@ struct iwl_priv { /* Last Rx'd beacon timestamp */ u64 timestamp; u16 beacon_int; + struct iwl4965_driver_hw_info hw_setting; struct ieee80211_vif *vif; - struct iwl_hw_params hw_params; - /* driver/uCode shared Tx Byte Counts and Rx status */ - void *shared_virt; - /* Physical Pointer to Tx Byte Counts and Rx status */ - dma_addr_t shared_phys; - /* Current association information needed to configure the * hardware */ u16 assoc_id; @@ -1210,6 +1200,7 @@ struct iwl_priv { #ifdef CONFIG_IWL4965_SENSITIVITY struct work_struct sensitivity_work; #endif + struct work_struct statistics_work; struct timer_list statistics_periodic; }; /*iwl_priv */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index 2dfd982d7d1f..d8a226e68ed1 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -277,16 +277,3 @@ int iwlcore_low_level_notify(struct iwl_priv *priv, } EXPORT_SYMBOL(iwlcore_low_level_notify); -int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) -{ - u32 stat_flags = 0; - struct iwl_host_cmd cmd = { - .id = REPLY_STATISTICS_CMD, - .meta.flags = flags, - .len = sizeof(stat_flags), - .data = (u8 *) &stat_flags, - }; - return iwl_send_cmd(priv, &cmd); -} -EXPORT_SYMBOL(iwl_send_statistics_request); - diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h index 7193d97630dc..6d82376f43f9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h @@ -82,9 +82,6 @@ struct iwl_cmd; #define IWL_SKU_A 0x2 #define IWL_SKU_N 0x8 -struct iwl_hcmd_ops { - int (*rxon_assoc)(struct iwl_priv *priv); -}; struct iwl_hcmd_utils_ops { int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); }; @@ -92,35 +89,19 @@ struct iwl_hcmd_utils_ops { struct iwl_lib_ops { /* iwlwifi driver (priv) init */ int (*init_drv)(struct iwl_priv *priv); - /* set hw dependant perameters */ - int (*set_hw_params)(struct iwl_priv *priv); - - void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, - struct iwl4965_tx_queue *txq, - u16 byte_cnt); - /* nic init */ - int (*hw_nic_init)(struct iwl_priv *priv); - /* alive notification */ - int (*alive_notify)(struct iwl_priv *priv); - /* check validity of rtc data address */ - int (*is_valid_rtc_data_addr)(u32 addr); - /* 1st ucode load */ - int (*load_ucode)(struct iwl_priv *priv); - /* rfkill */ - void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; + void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); }; struct iwl_ops { const struct iwl_lib_ops *lib; - const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; }; struct iwl_mod_params { int disable; /* def: 0 = enable radio */ - int sw_crypto; /* def: 0 = using hardware encryption */ + int hw_crypto; /* def: 0 = using software encryption */ int debug; /* def: 0 = minimal debug log messages */ int disable_hw_scan; /* def: 0 = use h/w scan */ int num_of_queues; /* def: HW dependent */ @@ -234,13 +215,4 @@ enum iwlcore_card_notify { int iwlcore_low_level_notify(struct iwl_priv *priv, enum iwlcore_card_notify notify); -extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); -int iwl_send_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq, u8 flags); - -static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) -{ - return priv->cfg->ops->hcmd->rxon_assoc(priv); -} - #endif /* __iwl_core_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0f16f2606f29..23632e54aab2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -102,14 +102,10 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, struct iwl_priv *priv = (struct iwl_priv *)file->private_data; char buf[256]; int pos = 0; - const size_t bufsz = sizeof(buf); - pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", - priv->tx_stats[0].cnt); - pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", - priv->tx_stats[1].cnt); - pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", - priv->tx_stats[2].cnt); + pos += sprintf(buf+pos, "mgmt: %u\n", priv->tx_stats[0].cnt); + pos += sprintf(buf+pos, "ctrl: %u\n", priv->tx_stats[1].cnt); + pos += sprintf(buf+pos, "data: %u\n", priv->tx_stats[2].cnt); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } @@ -121,14 +117,10 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, struct iwl_priv *priv = (struct iwl_priv *)file->private_data; char buf[256]; int pos = 0; - const size_t bufsz = sizeof(buf); - pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", - priv->rx_stats[0].cnt); - pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", - priv->rx_stats[1].cnt); - pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", - priv->rx_stats[2].cnt); + pos += sprintf(buf+pos, "mgmt: %u\n", priv->rx_stats[0].cnt); + pos += sprintf(buf+pos, "ctrl: %u\n", priv->rx_stats[1].cnt); + pos += sprintf(buf+pos, "data: %u\n", priv->rx_stats[2].cnt); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } @@ -146,7 +138,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, int i; int pos = 0; struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - const size_t bufsz = sizeof(buf); printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n", priv->dbgfs->sram_offset, priv->dbgfs->sram_len); @@ -168,9 +159,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, break; } } - pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); + pos += sprintf(buf+pos, "0x%08x ", val); } - pos += scnprintf(buf + pos, bufsz - pos, "\n"); + pos += sprintf(buf+pos, "\n"); iwl_release_nic_access(priv); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); @@ -207,7 +198,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, { struct iwl_priv *priv = (struct iwl_priv *)file->private_data; struct iwl4965_station_entry *station; - int max_sta = priv->hw_params.max_stations; + int max_sta = priv->hw_setting.max_stations; char *buf; int i, j, pos = 0; ssize_t ret; @@ -219,50 +210,44 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, if(!buf) return -ENOMEM; - pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", + pos += sprintf(buf+pos, "num of stations: %d\n\n", priv->num_stations); for (i = 0; i < max_sta; i++) { station = &priv->stations[i]; if (station->used) { - pos += scnprintf(buf + pos, bufsz - pos, - "station %d:\ngeneral data:\n", i+1); + pos += sprintf(buf+pos, "station %d:\ngeneral data:\n", + i+1); print_mac(mac, station->sta.sta.addr); - pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", + pos += sprintf(buf+pos, "id: %u\n", station->sta.sta.sta_id); - pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", + pos += sprintf(buf+pos, "mode: %u\n", station->sta.mode); - pos += scnprintf(buf + pos, bufsz - pos, - "flags: 0x%x\n", + pos += sprintf(buf+pos, "flags: 0x%x\n", station->sta.station_flags_msk); - pos += scnprintf(buf + pos, bufsz - pos, - "ps_status: %u\n", station->ps_status); - pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "seq_num\t\ttxq_id\t"); - pos += scnprintf(buf + pos, bufsz - pos, - "frame_count\twait_for_ba\t"); - pos += scnprintf(buf + pos, bufsz - pos, - "start_idx\tbitmap0\t"); - pos += scnprintf(buf + pos, bufsz - pos, - "bitmap1\trate_n_flags\n"); + pos += sprintf(buf+pos, "ps_status: %u\n", + station->ps_status); + + pos += sprintf(buf+pos, "tid data:\n"); + + pos += sprintf(buf+pos, "seq_num\t\ttxq_id\t"); + pos += sprintf(buf+pos, "frame_count\twait_for_ba\t"); + pos += sprintf(buf+pos, "start_idx\tbitmap0\t"); + pos += sprintf(buf+pos, "bitmap1\trate_n_flags\n"); for (j = 0; j < MAX_TID_COUNT; j++) { - pos += scnprintf(buf + pos, bufsz - pos, - "[%d]:\t\t%u\t", j, - station->tid[j].seq_number); - pos += scnprintf(buf + pos, bufsz - pos, - "%u\t\t%u\t\t%u\t\t", + pos += sprintf(buf+pos, "[%d]:\t\t%u\t", + j, station->tid[j].seq_number); + pos += sprintf(buf+pos, "%u\t\t%u\t\t%u\t\t", station->tid[j].agg.txq_id, station->tid[j].agg.frame_count, station->tid[j].agg.wait_for_ba); - pos += scnprintf(buf + pos, bufsz - pos, - "%u\t%llu\t%u\n", + pos += sprintf(buf+pos, "%u\t%llu\t%u\n", station->tid[j].agg.start_idx, (unsigned long long)station->tid[j].agg.bitmap, station->tid[j].agg.rate_n_flags); } - pos += scnprintf(buf + pos, bufsz - pos, "\n"); + pos += sprintf(buf+pos, "\n"); } } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c index fdb27f1cdc08..1f8c2999805b 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -51,7 +51,6 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_ADD_STA); IWL_CMD(REPLY_REMOVE_STA); IWL_CMD(REPLY_REMOVE_ALL_STA); - IWL_CMD(REPLY_WEPKEY); IWL_CMD(REPLY_TX); IWL_CMD(REPLY_RATE_SCALE); IWL_CMD(REPLY_LEDS_CMD); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 5980a5621cb8..8f38c24491cd 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -47,9 +47,6 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) if (!priv->rfkill_mngr.rfkill) return 0; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return 0; - IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); mutex_lock(&priv->mutex); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.h index a7f04b855403..e7aa51a1db18 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.h @@ -34,7 +34,7 @@ struct iwl_priv; #include -#ifdef CONFIG_IWLWIFI_RFKILL +#ifdef CONFIG_IWLCORE_RFKILL struct iwl_rfkill_mngr { struct rfkill *rfkill; struct input_dev *input_dev; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c deleted file mode 100644 index e4fdfaa2b9b2..000000000000 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c +++ /dev/null @@ -1,355 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * James P. Ketrenos - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include - -#include "iwl-eeprom.h" -#include "iwl-4965.h" -#include "iwl-core.h" -#include "iwl-sta.h" -#include "iwl-io.h" -#include "iwl-helpers.h" -#include "iwl-4965.h" -#include "iwl-sta.h" - -int iwl_get_free_ucode_key_index(struct iwl_priv *priv) -{ - int i; - - for (i = 0; i < STA_KEY_MAX_NUM; i++) - if (!test_and_set_bit(i, &priv->ucode_key_table)) - return i; - - return -1; -} - -int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) -{ - int i, not_empty = 0; - u8 buff[sizeof(struct iwl_wep_cmd) + - sizeof(struct iwl_wep_key) * WEP_KEYS_MAX]; - struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; - size_t cmd_size = sizeof(struct iwl_wep_cmd); - struct iwl_host_cmd cmd = { - .id = REPLY_WEPKEY, - .data = wep_cmd, - .meta.flags = CMD_ASYNC, - }; - - memset(wep_cmd, 0, cmd_size + - (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); - - for (i = 0; i < WEP_KEYS_MAX ; i++) { - wep_cmd->key[i].key_index = i; - if (priv->wep_keys[i].key_size) { - wep_cmd->key[i].key_offset = i; - not_empty = 1; - } else { - wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; - } - - wep_cmd->key[i].key_size = priv->wep_keys[i].key_size; - memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key, - priv->wep_keys[i].key_size); - } - - wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; - wep_cmd->num_keys = WEP_KEYS_MAX; - - cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX; - - cmd.len = cmd_size; - - if (not_empty || send_if_empty) - return iwl_send_cmd(priv, &cmd); - else - return 0; -} - -int iwl_remove_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - - if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERROR("index %d not used in uCode key table.\n", - keyconf->keyidx); - - priv->default_wep_key--; - memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); - ret = iwl_send_static_wepkey_cmd(priv, 1); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -int iwl_set_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf) -{ - int ret; - unsigned long flags; - - keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->hw_key_idx = keyconf->keyidx; - priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->default_wep_key++; - - if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERROR("index %d already used in uCode key table.\n", - keyconf->keyidx); - - priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; - memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, - keyconf->keylen); - - ret = iwl_send_static_wepkey_cmd(priv, 0); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - int ret; - - keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->hw_key_idx = keyconf->keyidx; - - key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - - if (keyconf->keylen == WEP_KEY_LEN_128) - key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; - - if (sta_id == priv->hw_params.bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; - - memcpy(priv->stations[sta_id].keyinfo.key, - keyconf->key, keyconf->keylen); - - memcpy(&priv->stations[sta_id].sta.key.key[3], - keyconf->key, keyconf->keylen); - - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - priv->stations[sta_id].sta.key.key_flags = key_flags; - - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - ret = iwl4965_send_add_station(priv, - &priv->stations[sta_id].sta, CMD_ASYNC); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - - key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - - if (sta_id == priv->hw_params.bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->hw_key_idx = keyconf->keyidx; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, - keyconf->keylen); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, - keyconf->keylen); - - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - priv->stations[sta_id].sta.key.key_flags = key_flags; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); - return iwl4965_send_add_station(priv, - &priv->stations[sta_id].sta, CMD_ASYNC); -} - -static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - int ret = 0; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - keyconf->hw_key_idx = keyconf->keyidx; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.conf = keyconf; - priv->stations[sta_id].keyinfo.keylen = 16; - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - - /* This copy is acutally not needed: we get the key with each TX */ - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id) -{ - unsigned long flags; - - priv->key_mapping_key = 0; - - spin_lock_irqsave(&priv->sta_lock, flags); - if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, - &priv->ucode_key_table)) - IWL_ERROR("index %d not used in uCode key table.\n", - priv->stations[sta_id].sta.key.key_offset); - memset(&priv->stations[sta_id].keyinfo, 0, - sizeof(struct iwl4965_hw_key)); - memset(&priv->stations[sta_id].sta.key, 0, - sizeof(struct iwl4965_keyinfo)); - priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); - return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); -} - -int iwl_set_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key, u8 sta_id) -{ - int ret; - - priv->key_mapping_key = 1; - - switch (key->alg) { - case ALG_CCMP: - ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id); - break; - case ALG_TKIP: - ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id); - break; - case ALG_WEP: - ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id); - break; - default: - IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); - ret = -EINVAL; - } - - return ret; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static void iwl_dump_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq) -{ - int i; - IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id); - IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n", - lq->general_params.single_stream_ant_msk, - lq->general_params.dual_stream_ant_msk); - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) - IWL_DEBUG_RATE("lq index %d 0x%X\n", - i, lq->rs_table[i].rate_n_flags); -} -#else -static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq) -{ -} -#endif - -int iwl_send_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq, u8 flags) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_TX_LINK_QUALITY_CMD, - .len = sizeof(struct iwl_link_quality_cmd), - .meta.flags = flags, - .data = lq, - }; - - if ((lq->sta_id == 0xFF) && - (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) - return -EINVAL; - - if (lq->sta_id == 0xFF) - lq->sta_id = IWL_AP_ID; - - iwl_dump_lq_cmd(priv,lq); - - if (iwl_is_associated(priv) && priv->assoc_station_added && - priv->lq_mngr.lq_ready) - return iwl_send_cmd(priv, &cmd); - - return 0; -} -EXPORT_SYMBOL(iwl_send_lq_cmd); - diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h deleted file mode 100644 index 44f272ecc827..000000000000 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * James P. Ketrenos - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ -#ifndef __iwl_sta_h__ -#define __iwl_sta_h__ - -#include - -#include "iwl-eeprom.h" -#include "iwl-core.h" -#include "iwl-4965.h" -#include "iwl-io.h" -#include "iwl-helpers.h" - -int iwl_get_free_ucode_key_index(struct iwl_priv *priv); -int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); -int iwl_remove_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key); -int iwl_set_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key); -int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id); -int iwl_set_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key, u8 sta_id); -#endif /* __iwl_sta_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1a5678fe4224..29a9ecdcbf35 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -70,7 +70,7 @@ static int iwl3945_param_disable; /* def: 0 = enable radio */ static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */ -int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */ +int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ /* * module name, copyright, version, etc. @@ -7974,10 +7974,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl3945_hw_ops.hw_scan = NULL; } - if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || + if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) || (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); + IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); err = -EINVAL; goto out; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl4965-base.c b/trunk/drivers/net/wireless/iwlwifi/iwl4965-base.c index d7e2358a213a..06e44dad5f02 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -50,7 +50,6 @@ #include "iwl-core.h" #include "iwl-io.h" #include "iwl-helpers.h" -#include "iwl-sta.h" static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_tx_queue *txq); @@ -398,9 +397,9 @@ static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_a if (is_ap) index = IWL_AP_ID; else if (is_broadcast_ether_addr(addr)) - index = priv->hw_params.bcast_sta_id; + index = priv->hw_setting.bcast_sta_id; else - for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) + for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) if (priv->stations[i].used && !compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { @@ -440,9 +439,9 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, if (is_ap) index = IWL_AP_ID; else if (is_broadcast_ether_addr(addr)) - index = priv->hw_params.bcast_sta_id; + index = priv->hw_setting.bcast_sta_id; else - for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { + for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) { if (!compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { index = i; @@ -483,7 +482,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, #ifdef CONFIG_IWL4965_HT /* BCAST station and IBSS stations do not work in HT mode */ - if (index != priv->hw_params.bcast_sta_id && + if (index != priv->hw_setting.bcast_sta_id && priv->iw_mode != IEEE80211_IF_TYPE_IBSS) iwl4965_set_ht_add_station(priv, index, (struct ieee80211_ht_info *) ht_data); @@ -575,11 +574,11 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) txq->need_update = 1; /* Set up entry in queue's byte count circular buffer */ - priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); + ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - ret = iwl4965_tx_queue_update_write_ptr(priv, txq); + iwl4965_tx_queue_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->hcmd_lock, flags); return ret ? ret : idx; @@ -596,6 +595,13 @@ static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) } +int iwl4965_send_statistics_request(struct iwl_priv *priv) +{ + u32 flags = 0; + return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, + sizeof(flags), &flags); +} + /** * iwl4965_rxon_add_station - add station into station table. * @@ -749,6 +755,60 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv) return 0; } +static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) +{ + int rc = 0; + struct iwl4965_rx_packet *res = NULL; + struct iwl4965_rxon_assoc_cmd rxon_assoc; + struct iwl_host_cmd cmd = { + .id = REPLY_RXON_ASSOC, + .len = sizeof(rxon_assoc), + .meta.flags = CMD_WANT_SKB, + .data = &rxon_assoc, + }; + const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon; + const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon; + + if ((rxon1->flags == rxon2->flags) && + (rxon1->filter_flags == rxon2->filter_flags) && + (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && + (rxon1->ofdm_ht_single_stream_basic_rates == + rxon2->ofdm_ht_single_stream_basic_rates) && + (rxon1->ofdm_ht_dual_stream_basic_rates == + rxon2->ofdm_ht_dual_stream_basic_rates) && + (rxon1->rx_chain == rxon2->rx_chain) && + (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { + IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); + return 0; + } + + rxon_assoc.flags = priv->staging_rxon.flags; + rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; + rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.reserved = 0; + rxon_assoc.ofdm_ht_single_stream_basic_rates = + priv->staging_rxon.ofdm_ht_single_stream_basic_rates; + rxon_assoc.ofdm_ht_dual_stream_basic_rates = + priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; + rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; + + rc = iwl_send_cmd_sync(priv, &cmd); + if (rc) + return rc; + + res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data; + if (res->hdr.flags & IWL_CMD_FAILED_MSK) { + IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n"); + rc = -EIO; + } + + priv->alloc_rxb_skb--; + dev_kfree_skb_any(cmd.meta.u.skb); + + return rc; +} + /** * iwl4965_commit_rxon - commit staging_rxon to hardware * @@ -780,7 +840,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) * iwl4965_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ if (!iwl4965_full_rxon_required(priv)) { - rc = iwl_send_rxon_assoc(priv); + rc = iwl4965_send_rxon_assoc(priv); if (rc) { IWL_ERROR("Error setting RXON_ASSOC " "configuration (%d).\n", rc); @@ -835,7 +895,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) le16_to_cpu(priv->staging_rxon.channel), print_mac(mac, priv->staging_rxon.bssid_addr)); - iwl4965_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); + iwl4965_set_rxon_hwcrypto(priv, priv->cfg->mod_params->hw_crypto); /* Apply the new configuration */ rc = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); @@ -881,9 +941,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) return -EIO; } priv->assoc_station_added = 1; - if (priv->default_wep_key && - iwl_send_static_wepkey_cmd(priv, 0)) - IWL_ERROR("Could not send WEP static key.\n"); } return 0; @@ -1051,6 +1108,131 @@ int iwl4965_send_add_station(struct iwl_priv *priv, return rc; } +static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + __le16 key_flags = 0; + + key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); + key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); + + if (sta_id == priv->hw_setting.bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; + + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->hw_key_idx = keyconf->keyidx; + + key_flags &= ~STA_KEY_FLG_INVALID; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; + + memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, + keyconf->keylen); + + memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, + keyconf->keylen); + + priv->stations[sta_id].sta.key.key_offset + = (sta_id % STA_KEY_MAX_NUM);/*FIXME*/ + priv->stations[sta_id].sta.key.key_flags = key_flags; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + + spin_unlock_irqrestore(&priv->sta_lock, flags); + + IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); + return iwl4965_send_add_station(priv, + &priv->stations[sta_id].sta, CMD_ASYNC); +} + +static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + int ret = 0; + + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + keyconf->hw_key_idx = keyconf->keyidx; + + spin_lock_irqsave(&priv->sta_lock, flags); + + priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.conf = keyconf; + priv->stations[sta_id].keyinfo.keylen = 16; + + /* This copy is acutally not needed: we get the key with each TX */ + memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); + + memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); + + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return ret; +} + +static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->sta_lock, flags); + memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key)); + memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); + priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); + iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); + return 0; +} + +static int iwl4965_set_dynamic_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key, u8 sta_id) +{ + int ret; + + switch (key->alg) { + case ALG_CCMP: + ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); + break; + case ALG_TKIP: + ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id); + break; + case ALG_WEP: + ret = -EOPNOTSUPP; + break; + default: + IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); + ret = -EINVAL; + } + + return ret; +} + +static int iwl4965_remove_static_key(struct iwl_priv *priv) +{ + int ret = -EOPNOTSUPP; + + return ret; +} + +static int iwl4965_set_static_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key) +{ + if (key->alg == ALG_WEP) + return -EOPNOTSUPP; + + IWL_ERROR("Static key invalid: alg %d\n", key->alg); + return -EINVAL; +} + static void iwl4965_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; @@ -1171,13 +1353,13 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) * ******************************************************************************/ -static void iwl4965_unset_hw_params(struct iwl_priv *priv) +static void iwl4965_unset_hw_setting(struct iwl_priv *priv) { - if (priv->shared_virt) + if (priv->hw_setting.shared_virt) pci_free_consistent(priv->pci_dev, sizeof(struct iwl4965_shared), - priv->shared_virt, - priv->shared_phys); + priv->hw_setting.shared_virt, + priv->hw_setting.shared_phys); } /** @@ -1794,7 +1976,7 @@ static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, | RXON_FLG_CCK_MSK); priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; } else { - /* Copied from iwl4965_post_associate() */ + /* Copied from iwl4965_bg_post_associate() */ if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else @@ -1933,10 +2115,6 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, int sta_id) { struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; - struct iwl_wep_key *wepkey; - int keyidx = 0; - - BUG_ON(ctl->key_idx > 3); switch (keyinfo->alg) { case ALG_CCMP: @@ -1955,29 +2133,16 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, break; case ALG_WEP: - wepkey = &priv->wep_keys[ctl->key_idx]; - cmd->cmd.tx.sec_ctl = 0; - if (priv->default_wep_key) { - /* the WEP key was sent as static */ - keyidx = ctl->key_idx; - memcpy(&cmd->cmd.tx.key[3], wepkey->key, - wepkey->key_size); - if (wepkey->key_size == WEP_KEY_LEN_128) - cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; - } else { - /* the WEP key was sent as dynamic */ - keyidx = keyinfo->keyidx; - memcpy(&cmd->cmd.tx.key[3], keyinfo->key, - keyinfo->keylen); - if (keyinfo->keylen == WEP_KEY_LEN_128) - cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; - } + cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP | + (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; - cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP | - (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); + if (keyinfo->keylen == 13) + cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; + + memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen); IWL_DEBUG_TX("Configuring packet for WEP encryption " - "with key %d\n", keyidx); + "with key %d\n", ctl->key_idx); break; default: @@ -2075,7 +2240,7 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, /* If this frame is broadcast or management, use broadcast station id */ if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || is_multicast_ether_addr(hdr->addr1)) - return priv->hw_params.bcast_sta_id; + return priv->hw_setting.bcast_sta_id; switch (priv->iw_mode) { @@ -2089,7 +2254,7 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, sta_id = iwl4965_hw_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; - return priv->hw_params.bcast_sta_id; + return priv->hw_setting.bcast_sta_id; /* If this frame is going out to an IBSS network, find the station, * or create a new station table entry */ @@ -2109,11 +2274,11 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, "Defaulting to broadcast...\n", print_mac(mac, hdr->addr1)); iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); - return priv->hw_params.bcast_sta_id; + return priv->hw_setting.bcast_sta_id; default: IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); - return priv->hw_params.bcast_sta_id; + return priv->hw_setting.bcast_sta_id; } } @@ -2260,7 +2425,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, * of the MAC header (device reads on dword boundaries). * We'll tell device about this padding later. */ - len = priv->hw_params.tx_cmd_len + + len = priv->hw_setting.tx_cmd_len + sizeof(struct iwl_cmd_header) + hdr_len; len_org = len; @@ -2331,7 +2496,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, ieee80211_get_hdrlen(fc)); /* Set up entry for this TFD in Tx byte-count array */ - priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len); + iwl4965_tx_queue_update_wr_ptr(priv, txq, len); /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); @@ -2427,8 +2592,7 @@ void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) CSR_UCODE_SW_BIT_RFKILL); spin_unlock_irqrestore(&priv->lock, flags); /* call the host command only if no hw rf-kill set */ - if (!test_bit(STATUS_RF_KILL_HW, &priv->status) && - iwl_is_ready(priv)) + if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0); @@ -3688,7 +3852,7 @@ static void iwl4965_rx_allocate(struct iwl_priv *priv) /* Alloc a new receive buffer */ rxb->skb = - alloc_skb(priv->hw_params.rx_buf_size, + alloc_skb(priv->hw_setting.rx_buf_size, __GFP_NOWARN | GFP_ATOMIC); if (!rxb->skb) { if (net_ratelimit()) @@ -3705,7 +3869,7 @@ static void iwl4965_rx_allocate(struct iwl_priv *priv) /* Get physical address of RB/SKB */ rxb->dma_addr = pci_map_single(priv->pci_dev, rxb->skb->data, - priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); + priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; } @@ -3748,7 +3912,7 @@ static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, - priv->hw_params.rx_buf_size, + priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE); dev_kfree_skb(rxq->pool[i].skb); } @@ -3800,7 +3964,7 @@ void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, - priv->hw_params.rx_buf_size, + priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE); priv->alloc_rxb_skb--; dev_kfree_skb(rxq->pool[i].skb); @@ -3935,7 +4099,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, - priv->hw_params.rx_buf_size, + priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE); pkt = (struct iwl4965_rx_packet *)rxb->skb->data; @@ -3988,7 +4152,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv) } pci_unmap_single(priv->pci_dev, rxb->dma_addr, - priv->hw_params.rx_buf_size, + priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE); spin_lock_irqsave(&rxq->lock, flags); list_add_tail(&rxb->list, &priv->rxq.rx_used); @@ -4141,7 +4305,7 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv) base = le32_to_cpu(priv->card_alive.error_event_table_ptr); - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + if (!iwl4965_hw_valid_rtc_data_addr(base)) { IWL_ERROR("Not valid error log pointer 0x%08X\n", base); return; } @@ -4236,7 +4400,7 @@ static void iwl4965_dump_nic_event_log(struct iwl_priv *priv) u32 size; /* # entries that we'll print */ base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + if (!iwl4965_hw_valid_rtc_data_addr(base)) { IWL_ERROR("Invalid event log pointer 0x%08X\n", base); return; } @@ -5011,6 +5175,156 @@ static int iwl4965_verify_ucode(struct iwl_priv *priv) return rc; } + +/* check contents of special bootstrap uCode SRAM */ +static int iwl4965_verify_bsm(struct iwl_priv *priv) +{ + __le32 *image = priv->ucode_boot.v_addr; + u32 len = priv->ucode_boot.len; + u32 reg; + u32 val; + + IWL_DEBUG_INFO("Begin verify bsm\n"); + + /* verify BSM SRAM contents */ + val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); + for (reg = BSM_SRAM_LOWER_BOUND; + reg < BSM_SRAM_LOWER_BOUND + len; + reg += sizeof(u32), image ++) { + val = iwl_read_prph(priv, reg); + if (val != le32_to_cpu(*image)) { + IWL_ERROR("BSM uCode verification failed at " + "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", + BSM_SRAM_LOWER_BOUND, + reg - BSM_SRAM_LOWER_BOUND, len, + val, le32_to_cpu(*image)); + return -EIO; + } + } + + IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); + + return 0; +} + +/** + * iwl4965_load_bsm - Load bootstrap instructions + * + * BSM operation: + * + * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program + * in special SRAM that does not power down during RFKILL. When powering back + * up after power-saving sleeps (or during initial uCode load), the BSM loads + * the bootstrap program into the on-board processor, and starts it. + * + * The bootstrap program loads (via DMA) instructions and data for a new + * program from host DRAM locations indicated by the host driver in the + * BSM_DRAM_* registers. Once the new program is loaded, it starts + * automatically. + * + * When initializing the NIC, the host driver points the BSM to the + * "initialize" uCode image. This uCode sets up some internal data, then + * notifies host via "initialize alive" that it is complete. + * + * The host then replaces the BSM_DRAM_* pointer values to point to the + * normal runtime uCode instructions and a backup uCode data cache buffer + * (filled initially with starting data values for the on-board processor), + * then triggers the "initialize" uCode to load and launch the runtime uCode, + * which begins normal operation. + * + * When doing a power-save shutdown, runtime uCode saves data SRAM into + * the backup data cache in DRAM before SRAM is powered down. + * + * When powering back up, the BSM loads the bootstrap program. This reloads + * the runtime uCode instructions and the backup data cache into SRAM, + * and re-launches the runtime uCode from where it left off. + */ +static int iwl4965_load_bsm(struct iwl_priv *priv) +{ + __le32 *image = priv->ucode_boot.v_addr; + u32 len = priv->ucode_boot.len; + dma_addr_t pinst; + dma_addr_t pdata; + u32 inst_len; + u32 data_len; + int rc; + int i; + u32 done; + u32 reg_offset; + + IWL_DEBUG_INFO("Begin load bsm\n"); + + /* make sure bootstrap program is no larger than BSM's SRAM size */ + if (len > IWL_MAX_BSM_SIZE) + return -EINVAL; + + /* Tell bootstrap uCode where to find the "Initialize" uCode + * in host DRAM ... host DRAM physical address bits 35:4 for 4965. + * NOTE: iwl4965_initialize_alive_start() will replace these values, + * after the "initialize" uCode has run, to point to + * runtime/protocol instructions and backup data cache. */ + pinst = priv->ucode_init.p_addr >> 4; + pdata = priv->ucode_init_data.p_addr >> 4; + inst_len = priv->ucode_init.len; + data_len = priv->ucode_init_data.len; + + rc = iwl_grab_nic_access(priv); + if (rc) + return rc; + + iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); + iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); + iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); + iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); + + /* Fill BSM memory with bootstrap instructions */ + for (reg_offset = BSM_SRAM_LOWER_BOUND; + reg_offset < BSM_SRAM_LOWER_BOUND + len; + reg_offset += sizeof(u32), image++) + _iwl_write_prph(priv, reg_offset, + le32_to_cpu(*image)); + + rc = iwl4965_verify_bsm(priv); + if (rc) { + iwl_release_nic_access(priv); + return rc; + } + + /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ + iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); + iwl_write_prph(priv, BSM_WR_MEM_DST_REG, + RTC_INST_LOWER_BOUND); + iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); + + /* Load bootstrap code into instruction SRAM now, + * to prepare to load "initialize" uCode */ + iwl_write_prph(priv, BSM_WR_CTRL_REG, + BSM_WR_CTRL_REG_BIT_START); + + /* Wait for load of bootstrap uCode to finish */ + for (i = 0; i < 100; i++) { + done = iwl_read_prph(priv, BSM_WR_CTRL_REG); + if (!(done & BSM_WR_CTRL_REG_BIT_START)) + break; + udelay(10); + } + if (i < 100) + IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); + else { + IWL_ERROR("BSM write did not complete!\n"); + return -EIO; + } + + /* Enable future boot loads whenever power management unit triggers it + * (e.g. when powering back up after power-save shutdown) */ + iwl_write_prph(priv, BSM_WR_CTRL_REG, + BSM_WR_CTRL_REG_BIT_START_EN); + + iwl_release_nic_access(priv); + + return 0; +} + static void iwl4965_nic_start(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ @@ -5320,7 +5634,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) */ static void iwl4965_alive_start(struct iwl_priv *priv) { - int ret = 0; + int rc = 0; IWL_DEBUG_INFO("Runtime Alive received.\n"); @@ -5343,10 +5657,10 @@ static void iwl4965_alive_start(struct iwl_priv *priv) iwlcore_clear_stations_table(priv); - ret = priv->cfg->ops->lib->alive_notify(priv); - if (ret) { + rc = iwl4965_alive_notify(priv); + if (rc) { IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n", - ret); + rc); goto restart; } @@ -5521,8 +5835,7 @@ static void iwl4965_down(struct iwl_priv *priv) static int __iwl4965_up(struct iwl_priv *priv) { - int i; - int ret; + int rc, i; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARNING("Exit pending; will not bring the NIC up\n"); @@ -5557,10 +5870,10 @@ static int __iwl4965_up(struct iwl_priv *priv) iwl_rfkill_set_hw_state(priv); iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - ret = priv->cfg->ops->lib->hw_nic_init(priv); - if (ret) { - IWL_ERROR("Unable to init nic\n"); - return ret; + rc = iwl4965_hw_nic_init(priv); + if (rc) { + IWL_ERROR("Unable to int nic\n"); + return rc; } /* make sure rfkill handshake bits are cleared */ @@ -5593,10 +5906,10 @@ static int __iwl4965_up(struct iwl_priv *priv) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - ret = priv->cfg->ops->lib->load_ucode(priv); + rc = iwl4965_load_bsm(priv); - if (ret) { - IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret); + if (rc) { + IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc); continue; } @@ -5833,7 +6146,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) } scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; + scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; @@ -5959,8 +6272,10 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data) #define IWL_DELAY_NEXT_SCAN (HZ*2) -static void iwl4965_post_associate(struct iwl_priv *priv) +static void iwl4965_bg_post_associate(struct work_struct *data) { + struct iwl_priv *priv = container_of(data, struct iwl_priv, + post_associate.work); struct ieee80211_conf *conf = NULL; int ret = 0; DECLARE_MAC_BUF(mac); @@ -5978,10 +6293,12 @@ static void iwl4965_post_associate(struct iwl_priv *priv) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + mutex_lock(&priv->mutex); - if (!priv->vif || !priv->is_open) + if (!priv->vif || !priv->is_open) { + mutex_unlock(&priv->mutex); return; - + } iwl4965_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -6065,18 +6382,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; -} - - -static void iwl4965_bg_post_associate(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, - post_associate.work); - - mutex_lock(&priv->mutex); - iwl4965_post_associate(priv); mutex_unlock(&priv->mutex); - } static void iwl4965_bg_abort_scan(struct work_struct *work) @@ -6698,10 +7004,6 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, if (changes & BSS_CHANGED_ASSOC) { IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc); - /* This should never happen as this function should - * never be called from interrupt context. */ - if (WARN_ON_ONCE(in_interrupt())) - return; if (bss_conf->assoc) { priv->assoc_id = bss_conf->aid; priv->beacon_int = bss_conf->beacon_int; @@ -6709,16 +7011,14 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, priv->assoc_capability = bss_conf->assoc_capability; priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - mutex_lock(&priv->mutex); - iwl4965_post_associate(priv); - mutex_unlock(&priv->mutex); + queue_work(priv->workqueue, &priv->post_associate.work); } else { priv->assoc_id = 0; IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); } } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); - iwl_send_rxon_assoc(priv); + iwl4965_send_rxon_assoc(priv); } } @@ -6806,11 +7106,13 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags &= ~STA_KEY_FLG_INVALID; - if (sta_id == priv->hw_params.bcast_sta_id) + if (sta_id == priv->hw_setting.bcast_sta_id) key_flags |= STA_KEY_MULTICAST_MSK; spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].sta.key.key_offset = + (sta_id % STA_KEY_MAX_NUM);/* FIXME */ priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; @@ -6836,11 +7138,11 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, DECLARE_MAC_BUF(mac); int ret = 0; u8 sta_id = IWL_INVALID_STATION; - u8 is_default_wep_key = 0; + u8 static_key; IWL_DEBUG_MAC80211("enter\n"); - if (priv->cfg->mod_params->sw_crypto) { + if (!priv->cfg->mod_params->hw_crypto) { IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } @@ -6849,44 +7151,35 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* only support pairwise keys */ return -EOPNOTSUPP; - sta_id = iwl4965_hw_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211("leave - %s not in station map.\n", - print_mac(mac, addr)); - return -EINVAL; + /* FIXME: need to differenciate between static and dynamic key + * in the level of mac80211 */ + static_key = !iwl_is_associated(priv); + if (!static_key) { + sta_id = iwl4965_hw_find_station(priv, addr); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211("leave - %s not in station map.\n", + print_mac(mac, addr)); + return -EINVAL; + } } - mutex_lock(&priv->mutex); iwl4965_scan_cancel_timeout(priv, 100); - mutex_unlock(&priv->mutex); - - /* If we are getting WEP group key and we didn't receive any key mapping - * so far, we are in legacy wep mode (group key only), otherwise we are - * in 1X mode. - * In legacy wep mode, we use another host command to the uCode */ - if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && - priv->iw_mode != IEEE80211_IF_TYPE_AP) { - if (cmd == SET_KEY) - is_default_wep_key = !priv->key_mapping_key; - else - is_default_wep_key = priv->default_wep_key; - } switch (cmd) { case SET_KEY: - if (is_default_wep_key) - ret = iwl_set_default_wep_key(priv, key); + if (static_key) + ret = iwl4965_set_static_key(priv, key); else - ret = iwl_set_dynamic_key(priv, key, sta_id); + ret = iwl4965_set_dynamic_key(priv, key, sta_id); IWL_DEBUG_MAC80211("enable hwcrypto key\n"); break; case DISABLE_KEY: - if (is_default_wep_key) - ret = iwl_remove_default_wep_key(priv, key); + if (static_key) + ret = iwl4965_remove_static_key(priv); else - ret = iwl_remove_dynamic_key(priv, sta_id); + ret = iwl4965_clear_sta_key_info(priv, sta_id); IWL_DEBUG_MAC80211("disable hwcrypto key\n"); break; @@ -7483,7 +7776,7 @@ static ssize_t show_statistics(struct device *d, return -EAGAIN; mutex_lock(&priv->mutex); - rc = iwl_send_statistics_request(priv, 0); + rc = iwl4965_send_statistics_request(priv); mutex_unlock(&priv->mutex); if (rc) { @@ -7791,8 +8084,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * 5. Setup HW constants ************************/ /* Device-specific setup */ - if (priv->cfg->ops->lib->set_hw_params(priv)) { - IWL_ERROR("failed to set hw parameters\n"); + if (iwl4965_hw_set_hw_setting(priv)) { + IWL_ERROR("failed to set hw settings\n"); goto out_iounmap; } @@ -7802,7 +8095,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = iwl_setup(priv); if (err) - goto out_unset_hw_params; + goto out_unset_hw_settings; /* At this point both hw and priv are initialized. */ /********************************** @@ -7828,7 +8121,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group); if (err) { IWL_ERROR("failed to create sysfs device attributes\n"); - goto out_unset_hw_params; + goto out_unset_hw_settings; } err = iwl_dbgfs_register(priv, DRV_NAME); @@ -7852,8 +8145,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); - out_unset_hw_params: - iwl4965_unset_hw_params(priv); + out_unset_hw_settings: + iwl4965_unset_hw_setting(priv); out_iounmap: pci_iounmap(pdev, priv->hw_base); out_pci_release_regions: @@ -7915,7 +8208,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) iwl4965_rx_queue_free(priv, &priv->rxq); iwl4965_hw_txq_ctx_free(priv); - iwl4965_unset_hw_params(priv); + iwl4965_unset_hw_setting(priv); iwlcore_clear_stations_table(priv); @@ -7980,17 +8273,9 @@ static int iwl4965_pci_resume(struct pci_dev *pdev) * *****************************************************************************/ -/* Hardware specific file defines the PCI IDs table for that hardware module */ -static struct pci_device_id iwl_hw_card_ids[] = { - {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, - {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, - {0} -}; -MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); - -static struct pci_driver iwl_driver = { +static struct pci_driver iwl4965_driver = { .name = DRV_NAME, - .id_table = iwl_hw_card_ids, + .id_table = iwl4965_hw_card_ids, .probe = iwl4965_pci_probe, .remove = __devexit_p(iwl4965_pci_remove), #ifdef CONFIG_PM @@ -8012,13 +8297,13 @@ static int __init iwl4965_init(void) return ret; } - ret = pci_register_driver(&iwl_driver); + ret = pci_register_driver(&iwl4965_driver); if (ret) { IWL_ERROR("Unable to initialize PCI module\n"); goto error_register; } #ifdef CONFIG_IWLWIFI_DEBUG - ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level); + ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level); if (ret) { IWL_ERROR("Unable to create driver sysfs file\n"); goto error_debug; @@ -8029,7 +8314,7 @@ static int __init iwl4965_init(void) #ifdef CONFIG_IWLWIFI_DEBUG error_debug: - pci_unregister_driver(&iwl_driver); + pci_unregister_driver(&iwl4965_driver); #endif error_register: iwl4965_rate_control_unregister(); @@ -8039,9 +8324,9 @@ static int __init iwl4965_init(void) static void __exit iwl4965_exit(void) { #ifdef CONFIG_IWLWIFI_DEBUG - driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level); + driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level); #endif - pci_unregister_driver(&iwl_driver); + pci_unregister_driver(&iwl4965_driver); iwl4965_rate_control_unregister(); } diff --git a/trunk/drivers/net/wireless/libertas/cmd.c b/trunk/drivers/net/wireless/libertas/cmd.c index 6328b9593877..4a82f5114ca0 100644 --- a/trunk/drivers/net/wireless/libertas/cmd.c +++ b/trunk/drivers/net/wireless/libertas/cmd.c @@ -4,7 +4,6 @@ */ #include -#include #include "host.h" #include "hostcmd.h" #include "decl.h" @@ -296,7 +295,6 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, lbs_deb_enter(LBS_DEB_CMD); - memset(&cmd, 0, sizeof(cmd)); cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); @@ -360,9 +358,7 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(cmd_action); - if (cmd_action == CMD_ACT_GET) - cmd.enable = 0; - else { + if (cmd_action == CMD_ACT_SET) { if (*enable) cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); else @@ -814,7 +810,6 @@ int lbs_get_channel(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_CMD); - memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET); @@ -862,7 +857,6 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) lbs_deb_enter(LBS_DEB_CMD); - memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); cmd.channel = cpu_to_le16(channel); @@ -1835,20 +1829,15 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, sizeof(confirm_sleep)); + if (ret) { lbs_pr_alert("confirm_sleep failed\n"); - goto out; + } else { + spin_lock_irqsave(&priv->driver_lock, flags); + if (!priv->intcounter) + priv->psstate = PS_STATE_SLEEP; + spin_unlock_irqrestore(&priv->driver_lock, flags); } - - spin_lock_irqsave(&priv->driver_lock, flags); - - /* If nothing to do, go back to sleep (?) */ - if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) - priv->psstate = PS_STATE_SLEEP; - - spin_unlock_irqrestore(&priv->driver_lock, flags); - -out: lbs_deb_leave(LBS_DEB_HOST); } @@ -1910,16 +1899,13 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) } spin_lock_irqsave(&priv->driver_lock, flags); - /* In-progress command? */ if (priv->cur_cmd) { allowed = 0; lbs_deb_host("cur_cmd was set\n"); } - - /* Pending events or command responses? */ - if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { + if (priv->intcounter > 0) { allowed = 0; - lbs_deb_host("pending events or command responses\n"); + lbs_deb_host("intcounter %d\n", priv->intcounter); } spin_unlock_irqrestore(&priv->driver_lock, flags); diff --git a/trunk/drivers/net/wireless/libertas/cmdresp.c b/trunk/drivers/net/wireless/libertas/cmdresp.c index 5abecb7673e6..245d3c3a9274 100644 --- a/trunk/drivers/net/wireless/libertas/cmdresp.c +++ b/trunk/drivers/net/wireless/libertas/cmdresp.c @@ -384,7 +384,7 @@ static inline int handle_cmd_response(struct lbs_private *priv, return ret; } -int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) +int lbs_process_rx_command(struct lbs_private *priv) { uint16_t respcmd, curcmd; struct cmd_header *resp; @@ -404,14 +404,14 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) goto done; } - resp = (void *)data; + resp = (void *)priv->upld_buf; curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); respcmd = le16_to_cpu(resp->command); result = le16_to_cpu(resp->result); lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n", - respcmd, le16_to_cpu(resp->seqnum), len); - lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); + respcmd, le16_to_cpu(resp->seqnum), priv->upld_len); + lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len); if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", @@ -569,13 +569,18 @@ static int lbs_send_confirmwake(struct lbs_private *priv) return ret; } -int lbs_process_event(struct lbs_private *priv, u32 event) +int lbs_process_event(struct lbs_private *priv) { int ret = 0; + u32 eventcause; lbs_deb_enter(LBS_DEB_CMD); - switch (event) { + spin_lock_irq(&priv->driver_lock); + eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT; + spin_unlock_irq(&priv->driver_lock); + + switch (eventcause) { case MACREG_INT_CODE_LINK_SENSED: lbs_deb_cmd("EVENT: link sensed\n"); break; @@ -691,10 +696,14 @@ int lbs_process_event(struct lbs_private *priv, u32 event) break; default: - lbs_pr_alert("EVENT: unknown event id %d\n", event); + lbs_pr_alert("EVENT: unknown event id %d\n", eventcause); break; } + spin_lock_irq(&priv->driver_lock); + priv->eventcause = 0; + spin_unlock_irq(&priv->driver_lock); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } diff --git a/trunk/drivers/net/wireless/libertas/debugfs.c b/trunk/drivers/net/wireless/libertas/debugfs.c index ad2fabca9116..7072e26b42d9 100644 --- a/trunk/drivers/net/wireless/libertas/debugfs.c +++ b/trunk/drivers/net/wireless/libertas/debugfs.c @@ -824,6 +824,7 @@ struct debug_data { /* To debug any member of struct lbs_private, simply add one line here. */ static struct debug_data items[] = { + {"intcounter", item_size(intcounter), item_addr(intcounter)}, {"psmode", item_size(psmode), item_addr(psmode)}, {"psstate", item_size(psstate), item_addr(psstate)}, }; diff --git a/trunk/drivers/net/wireless/libertas/decl.h b/trunk/drivers/net/wireless/libertas/decl.h index b652fa301e19..4aea421f07ce 100644 --- a/trunk/drivers/net/wireless/libertas/decl.h +++ b/trunk/drivers/net/wireless/libertas/decl.h @@ -19,7 +19,7 @@ struct cmd_ds_command; void lbs_set_mac_control(struct lbs_private *priv); -void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); +void lbs_send_tx_feedback(struct lbs_private *priv); int lbs_free_cmd_buffer(struct lbs_private *priv); @@ -30,16 +30,14 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, int lbs_allocate_cmd_buffer(struct lbs_private *priv); int lbs_execute_next_command(struct lbs_private *priv); -int lbs_process_event(struct lbs_private *priv, u32 event); -void lbs_queue_event(struct lbs_private *priv, u32 event); -void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); - +int lbs_process_event(struct lbs_private *priv); +void lbs_interrupt(struct lbs_private *priv); int lbs_set_radio_control(struct lbs_private *priv); u32 lbs_fw_index_to_data_rate(u8 index); u8 lbs_data_rate_to_fw_index(u32 rate); /** The proc fs interface */ -int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); +int lbs_process_rx_command(struct lbs_private *priv); void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, int result); int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); diff --git a/trunk/drivers/net/wireless/libertas/defs.h b/trunk/drivers/net/wireless/libertas/defs.h index d39520111062..84e8de5e21da 100644 --- a/trunk/drivers/net/wireless/libertas/defs.h +++ b/trunk/drivers/net/wireless/libertas/defs.h @@ -177,6 +177,8 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MRVDRV_CMD_UPLD_RDY 0x0008 #define MRVDRV_CARDEVENT 0x0010 +#define SBI_EVENT_CAUSE_SHIFT 3 + /** TxPD status */ /* Station firmware use TxPD status field to report final Tx transmit diff --git a/trunk/drivers/net/wireless/libertas/dev.h b/trunk/drivers/net/wireless/libertas/dev.h index 0d9edb9b11f5..1e6bae80396b 100644 --- a/trunk/drivers/net/wireless/libertas/dev.h +++ b/trunk/drivers/net/wireless/libertas/dev.h @@ -129,6 +129,10 @@ struct lbs_private { u32 bbp_offset; u32 rf_offset; + /** Upload length */ + u32 upld_len; + /* Upload buffer */ + u8 upld_buf[LBS_UPLD_SIZE]; /* Download sent: bit0 1/0=data_sent/data_tx_done, bit1 1/0=cmd_sent/cmd_tx_done, @@ -151,16 +155,21 @@ struct lbs_private { /** Hardware access */ int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); + int (*hw_get_int_status) (struct lbs_private *priv, u8 *); + int (*hw_read_event_cause) (struct lbs_private *); /* Wake On LAN */ uint32_t wol_criteria; uint8_t wol_gpio; uint8_t wol_gap; + /* was struct lbs_adapter from here... */ + /** Wlan adapter data structure*/ /** STATUS variables */ u32 fwrelease; u32 fwcapinfo; + /* protected with big lock */ struct mutex lock; @@ -172,6 +181,7 @@ struct lbs_private { /** command-related variables */ u16 seqnum; + /* protected by big lock */ struct cmd_ctrl_node *cmd_array; /** Current command */ @@ -184,17 +194,12 @@ struct lbs_private { struct list_head cmdpendingq; wait_queue_head_t cmd_pending; + /* command related variables protected by priv->driver_lock */ - /* Command responses sent from the hardware to the driver */ - u8 resp_idx; - u8 resp_buf[2][LBS_UPLD_SIZE]; - u32 resp_len[2]; - - /* Events sent from hardware to driver */ - struct kfifo *event_fifo; - - /* nickname */ - u8 nodename[16]; + /** Async and Sync Event variables */ + u32 intcounter; + u32 eventcause; + u8 nodename[16]; /* nickname */ /** spin locks */ spinlock_t driver_lock; @@ -204,6 +209,8 @@ struct lbs_private { int nr_retries; int cmd_timed_out; + u8 hisregcpy; + /** current ssid/bssid related parameters*/ struct current_bss_params curbssparams; diff --git a/trunk/drivers/net/wireless/libertas/if_cs.c b/trunk/drivers/net/wireless/libertas/if_cs.c index 54280e292ea5..53afebac7146 100644 --- a/trunk/drivers/net/wireless/libertas/if_cs.c +++ b/trunk/drivers/net/wireless/libertas/if_cs.c @@ -83,14 +83,14 @@ static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg) { unsigned int val = ioread8(card->iobase + reg); if (debug_output) - printk(KERN_INFO "inb %08x<%02x\n", reg, val); + printk(KERN_INFO "##inb %08x<%02x\n", reg, val); return val; } static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) { unsigned int val = ioread16(card->iobase + reg); if (debug_output) - printk(KERN_INFO "inw %08x<%04x\n", reg, val); + printk(KERN_INFO "##inw %08x<%04x\n", reg, val); return val; } static inline void if_cs_read16_rep( @@ -100,7 +100,7 @@ static inline void if_cs_read16_rep( unsigned long count) { if (debug_output) - printk(KERN_INFO "insw %08x<(0x%lx words)\n", + printk(KERN_INFO "##insw %08x<(0x%lx words)\n", reg, count); ioread16_rep(card->iobase + reg, buf, count); } @@ -108,14 +108,14 @@ static inline void if_cs_read16_rep( static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) { if (debug_output) - printk(KERN_INFO "outb %08x>%02x\n", reg, val); + printk(KERN_INFO "##outb %08x>%02x\n", reg, val); iowrite8(val, card->iobase + reg); } static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) { if (debug_output) - printk(KERN_INFO "outw %08x>%04x\n", reg, val); + printk(KERN_INFO "##outw %08x>%04x\n", reg, val); iowrite16(val, card->iobase + reg); } @@ -126,7 +126,7 @@ static inline void if_cs_write16_rep( unsigned long count) { if (debug_output) - printk(KERN_INFO "outsw %08x>(0x%lx words)\n", + printk(KERN_INFO "##outsw %08x>(0x%lx words)\n", reg, count); iowrite16_rep(card->iobase + reg, buf, count); } @@ -199,6 +199,17 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r #define IF_CS_C_S_CARDEVENT 0x0010 #define IF_CS_C_S_MASK 0x001f #define IF_CS_C_S_STATUS_MASK 0x7f00 +/* The following definitions should be the same as the MRVDRV_ ones */ + +#if MRVDRV_CMD_DNLD_RDY != IF_CS_C_S_CMD_DNLD_RDY +#error MRVDRV_CMD_DNLD_RDY and IF_CS_C_S_CMD_DNLD_RDY not in sync +#endif +#if MRVDRV_CMD_UPLD_RDY != IF_CS_C_S_CMD_UPLD_RDY +#error MRVDRV_CMD_UPLD_RDY and IF_CS_C_S_CMD_UPLD_RDY not in sync +#endif +#if MRVDRV_CARDEVENT != IF_CS_C_S_CARDEVENT +#error MRVDRV_CARDEVENT and IF_CS_C_S_CARDEVENT not in sync +#endif #define IF_CS_C_INT_CAUSE 0x00000022 #define IF_CS_C_IC_MASK 0x001f @@ -214,6 +225,55 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r +/********************************************************************/ +/* Interrupts */ +/********************************************************************/ + +static inline void if_cs_enable_ints(struct if_cs_card *card) +{ + lbs_deb_enter(LBS_DEB_CS); + if_cs_write16(card, IF_CS_H_INT_MASK, 0); +} + +static inline void if_cs_disable_ints(struct if_cs_card *card) +{ + lbs_deb_enter(LBS_DEB_CS); + if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); +} + +static irqreturn_t if_cs_interrupt(int irq, void *data) +{ + struct if_cs_card *card = data; + u16 int_cause; + + lbs_deb_enter(LBS_DEB_CS); + + int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); + if (int_cause == 0x0) { + /* Not for us */ + return IRQ_NONE; + + } else if (int_cause == 0xffff) { + /* Read in junk, the card has probably been removed */ + card->priv->surpriseremoved = 1; + return IRQ_HANDLED; + } else { + if (int_cause & IF_CS_H_IC_TX_OVER) + lbs_host_to_card_done(card->priv); + + /* clear interrupt */ + if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK); + } + spin_lock(&card->priv->driver_lock); + lbs_interrupt(card->priv); + spin_unlock(&card->priv->driver_lock); + + return IRQ_HANDLED; +} + + + + /********************************************************************/ /* I/O */ /********************************************************************/ @@ -291,7 +351,6 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb) */ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) { - unsigned long flags; int ret = -1; u16 val; @@ -319,12 +378,6 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) * bytes */ *len -= 8; ret = 0; - - /* Clear this flag again */ - spin_lock_irqsave(&priv->driver_lock, flags); - priv->dnld_sent = DNLD_RES_RECEIVED; - spin_unlock_irqrestore(&priv->driver_lock, flags); - out: lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len); return ret; @@ -343,9 +396,11 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); priv->stats.rx_dropped++; + printk(KERN_INFO "##HS %s:%d TODO\n", __FUNCTION__, __LINE__); goto dat_err; } + //TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN); skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2); if (!skb) goto out; @@ -369,96 +424,6 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) -/********************************************************************/ -/* Interrupts */ -/********************************************************************/ - -static inline void if_cs_enable_ints(struct if_cs_card *card) -{ - lbs_deb_enter(LBS_DEB_CS); - if_cs_write16(card, IF_CS_H_INT_MASK, 0); -} - -static inline void if_cs_disable_ints(struct if_cs_card *card) -{ - lbs_deb_enter(LBS_DEB_CS); - if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); -} - - -static irqreturn_t if_cs_interrupt(int irq, void *data) -{ - struct if_cs_card *card = data; - struct lbs_private *priv = card->priv; - u16 cause; - - lbs_deb_enter(LBS_DEB_CS); - - cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); - if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK); - - lbs_deb_cs("cause 0x%04x\n", cause); - if (cause == 0) { - /* Not for us */ - return IRQ_NONE; - } - - if (cause == 0xffff) { - /* Read in junk, the card has probably been removed */ - card->priv->surpriseremoved = 1; - return IRQ_HANDLED; - } - - /* TODO: I'm not sure what the best ordering is */ - - cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; - - if (cause & IF_CS_C_S_RX_UPLD_RDY) { - struct sk_buff *skb; - lbs_deb_cs("rx packet\n"); - skb = if_cs_receive_data(priv); - if (skb) - lbs_process_rxed_packet(priv, skb); - } - - if (cause & IF_CS_H_IC_TX_OVER) { - lbs_deb_cs("tx over\n"); - lbs_host_to_card_done(priv); - } - - if (cause & IF_CS_C_S_CMD_UPLD_RDY) { - unsigned long flags; - u8 i; - - lbs_deb_cs("cmd upload ready\n"); - spin_lock_irqsave(&priv->driver_lock, flags); - i = (priv->resp_idx == 0) ? 1 : 0; - spin_unlock_irqrestore(&priv->driver_lock, flags); - - BUG_ON(priv->resp_len[i]); - if_cs_receive_cmdres(priv, priv->resp_buf[i], - &priv->resp_len[i]); - - spin_lock_irqsave(&priv->driver_lock, flags); - lbs_notify_command_response(priv, i); - spin_unlock_irqrestore(&priv->driver_lock, flags); - } - - if (cause & IF_CS_H_IC_HOST_EVENT) { - u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS) - & IF_CS_C_S_STATUS_MASK; - if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, - IF_CS_H_IC_HOST_EVENT); - lbs_deb_cs("eventcause 0x%04x\n", event); - lbs_queue_event(priv, event >> 8 & 0xff); - } - - return IRQ_HANDLED; -} - - - - /********************************************************************/ /* Firmware */ /********************************************************************/ @@ -511,6 +476,8 @@ static int if_cs_prog_helper(struct if_cs_card *card) if (remain < count) count = remain; + /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n", + __LINE__, sent, fw->size); */ /* "write the number of bytes to be sent to the I/O Command * write length register" */ @@ -577,12 +544,18 @@ static int if_cs_prog_real(struct if_cs_card *card) ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK); if (ret < 0) { + int i; lbs_pr_err("helper firmware doesn't answer\n"); + for (i = 0; i < 0x50; i += 2) + printk(KERN_INFO "## HS %02x: %04x\n", + i, if_cs_read16(card, i)); goto err_release; } for (sent = 0; sent < fw->size; sent += len) { len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW); + /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n", + __LINE__, sent, fw->size); */ if (len & 1) { retry++; lbs_pr_info("odd, need to retry this firmware block\n"); @@ -669,6 +642,64 @@ static int if_cs_host_to_card(struct lbs_private *priv, } +static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg) +{ + struct if_cs_card *card = (struct if_cs_card *)priv->card; + int ret = 0; + u16 int_cause; + *ireg = 0; + + lbs_deb_enter(LBS_DEB_CS); + + if (priv->surpriseremoved) + goto out; + + int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK; + if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause); + + *ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; + + if (!*ireg) + goto sbi_get_int_status_exit; + +sbi_get_int_status_exit: + + /* is there a data packet for us? */ + if (*ireg & IF_CS_C_S_RX_UPLD_RDY) { + struct sk_buff *skb = if_cs_receive_data(priv); + lbs_process_rxed_packet(priv, skb); + *ireg &= ~IF_CS_C_S_RX_UPLD_RDY; + } + + if (*ireg & IF_CS_C_S_TX_DNLD_RDY) { + priv->dnld_sent = DNLD_RES_RECEIVED; + } + + /* Card has a command result for us */ + if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) { + ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len); + if (ret < 0) + lbs_pr_err("could not receive cmd from card\n"); + } + +out: + lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy); + return ret; +} + + +static int if_cs_read_event_cause(struct lbs_private *priv) +{ + lbs_deb_enter(LBS_DEB_CS); + + priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5; + if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT); + + return 0; +} + + + /********************************************************************/ /* Card Services */ /********************************************************************/ @@ -821,10 +852,13 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out2; } - /* Finish setting up fields in lbs_private */ + /* Store pointers to our call-back functions */ card->priv = priv; priv->card = card; - priv->hw_host_to_card = if_cs_host_to_card; + priv->hw_host_to_card = if_cs_host_to_card; + priv->hw_get_int_status = if_cs_get_int_status; + priv->hw_read_event_cause = if_cs_read_event_cause; + priv->fw_ready = 1; /* Now actually get the IRQ */ diff --git a/trunk/drivers/net/wireless/libertas/if_sdio.c b/trunk/drivers/net/wireless/libertas/if_sdio.c index 51f664bbee9d..eed73204bcc9 100644 --- a/trunk/drivers/net/wireless/libertas/if_sdio.c +++ b/trunk/drivers/net/wireless/libertas/if_sdio.c @@ -91,6 +91,8 @@ struct if_sdio_card { const char *firmware; u8 buffer[65536]; + u8 int_cause; + u32 event; spinlock_t lock; struct if_sdio_packet *packets; @@ -127,13 +129,13 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) static int if_sdio_handle_cmd(struct if_sdio_card *card, u8 *buffer, unsigned size) { - struct lbs_private *priv = card->priv; int ret; unsigned long flags; - u8 i; lbs_deb_enter(LBS_DEB_SDIO); + spin_lock_irqsave(&card->priv->driver_lock, flags); + if (size > LBS_CMD_BUFFER_SIZE) { lbs_deb_sdio("response packet too large (%d bytes)\n", (int)size); @@ -141,20 +143,20 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card, goto out; } - spin_lock_irqsave(&priv->driver_lock, flags); + memcpy(card->priv->upld_buf, buffer, size); + card->priv->upld_len = size; - i = (priv->resp_idx == 0) ? 1 : 0; - BUG_ON(priv->resp_len[i]); - priv->resp_len[i] = size; - memcpy(priv->resp_buf[i], buffer, size); - lbs_notify_command_response(priv, i); + card->int_cause |= MRVDRV_CMD_UPLD_RDY; - spin_unlock_irqrestore(&card->priv->driver_lock, flags); + lbs_interrupt(card->priv); ret = 0; out: + spin_unlock_irqrestore(&card->priv->driver_lock, flags); + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); + return ret; } @@ -200,6 +202,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card, u8 *buffer, unsigned size) { int ret; + unsigned long flags; u32 event; lbs_deb_enter(LBS_DEB_SDIO); @@ -219,9 +222,18 @@ static int if_sdio_handle_event(struct if_sdio_card *card, event |= buffer[2] << 16; event |= buffer[1] << 8; event |= buffer[0] << 0; + event <<= SBI_EVENT_CAUSE_SHIFT; } - lbs_queue_event(card->priv, event & 0xFF); + spin_lock_irqsave(&card->priv->driver_lock, flags); + + card->event = event; + card->int_cause |= MRVDRV_CARDEVENT; + + lbs_interrupt(card->priv); + + spin_unlock_irqrestore(&card->priv->driver_lock, flags); + ret = 0; out: @@ -758,6 +770,37 @@ static int if_sdio_host_to_card(struct lbs_private *priv, return ret; } +static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg) +{ + struct if_sdio_card *card; + + lbs_deb_enter(LBS_DEB_SDIO); + + card = priv->card; + + *ireg = card->int_cause; + card->int_cause = 0; + + lbs_deb_leave(LBS_DEB_SDIO); + + return 0; +} + +static int if_sdio_read_event_cause(struct lbs_private *priv) +{ + struct if_sdio_card *card; + + lbs_deb_enter(LBS_DEB_SDIO); + + card = priv->card; + + priv->eventcause = card->event; + + lbs_deb_leave(LBS_DEB_SDIO); + + return 0; +} + /*******************************************************************/ /* SDIO callbacks */ /*******************************************************************/ @@ -910,6 +953,8 @@ static int if_sdio_probe(struct sdio_func *func, priv->card = card; priv->hw_host_to_card = if_sdio_host_to_card; + priv->hw_get_int_status = if_sdio_get_int_status; + priv->hw_read_event_cause = if_sdio_read_event_cause; priv->fw_ready = 1; diff --git a/trunk/drivers/net/wireless/libertas/if_usb.c b/trunk/drivers/net/wireless/libertas/if_usb.c index 8032df72aaab..75aed9d07367 100644 --- a/trunk/drivers/net/wireless/libertas/if_usb.c +++ b/trunk/drivers/net/wireless/libertas/if_usb.c @@ -38,6 +38,8 @@ static void if_usb_receive_fwload(struct urb *urb); static int if_usb_prog_firmware(struct if_usb_card *cardp); static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, uint8_t *payload, uint16_t nb); +static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *); +static int if_usb_read_event_cause(struct lbs_private *); static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb); static void if_usb_free(struct if_usb_card *cardp); @@ -231,6 +233,8 @@ static int if_usb_probe(struct usb_interface *intf, cardp->priv->fw_ready = 1; priv->hw_host_to_card = if_usb_host_to_card; + priv->hw_get_int_status = if_usb_get_int_status; + priv->hw_read_event_cause = if_usb_read_event_cause; cardp->boot2_version = udev->descriptor.bcdDevice; if_usb_submit_rx_urb(cardp); @@ -578,6 +582,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, skb_pull(skb, MESSAGE_HEADER_LEN); lbs_process_rxed_packet(priv, skb); + priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); } static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, @@ -585,8 +590,6 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, struct if_usb_card *cardp, struct lbs_private *priv) { - u8 i; - if (recvlength > LBS_CMD_BUFFER_SIZE) { lbs_deb_usbd(&cardp->udev->dev, "The receive buffer is too large\n"); @@ -598,15 +601,12 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, BUG(); spin_lock(&priv->driver_lock); + cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY; + priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); + memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len); - i = (priv->resp_idx == 0) ? 1 : 0; - BUG_ON(priv->resp_len[i]); - priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN); - memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN, - priv->resp_len[i]); kfree_skb(skb); - lbs_notify_command_response(priv, i); - + lbs_interrupt(priv); spin_unlock(&priv->driver_lock); lbs_deb_usbd(&cardp->udev->dev, @@ -629,7 +629,6 @@ static void if_usb_receive(struct urb *urb) uint8_t *recvbuff = NULL; uint32_t recvtype = 0; __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); - uint32_t event; lbs_deb_enter(LBS_DEB_USB); @@ -661,20 +660,26 @@ static void if_usb_receive(struct urb *urb) break; case CMD_TYPE_INDICATION: - /* Event handling */ - event = le32_to_cpu(pkt[1]); - lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event); - kfree_skb(skb); + /* Event cause handling */ + spin_lock(&priv->driver_lock); - /* Icky undocumented magic special case */ - if (event & 0xffff0000) { - u32 trycount = (event & 0xffff0000) >> 16; + cardp->usb_event_cause = le32_to_cpu(pkt[1]); - lbs_send_tx_feedback(priv, trycount); - } else - lbs_queue_event(priv, event & 0xFF); - break; + lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n", + cardp->usb_event_cause); + /* Icky undocumented magic special case */ + if (cardp->usb_event_cause & 0xffff0000) { + lbs_send_tx_feedback(priv); + spin_unlock(&priv->driver_lock); + break; + } + cardp->usb_event_cause <<= 3; + cardp->usb_int_cause |= MRVDRV_CARDEVENT; + kfree_skb(skb); + lbs_interrupt(priv); + spin_unlock(&priv->driver_lock); + goto rx_exit; default: lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n", recvtype); @@ -717,6 +722,30 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN); } +/* called with priv->driver_lock held */ +static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg) +{ + struct if_usb_card *cardp = priv->card; + + *ireg = cardp->usb_int_cause; + cardp->usb_int_cause = 0; + + lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg); + + return 0; +} + +static int if_usb_read_event_cause(struct lbs_private *priv) +{ + struct if_usb_card *cardp = priv->card; + + priv->eventcause = cardp->usb_event_cause; + /* Re-submit rx urb here to avoid event lost issue */ + if_usb_submit_rx_urb(cardp); + + return 0; +} + /** * @brief This function issues Boot command to the Boot2 code * @param ivalue 1:Boot from FW by USB-Download diff --git a/trunk/drivers/net/wireless/libertas/if_usb.h b/trunk/drivers/net/wireless/libertas/if_usb.h index 5771a83a43f0..e4829a391eb9 100644 --- a/trunk/drivers/net/wireless/libertas/if_usb.h +++ b/trunk/drivers/net/wireless/libertas/if_usb.h @@ -46,6 +46,8 @@ struct if_usb_card { struct lbs_private *priv; struct sk_buff *rx_skb; + uint32_t usb_event_cause; + uint8_t usb_int_cause; uint8_t ep_in; uint8_t ep_out; diff --git a/trunk/drivers/net/wireless/libertas/main.c b/trunk/drivers/net/wireless/libertas/main.c index 406f54d40956..8f1122610974 100644 --- a/trunk/drivers/net/wireless/libertas/main.c +++ b/trunk/drivers/net/wireless/libertas/main.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -481,9 +480,10 @@ static void lbs_tx_timeout(struct net_device *dev) dev->trans_start = jiffies; - if (priv->currenttxskb) - lbs_send_tx_feedback(priv, 0); - + if (priv->currenttxskb) { + priv->eventcause = 0x01000000; + lbs_send_tx_feedback(priv); + } /* XX: Shouldn't we also call into the hw-specific driver to kick it somehow? */ lbs_host_to_card_done(priv); @@ -659,6 +659,7 @@ static int lbs_thread(void *data) struct net_device *dev = data; struct lbs_private *priv = dev->priv; wait_queue_t wait; + u8 ireg = 0; lbs_deb_enter(LBS_DEB_THREAD); @@ -666,10 +667,9 @@ static int lbs_thread(void *data) for (;;) { int shouldsleep; - u8 resp_idx; - lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n", - priv->currenttxskb, priv->dnld_sent); + lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n", + priv->intcounter, priv->currenttxskb, priv->dnld_sent); add_wait_queue(&priv->waitq, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -681,6 +681,8 @@ static int lbs_thread(void *data) shouldsleep = 1; /* We need to wait until we're _told_ to die */ else if (priv->psstate == PS_STATE_SLEEP) shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ + else if (priv->intcounter) + shouldsleep = 0; /* Interrupt pending. Deal with it now */ else if (priv->cmd_timed_out) shouldsleep = 0; /* Command timed out. Recover */ else if (!priv->fw_ready) @@ -693,34 +695,29 @@ static int lbs_thread(void *data) shouldsleep = 1; /* Can't send a command; one already running */ else if (!list_empty(&priv->cmdpendingq)) shouldsleep = 0; /* We have a command to send */ - else if (__kfifo_len(priv->event_fifo)) - shouldsleep = 0; /* We have an event to process */ - else if (priv->resp_len[priv->resp_idx]) - shouldsleep = 0; /* We have a command response */ else shouldsleep = 1; /* No command */ if (shouldsleep) { - lbs_deb_thread("sleeping, connect_status %d, " - "ps_mode %d, ps_state %d\n", - priv->connect_status, - priv->psmode, priv->psstate); + lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n", + priv->connect_status, priv->intcounter, + priv->psmode, priv->psstate); spin_unlock_irq(&priv->driver_lock); schedule(); } else spin_unlock_irq(&priv->driver_lock); - lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n", - priv->currenttxskb, priv->dnld_sent); + lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n", + priv->intcounter, priv->currenttxskb, priv->dnld_sent); set_current_state(TASK_RUNNING); remove_wait_queue(&priv->waitq, &wait); - lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n", - priv->currenttxskb, priv->dnld_sent); + lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n", + priv->intcounter, priv->currenttxskb, priv->dnld_sent); if (kthread_should_stop()) { - lbs_deb_thread("break from main thread\n"); + lbs_deb_thread("main-thread: break from main thread\n"); break; } @@ -729,23 +726,35 @@ static int lbs_thread(void *data) continue; } - lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", - priv->currenttxskb, priv->dnld_sent); - spin_lock_irq(&priv->driver_lock); - /* Process any pending command response */ - resp_idx = priv->resp_idx; - if (priv->resp_len[resp_idx]) { + + if (priv->intcounter) { + u8 int_status; + + priv->intcounter = 0; + int_status = priv->hw_get_int_status(priv, &ireg); + + if (int_status) { + lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n"); + spin_unlock_irq(&priv->driver_lock); + continue; + } + priv->hisregcpy |= ireg; + } + + lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n", + priv->intcounter, priv->currenttxskb, priv->dnld_sent); + + /* command response? */ + if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) { + lbs_deb_thread("main-thread: cmd response ready\n"); + + priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY; spin_unlock_irq(&priv->driver_lock); - lbs_process_command_response(priv, - priv->resp_buf[resp_idx], - priv->resp_len[resp_idx]); + lbs_process_rx_command(priv); spin_lock_irq(&priv->driver_lock); - priv->resp_len[resp_idx] = 0; } - spin_unlock_irq(&priv->driver_lock); - /* command timeout stuff */ if (priv->cmd_timed_out && priv->cur_cmd) { struct cmd_ctrl_node *cmdnode = priv->cur_cmd; @@ -766,18 +775,21 @@ static int lbs_thread(void *data) } priv->cmd_timed_out = 0; - /* Process hardware events, e.g. card removed, link lost */ - spin_lock_irq(&priv->driver_lock); - while (__kfifo_len(priv->event_fifo)) { - u32 event; + /* Any Card Event */ + if (priv->hisregcpy & MRVDRV_CARDEVENT) { + lbs_deb_thread("main-thread: Card Event Activity\n"); - __kfifo_get(priv->event_fifo, (unsigned char *) &event, - sizeof(event)); + priv->hisregcpy &= ~MRVDRV_CARDEVENT; + + if (priv->hw_read_event_cause(priv)) { + lbs_pr_alert("main-thread: hw_read_event_cause failed\n"); + spin_unlock_irq(&priv->driver_lock); + continue; + } + spin_unlock_irq(&priv->driver_lock); + lbs_process_event(priv); + } else spin_unlock_irq(&priv->driver_lock); - lbs_process_event(priv, event); - spin_lock_irq(&priv->driver_lock); - } - spin_unlock_irq(&priv->driver_lock); if (!priv->fw_ready) continue; @@ -786,10 +798,8 @@ static int lbs_thread(void *data) if (priv->psstate == PS_STATE_PRE_SLEEP && !priv->dnld_sent && !priv->cur_cmd) { if (priv->connect_status == LBS_CONNECTED) { - lbs_deb_thread("pre-sleep, currenttxskb %p, " - "dnld_sent %d, cur_cmd %p\n", - priv->currenttxskb, priv->dnld_sent, - priv->cur_cmd); + lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n", + priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd); lbs_ps_confirm_sleep(priv); } else { @@ -799,8 +809,7 @@ static int lbs_thread(void *data) * after firmware fixes it */ priv->psstate = PS_STATE_AWAKE; - lbs_pr_alert("ignore PS_SleepConfirm in " - "non-connected state\n"); + lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n"); } } @@ -1037,18 +1046,7 @@ static int lbs_init_adapter(struct lbs_private *priv) /* Allocate the command buffers */ if (lbs_allocate_cmd_buffer(priv)) { lbs_pr_err("Out of memory allocating command buffers\n"); - ret = -ENOMEM; - goto out; - } - priv->resp_idx = 0; - priv->resp_len[0] = priv->resp_len[1] = 0; - - /* Create the event FIFO */ - priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); - if (IS_ERR(priv->event_fifo)) { - lbs_pr_err("Out of memory allocating event FIFO buffer\n"); - ret = -ENOMEM; - goto out; + ret = -1; } out: @@ -1062,8 +1060,6 @@ static void lbs_free_adapter(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_MAIN); lbs_free_cmd_buffer(priv); - if (priv->event_fifo) - kfifo_free(priv->event_fifo); del_timer(&priv->command_timer); kfree(priv->networks); priv->networks = NULL; @@ -1438,41 +1434,27 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) return ret; } -void lbs_queue_event(struct lbs_private *priv, u32 event) -{ - unsigned long flags; - - lbs_deb_enter(LBS_DEB_THREAD); - spin_lock_irqsave(&priv->driver_lock, flags); - - if (priv->psstate == PS_STATE_SLEEP) - priv->psstate = PS_STATE_AWAKE; - - __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); - - wake_up_interruptible(&priv->waitq); - - spin_unlock_irqrestore(&priv->driver_lock, flags); - lbs_deb_leave(LBS_DEB_THREAD); -} -EXPORT_SYMBOL_GPL(lbs_queue_event); - -void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) +/** + * @brief This function handles the interrupt. it will change PS + * state if applicable. it will wake up main_thread to handle + * the interrupt event as well. + * + * @param dev A pointer to net_device structure + * @return n/a + */ +void lbs_interrupt(struct lbs_private *priv) { lbs_deb_enter(LBS_DEB_THREAD); + lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter); + priv->intcounter++; if (priv->psstate == PS_STATE_SLEEP) priv->psstate = PS_STATE_AWAKE; - - /* Swap buffers by flipping the response index */ - BUG_ON(resp_idx > 1); - priv->resp_idx = resp_idx; - wake_up_interruptible(&priv->waitq); lbs_deb_leave(LBS_DEB_THREAD); } -EXPORT_SYMBOL_GPL(lbs_notify_command_response); +EXPORT_SYMBOL_GPL(lbs_interrupt); static int __init lbs_init_module(void) { diff --git a/trunk/drivers/net/wireless/libertas/rx.c b/trunk/drivers/net/wireless/libertas/rx.c index 05af7316f698..09f023089ea4 100644 --- a/trunk/drivers/net/wireless/libertas/rx.c +++ b/trunk/drivers/net/wireless/libertas/rx.c @@ -145,14 +145,14 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) struct net_device *dev = priv->dev; struct rxpackethdr *p_rx_pkt; struct rxpd *p_rx_pd; + int hdrchop; struct ethhdr *p_ethhdr; + const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; lbs_deb_enter(LBS_DEB_RX); - BUG_ON(!skb); - skb->ip_summed = CHECKSUM_NONE; if (priv->monitormode) diff --git a/trunk/drivers/net/wireless/libertas/tx.c b/trunk/drivers/net/wireless/libertas/tx.c index a4972fed2941..77f1f9525b81 100644 --- a/trunk/drivers/net/wireless/libertas/tx.c +++ b/trunk/drivers/net/wireless/libertas/tx.c @@ -179,17 +179,31 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) * * @returns void */ -void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) +void lbs_send_tx_feedback(struct lbs_private *priv) { struct tx_radiotap_hdr *radiotap_hdr; + u32 status = priv->eventcause; + int txfail; + int try_count; if (!priv->monitormode || priv->currenttxskb == NULL) return; radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; - radiotap_hdr->data_retries = try_count ? - (1 + priv->txretrycount - try_count) : 0; + txfail = (status >> 24); + +#if 0 + /* The version of roofnet that we've tested does not use this yet + * But it may be used in the future. + */ + if (txfail) + radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL; +#endif + try_count = (status >> 16) & 0xff; + radiotap_hdr->data_retries = (try_count) ? + (1 + priv->txretrycount - try_count) : 0; + priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, priv->rtap_net_dev); diff --git a/trunk/drivers/net/wireless/ray_cs.c b/trunk/drivers/net/wireless/ray_cs.c index 963960dc30f2..f3858ee36f32 100644 --- a/trunk/drivers/net/wireless/ray_cs.c +++ b/trunk/drivers/net/wireless/ray_cs.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -2583,7 +2582,7 @@ static char *nettype[] = {"Adhoc", "Infra "}; static char *framing[] = {"Encapsulation", "Translation"} ; /*===========================================================================*/ -static int ray_cs_proc_show(struct seq_file *m, void *v) +static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) { /* Print current values which are not available via other means * eg ifconfig @@ -2607,93 +2606,83 @@ static int ray_cs_proc_show(struct seq_file *m, void *v) if (!local) return 0; - seq_puts(m, "Raylink Wireless LAN driver status\n"); - seq_printf(m, "%s\n", rcsid); + len = 0; + + len += sprintf(buf + len, "Raylink Wireless LAN driver status\n"); + len += sprintf(buf + len, "%s\n", rcsid); /* build 4 does not report version, and field is 0x55 after memtest */ - seq_puts(m, "Firmware version = "); + len += sprintf(buf + len, "Firmware version = "); if (local->fw_ver == 0x55) - seq_puts(m, "4 - Use dump_cis for more details\n"); + len += sprintf(buf + len, "4 - Use dump_cis for more details\n"); else - seq_printf(m, "%2d.%02d.%02d\n", + len += sprintf(buf + len, "%2d.%02d.%02d\n", local->fw_ver, local->fw_bld, local->fw_var); for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i]; c[32] = 0; - seq_printf(m, "%s network ESSID = \"%s\"\n", + len += sprintf(buf + len, "%s network ESSID = \"%s\"\n", nettype[local->sparm.b5.a_network_type], c); p = local->bss_id; - seq_printf(m, "BSSID = %s\n", + len += sprintf(buf + len, "BSSID = %s\n", print_mac(mac, p)); - seq_printf(m, "Country code = %d\n", + len += sprintf(buf + len, "Country code = %d\n", local->sparm.b5.a_curr_country_code); i = local->card_status; if (i < 0) i = 10; if (i > 16) i = 10; - seq_printf(m, "Card status = %s\n", card_status[i]); + len += sprintf(buf + len, "Card status = %s\n", card_status[i]); - seq_printf(m, "Framing mode = %s\n",framing[translate]); + len += sprintf(buf + len, "Framing mode = %s\n",framing[translate]); - seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl); + len += sprintf(buf + len, "Last pkt signal lvl = %d\n", local->last_rsl); if (local->beacon_rxed) { /* Pull some fields out of last beacon received */ - seq_printf(m, "Beacon Interval = %d Kus\n", + len += sprintf(buf + len, "Beacon Interval = %d Kus\n", local->last_bcn.beacon_intvl[0] + 256 * local->last_bcn.beacon_intvl[1]); p = local->last_bcn.elements; if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2; else { - seq_printf(m, "Parse beacon failed at essid element id = %d\n",p[0]); - return 0; + len += sprintf(buf + len, "Parse beacon failed at essid element id = %d\n",p[0]); + return len; } if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { - seq_puts(m, "Supported rate codes = "); + len += sprintf(buf + len, "Supported rate codes = "); for (i=2; idwell_time[0] + 256 * pfh->dwell_time[1]); - seq_printf(m, "Hop set = %d \n", pfh->hop_set); - seq_printf(m, "Hop pattern = %d \n", pfh->hop_pattern); - seq_printf(m, "Hop index = %d \n", pfh->hop_index); + len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set); + len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern); + len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index); p += p[1] + 2; } else { - seq_puts(m, "Parse beacon failed at FH param element\n"); - return 0; + len += sprintf(buf + len, "Parse beacon failed at FH param element\n"); + return len; } } else { - seq_puts(m, "No beacons received\n"); + len += sprintf(buf + len, "No beacons received\n"); } - return 0; + return len; } -static int ray_cs_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, ray_cs_proc_show, NULL); -} - -static const struct file_operations ray_cs_proc_fops = { - .owner = THIS_MODULE, - .open = ray_cs_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; #endif /*===========================================================================*/ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) @@ -2826,7 +2815,7 @@ static int __init init_ray_cs(void) #ifdef CONFIG_PROC_FS proc_mkdir("driver/ray_cs", NULL); - proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); + create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_read); raycs_write("driver/ray_cs/essid", write_essid, NULL); raycs_write("driver/ray_cs/net_type", write_int, &net_type); raycs_write("driver/ray_cs/translate", write_int, &translate); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index f8fe7a139a8a..0361524d193c 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -433,9 +433,11 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, if (delayed_flags & DELAYED_UPDATE_BEACON) { skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); - if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, - skb, &control)) + if (skb) { + rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, + &control); dev_kfree_skb(skb); + } } if (delayed_flags & DELAYED_CONFIG_ERP) diff --git a/trunk/drivers/ssb/driver_pcicore.c b/trunk/drivers/ssb/driver_pcicore.c index 75def13e797d..2cc668ac5609 100644 --- a/trunk/drivers/ssb/driver_pcicore.c +++ b/trunk/drivers/ssb/driver_pcicore.c @@ -562,9 +562,15 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, u32 intvec; intvec = ssb_read32(pdev, SSB_INTVEC); - tmp = ssb_read32(dev, SSB_TPSFLAG); - tmp &= SSB_TPSFLAG_BPFLAG; - intvec |= (1 << tmp); + if ((bus->chip_id & 0xFF00) == 0x4400) { + /* Workaround: On the BCM44XX the BPFLAG routing + * bit is wrong. Use a hardcoded constant. */ + intvec |= 0x00000002; + } else { + tmp = ssb_read32(dev, SSB_TPSFLAG); + tmp &= SSB_TPSFLAG_BPFLAG; + intvec |= (1 << tmp); + } ssb_write32(pdev, SSB_INTVEC, intvec); } diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index 4a80d74975e8..079e7bd86c90 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -1020,7 +1020,8 @@ enum ieee80211_ampdu_mlme_action { * level driver (e.g. assoc/disassoc status, erp parameters). * This function should not be used if no BSS has been set, unless * for association indication. The @changed parameter indicates which - * of the bss parameters has changed when a call is made. + * of the bss parameters has changed when a call is made. This callback + * has to be atomic. * * @configure_filter: Configure the device's RX filter. * See the section "Frame filtering" for more information. diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 699d97b8de5e..8af576c1d2f1 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -33,8 +33,6 @@ nl80211_type_to_mac80211_type(enum nl80211_iftype type) case NL80211_IFTYPE_MESH_POINT: return IEEE80211_IF_TYPE_MESH_POINT; #endif - case NL80211_IFTYPE_WDS: - return IEEE80211_IF_TYPE_WDS; default: return IEEE80211_IF_TYPE_INVALID; } @@ -720,18 +718,12 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct sta_info *sta; if (mac) { - rcu_read_lock(); - /* XXX: get sta belonging to dev */ sta = sta_info_get(local, mac); - if (!sta) { - rcu_read_unlock(); + if (!sta) return -ENOENT; - } sta_info_unlink(&sta); - rcu_read_unlock(); - sta_info_destroy(sta); } else sta_info_flush(local, sdata); @@ -748,23 +740,17 @@ static int ieee80211_change_station(struct wiphy *wiphy, struct sta_info *sta; struct ieee80211_sub_if_data *vlansdata; - rcu_read_lock(); - /* XXX: get sta belonging to dev */ sta = sta_info_get(local, mac); - if (!sta) { - rcu_read_unlock(); + if (!sta) return -ENOENT; - } if (params->vlan && params->vlan != sta->sdata->dev) { vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN || - vlansdata->vif.type != IEEE80211_IF_TYPE_AP) { - rcu_read_unlock(); + vlansdata->vif.type != IEEE80211_IF_TYPE_AP) return -EINVAL; - } sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); ieee80211_send_layer2_update(sta); @@ -772,8 +758,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, sta_apply_parameters(local, sta, params); - rcu_read_unlock(); - return 0; } diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 8e53ce7ed444..c642538e8282 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -102,7 +102,7 @@ struct ieee80211_sta_bss { u64 timestamp; int beacon_int; - bool probe_resp; + int probe_resp; unsigned long last_update; /* during assocation, we save an ERP value from a probe response so @@ -600,7 +600,8 @@ struct ieee80211_local { /* * The lock only protects the list, hash, timer and counter * against manipulation, reads are done in RCU. Additionally, - * the lock protects each BSS's TIM bitmap. + * the lock protects each BSS's TIM bitmap, a few items in + * STA info structures and various key pointers. */ spinlock_t sta_lock; unsigned long num_sta; @@ -634,13 +635,6 @@ struct ieee80211_local { struct list_head interfaces; - /* - * Key lock, protects sdata's key_list and sta_info's - * key pointers (write access, they're RCU.) - */ - spinlock_t key_lock; - - bool sta_sw_scanning; bool sta_hw_scanning; int scan_channel_idx; diff --git a/trunk/net/mac80211/key.c b/trunk/net/mac80211/key.c index 150d66dbda9d..711e36e54ff8 100644 --- a/trunk/net/mac80211/key.c +++ b/trunk/net/mac80211/key.c @@ -74,12 +74,9 @@ static void add_todo(struct ieee80211_key *key, u32 flag) spin_lock(&todo_lock); key->flags |= flag; - /* - * Remove again if already on the list so that we move it to the end. - */ - if (!list_empty(&key->todo)) - list_del(&key->todo); - list_add_tail(&key->todo, &todo_list); + /* only add if not already added */ + if (list_empty(&key->todo)) + list_add(&key->todo, &todo_list); schedule_work(&todo_work); spin_unlock(&todo_lock); } @@ -213,9 +210,9 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) { unsigned long flags; - spin_lock_irqsave(&sdata->local->key_lock, flags); + spin_lock_irqsave(&sdata->local->sta_lock, flags); __ieee80211_set_default_key(sdata, idx); - spin_unlock_irqrestore(&sdata->local->key_lock, flags); + spin_unlock_irqrestore(&sdata->local->sta_lock, flags); } @@ -342,7 +339,7 @@ void ieee80211_key_link(struct ieee80211_key *key, } } - spin_lock_irqsave(&sdata->local->key_lock, flags); + spin_lock_irqsave(&sdata->local->sta_lock, flags); if (sta) old_key = sta->key; @@ -351,81 +348,68 @@ void ieee80211_key_link(struct ieee80211_key *key, __ieee80211_key_replace(sdata, sta, old_key, key); - spin_unlock_irqrestore(&sdata->local->key_lock, flags); + spin_unlock_irqrestore(&sdata->local->sta_lock, flags); /* free old key later */ add_todo(old_key, KEY_FLAG_TODO_DELETE); add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); if (netif_running(sdata->dev)) - add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); + add_todo(key, KEY_FLAG_TODO_HWACCEL); } -static void __ieee80211_key_free(struct ieee80211_key *key) +void ieee80211_key_free(struct ieee80211_key *key) { + unsigned long flags; + + if (!key) + return; + /* * Replace key with nothingness if it was ever used. */ - if (key->sdata) + if (key->sdata) { + spin_lock_irqsave(&key->sdata->local->sta_lock, flags); __ieee80211_key_replace(key->sdata, key->sta, key, NULL); + spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags); + } add_todo(key, KEY_FLAG_TODO_DELETE); } -void ieee80211_key_free(struct ieee80211_key *key) -{ - unsigned long flags; - - if (!key) - return; - - spin_lock_irqsave(&key->sdata->local->key_lock, flags); - __ieee80211_key_free(key); - spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); -} - -/* - * To be safe against concurrent manipulations of the list (which shouldn't - * actually happen) we need to hold the spinlock. But under the spinlock we - * can't actually do much, so we defer processing to the todo list. Then run - * the todo list to be sure the operation and possibly previously pending - * operations are completed. - */ -static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata, - u32 todo_flags) +void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) { struct ieee80211_key *key; - unsigned long flags; might_sleep(); - spin_lock_irqsave(&sdata->local->key_lock, flags); + if (WARN_ON(!netif_running(sdata->dev))) + return; + + ieee80211_key_lock(); + list_for_each_entry(key, &sdata->key_list, list) - add_todo(key, todo_flags); - spin_unlock_irqrestore(&sdata->local->key_lock, flags); + ieee80211_key_enable_hw_accel(key); - ieee80211_key_todo(); + ieee80211_key_unlock(); } -void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) +void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) { - ASSERT_RTNL(); + struct ieee80211_key *key; - if (WARN_ON(!netif_running(sdata->dev))) - return; + might_sleep(); - ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); -} + ieee80211_key_lock(); -void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) -{ - ASSERT_RTNL(); + list_for_each_entry(key, &sdata->key_list, list) + ieee80211_key_disable_hw_accel(key); - ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE); + ieee80211_key_unlock(); } -static void __ieee80211_key_destroy(struct ieee80211_key *key) +static void __ieee80211_key_free(struct ieee80211_key *key) { if (!key) return; @@ -456,8 +440,7 @@ static void __ieee80211_key_todo(void) list_del_init(&key->todo); todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | KEY_FLAG_TODO_DEFKEY | - KEY_FLAG_TODO_HWACCEL_ADD | - KEY_FLAG_TODO_HWACCEL_REMOVE | + KEY_FLAG_TODO_HWACCEL | KEY_FLAG_TODO_DELETE); key->flags &= ~todoflags; spin_unlock(&todo_lock); @@ -473,16 +456,12 @@ static void __ieee80211_key_todo(void) ieee80211_debugfs_key_add_default(key->sdata); work_done = true; } - if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { + if (todoflags & KEY_FLAG_TODO_HWACCEL) { ieee80211_key_enable_hw_accel(key); work_done = true; } - if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) { - ieee80211_key_disable_hw_accel(key); - work_done = true; - } if (todoflags & KEY_FLAG_TODO_DELETE) { - __ieee80211_key_destroy(key); + __ieee80211_key_free(key); work_done = true; } @@ -503,16 +482,14 @@ void ieee80211_key_todo(void) void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) { struct ieee80211_key *key, *tmp; - unsigned long flags; + LIST_HEAD(tmp_list); ieee80211_key_lock(); ieee80211_debugfs_key_remove_default(sdata); - spin_lock_irqsave(&sdata->local->key_lock, flags); list_for_each_entry_safe(key, tmp, &sdata->key_list, list) - __ieee80211_key_free(key); - spin_unlock_irqrestore(&sdata->local->key_lock, flags); + ieee80211_key_free(key); __ieee80211_key_todo(); diff --git a/trunk/net/mac80211/key.h b/trunk/net/mac80211/key.h index f52c3df1fe9a..5d48518985b3 100644 --- a/trunk/net/mac80211/key.h +++ b/trunk/net/mac80211/key.h @@ -54,19 +54,16 @@ struct sta_info; * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an * RCU grace period, no longer be reachable other than from the * todo list. - * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration. - * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware - * acceleration. + * @KEY_FLAG_TODO_HWACCEL: Key needs to be added to hardware acceleration. * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. */ enum ieee80211_internal_key_flags { KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), KEY_FLAG_TODO_DELETE = BIT(1), - KEY_FLAG_TODO_HWACCEL_ADD = BIT(2), - KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3), - KEY_FLAG_TODO_DEFKEY = BIT(4), - KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), + KEY_FLAG_TODO_HWACCEL = BIT(2), + KEY_FLAG_TODO_DEFKEY = BIT(3), + KEY_FLAG_TODO_ADD_DEBUGFS = BIT(4), }; struct ieee80211_key { diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index e9a978979d38..bfcbcf5353ad 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -1587,8 +1587,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, INIT_LIST_HEAD(&local->interfaces); - spin_lock_init(&local->key_lock); - INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); sta_info_init(local); diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index 6b75cb6c6300..bdaab1391d4e 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -350,12 +350,14 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, } } -static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, - bool use_protection, - bool use_short_preamble) + +static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, + u8 erp_value) { struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; struct ieee80211_if_sta *ifsta = &sdata->u.sta; + bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; + bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; DECLARE_MAC_BUF(mac); u32 changed = 0; @@ -386,32 +388,6 @@ static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, return changed; } -static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, - u8 erp_value) -{ - bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; - bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; - - return ieee80211_handle_protect_preamb(sdata, - use_protection, use_short_preamble); -} - -static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_bss *bss) -{ - u32 changed = 0; - - if (bss->has_erp_value) - changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); - else { - u16 capab = bss->capability; - changed |= ieee80211_handle_protect_preamb(sdata, false, - (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); - } - - return changed; -} - int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_ht_info *ht_info) { @@ -535,7 +511,9 @@ static void ieee80211_set_associated(struct net_device *dev, sdata->bss_conf.beacon_int = bss->beacon_int; sdata->bss_conf.timestamp = bss->timestamp; - changed |= ieee80211_handle_bss_capability(sdata, bss); + if (bss->has_erp_value) + changed |= ieee80211_handle_erp_ie( + sdata, bss->erp_value); ieee80211_rx_bss_put(dev, bss); } @@ -2588,29 +2566,22 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #endif } + bss->band = rx_status->band; + + if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && + bss->probe_resp && beacon) { + /* STA mode: + * Do not allow beacon to override data from Probe Response. */ + ieee80211_rx_bss_put(dev, bss); + return; + } + /* save the ERP value so that it is available at association time */ if (elems.erp_info && elems.erp_info_len >= 1) { bss->erp_value = elems.erp_info[0]; bss->has_erp_value = 1; } - if (elems.ht_cap_elem && - (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len || - memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) { - kfree(bss->ht_ie); - bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC); - if (bss->ht_ie) { - memcpy(bss->ht_ie, elems.ht_cap_elem - 2, - elems.ht_cap_elem_len + 2); - bss->ht_ie_len = elems.ht_cap_elem_len + 2; - } else - bss->ht_ie_len = 0; - } else if (!elems.ht_cap_elem && bss->ht_ie) { - kfree(bss->ht_ie); - bss->ht_ie = NULL; - bss->ht_ie_len = 0; - } - bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); @@ -2632,26 +2603,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->supp_rates_len += clen; } - bss->band = rx_status->band; - - bss->timestamp = beacon_timestamp; - bss->last_update = jiffies; - bss->rssi = rx_status->ssi; - bss->signal = rx_status->signal; - bss->noise = rx_status->noise; - if (!beacon && !bss->probe_resp) - bss->probe_resp = true; - - /* - * In STA mode, the remaining parameters should not be overridden - * by beacons because they're not necessarily accurate there. - */ - if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - bss->probe_resp && beacon) { - ieee80211_rx_bss_put(dev, bss); - return; - } - if (elems.wpa && (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len || memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { @@ -2684,20 +2635,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->rsn_ie_len = 0; } - /* - * Cf. - * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC - * - * quoting: - * - * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia - * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi - * Alliance (September 1, 2004) is incorporated by reference herein. - * The inclusion of the WMM Parameters in probe responses and - * association responses is mandatory for WMM enabled networks. The - * inclusion of the WMM Parameters in beacons, however, is optional. - */ - if (elems.wmm_param && (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len || memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { @@ -2714,6 +2651,30 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->wmm_ie = NULL; bss->wmm_ie_len = 0; } + if (elems.ht_cap_elem && + (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len || + memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) { + kfree(bss->ht_ie); + bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC); + if (bss->ht_ie) { + memcpy(bss->ht_ie, elems.ht_cap_elem - 2, + elems.ht_cap_elem_len + 2); + bss->ht_ie_len = elems.ht_cap_elem_len + 2; + } else + bss->ht_ie_len = 0; + } else if (!elems.ht_cap_elem && bss->ht_ie) { + kfree(bss->ht_ie); + bss->ht_ie = NULL; + bss->ht_ie_len = 0; + } + + bss->timestamp = beacon_timestamp; + bss->last_update = jiffies; + bss->rssi = rx_status->ssi; + bss->signal = rx_status->signal; + bss->noise = rx_status->noise; + if (!beacon) + bss->probe_resp++; /* check if we need to merge IBSS */ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && @@ -2814,24 +2775,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); - if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, - elems.wmm_param_len); - } - - /* Do not send changes to driver if we are scanning. This removes - * requirement that driver's bss_info_changed function needs to be - * atomic. */ - if (local->sta_sw_scanning || local->sta_hw_scanning) - return; - if (elems.erp_info && elems.erp_info_len >= 1) changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); - else { - u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info); - changed |= ieee80211_handle_protect_preamb(sdata, false, - (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); - } if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { @@ -2844,6 +2789,11 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, &bss_info); } + if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { + ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, + elems.wmm_param_len); + } + ieee80211_bss_info_change_notify(sdata, changed); } diff --git a/trunk/net/mac80211/wext.c b/trunk/net/mac80211/wext.c index 76e1de1dc735..69aed16faff3 100644 --- a/trunk/net/mac80211/wext.c +++ b/trunk/net/mac80211/wext.c @@ -236,9 +236,6 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, case IW_MODE_ADHOC: type = IEEE80211_IF_TYPE_IBSS; break; - case IW_MODE_REPEAT: - type = IEEE80211_IF_TYPE_WDS; - break; case IW_MODE_MONITOR: type = IEEE80211_IF_TYPE_MNTR; break; @@ -983,8 +980,6 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sta_info *sta = NULL; - rcu_read_lock(); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || sdata->vif.type == IEEE80211_IF_TYPE_IBSS) sta = sta_info_get(local, sdata->u.sta.bssid); @@ -1001,9 +996,6 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev wstats->qual.noise = sta->last_noise; wstats->qual.updated = local->wstats_flags; } - - rcu_read_unlock(); - return wstats; } diff --git a/trunk/net/tipc/ref.c b/trunk/net/tipc/ref.c index 89cbab24d08f..c38744c96ed1 100644 --- a/trunk/net/tipc/ref.c +++ b/trunk/net/tipc/ref.c @@ -2,7 +2,7 @@ * net/tipc/ref.c: TIPC object registry code * * Copyright (c) 1991-2006, Ericsson AB - * Copyright (c) 2004-2007, Wind River Systems + * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,60 +36,32 @@ #include "core.h" #include "ref.h" - -/** - * struct reference - TIPC object reference entry - * @object: pointer to object associated with reference entry - * @lock: spinlock controlling access to object - * @ref: reference value for object (combines instance & array index info) - */ - -struct reference { - void *object; - spinlock_t lock; - u32 ref; -}; - -/** - * struct tipc_ref_table - table of TIPC object reference entries - * @entries: pointer to array of reference entries - * @capacity: array index of first unusable entry - * @init_point: array index of first uninitialized entry - * @first_free: array index of first unused object reference entry - * @last_free: array index of last unused object reference entry - * @index_mask: bitmask for array index portion of reference values - * @start_mask: initial value for instance value portion of reference values - */ - -struct ref_table { - struct reference *entries; - u32 capacity; - u32 init_point; - u32 first_free; - u32 last_free; - u32 index_mask; - u32 start_mask; -}; +#include "port.h" +#include "subscr.h" +#include "name_distr.h" +#include "name_table.h" +#include "config.h" +#include "discover.h" +#include "bearer.h" +#include "node.h" +#include "bcast.h" /* * Object reference table consists of 2**N entries. * - * State Object ptr Reference - * ----- ---------- --------- - * In use non-NULL XXXX|own index - * (XXXX changes each time entry is acquired) - * Free NULL YYYY|next free index - * (YYYY is one more than last used XXXX) - * Uninitialized NULL 0 + * A used entry has object ptr != 0, reference == XXXX|own index + * (XXXX changes each time entry is acquired) + * A free entry has object ptr == 0, reference == YYYY|next free index + * (YYYY is one more than last used XXXX) * - * Entry 0 is not used; this allows index 0 to denote the end of the free list. + * Free list is initially chained from entry (2**N)-1 to entry 1. + * Entry 0 is not used to allow index 0 to indicate the end of the free list. * - * Note that a reference value of 0 does not necessarily indicate that an - * entry is uninitialized, since the last entry in the free list could also - * have a reference value of 0 (although this is unlikely). + * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0 + * because entry 0's reference field has the form XXXX|1--1. */ -static struct ref_table tipc_ref_table = { NULL }; +struct ref_table tipc_ref_table = { NULL }; static DEFINE_RWLOCK(ref_table_lock); @@ -100,29 +72,29 @@ static DEFINE_RWLOCK(ref_table_lock); int tipc_ref_table_init(u32 requested_size, u32 start) { struct reference *table; - u32 actual_size; - - /* account for unused entry, then round up size to a power of 2 */ - - requested_size++; - for (actual_size = 16; actual_size < requested_size; actual_size <<= 1) - /* do nothing */ ; - - /* allocate table & mark all entries as uninitialized */ + u32 sz = 1 << 4; + u32 index_mask; + int i; - table = __vmalloc(actual_size * sizeof(struct reference), - GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); + while (sz < requested_size) { + sz <<= 1; + } + table = vmalloc(sz * sizeof(*table)); if (table == NULL) return -ENOMEM; + write_lock_bh(&ref_table_lock); + index_mask = sz - 1; + for (i = sz - 1; i >= 0; i--) { + table[i].object = NULL; + spin_lock_init(&table[i].lock); + table[i].data.next_plus_upper = (start & ~index_mask) + i - 1; + } tipc_ref_table.entries = table; - tipc_ref_table.capacity = requested_size; - tipc_ref_table.init_point = 1; - tipc_ref_table.first_free = 0; - tipc_ref_table.last_free = 0; - tipc_ref_table.index_mask = actual_size - 1; - tipc_ref_table.start_mask = start & ~tipc_ref_table.index_mask; - + tipc_ref_table.index_mask = index_mask; + tipc_ref_table.first_free = sz - 1; + tipc_ref_table.last_free = 1; + write_unlock_bh(&ref_table_lock); return TIPC_OK; } @@ -153,7 +125,7 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) u32 index; u32 index_mask; u32 next_plus_upper; - u32 ref; + u32 reference = 0; if (!object) { err("Attempt to acquire reference to non-existent object\n"); @@ -164,8 +136,6 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) return 0; } - /* take a free entry, if available; otherwise initialize a new entry */ - write_lock_bh(&ref_table_lock); if (tipc_ref_table.first_free) { index = tipc_ref_table.first_free; @@ -173,29 +143,17 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) index_mask = tipc_ref_table.index_mask; /* take lock in case a previous user of entry still holds it */ spin_lock_bh(&entry->lock); - next_plus_upper = entry->ref; + next_plus_upper = entry->data.next_plus_upper; tipc_ref_table.first_free = next_plus_upper & index_mask; - ref = (next_plus_upper & ~index_mask) + index; - entry->ref = ref; + reference = (next_plus_upper & ~index_mask) + index; + entry->data.reference = reference; entry->object = object; + if (lock != NULL) + *lock = &entry->lock; spin_unlock_bh(&entry->lock); - *lock = &entry->lock; - } - else if (tipc_ref_table.init_point < tipc_ref_table.capacity) { - index = tipc_ref_table.init_point++; - entry = &(tipc_ref_table.entries[index]); - spin_lock_init(&entry->lock); - ref = tipc_ref_table.start_mask + index; - entry->ref = ref; - entry->object = object; - *lock = &entry->lock; - } - else { - ref = 0; } write_unlock_bh(&ref_table_lock); - - return ref; + return reference; } /** @@ -211,99 +169,42 @@ void tipc_ref_discard(u32 ref) u32 index; u32 index_mask; + if (!ref) { + err("Attempt to discard reference 0\n"); + return; + } if (!tipc_ref_table.entries) { err("Reference table not found during discard attempt\n"); return; } + write_lock_bh(&ref_table_lock); index_mask = tipc_ref_table.index_mask; index = ref & index_mask; entry = &(tipc_ref_table.entries[index]); - write_lock_bh(&ref_table_lock); - if (!entry->object) { err("Attempt to discard reference to non-existent object\n"); goto exit; } - if (entry->ref != ref) { + if (entry->data.reference != ref) { err("Attempt to discard non-existent reference\n"); goto exit; } - /* - * mark entry as unused; increment instance part of entry's reference - * to invalidate any subsequent references - */ - + /* mark entry as unused */ entry->object = NULL; - entry->ref = (ref & ~index_mask) + (index_mask + 1); - - /* append entry to free entry list */ - if (tipc_ref_table.first_free == 0) tipc_ref_table.first_free = index; else - tipc_ref_table.entries[tipc_ref_table.last_free].ref |= index; + /* next_plus_upper is always XXXX|0--0 for last free entry */ + tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper + |= index; tipc_ref_table.last_free = index; + /* increment upper bits of entry to invalidate subsequent references */ + entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1); exit: write_unlock_bh(&ref_table_lock); } -/** - * tipc_ref_lock - lock referenced object and return pointer to it - */ - -void *tipc_ref_lock(u32 ref) -{ - if (likely(tipc_ref_table.entries)) { - struct reference *entry; - - entry = &tipc_ref_table.entries[ref & - tipc_ref_table.index_mask]; - if (likely(entry->ref != 0)) { - spin_lock_bh(&entry->lock); - if (likely((entry->ref == ref) && (entry->object))) - return entry->object; - spin_unlock_bh(&entry->lock); - } - } - return NULL; -} - -/** - * tipc_ref_unlock - unlock referenced object - */ - -void tipc_ref_unlock(u32 ref) -{ - if (likely(tipc_ref_table.entries)) { - struct reference *entry; - - entry = &tipc_ref_table.entries[ref & - tipc_ref_table.index_mask]; - if (likely((entry->ref == ref) && (entry->object))) - spin_unlock_bh(&entry->lock); - else - err("Attempt to unlock non-existent reference\n"); - } -} - -/** - * tipc_ref_deref - return pointer referenced object (without locking it) - */ - -void *tipc_ref_deref(u32 ref) -{ - if (likely(tipc_ref_table.entries)) { - struct reference *entry; - - entry = &tipc_ref_table.entries[ref & - tipc_ref_table.index_mask]; - if (likely(entry->ref == ref)) - return entry->object; - } - return NULL; -} - diff --git a/trunk/net/tipc/ref.h b/trunk/net/tipc/ref.h index 7e3798ea93b9..38f3a7f4a78d 100644 --- a/trunk/net/tipc/ref.h +++ b/trunk/net/tipc/ref.h @@ -2,7 +2,7 @@ * net/tipc/ref.h: Include file for TIPC object registry code * * Copyright (c) 1991-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,14 +37,95 @@ #ifndef _TIPC_REF_H #define _TIPC_REF_H +/** + * struct reference - TIPC object reference entry + * @object: pointer to object associated with reference entry + * @lock: spinlock controlling access to object + * @data: reference value associated with object (or link to next unused entry) + */ + +struct reference { + void *object; + spinlock_t lock; + union { + u32 next_plus_upper; + u32 reference; + } data; +}; + +/** + * struct tipc_ref_table - table of TIPC object reference entries + * @entries: pointer to array of reference entries + * @index_mask: bitmask for array index portion of reference values + * @first_free: array index of first unused object reference entry + * @last_free: array index of last unused object reference entry + */ + +struct ref_table { + struct reference *entries; + u32 index_mask; + u32 first_free; + u32 last_free; +}; + +extern struct ref_table tipc_ref_table; + int tipc_ref_table_init(u32 requested_size, u32 start); void tipc_ref_table_stop(void); u32 tipc_ref_acquire(void *object, spinlock_t **lock); void tipc_ref_discard(u32 ref); -void *tipc_ref_lock(u32 ref); -void tipc_ref_unlock(u32 ref); -void *tipc_ref_deref(u32 ref); + +/** + * tipc_ref_lock - lock referenced object and return pointer to it + */ + +static inline void *tipc_ref_lock(u32 ref) +{ + if (likely(tipc_ref_table.entries)) { + struct reference *r = + &tipc_ref_table.entries[ref & tipc_ref_table.index_mask]; + + spin_lock_bh(&r->lock); + if (likely(r->data.reference == ref)) + return r->object; + spin_unlock_bh(&r->lock); + } + return NULL; +} + +/** + * tipc_ref_unlock - unlock referenced object + */ + +static inline void tipc_ref_unlock(u32 ref) +{ + if (likely(tipc_ref_table.entries)) { + struct reference *r = + &tipc_ref_table.entries[ref & tipc_ref_table.index_mask]; + + if (likely(r->data.reference == ref)) + spin_unlock_bh(&r->lock); + else + err("tipc_ref_unlock() invoked using obsolete reference\n"); + } +} + +/** + * tipc_ref_deref - return pointer referenced object (without locking it) + */ + +static inline void *tipc_ref_deref(u32 ref) +{ + if (likely(tipc_ref_table.entries)) { + struct reference *r = + &tipc_ref_table.entries[ref & tipc_ref_table.index_mask]; + + if (likely(r->data.reference == ref)) + return r->object; + } + return NULL; +} #endif