* Re: FUSB200 xhci issue
From: Oleksij Rempel @ 2013-08-12 7:58 UTC (permalink / raw)
To: Alan Stern
Cc: Christian Lamparter, Sarah Sharp, Seth Forshee, ath9k_htc_fw,
USB list, linux-wireless, Sujith Manoharan
In-Reply-To: <Pine.LNX.4.44L0.1308100755250.31571-100000@netrider.rowland.org>
Am 10.08.2013 13:57, schrieb Alan Stern:
> On Sat, 10 Aug 2013, Oleksij Rempel wrote:
>
>> usb reset do not affect behaviour of firmware. At least after i remove
>> all attempts to reboot FW from driver.
>> If adapter will got reset signal, FW will be notified about it. Then FW
>> will remove reset flag and will just continue to work. After usb reset,
>> lsusb show correct, update information - EP3 and EP4 was updated from
>> INT to BULK.
>>
>> I assume, no i need to add to the driver some kind of firmware check.
>> What is the proper way to do it?
>
> The simplest way is to put a new value for the device descriptor's
> bcdDevice value in the firmware. Then all you have to do is check that
> value.
Since adding fw check will need fw version update. I would like to do
quick fix for current kernel and firmware version.
I will revert EP3 and EP4 from bulk back to interrupt. But, before
sending patch to the list i would like to know, how to reproduce the bug
which was fixed by converting this endpoints from interrupt to bulk.
--
Regards,
Oleksij
--
Regards,
Oleksij
^ permalink raw reply
* [PATCH 2/2] NFC: pn533: Staticize local symbols
From: Jingoo Han @ 2013-08-12 6:40 UTC (permalink / raw)
To: 'Lauro Ramos Venancio'
Cc: 'Aloisio Almeida Jr', 'Samuel Ortiz',
linux-wireless, linux-nfc, 'Waldemar Rymarkiewicz',
Thierry Escande, 'Olivier Guiter', Jingoo Han
These local symbols are used only in this file.
Fix the following sparse warnings:
drivers/nfc/pn533.c:2576:5: warning: symbol 'pn533_dev_up' was not declared. Should it be static?
drivers/nfc/pn533.c:2581:5: warning: symbol 'pn533_dev_down' was not declared. Should it be static?
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/nfc/pn533.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index daf92ac..1746225 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -2573,12 +2573,12 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf)
return rc;
}
-int pn533_dev_up(struct nfc_dev *nfc_dev)
+static int pn533_dev_up(struct nfc_dev *nfc_dev)
{
return pn533_rf_field(nfc_dev, 1);
}
-int pn533_dev_down(struct nfc_dev *nfc_dev)
+static int pn533_dev_down(struct nfc_dev *nfc_dev)
{
return pn533_rf_field(nfc_dev, 0);
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/2] NFC: nfcsim: Staticize local symbols
From: Jingoo Han @ 2013-08-12 6:37 UTC (permalink / raw)
To: 'Lauro Ramos Venancio'
Cc: 'Aloisio Almeida Jr', Samuel Ortiz, linux-wireless,
linux-nfc, 'Thierry Escande', Jingoo Han
These local symbols are used only in this file.
Fix the following sparse warnings:
drivers/nfc/nfcsim.c:63:25: warning: symbol 'wq' was not declared. Should it be static?
drivers/nfc/nfcsim.c:484:12: warning: symbol 'nfcsim_init' was not declared. Should it be static?
drivers/nfc/nfcsim.c:525:13: warning: symbol 'nfcsim_exit' was not declared. Should it be static?
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/nfc/nfcsim.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c
index c5c30fb..9a53f13 100644
--- a/drivers/nfc/nfcsim.c
+++ b/drivers/nfc/nfcsim.c
@@ -60,7 +60,7 @@ struct nfcsim {
static struct nfcsim *dev0;
static struct nfcsim *dev1;
-struct workqueue_struct *wq;
+static struct workqueue_struct *wq;
static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown)
{
@@ -481,7 +481,7 @@ static void nfcsim_free_device(struct nfcsim *dev)
kfree(dev);
}
-int __init nfcsim_init(void)
+static int __init nfcsim_init(void)
{
int rc;
@@ -522,7 +522,7 @@ exit:
return rc;
}
-void __exit nfcsim_exit(void)
+static void __exit nfcsim_exit(void)
{
nfcsim_cleanup_dev(dev0, 1);
nfcsim_cleanup_dev(dev1, 1);
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH v2 3.11] genetlink: fix family dump race
From: David Miller @ 2013-08-12 4:29 UTC (permalink / raw)
To: johannes
Cc: linux-wireless, netdev, tgraf, andrei.otcheretianski, ilan.peer,
johannes.berg
In-Reply-To: <1375879163-2116-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes@sipsolutions.net>
Date: Wed, 7 Aug 2013 14:39:23 +0200
> When dumping generic netlink families, only the first dump call
> is locked with genl_lock(), which protects the list of families,
> and thus subsequent calls can access the data without locking,
> racing against family addition/removal. This can cause a crash.
> Fix it - the locking needs to be conditional because the first
> time around it's already locked.
>
> BUG: unable to handle kernel paging request at f8467360
> IP: [<c14c56bb>] ctrl_dumpfamily+0x6b/0xe0
> EIP: 0060:[<c14c56bb>] EFLAGS: 00210297 CPU: 2
> EIP is at ctrl_dumpfamily+0x6b/0xe0
> EAX: f8467378 EBX: f8467340 ECX: 00000000 EDX: ec1610c4
> ESI: 00000001 EDI: c2077cc0 EBP: c46c3c00 ESP: c46c3bd4
> DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
> CR0: 80050033 CR2: f8467360 CR3: 26e54000 CR4: 001407d0
> DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
> DR6: ffff0ff0 DR7: 00000400
> Process wpa_supplicant (pid: 20081, ti=c46c2000 task=c44640b0 task.ti=c46c2000)
> Call Trace:
> [<c14c20bc>] netlink_dump+0x5c/0x200
> [<c14c3450>] __netlink_dump_start+0x140/0x160
> [<c14c5172>] genl_rcv_msg+0x102/0x270
> [<c14c4b5e>] netlink_rcv_skb+0x8e/0xb0
> [<c14c505c>] genl_rcv+0x1c/0x30
> [<c14c456b>] netlink_unicast+0x17b/0x1c0
> [<c14c47d4>] netlink_sendmsg+0x224/0x370
> [<c1485adf>] sock_sendmsg+0xff/0x120
I completely agree with your analysis that we need locking here, but
the crash OOPS backtrace doesn't make any sense to me.
The bug should trigger when we enter the dump continuation path, which
would look like:
ctrl_dumpfamily()
netlink_dump()
netlink_recvmsg()
...
Since this is the only way we get into ctrl_dumpfamily() without
holding genl_lock().
But in your trace we're going through genl_rcv() which means this is
the first call of the dump, and genl_rcv() takes the necessary locks.
^ permalink raw reply
* 80211s with DFS
From: Volker von Hoesslin @ SKBX Systems @ 2013-08-11 21:03 UTC (permalink / raw)
To: linux-wireless
hi mailinglist!
i have a real big problem! i'm trying to implement a wireless-mesh
(80211s) with openWRT (current trunk) over 11a (5GHz) with "authSAE" for
outdoor. all works fine, mesh is runnning and all fine. but now, i'm at
germany and for the outdoor use, i have to use the channel 100-140 with
DFS & TPC. so the mesh implementation dont work in this channel? with
this error:
authSAE config:
#######################################################
authsae:
{
sae:
{
debug = 480;
password = "foobar";
group = [19, 26, 21, 25, 20];
blacklist = 5;
thresh = 5;
lifetime = 3600;
};
meshd:
{
meshid = "foobar";
interface = "mesh0";
band = "11a";
channel = 104;
htmode = "ht20";
mcast-rate = 6;
debug = 1;
};
};
#######################################################
starting mesh with "authSAE":
#######################################################
# meshd-nl80211 -c /etc/authsae.cfg
----------
nlcfg rates hexdump
00 3c 00 5a 00 78 00 b4 00 f0 01 68 01 e0 02 1c
----------
----------
mgtk: hexdump
ce 5a b3 fc 8b 76 db 62 11 c9 58 33 fa 0c 26 88
----------
----------
Fixed Information Elements in this STA hexdump
01 08 8c 12 98 24 b0 48 60 6c
----------
meshd: Starting mesh with mesh id = foobar
----------
basic rates: hexdump
8c 98 b0
----------
joining mesh foobar on freq 3443784, mode 0
nlerror, cmd 68, seq 1376254403: Invalid argument
#######################################################
and this is without "authSAE":
#######################################################
# iw mesh0 set channel 104
# iw mesh0 mesh join foobar
command failed: Invalid argument (-22)
#######################################################
but this is working with a non-DFS channel 44:
#######################################################
# iw mesh0 set channel 44
# iw mesh0 mesh join hackewrt
[21044.240000] IPv6: ADDRCONF(NETDEV_CHANGE): mesh0: link becomes ready
[21044.240000] mesh-br: port 1(vlan11) entered forwarding state
[21044.250000] mesh-br: port 1(vlan11) entered forwarding state
[21044.260000] IPv6: ADDRCONF(NETDEV_CHANGE): vlan11: link becomes ready
[21044.260000] coova-br: port 1(vlan12) entered forwarding state
[21044.270000] coova-br: port 1(vlan12) entered forwarding state
[21044.280000] IPv6: ADDRCONF(NETDEV_CHANGE): vlan12: link becomes ready
root@6470028F55A2:~#
#######################################################
i think this error is from the "netlink lib(libnl genl)"...
if i use a channel without DFS, it works fine (in germany channel like
36-48)... so how it is possible to use mesh (80211s) with DFS ?
big thx for answer,
volker...
^ permalink raw reply
* Re: [RFC] mac80211: add support for split-MAC implementations
From: Johan Almbladh @ 2013-08-11 20:19 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <CAJWpbEg74C7DYbDkWCpNJRte7X7+40UHgNAL7uWLFHJ64CApKw@mail.gmail.com>
I would prefer my original solution that puts the decryption handler
after the sta_process handler. The code is cleaner since we avoid the
extra flag and the coupling between decrypt and sta_process. My
conclusion is that the change is correct, see below.
ieee80211_rx_h_check_more_data, ieee80211_rx_h_uapsd_and_pspoll:
The MOREDATA and PM bits are not protected by the encryption MIC. It
should be valid to process those bits regardless of the decryption
outcome.
ieee80211_rx_h_sta_process:
The updating of last_rx for an IBSS STA is conditional on the STA
being AUTHORIZED. That state is the same regardless of whether the
updating is done before or after decryption.
The main argument that the MOREDATA and PM bits are not protected by
the encryption and are therefore independent. You can always send a
spoofed NULLFUNC frame to an RSN AP or STA and have the PM and
MOREDATA bits processed accordingly. My change allows data frames that
could not be decrypted to be processed similar to NULLFUNC frames.
I have run mac80211 in STA and AP mode with this change for quite some
time now without any problems. I will run it in IBSS mode also as you
suggest.
Provided that my IBSS tests pass, should I send you a final patch that
changes the RX handler order and their locations in the file?
Johan
On Sat, Aug 10, 2013 at 1:31 PM, Johan Almbladh <ja@anyfi.net> wrote:
> On Fri, Aug 9, 2013 at 3:07 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
>>
>> On Thu, 2013-08-08 at 15:21 +0200, Johan Almbladh wrote:
>> > This patch enables power save processing for encrypted frames even if the
>> > encryption key is not set. This is a requirement when implementing split-MAC
>> > systems like Anyfi.net [1] and CAPWAP [2] on mac80211 using monitor frame
>> > injection and reception.
>>
>> I have no idea what these are, nor do I actually want to care much...
>
> Anyfi.net is a dynamic split-mac system where the security part of the
> 802.11 stack is located in your home router and the realtime part is
> handled by any router or AP that happens to be near your current
> location. The two parts are connected dynamically via a UDP tunnel
> that carries raw encrypted 802.11 frames, forming a complete 802.11
> stack that provides your home Wi-Fi wherever you are. In a community
> Wi-Fi deployment, the users get secure Wi-Fi access with automatic
> sign-on via their home Wi-Fi network which is simply available
> everywhere.
>
> Should you find the concept interesting there is quite extensive
> technical documentation at http://anyfi.net/documentation#architecture
> :-)
>
>
>> You presumably use Felix's active monitor mode?
>
> I use a monitor socket in a userspace daemon. The daemon receives
> encrypted 802.11 frames with radiotap encapsulation on this monitor
> socket. It also injects encrypted 802.11 frames with radiotap
> encapsulation by transmitting them on the same socket. I believe this
> is the way hostapd used to handle transmission of management and EAPOL
> frames before they switched to nl80211.
>
>
>> > The mac80211 RX handlers are reordered slightly so
>> > that the power save handler is invoked before the decryption handler.
>> >
>> > The patch is minimal in the sense that it provides the required functionality
>> > with a minimal change, but I am open to suggestions if this change is too
>> > intrusive. Please let me know what you think.
>>
>> I think you should ask yourself if this makes sense in the normal wifi
>> context... :-)
>
> You are right about that, but I think this little feature can be added
> without affecting the normal operation :-) To be honest, mac80211 has
> all the interfaces required for any split-mac implementation, thanks
> to the mac80211/hostapd partitioning. The *only* thing missing is the
> ability to handle AP power save processing without handling the
> encryption...
>
>
>> It actually seems like it *does* make sense, so it should have an
>> appropriate description for that, but I'm a bit worried about IBSS in
>> sta_process.
>
> The patch enables power save processing even if there is no unicast
> key set, but *also* if key is set but the decryption failed. This is
> what I meant with "intrusive". The IBSS updating in sta_process will
> also run in this case, but the STA is still required to be authorized.
>
> It's possible to narrow it down to only affect the case where no
> encryption key is set:
>
> * Keep the RX handlers in their original order
> * Don't drop frames where rx->key is NULL in ieee80211_rx_h_decrypt.
> Instead, mark the frame with a flag
> * Drop any marked frames at the end of ieee80211_rx_h_sta_process with
> RX_DROP_MONITOR
>
> I can prepare a new patch if you prefer this solution.
>
>> Also I've tried to keep the code in the file sequential, so this patch
>> should be moving ieee80211_rx_h_decrypt() itself as well.
>
> I'll make sure to put them in the right order.
>
> Johan
^ permalink raw reply
* brcsmac kernel panic
From: Daniel Wagner @ 2013-08-11 16:21 UTC (permalink / raw)
To: linux-wireless; +Cc: linux-kernel, Arend van Spriel
Hi,
I just updated my laptop (MacBook Air 2012) from 3.11-rc3+ to 3.11-rc4+
and since then brcsmac crashes short after enabling it. Unfortunately, I
did also change some config flags in the area of cpufreq (enabling
p-state driver) so the configuration is not exactly the same. Before I
try to figure out what I have changed, I am posting the picture of the
crash. Maybe it is something obvious.
v3.11-rc4-197-gd92581f
http://www.monom.org/misc/brcmsmac/v3.11-rc4.config
http://www.monom.org/misc/brcmsmac/IMAG0064.jpg
hth,
daniel
^ permalink raw reply
* Re: [PATCH 12/12] brcmsmac: support 4313iPA
From: Jonas Gorski @ 2013-08-11 12:48 UTC (permalink / raw)
To: Arend van Spriel; +Cc: John W. Linville, linux-wireless, Piotr Haber
In-Reply-To: <1376130450-29746-13-git-send-email-arend@broadcom.com>
Hi,
On Sat, Aug 10, 2013 at 12:27 PM, Arend van Spriel <arend@broadcom.com> wrote:
> From: Piotr Haber <phaber@broadcom.com>
>
> Add support for 4313 iPA variant.
> It is a variant of already supported 4313 ePA,
> so this patch adds the required PHY changes to
> support it properly including an updated switch
> control table for BT-combo card variants.
Okay, I'll bite. Since this patch was already reverted once, it
warrants some additional scrutiny.
First of all, the patch is quite large, and I wonder if it couldn't be
split into smaller patches, especially as it looks like there are
additional fixes/changes merged in it.
Detailed comments below ...
> Tested-by: Maximilian Engelhardt <maxi@daemonizer.de>
> Tested-by: David Costa <david@zarel.net>
> Reviewed-by: Arend Van Spriel <arend@broadcom.com>
> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
> Signed-off-by: Piotr Haber <phaber@broadcom.com>
> Signed-off-by: Arend van Spriel <arend@broadcom.com>
> ---
This is obviously a V2 (or V(n+1) where n was the reverted version),
so there should be something describing the changes to the reverted
version. Why should we trust it now to not break things again? (Yes, I
see those Tested-bys ;-)
> .../net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | 399 +++++++++++++--------
> .../wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c | 289 +++++++++------
> .../wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h | 1 +
> 3 files changed, 436 insertions(+), 253 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
> index 3d6b16c..b8ddaad 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
> @@ -1137,8 +1137,9 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
> gain0_15 = ((biq1 & 0xf) << 12) |
> ((tia & 0xf) << 8) |
> ((lna2 & 0x3) << 6) |
> - ((lna2 &
> - 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
> + ((lna2 & 0x3) << 4) |
> + ((lna1 & 0x3) << 2) |
> + ((lna1 & 0x3) << 0);
Unrelated style change.
>
> mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
> mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
> @@ -1328,6 +1329,43 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
> return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
> }
>
> +static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
> + u16 tia_gain, u16 lna2_gain)
> +{
> + u32 i_thresh_l, q_thresh_l;
> + u32 i_thresh_h, q_thresh_h;
> + struct lcnphy_iq_est iq_est_h, iq_est_l;
> +
> + wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
> + lna2_gain, 0);
> +
> + wlc_lcnphy_rx_gain_override_enable(pi, true);
> + wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
> + udelay(500);
> + write_radio_reg(pi, RADIO_2064_REG112, 0);
> + if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
> + return false;
> +
> + wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
> + udelay(500);
> + write_radio_reg(pi, RADIO_2064_REG112, 0);
> + if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
> + return false;
> +
> + i_thresh_l = (iq_est_l.i_pwr << 1);
> + i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
> +
> + q_thresh_l = (iq_est_l.q_pwr << 1);
> + q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
So X_thresh_l == iq_est_l.X_pwr * 2 and X_thresh_h == iq_est_l.X_pwr *
5? Why not trust the compiler to use optimize it? It would be a bit
more readable.
> + if ((iq_est_h.i_pwr > i_thresh_l) &&
> + (iq_est_h.i_pwr < i_thresh_h) &&
> + (iq_est_h.q_pwr > q_thresh_l) &&
> + (iq_est_h.q_pwr < q_thresh_h))
> + return true;
> +
> + return false;
> +}
> +
> static bool
> wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
> const struct lcnphy_rx_iqcomp *iqcomp,
> @@ -1342,8 +1380,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
> RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
> rfoverride3_old, rfoverride3val_old, rfoverride4_old,
> rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
> - int tia_gain;
> - u32 received_power, rx_pwr_threshold;
> + int tia_gain, lna2_gain, biq1_gain;
> + bool set_gain;
> u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
> u16 values_to_save[11];
> s16 *ptr;
> @@ -1368,126 +1406,134 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
> goto cal_done;
> }
>
> - if (module == 1) {
> + WARN_ON(module != 1);
> + tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
> + wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
>
> - tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
> - wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
This indentation change makes it a bit harder to review, but luckily
there is git show -b ...
> + for (i = 0; i < 11; i++)
> + values_to_save[i] =
> + read_radio_reg(pi, rxiq_cal_rf_reg[i]);
> + Core1TxControl_old = read_phy_reg(pi, 0x631);
> +
> + or_phy_reg(pi, 0x631, 0x0015);
> +
> + RFOverride0_old = read_phy_reg(pi, 0x44c);
> + RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
> + rfoverride2_old = read_phy_reg(pi, 0x4b0);
> + rfoverride2val_old = read_phy_reg(pi, 0x4b1);
> + rfoverride3_old = read_phy_reg(pi, 0x4f9);
> + rfoverride3val_old = read_phy_reg(pi, 0x4fa);
> + rfoverride4_old = read_phy_reg(pi, 0x938);
> + rfoverride4val_old = read_phy_reg(pi, 0x939);
> + afectrlovr_old = read_phy_reg(pi, 0x43b);
> + afectrlovrval_old = read_phy_reg(pi, 0x43c);
> + old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
> + old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
>
> - for (i = 0; i < 11; i++)
> - values_to_save[i] =
> - read_radio_reg(pi, rxiq_cal_rf_reg[i]);
> - Core1TxControl_old = read_phy_reg(pi, 0x631);
> -
> - or_phy_reg(pi, 0x631, 0x0015);
> -
> - RFOverride0_old = read_phy_reg(pi, 0x44c);
> - RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
> - rfoverride2_old = read_phy_reg(pi, 0x4b0);
> - rfoverride2val_old = read_phy_reg(pi, 0x4b1);
> - rfoverride3_old = read_phy_reg(pi, 0x4f9);
> - rfoverride3val_old = read_phy_reg(pi, 0x4fa);
> - rfoverride4_old = read_phy_reg(pi, 0x938);
> - rfoverride4val_old = read_phy_reg(pi, 0x939);
> - afectrlovr_old = read_phy_reg(pi, 0x43b);
> - afectrlovrval_old = read_phy_reg(pi, 0x43c);
> - old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
> - old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
> -
> - tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
> - if (tx_gain_override_old) {
> - wlc_lcnphy_get_tx_gain(pi, &old_gains);
> - tx_gain_index_old = pi_lcn->lcnphy_current_index;
> - }
> + tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
> + if (tx_gain_override_old) {
> + wlc_lcnphy_get_tx_gain(pi, &old_gains);
> + tx_gain_index_old = pi_lcn->lcnphy_current_index;
> + }
>
> - wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
> + wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
>
> - mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
> - mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
> + mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
> + mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
>
> - mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
> - mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
> + mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
> + mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
>
> - write_radio_reg(pi, RADIO_2064_REG116, 0x06);
> - write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
> - write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
> - write_radio_reg(pi, RADIO_2064_REG098, 0x03);
> - write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
> - mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
> - write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
> - write_radio_reg(pi, RADIO_2064_REG114, 0x01);
> - write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
> - write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
> -
> - mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
> - mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
> - mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
> - mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
> - mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
> - mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
> - mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
> - mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
> - mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
> - mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
> -
> - mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
> - mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
> -
> - wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
> - write_phy_reg(pi, 0x6da, 0xffff);
> - or_phy_reg(pi, 0x6db, 0x3);
> - wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
> - wlc_lcnphy_rx_gain_override_enable(pi, true);
> -
> - tia_gain = 8;
> - rx_pwr_threshold = 950;
> - while (tia_gain > 0) {
> - tia_gain -= 1;
> - wlc_lcnphy_set_rx_gain_by_distribution(pi,
> - 0, 0, 2, 2,
> - (u16)
> - tia_gain, 1, 0);
> - udelay(500);
> + write_radio_reg(pi, RADIO_2064_REG116, 0x06);
> + write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
> + write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
> + write_radio_reg(pi, RADIO_2064_REG098, 0x03);
> + write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
> + mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
> + write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
> + write_radio_reg(pi, RADIO_2064_REG114, 0x01);
> + write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
> + write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
> +
> + mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
> + mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
> + mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
> + mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
> + mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
> + mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
> + mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
> + mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
> + mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
> + mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
>
> - received_power =
> - wlc_lcnphy_measure_digital_power(pi, 2000);
> - if (received_power < rx_pwr_threshold)
> - break;
> + mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
> + mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
> +
> + write_phy_reg(pi, 0x6da, 0xffff);
> + or_phy_reg(pi, 0x6db, 0x3);
> +
> + wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
> + set_gain = false;
> +
> + lna2_gain = 3;
> + while ((lna2_gain >= 0) && !set_gain) {
> + tia_gain = 4;
> +
> + while ((tia_gain >= 0) && !set_gain) {
> + biq1_gain = 6;
> +
> + while ((biq1_gain >= 0) && !set_gain) {
> + set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
> + (u16)
> + biq1_gain,
> + (u16)
> + tia_gain,
> + (u16)
> + lna2_gain);
> + biq1_gain -= 1;
> + }
> + tia_gain -= 1;
> }
> - result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
> + lna2_gain -= 1;
> + }
This looks like it could be made more readable using for loops and a goto:
for (lna_gain = 3; lna_gain >= 0; lna_gain--) {
for (tia_gain = 4; tia_gain >= 0; tia_gain--) {
for (big1_gain = 6; big1_gain >= 0; big1_gain--) {
set_gain = wlc_lcnphy_rx_iq_cal_gain(...);
if (set_gain)
goto found;
}
}
}
found:
...
>
> - wlc_lcnphy_stop_tx_tone(pi);
> + if (set_gain)
> + result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
> + else
> + result = false;
>
> - write_phy_reg(pi, 0x631, Core1TxControl_old);
> + wlc_lcnphy_stop_tx_tone(pi);
>
> - write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
> - write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
> - write_phy_reg(pi, 0x4b0, rfoverride2_old);
> - write_phy_reg(pi, 0x4b1, rfoverride2val_old);
> - write_phy_reg(pi, 0x4f9, rfoverride3_old);
> - write_phy_reg(pi, 0x4fa, rfoverride3val_old);
> - write_phy_reg(pi, 0x938, rfoverride4_old);
> - write_phy_reg(pi, 0x939, rfoverride4val_old);
> - write_phy_reg(pi, 0x43b, afectrlovr_old);
> - write_phy_reg(pi, 0x43c, afectrlovrval_old);
> - write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
> - write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
> + write_phy_reg(pi, 0x631, Core1TxControl_old);
> +
> + write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
> + write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
> + write_phy_reg(pi, 0x4b0, rfoverride2_old);
> + write_phy_reg(pi, 0x4b1, rfoverride2val_old);
> + write_phy_reg(pi, 0x4f9, rfoverride3_old);
> + write_phy_reg(pi, 0x4fa, rfoverride3val_old);
> + write_phy_reg(pi, 0x938, rfoverride4_old);
> + write_phy_reg(pi, 0x939, rfoverride4val_old);
> + write_phy_reg(pi, 0x43b, afectrlovr_old);
> + write_phy_reg(pi, 0x43c, afectrlovrval_old);
> + write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
> + write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
>
> - wlc_lcnphy_clear_trsw_override(pi);
> + wlc_lcnphy_clear_trsw_override(pi);
>
> - mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
> + mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
>
> - for (i = 0; i < 11; i++)
> - write_radio_reg(pi, rxiq_cal_rf_reg[i],
> - values_to_save[i]);
> + for (i = 0; i < 11; i++)
> + write_radio_reg(pi, rxiq_cal_rf_reg[i],
> + values_to_save[i]);
>
> - if (tx_gain_override_old)
> - wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
> - else
> - wlc_lcnphy_disable_tx_gain_override(pi);
> + if (tx_gain_override_old)
> + wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
> + else
> + wlc_lcnphy_disable_tx_gain_override(pi);
>
> - wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
> - wlc_lcnphy_rx_gain_override_enable(pi, false);
> - }
> + wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
> + wlc_lcnphy_rx_gain_override_enable(pi, false);
>
> cal_done:
> kfree(ptr);
> @@ -1789,6 +1835,17 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
> write_radio_reg(pi, RADIO_2064_REG038, 3);
> write_radio_reg(pi, RADIO_2064_REG091, 7);
> }
> +
> + if (!(pi->sh->boardflags & BFL_FEM)) {
> + u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
> + 0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
> +
> + write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
> + write_radio_reg(pi, RADIO_2064_REG091, 0x3);
> + write_radio_reg(pi, RADIO_2064_REG038, 0x3);
> +
> + write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
> + }
> }
>
> static int
> @@ -1983,6 +2040,16 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
> } else {
> mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
> mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
> + mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
> + mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
> + mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
> + mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
> + mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
> + mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
> + mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
> + mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
> + mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
> + mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
What does this do? This seems to be applied regardless of iPA or ePA,
so I looks like it fixes something? Or is this needed for iPA and
harmless for ePA?
> }
> } else {
> mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
> @@ -2069,12 +2136,14 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
> (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
>
> mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
> + mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
Same here.
> }
>
> static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
> {
> struct phytbl_info tab;
> u32 rfseq, ind;
> + u8 tssi_sel;
>
> tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
> tab.tbl_width = 32;
> @@ -2096,7 +2165,13 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
>
> mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
>
> - wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
> + if (pi->sh->boardflags & BFL_FEM) {
> + tssi_sel = 0x1;
> + wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
> + } else {
> + tssi_sel = 0xe;
> + wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
> + }
Doesn't this change change tssi_sel from 0xe to 0x1 for (already
supported) ePA cards, and sets it to the old value 0xe for iPA ones? I
would have expected 0xe for BFL_FEM /ePA and 0x1 for iPA ... .
> mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
>
> mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
> @@ -2132,9 +2207,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
> mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
>
> if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
> - mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
> + mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
> mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
> } else {
> + mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
Okay, this one is new also for the ePA case, so I wonder why this
wasn't needed before?
> mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
> mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
> }
> @@ -2181,6 +2257,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
>
> mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
>
> + mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
> + mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
> + mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
> +
Same for these three writes.
> wlc_lcnphy_pwrctrl_rssiparams(pi);
> }
>
> @@ -2799,6 +2879,8 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
> read_radio_reg(pi, RADIO_2064_REG007) & 1;
> u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
> u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
> + u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
> +
These changes also look at a first glance unrelated to iPA, as well as ...
> idleTssi = read_phy_reg(pi, 0x4ab);
> suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
> MCTL_EN_MAC));
> @@ -2816,6 +2898,12 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
> mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
> mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
> wlc_lcnphy_tssi_setup(pi);
> +
> + mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
> + mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
> +
> + wlc_lcnphy_set_bbmult(pi, 0x0);
> +
These ones.
> wlc_phy_do_dummy_tx(pi, true, OFF);
> idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
> >> 0);
> @@ -2837,6 +2925,7 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
>
> mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
>
> + wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
> wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
> wlc_lcnphy_set_tx_gain(pi, &old_gains);
> wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
> @@ -3050,6 +3139,11 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
> wlc_lcnphy_write_table(pi, &tab);
> tab.tbl_offset++;
> }
> + mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
> + mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
> + mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
> + mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
> + mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
>
> mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
>
> @@ -3851,7 +3945,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
> target_gains.pad_gain = 21;
> target_gains.dac_gain = 0;
> wlc_lcnphy_set_tx_gain(pi, &target_gains);
> - wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
>
> if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
>
> @@ -3862,6 +3955,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
> lcnphy_recal ? LCNPHY_CAL_RECAL :
> LCNPHY_CAL_FULL), false);
> } else {
> + wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
> wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
> }
>
> @@ -4286,17 +4380,22 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
> if (CHSPEC_IS5G(pi->radio_chanspec))
> pa_gain = 0x70;
> else
> - pa_gain = 0x70;
> + pa_gain = 0x60;
You are reducing the value for !BFL_FEM, I assume this is a fix for something?
>
> if (pi->sh->boardflags & BFL_FEM)
> pa_gain = 0x10;
> +
Unnecessary whitespace change.
> tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
> tab.tbl_width = 32;
> tab.tbl_len = 1;
> tab.tbl_ptr = &val;
>
> for (j = 0; j < 128; j++) {
> - gm_gain = gain_table[j].gm;
> + if (pi->sh->boardflags & BFL_FEM)
> + gm_gain = gain_table[j].gm;
> + else
> + gm_gain = 15;
> +
> val = (((u32) pa_gain << 24) |
> (gain_table[j].pad << 16) |
> (gain_table[j].pga << 8) | gm_gain);
> @@ -4507,7 +4606,10 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
>
> write_phy_reg(pi, 0x4ea, 0x4688);
>
> - mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
> + if (pi->sh->boardflags & BFL_FEM)
> + mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
> + else
> + mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
>
> mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
>
> @@ -4518,6 +4620,13 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
> wlc_lcnphy_rcal(pi);
>
> wlc_lcnphy_rc_cal(pi);
> +
> + if (!(pi->sh->boardflags & BFL_FEM)) {
> + write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
> + write_radio_reg(pi, RADIO_2064_REG033, 0x19);
> + write_radio_reg(pi, RADIO_2064_REG039, 0xe);
> + }
> +
> }
>
> static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
> @@ -4530,6 +4639,7 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
> uint idx;
> u8 phybw40;
> struct phytbl_info tab;
> + const struct phytbl_info *tb;
> u32 val;
>
> phybw40 = CHSPEC_IS40(pi->radio_chanspec);
> @@ -4547,22 +4657,20 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
> wlc_lcnphy_write_table(pi, &tab);
> }
>
> - tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
> - tab.tbl_width = 16;
> - tab.tbl_ptr = &val;
> - tab.tbl_len = 1;
> -
> - val = 114;
> - tab.tbl_offset = 0;
> - wlc_lcnphy_write_table(pi, &tab);
> + if (!(pi->sh->boardflags & BFL_FEM)) {
> + tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
> + tab.tbl_width = 16;
> + tab.tbl_ptr = &val;
> + tab.tbl_len = 1;
>
> - val = 130;
> - tab.tbl_offset = 1;
> - wlc_lcnphy_write_table(pi, &tab);
> + val = 150;
> + tab.tbl_offset = 0;
> + wlc_lcnphy_write_table(pi, &tab);
>
> - val = 6;
> - tab.tbl_offset = 8;
> - wlc_lcnphy_write_table(pi, &tab);
> + val = 220;
> + tab.tbl_offset = 1;
> + wlc_lcnphy_write_table(pi, &tab);
> + }
So this isn't needed anymore for ePA cards?
>
> if (CHSPEC_IS2G(pi->radio_chanspec)) {
> if (pi->sh->boardflags & BFL_FEM)
> @@ -4576,7 +4684,6 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
> }
>
> if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
> - const struct phytbl_info *tb;
> int l;
>
> if (CHSPEC_IS2G(pi->radio_chanspec)) {
> @@ -4597,21 +4704,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
> wlc_lcnphy_write_table(pi, &tb[idx]);
> }
>
> - if ((pi->sh->boardflags & BFL_FEM)
> - && !(pi->sh->boardflags & BFL_FEM_BT))
> - wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
> - else if (pi->sh->boardflags & BFL_FEM_BT) {
> - if (pi->sh->boardrev < 0x1250)
> - wlc_lcnphy_write_table(
> - pi,
> - &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
> + if (pi->sh->boardflags & BFL_FEM) {
> + if (pi->sh->boardflags & BFL_FEM_BT) {
> + if (pi->sh->boardrev < 0x1250)
> + tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
> + else
> + tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
> + } else {
> + tb = &dot11lcn_sw_ctrl_tbl_info_4313_epa;
> + }
> + } else {
> + if (pi->sh->boardflags & BFL_FEM_BT)
> + tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa;
> else
> - wlc_lcnphy_write_table(
> - pi,
> - &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
> - } else
> - wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
> -
> + tb = &dot11lcn_sw_ctrl_tbl_info_4313;
> + }
> + wlc_lcnphy_write_table(pi, tb);
> wlc_lcnphy_load_rfpower(pi);
>
> wlc_lcnphy_clear_papd_comptable(pi);
> @@ -4955,6 +5063,8 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
> wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
>
> mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
> + if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
> + wlc_lcnphy_tssi_setup(pi);
> }
>
> void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
> @@ -4993,8 +5103,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
> if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
> return false;
>
> - if ((pi->sh->boardflags & BFL_FEM) &&
> - (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
> + if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
> if (pi_lcn->lcnphy_tempsense_option == 3) {
> pi->hwpwrctrl = true;
> pi->hwpwrctrl_capable = true;
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
> index 622c01c..9fb0ca2 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
> @@ -2058,6 +2058,73 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
> 0x0005,
> };
>
> +static const u16 dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo[] = {
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> + 0x0005,
> + 0x0006,
> + 0x0009,
> + 0x000a,
> +};
> +
> static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
> 0x0004,
> 0x0004,
> @@ -2834,6 +2901,12 @@ const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = {
> sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
> };
>
> +const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa = {
> + &dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo,
> + sizeof(dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo) /
> + sizeof(dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo[0]), 15, 0, 16
Not necessarily in this patch but maybe in a follow up cleanup patch:
ARRAY_SIZE() please?
I guess that's it from me.
Regards
Jonas
^ permalink raw reply
* [patch] iwlwifi: pcie: returning positive instead of negative
From: Dan Carpenter @ 2013-08-10 23:03 UTC (permalink / raw)
To: Johannes Berg
Cc: Emmanuel Grumbach, Intel Linux Wireless, John W. Linville,
linux-wireless, kernel-janitors
There is a missing '-' character here so we return positive 'ENOMEM'
instead of negative. The caller doesn't care. All non-zero returns
are translated to '-ENOMEM' in iwl_pcie_nic_init().
This is just a cleanup.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 134f7a1..a81d227 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -829,7 +829,7 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
sizeof(struct iwl_txq), GFP_KERNEL);
if (!trans_pcie->txq) {
IWL_ERR(trans, "Not enough memory for txq\n");
- ret = ENOMEM;
+ ret = -ENOMEM;
goto error;
}
^ permalink raw reply related
* Re: [PATCH] udev: fail firmware loading immediately if no search path is defined
From: Kay Sievers @ 2013-08-10 21:28 UTC (permalink / raw)
To: Tom Gundersen
Cc: Maarten Lankhorst, Linux Wireless List, Andy Lutomirski,
Intel Linux Wireless, Johannes Berg, linux-hotplug, Bryan Kadzban,
systemd Mailing List, linux-kernel
In-Reply-To: <CAG-2HqUT3hbFPSEqYnJvBOgS6p4dKf=nhqZtzqS-on8FFe9ipA@mail.gmail.com>
On Sat, Aug 10, 2013 at 11:00 PM, Tom Gundersen <teg@jklm.no> wrote:
> It would be simple enough to add an udev rule to just print 'ignoring
> firmware event' to the logs.
This and I guess:
SUBSYSTEM=="firmware", ACTION=="add", ATTR{loading}="-1"
would also just cancel the request at the same time without any other
code needed.
The udev firmware support just a configure option, just like the
kernel has them. So distributions should enable it in udev and the
kernel if they need it.
We simply cannot coordinate the defaults of systemd and the kernel
because the rules of the kernel are different. The kernel does "keep
defaults like stuff has been in the past" and udev does "make default
what makes the most sense on current systems".
> We should really ignore the event though, and
> not cancel it. Not sure if this is something we want upstream (after all,
> there are plenty of situations where we don't warn if the recommendations in
> the README file are not followed), or if distros and whoever wants it should
> ship that themselves. I'll leave that for Kay to decide.
The proper fix is that userspace firmware should be disabled in the
kernel for new systems, and kept enabled only for old systems. Old
systems need to enable a new udev version to support firmware loading.
There are currently broken in-kernel mis-users of the firmware
interface that use the firmware interface but disable uevents, they
still pull-in the user interface of the firmware loader. If nobody
wants to fix them, the code for the common users of the firmware
loader should at least get rid of the userspace fallback to call out
to userspace. At that point the udev configure option would not matter
any more.
> Lastly, note that the plan is to drop all the firmware code from udev in the
> not too distant future, so it doesn't really maker much sense to add new
> functionality to that at this point.
Right, I think all is fine. It's something that people can control
with the kernel and udev configuration options. It's just that the
defaults of the kernel and udev don't match at the moment, because
they have different policies of setting default values.
Kay
^ permalink raw reply
* rt2800usb: Kernel log spammed with TX status messages
From: Michael Büsch @ 2013-08-10 17:53 UTC (permalink / raw)
To: Ivo van Doorn, Gertjan van Wingerde, Helmut Schaa; +Cc: linux-wireless
[-- Attachment #1: Type: text/plain, Size: 7749 bytes --]
Hi,
My kernel logs are spammed with messages like the ones below.
I'm currently running latest debian sid kernel, which is based on 3.10.5.
The device is
Bus 009 Device 002: ID 148f:5370 Ralink Technology, Corp. RT5370 Wireless Adapter
Any idea on how to debug/fix this?
Aug 10 11:27:44 marge kernel: [ 5560.310989] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 11 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.311077] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 11 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.311101] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 11 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.319229] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 12 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.319271] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 12 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.319281] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 12 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.319305] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 13 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.330987] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 14 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.331107] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 14 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.331126] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 14 in queue 2
Aug 10 11:27:44 marge kernel: [ 5560.412247] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:44 marge kernel: [ 5560.412364] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:44 marge kernel: [ 5560.412488] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:44 marge kernel: [ 5560.412612] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5560.923400] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 0 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.923421] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 0 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.923424] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 0 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.927149] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 1 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.927166] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 1 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.927169] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 1 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.943279] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 2 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.943301] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 2 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.943310] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 2 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.943332] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 3 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.947404] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 4 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.947432] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 4 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.947436] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 4 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.947445] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 5 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.971166] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 6 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.971215] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 6 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.971224] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 6 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.971254] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.971264] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 8 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.979413] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 9 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.979448] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 9 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.979456] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 9 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.979476] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 10 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.987291] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 11 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.987339] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 11 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.987347] ieee80211 phy0: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 11 in queue 2
Aug 10 11:27:45 marge kernel: [ 5560.996550] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5560.996667] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.069806] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.069925] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.070048] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.070173] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.070298] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.070423] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.070547] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.070675] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.070798] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
Aug 10 11:27:45 marge kernel: [ 5561.087058] ieee80211 phy0: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [v3.10] [regression] [b43] : mac80211/minstrel: use the new rate control API
From: Ronald @ 2013-08-10 17:30 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless
In-Reply-To: <52057D86.9060500@openwrt.org>
Yes, issue fixed in v3.11-rc4. I assumed that since the regression
hopped over from v3.10 to v3.11, it got undetected. I also tested
v3.11 half way it's merge window (this kernel did boot) which
contained the regression as well.
Apparently it was noticed later and fixed later than I expected. Sorry
for the noise.
2013/8/10 Felix Fietkau <nbd@openwrt.org>:
> The fix for this issue has been merged upstream and is in the stable
> queue (so will probably be included in 3.10.6). Another way you can get
> rid of this error in your existing kernel is to enable
> CONFIG_MAC80211_RC_MINSTREL_HT in your .config
>
> - Felix
>
> On 2013-08-09 11:28 PM, Ronald wrote:
>> Excuse me, this should be a v3.10 regression.
>>
>> 2013/8/9 Ronald <ronald645@gmail.com>:
>>> [ Please cc me as I'm not subscribed ]
>>>
>>> Mentioned commit causes a regression on my box. It oopses after
>>> NetworkManager comes up and tries to use the card (I think).
>>>
>>> The card is:
>>>
>>> [ 1.220907] b43-phy0: Broadcom 4311 WLAN found (core revision 10)
>>> [ 1.230206] ata1.00: configured for UDMA/100
>>> [ 1.320018] b43-phy0: Found PHY: Analog 4, Type 2 (G), Revision 8
>>> [ 1.380120] Broadcom 43xx driver loaded [ Features: P ]
>>>
>>> I typed over the oops (first lines fell off, sorry):
>>>
>>> Workqueue: phy0 ieee80211_scan_work
>>> task: ffff880000211c20 ti: ffff880034c0c000 task.ti: ffff880034c0c000
>>> RIP: 0010:[<ffffffff81580382>] [<ffffffff81580382>] minstrel_get_rate+0x22/0x250
>>> RSP: 0018:ffff880034c0da88 EFLAGS: 00010286
>>> RAX: ffffffff81870ac0 RBX: 0000000000000000 RCX: ffff880034c0db58
>>> RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880034c67a00
>>> RBP: ffff880034c0dac8 R08: ffff8800000863a0 R09: 0000000000000fff
>>> R10: ffffffff81856020 R11: 0000000000000000 R12: ffff880034c67a00
>>> R13: ffff880034da2740 R14: ffff880034c0db58 R15: ffff88000039f940
>>> FS: 00007fd6da002700(0000) GS:ffffffff8181e000(0000) knlGS:0000000000000000
>>> CS: 0010 DS: 0000 ES: 0000 CR0: 000000000005003b
>>> CR2: 0000000000000048 CR3: 000000003517e000 CR4: 00000000000007f0
>>> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
>>> DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
>>> Stack:
>>> 0000000000000000 ffff880034c0db28 ffff880034c0daf8 ffff88003517c330
>>> 0000000000000000 ffff880034da2740 ffff880034c0db58 ffff88000039f940
>>> ffff880034c0daf8 ffffffff815653e1 ffff880034c0dbe0 ffff88003517c300
>>> Call Trace:
>>> [<ffffffff815653e1>] rate_control_get_rate+0xa1/0xe0
>>> [<ffffffff815709e9>] invoke_tx_handlers+0x729/0x1360
>>> [<ffffffff8104bc3d>] ? sched_clock_local.constprop.1+0x1d/0x90
>>> [<ffffffff8104ce6e>] ? check_preempt_wakeup+0x11e/0x240
>>> [<ffffffff8157169d>] ieee80211_tx+0x7d/0x100
>>> [<ffffffff815717b1>] ieee80211_xmit+0x91/0xc0
>>> [<ffffffff8157307e>] __ieee80211_tx_skb_tid_band+0x6e/0x80
>>> [<ffffffff81577643>] ieee80211_send_probe_req+0x73/0xc0
>>> [<ffffffff8155a10f>] ieee80211_scan_state_send_probe+0x9f/0xe0
>>> [<ffffffff8155ad9c>] ieee80211_scan_work+0x1fc/0x440
>>> [<ffffffff8103c9ba>] process_one_work+0x13a/0x3b0
>>> [<ffffffff8103cfcb>] worker_thread+0x10b/0x350
>>> [<ffffffff8103cec0>] ? rescuer_thread+0x250/0x250
>>> [<ffffffff81042afa>] kthread+0xba/0xc0
>>> [<ffffffff81042a40>] ? __kthread_parkme+0x80/0x80
>>> [<ffffffff8158c32a>] ret_from_fork+0x7a/0xb0
>>> [<ffffffff81042a40>] ? __kthread_parkme+0x80/0x80
>>> Code: 00 00 00 00 00 0f 1f 40 00 55 48 89 e5 48 83 ec 40 48 89 5d d8
>>> 4c 89 65 e0 48 89 d3 4c 89 6d e8 4c 89 7d f8 49 89 fc 4c 89 75 f0 <44>
>>> 0f b6 f7 4c 8b 71 18 48 89 ca 48 89 de 49 89 cd
>>> RIP [<ffffffff81580382>] minstrel_get_rate+0x22/0x250
>>> RSP <ffff880034c0da88>
>>> CR2: 0000000000000048
>>> ---[ end trace 071727ab6dc6fcf3 ]---
>>> Kernel panic - not syncing: Fatal exception in interrupt
>>> drm_kms_helper: panic occurred, switching back to text console
>>
>
^ permalink raw reply
* Re: [PATCH v3] brcmsmac: Fix WARNING caused by lack of calls to dma_mapping_error()
From: Larry Finger @ 2013-08-10 15:19 UTC (permalink / raw)
To: Arend van Spriel
Cc: John W. Linville, linux-wireless, Brett Rudley,
Franky (Zhenhui) Lin, Hante Meuleman, brcm80211-dev-list, Stable
In-Reply-To: <5205F19E.6060907@broadcom.com>
On 08/10/2013 02:54 AM, Arend van Spriel wrote:
> On 08/10/13 00:05, Larry Finger wrote:
>> On 08/09/2013 12:36 PM, John W. Linville wrote:
>>> From: "John W. Linville" <linville@tuxdriver.com>
>>>
>>> The driver fails to check the results of DMA mapping in twp places,
>>> which results in the following warning:
>>>
>>> [ 28.078515] ------------[ cut here ]------------
>>> [ 28.078529] WARNING: at lib/dma-debug.c:937 check_unmap+0x47e/0x930()
>>> [ 28.078533] bcma-pci-bridge 0000:0e:00.0: DMA-API: device driver
>>> failed to check map error[device address=0x00000000b5d60d6c]
>>> [size=1876 bytes] [mapped as
>>> single]
>>> [ 28.078536] Modules linked in: bnep bluetooth vboxpci(O)
>>> vboxnetadp(O) vboxnetflt(O) vboxdrv(O) ipv6 b43 brcmsmac rtl8192cu
>>> rtl8192c_common rtlwifi mac802
>>> 11 brcmutil cfg80211 snd_hda_codec_conexant rng_core snd_hda_intel
>>> kvm_amd snd_hda_codec ssb kvm mmc_core snd_pcm snd_seq snd_timer
>>> snd_seq_device snd k8temp
>>> cordic joydev serio_raw hwmon sr_mod sg pcmcia pcmcia_core soundcore
>>> cdrom i2c_nforce2 i2c_core forcedeth bcma snd_page_alloc autofs4 ext4
>>> jbd2 mbcache crc1
>>> 6 scsi_dh_alua scsi_dh_hp_sw scsi_dh_rdac scsi_dh_emc scsi_dh
>>> ata_generic pata_amd
>>> [ 28.078602] CPU: 1 PID: 2570 Comm: NetworkManager Tainted: G O
>>> 3.10.0-rc7-wl+ #42
>>> [ 28.078605] Hardware name: Hewlett-Packard HP Pavilion dv2700
>>> Notebook PC/30D6, BIOS F.27 11/27/2008
>>> [ 28.078607] 0000000000000009 ffff8800bbb03ad8 ffffffff8144f898
>>> ffff8800bbb03b18
>>> [ 28.078612] ffffffff8103e1eb 0000000000000002 ffff8800b719f480
>>> ffff8800b7b9c010
>>> [ 28.078617] ffffffff824204c0 ffffffff81754d57 0000000000000754
>>> ffff8800bbb03b78
>>> [ 28.078622] Call Trace:
>>> [ 28.078624] <IRQ> [<ffffffff8144f898>] dump_stack+0x19/0x1b
>>> [ 28.078634] [<ffffffff8103e1eb>] warn_slowpath_common+0x6b/0xa0
>>> [ 28.078638] [<ffffffff8103e2c1>] warn_slowpath_fmt+0x41/0x50
>>> [ 28.078650] [<ffffffff8122d7ae>] check_unmap+0x47e/0x930
>>> [ 28.078655] [<ffffffff8122de4c>] debug_dma_unmap_page+0x5c/0x70
>>> [ 28.078679] [<ffffffffa04a808c>] dma64_getnextrxp+0x10c/0x190 [brcmsmac]
>>> [ 28.078691] [<ffffffffa04a9042>] dma_rx+0x62/0x240 [brcmsmac]
>>> [ 28.078707] [<ffffffffa0479101>] brcms_c_dpc+0x211/0x9d0 [brcmsmac]
>>> [ 28.078717] [<ffffffffa046d927>] ? brcms_dpc+0x27/0xf0 [brcmsmac]
>>> [ 28.078731] [<ffffffffa046d947>] brcms_dpc+0x47/0xf0 [brcmsmac]
>>> [ 28.078736] [<ffffffff81047dcc>] tasklet_action+0x6c/0xf0
>>> --snip--
>>> [ 28.078974] [<ffffffff813891bd>] SyS_sendmsg+0xd/0x20
>>> [ 28.078979] [<ffffffff81455c24>] tracesys+0xdd/0xe2
>>> [ 28.078982] ---[ end trace 6164d1a08148e9c8 ]---
>>> [ 28.078984] Mapped at:
>>> [ 28.078985] [<ffffffff8122c8fd>] debug_dma_map_page+0x9d/0x150
>>> [ 28.078989] [<ffffffffa04a9322>] dma_rxfill+0x102/0x3d0 [brcmsmac]
>>> [ 28.079001] [<ffffffffa047a13d>] brcms_c_init+0x87d/0x1100 [brcmsmac]
>>> [ 28.079010] [<ffffffffa046d851>] brcms_init+0x21/0x30 [brcmsmac]
>>> [ 28.079018] [<ffffffffa04786e0>] brcms_c_up+0x150/0x430 [brcmsmac]
>>>
>>> As the patch adds a new failure mechanism to dma_rxfill(). When I
>>> changed the
>>> comment at the start of the routine to add that information, I also
>>> polished
>>> the wording.
>>>
>>> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
>>> Cc: Stable <stable@vger.kernel.org>
>>> Cc: Brett Rudley <brudley@broadcom.com>
>>> Cc: Arend van Spriel <arend@broadcom.com>
>>> Cc: Franky (Zhenhui) Lin <frankyl@broadcom.com>
>>> Cc: Hante Meuleman <meuleman@broadcom.com>
>>> Cc: brcm80211-dev-list@broadcom.com
>>> Signed-off-by: John W. Linville <linville@tuxdriver.com>
>>> ---
>>> Did this one get lost?
>>>
>>> V2 - fixed two patch errors.
>>> V3 - address comments from Arend (linville)
>>>
>>
>> For some reason, I never got the mail containing Arend's comments, and I
>> forgot about it. If John's V3 fixes take care of them, then it should be
>> pushed.
>
> Weird as I resend the comments. Do you have me on a blacklist ;-)
No. As you can see, this message came through. I also checked to make sure that
my intermediate mailer had not put your message in its spam bucket.
Larry
^ permalink raw reply
* [PATCH 2/2] ath9k: shrink a few data structures by reordering fields
From: Felix Fietkau @ 2013-08-10 13:59 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
In-Reply-To: <1376143156-74164-1-git-send-email-nbd@openwrt.org>
Also reduce the size of a few fields where possible
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 12 ++++++------
drivers/net/wireless/ath/ath9k/xmit.c | 16 ++++++++--------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 0d69b13..7b1d036 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -72,7 +72,6 @@ struct ath_config {
/*************************/
#define ATH_TXBUF_RESET(_bf) do { \
- (_bf)->bf_stale = false; \
(_bf)->bf_lastbf = NULL; \
(_bf)->bf_next = NULL; \
memset(&((_bf)->bf_state), 0, \
@@ -192,10 +191,10 @@ struct ath_txq {
struct ath_atx_ac {
struct ath_txq *txq;
- int sched;
struct list_head list;
struct list_head tid_q;
bool clear_ps_filter;
+ bool sched;
};
struct ath_frame_info {
@@ -212,6 +211,7 @@ struct ath_buf_state {
u8 bf_type;
u8 bfs_paprd;
u8 ndelim;
+ bool stale;
u16 seqno;
unsigned long bfs_paprd_timestamp;
};
@@ -225,7 +225,6 @@ struct ath_buf {
void *bf_desc; /* virtual addr of desc */
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
- bool bf_stale;
struct ieee80211_tx_rate rates[4];
struct ath_buf_state bf_state;
};
@@ -237,13 +236,14 @@ struct ath_atx_tid {
struct ath_node *an;
struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
- int bar_index;
u16 seq_start;
u16 seq_next;
u16 baw_size;
- int tidno;
+ u8 tidno;
int baw_head; /* first un-acked tx buffer */
int baw_tail; /* next unused tx buffer slot */
+
+ s8 bar_index;
bool sched;
bool paused;
bool active;
@@ -255,10 +255,10 @@ struct ath_node {
struct ieee80211_vif *vif; /* interface with which we're associated */
struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
struct ath_atx_ac ac[IEEE80211_NUM_ACS];
- int ps_key;
u16 maxampdu;
u8 mpdudensity;
+ s8 ps_key;
bool sleeping;
bool no_ps_filter;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index d8dfb3e..4fc80e3 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -493,7 +493,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
while (bf) {
bf_next = bf->bf_next;
- if (!bf->bf_stale || bf_next != NULL)
+ if (!bf->bf_state.stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
@@ -586,7 +586,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* not a holding desc.
*/
INIT_LIST_HEAD(&bf_head);
- if (bf_next != NULL || !bf_last->bf_stale)
+ if (bf_next != NULL || !bf_last->bf_state.stale)
list_move_tail(&bf->list, &bf_head);
if (!txpending) {
@@ -610,7 +610,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ieee80211_sta_eosp(sta);
}
/* retry the un-acked ones */
- if (bf->bf_next == NULL && bf_last->bf_stale) {
+ if (bf->bf_next == NULL && bf_last->bf_state.stale) {
struct ath_buf *tbf;
tbf = ath_clone_txbuf(sc, bf_last);
@@ -1734,7 +1734,7 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
while (!list_empty(list)) {
bf = list_first_entry(list, struct ath_buf, list);
- if (bf->bf_stale) {
+ if (bf->bf_state.stale) {
list_del(&bf->list);
ath_tx_return_buffer(sc, bf);
@@ -2490,7 +2490,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
* it with the STALE flag.
*/
bf_held = NULL;
- if (bf->bf_stale) {
+ if (bf->bf_state.stale) {
bf_held = bf;
if (list_is_last(&bf_held->list, &txq->axq_q))
break;
@@ -2514,7 +2514,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
* however leave the last descriptor back as the holding
* descriptor for hw.
*/
- lastbf->bf_stale = true;
+ lastbf->bf_state.stale = true;
INIT_LIST_HEAD(&bf_head);
if (!list_is_singular(&lastbf->list))
list_cut_position(&bf_head,
@@ -2585,7 +2585,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
}
bf = list_first_entry(fifo_list, struct ath_buf, list);
- if (bf->bf_stale) {
+ if (bf->bf_state.stale) {
list_del(&bf->list);
ath_tx_return_buffer(sc, bf);
bf = list_first_entry(fifo_list, struct ath_buf, list);
@@ -2607,7 +2607,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
ath_tx_txqaddbuf(sc, txq, &bf_q, true);
}
} else {
- lastbf->bf_stale = true;
+ lastbf->bf_state.stale = true;
if (bf != lastbf)
list_cut_position(&bf_head, fifo_list,
lastbf->list.prev);
--
1.8.0.2
^ permalink raw reply related
* [PATCH 1/2] ath9k: fix rx descriptor related race condition
From: Felix Fietkau @ 2013-08-10 13:59 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, stable
Similar to a race condition that exists in the tx path, the hardware
might re-read the 'next' pointer of a descriptor of the last completed
frame. This only affects non-EDMA (pre-AR93xx) devices.
To deal with this race, defer clearing and re-linking a completed rx
descriptor until the next one has been processed.
Cc: stable@vger.kernel.org
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 5 +----
drivers/net/wireless/ath/ath9k/recv.c | 17 +++++++++++++----
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 505c615..0d69b13 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -79,10 +79,6 @@ struct ath_config {
sizeof(struct ath_buf_state)); \
} while (0)
-#define ATH_RXBUF_RESET(_bf) do { \
- (_bf)->bf_stale = false; \
- } while (0)
-
/**
* enum buffer_type - Buffer type flags
*
@@ -315,6 +311,7 @@ struct ath_rx {
struct ath_descdma rxdma;
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
+ struct ath_buf *buf_hold;
struct sk_buff *frag;
u32 ampdu_ref;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 62dff97..2dd851a 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -42,8 +42,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
struct ath_desc *ds;
struct sk_buff *skb;
- ATH_RXBUF_RESET(bf);
-
ds = bf->bf_desc;
ds->ds_link = 0; /* link to null */
ds->ds_data = bf->bf_buf_addr;
@@ -70,6 +68,14 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
sc->rx.rxlink = &ds->ds_link;
}
+static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf)
+{
+ if (sc->rx.buf_hold)
+ ath_rx_buf_link(sc, sc->rx.buf_hold);
+
+ sc->rx.buf_hold = bf;
+}
+
static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
{
/* XXX block beacon interrupts */
@@ -117,7 +123,6 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
skb = bf->bf_mpdu;
- ATH_RXBUF_RESET(bf);
memset(skb->data, 0, ah->caps.rx_status_len);
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
ah->caps.rx_status_len, DMA_TO_DEVICE);
@@ -432,6 +437,7 @@ int ath_startrecv(struct ath_softc *sc)
if (list_empty(&sc->rx.rxbuf))
goto start_recv;
+ sc->rx.buf_hold = NULL;
sc->rx.rxlink = NULL;
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
ath_rx_buf_link(sc, bf);
@@ -677,6 +683,9 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
}
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+ if (bf == sc->rx.buf_hold)
+ return NULL;
+
ds = bf->bf_desc;
/*
@@ -1387,7 +1396,7 @@ requeue:
if (edma) {
ath_rx_edma_buf_link(sc, qtype);
} else {
- ath_rx_buf_link(sc, bf);
+ ath_rx_buf_relink(sc, bf);
ath9k_hw_rxena(ah);
}
} while (1);
--
1.8.0.2
^ permalink raw reply related
* Re: FUSB200 xhci issue
From: Alan Stern @ 2013-08-10 11:57 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Christian Lamparter, Sarah Sharp, Seth Forshee, ath9k_htc_fw,
USB list, linux-wireless
In-Reply-To: <5205DB86.2050905@rempel-privat.de>
On Sat, 10 Aug 2013, Oleksij Rempel wrote:
> usb reset do not affect behaviour of firmware. At least after i remove
> all attempts to reboot FW from driver.
> If adapter will got reset signal, FW will be notified about it. Then FW
> will remove reset flag and will just continue to work. After usb reset,
> lsusb show correct, update information - EP3 and EP4 was updated from
> INT to BULK.
>
> I assume, no i need to add to the driver some kind of firmware check.
> What is the proper way to do it?
The simplest way is to put a new value for the device descriptor's
bcdDevice value in the firmware. Then all you have to do is check that
value.
Alan Stern
^ permalink raw reply
* Re: [RFC] mac80211: add support for split-MAC implementations
From: Johan Almbladh @ 2013-08-10 11:31 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1376053671.8355.4.camel@jlt4.sipsolutions.net>
On Fri, Aug 9, 2013 at 3:07 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
>
> On Thu, 2013-08-08 at 15:21 +0200, Johan Almbladh wrote:
> > This patch enables power save processing for encrypted frames even if the
> > encryption key is not set. This is a requirement when implementing split-MAC
> > systems like Anyfi.net [1] and CAPWAP [2] on mac80211 using monitor frame
> > injection and reception.
>
> I have no idea what these are, nor do I actually want to care much...
Anyfi.net is a dynamic split-mac system where the security part of the
802.11 stack is located in your home router and the realtime part is
handled by any router or AP that happens to be near your current
location. The two parts are connected dynamically via a UDP tunnel
that carries raw encrypted 802.11 frames, forming a complete 802.11
stack that provides your home Wi-Fi wherever you are. In a community
Wi-Fi deployment, the users get secure Wi-Fi access with automatic
sign-on via their home Wi-Fi network which is simply available
everywhere.
Should you find the concept interesting there is quite extensive
technical documentation at http://anyfi.net/documentation#architecture
:-)
> You presumably use Felix's active monitor mode?
I use a monitor socket in a userspace daemon. The daemon receives
encrypted 802.11 frames with radiotap encapsulation on this monitor
socket. It also injects encrypted 802.11 frames with radiotap
encapsulation by transmitting them on the same socket. I believe this
is the way hostapd used to handle transmission of management and EAPOL
frames before they switched to nl80211.
> > The mac80211 RX handlers are reordered slightly so
> > that the power save handler is invoked before the decryption handler.
> >
> > The patch is minimal in the sense that it provides the required functionality
> > with a minimal change, but I am open to suggestions if this change is too
> > intrusive. Please let me know what you think.
>
> I think you should ask yourself if this makes sense in the normal wifi
> context... :-)
You are right about that, but I think this little feature can be added
without affecting the normal operation :-) To be honest, mac80211 has
all the interfaces required for any split-mac implementation, thanks
to the mac80211/hostapd partitioning. The *only* thing missing is the
ability to handle AP power save processing without handling the
encryption...
> It actually seems like it *does* make sense, so it should have an
> appropriate description for that, but I'm a bit worried about IBSS in
> sta_process.
The patch enables power save processing even if there is no unicast
key set, but *also* if key is set but the decryption failed. This is
what I meant with "intrusive". The IBSS updating in sta_process will
also run in this case, but the STA is still required to be authorized.
It's possible to narrow it down to only affect the case where no
encryption key is set:
* Keep the RX handlers in their original order
* Don't drop frames where rx->key is NULL in ieee80211_rx_h_decrypt.
Instead, mark the frame with a flag
* Drop any marked frames at the end of ieee80211_rx_h_sta_process with
RX_DROP_MONITOR
I can prepare a new patch if you prefer this solution.
> Also I've tried to keep the code in the file sequential, so this patch
> should be moving ieee80211_rx_h_decrypt() itself as well.
I'll make sure to put them in the right order.
Johan
^ permalink raw reply
* [PATCH 07/12] brcmfmac: add support for manual TDLS operations
From: Arend van Spriel @ 2013-08-10 10:27 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1376130450-29746-1-git-send-email-arend@broadcom.com>
Implement the .tdls_oper() callback and indicate TDLS support
in the wiphy flags.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
.../net/wireless/brcm80211/brcmfmac/fwil_types.h | 21 ++++++++
.../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 57 +++++++++++++++++++++-
2 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
index 665ef69..ecabb04 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
@@ -69,4 +69,25 @@ struct brcmf_fil_bss_enable_le {
__le32 enable;
};
+/**
+ * struct tdls_iovar - common structure for tdls iovars.
+ *
+ * @ea: ether address of peer station.
+ * @mode: mode value depending on specific tdls iovar.
+ * @chanspec: channel specification.
+ * @pad: unused (for future use).
+ */
+struct brcmf_tdls_iovar_le {
+ u8 ea[ETH_ALEN]; /* Station address */
+ u8 mode; /* mode: depends on iovar */
+ __le16 chanspec;
+ __le32 pad; /* future */
+};
+
+enum brcmf_tdls_manual_ep_ops {
+ BRCMF_TDLS_MANUAL_EP_CREATE = 1,
+ BRCMF_TDLS_MANUAL_EP_DELETE = 3,
+ BRCMF_TDLS_MANUAL_EP_DISCOVERY = 6
+};
+
#endif /* FWIL_TYPES_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index c3dfea3..0370e44 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -4126,6 +4126,53 @@ static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
}
+static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
+{
+ int ret;
+
+ switch (oper) {
+ case NL80211_TDLS_DISCOVERY_REQ:
+ ret = BRCMF_TDLS_MANUAL_EP_DISCOVERY;
+ break;
+ case NL80211_TDLS_SETUP:
+ ret = BRCMF_TDLS_MANUAL_EP_CREATE;
+ break;
+ case NL80211_TDLS_TEARDOWN:
+ ret = BRCMF_TDLS_MANUAL_EP_DELETE;
+ break;
+ default:
+ brcmf_err("unsupported operation: %d\n", oper);
+ ret = -EOPNOTSUPP;
+ }
+ return ret;
+}
+
+static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
+ struct net_device *ndev, u8 *peer,
+ enum nl80211_tdls_operation oper)
+{
+ struct brcmf_if *ifp;
+ struct brcmf_tdls_iovar_le info;
+ int ret = 0;
+
+ ret = brcmf_convert_nl80211_tdls_oper(oper);
+ if (ret < 0)
+ return ret;
+
+ ifp = netdev_priv(ndev);
+ memset(&info, 0, sizeof(info));
+ info.mode = (u8)ret;
+ if (peer)
+ memcpy(info.ea, peer, ETH_ALEN);
+
+ ret = brcmf_fil_iovar_data_set(ifp, "tdls_endpoint",
+ &info, sizeof(info));
+ if (ret < 0)
+ brcmf_err("tdls_endpoint iovar failed: ret=%d\n", ret);
+
+ return ret;
+}
+
static struct cfg80211_ops wl_cfg80211_ops = {
.add_virtual_intf = brcmf_cfg80211_add_iface,
.del_virtual_intf = brcmf_cfg80211_del_iface,
@@ -4164,6 +4211,7 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.stop_p2p_device = brcmf_p2p_stop_device,
.crit_proto_start = brcmf_cfg80211_crit_proto_start,
.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
+ .tdls_oper = brcmf_cfg80211_tdls_oper,
CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode)
};
@@ -4285,7 +4333,8 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
WIPHY_FLAG_OFFCHAN_TX |
- WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+ WIPHY_FLAG_SUPPORTS_TDLS;
wiphy->mgmt_stypes = brcmf_txrx_stypes;
wiphy->max_remain_on_channel_duration = 5000;
brcmf_wiphy_pno_params(wiphy);
@@ -4906,6 +4955,12 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
goto cfg80211_p2p_attach_out;
}
+ err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
+ if (err) {
+ brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
+ wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
+ }
+
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
&io_type);
if (err) {
--
1.8.1.3
^ permalink raw reply related
* [PATCH 12/12] brcmsmac: support 4313iPA
From: Arend van Spriel @ 2013-08-10 10:27 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Piotr Haber, Arend van Spriel
In-Reply-To: <1376130450-29746-1-git-send-email-arend@broadcom.com>
From: Piotr Haber <phaber@broadcom.com>
Add support for 4313 iPA variant.
It is a variant of already supported 4313 ePA,
so this patch adds the required PHY changes to
support it properly including an updated switch
control table for BT-combo card variants.
Tested-by: Maximilian Engelhardt <maxi@daemonizer.de>
Tested-by: David Costa <david@zarel.net>
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Piotr Haber <phaber@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
.../net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | 399 +++++++++++++--------
.../wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c | 289 +++++++++------
.../wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h | 1 +
3 files changed, 436 insertions(+), 253 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
index 3d6b16c..b8ddaad 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -1137,8 +1137,9 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
gain0_15 = ((biq1 & 0xf) << 12) |
((tia & 0xf) << 8) |
((lna2 & 0x3) << 6) |
- ((lna2 &
- 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
+ ((lna2 & 0x3) << 4) |
+ ((lna1 & 0x3) << 2) |
+ ((lna1 & 0x3) << 0);
mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
@@ -1328,6 +1329,43 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
}
+static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
+ u16 tia_gain, u16 lna2_gain)
+{
+ u32 i_thresh_l, q_thresh_l;
+ u32 i_thresh_h, q_thresh_h;
+ struct lcnphy_iq_est iq_est_h, iq_est_l;
+
+ wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
+ lna2_gain, 0);
+
+ wlc_lcnphy_rx_gain_override_enable(pi, true);
+ wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
+ udelay(500);
+ write_radio_reg(pi, RADIO_2064_REG112, 0);
+ if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
+ return false;
+
+ wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
+ udelay(500);
+ write_radio_reg(pi, RADIO_2064_REG112, 0);
+ if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
+ return false;
+
+ i_thresh_l = (iq_est_l.i_pwr << 1);
+ i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
+
+ q_thresh_l = (iq_est_l.q_pwr << 1);
+ q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
+ if ((iq_est_h.i_pwr > i_thresh_l) &&
+ (iq_est_h.i_pwr < i_thresh_h) &&
+ (iq_est_h.q_pwr > q_thresh_l) &&
+ (iq_est_h.q_pwr < q_thresh_h))
+ return true;
+
+ return false;
+}
+
static bool
wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
const struct lcnphy_rx_iqcomp *iqcomp,
@@ -1342,8 +1380,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
rfoverride3_old, rfoverride3val_old, rfoverride4_old,
rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
- int tia_gain;
- u32 received_power, rx_pwr_threshold;
+ int tia_gain, lna2_gain, biq1_gain;
+ bool set_gain;
u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
u16 values_to_save[11];
s16 *ptr;
@@ -1368,126 +1406,134 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
goto cal_done;
}
- if (module == 1) {
+ WARN_ON(module != 1);
+ tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
- tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
- wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+ for (i = 0; i < 11; i++)
+ values_to_save[i] =
+ read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+ Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+ or_phy_reg(pi, 0x631, 0x0015);
+
+ RFOverride0_old = read_phy_reg(pi, 0x44c);
+ RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+ rfoverride2_old = read_phy_reg(pi, 0x4b0);
+ rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+ rfoverride3_old = read_phy_reg(pi, 0x4f9);
+ rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+ rfoverride4_old = read_phy_reg(pi, 0x938);
+ rfoverride4val_old = read_phy_reg(pi, 0x939);
+ afectrlovr_old = read_phy_reg(pi, 0x43b);
+ afectrlovrval_old = read_phy_reg(pi, 0x43c);
+ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+ old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
- for (i = 0; i < 11; i++)
- values_to_save[i] =
- read_radio_reg(pi, rxiq_cal_rf_reg[i]);
- Core1TxControl_old = read_phy_reg(pi, 0x631);
-
- or_phy_reg(pi, 0x631, 0x0015);
-
- RFOverride0_old = read_phy_reg(pi, 0x44c);
- RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
- rfoverride2_old = read_phy_reg(pi, 0x4b0);
- rfoverride2val_old = read_phy_reg(pi, 0x4b1);
- rfoverride3_old = read_phy_reg(pi, 0x4f9);
- rfoverride3val_old = read_phy_reg(pi, 0x4fa);
- rfoverride4_old = read_phy_reg(pi, 0x938);
- rfoverride4val_old = read_phy_reg(pi, 0x939);
- afectrlovr_old = read_phy_reg(pi, 0x43b);
- afectrlovrval_old = read_phy_reg(pi, 0x43c);
- old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
- old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-
- tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
- if (tx_gain_override_old) {
- wlc_lcnphy_get_tx_gain(pi, &old_gains);
- tx_gain_index_old = pi_lcn->lcnphy_current_index;
- }
+ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+ if (tx_gain_override_old) {
+ wlc_lcnphy_get_tx_gain(pi, &old_gains);
+ tx_gain_index_old = pi_lcn->lcnphy_current_index;
+ }
- wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
- mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
- mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
- write_radio_reg(pi, RADIO_2064_REG116, 0x06);
- write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
- write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
- write_radio_reg(pi, RADIO_2064_REG098, 0x03);
- write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
- mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
- write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
- write_radio_reg(pi, RADIO_2064_REG114, 0x01);
- write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
- write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
-
- mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
- mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
- mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
- mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
- mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
- mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
- mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
- mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
-
- mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
- mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
- wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
- write_phy_reg(pi, 0x6da, 0xffff);
- or_phy_reg(pi, 0x6db, 0x3);
- wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
- wlc_lcnphy_rx_gain_override_enable(pi, true);
-
- tia_gain = 8;
- rx_pwr_threshold = 950;
- while (tia_gain > 0) {
- tia_gain -= 1;
- wlc_lcnphy_set_rx_gain_by_distribution(pi,
- 0, 0, 2, 2,
- (u16)
- tia_gain, 1, 0);
- udelay(500);
+ write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+ write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+ write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+ write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+ write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+ mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+ write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+ write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+ write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+ write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+ mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+ mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+ mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+ mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+ mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+ mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+ mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+ mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
- received_power =
- wlc_lcnphy_measure_digital_power(pi, 2000);
- if (received_power < rx_pwr_threshold)
- break;
+ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+ write_phy_reg(pi, 0x6da, 0xffff);
+ or_phy_reg(pi, 0x6db, 0x3);
+
+ wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+ set_gain = false;
+
+ lna2_gain = 3;
+ while ((lna2_gain >= 0) && !set_gain) {
+ tia_gain = 4;
+
+ while ((tia_gain >= 0) && !set_gain) {
+ biq1_gain = 6;
+
+ while ((biq1_gain >= 0) && !set_gain) {
+ set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
+ (u16)
+ biq1_gain,
+ (u16)
+ tia_gain,
+ (u16)
+ lna2_gain);
+ biq1_gain -= 1;
+ }
+ tia_gain -= 1;
}
- result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
+ lna2_gain -= 1;
+ }
- wlc_lcnphy_stop_tx_tone(pi);
+ if (set_gain)
+ result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
+ else
+ result = false;
- write_phy_reg(pi, 0x631, Core1TxControl_old);
+ wlc_lcnphy_stop_tx_tone(pi);
- write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
- write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
- write_phy_reg(pi, 0x4b0, rfoverride2_old);
- write_phy_reg(pi, 0x4b1, rfoverride2val_old);
- write_phy_reg(pi, 0x4f9, rfoverride3_old);
- write_phy_reg(pi, 0x4fa, rfoverride3val_old);
- write_phy_reg(pi, 0x938, rfoverride4_old);
- write_phy_reg(pi, 0x939, rfoverride4val_old);
- write_phy_reg(pi, 0x43b, afectrlovr_old);
- write_phy_reg(pi, 0x43c, afectrlovrval_old);
- write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
- write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+ write_phy_reg(pi, 0x631, Core1TxControl_old);
+
+ write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+ write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+ write_phy_reg(pi, 0x4b0, rfoverride2_old);
+ write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+ write_phy_reg(pi, 0x4f9, rfoverride3_old);
+ write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+ write_phy_reg(pi, 0x938, rfoverride4_old);
+ write_phy_reg(pi, 0x939, rfoverride4val_old);
+ write_phy_reg(pi, 0x43b, afectrlovr_old);
+ write_phy_reg(pi, 0x43c, afectrlovrval_old);
+ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+ write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
- wlc_lcnphy_clear_trsw_override(pi);
+ wlc_lcnphy_clear_trsw_override(pi);
- mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+ mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
- for (i = 0; i < 11; i++)
- write_radio_reg(pi, rxiq_cal_rf_reg[i],
- values_to_save[i]);
+ for (i = 0; i < 11; i++)
+ write_radio_reg(pi, rxiq_cal_rf_reg[i],
+ values_to_save[i]);
- if (tx_gain_override_old)
- wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
- else
- wlc_lcnphy_disable_tx_gain_override(pi);
+ if (tx_gain_override_old)
+ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+ else
+ wlc_lcnphy_disable_tx_gain_override(pi);
- wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
- wlc_lcnphy_rx_gain_override_enable(pi, false);
- }
+ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+ wlc_lcnphy_rx_gain_override_enable(pi, false);
cal_done:
kfree(ptr);
@@ -1789,6 +1835,17 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
write_radio_reg(pi, RADIO_2064_REG038, 3);
write_radio_reg(pi, RADIO_2064_REG091, 7);
}
+
+ if (!(pi->sh->boardflags & BFL_FEM)) {
+ u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
+ 0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
+
+ write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
+ write_radio_reg(pi, RADIO_2064_REG091, 0x3);
+ write_radio_reg(pi, RADIO_2064_REG038, 0x3);
+
+ write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
+ }
}
static int
@@ -1983,6 +2040,16 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
} else {
mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
+ mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
+ mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
+ mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
+ mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
+ mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
}
} else {
mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
@@ -2069,12 +2136,14 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
(auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
+ mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
}
static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
{
struct phytbl_info tab;
u32 rfseq, ind;
+ u8 tssi_sel;
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
tab.tbl_width = 32;
@@ -2096,7 +2165,13 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
- wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
+ if (pi->sh->boardflags & BFL_FEM) {
+ tssi_sel = 0x1;
+ wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
+ } else {
+ tssi_sel = 0xe;
+ wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
+ }
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
@@ -2132,9 +2207,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
- mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
+ mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
} else {
+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
}
@@ -2181,6 +2257,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
+ mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+
wlc_lcnphy_pwrctrl_rssiparams(pi);
}
@@ -2799,6 +2879,8 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
read_radio_reg(pi, RADIO_2064_REG007) & 1;
u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
+ u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
+
idleTssi = read_phy_reg(pi, 0x4ab);
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
@@ -2816,6 +2898,12 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
wlc_lcnphy_tssi_setup(pi);
+
+ mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
+ mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
+
+ wlc_lcnphy_set_bbmult(pi, 0x0);
+
wlc_phy_do_dummy_tx(pi, true, OFF);
idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
>> 0);
@@ -2837,6 +2925,7 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
+ wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
wlc_lcnphy_set_tx_gain(pi, &old_gains);
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
@@ -3050,6 +3139,11 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
wlc_lcnphy_write_table(pi, &tab);
tab.tbl_offset++;
}
+ mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
+ mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
+ mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
+ mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
+ mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
@@ -3851,7 +3945,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
target_gains.pad_gain = 21;
target_gains.dac_gain = 0;
wlc_lcnphy_set_tx_gain(pi, &target_gains);
- wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
@@ -3862,6 +3955,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
lcnphy_recal ? LCNPHY_CAL_RECAL :
LCNPHY_CAL_FULL), false);
} else {
+ wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
}
@@ -4286,17 +4380,22 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
if (CHSPEC_IS5G(pi->radio_chanspec))
pa_gain = 0x70;
else
- pa_gain = 0x70;
+ pa_gain = 0x60;
if (pi->sh->boardflags & BFL_FEM)
pa_gain = 0x10;
+
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
tab.tbl_width = 32;
tab.tbl_len = 1;
tab.tbl_ptr = &val;
for (j = 0; j < 128; j++) {
- gm_gain = gain_table[j].gm;
+ if (pi->sh->boardflags & BFL_FEM)
+ gm_gain = gain_table[j].gm;
+ else
+ gm_gain = 15;
+
val = (((u32) pa_gain << 24) |
(gain_table[j].pad << 16) |
(gain_table[j].pga << 8) | gm_gain);
@@ -4507,7 +4606,10 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
write_phy_reg(pi, 0x4ea, 0x4688);
- mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+ if (pi->sh->boardflags & BFL_FEM)
+ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+ else
+ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
@@ -4518,6 +4620,13 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
wlc_lcnphy_rcal(pi);
wlc_lcnphy_rc_cal(pi);
+
+ if (!(pi->sh->boardflags & BFL_FEM)) {
+ write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
+ write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+ write_radio_reg(pi, RADIO_2064_REG039, 0xe);
+ }
+
}
static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
@@ -4530,6 +4639,7 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
uint idx;
u8 phybw40;
struct phytbl_info tab;
+ const struct phytbl_info *tb;
u32 val;
phybw40 = CHSPEC_IS40(pi->radio_chanspec);
@@ -4547,22 +4657,20 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
wlc_lcnphy_write_table(pi, &tab);
}
- tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
- tab.tbl_width = 16;
- tab.tbl_ptr = &val;
- tab.tbl_len = 1;
-
- val = 114;
- tab.tbl_offset = 0;
- wlc_lcnphy_write_table(pi, &tab);
+ if (!(pi->sh->boardflags & BFL_FEM)) {
+ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+ tab.tbl_width = 16;
+ tab.tbl_ptr = &val;
+ tab.tbl_len = 1;
- val = 130;
- tab.tbl_offset = 1;
- wlc_lcnphy_write_table(pi, &tab);
+ val = 150;
+ tab.tbl_offset = 0;
+ wlc_lcnphy_write_table(pi, &tab);
- val = 6;
- tab.tbl_offset = 8;
- wlc_lcnphy_write_table(pi, &tab);
+ val = 220;
+ tab.tbl_offset = 1;
+ wlc_lcnphy_write_table(pi, &tab);
+ }
if (CHSPEC_IS2G(pi->radio_chanspec)) {
if (pi->sh->boardflags & BFL_FEM)
@@ -4576,7 +4684,6 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
}
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
- const struct phytbl_info *tb;
int l;
if (CHSPEC_IS2G(pi->radio_chanspec)) {
@@ -4597,21 +4704,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
wlc_lcnphy_write_table(pi, &tb[idx]);
}
- if ((pi->sh->boardflags & BFL_FEM)
- && !(pi->sh->boardflags & BFL_FEM_BT))
- wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
- else if (pi->sh->boardflags & BFL_FEM_BT) {
- if (pi->sh->boardrev < 0x1250)
- wlc_lcnphy_write_table(
- pi,
- &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
+ if (pi->sh->boardflags & BFL_FEM) {
+ if (pi->sh->boardflags & BFL_FEM_BT) {
+ if (pi->sh->boardrev < 0x1250)
+ tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
+ else
+ tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
+ } else {
+ tb = &dot11lcn_sw_ctrl_tbl_info_4313_epa;
+ }
+ } else {
+ if (pi->sh->boardflags & BFL_FEM_BT)
+ tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa;
else
- wlc_lcnphy_write_table(
- pi,
- &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
- } else
- wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
-
+ tb = &dot11lcn_sw_ctrl_tbl_info_4313;
+ }
+ wlc_lcnphy_write_table(pi, tb);
wlc_lcnphy_load_rfpower(pi);
wlc_lcnphy_clear_papd_comptable(pi);
@@ -4955,6 +5063,8 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
+ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+ wlc_lcnphy_tssi_setup(pi);
}
void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
@@ -4993,8 +5103,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
return false;
- if ((pi->sh->boardflags & BFL_FEM) &&
- (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
if (pi_lcn->lcnphy_tempsense_option == 3) {
pi->hwpwrctrl = true;
pi->hwpwrctrl_capable = true;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
index 622c01c..9fb0ca2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
@@ -2058,6 +2058,73 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
0x0005,
};
+static const u16 dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo[] = {
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+ 0x0005,
+ 0x0006,
+ 0x0009,
+ 0x000a,
+};
+
static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
0x0004,
0x0004,
@@ -2834,6 +2901,12 @@ const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = {
sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
};
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa = {
+ &dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo,
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo) /
+ sizeof(dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo[0]), 15, 0, 16
+};
+
const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = {
&dot11lcn_sw_ctrl_tbl_4313_epa_rev0,
sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
@@ -2988,134 +3061,134 @@ dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = {
};
const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = {
- {7, 0, 31, 0, 72},
- {7, 0, 31, 0, 70},
- {7, 0, 31, 0, 68},
- {7, 0, 30, 0, 67},
- {7, 0, 29, 0, 68},
- {7, 0, 28, 0, 68},
- {7, 0, 27, 0, 69},
- {7, 0, 26, 0, 70},
- {7, 0, 25, 0, 70},
- {7, 0, 24, 0, 71},
- {7, 0, 23, 0, 72},
- {7, 0, 23, 0, 70},
- {7, 0, 22, 0, 71},
- {7, 0, 21, 0, 72},
- {7, 0, 21, 0, 70},
- {7, 0, 21, 0, 68},
- {7, 0, 21, 0, 66},
- {7, 0, 21, 0, 64},
- {7, 0, 21, 0, 63},
- {7, 0, 20, 0, 64},
- {7, 0, 19, 0, 65},
- {7, 0, 19, 0, 64},
- {7, 0, 18, 0, 65},
- {7, 0, 18, 0, 64},
- {7, 0, 17, 0, 65},
- {7, 0, 17, 0, 64},
- {7, 0, 16, 0, 65},
- {7, 0, 16, 0, 64},
- {7, 0, 16, 0, 62},
- {7, 0, 16, 0, 60},
- {7, 0, 16, 0, 58},
- {7, 0, 15, 0, 61},
- {7, 0, 15, 0, 59},
- {7, 0, 14, 0, 61},
- {7, 0, 14, 0, 60},
- {7, 0, 14, 0, 58},
- {7, 0, 13, 0, 60},
- {7, 0, 13, 0, 59},
- {7, 0, 12, 0, 62},
- {7, 0, 12, 0, 60},
- {7, 0, 12, 0, 58},
- {7, 0, 11, 0, 62},
- {7, 0, 11, 0, 60},
- {7, 0, 11, 0, 59},
- {7, 0, 11, 0, 57},
- {7, 0, 10, 0, 61},
- {7, 0, 10, 0, 59},
- {7, 0, 10, 0, 57},
- {7, 0, 9, 0, 62},
- {7, 0, 9, 0, 60},
- {7, 0, 9, 0, 58},
- {7, 0, 9, 0, 57},
- {7, 0, 8, 0, 62},
- {7, 0, 8, 0, 60},
- {7, 0, 8, 0, 58},
- {7, 0, 8, 0, 57},
- {7, 0, 8, 0, 55},
- {7, 0, 7, 0, 61},
+ {15, 0, 31, 0, 72},
+ {15, 0, 31, 0, 70},
+ {15, 0, 31, 0, 68},
+ {15, 0, 30, 0, 68},
+ {15, 0, 29, 0, 69},
+ {15, 0, 28, 0, 69},
+ {15, 0, 27, 0, 70},
+ {15, 0, 26, 0, 70},
+ {15, 0, 25, 0, 71},
+ {15, 0, 24, 0, 72},
+ {15, 0, 23, 0, 73},
+ {15, 0, 23, 0, 71},
+ {15, 0, 22, 0, 72},
+ {15, 0, 21, 0, 73},
+ {15, 0, 21, 0, 71},
+ {15, 0, 21, 0, 69},
+ {15, 0, 21, 0, 67},
+ {15, 0, 21, 0, 65},
+ {15, 0, 21, 0, 63},
+ {15, 0, 20, 0, 65},
+ {15, 0, 19, 0, 66},
+ {15, 0, 19, 0, 64},
+ {15, 0, 18, 0, 66},
+ {15, 0, 18, 0, 64},
+ {15, 0, 17, 0, 66},
+ {15, 0, 17, 0, 64},
+ {15, 0, 16, 0, 66},
+ {15, 0, 16, 0, 64},
+ {15, 0, 16, 0, 62},
+ {15, 0, 16, 0, 61},
+ {15, 0, 16, 0, 59},
+ {15, 0, 15, 0, 61},
+ {15, 0, 15, 0, 59},
+ {15, 0, 14, 0, 62},
+ {15, 0, 14, 0, 60},
+ {15, 0, 14, 0, 58},
+ {15, 0, 13, 0, 61},
+ {15, 0, 13, 0, 59},
+ {15, 0, 12, 0, 62},
+ {15, 0, 12, 0, 61},
+ {15, 0, 12, 0, 59},
+ {15, 0, 11, 0, 62},
+ {15, 0, 11, 0, 61},
+ {15, 0, 11, 0, 59},
+ {15, 0, 11, 0, 57},
+ {15, 0, 10, 0, 61},
+ {15, 0, 10, 0, 59},
+ {15, 0, 10, 0, 58},
+ {15, 0, 9, 0, 62},
+ {15, 0, 9, 0, 61},
+ {15, 0, 9, 0, 59},
+ {15, 0, 9, 0, 57},
+ {15, 0, 8, 0, 62},
+ {15, 0, 8, 0, 61},
+ {15, 0, 8, 0, 59},
+ {15, 0, 8, 0, 57},
+ {15, 0, 8, 0, 56},
+ {15, 0, 8, 0, 54},
+ {15, 0, 8, 0, 53},
+ {15, 0, 8, 0, 51},
+ {15, 0, 8, 0, 50},
+ {7, 0, 7, 0, 69},
+ {7, 0, 7, 0, 67},
+ {7, 0, 7, 0, 65},
+ {7, 0, 7, 0, 64},
+ {7, 0, 7, 0, 62},
{7, 0, 7, 0, 60},
{7, 0, 7, 0, 58},
- {7, 0, 7, 0, 56},
+ {7, 0, 7, 0, 57},
{7, 0, 7, 0, 55},
{7, 0, 6, 0, 62},
- {7, 0, 6, 0, 60},
- {7, 0, 6, 0, 58},
+ {7, 0, 6, 0, 61},
+ {7, 0, 6, 0, 59},
{7, 0, 6, 0, 57},
- {7, 0, 6, 0, 55},
+ {7, 0, 6, 0, 56},
{7, 0, 6, 0, 54},
- {7, 0, 6, 0, 52},
+ {7, 0, 6, 0, 53},
{7, 0, 5, 0, 61},
- {7, 0, 5, 0, 59},
- {7, 0, 5, 0, 57},
+ {7, 0, 5, 0, 60},
+ {7, 0, 5, 0, 58},
{7, 0, 5, 0, 56},
- {7, 0, 5, 0, 54},
+ {7, 0, 5, 0, 55},
{7, 0, 5, 0, 53},
- {7, 0, 5, 0, 51},
- {7, 0, 4, 0, 62},
- {7, 0, 4, 0, 60},
- {7, 0, 4, 0, 58},
+ {7, 0, 5, 0, 52},
+ {7, 0, 5, 0, 50},
+ {7, 0, 5, 0, 49},
+ {7, 0, 5, 0, 47},
{7, 0, 4, 0, 57},
- {7, 0, 4, 0, 55},
+ {7, 0, 4, 0, 56},
{7, 0, 4, 0, 54},
- {7, 0, 4, 0, 52},
+ {7, 0, 4, 0, 53},
{7, 0, 4, 0, 51},
- {7, 0, 4, 0, 49},
+ {7, 0, 4, 0, 50},
{7, 0, 4, 0, 48},
+ {7, 0, 4, 0, 47},
{7, 0, 4, 0, 46},
- {7, 0, 3, 0, 60},
- {7, 0, 3, 0, 58},
- {7, 0, 3, 0, 57},
- {7, 0, 3, 0, 55},
- {7, 0, 3, 0, 54},
- {7, 0, 3, 0, 52},
+ {7, 0, 4, 0, 44},
+ {7, 0, 4, 0, 43},
+ {7, 0, 4, 0, 42},
+ {7, 0, 4, 0, 41},
+ {7, 0, 4, 0, 40},
{7, 0, 3, 0, 51},
- {7, 0, 3, 0, 49},
+ {7, 0, 3, 0, 50},
{7, 0, 3, 0, 48},
+ {7, 0, 3, 0, 47},
{7, 0, 3, 0, 46},
- {7, 0, 3, 0, 45},
{7, 0, 3, 0, 44},
{7, 0, 3, 0, 43},
+ {7, 0, 3, 0, 42},
{7, 0, 3, 0, 41},
- {7, 0, 2, 0, 61},
- {7, 0, 2, 0, 59},
- {7, 0, 2, 0, 57},
- {7, 0, 2, 0, 56},
- {7, 0, 2, 0, 54},
- {7, 0, 2, 0, 53},
- {7, 0, 2, 0, 51},
- {7, 0, 2, 0, 50},
- {7, 0, 2, 0, 48},
- {7, 0, 2, 0, 47},
- {7, 0, 2, 0, 46},
- {7, 0, 2, 0, 44},
- {7, 0, 2, 0, 43},
- {7, 0, 2, 0, 42},
- {7, 0, 2, 0, 41},
- {7, 0, 2, 0, 39},
- {7, 0, 2, 0, 38},
- {7, 0, 2, 0, 37},
- {7, 0, 2, 0, 36},
- {7, 0, 2, 0, 35},
- {7, 0, 2, 0, 34},
- {7, 0, 2, 0, 33},
- {7, 0, 2, 0, 32},
- {7, 0, 1, 0, 63},
- {7, 0, 1, 0, 61},
- {7, 0, 1, 0, 59},
- {7, 0, 1, 0, 57},
+ {3, 0, 3, 0, 56},
+ {3, 0, 3, 0, 54},
+ {3, 0, 3, 0, 53},
+ {3, 0, 3, 0, 51},
+ {3, 0, 3, 0, 50},
+ {3, 0, 3, 0, 48},
+ {3, 0, 3, 0, 47},
+ {3, 0, 3, 0, 46},
+ {3, 0, 3, 0, 44},
+ {3, 0, 3, 0, 43},
+ {3, 0, 3, 0, 42},
+ {3, 0, 3, 0, 41},
+ {3, 0, 3, 0, 39},
+ {3, 0, 3, 0, 38},
+ {3, 0, 3, 0, 37},
+ {3, 0, 3, 0, 36},
+ {3, 0, 3, 0, 35},
+ {3, 0, 3, 0, 34},
};
const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h
index 5f75e16..489422a 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h
@@ -20,6 +20,7 @@
extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[];
extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa_combo;
extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
--
1.8.1.3
^ permalink raw reply related
* [PATCH 05/12] brcmfmac: no fws locking outside fws module.
From: Arend van Spriel @ 2013-08-10 10:27 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Hante Meuleman, Arend van Spriel
In-Reply-To: <1376130450-29746-1-git-send-email-arend@broadcom.com>
From: Hante Meuleman <meuleman@broadcom.com>
FWS uses locking to protect its data while being called from
various entries. On bus_txdata the lock was kept resulting in
unnecessary long locking, but also creating possibility for
deadlock. This update changes the locking to release lock when
bus_txdata is called.
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 1 -
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 127 ++++++++++-----------
2 files changed, 62 insertions(+), 66 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index df94d0e..1273dfd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -558,7 +558,6 @@ struct brcmf_pub {
struct brcmf_fweh_info fweh;
struct brcmf_fws_info *fws;
- spinlock_t fws_spinlock;
struct brcmf_ampdu_rx_reorder
*reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS];
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 15fc807..82f9140 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -422,6 +422,8 @@ struct brcmf_fws_macdesc_table {
struct brcmf_fws_info {
struct brcmf_pub *drvr;
+ spinlock_t spinlock;
+ ulong flags;
struct brcmf_fws_stats stats;
struct brcmf_fws_hanger hanger;
enum brcmf_fws_fcmode fcmode;
@@ -484,6 +486,18 @@ static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws,
}
#undef BRCMF_FWS_TLV_DEF
+static void brcmf_fws_lock(struct brcmf_fws_info *fws)
+ __acquires(&fws->spinlock)
+{
+ spin_lock_irqsave(&fws->spinlock, fws->flags);
+}
+
+static void brcmf_fws_unlock(struct brcmf_fws_info *fws)
+ __releases(&fws->spinlock)
+{
+ spin_unlock_irqrestore(&fws->spinlock, fws->flags);
+}
+
static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg)
{
u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
@@ -870,8 +884,11 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
skcb->state = BRCMF_FWS_SKBSTATE_TIM;
bus = fws->drvr->bus_if;
err = brcmf_fws_hdrpush(fws, skb);
- if (err == 0)
+ if (err == 0) {
+ brcmf_fws_unlock(fws);
err = brcmf_bus_txdata(bus, skb);
+ brcmf_fws_lock(fws);
+ }
if (err)
brcmu_pkt_buf_free_skb(skb);
return true;
@@ -906,26 +923,10 @@ static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
return 0;
}
-/* using macro so sparse checking does not complain
- * about locking imbalance.
- */
-#define brcmf_fws_lock(drvr, flags) \
-do { \
- flags = 0; \
- spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \
-} while (0)
-
-/* using macro so sparse checking does not complain
- * about locking imbalance.
- */
-#define brcmf_fws_unlock(drvr, flags) \
- spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
-
static
int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
{
struct brcmf_fws_mac_descriptor *entry, *existing;
- ulong flags;
u8 mac_handle;
u8 ifidx;
u8 *addr;
@@ -939,10 +940,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
if (entry->occupied) {
brcmf_dbg(TRACE, "deleting %s mac %pM\n",
entry->name, addr);
- brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_lock(fws);
brcmf_fws_macdesc_cleanup(fws, entry, -1);
brcmf_fws_macdesc_deinit(entry);
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
} else
fws->stats.mac_update_failed++;
return 0;
@@ -951,13 +952,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
existing = brcmf_fws_macdesc_lookup(fws, addr);
if (IS_ERR(existing)) {
if (!entry->occupied) {
- brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_lock(fws);
entry->mac_handle = mac_handle;
brcmf_fws_macdesc_init(entry, addr, ifidx);
brcmf_fws_macdesc_set_name(fws, entry);
brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
BRCMF_FWS_PSQ_LEN);
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
} else {
fws->stats.mac_update_failed++;
@@ -965,13 +966,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
} else {
if (entry != existing) {
brcmf_dbg(TRACE, "copy mac %s\n", existing->name);
- brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_lock(fws);
memcpy(entry, existing,
offsetof(struct brcmf_fws_mac_descriptor, psq));
entry->mac_handle = mac_handle;
brcmf_fws_macdesc_deinit(existing);
brcmf_fws_macdesc_set_name(fws, entry);
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
addr);
} else {
@@ -987,7 +988,6 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
u8 type, u8 *data)
{
struct brcmf_fws_mac_descriptor *entry;
- ulong flags;
u8 mac_handle;
int ret;
@@ -997,7 +997,7 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
fws->stats.mac_ps_update_failed++;
return -ESRCH;
}
- brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_lock(fws);
/* a state update should wipe old credits */
entry->requested_credit = 0;
entry->requested_packet = 0;
@@ -1012,7 +1012,7 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
}
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
return ret;
}
@@ -1020,7 +1020,6 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
u8 type, u8 *data)
{
struct brcmf_fws_mac_descriptor *entry;
- ulong flags;
u8 ifidx;
int ret;
@@ -1039,7 +1038,7 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type,
entry->name);
- brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_lock(fws);
switch (type) {
case BRCMF_FWS_TYPE_INTERFACE_OPEN:
entry->state = BRCMF_FWS_STATE_OPEN;
@@ -1051,10 +1050,10 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
break;
default:
ret = -EINVAL;
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
goto fail;
}
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
return ret;
fail:
@@ -1066,7 +1065,6 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
u8 *data)
{
struct brcmf_fws_mac_descriptor *entry;
- ulong flags;
entry = &fws->desc.nodes[data[1] & 0x1F];
if (!entry->occupied) {
@@ -1080,14 +1078,14 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n",
brcmf_fws_get_tlv_name(type), type, entry->name,
data[0], data[2]);
- brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_lock(fws);
if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
entry->requested_credit = data[0];
else
entry->requested_packet = data[0];
entry->ac_bitmap = data[2];
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
return BRCMF_FWS_RET_OK_SCHEDULE;
}
@@ -1385,7 +1383,6 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
u8 *data)
{
- ulong flags;
int i;
if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
@@ -1394,19 +1391,18 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
}
brcmf_dbg(DATA, "enter: data %pM\n", data);
- brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_lock(fws);
for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
brcmf_fws_return_credits(fws, i, data[i]);
brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
fws->fifo_delay_map);
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
return BRCMF_FWS_RET_OK_SCHEDULE;
}
static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
{
- ulong lflags;
__le32 status_le;
u32 status;
u32 hslot;
@@ -1420,9 +1416,9 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
hslot = brcmf_txstatus_get_field(status, HSLOT);
genbit = brcmf_txstatus_get_field(status, GENERATION);
- brcmf_fws_lock(fws->drvr, lflags);
+ brcmf_fws_lock(fws);
brcmf_fws_txs_process(fws, flags, hslot, genbit);
- brcmf_fws_unlock(fws->drvr, lflags);
+ brcmf_fws_unlock(fws);
return BRCMF_FWS_RET_OK_NOSCHEDULE;
}
@@ -1442,7 +1438,6 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
{
struct brcmf_fws_info *fws = ifp->drvr->fws;
int i;
- ulong flags;
u8 *credits = data;
if (e->datalen < BRCMF_FWS_FIFO_COUNT) {
@@ -1455,7 +1450,7 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
fws->creditmap_received = true;
brcmf_dbg(TRACE, "enter: credits %pM\n", credits);
- brcmf_fws_lock(ifp->drvr, flags);
+ brcmf_fws_lock(fws);
for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) {
if (*credits)
fws->fifo_credit_map |= 1 << i;
@@ -1464,7 +1459,7 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
fws->fifo_credit[i] = *credits++;
}
brcmf_fws_schedule_deq(fws);
- brcmf_fws_unlock(ifp->drvr, flags);
+ brcmf_fws_unlock(fws);
return 0;
}
@@ -1473,12 +1468,11 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
void *data)
{
struct brcmf_fws_info *fws = ifp->drvr->fws;
- ulong flags;
- brcmf_fws_lock(ifp->drvr, flags);
+ brcmf_fws_lock(fws);
if (fws)
fws->bcmc_credit_check = true;
- brcmf_fws_unlock(ifp->drvr, flags);
+ brcmf_fws_unlock(fws);
return 0;
}
@@ -1702,17 +1696,22 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
return PTR_ERR(entry);
brcmf_fws_precommit_skb(fws, fifo, skb);
+ entry->transit_count++;
+ if (entry->suppressed)
+ entry->suppr_transit_count++;
+ brcmf_fws_unlock(fws);
rc = brcmf_bus_txdata(bus, skb);
+ brcmf_fws_lock(fws);
brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
skcb->if_flags, skcb->htod, rc);
if (rc < 0) {
+ entry->transit_count--;
+ if (entry->suppressed)
+ entry->suppr_transit_count--;
brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
goto rollback;
}
- entry->transit_count++;
- if (entry->suppressed)
- entry->suppr_transit_count++;
fws->stats.pkt2bus++;
fws->stats.send_pkts[fifo]++;
if (brcmf_skb_if_flags_get_field(skb, REQUESTED))
@@ -1749,7 +1748,6 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
struct brcmf_fws_info *fws = drvr->fws;
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
struct ethhdr *eh = (struct ethhdr *)(skb->data);
- ulong flags;
int fifo = BRCMF_FWS_FIFO_BCMC;
bool multicast = is_multicast_ether_addr(eh->h_dest);
bool pae = eh->h_proto == htons(ETH_P_PAE);
@@ -1770,7 +1768,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
if (!multicast)
fifo = brcmf_fws_prio2fifo[skb->priority];
- brcmf_fws_lock(drvr, flags);
+ brcmf_fws_lock(fws);
if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
fws->borrow_defer_timestamp = jiffies +
BRCMF_FWS_BORROW_DEFER_PERIOD;
@@ -1790,7 +1788,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
}
brcmu_pkt_buf_free_skb(skb);
}
- brcmf_fws_unlock(drvr, flags);
+ brcmf_fws_unlock(fws);
return 0;
}
@@ -1825,17 +1823,16 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
void brcmf_fws_del_interface(struct brcmf_if *ifp)
{
struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
- ulong flags;
if (!entry)
return;
- brcmf_fws_lock(ifp->drvr, flags);
+ brcmf_fws_lock(ifp->drvr->fws);
ifp->fws_desc = NULL;
brcmf_dbg(TRACE, "deleting %s\n", entry->name);
brcmf_fws_macdesc_deinit(entry);
brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
- brcmf_fws_unlock(ifp->drvr, flags);
+ brcmf_fws_unlock(ifp->drvr->fws);
}
static void brcmf_fws_dequeue_worker(struct work_struct *worker)
@@ -1843,7 +1840,6 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
struct brcmf_fws_info *fws;
struct brcmf_pub *drvr;
struct sk_buff *skb;
- ulong flags;
int fifo;
u32 hslot;
u32 ifidx;
@@ -1852,7 +1848,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
drvr = fws->drvr;
- brcmf_fws_lock(drvr, flags);
+ brcmf_fws_lock(fws);
for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
fifo--) {
if (!brcmf_fws_fc_active(fws)) {
@@ -1865,7 +1861,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
INDEX);
brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
/* Use bus module to send data frame */
+ brcmf_fws_unlock(fws);
ret = brcmf_bus_txdata(drvr->bus_if, skb);
+ brcmf_fws_lock(fws);
if (ret < 0)
brcmf_txfinalize(drvr, skb, false);
if (fws->bus_flow_blocked)
@@ -1900,7 +1898,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
}
}
}
- brcmf_fws_unlock(drvr, flags);
+ brcmf_fws_unlock(fws);
}
int brcmf_fws_init(struct brcmf_pub *drvr)
@@ -1909,8 +1907,6 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
int rc;
- spin_lock_init(&drvr->fws_spinlock);
-
drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL);
if (!drvr->fws) {
rc = -ENOMEM;
@@ -1918,6 +1914,9 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
}
fws = drvr->fws;
+
+ spin_lock_init(&fws->spinlock);
+
/* set linkage back */
fws->drvr = drvr;
fws->fcmode = fcmode;
@@ -1986,7 +1985,6 @@ fail:
void brcmf_fws_deinit(struct brcmf_pub *drvr)
{
struct brcmf_fws_info *fws = drvr->fws;
- ulong flags;
if (!fws)
return;
@@ -1995,10 +1993,10 @@ void brcmf_fws_deinit(struct brcmf_pub *drvr)
destroy_workqueue(drvr->fws->fws_wq);
/* cleanup */
- brcmf_fws_lock(drvr, flags);
+ brcmf_fws_lock(fws);
brcmf_fws_cleanup(fws, -1);
drvr->fws = NULL;
- brcmf_fws_unlock(drvr, flags);
+ brcmf_fws_unlock(fws);
/* free top structure */
kfree(fws);
@@ -2014,17 +2012,16 @@ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
{
- ulong flags;
u32 hslot;
if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_TIM) {
brcmu_pkt_buf_free_skb(skb);
return;
}
- brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_lock(fws);
hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0);
- brcmf_fws_unlock(fws->drvr, flags);
+ brcmf_fws_unlock(fws);
}
void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)
--
1.8.1.3
^ permalink raw reply related
* [PATCH 11/12] brcmfmac: use configurable sdio bus header length for tx packet
From: Arend van Spriel @ 2013-08-10 10:27 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Franky Lin, Arend van Spriel
In-Reply-To: <1376130450-29746-1-git-send-email-arend@broadcom.com>
From: Franky Lin <frankyl@broadcom.com>
Host tx glomming require an extended hardware sdio bus header to store
information for dongle. Introduce a variable in struct brcmf_sdio to replace
macro SDPCM_HDRLEN
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 30 ++++++++++++----------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 02ab5cd..1aa75d5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -461,6 +461,8 @@ struct brcmf_sdio {
struct brcmf_sdio_count sdcnt;
bool sr_enabled; /* SaveRestore enabled */
bool sleeping; /* SDIO bus sleeping */
+
+ u8 tx_hdrlen; /* sdio bus header length for tx packet */
};
/* clkstate */
@@ -1025,7 +1027,6 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
#define SDPCM_HWHDR_LEN 4
#define SDPCM_SWHDR_LEN 8
#define SDPCM_HDRLEN (SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN)
-#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN)
/* software header */
#define SDPCM_SEQ_MASK 0x000000ff
#define SDPCM_SEQ_WRAP 256
@@ -1838,7 +1839,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
}
skb_push(pkt_next, head_pad);
dat_buf = (u8 *)(pkt_next->data);
- memset(dat_buf, 0, head_pad + SDPCM_HDRLEN);
+ memset(dat_buf, 0, head_pad + bus->tx_hdrlen);
}
/* Check tail padding */
@@ -1874,7 +1875,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
else
hd_info.len = pkt_next->len - tail_pad;
hd_info.channel = chan;
- hd_info.dat_offset = head_pad + SDPCM_HDRLEN;
+ hd_info.dat_offset = head_pad + bus->tx_hdrlen;
brcmf_sdio_hdpack(bus, dat_buf, &hd_info);
if (BRCMF_BYTES_ON() &&
@@ -1882,7 +1883,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
(BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)))
brcmf_dbg_hex_dump(true, pkt_next, hd_info.len, "Tx Frame:\n");
else if (BRCMF_HDRS_ON())
- brcmf_dbg_hex_dump(true, pkt_next, head_pad + SDPCM_HDRLEN,
+ brcmf_dbg_hex_dump(true, pkt_next, head_pad + bus->tx_hdrlen,
"Tx Header:\n");
return 0;
@@ -1989,7 +1990,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
u32 intstatus = 0;
int ret = 0, prec_out;
uint cnt = 0;
- uint datalen;
u8 tx_prec_map;
brcmf_dbg(TRACE, "Enter\n");
@@ -2005,7 +2005,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
break;
}
spin_unlock_bh(&bus->txqlock);
- datalen = pkt->len - SDPCM_HDRLEN;
ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL);
@@ -2392,7 +2391,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
datalen = pkt->len;
/* Add space for the header */
- skb_push(pkt, SDPCM_HDRLEN);
+ skb_push(pkt, bus->tx_hdrlen);
/* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
prec = prio2prec((pkt->priority & PRIOMASK));
@@ -2405,7 +2404,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
/* Priority based enq */
spin_lock_irqsave(&bus->txqlock, flags);
if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
- skb_pull(pkt, SDPCM_HDRLEN);
+ skb_pull(pkt, bus->tx_hdrlen);
brcmf_err("out of bus->txq !!!\n");
ret = -ENOSR;
} else {
@@ -2566,8 +2565,8 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
brcmf_dbg(TRACE, "Enter\n");
/* Back the pointer to make a room for bus header */
- frame = msg - SDPCM_HDRLEN;
- len = (msglen += SDPCM_HDRLEN);
+ frame = msg - bus->tx_hdrlen;
+ len = (msglen += bus->tx_hdrlen);
/* Add alignment padding (optional for ctl frames) */
doff = ((unsigned long)frame % BRCMF_SDALIGN);
@@ -2575,10 +2574,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
frame -= doff;
len += doff;
msglen += doff;
- memset(frame, 0, doff + SDPCM_HDRLEN);
+ memset(frame, 0, doff + bus->tx_hdrlen);
}
/* precondition: doff < BRCMF_SDALIGN */
- doff += SDPCM_HDRLEN;
+ doff += bus->tx_hdrlen;
/* Round send length to next SDIO block */
if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
@@ -3895,8 +3894,11 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
bus->sdiodev->bus_if->chip = bus->ci->chip;
bus->sdiodev->bus_if->chiprev = bus->ci->chiprev;
- /* Attach to the brcmf/OS/network interface */
- ret = brcmf_attach(SDPCM_RESERVE, bus->sdiodev->dev);
+ /* default sdio bus header length for tx packet */
+ bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
+
+ /* Attach to the common layer, reserve hdr space */
+ ret = brcmf_attach(bus->tx_hdrlen, bus->sdiodev->dev);
if (ret != 0) {
brcmf_err("brcmf_attach failed\n");
goto fail;
--
1.8.1.3
^ permalink raw reply related
* [PATCH 08/12] brcmfmac: abstract tx packet processing functions
From: Arend van Spriel @ 2013-08-10 10:27 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Franky Lin, Arend van Spriel
In-Reply-To: <1376130450-29746-1-git-send-email-arend@broadcom.com>
From: Franky Lin <frankyl@broadcom.com>
Abstract brcmf_sdio_txpkt_prep and brcmf_sdio_txpkt_postp as a preparation
of chained tx packets for host side tx glomming.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 16 +-
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 237 +++++++++++++++------
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 2 +-
include/linux/platform_data/brcmfmac-sdio.h | 6 +
4 files changed, 183 insertions(+), 78 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index e3f3c48..e13b1a6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -592,6 +592,7 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, u8 *buf, uint nbytes)
{
struct sk_buff *mypkt;
+ struct sk_buff_head pktq;
int err;
mypkt = brcmu_pkt_buf_get_skb(nbytes);
@@ -602,7 +603,10 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
}
memcpy(mypkt->data, buf, nbytes);
- err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, mypkt);
+ __skb_queue_head_init(&pktq);
+ __skb_queue_tail(&pktq, mypkt);
+ err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, &pktq);
+ __skb_dequeue_tail(&pktq);
brcmu_pkt_buf_free_skb(mypkt);
return err;
@@ -611,22 +615,18 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
int
brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, struct sk_buff *pkt)
+ uint flags, struct sk_buff_head *pktq)
{
uint width;
int err = 0;
- struct sk_buff_head pkt_list;
brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
- fn, addr, pkt->len);
+ fn, addr, pktq->qlen);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
brcmf_sdio_addrprep(sdiodev, width, &addr);
- skb_queue_head_init(&pkt_list);
- skb_queue_tail(&pkt_list, pkt);
- err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, &pkt_list);
- skb_dequeue_tail(&pkt_list);
+ err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq);
return err;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index db31312..aa4caca 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -510,7 +510,6 @@ struct brcmf_sdio {
#ifdef DEBUG
static int qcount[NUMPRIO];
-static int tx_packets[NUMPRIO];
#endif /* DEBUG */
#define DEFAULT_SDIO_DRIVE_STRENGTH 6 /* in milliamps */
@@ -1759,85 +1758,185 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
return;
}
+/* flag marking a dummy skb added for DMA alignment requirement */
+#define DUMMY_SKB_FLAG 0x10000
+/* bit mask of data length chopped from the previous packet */
+#define DUMMY_SKB_CHOP_LEN_MASK 0xffff
+/**
+ * brcmf_sdio_txpkt_prep - packet preparation for transmit
+ * @bus: brcmf_sdio structure pointer
+ * @pktq: packet list pointer
+ * @chan: virtual channel to transmit the packet
+ *
+ * Processes to be applied to the packet
+ * - Align data buffer pointer
+ * - Align data buffer length
+ * - Prepare header
+ * Return: negative value if there is error
+ */
+static int
+brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
+ uint chan)
+{
+ u16 head_pad, tail_pad, tail_chop, pkt_len;
+ u16 head_align, sg_align;
+ u32 sw_header;
+ int ntail;
+ struct sk_buff *pkt_next, *pkt_new;
+ u8 *dat_buf;
+ unsigned blksize = bus->sdiodev->func[SDIO_FUNC_2]->cur_blksize;
+
+ /* SDIO ADMA requires at least 32 bit alignment */
+ head_align = 4;
+ sg_align = 4;
+ if (bus->sdiodev->pdata) {
+ head_align = bus->sdiodev->pdata->sd_head_align > 4 ?
+ bus->sdiodev->pdata->sd_head_align : 4;
+ sg_align = bus->sdiodev->pdata->sd_sgentry_align > 4 ?
+ bus->sdiodev->pdata->sd_sgentry_align : 4;
+ }
+ /* sg entry alignment should be a divisor of block size */
+ WARN_ON(blksize % sg_align);
+
+ pkt_next = pktq->next;
+ dat_buf = (u8 *)(pkt_next->data);
+
+ /* Check head padding */
+ head_pad = ((unsigned long)dat_buf % head_align);
+ if (head_pad) {
+ if (skb_headroom(pkt_next) < head_pad) {
+ bus->sdiodev->bus_if->tx_realloc++;
+ head_pad = 0;
+ if (skb_cow(pkt_next, head_pad))
+ return -ENOMEM;
+ }
+ skb_push(pkt_next, head_pad);
+ dat_buf = (u8 *)(pkt_next->data);
+ memset(dat_buf, 0, head_pad + SDPCM_HDRLEN);
+ }
+
+ /* Check tail padding */
+ pkt_new = NULL;
+ tail_chop = pkt_next->len % sg_align;
+ tail_pad = sg_align - tail_chop;
+ tail_pad += blksize - (pkt_next->len + tail_pad) % blksize;
+ if (skb_tailroom(pkt_next) < tail_pad && pkt_next->len > blksize) {
+ pkt_new = brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
+ if (pkt_new == NULL)
+ return -ENOMEM;
+ memcpy(pkt_new->data,
+ pkt_next->data + pkt_next->len - tail_chop,
+ tail_chop);
+ *(u32 *)(pkt_new->cb) = DUMMY_SKB_FLAG + tail_chop;
+ skb_trim(pkt_next, pkt_next->len - tail_chop);
+ __skb_queue_after(pktq, pkt_next, pkt_new);
+ } else {
+ ntail = pkt_next->data_len + tail_pad -
+ (pkt_next->end - pkt_next->tail);
+ if (skb_cloned(pkt_next) || ntail > 0)
+ if (pskb_expand_head(pkt_next, 0, ntail, GFP_ATOMIC))
+ return -ENOMEM;
+ if (skb_linearize(pkt_next))
+ return -ENOMEM;
+ dat_buf = (u8 *)(pkt_next->data);
+ __skb_put(pkt_next, tail_pad);
+ }
+
+ /* Now prep the header */
+ /* 4 bytes hardware header (frame tag)
+ * Byte 0~1: Frame length
+ * Byte 2~3: Checksum, bit-wise inverse of frame length
+ */
+ if (pkt_new)
+ pkt_len = pkt_next->len + tail_chop;
+ else
+ pkt_len = pkt_next->len - tail_pad;
+ *(__le16 *)dat_buf = cpu_to_le16(pkt_len);
+ *(((__le16 *)dat_buf) + 1) = cpu_to_le16(~pkt_len);
+ /* 8 bytes software header
+ * Byte 0: Tx sequence number
+ * Byte 1: 4 MSB Channel number
+ * Byte 2: Reserved
+ * Byte 3: Data offset
+ * Byte 4~7: Reserved
+ */
+ sw_header = bus->tx_seq;
+ sw_header |= ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK);
+ sw_header |= ((head_pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) &
+ SDPCM_DOFFSET_MASK;
+ *(((__le32 *)dat_buf) + 1) = cpu_to_le32(sw_header);
+ *(((__le32 *)dat_buf) + 2) = 0;
+
+ if (BRCMF_BYTES_ON() &&
+ ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) ||
+ (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)))
+ brcmf_dbg_hex_dump(true, pkt_next, pkt_len, "Tx Frame:\n");
+ else if (BRCMF_HDRS_ON())
+ brcmf_dbg_hex_dump(true, pkt_next, head_pad + SDPCM_HDRLEN,
+ "Tx Header:\n");
+
+ return 0;
+}
+
+/**
+ * brcmf_sdio_txpkt_postp - packet post processing for transmit
+ * @bus: brcmf_sdio structure pointer
+ * @pktq: packet list pointer
+ *
+ * Processes to be applied to the packet
+ * - Remove head padding
+ * - Remove tail padding
+ */
+static void
+brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq)
+{
+ u8 *hdr;
+ u32 dat_offset;
+ u32 dummy_flags, chop_len;
+ struct sk_buff *pkt_next, *tmp, *pkt_prev;
+
+ skb_queue_walk_safe(pktq, pkt_next, tmp) {
+ dummy_flags = *(u32 *)(pkt_next->cb);
+ if (dummy_flags & DUMMY_SKB_FLAG) {
+ chop_len = dummy_flags & DUMMY_SKB_CHOP_LEN_MASK;
+ if (chop_len) {
+ pkt_prev = pkt_next->prev;
+ memcpy(pkt_prev->data + pkt_prev->len,
+ pkt_next->data, chop_len);
+ skb_put(pkt_prev, chop_len);
+ }
+ __skb_unlink(pkt_next, pktq);
+ brcmu_pkt_buf_free_skb(pkt_next);
+ } else {
+ hdr = pkt_next->data + SDPCM_FRAMETAG_LEN;
+ dat_offset = le32_to_cpu(*(__le32 *)hdr);
+ dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >>
+ SDPCM_DOFFSET_SHIFT;
+ skb_pull(pkt_next, dat_offset);
+ }
+ }
+}
+
/* Writes a HW/SW header into the packet and sends it. */
/* Assumes: (a) header space already there, (b) caller holds lock */
static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
uint chan)
{
int ret;
- u8 *frame;
- u16 len, pad = 0;
- u32 swheader;
int i;
+ struct sk_buff_head localq;
brcmf_dbg(TRACE, "Enter\n");
- frame = (u8 *) (pkt->data);
-
- /* Add alignment padding, allocate new packet if needed */
- pad = ((unsigned long)frame % BRCMF_SDALIGN);
- if (pad) {
- if (skb_headroom(pkt) < pad) {
- brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
- skb_headroom(pkt), pad);
- bus->sdiodev->bus_if->tx_realloc++;
- ret = skb_cow(pkt, BRCMF_SDALIGN);
- if (ret)
- goto done;
- pad = ((unsigned long)frame % BRCMF_SDALIGN);
- }
- skb_push(pkt, pad);
- frame = (u8 *) (pkt->data);
- memset(frame, 0, pad + SDPCM_HDRLEN);
- }
- /* precondition: pad < BRCMF_SDALIGN */
-
- /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
- len = (u16) (pkt->len);
- *(__le16 *) frame = cpu_to_le16(len);
- *(((__le16 *) frame) + 1) = cpu_to_le16(~len);
-
- /* Software tag: channel, sequence number, data offset */
- swheader =
- ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
- (((pad +
- SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
-
- *(((__le32 *) frame) + 1) = cpu_to_le32(swheader);
- *(((__le32 *) frame) + 2) = 0;
-
-#ifdef DEBUG
- tx_packets[pkt->priority]++;
-#endif
-
- brcmf_dbg_hex_dump(BRCMF_BYTES_ON() &&
- ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) ||
- (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)),
- frame, len, "Tx Frame:\n");
- brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() &&
- ((BRCMF_CTL_ON() &&
- chan == SDPCM_CONTROL_CHANNEL) ||
- (BRCMF_DATA_ON() &&
- chan != SDPCM_CONTROL_CHANNEL))) &&
- BRCMF_HDRS_ON(),
- frame, min_t(u16, len, 16), "TxHdr:\n");
-
- /* Raise len to next SDIO block to eliminate tail command */
- if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- u16 pad = bus->blocksize - (len % bus->blocksize);
- if ((pad <= bus->roundup) && (pad < bus->blocksize))
- len += pad;
- } else if (len % BRCMF_SDALIGN) {
- len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
- }
-
- /* Some controllers have trouble with odd bytes -- round to even */
- if (len & (ALIGNMENT - 1))
- len = roundup(len, ALIGNMENT);
+ __skb_queue_head_init(&localq);
+ __skb_queue_tail(&localq, pkt);
+ ret = brcmf_sdio_txpkt_prep(bus, &localq, chan);
+ if (ret)
+ goto done;
sdio_claim_host(bus->sdiodev->func[1]);
ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
- SDIO_FUNC_2, F2SYNC, pkt);
+ SDIO_FUNC_2, F2SYNC, &localq);
bus->sdcnt.f2txdata++;
if (ret < 0) {
@@ -1868,8 +1967,8 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
done:
- /* restore pkt buffer pointer before calling tx complete routine */
- skb_pull(pkt, SDPCM_HDRLEN + pad);
+ brcmf_sdio_txpkt_postp(bus, &localq);
+ __skb_dequeue_tail(&localq);
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0);
return ret;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 09786a5..2b5407f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -208,7 +208,7 @@ extern int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
*/
extern int
brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, struct sk_buff *pkt);
+ uint flags, struct sk_buff_head *pktq);
extern int
brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, u8 *buf, uint nbytes);
diff --git a/include/linux/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h
index b717499..e75dcbf 100644
--- a/include/linux/platform_data/brcmfmac-sdio.h
+++ b/include/linux/platform_data/brcmfmac-sdio.h
@@ -94,6 +94,10 @@ void __init brcmfmac_init_pdata(void)
* Set this to true if the SDIO host controller has higher align requirement
* than 32 bytes for each scatterlist item.
*
+ * sd_head_align: alignment requirement for start of data buffer
+ *
+ * sd_sgentry_align: length alignment requirement for each sg entry
+ *
* power_on: This function is called by the brcmfmac when the module gets
* loaded. This can be particularly useful for low power devices. The platform
* spcific routine may for example decide to power up the complete device.
@@ -121,6 +125,8 @@ struct brcmfmac_sdio_platform_data {
unsigned int oob_irq_nr;
unsigned long oob_irq_flags;
bool broken_sg_support;
+ unsigned short sd_head_align;
+ unsigned short sd_sgentry_align;
void (*power_on)(void);
void (*power_off)(void);
void (*reset)(void);
--
1.8.1.3
^ permalink raw reply related
* [PATCH 06/12] brcmfmac: ignore IF event if firmware indicates it
From: Arend van Spriel @ 2013-08-10 10:27 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1376130450-29746-1-git-send-email-arend@broadcom.com>
Not every IF event from the firmware needs to result in a
related interface, netdev or wdev, on the host. This is
indicated in the event message. Handle that flag and effectively
ignore the firmware event.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 2 ++
drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 1273dfd..2eb9e64 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -194,6 +194,8 @@
#define BRCMF_E_IF_DEL 2
#define BRCMF_E_IF_CHANGE 3
+#define BRCMF_E_IF_FLAG_NOIF 1
+
#define BRCMF_E_IF_ROLE_STA 0
#define BRCMF_E_IF_ROLE_AP 1
#define BRCMF_E_IF_ROLE_WDS 2
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
index 83ee53a..fad77dd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -185,6 +185,10 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
ifevent->action, ifevent->ifidx, ifevent->bssidx,
ifevent->flags, ifevent->role);
+ if (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) {
+ brcmf_dbg(EVENT, "event can be ignored\n");
+ return;
+ }
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
brcmf_err("invalid interface index: %u\n",
ifevent->ifidx);
--
1.8.1.3
^ permalink raw reply related
* [PATCH 09/12] brcmfmac: remove align from brcmf_bus structure
From: Arend van Spriel @ 2013-08-10 10:27 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Franky Lin, Arend van Spriel
In-Reply-To: <1376130450-29746-1-git-send-email-arend@broadcom.com>
From: Franky Lin <frankyl@broadcom.com>
remove align from brcmf_bus since it is only used by sdio bus layer internally
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
.../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 1 -
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | 2 --
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 25 +++++++++++++++-------
3 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 289e386..64f4a2b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -350,7 +350,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
sdiodev->bus_if = bus_if;
bus_if->bus_priv.sdio = sdiodev;
- bus_if->align = BRCMF_SDALIGN;
dev_set_drvdata(&func->dev, bus_if);
dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
sdiodev->dev = &sdiodev->func[1]->dev;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 9249b6d..f7c1985 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -69,7 +69,6 @@ struct brcmf_bus_ops {
* @maxctl: maximum size for rxctl request message.
* @tx_realloc: number of tx packets realloced for headroom.
* @dstats: dongle-based statistical data.
- * @align: alignment requirement for the bus.
* @dcmd_list: bus/device specific dongle initialization commands.
* @chip: device identifier of the dongle chip.
* @chiprev: revision of the dongle chip.
@@ -84,7 +83,6 @@ struct brcmf_bus {
enum brcmf_bus_state state;
uint maxctl;
unsigned long tx_realloc;
- u8 align;
u32 chip;
u32 chiprev;
struct list_head dcmd_list;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index aa4caca..2563875 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1166,7 +1166,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
{
u16 dlen, totlen;
u8 *dptr, num = 0;
-
+ u32 align = 0;
u16 sublen;
struct sk_buff *pfirst, *pnext;
@@ -1181,6 +1181,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
brcmf_dbg(SDIO, "start: glomd %p glom %p\n",
bus->glomd, skb_peek(&bus->glom));
+ if (bus->sdiodev->pdata)
+ align = bus->sdiodev->pdata->sd_sgentry_align;
+ if (align < 4)
+ align = 4;
+
/* If there's a descriptor, generate the packet chain */
if (bus->glomd) {
pfirst = pnext = NULL;
@@ -1204,9 +1209,9 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
pnext = NULL;
break;
}
- if (sublen % BRCMF_SDALIGN) {
+ if (sublen % align) {
brcmf_err("sublen %d not multiple of %d\n",
- sublen, BRCMF_SDALIGN);
+ sublen, align);
}
totlen += sublen;
@@ -1219,7 +1224,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
}
/* Allocate/chain packet for next subframe */
- pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN);
+ pnext = brcmu_pkt_buf_get_skb(sublen + align);
if (pnext == NULL) {
brcmf_err("bcm_pkt_buf_get_skb failed, num %d len %d\n",
num, sublen);
@@ -1228,7 +1233,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
skb_queue_tail(&bus->glom, pnext);
/* Adhere to start alignment requirements */
- pkt_align(pnext, sublen, BRCMF_SDALIGN);
+ pkt_align(pnext, sublen, align);
}
/* If all allocations succeeded, save packet chain
@@ -3832,7 +3837,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
struct brcmf_sdio *bus;
struct brcmf_bus_dcmd *dlst;
u32 dngl_txglom;
- u32 dngl_txglomalign;
+ u32 txglomalign = 0;
u8 idx;
brcmf_dbg(TRACE, "Enter\n");
@@ -3926,9 +3931,13 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
dlst->param_len = sizeof(u32);
} else {
/* otherwise, set txglomalign */
- dngl_txglomalign = bus->sdiodev->bus_if->align;
+ if (sdiodev->pdata)
+ txglomalign = sdiodev->pdata->sd_sgentry_align;
+ /* SDIO ADMA requires at least 32 bit alignment */
+ if (txglomalign < 4)
+ txglomalign = 4;
dlst->name = "bus:txglomalign";
- dlst->param = (char *)&dngl_txglomalign;
+ dlst->param = (char *)&txglomalign;
dlst->param_len = sizeof(u32);
}
list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list);
--
1.8.1.3
^ permalink raw reply related
* [PATCH 10/12] brcmfmac: streamline sdio bus header code
From: Arend van Spriel @ 2013-08-10 10:27 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Franky Lin, Arend van Spriel
In-Reply-To: <1376130450-29746-1-git-send-email-arend@broadcom.com>
From: Franky Lin <frankyl@broadcom.com>
Streamlining sdio bus specific header related code as preparation for host
tx glomming
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 243 ++++++++++-----------
1 file changed, 120 insertions(+), 123 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 2563875..02ab5cd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -201,13 +201,6 @@ struct rte_console {
#define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */
#define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */
-/* HW frame tag */
-#define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */
-
-/* Total length of frame header for dongle protocol */
-#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
-#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN)
-
/*
* Software allocation of To SB Mailbox resources
*/
@@ -250,38 +243,6 @@ struct rte_console {
/* Current protocol version */
#define SDPCM_PROT_VERSION 4
-/* SW frame header */
-#define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff)
-
-#define SDPCM_CHANNEL_MASK 0x00000f00
-#define SDPCM_CHANNEL_SHIFT 8
-#define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f)
-
-#define SDPCM_NEXTLEN_OFFSET 2
-
-/* Data Offset from SOF (HW Tag, SW Tag, Pad) */
-#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */
-#define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff)
-#define SDPCM_DOFFSET_MASK 0xff000000
-#define SDPCM_DOFFSET_SHIFT 24
-#define SDPCM_FCMASK_OFFSET 4 /* Flow control */
-#define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff)
-#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */
-#define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff)
-
-#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */
-
-/* logical channel numbers */
-#define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */
-#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */
-#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */
-#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */
-#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */
-
-#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */
-
-#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80)
-
/*
* Shared structure between dongle and the host.
* The structure contains pointers to trap or assert information.
@@ -396,8 +357,8 @@ struct sdpcm_shared_le {
__le32 brpt_addr;
};
-/* SDIO read frame info */
-struct brcmf_sdio_read {
+/* dongle SDIO bus specific header info */
+struct brcmf_sdio_hdrinfo {
u8 seq_num;
u8 channel;
u16 len;
@@ -431,7 +392,7 @@ struct brcmf_sdio {
u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN];
u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */
u8 rx_seq; /* Receive sequence number (expected) */
- struct brcmf_sdio_read cur_read;
+ struct brcmf_sdio_hdrinfo cur_read;
/* info of current read frame */
bool rxskip; /* Skip receive (awaiting NAK ACK) */
bool rxpending; /* Data frame pending in dongle */
@@ -1042,18 +1003,64 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
}
}
-static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
- struct brcmf_sdio_read *rd,
- enum brcmf_sdio_frmtype type)
+/**
+ * brcmfmac sdio bus specific header
+ * This is the lowest layer header wrapped on the packets transmitted between
+ * host and WiFi dongle which contains information needed for SDIO core and
+ * firmware
+ *
+ * It consists of 2 parts: hw header and software header
+ * hardware header (frame tag) - 4 bytes
+ * Byte 0~1: Frame length
+ * Byte 2~3: Checksum, bit-wise inverse of frame length
+ * software header - 8 bytes
+ * Byte 0: Rx/Tx sequence number
+ * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag
+ * Byte 2: Length of next data frame, reserved for Tx
+ * Byte 3: Data offset
+ * Byte 4: Flow control bits, reserved for Tx
+ * Byte 5: Maximum Sequence number allowed by firmware for Tx, N/A for Tx packet
+ * Byte 6~7: Reserved
+ */
+#define SDPCM_HWHDR_LEN 4
+#define SDPCM_SWHDR_LEN 8
+#define SDPCM_HDRLEN (SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN)
+#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN)
+/* software header */
+#define SDPCM_SEQ_MASK 0x000000ff
+#define SDPCM_SEQ_WRAP 256
+#define SDPCM_CHANNEL_MASK 0x00000f00
+#define SDPCM_CHANNEL_SHIFT 8
+#define SDPCM_CONTROL_CHANNEL 0 /* Control */
+#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication */
+#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv */
+#define SDPCM_GLOM_CHANNEL 3 /* Coalesced packets */
+#define SDPCM_TEST_CHANNEL 15 /* Test/debug packets */
+#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80)
+#define SDPCM_NEXTLEN_MASK 0x00ff0000
+#define SDPCM_NEXTLEN_SHIFT 16
+#define SDPCM_DOFFSET_MASK 0xff000000
+#define SDPCM_DOFFSET_SHIFT 24
+#define SDPCM_FCMASK_MASK 0x000000ff
+#define SDPCM_WINDOW_MASK 0x0000ff00
+#define SDPCM_WINDOW_SHIFT 8
+
+static inline u8 brcmf_sdio_getdatoffset(u8 *swheader)
+{
+ u32 hdrvalue;
+ hdrvalue = *(u32 *)swheader;
+ return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT);
+}
+
+static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
+ struct brcmf_sdio_hdrinfo *rd,
+ enum brcmf_sdio_frmtype type)
{
u16 len, checksum;
u8 rx_seq, fc, tx_seq_max;
+ u32 swheader;
- /*
- * 4 bytes hardware header (frame tag)
- * Byte 0~1: Frame length
- * Byte 2~3: Checksum, bit-wise inverse of frame length
- */
+ /* hw header */
len = get_unaligned_le16(header);
checksum = get_unaligned_le16(header + sizeof(u16));
/* All zero means no more to read */
@@ -1082,24 +1089,16 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
}
rd->len = len;
- /*
- * 8 bytes hardware header
- * Byte 0: Rx sequence number
- * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag
- * Byte 2: Length of next data frame
- * Byte 3: Data offset
- * Byte 4: Flow control bits
- * Byte 5: Maximum Sequence number allow for Tx
- * Byte 6~7: Reserved
- */
- if (type == BRCMF_SDIO_FT_SUPER &&
- SDPCM_GLOMDESC(&header[SDPCM_FRAMETAG_LEN])) {
+ /* software header */
+ header += SDPCM_HWHDR_LEN;
+ swheader = le32_to_cpu(*(__le32 *)header);
+ if (type == BRCMF_SDIO_FT_SUPER && SDPCM_GLOMDESC(header)) {
brcmf_err("Glom descriptor found in superframe head\n");
rd->len = 0;
return -EINVAL;
}
- rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]);
- rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]);
+ rx_seq = (u8)(swheader & SDPCM_SEQ_MASK);
+ rd->channel = (swheader & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT;
if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL &&
type != BRCMF_SDIO_FT_SUPER) {
brcmf_err("HW header length too long\n");
@@ -1119,7 +1118,7 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
rd->len = 0;
return -EINVAL;
}
- rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]);
+ rd->dat_offset = brcmf_sdio_getdatoffset(header);
if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
brcmf_err("seq %d: bad data offset\n", rx_seq);
bus->sdcnt.rx_badhdr++;
@@ -1136,14 +1135,15 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
/* no need to check the reset for subframe */
if (type == BRCMF_SDIO_FT_SUB)
return 0;
- rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
+ rd->len_nxtfrm = (swheader & SDPCM_NEXTLEN_MASK) >> SDPCM_NEXTLEN_SHIFT;
if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) {
/* only warm for NON glom packet */
if (rd->channel != SDPCM_GLOM_CHANNEL)
brcmf_err("seq %d: next length error\n", rx_seq);
rd->len_nxtfrm = 0;
}
- fc = SDPCM_FCMASK_VALUE(&header[SDPCM_FRAMETAG_LEN]);
+ swheader = le32_to_cpu(*(__le32 *)(header + 4));
+ fc = swheader & SDPCM_FCMASK_MASK;
if (bus->flowcontrol != fc) {
if (~bus->flowcontrol & fc)
bus->sdcnt.fc_xoff++;
@@ -1152,7 +1152,7 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
bus->sdcnt.fc_rcvd++;
bus->flowcontrol = fc;
}
- tx_seq_max = SDPCM_WINDOW_VALUE(&header[SDPCM_FRAMETAG_LEN]);
+ tx_seq_max = (swheader & SDPCM_WINDOW_MASK) >> SDPCM_WINDOW_SHIFT;
if ((u8)(tx_seq_max - bus->tx_seq) > 0x40) {
brcmf_err("seq %d: max tx seq number error\n", rx_seq);
tx_seq_max = bus->tx_seq + 2;
@@ -1162,6 +1162,28 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
return 0;
}
+static inline void brcmf_sdio_update_hwhdr(u8 *header, u16 frm_length)
+{
+ *(__le16 *)header = cpu_to_le16(frm_length);
+ *(((__le16 *)header) + 1) = cpu_to_le16(~frm_length);
+}
+
+static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header,
+ struct brcmf_sdio_hdrinfo *hd_info)
+{
+ u32 sw_header;
+
+ brcmf_sdio_update_hwhdr(header, hd_info->len);
+
+ sw_header = bus->tx_seq;
+ sw_header |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) &
+ SDPCM_CHANNEL_MASK;
+ sw_header |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) &
+ SDPCM_DOFFSET_MASK;
+ *(((__le32 *)header) + 1) = cpu_to_le32(sw_header);
+ *(((__le32 *)header) + 2) = 0;
+}
+
static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
{
u16 dlen, totlen;
@@ -1173,7 +1195,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
int errcode;
u8 doff, sfdoff;
- struct brcmf_sdio_read rd_new;
+ struct brcmf_sdio_hdrinfo rd_new;
/* If packets, issue read(s) and send up packet chain */
/* Return sequence numbers consumed? */
@@ -1309,8 +1331,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
rd_new.seq_num = rxseq;
rd_new.len = dlen;
sdio_claim_host(bus->sdiodev->func[1]);
- errcode = brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
- BRCMF_SDIO_FT_SUPER);
+ errcode = brcmf_sdio_hdparse(bus, pfirst->data, &rd_new,
+ BRCMF_SDIO_FT_SUPER);
sdio_release_host(bus->sdiodev->func[1]);
bus->cur_read.len = rd_new.len_nxtfrm << 4;
@@ -1328,8 +1350,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
rd_new.len = pnext->len;
rd_new.seq_num = rxseq++;
sdio_claim_host(bus->sdiodev->func[1]);
- errcode = brcmf_sdio_hdparser(bus, pnext->data, &rd_new,
- BRCMF_SDIO_FT_SUB);
+ errcode = brcmf_sdio_hdparse(bus, pnext->data, &rd_new,
+ BRCMF_SDIO_FT_SUB);
sdio_release_host(bus->sdiodev->func[1]);
brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
pnext->data, 32, "subframe:\n");
@@ -1361,7 +1383,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
dptr = (u8 *) (pfirst->data);
sublen = get_unaligned_le16(dptr);
- doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+ doff = brcmf_sdio_getdatoffset(&dptr[SDPCM_HWHDR_LEN]);
brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(),
dptr, pfirst->len,
@@ -1539,7 +1561,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
uint rxleft = 0; /* Remaining number of frames allowed */
int ret; /* Return code from calls */
uint rxcount = 0; /* Total frames read */
- struct brcmf_sdio_read *rd = &bus->cur_read, rd_new;
+ struct brcmf_sdio_hdrinfo *rd = &bus->cur_read, rd_new;
u8 head_read = 0;
brcmf_dbg(TRACE, "Enter\n");
@@ -1587,8 +1609,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
bus->rxhdr, SDPCM_HDRLEN,
"RxHdr:\n");
- if (brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
- BRCMF_SDIO_FT_NORMAL)) {
+ if (brcmf_sdio_hdparse(bus, bus->rxhdr, rd,
+ BRCMF_SDIO_FT_NORMAL)) {
sdio_release_host(bus->sdiodev->func[1]);
if (!bus->rxpending)
break;
@@ -1652,8 +1674,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
rd_new.seq_num = rd->seq_num;
sdio_claim_host(bus->sdiodev->func[1]);
- if (brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new,
- BRCMF_SDIO_FT_NORMAL)) {
+ if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new,
+ BRCMF_SDIO_FT_NORMAL)) {
rd->len = 0;
brcmu_pkt_buf_free_skb(pkt);
}
@@ -1697,7 +1719,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
/* Save superframe descriptor and allocate packet frame */
if (rd->channel == SDPCM_GLOM_CHANNEL) {
- if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
+ if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_HWHDR_LEN])) {
brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n",
rd->len);
brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
@@ -1783,13 +1805,12 @@ static int
brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
uint chan)
{
- u16 head_pad, tail_pad, tail_chop, pkt_len;
- u16 head_align, sg_align;
- u32 sw_header;
+ u16 head_pad, tail_pad, tail_chop, head_align, sg_align;
int ntail;
struct sk_buff *pkt_next, *pkt_new;
u8 *dat_buf;
unsigned blksize = bus->sdiodev->func[SDIO_FUNC_2]->cur_blksize;
+ struct brcmf_sdio_hdrinfo hd_info = {0};
/* SDIO ADMA requires at least 32 bit alignment */
head_align = 4;
@@ -1848,34 +1869,18 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
}
/* Now prep the header */
- /* 4 bytes hardware header (frame tag)
- * Byte 0~1: Frame length
- * Byte 2~3: Checksum, bit-wise inverse of frame length
- */
if (pkt_new)
- pkt_len = pkt_next->len + tail_chop;
+ hd_info.len = pkt_next->len + tail_chop;
else
- pkt_len = pkt_next->len - tail_pad;
- *(__le16 *)dat_buf = cpu_to_le16(pkt_len);
- *(((__le16 *)dat_buf) + 1) = cpu_to_le16(~pkt_len);
- /* 8 bytes software header
- * Byte 0: Tx sequence number
- * Byte 1: 4 MSB Channel number
- * Byte 2: Reserved
- * Byte 3: Data offset
- * Byte 4~7: Reserved
- */
- sw_header = bus->tx_seq;
- sw_header |= ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK);
- sw_header |= ((head_pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) &
- SDPCM_DOFFSET_MASK;
- *(((__le32 *)dat_buf) + 1) = cpu_to_le32(sw_header);
- *(((__le32 *)dat_buf) + 2) = 0;
+ hd_info.len = pkt_next->len - tail_pad;
+ hd_info.channel = chan;
+ hd_info.dat_offset = head_pad + SDPCM_HDRLEN;
+ brcmf_sdio_hdpack(bus, dat_buf, &hd_info);
if (BRCMF_BYTES_ON() &&
((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) ||
(BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)))
- brcmf_dbg_hex_dump(true, pkt_next, pkt_len, "Tx Frame:\n");
+ brcmf_dbg_hex_dump(true, pkt_next, hd_info.len, "Tx Frame:\n");
else if (BRCMF_HDRS_ON())
brcmf_dbg_hex_dump(true, pkt_next, head_pad + SDPCM_HDRLEN,
"Tx Header:\n");
@@ -1913,7 +1918,7 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq)
__skb_unlink(pkt_next, pktq);
brcmu_pkt_buf_free_skb(pkt_next);
} else {
- hdr = pkt_next->data + SDPCM_FRAMETAG_LEN;
+ hdr = pkt_next->data + SDPCM_HWHDR_LEN;
dat_offset = le32_to_cpu(*(__le32 *)hdr);
dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >>
SDPCM_DOFFSET_SHIFT;
@@ -1969,7 +1974,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
}
sdio_release_host(bus->sdiodev->func[1]);
if (ret == 0)
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP;
done:
brcmf_sdio_txpkt_postp(bus, &localq);
@@ -2325,7 +2330,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
}
} else {
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP;
}
sdio_release_host(bus->sdiodev->func[1]);
bus->ctrl_frame_stat = false;
@@ -2540,7 +2545,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
return ret;
}
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP;
return ret;
}
@@ -2550,13 +2555,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
{
u8 *frame;
u16 len;
- u32 swheader;
uint retries = 0;
u8 doff = 0;
int ret = -1;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus;
+ struct brcmf_sdio_hdrinfo hd_info = {0};
brcmf_dbg(TRACE, "Enter\n");
@@ -2595,18 +2600,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
brcmf_sdbrcm_bus_sleep(bus, false, false);
sdio_release_host(bus->sdiodev->func[1]);
- /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
- *(__le16 *) frame = cpu_to_le16((u16) msglen);
- *(((__le16 *) frame) + 1) = cpu_to_le16(~msglen);
-
- /* Software tag: channel, sequence number, data offset */
- swheader =
- ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) &
- SDPCM_CHANNEL_MASK)
- | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
- SDPCM_DOFFSET_MASK);
- put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
- put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+ hd_info.len = (u16)msglen;
+ hd_info.channel = SDPCM_CONTROL_CHANNEL;
+ hd_info.dat_offset = doff;
+ brcmf_sdio_hdpack(bus, frame, &hd_info);
if (!data_ok(bus)) {
brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n",
@@ -3856,7 +3853,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
bus->txbound = BRCMF_TXBOUND;
bus->rxbound = BRCMF_RXBOUND;
bus->txminmax = BRCMF_TXMINMAX;
- bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
+ bus->tx_seq = SDPCM_SEQ_WRAP - 1;
INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
--
1.8.1.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox