From patchwork Sat May 31 18:54:14 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea Merello X-Patchwork-Id: 4276471 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7F512BEEA7 for ; Sat, 31 May 2014 18:54:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 85B6320253 for ; Sat, 31 May 2014 18:54:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 483E020225 for ; Sat, 31 May 2014 18:54:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751578AbaEaSyg (ORCPT ); Sat, 31 May 2014 14:54:36 -0400 Received: from mail-wi0-f179.google.com ([209.85.212.179]:43031 "EHLO mail-wi0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751206AbaEaSyf (ORCPT ); Sat, 31 May 2014 14:54:35 -0400 Received: by mail-wi0-f179.google.com with SMTP id bs8so2669873wib.0 for ; Sat, 31 May 2014 11:54:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:reply-to:in-reply-to:references:from:date:message-id :subject:to:cc:content-type; bh=LryCkwzRR03nVXkR14HxrAMSOacVlWBAwm22K/TbmXw=; b=0FhbVznLbyFWh6HFX5bTm/xS2qVB4V7oOfpR+Gfh2niVcTMAb2XFwHmTkY/4no901m 3DGzQUQdIQOEylKVwHT+KEVXe1BBN8tSISPeA4QtOTU06GNa61WRfzuf85Juo3mzUA+z 9tfsvQGZcER5b6ZkurOpw06SlqlBz/hk7GjzWA871CEbgYx5XDfRNVPFpLouOaYqhdel 0su2q7G0ctUcCTBWTpavFVJDU7T/hSmDf3WK2QXIieCSQCRSmQ3C5Z8kdYbwAiqi/6R2 YKLM7aw+BTGLWLwZYeLw1xxRrVo7lWCoco0z8UBdsS/O2X1SJ1DhXrAkz+KVbQZgIg7F +Rjg== X-Received: by 10.194.87.200 with SMTP id ba8mr35111507wjb.28.1401562474237; Sat, 31 May 2014 11:54:34 -0700 (PDT) MIME-Version: 1.0 Received: by 10.216.244.134 with HTTP; Sat, 31 May 2014 11:54:14 -0700 (PDT) Reply-To: andrea.merello@gmail.com In-Reply-To: <1401285737.8146.21.camel@jlt4.sipsolutions.net> References: <1400509775.4273.8.camel@jlt4.sipsolutions.net> <1400510950.4273.9.camel@jlt4.sipsolutions.net> <1400515344.4273.19.camel@jlt4.sipsolutions.net> <1401285737.8146.21.camel@jlt4.sipsolutions.net> From: Andrea Merello Date: Sat, 31 May 2014 20:54:14 +0200 Message-ID: Subject: Re: [RFC] mac80211: at76x50x_usb driver broken by commit 3afc216.. and RX path involved in scan To: Johannes Berg Cc: emmanuel.grumbach@intel.com, Linux Wireless List , joerg.albert@gmx.de, Alex Stewart , n0_5p4m_p13453@hotmail.com, Pavel Roskin , agx@sigxcpu.org, Kalle Valo , sesmo@gmx.net, John Linville Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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? I did a simpler implementation that only search for channel information.. So.. What about the following patch? :) Andrea drivers/net/wireless/at76c50x-usb.c | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 10fd12e..06a64f4 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1502,6 +1502,61 @@ static void at76_work_submit_rx(struct work_struct *work) mutex_unlock(&priv->mtx); } +/* 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; + } + +exit: + return ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ); +} + static void at76_rx_tasklet(unsigned long param) { struct urb *urb = (struct urb *)param; @@ -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); at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d", priv->rx_skb->len, priv->rx_skb->data_len);