Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts: net/mac80211/sta_info.c net/wireless/core.h
This commit is contained in:
commit
9a574cd67a
@ -5043,9 +5043,8 @@ S: Maintained
|
|||||||
F: drivers/net/ethernet/marvell/sk*
|
F: drivers/net/ethernet/marvell/sk*
|
||||||
|
|
||||||
MARVELL LIBERTAS WIRELESS DRIVER
|
MARVELL LIBERTAS WIRELESS DRIVER
|
||||||
M: Dan Williams <dcbw@redhat.com>
|
|
||||||
L: libertas-dev@lists.infradead.org
|
L: libertas-dev@lists.infradead.org
|
||||||
S: Maintained
|
S: Orphan
|
||||||
F: drivers/net/wireless/libertas/
|
F: drivers/net/wireless/libertas/
|
||||||
|
|
||||||
MARVELL MV643XX ETHERNET DRIVER
|
MARVELL MV643XX ETHERNET DRIVER
|
||||||
|
@ -73,9 +73,11 @@ static struct usb_device_id ath3k_table[] = {
|
|||||||
{ USB_DEVICE(0x03F0, 0x311D) },
|
{ USB_DEVICE(0x03F0, 0x311D) },
|
||||||
|
|
||||||
/* Atheros AR3012 with sflash firmware*/
|
/* Atheros AR3012 with sflash firmware*/
|
||||||
|
{ USB_DEVICE(0x0CF3, 0x0036) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x3004) },
|
{ USB_DEVICE(0x0CF3, 0x3004) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x3008) },
|
{ USB_DEVICE(0x0CF3, 0x3008) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x311D) },
|
{ USB_DEVICE(0x0CF3, 0x311D) },
|
||||||
|
{ USB_DEVICE(0x0CF3, 0x817a) },
|
||||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
{ USB_DEVICE(0x13d3, 0x3375) },
|
||||||
{ USB_DEVICE(0x04CA, 0x3004) },
|
{ USB_DEVICE(0x04CA, 0x3004) },
|
||||||
{ USB_DEVICE(0x04CA, 0x3005) },
|
{ USB_DEVICE(0x04CA, 0x3005) },
|
||||||
@ -107,9 +109,11 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
|
|||||||
static struct usb_device_id ath3k_blist_tbl[] = {
|
static struct usb_device_id ath3k_blist_tbl[] = {
|
||||||
|
|
||||||
/* Atheros AR3012 with sflash firmware*/
|
/* Atheros AR3012 with sflash firmware*/
|
||||||
|
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
||||||
|
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||||
|
@ -131,9 +131,11 @@ static struct usb_device_id blacklist_table[] = {
|
|||||||
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
|
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
|
||||||
|
|
||||||
/* Atheros 3012 with sflash firmware */
|
/* Atheros 3012 with sflash firmware */
|
||||||
|
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
||||||
|
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||||
|
@ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
|||||||
AR_PHY_AGC_CONTROL_FLTR_CAL |
|
AR_PHY_AGC_CONTROL_FLTR_CAL |
|
||||||
AR_PHY_AGC_CONTROL_PKDET_CAL;
|
AR_PHY_AGC_CONTROL_PKDET_CAL;
|
||||||
|
|
||||||
|
/* Use chip chainmask only for calibration */
|
||||||
ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
|
ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
|
||||||
|
|
||||||
if (rtt) {
|
if (rtt) {
|
||||||
@ -1151,6 +1152,9 @@ skip_tx_iqcal:
|
|||||||
ar9003_hw_rtt_disable(ah);
|
ar9003_hw_rtt_disable(ah);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Revert chainmask to runtime parameters */
|
||||||
|
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
|
||||||
|
|
||||||
/* Initialize list pointers */
|
/* Initialize list pointers */
|
||||||
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
|
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ void ath_tx_complete_poll_work(struct work_struct *work)
|
|||||||
int i;
|
int i;
|
||||||
bool needreset = false;
|
bool needreset = false;
|
||||||
|
|
||||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||||
if (ATH_TXQ_SETUP(sc, i)) {
|
txq = sc->tx.txq_map[i];
|
||||||
txq = &sc->tx.txq[i];
|
|
||||||
ath_txq_lock(sc, txq);
|
ath_txq_lock(sc, txq);
|
||||||
if (txq->axq_depth) {
|
if (txq->axq_depth) {
|
||||||
if (txq->axq_tx_inprogress) {
|
if (txq->axq_tx_inprogress) {
|
||||||
@ -170,6 +170,7 @@ void ath_rx_poll(unsigned long data)
|
|||||||
{
|
{
|
||||||
struct ath_softc *sc = (struct ath_softc *)data;
|
struct ath_softc *sc = (struct ath_softc *)data;
|
||||||
|
|
||||||
|
if (!test_bit(SC_OP_INVALID, &sc->sc_flags))
|
||||||
ieee80211_queue_work(sc->hw, &sc->hw_check_work);
|
ieee80211_queue_work(sc->hw, &sc->hw_check_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
|||||||
const struct b43_dma_ops *ops;
|
const struct b43_dma_ops *ops;
|
||||||
struct b43_dmaring *ring;
|
struct b43_dmaring *ring;
|
||||||
struct b43_dmadesc_meta *meta;
|
struct b43_dmadesc_meta *meta;
|
||||||
|
static const struct b43_txstatus fake; /* filled with 0 */
|
||||||
|
const struct b43_txstatus *txstat;
|
||||||
int slot, firstused;
|
int slot, firstused;
|
||||||
bool frame_succeed;
|
bool frame_succeed;
|
||||||
|
int skip;
|
||||||
|
static u8 err_out1, err_out2;
|
||||||
|
|
||||||
ring = parse_cookie(dev, status->cookie, &slot);
|
ring = parse_cookie(dev, status->cookie, &slot);
|
||||||
if (unlikely(!ring))
|
if (unlikely(!ring))
|
||||||
@ -1501,14 +1505,37 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
|||||||
firstused = ring->current_slot - ring->used_slots + 1;
|
firstused = ring->current_slot - ring->used_slots + 1;
|
||||||
if (firstused < 0)
|
if (firstused < 0)
|
||||||
firstused = ring->nr_slots + firstused;
|
firstused = ring->nr_slots + firstused;
|
||||||
|
|
||||||
|
skip = 0;
|
||||||
if (unlikely(slot != firstused)) {
|
if (unlikely(slot != firstused)) {
|
||||||
/* This possibly is a firmware bug and will result in
|
/* This possibly is a firmware bug and will result in
|
||||||
* malfunction, memory leaks and/or stall of DMA functionality. */
|
* malfunction, memory leaks and/or stall of DMA functionality.
|
||||||
b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
|
*/
|
||||||
"Expected %d, but got %d\n",
|
if (slot == next_slot(ring, next_slot(ring, firstused))) {
|
||||||
|
/* If a single header/data pair was missed, skip over
|
||||||
|
* the first two slots in an attempt to recover.
|
||||||
|
*/
|
||||||
|
slot = firstused;
|
||||||
|
skip = 2;
|
||||||
|
if (!err_out1) {
|
||||||
|
/* Report the error once. */
|
||||||
|
b43dbg(dev->wl,
|
||||||
|
"Skip on DMA ring %d slot %d.\n",
|
||||||
|
ring->index, slot);
|
||||||
|
err_out1 = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* More than a single header/data pair were missed.
|
||||||
|
* Report this error once.
|
||||||
|
*/
|
||||||
|
if (!err_out2)
|
||||||
|
b43dbg(dev->wl,
|
||||||
|
"Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
|
||||||
ring->index, firstused, slot);
|
ring->index, firstused, slot);
|
||||||
|
err_out2 = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ops = ring->ops;
|
ops = ring->ops;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
|||||||
slot, firstused, ring->index);
|
slot, firstused, ring->index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meta->skb) {
|
if (meta->skb) {
|
||||||
struct b43_private_tx_info *priv_info =
|
struct b43_private_tx_info *priv_info =
|
||||||
b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
|
b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
|
||||||
|
|
||||||
unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
|
unmap_descbuffer(ring, meta->dmaaddr,
|
||||||
|
meta->skb->len, 1);
|
||||||
kfree(priv_info->bouncebuffer);
|
kfree(priv_info->bouncebuffer);
|
||||||
priv_info->bouncebuffer = NULL;
|
priv_info->bouncebuffer = NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
|||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
|
|
||||||
if (unlikely(!meta->skb)) {
|
if (unlikely(!meta->skb)) {
|
||||||
/* This is a scatter-gather fragment of a frame, so
|
/* This is a scatter-gather fragment of a frame,
|
||||||
* the skb pointer must not be NULL. */
|
* so the skb pointer must not be NULL.
|
||||||
|
*/
|
||||||
b43dbg(dev->wl, "TX status unexpected NULL skb "
|
b43dbg(dev->wl, "TX status unexpected NULL skb "
|
||||||
"at slot %d (first=%d) on ring %d\n",
|
"at slot %d (first=%d) on ring %d\n",
|
||||||
slot, firstused, ring->index);
|
slot, firstused, ring->index);
|
||||||
@ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Call back to inform the ieee80211 subsystem about
|
* Call back to inform the ieee80211 subsystem about
|
||||||
* the status of the transmission.
|
* the status of the transmission. When skipping over
|
||||||
|
* a missed TX status report, use a status structure
|
||||||
|
* filled with zeros to indicate that the frame was not
|
||||||
|
* sent (frame_count 0) and not acknowledged
|
||||||
*/
|
*/
|
||||||
frame_succeed = b43_fill_txstatus_report(dev, info, status);
|
if (unlikely(skip))
|
||||||
|
txstat = &fake;
|
||||||
|
else
|
||||||
|
txstat = status;
|
||||||
|
|
||||||
|
frame_succeed = b43_fill_txstatus_report(dev, info,
|
||||||
|
txstat);
|
||||||
#ifdef CONFIG_B43_DEBUG
|
#ifdef CONFIG_B43_DEBUG
|
||||||
if (frame_succeed)
|
if (frame_succeed)
|
||||||
ring->nr_succeed_tx_packets++;
|
ring->nr_succeed_tx_packets++;
|
||||||
@ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
|||||||
/* Everything unmapped and free'd. So it's not used anymore. */
|
/* Everything unmapped and free'd. So it's not used anymore. */
|
||||||
ring->used_slots--;
|
ring->used_slots--;
|
||||||
|
|
||||||
if (meta->is_last_fragment) {
|
if (meta->is_last_fragment && !skip) {
|
||||||
/* This is the last scatter-gather
|
/* This is the last scatter-gather
|
||||||
* fragment of the frame. We are done. */
|
* fragment of the frame. We are done. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
slot = next_slot(ring, slot);
|
slot = next_slot(ring, slot);
|
||||||
|
if (skip > 0)
|
||||||
|
--skip;
|
||||||
}
|
}
|
||||||
if (ring->stopped) {
|
if (ring->stopped) {
|
||||||
B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
|
B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
|
||||||
|
@ -1564,7 +1564,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
|
|||||||
u16 clip_off[2] = { 0xFFFF, 0xFFFF };
|
u16 clip_off[2] = { 0xFFFF, 0xFFFF };
|
||||||
|
|
||||||
u8 vcm_final = 0;
|
u8 vcm_final = 0;
|
||||||
s8 offset[4];
|
s32 offset[4];
|
||||||
s32 results[8][4] = { };
|
s32 results[8][4] = { };
|
||||||
s32 results_min[4] = { };
|
s32 results_min[4] = { };
|
||||||
s32 poll_results[4] = { };
|
s32 poll_results[4] = { };
|
||||||
@ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
|
|||||||
}
|
}
|
||||||
for (i = 0; i < 4; i += 2) {
|
for (i = 0; i < 4; i += 2) {
|
||||||
s32 curr;
|
s32 curr;
|
||||||
s32 mind = 40;
|
s32 mind = 0x100000;
|
||||||
s32 minpoll = 249;
|
s32 minpoll = 249;
|
||||||
u8 minvcm = 0;
|
u8 minvcm = 0;
|
||||||
if (2 * core != i)
|
if (2 * core != i)
|
||||||
@ -1732,7 +1732,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
|
|||||||
u8 regs_save_radio[2];
|
u8 regs_save_radio[2];
|
||||||
u16 regs_save_phy[2];
|
u16 regs_save_phy[2];
|
||||||
|
|
||||||
s8 offset[4];
|
s32 offset[4];
|
||||||
u8 core;
|
u8 core;
|
||||||
u8 rail;
|
u8 rail;
|
||||||
|
|
||||||
@ -1799,7 +1799,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
s32 mind = 40;
|
s32 mind = 0x100000;
|
||||||
u8 minvcm = 0;
|
u8 minvcm = 0;
|
||||||
s32 minpoll = 249;
|
s32 minpoll = 249;
|
||||||
s32 curr;
|
s32 curr;
|
||||||
|
@ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
|
|||||||
gain0_15 = ((biq1 & 0xf) << 12) |
|
gain0_15 = ((biq1 & 0xf) << 12) |
|
||||||
((tia & 0xf) << 8) |
|
((tia & 0xf) << 8) |
|
||||||
((lna2 & 0x3) << 6) |
|
((lna2 & 0x3) << 6) |
|
||||||
((lna2 & 0x3) << 4) |
|
((lna2 &
|
||||||
((lna1 & 0x3) << 2) |
|
0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
|
||||||
((lna1 & 0x3) << 0);
|
|
||||||
|
|
||||||
mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
|
mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
|
||||||
mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
|
mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
|
||||||
@ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
|
mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
|
||||||
mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
|
|
||||||
mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
|
|||||||
return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
|
return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
|
|
||||||
u16 tia_gain, u16 lna2_gain)
|
|
||||||
{
|
|
||||||
u32 i_thresh_l, q_thresh_l;
|
|
||||||
u32 i_thresh_h, q_thresh_h;
|
|
||||||
struct lcnphy_iq_est iq_est_h, iq_est_l;
|
|
||||||
|
|
||||||
wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
|
|
||||||
lna2_gain, 0);
|
|
||||||
|
|
||||||
wlc_lcnphy_rx_gain_override_enable(pi, true);
|
|
||||||
wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
|
|
||||||
udelay(500);
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG112, 0);
|
|
||||||
if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
|
|
||||||
udelay(500);
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG112, 0);
|
|
||||||
if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
i_thresh_l = (iq_est_l.i_pwr << 1);
|
|
||||||
i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
|
|
||||||
|
|
||||||
q_thresh_l = (iq_est_l.q_pwr << 1);
|
|
||||||
q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
|
|
||||||
if ((iq_est_h.i_pwr > i_thresh_l) &&
|
|
||||||
(iq_est_h.i_pwr < i_thresh_h) &&
|
|
||||||
(iq_est_h.q_pwr > q_thresh_l) &&
|
|
||||||
(iq_est_h.q_pwr < q_thresh_h))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
|
wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
|
||||||
const struct lcnphy_rx_iqcomp *iqcomp,
|
const struct lcnphy_rx_iqcomp *iqcomp,
|
||||||
@ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
|
|||||||
RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
|
RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
|
||||||
rfoverride3_old, rfoverride3val_old, rfoverride4_old,
|
rfoverride3_old, rfoverride3val_old, rfoverride4_old,
|
||||||
rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
|
rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
|
||||||
int tia_gain, lna2_gain, biq1_gain;
|
int tia_gain;
|
||||||
bool set_gain;
|
u32 received_power, rx_pwr_threshold;
|
||||||
u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
|
u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
|
||||||
u16 values_to_save[11];
|
u16 values_to_save[11];
|
||||||
s16 *ptr;
|
s16 *ptr;
|
||||||
@ -1408,7 +1368,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
|
|||||||
goto cal_done;
|
goto cal_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
WARN_ON(module != 1);
|
if (module == 1) {
|
||||||
|
|
||||||
tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
|
tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
|
||||||
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
|
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
|
||||||
|
|
||||||
@ -1471,38 +1432,28 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
|
|||||||
mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
|
mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
|
||||||
mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
|
mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
|
||||||
|
|
||||||
|
wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
|
||||||
write_phy_reg(pi, 0x6da, 0xffff);
|
write_phy_reg(pi, 0x6da, 0xffff);
|
||||||
or_phy_reg(pi, 0x6db, 0x3);
|
or_phy_reg(pi, 0x6db, 0x3);
|
||||||
|
|
||||||
wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
|
wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
|
||||||
set_gain = false;
|
wlc_lcnphy_rx_gain_override_enable(pi, true);
|
||||||
|
|
||||||
lna2_gain = 3;
|
tia_gain = 8;
|
||||||
while ((lna2_gain >= 0) && !set_gain) {
|
rx_pwr_threshold = 950;
|
||||||
tia_gain = 4;
|
while (tia_gain > 0) {
|
||||||
|
|
||||||
while ((tia_gain >= 0) && !set_gain) {
|
|
||||||
biq1_gain = 6;
|
|
||||||
|
|
||||||
while ((biq1_gain >= 0) && !set_gain) {
|
|
||||||
set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
|
|
||||||
(u16)
|
|
||||||
biq1_gain,
|
|
||||||
(u16)
|
|
||||||
tia_gain,
|
|
||||||
(u16)
|
|
||||||
lna2_gain);
|
|
||||||
biq1_gain -= 1;
|
|
||||||
}
|
|
||||||
tia_gain -= 1;
|
tia_gain -= 1;
|
||||||
}
|
wlc_lcnphy_set_rx_gain_by_distribution(pi,
|
||||||
lna2_gain -= 1;
|
0, 0, 2, 2,
|
||||||
}
|
(u16)
|
||||||
|
tia_gain, 1, 0);
|
||||||
|
udelay(500);
|
||||||
|
|
||||||
if (set_gain)
|
received_power =
|
||||||
result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
|
wlc_lcnphy_measure_digital_power(pi, 2000);
|
||||||
else
|
if (received_power < rx_pwr_threshold)
|
||||||
result = false;
|
break;
|
||||||
|
}
|
||||||
|
result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
|
||||||
|
|
||||||
wlc_lcnphy_stop_tx_tone(pi);
|
wlc_lcnphy_stop_tx_tone(pi);
|
||||||
|
|
||||||
@ -1536,6 +1487,7 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
|
|||||||
|
|
||||||
wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
|
wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
|
||||||
wlc_lcnphy_rx_gain_override_enable(pi, false);
|
wlc_lcnphy_rx_gain_override_enable(pi, false);
|
||||||
|
}
|
||||||
|
|
||||||
cal_done:
|
cal_done:
|
||||||
kfree(ptr);
|
kfree(ptr);
|
||||||
@ -1837,17 +1789,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
|
|||||||
write_radio_reg(pi, RADIO_2064_REG038, 3);
|
write_radio_reg(pi, RADIO_2064_REG038, 3);
|
||||||
write_radio_reg(pi, RADIO_2064_REG091, 7);
|
write_radio_reg(pi, RADIO_2064_REG091, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pi->sh->boardflags & BFL_FEM)) {
|
|
||||||
u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
|
|
||||||
0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
|
|
||||||
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG091, 0x3);
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG038, 0x3);
|
|
||||||
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2042,16 +1983,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
|
|||||||
} else {
|
} else {
|
||||||
mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
|
mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
|
||||||
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
|
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
|
||||||
mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
|
mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
|
||||||
@ -2138,14 +2069,12 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
|
|||||||
(auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
|
(auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
|
||||||
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
|
mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
|
||||||
mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
|
static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
|
||||||
{
|
{
|
||||||
struct phytbl_info tab;
|
struct phytbl_info tab;
|
||||||
u32 rfseq, ind;
|
u32 rfseq, ind;
|
||||||
u8 tssi_sel;
|
|
||||||
|
|
||||||
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
|
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
|
||||||
tab.tbl_width = 32;
|
tab.tbl_width = 32;
|
||||||
@ -2167,13 +2096,7 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
|
|||||||
|
|
||||||
mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
|
mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
|
||||||
|
|
||||||
if (pi->sh->boardflags & BFL_FEM) {
|
|
||||||
tssi_sel = 0x1;
|
|
||||||
wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
|
wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
|
||||||
} else {
|
|
||||||
tssi_sel = 0xe;
|
|
||||||
wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
|
|
||||||
}
|
|
||||||
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
|
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
|
||||||
|
|
||||||
mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
|
mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
|
||||||
@ -2209,10 +2132,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
|
|||||||
mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
|
mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
|
||||||
|
|
||||||
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
|
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
|
||||||
mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
|
mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
|
||||||
mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
|
mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
|
||||||
} else {
|
} else {
|
||||||
mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
|
mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
|
||||||
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
|
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
|
||||||
}
|
}
|
||||||
@ -2259,10 +2181,6 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
|
|||||||
|
|
||||||
mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
|
mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
|
||||||
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
|
|
||||||
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
|
|
||||||
|
|
||||||
wlc_lcnphy_pwrctrl_rssiparams(pi);
|
wlc_lcnphy_pwrctrl_rssiparams(pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2881,8 +2799,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
|
|||||||
read_radio_reg(pi, RADIO_2064_REG007) & 1;
|
read_radio_reg(pi, RADIO_2064_REG007) & 1;
|
||||||
u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
|
u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
|
||||||
u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
|
u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
|
||||||
u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
|
|
||||||
|
|
||||||
idleTssi = read_phy_reg(pi, 0x4ab);
|
idleTssi = read_phy_reg(pi, 0x4ab);
|
||||||
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
|
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
|
||||||
MCTL_EN_MAC));
|
MCTL_EN_MAC));
|
||||||
@ -2900,12 +2816,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
|
|||||||
mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
|
mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
|
||||||
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
|
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
|
||||||
wlc_lcnphy_tssi_setup(pi);
|
wlc_lcnphy_tssi_setup(pi);
|
||||||
|
|
||||||
mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
|
|
||||||
mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
|
|
||||||
|
|
||||||
wlc_lcnphy_set_bbmult(pi, 0x0);
|
|
||||||
|
|
||||||
wlc_phy_do_dummy_tx(pi, true, OFF);
|
wlc_phy_do_dummy_tx(pi, true, OFF);
|
||||||
idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
|
idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
|
||||||
>> 0);
|
>> 0);
|
||||||
@ -2927,7 +2837,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
|
|||||||
|
|
||||||
mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
|
mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
|
||||||
|
|
||||||
wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
|
|
||||||
wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
|
wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
|
||||||
wlc_lcnphy_set_tx_gain(pi, &old_gains);
|
wlc_lcnphy_set_tx_gain(pi, &old_gains);
|
||||||
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
|
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
|
||||||
@ -3141,11 +3050,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
|
|||||||
wlc_lcnphy_write_table(pi, &tab);
|
wlc_lcnphy_write_table(pi, &tab);
|
||||||
tab.tbl_offset++;
|
tab.tbl_offset++;
|
||||||
}
|
}
|
||||||
mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
|
|
||||||
mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
|
|
||||||
mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
|
|
||||||
mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
|
|
||||||
mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
|
|
||||||
|
|
||||||
mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
|
mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
|
||||||
|
|
||||||
@ -3947,6 +3851,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
|
|||||||
target_gains.pad_gain = 21;
|
target_gains.pad_gain = 21;
|
||||||
target_gains.dac_gain = 0;
|
target_gains.dac_gain = 0;
|
||||||
wlc_lcnphy_set_tx_gain(pi, &target_gains);
|
wlc_lcnphy_set_tx_gain(pi, &target_gains);
|
||||||
|
wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
|
||||||
|
|
||||||
if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
|
if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
|
||||||
|
|
||||||
@ -3957,7 +3862,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
|
|||||||
lcnphy_recal ? LCNPHY_CAL_RECAL :
|
lcnphy_recal ? LCNPHY_CAL_RECAL :
|
||||||
LCNPHY_CAL_FULL), false);
|
LCNPHY_CAL_FULL), false);
|
||||||
} else {
|
} else {
|
||||||
wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
|
|
||||||
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
|
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4382,22 +4286,17 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
|
|||||||
if (CHSPEC_IS5G(pi->radio_chanspec))
|
if (CHSPEC_IS5G(pi->radio_chanspec))
|
||||||
pa_gain = 0x70;
|
pa_gain = 0x70;
|
||||||
else
|
else
|
||||||
pa_gain = 0x60;
|
pa_gain = 0x70;
|
||||||
|
|
||||||
if (pi->sh->boardflags & BFL_FEM)
|
if (pi->sh->boardflags & BFL_FEM)
|
||||||
pa_gain = 0x10;
|
pa_gain = 0x10;
|
||||||
|
|
||||||
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
|
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
|
||||||
tab.tbl_width = 32;
|
tab.tbl_width = 32;
|
||||||
tab.tbl_len = 1;
|
tab.tbl_len = 1;
|
||||||
tab.tbl_ptr = &val;
|
tab.tbl_ptr = &val;
|
||||||
|
|
||||||
for (j = 0; j < 128; j++) {
|
for (j = 0; j < 128; j++) {
|
||||||
if (pi->sh->boardflags & BFL_FEM)
|
|
||||||
gm_gain = gain_table[j].gm;
|
gm_gain = gain_table[j].gm;
|
||||||
else
|
|
||||||
gm_gain = 15;
|
|
||||||
|
|
||||||
val = (((u32) pa_gain << 24) |
|
val = (((u32) pa_gain << 24) |
|
||||||
(gain_table[j].pad << 16) |
|
(gain_table[j].pad << 16) |
|
||||||
(gain_table[j].pga << 8) | gm_gain);
|
(gain_table[j].pga << 8) | gm_gain);
|
||||||
@ -4608,10 +4507,7 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
|
|||||||
|
|
||||||
write_phy_reg(pi, 0x4ea, 0x4688);
|
write_phy_reg(pi, 0x4ea, 0x4688);
|
||||||
|
|
||||||
if (pi->sh->boardflags & BFL_FEM)
|
|
||||||
mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
|
mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
|
||||||
else
|
|
||||||
mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
|
|
||||||
|
|
||||||
mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
|
mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
|
||||||
|
|
||||||
@ -4622,13 +4518,6 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
|
|||||||
wlc_lcnphy_rcal(pi);
|
wlc_lcnphy_rcal(pi);
|
||||||
|
|
||||||
wlc_lcnphy_rc_cal(pi);
|
wlc_lcnphy_rc_cal(pi);
|
||||||
|
|
||||||
if (!(pi->sh->boardflags & BFL_FEM)) {
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG033, 0x19);
|
|
||||||
write_radio_reg(pi, RADIO_2064_REG039, 0xe);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
|
static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
|
||||||
@ -4658,20 +4547,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
|
|||||||
wlc_lcnphy_write_table(pi, &tab);
|
wlc_lcnphy_write_table(pi, &tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pi->sh->boardflags & BFL_FEM)) {
|
|
||||||
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
|
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
|
||||||
tab.tbl_width = 16;
|
tab.tbl_width = 16;
|
||||||
tab.tbl_ptr = &val;
|
tab.tbl_ptr = &val;
|
||||||
tab.tbl_len = 1;
|
tab.tbl_len = 1;
|
||||||
|
|
||||||
val = 150;
|
val = 114;
|
||||||
tab.tbl_offset = 0;
|
tab.tbl_offset = 0;
|
||||||
wlc_lcnphy_write_table(pi, &tab);
|
wlc_lcnphy_write_table(pi, &tab);
|
||||||
|
|
||||||
val = 220;
|
val = 130;
|
||||||
tab.tbl_offset = 1;
|
tab.tbl_offset = 1;
|
||||||
wlc_lcnphy_write_table(pi, &tab);
|
wlc_lcnphy_write_table(pi, &tab);
|
||||||
}
|
|
||||||
|
val = 6;
|
||||||
|
tab.tbl_offset = 8;
|
||||||
|
wlc_lcnphy_write_table(pi, &tab);
|
||||||
|
|
||||||
if (CHSPEC_IS2G(pi->radio_chanspec)) {
|
if (CHSPEC_IS2G(pi->radio_chanspec)) {
|
||||||
if (pi->sh->boardflags & BFL_FEM)
|
if (pi->sh->boardflags & BFL_FEM)
|
||||||
@ -5064,7 +4955,6 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
|
|||||||
wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
|
wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
|
||||||
|
|
||||||
mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
|
mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
|
||||||
wlc_lcnphy_tssi_setup(pi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
|
void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
|
||||||
@ -5103,7 +4993,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
|
|||||||
if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
|
if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
|
if ((pi->sh->boardflags & BFL_FEM) &&
|
||||||
|
(LCNREV_IS(pi->pubpi.phy_rev, 1))) {
|
||||||
if (pi_lcn->lcnphy_tempsense_option == 3) {
|
if (pi_lcn->lcnphy_tempsense_option == 3) {
|
||||||
pi->hwpwrctrl = true;
|
pi->hwpwrctrl = true;
|
||||||
pi->hwpwrctrl_capable = true;
|
pi->hwpwrctrl_capable = true;
|
||||||
|
@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
|
static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
|
||||||
0x0009,
|
|
||||||
0x000a,
|
0x000a,
|
||||||
0x0005,
|
|
||||||
0x0006,
|
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
0x0009,
|
0x0009,
|
||||||
0x000a,
|
|
||||||
0x0005,
|
|
||||||
0x0006,
|
0x0006,
|
||||||
|
0x0005,
|
||||||
|
0x000a,
|
||||||
|
0x0009,
|
||||||
|
0x0006,
|
||||||
|
0x0005,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
|
static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
|
||||||
|
@ -475,6 +475,7 @@ il3945_tx_skb(struct il_priv *il,
|
|||||||
dma_addr_t txcmd_phys;
|
dma_addr_t txcmd_phys;
|
||||||
int txq_id = skb_get_queue_mapping(skb);
|
int txq_id = skb_get_queue_mapping(skb);
|
||||||
u16 len, idx, hdr_len;
|
u16 len, idx, hdr_len;
|
||||||
|
u16 firstlen, secondlen;
|
||||||
u8 id;
|
u8 id;
|
||||||
u8 unicast;
|
u8 unicast;
|
||||||
u8 sta_id;
|
u8 sta_id;
|
||||||
@ -589,21 +590,22 @@ il3945_tx_skb(struct il_priv *il,
|
|||||||
len =
|
len =
|
||||||
sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) +
|
sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) +
|
||||||
hdr_len;
|
hdr_len;
|
||||||
len = (len + 3) & ~3;
|
firstlen = (len + 3) & ~3;
|
||||||
|
|
||||||
/* Physical address of this Tx command's header (not MAC header!),
|
/* Physical address of this Tx command's header (not MAC header!),
|
||||||
* within command buffer array. */
|
* within command buffer array. */
|
||||||
txcmd_phys =
|
txcmd_phys =
|
||||||
pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE);
|
pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen,
|
||||||
|
PCI_DMA_TODEVICE);
|
||||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys)))
|
if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys)))
|
||||||
goto drop_unlock;
|
goto drop_unlock;
|
||||||
|
|
||||||
/* Set up TFD's 2nd entry to point directly to remainder of skb,
|
/* Set up TFD's 2nd entry to point directly to remainder of skb,
|
||||||
* if any (802.11 null frames have no payload). */
|
* if any (802.11 null frames have no payload). */
|
||||||
len = skb->len - hdr_len;
|
secondlen = skb->len - hdr_len;
|
||||||
if (len) {
|
if (secondlen > 0) {
|
||||||
phys_addr =
|
phys_addr =
|
||||||
pci_map_single(il->pci_dev, skb->data + hdr_len, len,
|
pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen,
|
||||||
PCI_DMA_TODEVICE);
|
PCI_DMA_TODEVICE);
|
||||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr)))
|
if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr)))
|
||||||
goto drop_unlock;
|
goto drop_unlock;
|
||||||
@ -611,12 +613,12 @@ il3945_tx_skb(struct il_priv *il,
|
|||||||
|
|
||||||
/* Add buffer containing Tx command and MAC(!) header to TFD's
|
/* Add buffer containing Tx command and MAC(!) header to TFD's
|
||||||
* first entry */
|
* first entry */
|
||||||
il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0);
|
il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0);
|
||||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||||
dma_unmap_len_set(out_meta, len, len);
|
dma_unmap_len_set(out_meta, len, firstlen);
|
||||||
if (len)
|
if (secondlen > 0)
|
||||||
il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0,
|
il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen, 0,
|
||||||
U32_PAD(len));
|
U32_PAD(secondlen));
|
||||||
|
|
||||||
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||||
txq->need_update = 1;
|
txq->need_update = 1;
|
||||||
|
@ -2152,7 +2152,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
|
|||||||
int rate_idx;
|
int rate_idx;
|
||||||
int i;
|
int i;
|
||||||
u32 rate;
|
u32 rate;
|
||||||
u8 use_green = il4965_rs_use_green(il, sta);
|
u8 use_green;
|
||||||
u8 active_tbl = 0;
|
u8 active_tbl = 0;
|
||||||
u8 valid_tx_ant;
|
u8 valid_tx_ant;
|
||||||
struct il_station_priv *sta_priv;
|
struct il_station_priv *sta_priv;
|
||||||
@ -2160,6 +2160,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
|
|||||||
if (!sta || !lq_sta)
|
if (!sta || !lq_sta)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
use_green = il4965_rs_use_green(il, sta);
|
||||||
sta_priv = (void *)sta->drv_priv;
|
sta_priv = (void *)sta->drv_priv;
|
||||||
|
|
||||||
i = lq_sta->last_txrate_idx;
|
i = lq_sta->last_txrate_idx;
|
||||||
|
@ -1261,6 +1261,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag
|
||||||
|
* in iwl_down but cancel the workers only later.
|
||||||
|
*/
|
||||||
|
if (!priv->ucode_loaded) {
|
||||||
|
IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Synchronous commands from this op-mode must hold
|
* Synchronous commands from this op-mode must hold
|
||||||
* the mutex, this ensures we don't try to send two
|
* the mutex, this ensures we don't try to send two
|
||||||
|
@ -367,6 +367,8 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->ucode_loaded = true;
|
||||||
|
|
||||||
if (ucode_type != IWL_UCODE_WOWLAN) {
|
if (ucode_type != IWL_UCODE_WOWLAN) {
|
||||||
/* delay a bit to give rfkill time to run */
|
/* delay a bit to give rfkill time to run */
|
||||||
msleep(5);
|
msleep(5);
|
||||||
@ -380,8 +382,6 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->ucode_loaded = true;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,6 +475,10 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
|||||||
|
|
||||||
/* If platform's RF_KILL switch is NOT set to KILL */
|
/* If platform's RF_KILL switch is NOT set to KILL */
|
||||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||||
|
if (hw_rfkill)
|
||||||
|
set_bit(STATUS_RFKILL, &trans_pcie->status);
|
||||||
|
else
|
||||||
|
clear_bit(STATUS_RFKILL, &trans_pcie->status);
|
||||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||||
if (hw_rfkill && !run_in_rfkill)
|
if (hw_rfkill && !run_in_rfkill)
|
||||||
return -ERFKILL;
|
return -ERFKILL;
|
||||||
@ -641,6 +645,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
|||||||
|
|
||||||
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
bool hw_rfkill;
|
bool hw_rfkill;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -656,6 +661,10 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
|||||||
iwl_enable_rfkill_int(trans);
|
iwl_enable_rfkill_int(trans);
|
||||||
|
|
||||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||||
|
if (hw_rfkill)
|
||||||
|
set_bit(STATUS_RFKILL, &trans_pcie->status);
|
||||||
|
else
|
||||||
|
clear_bit(STATUS_RFKILL, &trans_pcie->status);
|
||||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -694,6 +703,10 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
|
|||||||
* op_mode.
|
* op_mode.
|
||||||
*/
|
*/
|
||||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||||
|
if (hw_rfkill)
|
||||||
|
set_bit(STATUS_RFKILL, &trans_pcie->status);
|
||||||
|
else
|
||||||
|
clear_bit(STATUS_RFKILL, &trans_pcie->status);
|
||||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1264,7 +1264,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
|||||||
for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
|
for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
|
||||||
int copy = 0;
|
int copy = 0;
|
||||||
|
|
||||||
if (!cmd->len)
|
if (!cmd->len[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
|
/* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
|
||||||
|
@ -157,6 +157,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd_code = le16_to_cpu(host_cmd->command);
|
||||||
|
cmd_size = le16_to_cpu(host_cmd->size);
|
||||||
|
|
||||||
|
if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
|
||||||
|
cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
|
||||||
|
cmd_code != HostCmd_CMD_FUNC_INIT) {
|
||||||
|
dev_err(adapter->dev,
|
||||||
|
"DNLD_CMD: FW in reset state, ignore cmd %#x\n",
|
||||||
|
cmd_code);
|
||||||
|
mwifiex_complete_cmd(adapter, cmd_node);
|
||||||
|
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set command sequence number */
|
/* Set command sequence number */
|
||||||
adapter->seq_num++;
|
adapter->seq_num++;
|
||||||
host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
|
host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
|
||||||
@ -168,9 +182,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
|
|||||||
adapter->curr_cmd = cmd_node;
|
adapter->curr_cmd = cmd_node;
|
||||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||||
|
|
||||||
cmd_code = le16_to_cpu(host_cmd->command);
|
|
||||||
cmd_size = le16_to_cpu(host_cmd->size);
|
|
||||||
|
|
||||||
/* Adjust skb length */
|
/* Adjust skb length */
|
||||||
if (cmd_node->cmd_skb->len > cmd_size)
|
if (cmd_node->cmd_skb->len > cmd_size)
|
||||||
/*
|
/*
|
||||||
@ -484,8 +495,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
|
|||||||
|
|
||||||
ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
|
ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
|
||||||
data_buf);
|
data_buf);
|
||||||
if (!ret)
|
|
||||||
ret = mwifiex_wait_queue_complete(adapter);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -588,9 +597,10 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
|
|||||||
if (cmd_no == HostCmd_CMD_802_11_SCAN) {
|
if (cmd_no == HostCmd_CMD_802_11_SCAN) {
|
||||||
mwifiex_queue_scan_cmd(priv, cmd_node);
|
mwifiex_queue_scan_cmd(priv, cmd_node);
|
||||||
} else {
|
} else {
|
||||||
adapter->cmd_queued = cmd_node;
|
|
||||||
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
|
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
|
||||||
queue_work(adapter->workqueue, &adapter->main_work);
|
queue_work(adapter->workqueue, &adapter->main_work);
|
||||||
|
if (cmd_node->wait_q_enabled)
|
||||||
|
ret = mwifiex_wait_queue_complete(adapter, cmd_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -709,6 +709,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* cancel current command */
|
||||||
|
if (adapter->curr_cmd) {
|
||||||
|
dev_warn(adapter->dev, "curr_cmd is still in processing\n");
|
||||||
|
del_timer(&adapter->cmd_timer);
|
||||||
|
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
|
||||||
|
adapter->curr_cmd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* shut down mwifiex */
|
/* shut down mwifiex */
|
||||||
dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
|
dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
|
||||||
|
|
||||||
|
@ -728,7 +728,6 @@ struct mwifiex_adapter {
|
|||||||
u16 cmd_wait_q_required;
|
u16 cmd_wait_q_required;
|
||||||
struct mwifiex_wait_queue cmd_wait_q;
|
struct mwifiex_wait_queue cmd_wait_q;
|
||||||
u8 scan_wait_q_woken;
|
u8 scan_wait_q_woken;
|
||||||
struct cmd_ctrl_node *cmd_queued;
|
|
||||||
spinlock_t queue_lock; /* lock for tx queues */
|
spinlock_t queue_lock; /* lock for tx queues */
|
||||||
struct completion fw_load;
|
struct completion fw_load;
|
||||||
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
|
||||||
@ -1029,7 +1028,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
|
|||||||
struct mwifiex_multicast_list *mcast_list);
|
struct mwifiex_multicast_list *mcast_list);
|
||||||
int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
|
int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
|
||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
|
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
|
||||||
|
struct cmd_ctrl_node *cmd_queued);
|
||||||
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
|
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
|
||||||
struct cfg80211_ssid *req_ssid);
|
struct cfg80211_ssid *req_ssid);
|
||||||
int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
|
int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
|
||||||
|
@ -1519,6 +1519,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
|
|||||||
}
|
}
|
||||||
memcpy(adapter->upld_buf, skb->data,
|
memcpy(adapter->upld_buf, skb->data,
|
||||||
min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
|
min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
|
||||||
|
skb_push(skb, INTF_HEADER_LEN);
|
||||||
if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
|
if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
|
||||||
PCI_DMA_FROMDEVICE))
|
PCI_DMA_FROMDEVICE))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1388,10 +1388,13 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
|
|||||||
list_del(&cmd_node->list);
|
list_del(&cmd_node->list);
|
||||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||||
flags);
|
flags);
|
||||||
adapter->cmd_queued = cmd_node;
|
|
||||||
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
|
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
|
||||||
true);
|
true);
|
||||||
queue_work(adapter->workqueue, &adapter->main_work);
|
queue_work(adapter->workqueue, &adapter->main_work);
|
||||||
|
|
||||||
|
/* Perform internal scan synchronously */
|
||||||
|
if (!priv->scan_request)
|
||||||
|
mwifiex_wait_queue_complete(adapter, cmd_node);
|
||||||
} else {
|
} else {
|
||||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||||
flags);
|
flags);
|
||||||
@ -1946,9 +1949,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
|
|||||||
/* Normal scan */
|
/* Normal scan */
|
||||||
ret = mwifiex_scan_networks(priv, NULL);
|
ret = mwifiex_scan_networks(priv, NULL);
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
ret = mwifiex_wait_queue_complete(priv->adapter);
|
|
||||||
|
|
||||||
up(&priv->async_sem);
|
up(&priv->async_sem);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -54,16 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
|
|||||||
* This function waits on a cmd wait queue. It also cancels the pending
|
* This function waits on a cmd wait queue. It also cancels the pending
|
||||||
* request after waking up, in case of errors.
|
* request after waking up, in case of errors.
|
||||||
*/
|
*/
|
||||||
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
|
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
|
||||||
|
struct cmd_ctrl_node *cmd_queued)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
struct cmd_ctrl_node *cmd_queued;
|
|
||||||
|
|
||||||
if (!adapter->cmd_queued)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cmd_queued = adapter->cmd_queued;
|
|
||||||
adapter->cmd_queued = NULL;
|
|
||||||
|
|
||||||
dev_dbg(adapter->dev, "cmd pending\n");
|
dev_dbg(adapter->dev, "cmd pending\n");
|
||||||
atomic_inc(&adapter->cmd_pending);
|
atomic_inc(&adapter->cmd_pending);
|
||||||
|
@ -932,6 +932,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||||||
if (unlikely(!_urb)) {
|
if (unlikely(!_urb)) {
|
||||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||||
"Can't allocate urb. Drop skb!\n");
|
"Can't allocate urb. Drop skb!\n");
|
||||||
|
kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_rtl_submit_tx_urb(hw, _urb);
|
_rtl_submit_tx_urb(hw, _urb);
|
||||||
|
@ -359,6 +359,7 @@ static void __sco_sock_close(struct sock *sk)
|
|||||||
sco_chan_del(sk, ECONNRESET);
|
sco_chan_del(sk, ECONNRESET);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BT_CONNECT2:
|
||||||
case BT_CONNECT:
|
case BT_CONNECT:
|
||||||
case BT_DISCONN:
|
case BT_DISCONN:
|
||||||
sco_chan_del(sk, ECONNRESET);
|
sco_chan_del(sk, ECONNRESET);
|
||||||
|
@ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
|
|||||||
static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
|
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
ASSERT_RTNL();
|
||||||
|
|
||||||
if (local->monitor_sdata)
|
if (local->monitor_sdata)
|
||||||
goto out_unlock;
|
return 0;
|
||||||
|
|
||||||
sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
|
sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
|
||||||
if (!sdata) {
|
if (!sdata)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up data */
|
/* set up data */
|
||||||
sdata->local = local;
|
sdata->local = local;
|
||||||
@ -377,13 +375,13 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
|||||||
if (WARN_ON(ret)) {
|
if (WARN_ON(ret)) {
|
||||||
/* ok .. stupid driver, it asked for this! */
|
/* ok .. stupid driver, it asked for this! */
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
goto out_unlock;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ieee80211_check_queues(sdata);
|
ret = ieee80211_check_queues(sdata);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
goto out_unlock;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
|
ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
|
||||||
@ -391,13 +389,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
drv_remove_interface(local, sdata);
|
drv_remove_interface(local, sdata);
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
goto out_unlock;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&local->iflist_mtx);
|
||||||
rcu_assign_pointer(local->monitor_sdata, sdata);
|
rcu_assign_pointer(local->monitor_sdata, sdata);
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&local->iflist_mtx);
|
mutex_unlock(&local->iflist_mtx);
|
||||||
return ret;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
|
static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
|
||||||
@ -407,14 +406,20 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
|
|||||||
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
|
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ASSERT_RTNL();
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
|
|
||||||
sdata = rcu_dereference_protected(local->monitor_sdata,
|
sdata = rcu_dereference_protected(local->monitor_sdata,
|
||||||
lockdep_is_held(&local->iflist_mtx));
|
lockdep_is_held(&local->iflist_mtx));
|
||||||
if (!sdata)
|
if (!sdata) {
|
||||||
goto out_unlock;
|
mutex_unlock(&local->iflist_mtx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rcu_assign_pointer(local->monitor_sdata, NULL);
|
rcu_assign_pointer(local->monitor_sdata, NULL);
|
||||||
|
mutex_unlock(&local->iflist_mtx);
|
||||||
|
|
||||||
synchronize_net();
|
synchronize_net();
|
||||||
|
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
@ -422,8 +427,6 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
|
|||||||
drv_remove_interface(local, sdata);
|
drv_remove_interface(local, sdata);
|
||||||
|
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&local->iflist_mtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1004,7 +1004,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
|
|||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
||||||
if (ieee80211_vif_is_mesh(&sdata->vif))
|
if (ieee80211_vif_is_mesh(&sdata->vif) &&
|
||||||
|
ieee80211_sdata_running(sdata))
|
||||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
@ -3531,8 +3531,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
|
|||||||
|
|
||||||
/* Restart STA timers */
|
/* Restart STA timers */
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||||
|
if (ieee80211_sdata_running(sdata))
|
||||||
ieee80211_restart_sta_timer(sdata);
|
ieee80211_restart_sta_timer(sdata);
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2666,7 +2666,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
|
|||||||
|
|
||||||
memset(nskb->cb, 0, sizeof(nskb->cb));
|
memset(nskb->cb, 0, sizeof(nskb->cb));
|
||||||
|
|
||||||
ieee80211_tx_skb(rx->sdata, nskb);
|
if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb);
|
||||||
|
|
||||||
|
info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
|
||||||
|
IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
|
||||||
|
IEEE80211_TX_CTL_NO_CCK_RATE;
|
||||||
|
if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
|
||||||
|
info->hw_queue =
|
||||||
|
local->hw.offchannel_tx_hw_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
__ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7,
|
||||||
|
status->band);
|
||||||
}
|
}
|
||||||
dev_kfree_skb(rx->skb);
|
dev_kfree_skb(rx->skb);
|
||||||
return RX_QUEUED;
|
return RX_QUEUED;
|
||||||
|
@ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
|
|||||||
rdev_rfkill_poll(rdev);
|
rdev_rfkill_poll(rdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
||||||
|
struct wireless_dev *wdev)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(&rdev->devlist_mtx);
|
||||||
|
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
|
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!wdev->p2p_started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rdev_stop_p2p_device(rdev, wdev);
|
||||||
|
wdev->p2p_started = false;
|
||||||
|
|
||||||
|
rdev->opencount--;
|
||||||
|
|
||||||
|
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
|
||||||
|
bool busy = work_busy(&rdev->scan_done_wk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the work isn't pending or running (in which case it would
|
||||||
|
* be waiting for the lock we hold) the driver didn't properly
|
||||||
|
* cancel the scan when the interface was removed. In this case
|
||||||
|
* warn and leak the scan request object to not crash later.
|
||||||
|
*/
|
||||||
|
WARN_ON(!busy);
|
||||||
|
|
||||||
|
rdev->scan_req->aborted = true;
|
||||||
|
___cfg80211_scan_done(rdev, !busy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = data;
|
struct cfg80211_registered_device *rdev = data;
|
||||||
@ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
|
||||||
|
/* read-only iteration need not hold the devlist_mtx */
|
||||||
|
|
||||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||||
if (wdev->netdev) {
|
if (wdev->netdev) {
|
||||||
@ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
|||||||
/* otherwise, check iftype */
|
/* otherwise, check iftype */
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
if (!wdev->p2p_started)
|
/* but this requires it */
|
||||||
break;
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
rdev_stop_p2p_device(rdev, wdev);
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev->p2p_started = false;
|
cfg80211_stop_p2p_device(rdev, wdev);
|
||||||
rdev->opencount--;
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -745,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work)
|
|||||||
wdev = container_of(work, struct wireless_dev, cleanup_work);
|
wdev = container_of(work, struct wireless_dev, cleanup_work);
|
||||||
rdev = wiphy_to_dev(wdev->wiphy);
|
rdev = wiphy_to_dev(wdev->wiphy);
|
||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
|
if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
|
||||||
rdev->scan_req->aborted = true;
|
rdev->scan_req->aborted = true;
|
||||||
___cfg80211_scan_done(rdev, true);
|
___cfg80211_scan_done(rdev, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg80211_unlock_rdev(rdev);
|
|
||||||
|
|
||||||
mutex_lock(&rdev->sched_scan_mtx);
|
|
||||||
|
|
||||||
if (WARN_ON(rdev->sched_scan_req &&
|
if (WARN_ON(rdev->sched_scan_req &&
|
||||||
rdev->sched_scan_req->dev == wdev->netdev)) {
|
rdev->sched_scan_req->dev == wdev->netdev)) {
|
||||||
__cfg80211_stop_sched_scan(rdev, false);
|
__cfg80211_stop_sched_scan(rdev, false);
|
||||||
@ -781,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
list_del_rcu(&wdev->list);
|
list_del_rcu(&wdev->list);
|
||||||
rdev->devlist_generation++;
|
rdev->devlist_generation++;
|
||||||
|
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
if (!wdev->p2p_started)
|
cfg80211_stop_p2p_device(rdev, wdev);
|
||||||
break;
|
|
||||||
rdev_stop_p2p_device(rdev, wdev);
|
|
||||||
wdev->p2p_started = false;
|
|
||||||
rdev->opencount--;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_unregister_wdev);
|
EXPORT_SYMBOL(cfg80211_unregister_wdev);
|
||||||
@ -945,6 +973,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||||||
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
|
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
#ifdef CONFIG_CFG80211_WEXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
@ -976,6 +1005,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
rdev->opencount++;
|
rdev->opencount++;
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
|
@ -503,6 +503,9 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
|||||||
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev);
|
struct wireless_dev *wdev);
|
||||||
|
|
||||||
|
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
||||||
|
struct wireless_dev *wdev);
|
||||||
|
|
||||||
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
|
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
|
||||||
|
|
||||||
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
|
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
|
||||||
|
@ -5048,14 +5048,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||||||
if (!rdev->ops->scan)
|
if (!rdev->ops->scan)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (rdev->scan_req)
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
return -EBUSY;
|
if (rdev->scan_req) {
|
||||||
|
err = -EBUSY;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
||||||
n_channels = validate_scan_freqs(
|
n_channels = validate_scan_freqs(
|
||||||
info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
|
info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
|
||||||
if (!n_channels)
|
if (!n_channels) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
n_channels = 0;
|
n_channels = 0;
|
||||||
@ -5069,23 +5074,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||||||
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
|
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
|
||||||
n_ssids++;
|
n_ssids++;
|
||||||
|
|
||||||
if (n_ssids > wiphy->max_scan_ssids)
|
if (n_ssids > wiphy->max_scan_ssids) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_IE])
|
if (info->attrs[NL80211_ATTR_IE])
|
||||||
ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
|
ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
|
||||||
else
|
else
|
||||||
ie_len = 0;
|
ie_len = 0;
|
||||||
|
|
||||||
if (ie_len > wiphy->max_scan_ie_len)
|
if (ie_len > wiphy->max_scan_ie_len) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
request = kzalloc(sizeof(*request)
|
request = kzalloc(sizeof(*request)
|
||||||
+ sizeof(*request->ssids) * n_ssids
|
+ sizeof(*request->ssids) * n_ssids
|
||||||
+ sizeof(*request->channels) * n_channels
|
+ sizeof(*request->channels) * n_channels
|
||||||
+ ie_len, GFP_KERNEL);
|
+ ie_len, GFP_KERNEL);
|
||||||
if (!request)
|
if (!request) {
|
||||||
return -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (n_ssids)
|
if (n_ssids)
|
||||||
request->ssids = (void *)&request->channels[n_channels];
|
request->ssids = (void *)&request->channels[n_channels];
|
||||||
@ -5222,6 +5233,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||||||
kfree(request);
|
kfree(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8130,20 +8143,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
|
|||||||
if (!rdev->ops->stop_p2p_device)
|
if (!rdev->ops->stop_p2p_device)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (!wdev->p2p_started)
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
return 0;
|
cfg80211_stop_p2p_device(rdev, wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
rdev_stop_p2p_device(rdev, wdev);
|
|
||||||
wdev->p2p_started = false;
|
|
||||||
|
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
|
||||||
rdev->opencount--;
|
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
|
||||||
|
|
||||||
if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
|
|
||||||
rdev->scan_req->aborted = true;
|
|
||||||
___cfg80211_scan_done(rdev, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -8929,7 +8931,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
|
|||||||
struct nlattr *nest;
|
struct nlattr *nest;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ASSERT_RDEV_LOCK(rdev);
|
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
if (WARN_ON(!req))
|
if (WARN_ON(!req))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
|||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ASSERT_RDEV_LOCK(rdev);
|
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
request = rdev->scan_req;
|
request = rdev->scan_req;
|
||||||
|
|
||||||
@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
|
|||||||
rdev = container_of(wk, struct cfg80211_registered_device,
|
rdev = container_of(wk, struct cfg80211_registered_device,
|
||||||
scan_done_wk);
|
scan_done_wk);
|
||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
___cfg80211_scan_done(rdev, false);
|
___cfg80211_scan_done(rdev, false);
|
||||||
cfg80211_unlock_rdev(rdev);
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
|
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
|
||||||
@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
|||||||
found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
|
found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
found->pub.beacon_interval = tmp->pub.beacon_interval;
|
|
||||||
found->pub.signal = tmp->pub.signal;
|
|
||||||
found->pub.capability = tmp->pub.capability;
|
|
||||||
found->ts = tmp->ts;
|
|
||||||
|
|
||||||
/* Update IEs */
|
/* Update IEs */
|
||||||
if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
|
if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
|
||||||
const struct cfg80211_bss_ies *old;
|
const struct cfg80211_bss_ies *old;
|
||||||
@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
|||||||
|
|
||||||
if (found->pub.hidden_beacon_bss &&
|
if (found->pub.hidden_beacon_bss &&
|
||||||
!list_empty(&found->hidden_list)) {
|
!list_empty(&found->hidden_list)) {
|
||||||
|
const struct cfg80211_bss_ies *f;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The found BSS struct is one of the probe
|
* The found BSS struct is one of the probe
|
||||||
* response members of a group, but we're
|
* response members of a group, but we're
|
||||||
@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
|||||||
* SSID to showing it, which is confusing so
|
* SSID to showing it, which is confusing so
|
||||||
* drop this information.
|
* drop this information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
f = rcu_access_pointer(tmp->pub.beacon_ies);
|
||||||
|
kfree_rcu((struct cfg80211_bss_ies *)f,
|
||||||
|
rcu_head);
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
|||||||
kfree_rcu((struct cfg80211_bss_ies *)old,
|
kfree_rcu((struct cfg80211_bss_ies *)old,
|
||||||
rcu_head);
|
rcu_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
found->pub.beacon_interval = tmp->pub.beacon_interval;
|
||||||
|
found->pub.signal = tmp->pub.signal;
|
||||||
|
found->pub.capability = tmp->pub.capability;
|
||||||
|
found->ts = tmp->ts;
|
||||||
} else {
|
} else {
|
||||||
struct cfg80211_internal_bss *new;
|
struct cfg80211_internal_bss *new;
|
||||||
struct cfg80211_internal_bss *hidden;
|
struct cfg80211_internal_bss *hidden;
|
||||||
@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
|||||||
if (IS_ERR(rdev))
|
if (IS_ERR(rdev))
|
||||||
return PTR_ERR(rdev);
|
return PTR_ERR(rdev);
|
||||||
|
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
if (rdev->scan_req) {
|
if (rdev->scan_req) {
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
|||||||
dev_hold(dev);
|
dev_hold(dev);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
kfree(creq);
|
kfree(creq);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
|
@ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
|
|||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
ASSERT_RDEV_LOCK(rdev);
|
ASSERT_RDEV_LOCK(rdev);
|
||||||
ASSERT_WDEV_LOCK(wdev);
|
ASSERT_WDEV_LOCK(wdev);
|
||||||
|
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
if (rdev->scan_req)
|
if (rdev->scan_req)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
@ -324,11 +325,9 @@ void cfg80211_sme_scan_done(struct net_device *dev)
|
|||||||
{
|
{
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
|
|
||||||
mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
|
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
__cfg80211_sme_scan_done(dev);
|
__cfg80211_sme_scan_done(dev);
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cfg80211_sme_rx_auth(struct net_device *dev,
|
void cfg80211_sme_rx_auth(struct net_device *dev,
|
||||||
@ -928,9 +927,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
/* might request scan - scan_mtx -> wdev_mtx dependency */
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(dev->ieee80211_ptr);
|
wdev_lock(dev->ieee80211_ptr);
|
||||||
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
|
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
|
||||||
wdev_unlock(dev->ieee80211_ptr);
|
wdev_unlock(dev->ieee80211_ptr);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -27,7 +27,8 @@
|
|||||||
#define WIPHY_PR_ARG __entry->wiphy_name
|
#define WIPHY_PR_ARG __entry->wiphy_name
|
||||||
|
|
||||||
#define WDEV_ENTRY __field(u32, id)
|
#define WDEV_ENTRY __field(u32, id)
|
||||||
#define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0)
|
#define WDEV_ASSIGN (__entry->id) = (!IS_ERR_OR_NULL(wdev) \
|
||||||
|
? wdev->identifier : 0)
|
||||||
#define WDEV_PR_FMT "wdev(%u)"
|
#define WDEV_PR_FMT "wdev(%u)"
|
||||||
#define WDEV_PR_ARG (__entry->id)
|
#define WDEV_PR_ARG (__entry->id)
|
||||||
|
|
||||||
@ -1778,7 +1779,7 @@ TRACE_EVENT(rdev_set_mac_acl,
|
|||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
WIPHY_ASSIGN;
|
NETDEV_ASSIGN;
|
||||||
__entry->acl_policy = params->acl_policy;
|
__entry->acl_policy = params->acl_policy;
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d",
|
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d",
|
||||||
|
@ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
|
|||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
|
||||||
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
||||||
@ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
|
|||||||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||||
out:
|
out:
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
@ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
|
|||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
@ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
|
|||||||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||||
out:
|
out:
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
@ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
|
|||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
|
||||||
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
||||||
@ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
|
|||||||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||||
out:
|
out:
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user