Update to compat-wireless-2009-05-01
[librecmc/librecmc.git] / package / mac80211 / patches / 540-b43-Add-fw-capabilities.patch
1 Completely untested patch to implement firmware capabilities
2 and automagic QoS-disabling.
3
4
5 --- a/drivers/net/wireless/b43/b43.h
6 +++ b/drivers/net/wireless/b43/b43.h
7 @@ -163,6 +163,7 @@ enum {
8  #define B43_SHM_SH_WLCOREREV           0x0016  /* 802.11 core revision */
9  #define B43_SHM_SH_PCTLWDPOS           0x0008
10  #define B43_SHM_SH_RXPADOFF            0x0034  /* RX Padding data offset (PIO only) */
11 +#define B43_SHM_SH_FWCAPA              0x0042  /* Firmware capabilities (Opensource firmware only) */
12  #define B43_SHM_SH_PHYVER              0x0050  /* PHY version */
13  #define B43_SHM_SH_PHYTYPE             0x0052  /* PHY type */
14  #define B43_SHM_SH_ANTSWAP             0x005C  /* Antenna swap threshold */
15 @@ -297,6 +298,10 @@ enum {
16  #define B43_HF_MLADVW          0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
17  #define B43_HF_PR45960W                0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
18  
19 +/* Firmware capabilities field in SHM (Opensource firmware only) */
20 +#define B43_FWCAPA_HWCRYPTO    0x0001
21 +#define B43_FWCAPA_QOS         0x0002
22 +
23  /* MacFilter offsets. */
24  #define B43_MACFILTER_SELF             0x0000
25  #define B43_MACFILTER_BSSID            0x0003
26 @@ -596,6 +601,13 @@ struct b43_wl {
27         /* Pointer to the ieee80211 hardware data structure */
28         struct ieee80211_hw *hw;
29  
30 +       /* The number of queues that were registered with the mac80211 subsystem
31 +        * initially. This is a backup copy of hw->queues in case hw->queues has
32 +        * to be dynamically lowered at runtime (Firmware does not support QoS).
33 +        * hw->queues has to be restored to the original value before unregistering
34 +        * from the mac80211 subsystem. */
35 +       u16 mac80211_initially_registered_queues;
36 +
37         struct mutex mutex;
38         spinlock_t irq_lock;
39         /* R/W lock for data transmission.
40 @@ -752,6 +764,8 @@ struct b43_wldev {
41         bool dfq_valid;         /* Directed frame queue valid (IBSS PS mode, ATIM) */
42         bool radio_hw_enable;   /* saved state of radio hardware enabled state */
43         bool suspend_in_progress;       /* TRUE, if we are in a suspend/resume cycle */
44 +       bool qos_enabled;               /* TRUE, if QoS is used. */
45 +       bool hwcrypto_enabled;          /* TRUE, if HW crypto acceleration is enabled. */
46  
47         /* PHY/Radio device. */
48         struct b43_phy phy;
49 --- a/drivers/net/wireless/b43/dma.c
50 +++ b/drivers/net/wireless/b43/dma.c
51 @@ -1285,7 +1285,7 @@ static struct b43_dmaring *select_ring_b
52  {
53         struct b43_dmaring *ring;
54  
55 -       if (b43_modparam_qos) {
56 +       if (dev->qos_enabled) {
57                 /* 0 = highest priority */
58                 switch (queue_prio) {
59                 default:
60 --- a/drivers/net/wireless/b43/main.c
61 +++ b/drivers/net/wireless/b43/main.c
62 @@ -80,8 +80,8 @@ static int modparam_nohwcrypt;
63  module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
64  MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
65  
66 -int b43_modparam_qos = 1;
67 -module_param_named(qos, b43_modparam_qos, int, 0444);
68 +static int modparam_qos = 1;
69 +module_param_named(qos, modparam_qos, int, 0444);
70  MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
71  
72  static int modparam_btcoex = 1;
73 @@ -538,6 +538,13 @@ void b43_hf_write(struct b43_wldev *dev,
74         b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
75  }
76  
77 +/* Read the firmware capabilities bitmask (Opensource firmware only) */
78 +static u16 b43_fwcapa_read(struct b43_wldev *dev)
79 +{
80 +       B43_WARN_ON(!dev->fw.opensource);
81 +       return b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_FWCAPA);
82 +}
83 +
84  void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
85  {
86         u32 low, high;
87 @@ -2307,12 +2314,34 @@ static int b43_upload_microcode(struct b
88         dev->fw.patch = fwpatch;
89         dev->fw.opensource = (fwdate == 0xFFFF);
90  
91 +       /* Default to use-all-queues. */
92 +       dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues;
93 +       dev->qos_enabled = !!modparam_qos;
94 +       /* Default to firmware/hardware crypto acceleration. */
95 +       dev->hwcrypto_enabled = 1;
96 +
97         if (dev->fw.opensource) {
98 +               u16 fwcapa;
99 +
100                 /* Patchlevel info is encoded in the "time" field. */
101                 dev->fw.patch = fwtime;
102 -               b43info(dev->wl, "Loading OpenSource firmware version %u.%u%s\n",
103 -                       dev->fw.rev, dev->fw.patch,
104 -                       dev->fw.pcm_request_failed ? " (Hardware crypto not supported)" : "");
105 +               b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n",
106 +                       dev->fw.rev, dev->fw.patch);
107 +
108 +               fwcapa = b43_fwcapa_read(dev);
109 +               if (!(fwcapa & B43_FWCAPA_HWCRYPTO) || dev->fw.pcm_request_failed) {
110 +                       b43info(dev->wl, "Hardware crypto acceleration not supported by firmware\n");
111 +                       /* Disable hardware crypto and fall back to software crypto. */
112 +                       dev->hwcrypto_enabled = 0;
113 +               }
114 +               if (!(fwcapa & B43_FWCAPA_QOS)) {
115 +                       b43info(dev->wl, "QoS not supported by firmware\n");
116 +                       /* Disable QoS. Tweak hw->queues to 1. It will be restored before
117 +                        * ieee80211_unregister to make sure the networking core can
118 +                        * properly free possible resources. */
119 +                       dev->wl->hw->queues = 1;
120 +                       dev->qos_enabled = 0;
121 +               }
122         } else {
123                 b43info(dev->wl, "Loading firmware version %u.%u "
124                         "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
125 @@ -3629,7 +3658,7 @@ static int b43_op_set_key(struct ieee802
126         if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
127                 goto out_unlock;
128  
129 -       if (dev->fw.pcm_request_failed) {
130 +       if (dev->fw.pcm_request_failed || !dev->hwcrypto_enabled) {
131                 /* We don't have firmware for the crypto engine.
132                  * Must use software-crypto. */
133                 err = -EOPNOTSUPP;
134 @@ -4737,6 +4766,7 @@ static int b43_wireless_init(struct ssb_
135                 b43err(NULL, "Could not allocate ieee80211 device\n");
136                 goto out;
137         }
138 +       wl = hw_to_b43_wl(hw);
139  
140         /* fill hw info */
141         hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
142 @@ -4750,7 +4780,8 @@ static int b43_wireless_init(struct ssb_
143                 BIT(NL80211_IFTYPE_WDS) |
144                 BIT(NL80211_IFTYPE_ADHOC);
145  
146 -       hw->queues = b43_modparam_qos ? 4 : 1;
147 +       hw->queues = modparam_qos ? 4 : 1;
148 +       wl->mac80211_initially_registered_queues = hw->queues;
149         hw->max_rates = 2;
150         SET_IEEE80211_DEV(hw, dev->dev);
151         if (is_valid_ether_addr(sprom->et1mac))
152 @@ -4758,9 +4789,7 @@ static int b43_wireless_init(struct ssb_
153         else
154                 SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
155  
156 -       /* Get and initialize struct b43_wl */
157 -       wl = hw_to_b43_wl(hw);
158 -       memset(wl, 0, sizeof(*wl));
159 +       /* Initialize struct b43_wl */
160         wl->hw = hw;
161         spin_lock_init(&wl->irq_lock);
162         rwlock_init(&wl->tx_lock);
163 @@ -4826,8 +4855,13 @@ static void b43_remove(struct ssb_device
164         cancel_work_sync(&wldev->restart_work);
165  
166         B43_WARN_ON(!wl);
167 -       if (wl->current_dev == wldev)
168 +       if (wl->current_dev == wldev) {
169 +               /* Restore the queues count before unregistering, because firmware detect
170 +                * might have modified it. Restoring is important, so the networking
171 +                * stack can properly free resources. */
172 +               wl->hw->queues = wl->mac80211_initially_registered_queues;
173                 ieee80211_unregister_hw(wl->hw);
174 +       }
175  
176         b43_one_core_detach(dev);
177  
178 --- a/drivers/net/wireless/b43/main.h
179 +++ b/drivers/net/wireless/b43/main.h
180 @@ -39,7 +39,6 @@
181  #define PAD_BYTES(nr_bytes)            P4D_BYTES( __LINE__ , (nr_bytes))
182  
183  
184 -extern int b43_modparam_qos;
185  extern int b43_modparam_verbose;
186  
187  /* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if
188 --- a/drivers/net/wireless/b43/pio.c
189 +++ b/drivers/net/wireless/b43/pio.c
190 @@ -313,7 +313,7 @@ static struct b43_pio_txqueue *select_qu
191  {
192         struct b43_pio_txqueue *q;
193  
194 -       if (b43_modparam_qos) {
195 +       if (dev->qos_enabled) {
196                 /* 0 = highest priority */
197                 switch (queue_prio) {
198                 default: