diff options
-rw-r--r-- | at76_usb.c | 577 |
1 files changed, 292 insertions, 285 deletions
@@ -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) { |