Search Linux Wireless

Re: [RFC] mac80211: at76x50x_usb driver broken by commit 3afc216.. and RX path involved in scan

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Andrea,

On Sat, 2014-05-31 at 20:54 +0200, Andrea Merello wrote:
> Hello,
> I found some useful helper function in mac80211, and I used some of
> them, but unfortunately I finally parsed information element in
> beacon/probe-response by myself:
> I found the utility ieee802_11_parse_elems(), but it seems that it
> relies on structures that are declared in some .h file located locally
> to mac80211.. So I suppose it is not intended for use outside
> mac80211, is it?

Yeah, and it would do much more than what you want. You could use
cfg80211_find_ie() though to simplify the code.

> +/* This is a workaround to make scan working:
> + * currently mac80211 does not process frames with no frequency
> + * information.
> + * However during scan the HW performs a sweep by itself, and we
> + * are unable to know where the radio is actually tuned.
> + * This function tries to do its best to guess this information..
> + * If the current frame is a beacon or a probe response, the channel
> + * information is extracted from it.
> + * For other frames, or if it happen that for whatever reason we fail
> + * to parse beacons and probe responses, this function returns
> + * the priv->channel information, that should be valid at least
> + * when we are NOT scanning.
> + */
> +static int at76_parse_freq(struct at76_priv *priv)
> +{
> +       size_t el_off;
> +       u8 id;
> +       u8 *el;
> +       int el_len;
> +       int channel = priv->channel;
> +       int len = priv->rx_skb->len;
> +       struct ieee80211_hdr *hdr = (void *)priv->rx_skb->data;
> +
> +       if (len < 24)
> +               goto exit;
> +
> +       if (ieee80211_is_probe_resp(hdr->frame_control)) {
> +               el_off = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
> +               el = ((struct ieee80211_mgmt *)hdr)->u.probe_resp.variable;
> +       } else if (ieee80211_is_beacon(hdr->frame_control)) {
> +               el_off = offsetof(struct ieee80211_mgmt, u.beacon.variable);
> +               el = ((struct ieee80211_mgmt *)hdr)->u.beacon.variable;
> +       } else
> +               goto exit;
> +
> +       len -= el_off;
> +
> +       while (len >= 2) {
> +               id = *el++;
> +               el_len = *el++;
> +               len -= 2;
> +
> +               if (id == WLAN_EID_DS_PARAMS) {
> +                       if ((el_len > 0) && (len >= el_len))
> +                               channel = *el;
> +                       break;
> +               }
> +               len -= el_len;
> +               el += el_len;
> +       }

So the loop can be simplified to

	el = cfg80211_find_ie(WLAN_EID_DS_PARAMS, el, el_len);
	if (el && el[1] > 0)
		channel = el[2];

> @@ -1542,6 +1597,8 @@ static void at76_rx_tasklet(unsigned long param)
>         rx_status.signal = buf->rssi;
>         rx_status.flag |= RX_FLAG_DECRYPTED;
>         rx_status.flag |= RX_FLAG_IV_STRIPPED;
> +       rx_status.band = IEEE80211_BAND_2GHZ;
> +       rx_status.freq = at76_parse_freq(priv);

You might also invoke this only when you know you're scanning, to avoid
the overhead otherwise, but with this driver it probably doesn't matter
much.

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux