Commit 75a241f9 authored by David S. Miller's avatar David S. Miller
parents e18e37e5 957b0516
...@@ -2101,6 +2101,9 @@ static int gelic_wl_associate_bss(struct gelic_wl_info *wl, ...@@ -2101,6 +2101,9 @@ static int gelic_wl_associate_bss(struct gelic_wl_info *wl,
if (ret) { if (ret) {
pr_debug("%s: WEP/WPA setup failed %d\n", __func__, pr_debug("%s: WEP/WPA setup failed %d\n", __func__,
ret); ret);
ret = -EPERM;
gelic_wl_send_iwap_event(wl, NULL);
goto out;
} }
/* start association */ /* start association */
......
...@@ -6713,11 +6713,11 @@ static int airo_set_auth(struct net_device *dev, ...@@ -6713,11 +6713,11 @@ static int airo_set_auth(struct net_device *dev,
local->config.authType = AUTH_ENCRYPT; local->config.authType = AUTH_ENCRYPT;
} else } else
return -EINVAL; return -EINVAL;
break;
/* Commit the changes to flags if needed */ /* Commit the changes to flags if needed */
if (local->config.authType != currentAuthType) if (local->config.authType != currentAuthType)
set_bit (FLAG_COMMIT, &local->flags); set_bit (FLAG_COMMIT, &local->flags);
break;
} }
case IW_AUTH_WPA_ENABLED: case IW_AUTH_WPA_ENABLED:
......
...@@ -310,7 +310,7 @@ struct ar9170_tx_control { ...@@ -310,7 +310,7 @@ struct ar9170_tx_control {
struct ar9170_rx_head { struct ar9170_rx_head {
u8 plcp[12]; u8 plcp[12];
}; } __packed;
struct ar9170_rx_tail { struct ar9170_rx_tail {
union { union {
...@@ -318,16 +318,16 @@ struct ar9170_rx_tail { ...@@ -318,16 +318,16 @@ struct ar9170_rx_tail {
u8 rssi_ant0, rssi_ant1, rssi_ant2, u8 rssi_ant0, rssi_ant1, rssi_ant2,
rssi_ant0x, rssi_ant1x, rssi_ant2x, rssi_ant0x, rssi_ant1x, rssi_ant2x,
rssi_combined; rssi_combined;
}; } __packed;
u8 rssi[7]; u8 rssi[7];
}; } __packed;
u8 evm_stream0[6], evm_stream1[6]; u8 evm_stream0[6], evm_stream1[6];
u8 phy_err; u8 phy_err;
u8 SAidx, DAidx; u8 SAidx, DAidx;
u8 error; u8 error;
u8 status; u8 status;
}; } __packed;
#define AR9170_ENC_ALG_NONE 0x0 #define AR9170_ENC_ALG_NONE 0x0
#define AR9170_ENC_ALG_WEP64 0x1 #define AR9170_ENC_ALG_WEP64 0x1
......
...@@ -59,6 +59,8 @@ static struct usb_device_id ar9170_usb_ids[] = { ...@@ -59,6 +59,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0x9170) }, { USB_DEVICE(0x0cf3, 0x9170) },
/* Atheros TG121N */ /* Atheros TG121N */
{ USB_DEVICE(0x0cf3, 0x1001) }, { USB_DEVICE(0x0cf3, 0x1001) },
/* Cace Airpcap NX */
{ USB_DEVICE(0xcace, 0x0300) },
/* D-Link DWA 160A */ /* D-Link DWA 160A */
{ USB_DEVICE(0x07d1, 0x3c10) }, { USB_DEVICE(0x07d1, 0x3c10) },
/* Netgear WNDA3100 */ /* Netgear WNDA3100 */
...@@ -67,6 +69,8 @@ static struct usb_device_id ar9170_usb_ids[] = { ...@@ -67,6 +69,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
{ USB_DEVICE(0x0846, 0x9001) }, { USB_DEVICE(0x0846, 0x9001) },
/* Zydas ZD1221 */ /* Zydas ZD1221 */
{ USB_DEVICE(0x0ace, 0x1221) }, { USB_DEVICE(0x0ace, 0x1221) },
/* ZyXEL NWD271N */
{ USB_DEVICE(0x0586, 0x3417) },
/* Z-Com UB81 BG */ /* Z-Com UB81 BG */
{ USB_DEVICE(0x0cde, 0x0023) }, { USB_DEVICE(0x0cde, 0x0023) },
/* Z-Com UB82 ABG */ /* Z-Com UB82 ABG */
......
...@@ -250,6 +250,8 @@ static struct usb_device_id dev_table[] = { ...@@ -250,6 +250,8 @@ static struct usb_device_id dev_table[] = {
{ USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A) }, { USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A) },
/* Siemens Gigaset USB WLAN Adapter 11 */ /* Siemens Gigaset USB WLAN Adapter 11 */
{ USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A) }, { USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A) },
/* OQO Model 01+ Internal Wi-Fi */
{ USB_DEVICE(0x1557, 0x0002), USB_DEVICE_DATA(BOARD_505A) },
/* /*
* at76c505amx-rfmd * at76c505amx-rfmd
*/ */
......
...@@ -493,6 +493,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) ...@@ -493,6 +493,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
int hdrlen, padsize, retval; int hdrlen, padsize, retval;
bool decrypt_error = false; bool decrypt_error = false;
u8 keyix; u8 keyix;
__le16 fc;
spin_lock_bh(&sc->rx.rxbuflock); spin_lock_bh(&sc->rx.rxbuflock);
...@@ -606,6 +607,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) ...@@ -606,6 +607,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
/* see if any padding is done by the hw and remove it */ /* see if any padding is done by the hw and remove it */
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb); hdrlen = ieee80211_get_hdrlen_from_skb(skb);
fc = hdr->frame_control;
/* The MAC header is padded to have 32-bit boundary if the /* The MAC header is padded to have 32-bit boundary if the
* packet payload is non-zero. The general calculation for * packet payload is non-zero. The general calculation for
...@@ -690,7 +692,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) ...@@ -690,7 +692,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
sc->rx.rxotherant = 0; sc->rx.rxotherant = 0;
} }
if (ieee80211_is_beacon(hdr->frame_control) && if (ieee80211_is_beacon(fc) &&
(sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) { (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) {
sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
......
...@@ -555,11 +555,32 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, ...@@ -555,11 +555,32 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
return 1; return 1;
} }
static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb)
{
unsigned char *f = skb->data + ring->frameoffset;
return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7]) == 0xFF);
}
static void b43_poison_rx_buffer(struct b43_dmaring *ring, struct sk_buff *skb)
{
struct b43_rxhdr_fw4 *rxhdr;
unsigned char *frame;
/* This poisons the RX buffer to detect DMA failures. */
rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
rxhdr->frame_len = 0;
B43_WARN_ON(ring->rx_buffersize < ring->frameoffset + sizeof(struct b43_plcp_hdr6) + 2);
frame = skb->data + ring->frameoffset;
memset(frame, 0xFF, sizeof(struct b43_plcp_hdr6) + 2 /* padding */);
}
static int setup_rx_descbuffer(struct b43_dmaring *ring, static int setup_rx_descbuffer(struct b43_dmaring *ring,
struct b43_dmadesc_generic *desc, struct b43_dmadesc_generic *desc,
struct b43_dmadesc_meta *meta, gfp_t gfp_flags) struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
{ {
struct b43_rxhdr_fw4 *rxhdr;
dma_addr_t dmaaddr; dma_addr_t dmaaddr;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -568,6 +589,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, ...@@ -568,6 +589,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
if (unlikely(!skb)) if (unlikely(!skb))
return -ENOMEM; return -ENOMEM;
b43_poison_rx_buffer(ring, skb);
dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
/* ugh. try to realloc in zone_dma */ /* ugh. try to realloc in zone_dma */
...@@ -578,6 +600,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, ...@@ -578,6 +600,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
if (unlikely(!skb)) if (unlikely(!skb))
return -ENOMEM; return -ENOMEM;
b43_poison_rx_buffer(ring, skb);
dmaaddr = map_descbuffer(ring, skb->data, dmaaddr = map_descbuffer(ring, skb->data,
ring->rx_buffersize, 0); ring->rx_buffersize, 0);
if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
...@@ -592,9 +615,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, ...@@ -592,9 +615,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
ring->ops->fill_descriptor(ring, desc, dmaaddr, ring->ops->fill_descriptor(ring, desc, dmaaddr,
ring->rx_buffersize, 0, 0, 0); ring->rx_buffersize, 0, 0, 0);
rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
rxhdr->frame_len = 0;
return 0; return 0;
} }
...@@ -1483,12 +1503,17 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) ...@@ -1483,12 +1503,17 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
len = le16_to_cpu(rxhdr->frame_len); len = le16_to_cpu(rxhdr->frame_len);
} while (len == 0 && i++ < 5); } while (len == 0 && i++ < 5);
if (unlikely(len == 0)) { if (unlikely(len == 0)) {
/* recycle the descriptor buffer. */ dmaaddr = meta->dmaaddr;
sync_descbuffer_for_device(ring, meta->dmaaddr, goto drop_recycle_buffer;
ring->rx_buffersize);
goto drop;
} }
} }
if (unlikely(b43_rx_buffer_is_poisoned(ring, skb))) {
/* Something went wrong with the DMA.
* The device did not touch the buffer and did not overwrite the poison. */
b43dbg(ring->dev->wl, "DMA RX: Dropping poisoned buffer.\n");
dmaaddr = meta->dmaaddr;
goto drop_recycle_buffer;
}
if (unlikely(len > ring->rx_buffersize)) { if (unlikely(len > ring->rx_buffersize)) {
/* The data did not fit into one descriptor buffer /* The data did not fit into one descriptor buffer
* and is split over multiple buffers. * and is split over multiple buffers.
...@@ -1501,6 +1526,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) ...@@ -1501,6 +1526,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
while (1) { while (1) {
desc = ops->idx2desc(ring, *slot, &meta); desc = ops->idx2desc(ring, *slot, &meta);
/* recycle the descriptor buffer. */ /* recycle the descriptor buffer. */
b43_poison_rx_buffer(ring, meta->skb);
sync_descbuffer_for_device(ring, meta->dmaaddr, sync_descbuffer_for_device(ring, meta->dmaaddr,
ring->rx_buffersize); ring->rx_buffersize);
*slot = next_slot(ring, *slot); *slot = next_slot(ring, *slot);
...@@ -1519,8 +1545,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) ...@@ -1519,8 +1545,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
if (unlikely(err)) { if (unlikely(err)) {
b43dbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer() failed\n"); b43dbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer() failed\n");
sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); goto drop_recycle_buffer;
goto drop;
} }
unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
...@@ -1530,6 +1555,11 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) ...@@ -1530,6 +1555,11 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
b43_rx(ring->dev, skb, rxhdr); b43_rx(ring->dev, skb, rxhdr);
drop: drop:
return; return;
drop_recycle_buffer:
/* Poison and recycle the RX buffer. */
b43_poison_rx_buffer(ring, skb);
sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
} }
void b43_dma_rx(struct b43_dmaring *ring) void b43_dma_rx(struct b43_dmaring *ring)
......
...@@ -3974,6 +3974,11 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev, ...@@ -3974,6 +3974,11 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
phy->next_txpwr_check_time = jiffies; phy->next_txpwr_check_time = jiffies;
/* PHY TX errors counter. */ /* PHY TX errors counter. */
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
#if B43_DEBUG
phy->phy_locked = 0;
phy->radio_locked = 0;
#endif
} }
static void setup_struct_wldev_for_init(struct b43_wldev *dev) static void setup_struct_wldev_for_init(struct b43_wldev *dev)
......
...@@ -131,12 +131,16 @@ void b43_radio_lock(struct b43_wldev *dev) ...@@ -131,12 +131,16 @@ void b43_radio_lock(struct b43_wldev *dev)
{ {
u32 macctl; u32 macctl;
#if B43_DEBUG
B43_WARN_ON(dev->phy.radio_locked);
dev->phy.radio_locked = 1;
#endif
macctl = b43_read32(dev, B43_MMIO_MACCTL); macctl = b43_read32(dev, B43_MMIO_MACCTL);
B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK);
macctl |= B43_MACCTL_RADIOLOCK; macctl |= B43_MACCTL_RADIOLOCK;
b43_write32(dev, B43_MMIO_MACCTL, macctl); b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Commit the write and wait for the device /* Commit the write and wait for the firmware
* to exit any radio register access. */ * to finish any radio register access. */
b43_read32(dev, B43_MMIO_MACCTL); b43_read32(dev, B43_MMIO_MACCTL);
udelay(10); udelay(10);
} }
...@@ -145,11 +149,15 @@ void b43_radio_unlock(struct b43_wldev *dev) ...@@ -145,11 +149,15 @@ void b43_radio_unlock(struct b43_wldev *dev)
{ {
u32 macctl; u32 macctl;
#if B43_DEBUG
B43_WARN_ON(!dev->phy.radio_locked);
dev->phy.radio_locked = 0;
#endif
/* Commit any write */ /* Commit any write */
b43_read16(dev, B43_MMIO_PHY_VER); b43_read16(dev, B43_MMIO_PHY_VER);
/* unlock */ /* unlock */
macctl = b43_read32(dev, B43_MMIO_MACCTL); macctl = b43_read32(dev, B43_MMIO_MACCTL);
B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK));
macctl &= ~B43_MACCTL_RADIOLOCK; macctl &= ~B43_MACCTL_RADIOLOCK;
b43_write32(dev, B43_MMIO_MACCTL, macctl); b43_write32(dev, B43_MMIO_MACCTL, macctl);
} }
......
...@@ -245,8 +245,10 @@ struct b43_phy { ...@@ -245,8 +245,10 @@ struct b43_phy {
atomic_t txerr_cnt; atomic_t txerr_cnt;
#ifdef CONFIG_B43_DEBUG #ifdef CONFIG_B43_DEBUG
/* PHY registers locked by b43_phy_lock()? */ /* PHY registers locked (w.r.t. firmware) */
bool phy_locked; bool phy_locked;
/* Radio registers locked (w.r.t. firmware) */
bool radio_locked;
#endif /* B43_DEBUG */ #endif /* B43_DEBUG */
}; };
......
...@@ -4913,6 +4913,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) ...@@ -4913,6 +4913,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
hw->wiphy->custom_regulatory = true; hw->wiphy->custom_regulatory = true;
hw->wiphy->max_scan_ssids = 1; /* WILL FIX */
/* Default value; 4 EDCA QOS priorities */ /* Default value; 4 EDCA QOS priorities */
hw->queues = 4; hw->queues = 4;
......
...@@ -170,6 +170,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) ...@@ -170,6 +170,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
lbs_deb_rx("rx err: frame received with bad length\n"); lbs_deb_rx("rx err: frame received with bad length\n");
dev->stats.rx_length_errors++; dev->stats.rx_length_errors++;
ret = 0; ret = 0;
dev_kfree_skb(skb);
goto done; goto done;
} }
...@@ -181,6 +182,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) ...@@ -181,6 +182,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
lbs_pr_alert("rxpd not ok\n"); lbs_pr_alert("rxpd not ok\n");
dev->stats.rx_errors++; dev->stats.rx_errors++;
ret = 0; ret = 0;
dev_kfree_skb(skb);
goto done; goto done;
} }
......
...@@ -372,15 +372,13 @@ int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx, ...@@ -372,15 +372,13 @@ int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
} }
/* Wait upto 100ms for tx queue to empty */ /* Wait upto 100ms for tx queue to empty */
k = 100; for (k = 100; k > 0; k--) {
do {
k--;
udelay(1000); udelay(1000);
ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY, ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
&xmitting); &xmitting);
if (ret) if (ret || !xmitting)
break; break;
} while ((k > 0) && xmitting); }
if (k == 0) if (k == 0)
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
......
...@@ -14,9 +14,9 @@ ...@@ -14,9 +14,9 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_P54_LEDS
#include <linux/leds.h> #include <linux/leds.h>
#endif /* CONFIG_MAC80211_LEDS */ #endif /* CONFIG_P54_LEDS */
enum p54_control_frame_types { enum p54_control_frame_types {
P54_CONTROL_TYPE_SETUP = 0, P54_CONTROL_TYPE_SETUP = 0,
...@@ -116,7 +116,7 @@ enum fw_state { ...@@ -116,7 +116,7 @@ enum fw_state {
FW_STATE_RESETTING, FW_STATE_RESETTING,
}; };
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_P54_LEDS
#define P54_LED_MAX_NAME_LEN 31 #define P54_LED_MAX_NAME_LEN 31
...@@ -129,7 +129,7 @@ struct p54_led_dev { ...@@ -129,7 +129,7 @@ struct p54_led_dev {
unsigned int registered; unsigned int registered;
}; };
#endif /* CONFIG_MAC80211_LEDS */ #endif /* CONFIG_P54_LEDS */
struct p54_common { struct p54_common {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
...@@ -177,10 +177,10 @@ struct p54_common { ...@@ -177,10 +177,10 @@ struct p54_common {
u8 privacy_caps; u8 privacy_caps;
u8 rx_keycache_size; u8 rx_keycache_size;
/* LED management */ /* LED management */
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_P54_LEDS
struct p54_led_dev assoc_led; struct p54_led_dev assoc_led;
struct p54_led_dev tx_led; struct p54_led_dev tx_led;
#endif /* CONFIG_MAC80211_LEDS */ #endif /* CONFIG_P54_LEDS */
u16 softled_state; /* bit field of glowing LEDs */ u16 softled_state; /* bit field of glowing LEDs */
}; };
......
...@@ -457,9 +457,10 @@ static int p54spi_wq_tx(struct p54s_priv *priv) ...@@ -457,9 +457,10 @@ static int p54spi_wq_tx(struct p54s_priv *priv)
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
struct p54_tx_info *minfo; struct p54_tx_info *minfo;
struct p54s_tx_info *dinfo; struct p54s_tx_info *dinfo;
unsigned long flags;
int ret = 0; int ret = 0;
spin_lock_bh(&priv->tx_lock); spin_lock_irqsave(&priv->tx_lock, flags);
while (!list_empty(&priv->tx_pending)) { while (!list_empty(&priv->tx_pending)) {
entry = list_entry(priv->tx_pending.next, entry = list_entry(priv->tx_pending.next,
...@@ -467,7 +468,7 @@ static int p54spi_wq_tx(struct p54s_priv *priv) ...@@ -467,7 +468,7 @@ static int p54spi_wq_tx(struct p54s_priv *priv)
list_del_init(&entry->tx_list); list_del_init(&entry->tx_list);
spin_unlock_bh(&priv->tx_lock); spin_unlock_irqrestore(&priv->tx_lock, flags);
dinfo = container_of((void *) entry, struct p54s_tx_info, dinfo = container_of((void *) entry, struct p54s_tx_info,
tx_list); tx_list);
...@@ -479,16 +480,14 @@ static int p54spi_wq_tx(struct p54s_priv *priv) ...@@ -479,16 +480,14 @@ static int p54spi_wq_tx(struct p54s_priv *priv)
ret = p54spi_tx_frame(priv, skb); ret = p54spi_tx_frame(priv, skb);
spin_lock_bh(&priv->tx_lock);
if (ret < 0) { if (ret < 0) {
p54_free_skb(priv->hw, skb); p54_free_skb(priv->hw, skb);
goto out; return ret;
} }
}
out: spin_lock_irqsave(&priv->tx_lock, flags);
spin_unlock_bh(&priv->tx_lock); }
spin_unlock_irqrestore(&priv->tx_lock, flags);
return ret; return ret;
} }
...@@ -498,12 +497,13 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb) ...@@ -498,12 +497,13 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct p54_tx_info *mi = (struct p54_tx_info *) info->rate_driver_data; struct p54_tx_info *mi = (struct p54_tx_info *) info->rate_driver_data;
struct p54s_tx_info *di = (struct p54s_tx_info *) mi->data; struct p54s_tx_info *di = (struct p54s_tx_info *) mi->data;
unsigned long flags;
BUILD_BUG_ON(sizeof(*di) > sizeof((mi->data))); BUILD_BUG_ON(sizeof(*di) > sizeof((mi->data)));
spin_lock_bh(&priv->tx_lock); spin_lock_irqsave(&priv->tx_lock, flags);
list_add_tail(&di->tx_list, &priv->tx_pending); list_add_tail(&di->tx_list, &priv->tx_pending);
spin_unlock_bh(&priv->tx_lock); spin_unlock_irqrestore(&priv->tx_lock, flags);
queue_work(priv->hw->workqueue, &priv->work); queue_work(priv->hw->workqueue, &priv->work);
} }
...@@ -604,6 +604,7 @@ static int p54spi_op_start(struct ieee80211_hw *dev) ...@@ -604,6 +604,7 @@ static int p54spi_op_start(struct ieee80211_hw *dev)
static void p54spi_op_stop(struct ieee80211_hw *dev) static void p54spi_op_stop(struct ieee80211_hw *dev)
{ {
struct p54s_priv *priv = dev->priv; struct p54s_priv *priv = dev->priv;
unsigned long flags;
if (mutex_lock_interruptible(&priv->mutex)) { if (mutex_lock_interruptible(&priv->mutex)) {
/* FIXME: how to handle this error? */ /* FIXME: how to handle this error? */
...@@ -615,9 +616,9 @@ static void p54spi_op_stop(struct ieee80211_hw *dev) ...@@ -615,9 +616,9 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
cancel_work_sync(&priv->work); cancel_work_sync(&priv->work);
p54spi_power_off(priv); p54spi_power_off(priv);
spin_lock_bh(&priv->tx_lock); spin_lock_irqsave(&priv->tx_lock, flags);
INIT_LIST_HEAD(&priv->tx_pending); INIT_LIST_HEAD(&priv->tx_pending);
spin_unlock_bh(&priv->tx_lock); spin_unlock_irqrestore(&priv->tx_lock, flags);
priv->fw_state = FW_STATE_OFF; priv->fw_state = FW_STATE_OFF;
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
......
...@@ -71,6 +71,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { ...@@ -71,6 +71,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */
{USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
{USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
{USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */
{USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
{USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
{USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
......
...@@ -646,10 +646,8 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) ...@@ -646,10 +646,8 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
* Register HW. * Register HW.
*/ */
status = ieee80211_register_hw(rt2x00dev->hw); status = ieee80211_register_hw(rt2x00dev->hw);
if (status) { if (status)
rt2x00lib_remove_hw(rt2x00dev);
return status; return status;
}
set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags); set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags);
......
...@@ -2369,6 +2369,8 @@ static struct usb_device_id rt73usb_device_table[] = { ...@@ -2369,6 +2369,8 @@ static struct usb_device_id rt73usb_device_table[] = {
/* Buffalo */ /* Buffalo */
{ USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) },
/* CNet */ /* CNet */
{ USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) },
......
...@@ -258,7 +258,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) ...@@ -258,7 +258,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
(chan->max_power - local->power_constr_level) : (chan->max_power - local->power_constr_level) :
chan->max_power; chan->max_power;
if (local->user_power_level) if (local->user_power_level >= 0)
power = min(power, local->user_power_level); power = min(power, local->user_power_level);
if (local->hw.conf.power_level != power) { if (local->hw.conf.power_level != power) {
......
...@@ -441,6 +441,9 @@ static bool ieee80211_check_tim(struct ieee802_11_elems *elems, u16 aid) ...@@ -441,6 +441,9 @@ static bool ieee80211_check_tim(struct ieee802_11_elems *elems, u16 aid)
u8 index, indexn1, indexn2; u8 index, indexn1, indexn2;
struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim; struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim;
if (unlikely(!tim || elems->tim_len < 4))
return false;
aid &= 0x3fff; aid &= 0x3fff;
index = aid / 8; index = aid / 8;
mask = 1 << (aid & 7); mask = 1 << (aid & 7);
...@@ -945,9 +948,13 @@ void ieee80211_beacon_loss_work(struct work_struct *work) ...@@ -945,9 +948,13 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
u.mgd.beacon_loss_work); u.mgd.beacon_loss_work);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM " #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
"- sending probe request\n", sdata->dev->name, if (net_ratelimit()) {
sdata->u.mgd.bssid); printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
"- sending probe request\n", sdata->dev->name,
sdata->u.mgd.bssid);
}
#endif
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
...@@ -1007,9 +1014,13 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) ...@@ -1007,9 +1014,13 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
(local->hw.conf.flags & IEEE80211_CONF_PS)) && (local->hw.conf.flags & IEEE80211_CONF_PS)) &&
time_after(jiffies, time_after(jiffies,
ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) { ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
printk(KERN_DEBUG "%s: beacon loss from AP %pM " #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
"- sending probe request\n", if (net_ratelimit()) {
sdata->dev->name, ifmgd->bssid); printk(KERN_DEBUG "%s: beacon loss from AP %pM "
"- sending probe request\n",
sdata->dev->name, ifmgd->bssid);
}
#endif
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
ifmgd->ssid_len, NULL, 0); ifmgd->ssid_len, NULL, 0);
...@@ -2105,12 +2116,13 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) ...@@ -2105,12 +2116,13 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
struct ieee80211_local *local = struct ieee80211_local *local =
container_of(work, struct ieee80211_local, container_of(work, struct ieee80211_local,
dynamic_ps_enable_work); dynamic_ps_enable_work);
/* XXX: using scan_sdata is completely broken! */
struct ieee80211_sub_if_data *sdata = local->scan_sdata; struct ieee80211_sub_if_data *sdata = local->scan_sdata;
if (local->hw.conf.flags & IEEE80211_CONF_PS) if (local->hw.conf.flags & IEEE80211_CONF_PS)
return; return;
if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK && sdata)
ieee80211_send_nullfunc(local, sdata, 1); ieee80211_send_nullfunc(local, sdata, 1);
local->hw.conf.flags |= IEEE80211_CONF_PS; local->hw.conf.flags |= IEEE80211_CONF_PS;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
struct tid_ampdu_rx *tid_agg_rx, struct tid_ampdu_rx *tid_agg_rx,
struct sk_buff *skb, struct sk_buff *skb,
struct ieee80211_rx_status *status,
u16 mpdu_seq_num, u16 mpdu_seq_num,
int bar_req); int bar_req);
/* /*
...@@ -1688,7 +1689,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) ...@@ -1688,7 +1689,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
/* manage reordering buffer according to requested */ /* manage reordering buffer according to requested */
/* sequence number */ /* sequence number */
rcu_read_lock(); rcu_read_lock();
ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, NULL,
start_seq_num, 1); start_seq_num, 1);
rcu_read_unlock(); rcu_read_unlock();
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
...@@ -2293,6 +2294,7 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) ...@@ -2293,6 +2294,7 @@ static inline u16 seq_sub(u16 sq1, u16 sq2)
static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
struct tid_ampdu_rx *tid_agg_rx, struct tid_ampdu_rx *tid_agg_rx,
struct sk_buff *skb, struct sk_buff *skb,
struct ieee80211_rx_status *rxstatus,
u16 mpdu_seq_num, u16 mpdu_seq_num,
int bar_req) int bar_req)
{ {
...@@ -2374,6 +2376,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, ...@@ -2374,6 +2376,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
/* put the frame in the reordering buffer */ /* put the frame in the reordering buffer */
tid_agg_rx->reorder_buf[index] = skb; tid_agg_rx->reorder_buf[index] = skb;
memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus,
sizeof(*rxstatus));
tid_agg_rx->stored_mpdu_num++; tid_agg_rx->stored_mpdu_num++;
/* release the buffer until next missing frame */ /* release the buffer until next missing frame */
index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn)
...@@ -2399,7 +2403,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, ...@@ -2399,7 +2403,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
} }
static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
struct sk_buff *skb) struct sk_buff *skb,
struct ieee80211_rx_status *status)
{ {
struct ieee80211_hw *hw = &local->hw; struct ieee80211_hw *hw = &local->hw;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
...@@ -2448,7 +2453,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, ...@@ -2448,7 +2453,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
/* according to mpdu sequence number deal with reordering buffer */ /* according to mpdu sequence number deal with reordering buffer */
mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, status,
mpdu_seq_num, 0); mpdu_seq_num, 0);
end_reorder: end_reorder:
return ret; return ret;
...@@ -2512,7 +2517,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -2512,7 +2517,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
return; return;
} }
if (!ieee80211_rx_reorder_ampdu(local, skb)) if (!ieee80211_rx_reorder_ampdu(local, skb, status))
__ieee80211_rx_handle_packet(hw, skb, status, rate); __ieee80211_rx_handle_packet(hw, skb, status, rate);
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -417,6 +417,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, ...@@ -417,6 +417,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
{ {
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_channel* chan = local->hw.conf.channel; struct ieee80211_channel* chan = local->hw.conf.channel;
bool reconf = false;
u32 reconf_flags = 0; u32 reconf_flags = 0;
int new_power_level; int new_power_level;
...@@ -427,14 +428,38 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, ...@@ -427,14 +428,38 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
if (!chan) if (!chan)
return -EINVAL; return -EINVAL;
if (data->txpower.fixed) /* only change when not disabling */
new_power_level = min(data->txpower.value, chan->max_power); if (!data->txpower.disabled) {
else /* Automatic power level setting */ if (data->txpower.fixed) {
new_power_level = chan->max_power; if (data->txpower.value < 0)
return -EINVAL;
new_power_level = data->txpower.value;
/*
* Debatable, but we cannot do a fixed power
* level above the regulatory constraint.
* Use "iwconfig wlan0 txpower 15dBm" instead.
*/
if (new_power_level > chan->max_power)
return -EINVAL;
} else {
/*
* Automatic power level setting, max being the value
* passed in from userland.
*/
if (data->txpower.value < 0)
new_power_level = -1;
else
new_power_level = data->txpower.value;
}
reconf = true;
local->user_power_level = new_power_level; /*
if (local->hw.conf.power_level != new_power_level) * ieee80211_hw_config() will limit to the channel's
reconf_flags |= IEEE80211_CONF_CHANGE_POWER; * max power and possibly power constraint from AP.
*/
local->user_power_level = new_power_level;
}
if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
local->hw.conf.radio_enabled = !(data->txpower.disabled); local->hw.conf.radio_enabled = !(data->txpower.disabled);
...@@ -442,7 +467,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, ...@@ -442,7 +467,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
ieee80211_led_radio(local, local->hw.conf.radio_enabled); ieee80211_led_radio(local, local->hw.conf.radio_enabled);
} }
if (reconf_flags) if (reconf || reconf_flags)
ieee80211_hw_config(local, reconf_flags); ieee80211_hw_config(local, reconf_flags);
return 0; return 0;
...@@ -530,7 +555,7 @@ static int ieee80211_ioctl_giwfrag(struct net_device *dev, ...@@ -530,7 +555,7 @@ static int ieee80211_ioctl_giwfrag(struct net_device *dev,
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
frag->value = local->fragmentation_threshold; frag->value = local->fragmentation_threshold;
frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD); frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD);
frag->fixed = 1; frag->fixed = 1;
return 0; return 0;
......
...@@ -90,7 +90,7 @@ struct cfg80211_internal_bss { ...@@ -90,7 +90,7 @@ struct cfg80211_internal_bss {
struct rb_node rbn; struct rb_node rbn;
unsigned long ts; unsigned long ts;
struct kref ref; struct kref ref;
bool hold; bool hold, ies_allocated;
/* must be last because of priv member */ /* must be last because of priv member */
struct cfg80211_bss pub; struct cfg80211_bss pub;
......
...@@ -2095,11 +2095,12 @@ int set_regdom(const struct ieee80211_regdomain *rd) ...@@ -2095,11 +2095,12 @@ int set_regdom(const struct ieee80211_regdomain *rd)
/* Caller must hold cfg80211_mutex */ /* Caller must hold cfg80211_mutex */
void reg_device_remove(struct wiphy *wiphy) void reg_device_remove(struct wiphy *wiphy)
{ {
struct wiphy *request_wiphy; struct wiphy *request_wiphy = NULL;
assert_cfg80211_lock(); assert_cfg80211_lock();
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); if (last_request)
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
kfree(wiphy->regd); kfree(wiphy->regd);
if (!last_request || !request_wiphy) if (!last_request || !request_wiphy)
......
...@@ -58,6 +58,10 @@ static void bss_release(struct kref *ref) ...@@ -58,6 +58,10 @@ static void bss_release(struct kref *ref)
bss = container_of(ref, struct cfg80211_internal_bss, ref); bss = container_of(ref, struct cfg80211_internal_bss, ref);
if (bss->pub.free_priv) if (bss->pub.free_priv)
bss->pub.free_priv(&bss->pub); bss->pub.free_priv(&bss->pub);
if (bss->ies_allocated)
kfree(bss->pub.information_elements);
kfree(bss); kfree(bss);
} }
...@@ -360,19 +364,41 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, ...@@ -360,19 +364,41 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
found = rb_find_bss(dev, res); found = rb_find_bss(dev, res);
if (found && overwrite) { if (found) {
list_replace(&found->list, &res->list);
rb_replace_node(&found->rbn, &res->rbn,
&dev->bss_tree);
kref_put(&found->ref, bss_release);
found = res;
} else if (found) {
kref_get(&found->ref); kref_get(&found->ref);
found->pub.beacon_interval = res->pub.beacon_interval; found->pub.beacon_interval = res->pub.beacon_interval;
found->pub.tsf = res->pub.tsf; found->pub.tsf = res->pub.tsf;
found->pub.signal = res->pub.signal; found->pub.signal = res->pub.signal;
found->pub.capability = res->pub.capability; found->pub.capability = res->pub.capability;
found->ts = res->ts; found->ts = res->ts;
/* overwrite IEs */
if (overwrite) {
size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
size_t ielen = res->pub.len_information_elements;
if (ksize(found) >= used + ielen) {
memcpy(found->pub.information_elements,
res->pub.information_elements, ielen);
found->pub.len_information_elements = ielen;
} else {
u8 *ies = found->pub.information_elements;
if (found->ies_allocated) {
if (ksize(ies) < ielen)
ies = krealloc(ies, ielen,
GFP_ATOMIC);
} else
ies = kmalloc(ielen, GFP_ATOMIC);
if (ies) {
memcpy(ies, res->pub.information_elements, ielen);
found->ies_allocated = true;
found->pub.information_elements = ies;
}
}
}
kref_put(&res->ref, bss_release); kref_put(&res->ref, bss_release);
} else { } else {
/* this "consumes" the reference */ /* this "consumes" the reference */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment