aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--at76_usb.c577
1 files changed, 292 insertions, 285 deletions
diff --git a/at76_usb.c b/at76_usb.c
index c0307e6..bb8b714 100644
--- a/at76_usb.c
+++ b/at76_usb.c
@@ -349,22 +349,21 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *dfu_buffer,
at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_SYNC");
ret = at76_dfu_get_status(udev, &dfu_stat_buf);
+ if (ret < 0)
+ break;
- if (ret >= 0) {
- dfu_state = dfu_stat_buf.state;
- dfu_timeout = at76_get_timeout(&dfu_stat_buf);
- need_dfu_state = 0;
+ dfu_state = dfu_stat_buf.state;
+ dfu_timeout = at76_get_timeout(&dfu_stat_buf);
+ need_dfu_state = 0;
- /* override the timeout from the status response,
- needed for AT76C505A */
- if (manifest_sync_timeout > 0)
- dfu_timeout = manifest_sync_timeout;
+ /* override the timeout from the status response,
+ needed for AT76C505A */
+ if (manifest_sync_timeout > 0)
+ dfu_timeout = manifest_sync_timeout;
- at76_dbg(DBG_DFU,
- "DFU: Waiting for manifest phase");
- schedule_timeout_interruptible(msecs_to_jiffies
- (dfu_timeout));
- }
+ at76_dbg(DBG_DFU, "DFU: Waiting for manifest phase");
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (dfu_timeout));
break;
case STATE_DFU_MANIFEST:
@@ -850,16 +849,17 @@ static int at76_set_radio(struct at76_priv *priv, int on_off)
{
int ret;
- if (priv->radio_on != on_off) {
- ret = at76_set_card_command(priv->udev, CMD_RADIO, NULL, 0);
- if (ret < 0) {
- err("%s: at76_set_card_command(CMD_RADIO) failed: %d",
- priv->netdev->name, ret);
- } else
- ret = 1;
- priv->radio_on = on_off;
+ if (priv->radio_on == on_off)
+ return 0;
+
+ ret = at76_set_card_command(priv->udev, CMD_RADIO, NULL, 0);
+ if (ret < 0) {
+ err("%s: at76_set_card_command(CMD_RADIO) failed: %d",
+ priv->netdev->name, ret);
} else
- ret = 0;
+ ret = 1;
+
+ priv->radio_on = on_off;
return ret;
}
@@ -1589,9 +1589,9 @@ static void at76_write_bulk_callback(struct urb *urb)
at76_dbg(DBG_URB,
"%s - nonzero write bulk status received: %d",
__func__, urb->status);
+ stats->tx_errors++;
} else
return; /* urb has been unlinked */
- stats->tx_errors++;
} else
stats->tx_packets++;
@@ -1600,24 +1600,25 @@ static void at76_write_bulk_callback(struct urb *urb)
priv->next_mgmt_bulk = NULL;
spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
- if (mgmt_buf) {
- /* we don't copy the padding bytes, but add them
- to the length */
- memcpy(priv->bulk_out_buffer, mgmt_buf,
- le16_to_cpu(mgmt_buf->wlength) + AT76_TX_HDRLEN);
- usb_fill_bulk_urb(priv->write_urb, priv->udev,
- priv->tx_bulk_pipe, priv->bulk_out_buffer,
- le16_to_cpu(mgmt_buf->wlength) +
- mgmt_buf->padding + AT76_TX_HDRLEN,
- at76_write_bulk_callback, priv);
- ret = usb_submit_urb(priv->write_urb, GFP_ATOMIC);
- if (ret) {
- err("%s: %s error in tx submit urb: %d",
- priv->netdev->name, __func__, ret);
- }
- kfree(mgmt_buf);
- } else
+ if (!mgmt_buf) {
netif_wake_queue(priv->netdev);
+ return;
+ }
+
+ /* we don't copy the padding bytes, but add them
+ to the length */
+ memcpy(priv->bulk_out_buffer, mgmt_buf,
+ le16_to_cpu(mgmt_buf->wlength) + AT76_TX_HDRLEN);
+ usb_fill_bulk_urb(priv->write_urb, priv->udev, priv->tx_bulk_pipe,
+ priv->bulk_out_buffer,
+ le16_to_cpu(mgmt_buf->wlength) + mgmt_buf->padding +
+ AT76_TX_HDRLEN, at76_write_bulk_callback, priv);
+ ret = usb_submit_urb(priv->write_urb, GFP_ATOMIC);
+ if (ret) {
+ err("%s: %s error in tx submit urb: %d",
+ priv->netdev->name, __func__, ret);
+ }
+ kfree(mgmt_buf);
}
/* Send a management frame on bulk-out.
@@ -1653,38 +1654,37 @@ static int at76_send_mgmt_bulk(struct at76_priv *priv,
kfree(priv->next_mgmt_bulk);
}
- if (txbuf) {
+ if (!txbuf)
+ return ret;
- txbuf->tx_rate = 0;
- txbuf->padding = at76_calc_padding(le16_to_cpu(txbuf->wlength));
+ txbuf->tx_rate = 0;
+ txbuf->padding = at76_calc_padding(le16_to_cpu(txbuf->wlength));
- if (priv->next_mgmt_bulk) {
- err("%s: %s URB status %d, but mgmt is pending",
- priv->netdev->name, __func__, urb_status);
- }
+ if (priv->next_mgmt_bulk) {
+ err("%s: %s URB status %d, but mgmt is pending",
+ priv->netdev->name, __func__, urb_status);
+ }
- at76_dbg(DBG_TX_MGMT,
- "%s: tx mgmt: wlen %d tx_rate %d pad %d %s",
- priv->netdev->name, le16_to_cpu(txbuf->wlength),
- txbuf->tx_rate, txbuf->padding,
- hex2str(txbuf->packet, le16_to_cpu(txbuf->wlength)));
-
- /* txbuf was not consumed above -> send mgmt msg immediately */
- memcpy(priv->bulk_out_buffer, txbuf,
- le16_to_cpu(txbuf->wlength) + AT76_TX_HDRLEN);
- usb_fill_bulk_urb(priv->write_urb, priv->udev,
- priv->tx_bulk_pipe, priv->bulk_out_buffer,
- le16_to_cpu(txbuf->wlength) + txbuf->padding +
- AT76_TX_HDRLEN, at76_write_bulk_callback,
- priv);
- ret = usb_submit_urb(priv->write_urb, GFP_ATOMIC);
- if (ret) {
- err("%s: %s error in tx submit urb: %d",
- priv->netdev->name, __func__, ret);
- }
- kfree(txbuf);
+ at76_dbg(DBG_TX_MGMT,
+ "%s: tx mgmt: wlen %d tx_rate %d pad %d %s",
+ priv->netdev->name, le16_to_cpu(txbuf->wlength),
+ txbuf->tx_rate, txbuf->padding,
+ hex2str(txbuf->packet, le16_to_cpu(txbuf->wlength)));
+
+ /* txbuf was not consumed above -> send mgmt msg immediately */
+ memcpy(priv->bulk_out_buffer, txbuf,
+ le16_to_cpu(txbuf->wlength) + AT76_TX_HDRLEN);
+ usb_fill_bulk_urb(priv->write_urb, priv->udev, priv->tx_bulk_pipe,
+ priv->bulk_out_buffer,
+ le16_to_cpu(txbuf->wlength) + txbuf->padding +
+ AT76_TX_HDRLEN, at76_write_bulk_callback, priv);
+ ret = usb_submit_urb(priv->write_urb, GFP_ATOMIC);
+ if (ret) {
+ err("%s: %s error in tx submit urb: %d",
+ priv->netdev->name, __func__, ret);
}
- /* if (txbuf) */
+ kfree(txbuf);
+
return ret;
}
@@ -4271,65 +4271,63 @@ static void at76_work_join(struct work_struct *work)
priv->curr_bss = at76_match_bss(priv, priv->curr_bss);
spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
- if (priv->curr_bss != NULL) {
- ret = at76_join_bss(priv, priv->curr_bss);
- if (ret < 0) {
- err("%s: join_bss failed with %d",
- priv->netdev->name, ret);
+ if (priv->curr_bss == NULL) {
+ /* here we haven't found a matching (i)bss ... */
+ if (priv->iw_mode == IW_MODE_ADHOC) {
+ priv->istate = STARTIBSS;
+ at76_start_ibss(priv);
goto end_join;
}
+ /* haven't found a matching BSS in infra mode - try again */
+ priv->istate = SCANNING;
+ schedule_work(&priv->work_scan);
+ goto end_join;
+ }
- ret = at76_wait_completion(priv, CMD_JOIN);
- if (ret != CMD_STATUS_COMPLETE) {
- if (ret != CMD_STATUS_TIME_OUT)
- err("%s join_bss completed with %d",
- priv->netdev->name, ret);
- else
- printk(KERN_INFO
- "%s: join_bss ssid %s timed out\n",
- priv->netdev->name,
- mac2str(priv->curr_bss->bssid));
+ ret = at76_join_bss(priv, priv->curr_bss);
+ if (ret < 0) {
+ err("%s: join_bss failed with %d", priv->netdev->name, ret);
+ goto end_join;
+ }
- /* retry next BSS immediately */
- schedule_work(&priv->work_join);
- goto end_join;
- }
+ ret = at76_wait_completion(priv, CMD_JOIN);
+ if (ret != CMD_STATUS_COMPLETE) {
+ if (ret != CMD_STATUS_TIME_OUT)
+ err("%s join_bss completed with %d",
+ priv->netdev->name, ret);
+ else
+ printk(KERN_INFO
+ "%s: join_bss ssid %s timed out\n",
+ priv->netdev->name,
+ mac2str(priv->curr_bss->bssid));
- /* here we have joined the (I)BSS */
- if (priv->iw_mode == IW_MODE_ADHOC) {
- struct bss_info *bptr = priv->curr_bss;
- priv->istate = CONNECTED;
- /* get ESSID, BSSID and channel for priv->curr_bss */
- priv->essid_size = bptr->ssid_len;
- memcpy(priv->essid, bptr->ssid, bptr->ssid_len);
- memcpy(priv->bssid, bptr->bssid, ETH_ALEN);
- priv->channel = bptr->channel;
- at76_iwevent_bss_connect(priv->netdev, bptr->bssid);
- netif_carrier_on(priv->netdev);
- netif_start_queue(priv->netdev);
- /* just to be sure */
- cancel_delayed_work(&priv->dwork_mgmt);
- } else {
- /* send auth req */
- priv->istate = AUTHENTICATING;
- at76_auth_req(priv, priv->curr_bss, 1, NULL);
- at76_dbg(DBG_MGMT_TIMER,
- "%s:%d: starting mgmt_timer + HZ",
- __func__, __LINE__);
- schedule_delayed_work(&priv->dwork_mgmt, HZ);
- }
+ /* retry next BSS immediately */
+ schedule_work(&priv->work_join);
goto end_join;
}
- /* here we haven't found a matching (i)bss ... */
+ /* here we have joined the (I)BSS */
if (priv->iw_mode == IW_MODE_ADHOC) {
- priv->istate = STARTIBSS;
- at76_start_ibss(priv);
- goto end_join;
+ struct bss_info *bptr = priv->curr_bss;
+ priv->istate = CONNECTED;
+ /* get ESSID, BSSID and channel for priv->curr_bss */
+ priv->essid_size = bptr->ssid_len;
+ memcpy(priv->essid, bptr->ssid, bptr->ssid_len);
+ memcpy(priv->bssid, bptr->bssid, ETH_ALEN);
+ priv->channel = bptr->channel;
+ at76_iwevent_bss_connect(priv->netdev, bptr->bssid);
+ netif_carrier_on(priv->netdev);
+ netif_start_queue(priv->netdev);
+ /* just to be sure */
+ cancel_delayed_work(&priv->dwork_mgmt);
+ } else {
+ /* send auth req */
+ priv->istate = AUTHENTICATING;
+ at76_auth_req(priv, priv->curr_bss, 1, NULL);
+ at76_dbg(DBG_MGMT_TIMER,
+ "%s:%d: starting mgmt_timer + HZ", __func__, __LINE__);
+ schedule_delayed_work(&priv->dwork_mgmt, HZ);
}
- /* haven't found a matching BSS in infra mode - try again */
- priv->istate = SCANNING;
- schedule_work(&priv->work_scan);
end_join:
mutex_unlock(&priv->mtx);
@@ -4706,29 +4704,31 @@ static void at76_rx_mgmt_assoc(struct at76_priv *priv,
"assoc_id 0x%04x rates %s", priv->netdev->name,
mac2str(mgmt->addr3), capa, status, assoc_id,
hex2str(resp->info_element->data, resp->info_element->len));
- if (priv->istate == ASSOCIATING) {
- at76_assert(priv->curr_bss != NULL);
- if (priv->curr_bss == NULL)
- return;
- if (status == WLAN_STATUS_SUCCESS) {
- struct bss_info *ptr = priv->curr_bss;
- ptr->assoc_id = assoc_id & 0x3fff;
- /* update iwconfig params */
- memcpy(priv->bssid, ptr->bssid, ETH_ALEN);
- memcpy(priv->essid, ptr->ssid, ptr->ssid_len);
- priv->essid_size = ptr->ssid_len;
- priv->channel = ptr->channel;
- schedule_work(&priv->work_assoc_done);
- } else {
- priv->istate = JOINING;
- schedule_work(&priv->work_join);
- }
- cancel_delayed_work(&priv->dwork_mgmt);
- } else {
+ if (priv->istate != ASSOCIATING) {
printk(KERN_INFO "%s: AssocResp in state %d ignored\n",
priv->netdev->name, priv->istate);
+ return;
}
+
+ at76_assert(priv->curr_bss != NULL);
+ if (priv->curr_bss == NULL)
+ return;
+
+ if (status == WLAN_STATUS_SUCCESS) {
+ struct bss_info *ptr = priv->curr_bss;
+ ptr->assoc_id = assoc_id & 0x3fff;
+ /* update iwconfig params */
+ memcpy(priv->bssid, ptr->bssid, ETH_ALEN);
+ memcpy(priv->essid, ptr->ssid, ptr->ssid_len);
+ priv->essid_size = ptr->ssid_len;
+ priv->channel = ptr->channel;
+ schedule_work(&priv->work_assoc_done);
+ } else {
+ priv->istate = JOINING;
+ schedule_work(&priv->work_join);
+ }
+ cancel_delayed_work(&priv->dwork_mgmt);
}
static void at76_rx_mgmt_reassoc(struct at76_priv *priv,
@@ -4747,39 +4747,41 @@ static void at76_rx_mgmt_reassoc(struct at76_priv *priv,
"assoc_id 0x%04x rates %s", priv->netdev->name,
mac2str(mgmt->addr3), capa, status, assoc_id,
hex2str(resp->info_element->data, resp->info_element->len));
- if (priv->istate == REASSOCIATING) {
- at76_assert(priv->new_bss != NULL);
- if (priv->new_bss == NULL)
- return;
- if (status == WLAN_STATUS_SUCCESS) {
- struct bss_info *bptr = priv->new_bss;
- bptr->assoc_id = assoc_id;
- priv->istate = CONNECTED;
-
- at76_iwevent_bss_connect(priv->netdev, bptr->bssid);
-
- spin_lock_irqsave(&priv->bss_list_spinlock, flags);
- priv->curr_bss = priv->new_bss;
- priv->new_bss = NULL;
- spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
-
- /* get ESSID, BSSID and channel for priv->curr_bss */
- priv->essid_size = bptr->ssid_len;
- memcpy(priv->essid, bptr->ssid, bptr->ssid_len);
- memcpy(priv->bssid, bptr->bssid, ETH_ALEN);
- priv->channel = bptr->channel;
- at76_dbg(DBG_PROGRESS, "%s: reassociated to BSSID %s",
- priv->netdev->name, mac2str(priv->bssid));
- schedule_work(&priv->work_assoc_done);
- } else {
- cancel_delayed_work(&priv->dwork_mgmt);
- priv->istate = JOINING;
- schedule_work(&priv->work_join);
- }
- } else {
+ if (priv->istate != REASSOCIATING) {
printk(KERN_INFO "%s: ReAssocResp in state %d ignored\n",
priv->netdev->name, priv->istate);
+ return;
+ }
+
+ at76_assert(priv->new_bss != NULL);
+ if (priv->new_bss == NULL)
+ return;
+
+ if (status == WLAN_STATUS_SUCCESS) {
+ struct bss_info *bptr = priv->new_bss;
+ bptr->assoc_id = assoc_id;
+ priv->istate = CONNECTED;
+
+ at76_iwevent_bss_connect(priv->netdev, bptr->bssid);
+
+ spin_lock_irqsave(&priv->bss_list_spinlock, flags);
+ priv->curr_bss = priv->new_bss;
+ priv->new_bss = NULL;
+ spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
+
+ /* get ESSID, BSSID and channel for priv->curr_bss */
+ priv->essid_size = bptr->ssid_len;
+ memcpy(priv->essid, bptr->ssid, bptr->ssid_len);
+ memcpy(priv->bssid, bptr->bssid, ETH_ALEN);
+ priv->channel = bptr->channel;
+ at76_dbg(DBG_PROGRESS, "%s: reassociated to BSSID %s",
+ priv->netdev->name, mac2str(priv->bssid));
+ schedule_work(&priv->work_assoc_done);
+ } else {
+ cancel_delayed_work(&priv->dwork_mgmt);
+ priv->istate = JOINING;
+ schedule_work(&priv->work_join);
}
}
@@ -4805,32 +4807,35 @@ static void at76_rx_mgmt_disassoc(struct at76_priv *priv,
if (priv->new_bss == NULL)
return;
}
- if (!compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid) &&
- (!compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1) ||
- is_broadcast_ether_addr(mgmt->addr1))) {
- /* this is a DisAssoc from the BSS we are connected or
- trying to connect to, directed to us or broadcasted */
- /* jal: TODO: can the DisAssoc also come from the BSS
- we've sent a ReAssocReq to (i.e. from priv->new_bss) ? */
- if (priv->istate == DISASSOCIATING ||
- priv->istate == ASSOCIATING ||
- priv->istate == REASSOCIATING ||
- priv->istate == CONNECTED || priv->istate == JOINING) {
- if (priv->istate == CONNECTED) {
- netif_carrier_off(priv->netdev);
- netif_stop_queue(priv->netdev);
- at76_iwevent_bss_disconnect(priv->netdev);
- }
- cancel_delayed_work(&priv->dwork_mgmt);
- priv->istate = JOINING;
- schedule_work(&priv->work_join);
- } else {
- /* ignore DisAssoc in states AUTH, ASSOC */
- printk(KERN_INFO "%s: DisAssoc in state %d ignored\n",
- priv->netdev->name, priv->istate);
- }
+
+ /* Not our BSSID, ignore */
+ if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid))
+ return;
+
+ /* Not for our STA and not broadcast, ignore */
+ if (compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)
+ && !is_broadcast_ether_addr(mgmt->addr1))
+ return;
+
+ /* jal: TODO: can the DisAssoc also come from the BSS
+ we've sent a ReAssocReq to (i.e. from priv->new_bss) ? */
+
+ if (priv->istate != DISASSOCIATING && priv->istate != ASSOCIATING
+ && priv->istate != REASSOCIATING && priv->istate != CONNECTED
+ && priv->istate != JOINING) {
+ printk(KERN_INFO "%s: DisAssoc in state %d ignored\n",
+ priv->netdev->name, priv->istate);
+ return;
}
- /* ignore DisAssoc to other STA or from other BSSID */
+
+ if (priv->istate == CONNECTED) {
+ netif_carrier_off(priv->netdev);
+ netif_stop_queue(priv->netdev);
+ at76_iwevent_bss_disconnect(priv->netdev);
+ }
+ cancel_delayed_work(&priv->dwork_mgmt);
+ priv->istate = JOINING;
+ schedule_work(&priv->work_join);
}
static void at76_rx_mgmt_auth(struct at76_priv *priv,
@@ -4866,37 +4871,34 @@ static void at76_rx_mgmt_auth(struct at76_priv *priv,
if (priv->curr_bss == NULL)
return;
- if (!compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid) &&
- !compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)) {
- /* this is a AuthFrame from the BSS we are connected or
- trying to connect to, directed to us */
- if (status != WLAN_STATUS_SUCCESS) {
- cancel_delayed_work(&priv->dwork_mgmt);
- /* try to join next bss */
- priv->istate = JOINING;
- schedule_work(&priv->work_join);
- return;
- }
+ /* Not our BSSID or not for our STA, ignore */
+ if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid)
+ || compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1))
+ return;
- if (priv->auth_mode == WLAN_AUTH_OPEN || seq_nr == 4) {
- priv->retries = ASSOC_RETRIES;
- priv->istate = ASSOCIATING;
- at76_assoc_req(priv, priv->curr_bss);
- at76_dbg(DBG_MGMT_TIMER,
- "%s:%d: starting mgmt_timer + HZ",
- __func__, __LINE__);
- schedule_delayed_work(&priv->dwork_mgmt, HZ);
- return;
- }
+ if (status != WLAN_STATUS_SUCCESS) {
+ cancel_delayed_work(&priv->dwork_mgmt);
+ /* try to join next bss */
+ priv->istate = JOINING;
+ schedule_work(&priv->work_join);
+ return;
+ }
- at76_assert(seq_nr == 2);
- at76_auth_req(priv, priv->curr_bss, seq_nr + 1,
- resp->info_element);
- at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ",
- __func__, __LINE__);
+ if (priv->auth_mode == WLAN_AUTH_OPEN || seq_nr == 4) {
+ priv->retries = ASSOC_RETRIES;
+ priv->istate = ASSOCIATING;
+ at76_assoc_req(priv, priv->curr_bss);
+ at76_dbg(DBG_MGMT_TIMER,
+ "%s:%d: starting mgmt_timer + HZ", __func__, __LINE__);
schedule_delayed_work(&priv->dwork_mgmt, HZ);
+ return;
}
- /* else: ignore AuthFrames to other recipients */
+
+ at76_assert(seq_nr == 2);
+ at76_auth_req(priv, priv->curr_bss, seq_nr + 1, resp->info_element);
+ at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", __func__,
+ __LINE__);
+ schedule_delayed_work(&priv->dwork_mgmt, HZ);
}
static void at76_rx_mgmt_deauth(struct at76_priv *priv,
@@ -4910,32 +4912,34 @@ static void at76_rx_mgmt_deauth(struct at76_priv *priv,
"%s: rx DeAuth bssid %s reason 0x%04x destination %s",
priv->netdev->name, mac2str(mgmt->addr3),
le16_to_cpu(resp->reason), mac2str(mgmt->addr1));
- if (priv->istate == DISASSOCIATING ||
- priv->istate == AUTHENTICATING ||
- priv->istate == ASSOCIATING ||
- priv->istate == REASSOCIATING || priv->istate == CONNECTED) {
- at76_assert(priv->curr_bss != NULL);
- if (priv->curr_bss == NULL)
- return;
- if (!compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid) &&
- (!compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1) ||
- is_broadcast_ether_addr(mgmt->addr1))) {
- /* this is a DeAuth from the BSS we are connected or
- trying to connect to, directed to us or broadcasted */
- if (priv->istate == CONNECTED) {
- at76_iwevent_bss_disconnect(priv->netdev);
- }
- priv->istate = JOINING;
- schedule_work(&priv->work_join);
- cancel_delayed_work(&priv->dwork_mgmt);
- }
- /* ignore DeAuth to other STA or from other BSSID */
- } else {
- /* ignore DeAuth in states SCANNING */
+ if (priv->istate != DISASSOCIATING && priv->istate != AUTHENTICATING
+ && priv->istate != ASSOCIATING && priv->istate != REASSOCIATING
+ && priv->istate != CONNECTED) {
printk(KERN_INFO "%s: DeAuth in state %d ignored\n",
priv->netdev->name, priv->istate);
+ return;
}
+
+ at76_assert(priv->curr_bss != NULL);
+ if (priv->curr_bss == NULL)
+ return;
+
+ /* Not our BSSID, ignore */
+ if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid))
+ return;
+
+ /* Not for our STA and not broadcast, ignore */
+ if (compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)
+ && !is_broadcast_ether_addr(mgmt->addr1))
+ return;
+
+ if (priv->istate == CONNECTED)
+ at76_iwevent_bss_disconnect(priv->netdev);
+
+ priv->istate = JOINING;
+ schedule_work(&priv->work_join);
+ cancel_delayed_work(&priv->dwork_mgmt);
}
static void at76_rx_mgmt_beacon(struct at76_priv *priv,
@@ -5048,48 +5052,52 @@ static void at76_rx_mgmt_beacon(struct at76_priv *priv,
switch (tlv->id) {
case MFIE_TYPE_SSID:
+ if (have_ssid)
+ break;
+
len = min_t(int, IW_ESSID_MAX_SIZE, tlv->len);
- if (!have_ssid && ((new_entry) ||
- !at76_is_cloaked_ssid(tlv->data,
- len))) {
- /* we copy only if this is a new entry,
- or the incoming SSID is not a cloaked SSID. This
- will protect us from overwriting a real SSID read
- in a ProbeResponse with a cloaked one from a
- following beacon. */
-
- match->ssid_len = len;
- memcpy(match->ssid, tlv->data, len);
- match->ssid[len] = '\0'; /* terminate the
- string for
- printing */
- at76_dbg(DBG_RX_BEACON, "%s: SSID - %s",
- priv->netdev->name, match->ssid);
+
+ /* we copy only if this is a new entry,
+ or the incoming SSID is not a cloaked SSID. This
+ will protect us from overwriting a real SSID read
+ in a ProbeResponse with a cloaked one from a
+ following beacon. */
+ if (!new_entry && at76_is_cloaked_ssid(tlv->data, len)) {
+ have_ssid = 1;
+ break;
}
+
+ match->ssid_len = len;
+ memcpy(match->ssid, tlv->data, len);
+ match->ssid[len] = '\0'; /* terminate the
+ string for
+ printing */
+ at76_dbg(DBG_RX_BEACON, "%s: SSID - %s",
+ priv->netdev->name, match->ssid);
have_ssid = 1;
break;
case MFIE_TYPE_RATES:
- if (!have_rates) {
- match->rates_len =
- min_t(int, sizeof(match->rates), tlv->len);
- memcpy(match->rates, tlv->data,
- match->rates_len);
- have_rates = 1;
- at76_dbg(DBG_RX_BEACON,
- "%s: SUPPORTED RATES %s",
- priv->netdev->name,
- hex2str(tlv->data, tlv->len));
- }
+ if (have_rates)
+ break;
+
+ match->rates_len =
+ min_t(int, sizeof(match->rates), tlv->len);
+ memcpy(match->rates, tlv->data, match->rates_len);
+ have_rates = 1;
+ at76_dbg(DBG_RX_BEACON, "%s: SUPPORTED RATES %s",
+ priv->netdev->name,
+ hex2str(tlv->data, tlv->len));
break;
case MFIE_TYPE_DS_SET:
- if (!have_channel) {
- match->channel = tlv->data[0];
- have_channel = 1;
- at76_dbg(DBG_RX_BEACON, "%s: CHANNEL - %d",
- priv->netdev->name, match->channel);
- }
+ if (have_channel)
+ break;
+
+ match->channel = tlv->data[0];
+ have_channel = 1;
+ at76_dbg(DBG_RX_BEACON, "%s: CHANNEL - %d",
+ priv->netdev->name, match->channel);
break;
case MFIE_TYPE_CF_SET:
@@ -5435,21 +5443,20 @@ static struct sk_buff *at76_check_for_rx_frags(struct at76_priv *priv)
bptr = priv->rx_data;
optr = NULL;
for (i = 0; i < NR_RX_DATA_BUF; i++, bptr++) {
- if (bptr->skb != NULL) {
- if (!compare_ether_addr(i802_11_hdr->addr2,
- bptr->sender))
- break;
- else if (optr == NULL) {
- optr = bptr;
- oldest = bptr->last_rx;
- } else {
- if (bptr->last_rx < oldest)
- optr = bptr;
- }
- } else {
+ if (bptr->skb == NULL) {
optr = bptr;
oldest = 0UL;
+ continue;
}
+
+ if (!compare_ether_addr(i802_11_hdr->addr2, bptr->sender))
+ break;
+
+ if (optr == NULL) {
+ optr = bptr;
+ oldest = bptr->last_rx;
+ } else if (bptr->last_rx < oldest)
+ optr = bptr;
}
if (i < NR_RX_DATA_BUF) {