From: John W. Linville Date: Fri, 15 Jul 2011 14:05:24 +0000 (-0400) Subject: Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel... X-Git-Tag: firefly_0821_release~3680^2~5008^2~124^2 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=95a943c162d74b20d869917bdf5df11293c35b63;hp=-c;p=firefly-linux-kernel-4.4.55.git Merge branch 'master' of git://git./linux/kernel/git/linville/wireless-next-2.6 into for-davem Conflicts: net/bluetooth/l2cap_core.c --- 95a943c162d74b20d869917bdf5df11293c35b63 diff --combined drivers/net/wireless/ath/ath5k/base.c index fb05bf89b8e3,5f055d69b220..dce848f76d7c --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@@ -42,7 -42,6 +42,7 @@@ #include #include +#include #include #include #include @@@ -532,7 -531,7 +532,7 @@@ ath5k_update_bssid_mask_and_opmode(stru if (iter_data.n_stas > 1) { /* If you have multiple STA interfaces connected to * different APs, ARPs are not received (most of the time?) - * Enabling PROMISC appears to fix that probem. + * Enabling PROMISC appears to fix that problem. */ sc->filter_flags |= AR5K_RX_FILTER_PROM; } @@@ -815,8 -814,7 +815,7 @@@ ath5k_desc_alloc(struct ath5k_softc *sc INIT_LIST_HEAD(&sc->txbuf); sc->txbuf_len = ATH_TXBUF; - for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, - da += sizeof(*ds)) { + for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) { bf->desc = ds; bf->daddr = da; list_add_tail(&bf->list, &sc->txbuf); @@@ -982,7 -980,7 +981,7 @@@ ath5k_beaconq_config(struct ath5k_soft goto err; if (sc->opmode == NL80211_IFTYPE_AP || - sc->opmode == NL80211_IFTYPE_MESH_POINT) { + sc->opmode == NL80211_IFTYPE_MESH_POINT) { /* * Always burst out beacon and CAB traffic * (aifs = cwmin = cwmax = 0) @@@ -1262,16 -1260,15 +1261,15 @@@ ath5k_update_beacon_rssi(struct ath5k_s */ static int ath5k_common_padpos(struct sk_buff *skb) { - struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 frame_control = hdr->frame_control; int padpos = 24; - if (ieee80211_has_a4(frame_control)) { + if (ieee80211_has_a4(frame_control)) padpos += ETH_ALEN; - } - if (ieee80211_is_data_qos(frame_control)) { + + if (ieee80211_is_data_qos(frame_control)) padpos += IEEE80211_QOS_CTL_LEN; - } return padpos; } @@@ -1285,13 -1282,13 +1283,13 @@@ static int ath5k_add_padding(struct sk_ int padpos = ath5k_common_padpos(skb); int padsize = padpos & 3; - if (padsize && skb->len>padpos) { + if (padsize && skb->len > padpos) { if (skb_headroom(skb) < padsize) return -1; skb_push(skb, padsize); - memmove(skb->data, skb->data+padsize, padpos); + memmove(skb->data, skb->data + padsize, padpos); return padsize; } @@@ -1316,7 -1313,7 +1314,7 @@@ static int ath5k_remove_padding(struct int padpos = ath5k_common_padpos(skb); int padsize = padpos & 3; - if (padsize && skb->len>=padpos+padsize) { + if (padsize && skb->len >= padpos + padsize) { memmove(skb->data + padsize, skb->data, padpos); skb_pull(skb, padsize); return padsize; @@@ -1352,7 -1349,7 +1350,7 @@@ ath5k_receive_frame(struct ath5k_softc * timestamp (beginning of phy frame, data frame, end of rx?). * The only thing we know is that it is hardware specific... * On AR5213 it seems the rx timestamp is at the end of the - * frame, but i'm not sure. + * frame, but I'm not sure. * * NOTE: mac80211 defines mactime at the beginning of the first * data symbol. Since we don't have any time references it's @@@ -1450,10 -1447,11 +1448,11 @@@ ath5k_receive_frame_ok(struct ath5k_sof static void ath5k_set_current_imask(struct ath5k_softc *sc) { - enum ath5k_int imask = sc->imask; + enum ath5k_int imask; unsigned long flags; spin_lock_irqsave(&sc->irqlock, flags); + imask = sc->imask; if (sc->rx_pending) imask &= ~AR5K_INT_RX_ALL; if (sc->tx_pending) @@@ -1556,7 -1554,8 +1555,8 @@@ ath5k_tx_queue(struct ieee80211_hw *hw goto drop_packet; } - if (txq->txq_len >= txq->txq_max) + if (txq->txq_len >= txq->txq_max && + txq->qnum <= AR5K_TX_QUEUE_ID_DATA_MAX) ieee80211_stop_queue(hw, txq->qnum); spin_lock_irqsave(&sc->txbuflock, flags); @@@ -1711,7 -1710,7 +1711,7 @@@ ath5k_tasklet_tx(unsigned long data int i; struct ath5k_softc *sc = (void *)data; - for (i=0; i < AR5K_NUM_TX_QUEUES; i++) + for (i = 0; i < AR5K_NUM_TX_QUEUES; i++) if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) ath5k_tx_processq(sc, &sc->txqs[i]); @@@ -1766,7 -1765,7 +1766,7 @@@ ath5k_beacon_setup(struct ath5k_softc * * 4 beacons to make sure everybody hears our AP. * When a client tries to associate, hw will keep * track of the tx antenna to be used for this client - * automaticaly, based on ACKed packets. + * automatically, based on ACKed packets. * * Note: AP still listens and transmits RTS on the * default antenna which is supposed to be an omni. @@@ -1902,7 -1901,7 +1902,7 @@@ ath5k_beacon_send(struct ath5k_softc *s avf = (void *)vif->drv_priv; bf = avf->bbuf; if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || - sc->opmode == NL80211_IFTYPE_MONITOR)) { + sc->opmode == NL80211_IFTYPE_MONITOR)) { ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); return; } @@@ -1919,7 -1918,7 +1919,7 @@@ /* refresh the beacon for AP or MESH mode */ if (sc->opmode == NL80211_IFTYPE_AP || - sc->opmode == NL80211_IFTYPE_MESH_POINT) + sc->opmode == NL80211_IFTYPE_MESH_POINT) ath5k_beacon_update(sc->hw, vif); trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]); @@@ -1932,6 -1931,10 +1932,10 @@@ skb = ieee80211_get_buffered_bc(sc->hw, vif); while (skb) { ath5k_tx_queue(sc->hw, skb, sc->cabq); + + if (sc->cabq->txq_len >= sc->cabq->txq_max) + break; + skb = ieee80211_get_buffered_bc(sc->hw, vif); } @@@ -1978,7 -1981,7 +1982,7 @@@ ath5k_beacon_update_timers(struct ath5k hw_tsf = ath5k_hw_get_tsf64(ah); hw_tu = TSF_TO_TU(hw_tsf); - #define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3 + #define FUDGE (AR5K_TUNE_SW_BEACON_RESP + 3) /* We use FUDGE to make sure the next TBTT is ahead of the current TU. * Since we later subtract AR5K_TUNE_SW_BEACON_RESP (10) in the timer * configuration we need to make sure it is bigger than that. */ @@@ -2101,11 -2104,11 +2105,11 @@@ static void ath5k_tasklet_beacon(unsign * * In IBSS mode we use this interrupt just to * keep track of the next TBTT (target beacon - * transmission time) in order to detect wether + * transmission time) in order to detect whether * automatic TSF updates happened. */ if (sc->opmode == NL80211_IFTYPE_ADHOC) { - /* XXX: only if VEOL suppported */ + /* XXX: only if VEOL supported */ u64 tsf = ath5k_hw_get_tsf64(sc->ah); sc->nexttbtt += sc->bintval; ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, @@@ -2200,13 -2203,12 +2204,12 @@@ ath5k_intr(int irq, void *dev_id ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "rx overrun, resetting\n"); ieee80211_queue_work(sc->hw, &sc->reset_work); - } - else + } else ath5k_schedule_rx(sc); } else { - if (status & AR5K_INT_SWBA) { + if (status & AR5K_INT_SWBA) tasklet_hi_schedule(&sc->beacontq); - } + if (status & AR5K_INT_RXEOL) { /* * NB: the hardware should re-read the link when @@@ -2358,7 -2360,7 +2361,7 @@@ ath5k_tx_complete_poll_work(struct work * Initialization routines * \*************************/ - int + int __devinit ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) { struct ieee80211_hw *hw = sc->hw; @@@ -2423,6 -2425,7 +2426,7 @@@ common->ah = sc->ah; common->hw = hw; common->priv = sc; + common->clockrate = 40; /* * Cache line size is used to size and align various @@@ -2469,7 -2472,7 +2473,7 @@@ sc->ah->ah_radio_5ghz_revision), sc->ah->ah_radio_5ghz_revision); /* No 2GHz support (5110 and some - * 5Ghz only cards) -> report 5Ghz radio */ + * 5GHz only cards) -> report 5GHz radio */ } else if (!test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) { ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", @@@ -2488,7 -2491,7 +2492,7 @@@ /* Multi chip radio (RF5111 - RF2111) -> * report both 2GHz/5GHz radios */ else if (sc->ah->ah_radio_5ghz_revision && - sc->ah->ah_radio_2ghz_revision){ + sc->ah->ah_radio_2ghz_revision) { ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", ath5k_chip_name(AR5K_VERSION_RAD, sc->ah->ah_radio_5ghz_revision), @@@ -2713,8 -2716,7 +2717,7 @@@ ath5k_reset(struct ath5k_softc *sc, str fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, - skip_pcu); + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, skip_pcu); if (ret) { ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); goto err; @@@ -2728,7 -2730,7 +2731,7 @@@ ath5k_ani_init(ah, ani_mode); - ah->ah_cal_next_full = jiffies; + ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100); ah->ah_cal_next_ani = jiffies; ah->ah_cal_next_nf = jiffies; ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); @@@ -2772,7 -2774,7 +2775,7 @@@ static void ath5k_reset_work(struct wor mutex_unlock(&sc->lock); } - static int + static int __devinit ath5k_init(struct ieee80211_hw *hw) { @@@ -2800,7 -2802,7 +2803,7 @@@ /* * Collect the channel list. The 802.11 layer - * is resposible for filtering this list based + * is responsible for filtering this list based * on settings like the phy mode and regulatory * domain restrictions. */ diff --combined drivers/net/wireless/b43/main.c index e9a01e3eede7,8bcda5084dec..092dd9318869 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@@ -1155,6 -1155,21 +1155,21 @@@ void b43_power_saving_ctl_bits(struct b } } + #ifdef CONFIG_B43_BCMA + static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) + { + u32 flags = 0; + + if (gmode) + flags = B43_BCMA_IOCTL_GMODE; + flags |= B43_BCMA_IOCTL_PHY_CLKEN; + flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */ + b43_device_enable(dev, flags); + + /* TODO: reset PHY */ + } + #endif + static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode) { struct ssb_device *sdev = dev->dev->sdev; @@@ -1187,7 -1202,18 +1202,18 @@@ void b43_wireless_core_reset(struct b43 { u32 macctl; - b43_ssb_wireless_core_reset(dev, gmode); + switch (dev->dev->bus_type) { + #ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + b43_bcma_wireless_core_reset(dev, gmode); + break; + #endif + #ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + b43_ssb_wireless_core_reset(dev, gmode); + break; + #endif + } /* Turn Analog ON, but only if we already know the PHY-type. * This protects against very early setup where we don't know the @@@ -1938,7 -1964,7 +1964,7 @@@ static irqreturn_t b43_do_interrupt(str return IRQ_NONE; reason &= dev->irq_mask; if (!reason) - return IRQ_HANDLED; + return IRQ_NONE; dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) & 0x0001DC00; @@@ -2133,21 -2159,43 +2159,43 @@@ static int b43_try_request_fw(struct b4 u32 tmshigh; int err; + /* Files for HT and LCN were found by trying one by one */ + /* Get microcode */ - if ((rev >= 5) && (rev <= 10)) + if ((rev >= 5) && (rev <= 10)) { filename = "ucode5"; - else if ((rev >= 11) && (rev <= 12)) + } else if ((rev >= 11) && (rev <= 12)) { filename = "ucode11"; - else if (rev == 13) + } else if (rev == 13) { filename = "ucode13"; - else if (rev == 14) + } else if (rev == 14) { filename = "ucode14"; - else if (rev == 15) + } else if (rev == 15) { filename = "ucode15"; - else if ((rev >= 16) && (rev <= 20)) - filename = "ucode16_mimo"; - else - goto err_no_ucode; + } else { + switch (dev->phy.type) { + case B43_PHYTYPE_N: + if (rev >= 16) + filename = "ucode16_mimo"; + else + goto err_no_ucode; + break; + case B43_PHYTYPE_HT: + if (rev == 29) + filename = "ucode29_mimo"; + else + goto err_no_ucode; + break; + case B43_PHYTYPE_LCN: + if (rev == 24) + filename = "ucode24_mimo"; + else + goto err_no_ucode; + break; + default: + goto err_no_ucode; + } + } err = b43_do_request_fw(ctx, filename, &fw->ucode); if (err) goto err_load; @@@ -2206,6 -2254,18 +2254,18 @@@ else goto err_no_initvals; break; + case B43_PHYTYPE_HT: + if (rev == 29) + filename = "ht0initvals29"; + else + goto err_no_initvals; + break; + case B43_PHYTYPE_LCN: + if (rev == 24) + filename = "lcn0initvals24"; + else + goto err_no_initvals; + break; default: goto err_no_initvals; } @@@ -2253,6 -2313,18 +2313,18 @@@ else goto err_no_initvals; break; + case B43_PHYTYPE_HT: + if (rev == 29) + filename = "ht0bsinitvals29"; + else + goto err_no_initvals; + break; + case B43_PHYTYPE_LCN: + if (rev == 24) + filename = "lcn0bsinitvals24"; + else + goto err_no_initvals; + break; default: goto err_no_initvals; } @@@ -2624,11 -2696,24 +2696,24 @@@ static int b43_gpio_init(struct b43_wld if (dev->dev->core_rev >= 2) mask |= 0x0010; /* FIXME: This is redundant. */ - gpiodev = b43_ssb_gpio_dev(dev); - if (gpiodev) - ssb_write32(gpiodev, B43_GPIO_CONTROL, - (ssb_read32(gpiodev, B43_GPIO_CONTROL) - & mask) | set); + switch (dev->dev->bus_type) { + #ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, + (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc, + BCMA_CC_GPIOCTL) & mask) | set); + break; + #endif + #ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + gpiodev = b43_ssb_gpio_dev(dev); + if (gpiodev) + ssb_write32(gpiodev, B43_GPIO_CONTROL, + (ssb_read32(gpiodev, B43_GPIO_CONTROL) + & mask) | set); + break; + #endif + } return 0; } @@@ -2638,9 -2723,21 +2723,21 @@@ static void b43_gpio_cleanup(struct b43 { struct ssb_device *gpiodev; - gpiodev = b43_ssb_gpio_dev(dev); - if (gpiodev) - ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); + switch (dev->dev->bus_type) { + #ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, + 0); + break; + #endif + #ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + gpiodev = b43_ssb_gpio_dev(dev); + if (gpiodev) + ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); + break; + #endif + } } /* http://bcm-specs.sipsolutions.net/EnableMac */ @@@ -2712,12 -2809,30 +2809,30 @@@ out /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) { - u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); - if (on) - tmslow |= B43_TMSLOW_MACPHYCLKEN; - else - tmslow &= ~B43_TMSLOW_MACPHYCLKEN; - ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); + u32 tmp; + + switch (dev->dev->bus_type) { + #ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + tmp = bcma_read32(dev->dev->bdev, BCMA_IOCTL); + if (on) + tmp |= B43_BCMA_IOCTL_MACPHYCLKEN; + else + tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN; + bcma_write32(dev->dev->bdev, BCMA_IOCTL, tmp); + break; + #endif + #ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); + if (on) + tmp |= B43_TMSLOW_MACPHYCLKEN; + else + tmp &= ~B43_TMSLOW_MACPHYCLKEN; + ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); + break; + #endif + } } static void b43_adjust_opmode(struct b43_wldev *dev) @@@ -2956,8 -3071,20 +3071,20 @@@ static int b43_chip_init(struct b43_wld b43_mac_phy_clock_set(dev, true); - b43_write16(dev, B43_MMIO_POWERUP_DELAY, - dev->sdev->bus->chipco.fast_pwrup_delay); + switch (dev->dev->bus_type) { + #ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + /* FIXME: 0xE74 is quite common, but should be read from CC */ + b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74); + break; + #endif + #ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + b43_write16(dev, B43_MMIO_POWERUP_DELAY, + dev->dev->sdev->bus->chipco.fast_pwrup_delay); + break; + #endif + } err = 0; b43dbg(dev->wl, "Chip initialized\n"); @@@ -3473,21 -3600,33 +3600,33 @@@ static void b43_op_set_tsf(struct ieee8 static void b43_put_phy_into_reset(struct b43_wldev *dev) { - struct ssb_device *sdev = dev->sdev; - u32 tmslow; + u32 tmp; - tmslow = ssb_read32(sdev, SSB_TMSLOW); - tmslow &= ~B43_TMSLOW_GMODE; - tmslow |= B43_TMSLOW_PHYRESET; - tmslow |= SSB_TMSLOW_FGC; - ssb_write32(sdev, SSB_TMSLOW, tmslow); - msleep(1); + switch (dev->dev->bus_type) { + #ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + b43err(dev->wl, + "Putting PHY into reset not supported on BCMA\n"); + break; + #endif + #ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); + tmp &= ~B43_TMSLOW_GMODE; + tmp |= B43_TMSLOW_PHYRESET; + tmp |= SSB_TMSLOW_FGC; + ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); + msleep(1); + + tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); + tmp &= ~SSB_TMSLOW_FGC; + tmp |= B43_TMSLOW_PHYRESET; + ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); + msleep(1); - tmslow = ssb_read32(sdev, SSB_TMSLOW); - tmslow &= ~SSB_TMSLOW_FGC; - tmslow |= B43_TMSLOW_PHYRESET; - ssb_write32(sdev, SSB_TMSLOW, tmslow); - msleep(1); + break; + #endif + } } static const char *band_to_string(enum ieee80211_band band) @@@ -4103,10 -4242,16 +4242,16 @@@ static int b43_phy_versioning(struct b4 if (phy_rev > 1) unsupported = 1; break; + #endif + #ifdef CONFIG_B43_PHY_LCN + case B43_PHYTYPE_LCN: + if (phy_rev > 1) + unsupported = 1; + break; #endif default: unsupported = 1; - }; + } if (unsupported) { b43err(dev->wl, "FOUND UNSUPPORTED PHY " "(Analog %u, Type %u, Revision %u)\n", @@@ -4117,22 -4262,42 +4262,42 @@@ analog_type, phy_type, phy_rev); /* Get RADIO versioning */ - if (dev->dev->chip_id == 0x4317) { - if (dev->dev->chip_rev == 0) - tmp = 0x3205017F; - else if (dev->dev->chip_rev == 1) - tmp = 0x4205017F; - else - tmp = 0x5205017F; + if (dev->dev->core_rev >= 24) { + u16 radio24[3]; + + for (tmp = 0; tmp < 3; tmp++) { + b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp); + radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); + } + + /* Broadcom uses "id" for our "ver" and has separated "ver" */ + /* radio_ver = (radio24[0] & 0xF0) >> 4; */ + + radio_manuf = 0x17F; + radio_ver = (radio24[2] << 8) | radio24[1]; + radio_rev = (radio24[0] & 0xF); } else { - b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID); - tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); - b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID); - tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16; - } - radio_manuf = (tmp & 0x00000FFF); - radio_ver = (tmp & 0x0FFFF000) >> 12; - radio_rev = (tmp & 0xF0000000) >> 28; + if (dev->dev->chip_id == 0x4317) { + if (dev->dev->chip_rev == 0) + tmp = 0x3205017F; + else if (dev->dev->chip_rev == 1) + tmp = 0x4205017F; + else + tmp = 0x5205017F; + } else { + b43_write16(dev, B43_MMIO_RADIO_CONTROL, + B43_RADIOCTL_ID); + tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); + b43_write16(dev, B43_MMIO_RADIO_CONTROL, + B43_RADIOCTL_ID); + tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) + << 16; + } + radio_manuf = (tmp & 0x00000FFF); + radio_ver = (tmp & 0x0FFFF000) >> 12; + radio_rev = (tmp & 0xF0000000) >> 28; + } + if (radio_manuf != 0x17F /* Broadcom */) unsupported = 1; switch (phy_type) { @@@ -4164,6 -4329,10 +4329,10 @@@ if (radio_ver != 0x2059) unsupported = 1; break; + case B43_PHYTYPE_LCN: + if (radio_ver != 0x2064) + unsupported = 1; + break; default: B43_WARN_ON(1); } @@@ -4347,7 -4516,6 +4516,6 @@@ static void b43_wireless_core_exit(stru /* Initialize a wireless core */ static int b43_wireless_core_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->sdev->bus; struct ssb_sprom *sprom = dev->dev->bus_sprom; struct b43_phy *phy = &dev->phy; int err; @@@ -4366,7 -4534,20 +4534,20 @@@ phy->ops->prepare_structs(dev); /* Enable IRQ routing to this device. */ - ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev); + switch (dev->dev->bus_type) { + #ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci, + dev->dev->bdev, true); + break; + #endif + #ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + ssb_pcicore_dev_irqvecs_enable(&dev->dev->sdev->bus->pcicore, + dev->dev->sdev); + break; + #endif + } b43_imcfglo_timeouts_workaround(dev); b43_bluetooth_coext_disable(dev); @@@ -4397,8 -4578,9 +4578,9 @@@ if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW) hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */ #ifdef CONFIG_SSB_DRIVER_PCICORE - if ((bus->bustype == SSB_BUSTYPE_PCI) && - (bus->pcicore.dev->id.revision <= 10)) + if (dev->dev->bus_type == B43_BUS_SSB && + dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && + dev->dev->sdev->bus->pcicore.dev->id.revision <= 10) hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */ #endif hf &= ~B43_HF_SKCFPUP; @@@ -4764,8 -4946,7 +4946,7 @@@ static void b43_wireless_core_detach(st static int b43_wireless_core_attach(struct b43_wldev *dev) { struct b43_wl *wl = dev->wl; - struct ssb_bus *bus = dev->sdev->bus; - struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL; + struct pci_dev *pdev = NULL; int err; bool have_2ghz_phy = 0, have_5ghz_phy = 0; @@@ -4776,20 -4957,38 +4957,38 @@@ * that in core_init(), too. */ + #ifdef CONFIG_B43_SSB + if (dev->dev->bus_type == B43_BUS_SSB && + dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) + pdev = dev->dev->sdev->bus->host_pci; + #endif + err = b43_bus_powerup(dev, 0); if (err) { b43err(wl, "Bus powerup failed\n"); goto out; } - /* Get the PHY type. */ - if (dev->dev->core_rev >= 5) { - u32 tmshigh; - tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); - have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY); - have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY); - } else - B43_WARN_ON(1); + /* Get the PHY type. */ + switch (dev->dev->bus_type) { + #ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + /* FIXME */ + have_2ghz_phy = 1; + have_5ghz_phy = 0; + break; + #endif + #ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + if (dev->dev->core_rev >= 5) { + u32 tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH); + have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY); + have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY); + } else + B43_WARN_ON(1); + break; + #endif + } dev->phy.gmode = have_2ghz_phy; dev->phy.radio_on = 1; @@@ -4815,6 -5014,8 +5014,8 @@@ #endif case B43_PHYTYPE_G: case B43_PHYTYPE_N: + case B43_PHYTYPE_HT: + case B43_PHYTYPE_LCN: have_2ghz_phy = 1; break; default: @@@ -4877,13 -5078,13 +5078,13 @@@ static void b43_one_core_detach(struct /* Do not cancel ieee80211-workqueue based work here. * See comment in b43_remove(). */ - wldev = ssb_get_drvdata(dev->sdev); + wldev = b43_bus_get_wldev(dev); wl = wldev->wl; b43_debugfs_remove_device(wldev); b43_wireless_core_detach(wldev); list_del(&wldev->list); wl->nr_devs--; - ssb_set_drvdata(dev->sdev, NULL); + b43_bus_set_wldev(dev, NULL); kfree(wldev); } @@@ -4898,7 -5099,6 +5099,6 @@@ static int b43_one_core_attach(struct b wldev->use_pio = b43_modparam_pio; wldev->dev = dev; - wldev->sdev = dev->sdev; /* TODO: Remove when not needed */ wldev->wl = wl; b43_set_status(wldev, B43_STAT_UNINIT); wldev->bad_frames_preempt = modparam_bad_frames_preempt; @@@ -4910,7 -5110,7 +5110,7 @@@ list_add(&wldev->list, &wl->devlist); wl->nr_devs++; - ssb_set_drvdata(dev->sdev, wldev); + b43_bus_set_wldev(dev, wldev); b43_debugfs_add_device(wldev); out: @@@ -4959,9 -5159,9 +5159,9 @@@ static void b43_wireless_exit(struct b4 ieee80211_free_hw(hw); } - static struct b43_wl *b43_wireless_init(struct ssb_device *dev) + static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) { - struct ssb_sprom *sprom = &dev->bus->sprom; + struct ssb_sprom *sprom = dev->bus_sprom; struct ieee80211_hw *hw; struct b43_wl *wl; @@@ -5003,14 -5203,21 +5203,21 @@@ skb_queue_head_init(&wl->tx_queue); b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", - dev->bus->chip_id, dev->id.revision); + dev->chip_id, dev->core_rev); return wl; } #ifdef CONFIG_B43_BCMA static int b43_bcma_probe(struct bcma_device *core) { + struct b43_bus_dev *dev; + + dev = b43_bus_dev_bcma_init(core); + if (!dev) + return -ENODEV; + b43err(NULL, "BCMA is not supported yet!"); + kfree(dev); return -EOPNOTSUPP; } @@@ -5045,7 -5252,7 +5252,7 @@@ int b43_ssb_probe(struct ssb_device *sd /* Probing the first core. Must setup common struct b43_wl */ first = 1; b43_sprom_fixup(sdev->bus); - wl = b43_wireless_init(sdev); + wl = b43_wireless_init(dev); if (IS_ERR(wl)) { err = PTR_ERR(wl); goto out; diff --combined drivers/net/wireless/iwlwifi/iwl-dev.h index c6560e97a62b,a0cca02032e7..424c45c43f5b --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@@ -31,7 -31,6 +31,7 @@@ #ifndef __iwl_dev_h__ #define __iwl_dev_h__ +#include #include /* for struct pci_device_id */ #include #include @@@ -260,11 -259,9 +260,9 @@@ struct iwl_channel_info enum { CMD_SYNC = 0, - CMD_SIZE_NORMAL = 0, - CMD_NO_SKB = 0, - CMD_ASYNC = (1 << 1), - CMD_WANT_SKB = (1 << 2), - CMD_MAPPED = (1 << 3), + CMD_ASYNC = BIT(0), + CMD_WANT_SKB = BIT(1), + CMD_ON_DEMAND = BIT(2), }; #define DEF_CMD_PAYLOAD_SIZE 320 @@@ -297,6 -294,16 +295,16 @@@ enum iwl_hcmd_dataflag IWL_HCMD_DFL_NOCOPY = BIT(0), }; + /** + * struct iwl_host_cmd - Host command to the uCode + * @data: array of chunks that composes the data of the host command + * @reply_page: pointer to the page that holds the response to the host command + * @callback: + * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC + * @len: array of the lenths of the chunks in data + * @dataflags: + * @id: id of the host command + */ struct iwl_host_cmd { const void *data[IWL_MAX_CMD_TFDS]; unsigned long reply_page; @@@ -634,7 -641,6 +642,6 @@@ struct iwl_sensitivity_ranges /** * struct iwl_hw_params * @max_txq_num: Max # Tx queues supported - * @dma_chnl_num: Number of Tx DMA/FIFO channels * @scd_bc_tbls_size: size of scheduler byte count tables * @tfd_size: TFD size * @tx/rx_chains_num: Number of TX/RX chains @@@ -656,7 -662,6 +663,6 @@@ */ struct iwl_hw_params { u8 max_txq_num; - u8 dma_chnl_num; u16 scd_bc_tbls_size; u32 tfd_size; u8 tx_chains_num; @@@ -696,8 -701,6 +702,6 @@@ ****************************************************************************/ extern void iwl_update_chain_flags(struct iwl_priv *priv); extern const u8 iwl_bcast_addr[ETH_ALEN]; - extern int iwl_rxq_stop(struct iwl_priv *priv); - extern void iwl_txq_ctx_stop(struct iwl_priv *priv); extern int iwl_queue_space(const struct iwl_queue *q); static inline int iwl_queue_used(const struct iwl_queue *q, int i) { @@@ -1233,19 -1236,37 +1237,37 @@@ struct iwl_trans * struct iwl_trans_ops - transport specific operations * @rx_init: inits the rx memory, allocate it if needed + * @rx_stop: stop the rx * @rx_free: frees the rx memory * @tx_init:inits the tx memory, allocate if needed + * @tx_stop: stop the tx + * @tx_free: frees the tx memory + * @send_cmd:send a host command + * @send_cmd_pdu:send a host command: flags can be CMD_* */ struct iwl_trans_ops { int (*rx_init)(struct iwl_priv *priv); + int (*rx_stop)(struct iwl_priv *priv); void (*rx_free)(struct iwl_priv *priv); + int (*tx_init)(struct iwl_priv *priv); + int (*tx_stop)(struct iwl_priv *priv); + void (*tx_free)(struct iwl_priv *priv); + + int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); + + int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, + const void *data); }; struct iwl_trans { const struct iwl_trans_ops *ops; }; + /* uCode ownership */ + #define IWL_OWNERSHIP_DRIVER 0 + #define IWL_OWNERSHIP_TM 1 + struct iwl_priv { /* ieee device used by generic ieee processing code */ @@@ -1334,6 -1355,10 +1356,10 @@@ int fw_index; /* firmware we're trying to load */ u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ + + /* uCode owner: default: IWL_OWNERSHIP_DRIVER */ + u8 ucode_owner; + struct fw_img ucode_rt; struct fw_img ucode_init; @@@ -1509,6 -1534,9 +1535,9 @@@ u16 dynamic_frag_thresh; u8 bt_ci_compliance; struct work_struct bt_traffic_change_work; + bool bt_enable_pspoll; + struct iwl_rxon_context *cur_rssi_ctx; + bool bt_is_sco; struct iwl_hw_params hw_params; @@@ -1577,7 -1605,7 +1606,7 @@@ #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL struct iwl_testmode_trace testmode_trace; #endif - u32 dbg_fixed_rate; + u32 tm_fixed_rate; }; /*iwl_priv */ diff --combined drivers/net/wireless/libertas/cmd.c index 9dcf967e1ee4,a515a8fd02ac..dbd24a4607ec --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@@ -3,7 -3,6 +3,7 @@@ * It prepares command and sends it to firmware when it is ready. */ +#include #include #include #include @@@ -874,6 -873,7 +874,7 @@@ int lbs_get_reg(struct lbs_private *pri memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_GET); + cmd.offset = cpu_to_le16(offset); if (reg != CMD_MAC_REG_ACCESS && reg != CMD_BBP_REG_ACCESS && @@@ -883,7 -883,7 +884,7 @@@ } ret = lbs_cmd_with_response(priv, reg, &cmd); - if (ret) { + if (!ret) { if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS) *value = cmd.value.bbp_rf; else if (reg == CMD_MAC_REG_ACCESS) @@@ -916,6 -916,7 +917,7 @@@ int lbs_set_reg(struct lbs_private *pri memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); + cmd.offset = cpu_to_le16(offset); if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS) cmd.value.bbp_rf = (u8) (value & 0xFF); @@@ -1068,16 -1069,34 +1070,34 @@@ static void lbs_cleanup_and_insert_cmd( spin_unlock_irqrestore(&priv->driver_lock, flags); } - void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, - int result) + void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, + int result) { + /* + * Normally, commands are removed from cmdpendingq before being + * submitted. However, we can arrive here on alternative codepaths + * where the command is still pending. Make sure the command really + * isn't part of a list at this point. + */ + list_del_init(&cmd->list); + cmd->result = result; cmd->cmdwaitqwoken = 1; - wake_up_interruptible(&cmd->cmdwait_q); + wake_up(&cmd->cmdwait_q); if (!cmd->callback || cmd->callback == lbs_cmd_async_callback) __lbs_cleanup_and_insert_cmd(priv, cmd); priv->cur_cmd = NULL; + wake_up_interruptible(&priv->waitq); + } + + void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, + int result) + { + unsigned long flags; + spin_lock_irqsave(&priv->driver_lock, flags); + __lbs_complete_command(priv, cmd, result); + spin_unlock_irqrestore(&priv->driver_lock, flags); } int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) @@@ -1249,7 -1268,7 +1269,7 @@@ static struct cmd_ctrl_node *lbs_get_fr if (!list_empty(&priv->cmdfreeq)) { tempnode = list_first_entry(&priv->cmdfreeq, struct cmd_ctrl_node, list); - list_del(&tempnode->list); + list_del_init(&tempnode->list); } else { lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n"); tempnode = NULL; @@@ -1357,10 -1376,7 +1377,7 @@@ int lbs_execute_next_command(struct lbs cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); - spin_lock_irqsave(&priv->driver_lock, flags); - list_del(&cmdnode->list); lbs_complete_command(priv, cmdnode, 0); - spin_unlock_irqrestore(&priv->driver_lock, flags); ret = 0; goto done; @@@ -1370,10 -1386,7 +1387,7 @@@ (priv->psstate == PS_STATE_PRE_SLEEP)) { lbs_deb_host( "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n"); - spin_lock_irqsave(&priv->driver_lock, flags); - list_del(&cmdnode->list); lbs_complete_command(priv, cmdnode, 0); - spin_unlock_irqrestore(&priv->driver_lock, flags); priv->needtowakeup = 1; ret = 0; @@@ -1385,7 -1398,7 +1399,7 @@@ } } spin_lock_irqsave(&priv->driver_lock, flags); - list_del(&cmdnode->list); + list_del_init(&cmdnode->list); spin_unlock_irqrestore(&priv->driver_lock, flags); lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n", le16_to_cpu(cmd->command)); @@@ -1668,7 -1681,13 +1682,13 @@@ int __lbs_cmd(struct lbs_private *priv } might_sleep(); - wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); + + /* + * Be careful with signals here. A signal may be received as the system + * goes into suspend or resume. We do not want this to interrupt the + * command, so we perform an uninterruptible sleep. + */ + wait_event(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); spin_lock_irqsave(&priv->driver_lock, flags); ret = cmdnode->result; diff --combined drivers/net/wireless/libertas/cmdresp.c index 2ffe5a1ff003,7da8949b0511..178b222b3ce1 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@@ -3,7 -3,6 +3,7 @@@ * responses as well as events generated by firmware. */ +#include #include #include #include @@@ -166,7 -165,7 +166,7 @@@ int lbs_process_command_response(struc lbs_deb_host("CMD_RESP: PS action 0x%X\n", action); } - lbs_complete_command(priv, priv->cur_cmd, result); + __lbs_complete_command(priv, priv->cur_cmd, result); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = 0; @@@ -187,7 -186,7 +187,7 @@@ break; } - lbs_complete_command(priv, priv->cur_cmd, result); + __lbs_complete_command(priv, priv->cur_cmd, result); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; @@@ -205,7 -204,7 +205,7 @@@ if (priv->cur_cmd) { /* Clean up and Put current command back to cmdfreeq */ - lbs_complete_command(priv, priv->cur_cmd, result); + __lbs_complete_command(priv, priv->cur_cmd, result); } spin_unlock_irqrestore(&priv->driver_lock, flags); diff --combined drivers/net/wireless/libertas/main.c index cf3d2c8e1969,a839de06fa67..c79aac4b1dae --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@@ -9,7 -9,6 +9,7 @@@ #include #include #include +#include #include #include #include @@@ -639,6 -638,14 +639,14 @@@ static void lbs_cmd_timeout_handler(uns le16_to_cpu(priv->cur_cmd->cmdbuf->command)); priv->cmd_timed_out = 1; + + /* + * If the device didn't even acknowledge the command, reset the state + * so that we don't block all future commands due to this one timeout. + */ + if (priv->dnld_sent == DNLD_CMD_SENT) + priv->dnld_sent = DNLD_RES_RECEIVED; + wake_up_interruptible(&priv->waitq); out: spin_unlock_irqrestore(&priv->driver_lock, flags); @@@ -995,7 -1002,7 +1003,7 @@@ void lbs_stop_card(struct lbs_private * list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { cmdnode->result = -ENOENT; cmdnode->cmdwaitqwoken = 1; - wake_up_interruptible(&cmdnode->cmdwait_q); + wake_up(&cmdnode->cmdwait_q); } /* Flush the command the card is currently processing */ @@@ -1003,7 -1010,7 +1011,7 @@@ lbs_deb_main("clearing current command\n"); priv->cur_cmd->result = -ENOENT; priv->cur_cmd->cmdwaitqwoken = 1; - wake_up_interruptible(&priv->cur_cmd->cmdwait_q); + wake_up(&priv->cur_cmd->cmdwait_q); } lbs_deb_main("done clearing commands\n"); spin_unlock_irqrestore(&priv->driver_lock, flags); diff --combined include/net/bluetooth/hci_core.h index 19639df80e67,c41e275917c7..8f441b8b2963 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@@ -25,7 -25,6 +25,7 @@@ #ifndef __HCI_CORE_H #define __HCI_CORE_H +#include #include /* HCI upper protocols */ @@@ -75,12 -74,28 +75,28 @@@ struct bt_uuid u8 svc_hint; }; + struct key_master_id { + __le16 ediv; + u8 rand[8]; + } __packed; + + struct link_key_data { + bdaddr_t bdaddr; + u8 type; + u8 val[16]; + u8 pin_len; + u8 dlen; + u8 data[0]; + } __packed; + struct link_key { struct list_head list; bdaddr_t bdaddr; u8 type; u8 val[16]; u8 pin_len; + u8 dlen; + u8 data[0]; }; struct oob_data { @@@ -114,6 -129,7 +130,7 @@@ struct hci_dev __u8 major_class; __u8 minor_class; __u8 features[8]; + __u8 extfeatures[8]; __u8 commands[64]; __u8 ssp_mode; __u8 hci_ver; @@@ -224,7 -240,6 +241,6 @@@ struct hci_conn struct list_head list; atomic_t refcnt; - spinlock_t lock; bdaddr_t dst; __u8 dst_type; @@@ -246,11 -261,11 +262,11 @@@ __u8 sec_level; __u8 pending_sec_level; __u8 pin_length; + __u8 enc_key_size; __u8 io_capability; __u8 power_save; __u16 disc_timeout; unsigned long pend; - __u8 ltk[16]; __u8 remote_cap; __u8 remote_oob; @@@ -273,7 -288,6 +289,6 @@@ struct hci_dev *hdev; void *l2cap_data; void *sco_data; - void *priv; struct hci_conn *link; @@@ -539,6 -553,11 +554,11 @@@ int hci_link_keys_clear(struct hci_dev struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); + struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); + struct link_key *hci_find_link_key_type(struct hci_dev *hdev, + bdaddr_t *bdaddr, u8 type); + int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, + u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]); int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_remote_oob_data_clear(struct hci_dev *hdev); @@@ -580,6 -599,9 +600,9 @@@ void hci_conn_del_sysfs(struct hci_con #define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) #define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) + /* ----- Extended LMP capabilities ----- */ + #define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE) + /* ----- HCI protocols ----- */ struct hci_proto { char *name; diff --combined net/bluetooth/hci_core.c index b18db5628275,908fcd384ab4..ec0bc3f60f2e --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@@ -60,8 -60,6 +60,6 @@@ static void hci_tx_task(unsigned long a static DEFINE_RWLOCK(hci_task_lock); - static int enable_smp; - /* HCI device list */ LIST_HEAD(hci_dev_list); DEFINE_RWLOCK(hci_dev_list_lock); @@@ -148,7 -146,7 +146,7 @@@ static int __hci_request(struct hci_de switch (hdev->req_status) { case HCI_REQ_DONE: - err = -bt_err(hdev->req_result); + err = -bt_to_errno(hdev->req_result); break; case HCI_REQ_CANCELED: @@@ -542,7 -540,7 +540,7 @@@ int hci_dev_open(__u16 dev ret = __hci_request(hdev, hci_init_req, 0, msecs_to_jiffies(HCI_INIT_TIMEOUT)); - if (lmp_le_capable(hdev)) + if (lmp_host_le_capable(hdev)) ret = __hci_request(hdev, hci_le_init_req, 0, msecs_to_jiffies(HCI_INIT_TIMEOUT)); @@@ -1059,6 -1057,42 +1057,42 @@@ static int hci_persistent_key(struct hc return 0; } + struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) + { + struct link_key *k; + + list_for_each_entry(k, &hdev->link_keys, list) { + struct key_master_id *id; + + if (k->type != HCI_LK_SMP_LTK) + continue; + + if (k->dlen != sizeof(*id)) + continue; + + id = (void *) &k->data; + if (id->ediv == ediv && + (memcmp(rand, id->rand, sizeof(id->rand)) == 0)) + return k; + } + + return NULL; + } + EXPORT_SYMBOL(hci_find_ltk); + + struct link_key *hci_find_link_key_type(struct hci_dev *hdev, + bdaddr_t *bdaddr, u8 type) + { + struct link_key *k; + + list_for_each_entry(k, &hdev->link_keys, list) + if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0) + return k; + + return NULL; + } + EXPORT_SYMBOL(hci_find_link_key_type); + int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) { @@@ -1114,6 -1148,44 +1148,44 @@@ return 0; } + int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, + u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]) + { + struct link_key *key, *old_key; + struct key_master_id *id; + u8 old_key_type; + + BT_DBG("%s addr %s", hdev->name, batostr(bdaddr)); + + old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK); + if (old_key) { + key = old_key; + old_key_type = old_key->type; + } else { + key = kzalloc(sizeof(*key) + sizeof(*id), GFP_ATOMIC); + if (!key) + return -ENOMEM; + list_add(&key->list, &hdev->link_keys); + old_key_type = 0xff; + } + + key->dlen = sizeof(*id); + + bacpy(&key->bdaddr, bdaddr); + memcpy(key->val, ltk, sizeof(key->val)); + key->type = HCI_LK_SMP_LTK; + key->pin_len = key_size; + + id = (void *) &key->data; + id->ediv = ediv; + memcpy(id->rand, rand, sizeof(id->rand)); + + if (new_key) + mgmt_new_key(hdev->id, key, old_key_type); + + return 0; + } + int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) { struct link_key *key; @@@ -1246,7 -1318,7 +1318,7 @@@ int hci_blacklist_add(struct hci_dev *h if (bacmp(bdaddr, BDADDR_ANY) == 0) return -EBADF; - hci_dev_lock(hdev); + hci_dev_lock_bh(hdev); if (hci_blacklist_lookup(hdev, bdaddr)) { err = -EEXIST; @@@ -1266,7 -1338,7 +1338,7 @@@ err = 0; err: - hci_dev_unlock(hdev); + hci_dev_unlock_bh(hdev); return err; } @@@ -1275,7 -1347,7 +1347,7 @@@ int hci_blacklist_del(struct hci_dev *h struct bdaddr_list *entry; int err = 0; - hci_dev_lock(hdev); + hci_dev_lock_bh(hdev); if (bacmp(bdaddr, BDADDR_ANY) == 0) { hci_blacklist_clear(hdev); @@@ -1292,7 -1364,7 +1364,7 @@@ kfree(entry); done: - hci_dev_unlock(hdev); + hci_dev_unlock_bh(hdev); return err; } @@@ -1368,14 -1440,6 +1440,6 @@@ int hci_add_adv_entry(struct hci_dev *h return 0; } - static struct crypto_blkcipher *alloc_cypher(void) - { - if (enable_smp) - return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); - - return ERR_PTR(-ENOTSUPP); - } - /* Register HCI device */ int hci_register_dev(struct hci_dev *hdev) { @@@ -1460,7 -1524,7 +1524,7 @@@ if (!hdev->workqueue) goto nomem; - hdev->tfm = alloc_cypher(); + hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(hdev->tfm)) BT_INFO("Failed to load transform for ecb(aes): %ld", PTR_ERR(hdev->tfm)); @@@ -1707,7 -1771,7 +1771,7 @@@ int hci_recv_fragment(struct hci_dev *h data += (count - rem); count = rem; - }; + } return rem; } @@@ -1742,7 -1806,7 +1806,7 @@@ int hci_recv_stream_fragment(struct hci data += (count - rem); count = rem; - }; + } return rem; } @@@ -2352,6 -2416,3 +2416,3 @@@ static void hci_cmd_task(unsigned long } } } - - module_param(enable_smp, bool, 0644); - MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");