diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/b43/debugfs.c | 77 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/lo.c | 721 | ||||
-rw-r--r-- | drivers/net/wireless/b43/lo.h | 115 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy.c | 123 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy.h | 16 |
8 files changed, 396 insertions, 686 deletions
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 7fca2ebc747f..210e2789c1c3 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c | |||
@@ -270,24 +270,22 @@ static int restart_write_file(struct b43_wldev *dev, | |||
270 | return err; | 270 | return err; |
271 | } | 271 | } |
272 | 272 | ||
273 | static ssize_t append_lo_table(ssize_t count, char *buf, const size_t bufsize, | 273 | static unsigned long calc_expire_secs(unsigned long now, |
274 | struct b43_loctl table[B43_NR_BB][B43_NR_RF]) | 274 | unsigned long time, |
275 | unsigned long expire) | ||
275 | { | 276 | { |
276 | unsigned int i, j; | 277 | expire = time + expire; |
277 | struct b43_loctl *ctl; | 278 | |
278 | 279 | if (time_after(now, expire)) | |
279 | for (i = 0; i < B43_NR_BB; i++) { | 280 | return 0; /* expired */ |
280 | for (j = 0; j < B43_NR_RF; j++) { | 281 | if (expire < now) { |
281 | ctl = &(table[i][j]); | 282 | /* jiffies wrapped */ |
282 | fappend("(bbatt %2u, rfatt %2u) -> " | 283 | expire -= MAX_JIFFY_OFFSET; |
283 | "(I %+3d, Q %+3d, Used: %d, Calibrated: %d)\n", | 284 | now -= MAX_JIFFY_OFFSET; |
284 | i, j, ctl->i, ctl->q, | ||
285 | ctl->used, | ||
286 | b43_loctl_is_calibrated(ctl)); | ||
287 | } | ||
288 | } | 285 | } |
286 | B43_WARN_ON(expire < now); | ||
289 | 287 | ||
290 | return count; | 288 | return (expire - now) / HZ; |
291 | } | 289 | } |
292 | 290 | ||
293 | static ssize_t loctls_read_file(struct b43_wldev *dev, | 291 | static ssize_t loctls_read_file(struct b43_wldev *dev, |
@@ -296,27 +294,45 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, | |||
296 | ssize_t count = 0; | 294 | ssize_t count = 0; |
297 | struct b43_txpower_lo_control *lo; | 295 | struct b43_txpower_lo_control *lo; |
298 | int i, err = 0; | 296 | int i, err = 0; |
297 | struct b43_lo_calib *cal; | ||
298 | unsigned long now = jiffies; | ||
299 | struct b43_phy *phy = &dev->phy; | ||
299 | 300 | ||
300 | if (dev->phy.type != B43_PHYTYPE_G) { | 301 | if (phy->type != B43_PHYTYPE_G) { |
301 | fappend("Device is not a G-PHY\n"); | 302 | fappend("Device is not a G-PHY\n"); |
302 | err = -ENODEV; | 303 | err = -ENODEV; |
303 | goto out; | 304 | goto out; |
304 | } | 305 | } |
305 | lo = dev->phy.lo_control; | 306 | lo = phy->lo_control; |
306 | fappend("-- Local Oscillator calibration data --\n\n"); | 307 | fappend("-- Local Oscillator calibration data --\n\n"); |
307 | fappend("Measured: %d, Rebuild: %d, HW-power-control: %d\n", | 308 | fappend("HW-power-control enabled: %d\n", |
308 | lo->lo_measured, | ||
309 | lo->rebuild, | ||
310 | dev->phy.hardware_power_control); | 309 | dev->phy.hardware_power_control); |
311 | fappend("TX Bias: 0x%02X, TX Magn: 0x%02X\n", | 310 | fappend("TX Bias: 0x%02X, TX Magn: 0x%02X (expire in %lu sec)\n", |
312 | lo->tx_bias, lo->tx_magn); | 311 | lo->tx_bias, lo->tx_magn, |
313 | fappend("Power Vector: 0x%08X%08X\n", | 312 | calc_expire_secs(now, lo->txctl_measured_time, |
313 | B43_LO_TXCTL_EXPIRE)); | ||
314 | fappend("Power Vector: 0x%08X%08X (expires in %lu sec)\n", | ||
314 | (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32), | 315 | (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32), |
315 | (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL)); | 316 | (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL), |
316 | fappend("\nControl table WITH PADMIX:\n"); | 317 | calc_expire_secs(now, lo->pwr_vec_read_time, |
317 | count = append_lo_table(count, buf, bufsize, lo->with_padmix); | 318 | B43_LO_PWRVEC_EXPIRE)); |
318 | fappend("\nControl table WITHOUT PADMIX:\n"); | 319 | |
319 | count = append_lo_table(count, buf, bufsize, lo->no_padmix); | 320 | fappend("\nCalibrated settings:\n"); |
321 | list_for_each_entry(cal, &lo->calib_list, list) { | ||
322 | bool active; | ||
323 | |||
324 | active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && | ||
325 | b43_compare_rfatt(&cal->rfatt, &phy->rfatt)); | ||
326 | fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d " | ||
327 | "(expires in %lu sec)%s\n", | ||
328 | cal->bbatt.att, | ||
329 | cal->rfatt.att, cal->rfatt.with_padmix, | ||
330 | cal->ctl.i, cal->ctl.q, | ||
331 | calc_expire_secs(now, cal->calib_time, | ||
332 | B43_LO_CALIB_EXPIRE), | ||
333 | active ? " ACTIVE" : ""); | ||
334 | } | ||
335 | |||
320 | fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n"); | 336 | fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n"); |
321 | for (i = 0; i < lo->rfatt_list.len; i++) { | 337 | for (i = 0; i < lo->rfatt_list.len; i++) { |
322 | fappend("%u(%d), ", | 338 | fappend("%u(%d), ", |
@@ -351,7 +367,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, | |||
351 | struct b43_dfs_file *dfile; | 367 | struct b43_dfs_file *dfile; |
352 | ssize_t uninitialized_var(ret); | 368 | ssize_t uninitialized_var(ret); |
353 | char *buf; | 369 | char *buf; |
354 | const size_t bufsize = 1024 * 128; | 370 | const size_t bufsize = 1024 * 16; /* 16 kiB buffer */ |
355 | const size_t buforder = get_order(bufsize); | 371 | const size_t buforder = get_order(bufsize); |
356 | int err = 0; | 372 | int err = 0; |
357 | 373 | ||
@@ -380,8 +396,6 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, | |||
380 | err = -ENOMEM; | 396 | err = -ENOMEM; |
381 | goto out_unlock; | 397 | goto out_unlock; |
382 | } | 398 | } |
383 | /* Sparse warns about the following memset, because it has a big | ||
384 | * size value. That warning is bogus, so I will ignore it. --mb */ | ||
385 | memset(buf, 0, bufsize); | 399 | memset(buf, 0, bufsize); |
386 | if (dfops->take_irqlock) { | 400 | if (dfops->take_irqlock) { |
387 | spin_lock_irq(&dev->wl->irq_lock); | 401 | spin_lock_irq(&dev->wl->irq_lock); |
@@ -523,6 +537,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) | |||
523 | add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0); | 537 | add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0); |
524 | add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); | 538 | add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); |
525 | add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); | 539 | add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); |
540 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); | ||
526 | 541 | ||
527 | #undef add_dyn_dbg | 542 | #undef add_dyn_dbg |
528 | } | 543 | } |
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index 6eebe858db5a..c75cff4151d9 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h | |||
@@ -10,6 +10,7 @@ enum b43_dyndbg { /* Dynamic debugging features */ | |||
10 | B43_DBG_DMAVERBOSE, | 10 | B43_DBG_DMAVERBOSE, |
11 | B43_DBG_PWORK_FAST, | 11 | B43_DBG_PWORK_FAST, |
12 | B43_DBG_PWORK_STOP, | 12 | B43_DBG_PWORK_STOP, |
13 | B43_DBG_LO, | ||
13 | __B43_NR_DYNDBG, | 14 | __B43_NR_DYNDBG, |
14 | }; | 15 | }; |
15 | 16 | ||
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index d890f366a23b..4edee6da2b8b 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c | |||
@@ -36,10 +36,22 @@ | |||
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | 37 | ||
38 | 38 | ||
39 | /* Define to 1 to always calibrate all possible LO control pairs. | 39 | static struct b43_lo_calib * b43_find_lo_calib(struct b43_txpower_lo_control *lo, |
40 | * This is a workaround until we fix the partial LO calibration optimization. */ | 40 | const struct b43_bbatt *bbatt, |
41 | #define B43_CALIB_ALL_LOCTLS 1 | 41 | const struct b43_rfatt *rfatt) |
42 | { | ||
43 | struct b43_lo_calib *c; | ||
44 | |||
45 | list_for_each_entry(c, &lo->calib_list, list) { | ||
46 | if (!b43_compare_bbatt(&c->bbatt, bbatt)) | ||
47 | continue; | ||
48 | if (!b43_compare_rfatt(&c->rfatt, rfatt)) | ||
49 | continue; | ||
50 | return c; | ||
51 | } | ||
42 | 52 | ||
53 | return NULL; | ||
54 | } | ||
43 | 55 | ||
44 | /* Write the LocalOscillator Control (adjust) value-pair. */ | 56 | /* Write the LocalOscillator Control (adjust) value-pair. */ |
45 | static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) | 57 | static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) |
@@ -64,183 +76,6 @@ static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) | |||
64 | b43_phy_write(dev, reg, value); | 76 | b43_phy_write(dev, reg, value); |
65 | } | 77 | } |
66 | 78 | ||
67 | static int assert_rfatt_and_bbatt(const struct b43_rfatt *rfatt, | ||
68 | const struct b43_bbatt *bbatt, | ||
69 | struct b43_wldev *dev) | ||
70 | { | ||
71 | int err = 0; | ||
72 | |||
73 | /* Check the attenuation values against the LO control array sizes. */ | ||
74 | if (unlikely(rfatt->att >= B43_NR_RF)) { | ||
75 | b43err(dev->wl, "rfatt(%u) >= size of LO array\n", rfatt->att); | ||
76 | err = -EINVAL; | ||
77 | } | ||
78 | if (unlikely(bbatt->att >= B43_NR_BB)) { | ||
79 | b43err(dev->wl, "bbatt(%u) >= size of LO array\n", bbatt->att); | ||
80 | err = -EINVAL; | ||
81 | } | ||
82 | |||
83 | return err; | ||
84 | } | ||
85 | |||
86 | #if !B43_CALIB_ALL_LOCTLS | ||
87 | static | ||
88 | struct b43_loctl *b43_get_lo_g_ctl_nopadmix(struct b43_wldev *dev, | ||
89 | const struct b43_rfatt *rfatt, | ||
90 | const struct b43_bbatt *bbatt) | ||
91 | { | ||
92 | struct b43_phy *phy = &dev->phy; | ||
93 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
94 | |||
95 | if (assert_rfatt_and_bbatt(rfatt, bbatt, dev)) | ||
96 | return &(lo->no_padmix[0][0]); /* Just prevent a crash */ | ||
97 | return &(lo->no_padmix[bbatt->att][rfatt->att]); | ||
98 | } | ||
99 | #endif /* !B43_CALIB_ALL_LOCTLS */ | ||
100 | |||
101 | struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev, | ||
102 | const struct b43_rfatt *rfatt, | ||
103 | const struct b43_bbatt *bbatt) | ||
104 | { | ||
105 | struct b43_phy *phy = &dev->phy; | ||
106 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
107 | |||
108 | if (assert_rfatt_and_bbatt(rfatt, bbatt, dev)) | ||
109 | return &(lo->no_padmix[0][0]); /* Just prevent a crash */ | ||
110 | if (rfatt->with_padmix) | ||
111 | return &(lo->with_padmix[bbatt->att][rfatt->att]); | ||
112 | return &(lo->no_padmix[bbatt->att][rfatt->att]); | ||
113 | } | ||
114 | |||
115 | /* Call a function for every possible LO control value-pair. */ | ||
116 | static void b43_call_for_each_loctl(struct b43_wldev *dev, | ||
117 | void (*func) (struct b43_wldev *, | ||
118 | struct b43_loctl *)) | ||
119 | { | ||
120 | struct b43_phy *phy = &dev->phy; | ||
121 | struct b43_txpower_lo_control *ctl = phy->lo_control; | ||
122 | int i, j; | ||
123 | |||
124 | for (i = 0; i < B43_NR_BB; i++) { | ||
125 | for (j = 0; j < B43_NR_RF; j++) | ||
126 | func(dev, &(ctl->with_padmix[i][j])); | ||
127 | } | ||
128 | for (i = 0; i < B43_NR_BB; i++) { | ||
129 | for (j = 0; j < B43_NR_RF; j++) | ||
130 | func(dev, &(ctl->no_padmix[i][j])); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static u16 lo_b_r15_loop(struct b43_wldev *dev) | ||
135 | { | ||
136 | int i; | ||
137 | u16 ret = 0; | ||
138 | |||
139 | for (i = 0; i < 10; i++) { | ||
140 | b43_phy_write(dev, 0x0015, 0xAFA0); | ||
141 | udelay(1); | ||
142 | b43_phy_write(dev, 0x0015, 0xEFA0); | ||
143 | udelay(10); | ||
144 | b43_phy_write(dev, 0x0015, 0xFFA0); | ||
145 | udelay(40); | ||
146 | ret += b43_phy_read(dev, 0x002C); | ||
147 | } | ||
148 | |||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | void b43_lo_b_measure(struct b43_wldev *dev) | ||
153 | { | ||
154 | struct b43_phy *phy = &dev->phy; | ||
155 | u16 regstack[12] = { 0 }; | ||
156 | u16 mls; | ||
157 | u16 fval; | ||
158 | int i, j; | ||
159 | |||
160 | regstack[0] = b43_phy_read(dev, 0x0015); | ||
161 | regstack[1] = b43_radio_read16(dev, 0x0052) & 0xFFF0; | ||
162 | |||
163 | if (phy->radio_ver == 0x2053) { | ||
164 | regstack[2] = b43_phy_read(dev, 0x000A); | ||
165 | regstack[3] = b43_phy_read(dev, 0x002A); | ||
166 | regstack[4] = b43_phy_read(dev, 0x0035); | ||
167 | regstack[5] = b43_phy_read(dev, 0x0003); | ||
168 | regstack[6] = b43_phy_read(dev, 0x0001); | ||
169 | regstack[7] = b43_phy_read(dev, 0x0030); | ||
170 | |||
171 | regstack[8] = b43_radio_read16(dev, 0x0043); | ||
172 | regstack[9] = b43_radio_read16(dev, 0x007A); | ||
173 | regstack[10] = b43_read16(dev, 0x03EC); | ||
174 | regstack[11] = b43_radio_read16(dev, 0x0052) & 0x00F0; | ||
175 | |||
176 | b43_phy_write(dev, 0x0030, 0x00FF); | ||
177 | b43_write16(dev, 0x03EC, 0x3F3F); | ||
178 | b43_phy_write(dev, 0x0035, regstack[4] & 0xFF7F); | ||
179 | b43_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0); | ||
180 | } | ||
181 | b43_phy_write(dev, 0x0015, 0xB000); | ||
182 | b43_phy_write(dev, 0x002B, 0x0004); | ||
183 | |||
184 | if (phy->radio_ver == 0x2053) { | ||
185 | b43_phy_write(dev, 0x002B, 0x0203); | ||
186 | b43_phy_write(dev, 0x002A, 0x08A3); | ||
187 | } | ||
188 | |||
189 | phy->minlowsig[0] = 0xFFFF; | ||
190 | |||
191 | for (i = 0; i < 4; i++) { | ||
192 | b43_radio_write16(dev, 0x0052, regstack[1] | i); | ||
193 | lo_b_r15_loop(dev); | ||
194 | } | ||
195 | for (i = 0; i < 10; i++) { | ||
196 | b43_radio_write16(dev, 0x0052, regstack[1] | i); | ||
197 | mls = lo_b_r15_loop(dev) / 10; | ||
198 | if (mls < phy->minlowsig[0]) { | ||
199 | phy->minlowsig[0] = mls; | ||
200 | phy->minlowsigpos[0] = i; | ||
201 | } | ||
202 | } | ||
203 | b43_radio_write16(dev, 0x0052, regstack[1] | phy->minlowsigpos[0]); | ||
204 | |||
205 | phy->minlowsig[1] = 0xFFFF; | ||
206 | |||
207 | for (i = -4; i < 5; i += 2) { | ||
208 | for (j = -4; j < 5; j += 2) { | ||
209 | if (j < 0) | ||
210 | fval = (0x0100 * i) + j + 0x0100; | ||
211 | else | ||
212 | fval = (0x0100 * i) + j; | ||
213 | b43_phy_write(dev, 0x002F, fval); | ||
214 | mls = lo_b_r15_loop(dev) / 10; | ||
215 | if (mls < phy->minlowsig[1]) { | ||
216 | phy->minlowsig[1] = mls; | ||
217 | phy->minlowsigpos[1] = fval; | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | phy->minlowsigpos[1] += 0x0101; | ||
222 | |||
223 | b43_phy_write(dev, 0x002F, phy->minlowsigpos[1]); | ||
224 | if (phy->radio_ver == 0x2053) { | ||
225 | b43_phy_write(dev, 0x000A, regstack[2]); | ||
226 | b43_phy_write(dev, 0x002A, regstack[3]); | ||
227 | b43_phy_write(dev, 0x0035, regstack[4]); | ||
228 | b43_phy_write(dev, 0x0003, regstack[5]); | ||
229 | b43_phy_write(dev, 0x0001, regstack[6]); | ||
230 | b43_phy_write(dev, 0x0030, regstack[7]); | ||
231 | |||
232 | b43_radio_write16(dev, 0x0043, regstack[8]); | ||
233 | b43_radio_write16(dev, 0x007A, regstack[9]); | ||
234 | |||
235 | b43_radio_write16(dev, 0x0052, | ||
236 | (b43_radio_read16(dev, 0x0052) & 0x000F) | ||
237 | | regstack[11]); | ||
238 | |||
239 | b43_write16(dev, 0x03EC, regstack[10]); | ||
240 | } | ||
241 | b43_phy_write(dev, 0x0015, regstack[0]); | ||
242 | } | ||
243 | |||
244 | static u16 lo_measure_feedthrough(struct b43_wldev *dev, | 79 | static u16 lo_measure_feedthrough(struct b43_wldev *dev, |
245 | u16 lna, u16 pga, u16 trsw_rx) | 80 | u16 lna, u16 pga, u16 trsw_rx) |
246 | { | 81 | { |
@@ -438,48 +273,26 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) | |||
438 | b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52) | 273 | b43_radio_write16(dev, 0x52, b43_radio_read16(dev, 0x52) |
439 | & 0xFFF0); /* TX bias == 0 */ | 274 | & 0xFFF0); /* TX bias == 0 */ |
440 | } | 275 | } |
276 | lo->txctl_measured_time = jiffies; | ||
441 | } | 277 | } |
442 | 278 | ||
443 | static void lo_read_power_vector(struct b43_wldev *dev) | 279 | static void lo_read_power_vector(struct b43_wldev *dev) |
444 | { | 280 | { |
445 | struct b43_phy *phy = &dev->phy; | 281 | struct b43_phy *phy = &dev->phy; |
446 | struct b43_txpower_lo_control *lo = phy->lo_control; | 282 | struct b43_txpower_lo_control *lo = phy->lo_control; |
447 | u16 i; | 283 | int i; |
448 | u64 tmp; | 284 | u64 tmp; |
449 | u64 power_vector = 0; | 285 | u64 power_vector = 0; |
450 | int rf_offset, bb_offset; | ||
451 | struct b43_loctl *loctl; | ||
452 | 286 | ||
453 | for (i = 0; i < 8; i += 2) { | 287 | for (i = 0; i < 8; i += 2) { |
454 | tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i); | 288 | tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i); |
455 | /* Clear the top byte. We get holes in the bitmap... */ | ||
456 | tmp &= 0xFF; | ||
457 | power_vector |= (tmp << (i * 8)); | 289 | power_vector |= (tmp << (i * 8)); |
458 | /* Clear the vector on the device. */ | 290 | /* Clear the vector on the device. */ |
459 | b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0); | 291 | b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0); |
460 | } | 292 | } |
461 | |||
462 | if (power_vector) | 293 | if (power_vector) |
463 | lo->power_vector = power_vector; | 294 | lo->power_vector = power_vector; |
464 | power_vector = lo->power_vector; | 295 | lo->pwr_vec_read_time = jiffies; |
465 | |||
466 | for (i = 0; i < 64; i++) { | ||
467 | if (power_vector & ((u64) 1ULL << i)) { | ||
468 | /* Now figure out which b43_loctl corresponds | ||
469 | * to this bit. | ||
470 | */ | ||
471 | rf_offset = i / lo->rfatt_list.len; | ||
472 | bb_offset = i % lo->rfatt_list.len; //FIXME? | ||
473 | loctl = | ||
474 | b43_get_lo_g_ctl(dev, | ||
475 | &lo->rfatt_list.list[rf_offset], | ||
476 | &lo->bbatt_list.list[bb_offset]); | ||
477 | /* And mark it as "used", as the device told us | ||
478 | * through the bitmap it is using it. | ||
479 | */ | ||
480 | loctl->used = 1; | ||
481 | } | ||
482 | } | ||
483 | } | 296 | } |
484 | 297 | ||
485 | /* 802.11/LO/GPHY/MeasuringGains */ | 298 | /* 802.11/LO/GPHY/MeasuringGains */ |
@@ -609,8 +422,6 @@ static void lo_measure_setup(struct b43_wldev *dev, | |||
609 | b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410); | 422 | b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410); |
610 | b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820); | 423 | b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820); |
611 | } | 424 | } |
612 | if (!lo->rebuild && b43_has_hardware_pctl(phy)) | ||
613 | lo_read_power_vector(dev); | ||
614 | if (phy->rev >= 2) { | 425 | if (phy->rev >= 2) { |
615 | sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); | 426 | sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); |
616 | sav->phy_analogoverval = | 427 | sav->phy_analogoverval = |
@@ -691,8 +502,12 @@ static void lo_measure_setup(struct b43_wldev *dev, | |||
691 | b43_radio_read16(dev, 0x51); /* dummy read */ | 502 | b43_radio_read16(dev, 0x51); /* dummy read */ |
692 | if (phy->type == B43_PHYTYPE_G) | 503 | if (phy->type == B43_PHYTYPE_G) |
693 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); | 504 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); |
694 | if (lo->rebuild) | 505 | |
506 | /* Re-measure the txctl values, if needed. */ | ||
507 | if (time_before(lo->txctl_measured_time, | ||
508 | jiffies - B43_LO_TXCTL_EXPIRE)) | ||
695 | lo_measure_txctl_values(dev); | 509 | lo_measure_txctl_values(dev); |
510 | |||
696 | if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) { | 511 | if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) { |
697 | b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078); | 512 | b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078); |
698 | } else { | 513 | } else { |
@@ -707,7 +522,6 @@ static void lo_measure_restore(struct b43_wldev *dev, | |||
707 | struct lo_g_saved_values *sav) | 522 | struct lo_g_saved_values *sav) |
708 | { | 523 | { |
709 | struct b43_phy *phy = &dev->phy; | 524 | struct b43_phy *phy = &dev->phy; |
710 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
711 | u16 tmp; | 525 | u16 tmp; |
712 | 526 | ||
713 | if (phy->rev >= 2) { | 527 | if (phy->rev >= 2) { |
@@ -722,14 +536,6 @@ static void lo_measure_restore(struct b43_wldev *dev, | |||
722 | tmp = (phy->pga_gain | 0xEFA0); | 536 | tmp = (phy->pga_gain | 0xEFA0); |
723 | b43_phy_write(dev, B43_PHY_PGACTL, tmp); | 537 | b43_phy_write(dev, B43_PHY_PGACTL, tmp); |
724 | } | 538 | } |
725 | if (b43_has_hardware_pctl(phy)) { | ||
726 | b43_gphy_dc_lt_init(dev); | ||
727 | } else { | ||
728 | if (lo->rebuild) | ||
729 | b43_lo_g_adjust_to(dev, 3, 2, 0); | ||
730 | else | ||
731 | b43_lo_g_adjust(dev); | ||
732 | } | ||
733 | if (phy->type == B43_PHYTYPE_G) { | 539 | if (phy->type == B43_PHYTYPE_G) { |
734 | if (phy->rev >= 3) | 540 | if (phy->rev >= 3) |
735 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078); | 541 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078); |
@@ -793,7 +599,6 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev, | |||
793 | struct b43_lo_g_statemachine *d) | 599 | struct b43_lo_g_statemachine *d) |
794 | { | 600 | { |
795 | struct b43_phy *phy = &dev->phy; | 601 | struct b43_phy *phy = &dev->phy; |
796 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
797 | struct b43_loctl test_loctl; | 602 | struct b43_loctl test_loctl; |
798 | struct b43_loctl orig_loctl; | 603 | struct b43_loctl orig_loctl; |
799 | struct b43_loctl prev_loctl = { | 604 | struct b43_loctl prev_loctl = { |
@@ -852,7 +657,7 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev, | |||
852 | found_lower = 1; | 657 | found_lower = 1; |
853 | d->lowest_feedth = feedth; | 658 | d->lowest_feedth = feedth; |
854 | if ((d->nr_measured < 2) && | 659 | if ((d->nr_measured < 2) && |
855 | (!has_loopback_gain(phy) || lo->rebuild)) | 660 | !has_loopback_gain(phy)) |
856 | break; | 661 | break; |
857 | } | 662 | } |
858 | } | 663 | } |
@@ -874,7 +679,6 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, | |||
874 | int *max_rx_gain) | 679 | int *max_rx_gain) |
875 | { | 680 | { |
876 | struct b43_phy *phy = &dev->phy; | 681 | struct b43_phy *phy = &dev->phy; |
877 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
878 | struct b43_lo_g_statemachine d; | 682 | struct b43_lo_g_statemachine d; |
879 | u16 feedth; | 683 | u16 feedth; |
880 | int found_lower; | 684 | int found_lower; |
@@ -883,18 +687,18 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, | |||
883 | 687 | ||
884 | d.nr_measured = 0; | 688 | d.nr_measured = 0; |
885 | d.state_val_multiplier = 1; | 689 | d.state_val_multiplier = 1; |
886 | if (has_loopback_gain(phy) && !lo->rebuild) | 690 | if (has_loopback_gain(phy)) |
887 | d.state_val_multiplier = 3; | 691 | d.state_val_multiplier = 3; |
888 | 692 | ||
889 | memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl)); | 693 | memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl)); |
890 | if (has_loopback_gain(phy) && lo->rebuild) | 694 | if (has_loopback_gain(phy)) |
891 | max_repeat = 4; | 695 | max_repeat = 4; |
892 | do { | 696 | do { |
893 | b43_lo_write(dev, &d.min_loctl); | 697 | b43_lo_write(dev, &d.min_loctl); |
894 | feedth = lo_measure_feedthrough(dev, phy->lna_gain, | 698 | feedth = lo_measure_feedthrough(dev, phy->lna_gain, |
895 | phy->pga_gain, | 699 | phy->pga_gain, |
896 | phy->trsw_rx_gain); | 700 | phy->trsw_rx_gain); |
897 | if (!lo->rebuild && feedth < 0x258) { | 701 | if (feedth < 0x258) { |
898 | if (feedth >= 0x12C) | 702 | if (feedth >= 0x12C) |
899 | *max_rx_gain += 6; | 703 | *max_rx_gain += 6; |
900 | else | 704 | else |
@@ -944,278 +748,188 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, | |||
944 | } while (++repeat_cnt < max_repeat); | 748 | } while (++repeat_cnt < max_repeat); |
945 | } | 749 | } |
946 | 750 | ||
947 | #if B43_CALIB_ALL_LOCTLS | 751 | static |
948 | static const struct b43_rfatt b43_full_rfatt_list_items[] = { | 752 | struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev, |
949 | { .att = 0, .with_padmix = 0, }, | 753 | const struct b43_bbatt *bbatt, |
950 | { .att = 1, .with_padmix = 0, }, | 754 | const struct b43_rfatt *rfatt) |
951 | { .att = 2, .with_padmix = 0, }, | ||
952 | { .att = 3, .with_padmix = 0, }, | ||
953 | { .att = 4, .with_padmix = 0, }, | ||
954 | { .att = 5, .with_padmix = 0, }, | ||
955 | { .att = 6, .with_padmix = 0, }, | ||
956 | { .att = 7, .with_padmix = 0, }, | ||
957 | { .att = 8, .with_padmix = 0, }, | ||
958 | { .att = 9, .with_padmix = 0, }, | ||
959 | { .att = 10, .with_padmix = 0, }, | ||
960 | { .att = 11, .with_padmix = 0, }, | ||
961 | { .att = 12, .with_padmix = 0, }, | ||
962 | { .att = 13, .with_padmix = 0, }, | ||
963 | { .att = 14, .with_padmix = 0, }, | ||
964 | { .att = 15, .with_padmix = 0, }, | ||
965 | { .att = 0, .with_padmix = 1, }, | ||
966 | { .att = 1, .with_padmix = 1, }, | ||
967 | { .att = 2, .with_padmix = 1, }, | ||
968 | { .att = 3, .with_padmix = 1, }, | ||
969 | { .att = 4, .with_padmix = 1, }, | ||
970 | { .att = 5, .with_padmix = 1, }, | ||
971 | { .att = 6, .with_padmix = 1, }, | ||
972 | { .att = 7, .with_padmix = 1, }, | ||
973 | { .att = 8, .with_padmix = 1, }, | ||
974 | { .att = 9, .with_padmix = 1, }, | ||
975 | { .att = 10, .with_padmix = 1, }, | ||
976 | { .att = 11, .with_padmix = 1, }, | ||
977 | { .att = 12, .with_padmix = 1, }, | ||
978 | { .att = 13, .with_padmix = 1, }, | ||
979 | { .att = 14, .with_padmix = 1, }, | ||
980 | { .att = 15, .with_padmix = 1, }, | ||
981 | }; | ||
982 | static const struct b43_rfatt_list b43_full_rfatt_list = { | ||
983 | .list = b43_full_rfatt_list_items, | ||
984 | .len = ARRAY_SIZE(b43_full_rfatt_list_items), | ||
985 | }; | ||
986 | |||
987 | static const struct b43_bbatt b43_full_bbatt_list_items[] = { | ||
988 | { .att = 0, }, | ||
989 | { .att = 1, }, | ||
990 | { .att = 2, }, | ||
991 | { .att = 3, }, | ||
992 | { .att = 4, }, | ||
993 | { .att = 5, }, | ||
994 | { .att = 6, }, | ||
995 | { .att = 7, }, | ||
996 | { .att = 8, }, | ||
997 | { .att = 9, }, | ||
998 | { .att = 10, }, | ||
999 | { .att = 11, }, | ||
1000 | }; | ||
1001 | static const struct b43_bbatt_list b43_full_bbatt_list = { | ||
1002 | .list = b43_full_bbatt_list_items, | ||
1003 | .len = ARRAY_SIZE(b43_full_bbatt_list_items), | ||
1004 | }; | ||
1005 | #endif /* B43_CALIB_ALL_LOCTLS */ | ||
1006 | |||
1007 | static void lo_measure(struct b43_wldev *dev) | ||
1008 | { | 755 | { |
1009 | struct b43_phy *phy = &dev->phy; | 756 | struct b43_phy *phy = &dev->phy; |
1010 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
1011 | struct b43_loctl loctl = { | 757 | struct b43_loctl loctl = { |
1012 | .i = 0, | 758 | .i = 0, |
1013 | .q = 0, | 759 | .q = 0, |
1014 | }; | 760 | }; |
1015 | struct b43_loctl *ploctl; | ||
1016 | int max_rx_gain; | 761 | int max_rx_gain; |
1017 | int rfidx, bbidx; | 762 | struct b43_lo_calib *cal; |
1018 | const struct b43_bbatt_list *bbatt_list; | 763 | struct lo_g_saved_values uninitialized_var(saved_regs); |
1019 | const struct b43_rfatt_list *rfatt_list; | ||
1020 | |||
1021 | /* Values from the "TXCTL Register and Value Table" */ | 764 | /* Values from the "TXCTL Register and Value Table" */ |
1022 | u16 txctl_reg; | 765 | u16 txctl_reg; |
1023 | u16 txctl_value; | 766 | u16 txctl_value; |
1024 | u16 pad_mix_gain; | 767 | u16 pad_mix_gain; |
1025 | 768 | ||
1026 | bbatt_list = &lo->bbatt_list; | 769 | saved_regs.old_channel = phy->channel; |
1027 | rfatt_list = &lo->rfatt_list; | 770 | b43_mac_suspend(dev); |
1028 | #if B43_CALIB_ALL_LOCTLS | 771 | lo_measure_setup(dev, &saved_regs); |
1029 | bbatt_list = &b43_full_bbatt_list; | ||
1030 | rfatt_list = &b43_full_rfatt_list; | ||
1031 | #endif | ||
1032 | 772 | ||
1033 | txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain); | 773 | txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain); |
1034 | 774 | ||
1035 | for (rfidx = 0; rfidx < rfatt_list->len; rfidx++) { | 775 | b43_radio_write16(dev, 0x43, |
1036 | 776 | (b43_radio_read16(dev, 0x43) & 0xFFF0) | |
1037 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | 777 | | rfatt->att); |
1038 | & 0xFFF0) | | 778 | b43_radio_write16(dev, txctl_reg, |
1039 | rfatt_list->list[rfidx].att); | 779 | (b43_radio_read16(dev, txctl_reg) & ~txctl_value) |
1040 | b43_radio_write16(dev, txctl_reg, | 780 | | (rfatt->with_padmix) ? txctl_value : 0); |
1041 | (b43_radio_read16(dev, txctl_reg) | ||
1042 | & ~txctl_value) | ||
1043 | | (rfatt_list->list[rfidx].with_padmix ? | ||
1044 | txctl_value : 0)); | ||
1045 | |||
1046 | for (bbidx = 0; bbidx < bbatt_list->len; bbidx++) { | ||
1047 | if (lo->rebuild) { | ||
1048 | #if B43_CALIB_ALL_LOCTLS | ||
1049 | ploctl = b43_get_lo_g_ctl(dev, | ||
1050 | &rfatt_list->list[rfidx], | ||
1051 | &bbatt_list->list[bbidx]); | ||
1052 | #else | ||
1053 | ploctl = b43_get_lo_g_ctl_nopadmix(dev, | ||
1054 | &rfatt_list-> | ||
1055 | list[rfidx], | ||
1056 | &bbatt_list-> | ||
1057 | list[bbidx]); | ||
1058 | #endif | ||
1059 | } else { | ||
1060 | ploctl = b43_get_lo_g_ctl(dev, | ||
1061 | &rfatt_list->list[rfidx], | ||
1062 | &bbatt_list->list[bbidx]); | ||
1063 | if (!ploctl->used) | ||
1064 | continue; | ||
1065 | } | ||
1066 | memcpy(&loctl, ploctl, sizeof(loctl)); | ||
1067 | loctl.i = 0; | ||
1068 | loctl.q = 0; | ||
1069 | |||
1070 | max_rx_gain = rfatt_list->list[rfidx].att * 2; | ||
1071 | max_rx_gain += bbatt_list->list[bbidx].att / 2; | ||
1072 | if (rfatt_list->list[rfidx].with_padmix) | ||
1073 | max_rx_gain -= pad_mix_gain; | ||
1074 | if (has_loopback_gain(phy)) | ||
1075 | max_rx_gain += phy->max_lb_gain; | ||
1076 | lo_measure_gain_values(dev, max_rx_gain, | ||
1077 | has_loopback_gain(phy)); | ||
1078 | |||
1079 | b43_phy_set_baseband_attenuation(dev, | ||
1080 | bbatt_list->list[bbidx].att); | ||
1081 | lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); | ||
1082 | if (phy->type == B43_PHYTYPE_B) { | ||
1083 | loctl.i++; | ||
1084 | loctl.q++; | ||
1085 | } | ||
1086 | b43_loctl_set_calibrated(&loctl, 1); | ||
1087 | memcpy(ploctl, &loctl, sizeof(loctl)); | ||
1088 | } | ||
1089 | } | ||
1090 | } | ||
1091 | |||
1092 | #if B43_DEBUG | ||
1093 | static void do_validate_loctl(struct b43_wldev *dev, struct b43_loctl *control) | ||
1094 | { | ||
1095 | const int is_initializing = (b43_status(dev) == B43_STAT_UNINIT); | ||
1096 | int i = control->i; | ||
1097 | int q = control->q; | ||
1098 | 781 | ||
1099 | if (b43_loctl_is_calibrated(control)) { | 782 | max_rx_gain = rfatt->att * 2; |
1100 | if ((abs(i) > 16) || (abs(q) > 16)) | 783 | max_rx_gain += bbatt->att / 2; |
1101 | goto error; | 784 | if (rfatt->with_padmix) |
1102 | } else { | 785 | max_rx_gain -= pad_mix_gain; |
1103 | if (control->used) | 786 | if (has_loopback_gain(phy)) |
1104 | goto error; | 787 | max_rx_gain += phy->max_lb_gain; |
1105 | if (dev->phy.lo_control->rebuild) { | 788 | lo_measure_gain_values(dev, max_rx_gain, |
1106 | control->i = 0; | 789 | has_loopback_gain(phy)); |
1107 | control->q = 0; | 790 | |
1108 | if ((i != B43_LOCTL_POISON) || | 791 | b43_phy_set_baseband_attenuation(dev, bbatt->att); |
1109 | (q != B43_LOCTL_POISON)) | 792 | lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); |
1110 | goto error; | 793 | |
1111 | } | 794 | lo_measure_restore(dev, &saved_regs); |
795 | b43_mac_enable(dev); | ||
796 | |||
797 | if (b43_debug(dev, B43_DBG_LO)) { | ||
798 | b43dbg(dev->wl, "LO: Calibrated for BB(%u), RF(%u,%u) " | ||
799 | "=> I=%d Q=%d\n", | ||
800 | bbatt->att, rfatt->att, rfatt->with_padmix, | ||
801 | loctl.i, loctl.q); | ||
1112 | } | 802 | } |
1113 | if (is_initializing && control->used) | ||
1114 | goto error; | ||
1115 | |||
1116 | return; | ||
1117 | error: | ||
1118 | b43err(dev->wl, "LO control pair validation failed " | ||
1119 | "(I: %d, Q: %d, used %u, calib: %u, initing: %d)\n", | ||
1120 | i, q, control->used, | ||
1121 | b43_loctl_is_calibrated(control), | ||
1122 | is_initializing); | ||
1123 | } | ||
1124 | 803 | ||
1125 | static void validate_all_loctls(struct b43_wldev *dev) | 804 | cal = kmalloc(sizeof(*cal), GFP_KERNEL); |
1126 | { | 805 | if (!cal) { |
1127 | b43_call_for_each_loctl(dev, do_validate_loctl); | 806 | b43warn(dev->wl, "LO calib: out of memory\n"); |
1128 | } | 807 | return NULL; |
1129 | |||
1130 | static void do_reset_calib(struct b43_wldev *dev, struct b43_loctl *control) | ||
1131 | { | ||
1132 | if (dev->phy.lo_control->rebuild || | ||
1133 | control->used) { | ||
1134 | b43_loctl_set_calibrated(control, 0); | ||
1135 | control->i = B43_LOCTL_POISON; | ||
1136 | control->q = B43_LOCTL_POISON; | ||
1137 | } | 808 | } |
809 | memcpy(&cal->bbatt, bbatt, sizeof(*bbatt)); | ||
810 | memcpy(&cal->rfatt, rfatt, sizeof(*rfatt)); | ||
811 | memcpy(&cal->ctl, &loctl, sizeof(loctl)); | ||
812 | cal->calib_time = jiffies; | ||
813 | INIT_LIST_HEAD(&cal->list); | ||
814 | |||
815 | return cal; | ||
1138 | } | 816 | } |
1139 | 817 | ||
1140 | static void reset_all_loctl_calibration_states(struct b43_wldev *dev) | 818 | /* Get a calibrated LO setting for the given attenuation values. |
819 | * Might return a NULL pointer under OOM! */ | ||
820 | static | ||
821 | struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev, | ||
822 | const struct b43_bbatt *bbatt, | ||
823 | const struct b43_rfatt *rfatt) | ||
1141 | { | 824 | { |
1142 | b43_call_for_each_loctl(dev, do_reset_calib); | 825 | struct b43_txpower_lo_control *lo = dev->phy.lo_control; |
826 | struct b43_lo_calib *c; | ||
827 | |||
828 | c = b43_find_lo_calib(lo, bbatt, rfatt); | ||
829 | if (c) | ||
830 | return c; | ||
831 | /* Not in the list of calibrated LO settings. | ||
832 | * Calibrate it now. */ | ||
833 | c = b43_calibrate_lo_setting(dev, bbatt, rfatt); | ||
834 | if (!c) | ||
835 | return NULL; | ||
836 | list_add(&c->list, &lo->calib_list); | ||
837 | |||
838 | return c; | ||
1143 | } | 839 | } |
1144 | 840 | ||
1145 | #else /* B43_DEBUG */ | 841 | void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all) |
1146 | static inline void validate_all_loctls(struct b43_wldev *dev) { } | ||
1147 | static inline void reset_all_loctl_calibration_states(struct b43_wldev *dev) { } | ||
1148 | #endif /* B43_DEBUG */ | ||
1149 | |||
1150 | void b43_lo_g_measure(struct b43_wldev *dev) | ||
1151 | { | 842 | { |
1152 | struct b43_phy *phy = &dev->phy; | 843 | struct b43_phy *phy = &dev->phy; |
1153 | struct lo_g_saved_values uninitialized_var(sav); | 844 | struct b43_txpower_lo_control *lo = phy->lo_control; |
1154 | 845 | int i; | |
1155 | B43_WARN_ON((phy->type != B43_PHYTYPE_B) && | 846 | int rf_offset, bb_offset; |
1156 | (phy->type != B43_PHYTYPE_G)); | 847 | const struct b43_rfatt *rfatt; |
1157 | 848 | const struct b43_bbatt *bbatt; | |
1158 | sav.old_channel = phy->channel; | 849 | u64 power_vector; |
1159 | lo_measure_setup(dev, &sav); | 850 | bool table_changed = 0; |
1160 | reset_all_loctl_calibration_states(dev); | ||
1161 | lo_measure(dev); | ||
1162 | lo_measure_restore(dev, &sav); | ||
1163 | |||
1164 | validate_all_loctls(dev); | ||
1165 | 851 | ||
1166 | phy->lo_control->lo_measured = 1; | 852 | BUILD_BUG_ON(B43_DC_LT_SIZE != 32); |
1167 | phy->lo_control->rebuild = 0; | 853 | B43_WARN_ON(lo->rfatt_list.len * lo->bbatt_list.len > 64); |
1168 | } | ||
1169 | 854 | ||
1170 | #if B43_DEBUG | 855 | power_vector = lo->power_vector; |
1171 | static void validate_loctl_calibration(struct b43_wldev *dev, | 856 | if (!update_all && !power_vector) |
1172 | struct b43_loctl *loctl, | 857 | return; /* Nothing to do. */ |
1173 | struct b43_rfatt *rfatt, | 858 | |
1174 | struct b43_bbatt *bbatt) | 859 | /* Suspend the MAC now to avoid continuous suspend/enable |
1175 | { | 860 | * cycles in the loop. */ |
1176 | if (b43_loctl_is_calibrated(loctl)) | 861 | b43_mac_suspend(dev); |
1177 | return; | 862 | |
1178 | if (!dev->phy.lo_control->lo_measured) { | 863 | for (i = 0; i < B43_DC_LT_SIZE * 2; i++) { |
1179 | /* On init we set the attenuation values before we | 864 | struct b43_lo_calib *cal; |
1180 | * calibrated the LO. I guess that's OK. */ | 865 | int idx; |
1181 | return; | 866 | u16 val; |
867 | |||
868 | if (!update_all && !(power_vector & (((u64)1ULL) << i))) | ||
869 | continue; | ||
870 | /* Update the table entry for this power_vector bit. | ||
871 | * The table rows are RFatt entries and columns are BBatt. */ | ||
872 | bb_offset = i / lo->rfatt_list.len; | ||
873 | rf_offset = i % lo->rfatt_list.len; | ||
874 | bbatt = &(lo->bbatt_list.list[bb_offset]); | ||
875 | rfatt = &(lo->rfatt_list.list[rf_offset]); | ||
876 | |||
877 | cal = b43_calibrate_lo_setting(dev, bbatt, rfatt); | ||
878 | if (!cal) { | ||
879 | b43warn(dev->wl, "LO: Could not " | ||
880 | "calibrate DC table entry\n"); | ||
881 | continue; | ||
882 | } | ||
883 | /*FIXME: Is Q really in the low nibble? */ | ||
884 | val = (u8)(cal->ctl.q); | ||
885 | val |= ((u8)(cal->ctl.i)) << 4; | ||
886 | kfree(cal); | ||
887 | |||
888 | /* Get the index into the hardware DC LT. */ | ||
889 | idx = i / 2; | ||
890 | /* Change the table in memory. */ | ||
891 | if (i % 2) { | ||
892 | /* Change the high byte. */ | ||
893 | lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00FF) | ||
894 | | ((val & 0x00FF) << 8); | ||
895 | } else { | ||
896 | /* Change the low byte. */ | ||
897 | lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xFF00) | ||
898 | | (val & 0x00FF); | ||
899 | } | ||
900 | table_changed = 1; | ||
1182 | } | 901 | } |
1183 | b43err(dev->wl, "Adjusting Local Oscillator to an uncalibrated " | 902 | if (table_changed) { |
1184 | "control pair: rfatt=%u,%spadmix bbatt=%u\n", | 903 | /* The table changed in memory. Update the hardware table. */ |
1185 | rfatt->att, | 904 | for (i = 0; i < B43_DC_LT_SIZE; i++) |
1186 | (rfatt->with_padmix) ? "" : "no-", | 905 | b43_phy_write(dev, 0x3A0 + i, lo->dc_lt[i]); |
1187 | bbatt->att); | 906 | } |
1188 | } | 907 | b43_mac_enable(dev); |
1189 | #else | ||
1190 | static inline void validate_loctl_calibration(struct b43_wldev *dev, | ||
1191 | struct b43_loctl *loctl, | ||
1192 | struct b43_rfatt *rfatt, | ||
1193 | struct b43_bbatt *bbatt) | ||
1194 | { | ||
1195 | } | 908 | } |
1196 | #endif | ||
1197 | 909 | ||
1198 | static inline void fixup_rfatt_for_txcontrol(struct b43_rfatt *rf, | 910 | /* Fixup the RF attenuation value for the case where we are |
1199 | u8 tx_control) | 911 | * using the PAD mixer. */ |
912 | static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf) | ||
1200 | { | 913 | { |
1201 | if (tx_control & B43_TXCTL_TXMIX) { | 914 | if (!rf->with_padmix) |
1202 | if (rf->att < 5) | 915 | return; |
1203 | rf->att = 4; | 916 | if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3)) |
1204 | } | 917 | rf->att = 4; |
1205 | } | 918 | } |
1206 | 919 | ||
1207 | void b43_lo_g_adjust(struct b43_wldev *dev) | 920 | void b43_lo_g_adjust(struct b43_wldev *dev) |
1208 | { | 921 | { |
1209 | struct b43_phy *phy = &dev->phy; | 922 | struct b43_phy *phy = &dev->phy; |
923 | struct b43_lo_calib *cal; | ||
1210 | struct b43_rfatt rf; | 924 | struct b43_rfatt rf; |
1211 | struct b43_loctl *loctl; | ||
1212 | 925 | ||
1213 | memcpy(&rf, &phy->rfatt, sizeof(rf)); | 926 | memcpy(&rf, &phy->rfatt, sizeof(rf)); |
1214 | fixup_rfatt_for_txcontrol(&rf, phy->tx_control); | 927 | b43_lo_fixup_rfatt(&rf); |
1215 | 928 | ||
1216 | loctl = b43_get_lo_g_ctl(dev, &rf, &phy->bbatt); | 929 | cal = b43_get_calib_lo_settings(dev, &phy->bbatt, &rf); |
1217 | validate_loctl_calibration(dev, loctl, &rf, &phy->bbatt); | 930 | if (!cal) |
1218 | b43_lo_write(dev, loctl); | 931 | return; |
932 | b43_lo_write(dev, &cal->ctl); | ||
1219 | } | 933 | } |
1220 | 934 | ||
1221 | void b43_lo_g_adjust_to(struct b43_wldev *dev, | 935 | void b43_lo_g_adjust_to(struct b43_wldev *dev, |
@@ -1223,39 +937,102 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev, | |||
1223 | { | 937 | { |
1224 | struct b43_rfatt rf; | 938 | struct b43_rfatt rf; |
1225 | struct b43_bbatt bb; | 939 | struct b43_bbatt bb; |
1226 | struct b43_loctl *loctl; | 940 | struct b43_lo_calib *cal; |
1227 | 941 | ||
1228 | memset(&rf, 0, sizeof(rf)); | 942 | memset(&rf, 0, sizeof(rf)); |
1229 | memset(&bb, 0, sizeof(bb)); | 943 | memset(&bb, 0, sizeof(bb)); |
1230 | rf.att = rfatt; | 944 | rf.att = rfatt; |
1231 | bb.att = bbatt; | 945 | bb.att = bbatt; |
1232 | fixup_rfatt_for_txcontrol(&rf, tx_control); | 946 | b43_lo_fixup_rfatt(&rf); |
1233 | loctl = b43_get_lo_g_ctl(dev, &rf, &bb); | 947 | cal = b43_get_calib_lo_settings(dev, &bb, &rf); |
1234 | validate_loctl_calibration(dev, loctl, &rf, &bb); | 948 | if (!cal) |
1235 | b43_lo_write(dev, loctl); | 949 | return; |
950 | b43_lo_write(dev, &cal->ctl); | ||
1236 | } | 951 | } |
1237 | 952 | ||
1238 | static void do_mark_unused(struct b43_wldev *dev, struct b43_loctl *control) | 953 | /* Periodic LO maintanance work */ |
954 | void b43_lo_g_maintanance_work(struct b43_wldev *dev) | ||
1239 | { | 955 | { |
1240 | control->used = 0; | 956 | struct b43_phy *phy = &dev->phy; |
957 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
958 | unsigned long now; | ||
959 | unsigned long expire; | ||
960 | struct b43_lo_calib *cal, *tmp; | ||
961 | bool current_item_expired = 0; | ||
962 | bool hwpctl; | ||
963 | |||
964 | if (!lo) | ||
965 | return; | ||
966 | now = jiffies; | ||
967 | hwpctl = b43_has_hardware_pctl(phy); | ||
968 | |||
969 | if (hwpctl) { | ||
970 | /* Read the power vector and update it, if needed. */ | ||
971 | expire = now - B43_LO_PWRVEC_EXPIRE; | ||
972 | if (time_before(lo->pwr_vec_read_time, expire)) { | ||
973 | lo_read_power_vector(dev); | ||
974 | b43_gphy_dc_lt_init(dev, 0); | ||
975 | } | ||
976 | //FIXME Recalc the whole DC table from time to time? | ||
977 | } | ||
978 | |||
979 | if (hwpctl) | ||
980 | return; | ||
981 | /* Search for expired LO settings. Remove them. | ||
982 | * Recalibrate the current setting, if expired. */ | ||
983 | expire = now - B43_LO_CALIB_EXPIRE; | ||
984 | list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { | ||
985 | if (!time_before(cal->calib_time, expire)) | ||
986 | continue; | ||
987 | /* This item expired. */ | ||
988 | if (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && | ||
989 | b43_compare_rfatt(&cal->rfatt, &phy->rfatt)) { | ||
990 | B43_WARN_ON(current_item_expired); | ||
991 | current_item_expired = 1; | ||
992 | } | ||
993 | if (b43_debug(dev, B43_DBG_LO)) { | ||
994 | b43dbg(dev->wl, "LO: Item BB(%u), RF(%u,%u), " | ||
995 | "I=%d, Q=%d expired\n", | ||
996 | cal->bbatt.att, cal->rfatt.att, | ||
997 | cal->rfatt.with_padmix, | ||
998 | cal->ctl.i, cal->ctl.q); | ||
999 | } | ||
1000 | list_del(&cal->list); | ||
1001 | kfree(cal); | ||
1002 | } | ||
1003 | if (current_item_expired || unlikely(list_empty(&lo->calib_list))) { | ||
1004 | /* Recalibrate currently used LO setting. */ | ||
1005 | if (b43_debug(dev, B43_DBG_LO)) | ||
1006 | b43dbg(dev->wl, "LO: Recalibrating current LO setting\n"); | ||
1007 | cal = b43_calibrate_lo_setting(dev, &phy->bbatt, &phy->rfatt); | ||
1008 | if (cal) { | ||
1009 | list_add(&cal->list, &lo->calib_list); | ||
1010 | b43_lo_write(dev, &cal->ctl); | ||
1011 | } else | ||
1012 | b43warn(dev->wl, "Failed to recalibrate current LO setting\n"); | ||
1013 | } | ||
1241 | } | 1014 | } |
1242 | 1015 | ||
1243 | void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev) | 1016 | void b43_lo_g_cleanup(struct b43_wldev *dev) |
1244 | { | 1017 | { |
1245 | struct b43_phy *phy = &dev->phy; | 1018 | struct b43_txpower_lo_control *lo = dev->phy.lo_control; |
1246 | struct b43_txpower_lo_control *lo = phy->lo_control; | 1019 | struct b43_lo_calib *cal, *tmp; |
1247 | 1020 | ||
1248 | b43_call_for_each_loctl(dev, do_mark_unused); | 1021 | if (!lo) |
1249 | lo->rebuild = 1; | 1022 | return; |
1023 | list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { | ||
1024 | list_del(&cal->list); | ||
1025 | kfree(cal); | ||
1026 | } | ||
1250 | } | 1027 | } |
1251 | 1028 | ||
1252 | void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev) | 1029 | /* LO Initialization */ |
1030 | void b43_lo_g_init(struct b43_wldev *dev) | ||
1253 | { | 1031 | { |
1254 | struct b43_phy *phy = &dev->phy; | 1032 | struct b43_phy *phy = &dev->phy; |
1255 | struct b43_rfatt rf; | ||
1256 | 1033 | ||
1257 | memcpy(&rf, &phy->rfatt, sizeof(rf)); | 1034 | if (b43_has_hardware_pctl(phy)) { |
1258 | fixup_rfatt_for_txcontrol(&rf, phy->tx_control); | 1035 | lo_read_power_vector(dev); |
1259 | 1036 | b43_gphy_dc_lt_init(dev, 1); | |
1260 | b43_get_lo_g_ctl(dev, &rf, &phy->bbatt)->used = 1; | 1037 | } |
1261 | } | 1038 | } |
diff --git a/drivers/net/wireless/b43/lo.h b/drivers/net/wireless/b43/lo.h index 455615d1f8c6..1da321cabc12 100644 --- a/drivers/net/wireless/b43/lo.h +++ b/drivers/net/wireless/b43/lo.h | |||
@@ -10,82 +10,63 @@ struct b43_loctl { | |||
10 | /* Control values. */ | 10 | /* Control values. */ |
11 | s8 i; | 11 | s8 i; |
12 | s8 q; | 12 | s8 q; |
13 | /* "Used by hardware" flag. */ | ||
14 | bool used; | ||
15 | #ifdef CONFIG_B43_DEBUG | ||
16 | /* Is this lo-control-array entry calibrated? */ | ||
17 | bool calibrated; | ||
18 | #endif | ||
19 | }; | 13 | }; |
20 | |||
21 | /* Debugging: Poison value for i and q values. */ | 14 | /* Debugging: Poison value for i and q values. */ |
22 | #define B43_LOCTL_POISON 111 | 15 | #define B43_LOCTL_POISON 111 |
23 | 16 | ||
24 | /* loctl->calibrated debugging mechanism */ | 17 | /* This struct holds calibrated LO settings for a set of |
25 | #ifdef CONFIG_B43_DEBUG | 18 | * Baseband and RF attenuation settings. */ |
26 | static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl, | 19 | struct b43_lo_calib { |
27 | bool calibrated) | 20 | /* The set of attenuation values this set of LO |
28 | { | 21 | * control values is calibrated for. */ |
29 | loctl->calibrated = calibrated; | 22 | struct b43_bbatt bbatt; |
30 | } | 23 | struct b43_rfatt rfatt; |
31 | static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl) | 24 | /* The set of control values for the LO. */ |
32 | { | 25 | struct b43_loctl ctl; |
33 | return loctl->calibrated; | 26 | /* The time when these settings were calibrated (in jiffies) */ |
34 | } | 27 | unsigned long calib_time; |
35 | #else | 28 | /* List. */ |
36 | static inline void b43_loctl_set_calibrated(struct b43_loctl *loctl, | 29 | struct list_head list; |
37 | bool calibrated) | 30 | }; |
38 | { | 31 | |
39 | } | 32 | /* Size of the DC Lookup Table in 16bit words. */ |
40 | static inline bool b43_loctl_is_calibrated(struct b43_loctl *loctl) | 33 | #define B43_DC_LT_SIZE 32 |
41 | { | 34 | |
42 | return 1; | 35 | /* Local Oscillator calibration information */ |
43 | } | ||
44 | #endif | ||
45 | |||
46 | /* TX Power LO Control Array. | ||
47 | * Value-pairs to adjust the LocalOscillator are stored | ||
48 | * in this structure. | ||
49 | * There are two different set of values. One for "Flag is Set" | ||
50 | * and one for "Flag is Unset". | ||
51 | * By "Flag" the flag in struct b43_rfatt is meant. | ||
52 | * The Value arrays are two-dimensional. The first index | ||
53 | * is the baseband attenuation and the second index | ||
54 | * is the radio attenuation. | ||
55 | * Use b43_get_lo_g_ctl() to retrieve a value from the lists. | ||
56 | */ | ||
57 | struct b43_txpower_lo_control { | 36 | struct b43_txpower_lo_control { |
58 | #define B43_NR_BB 12 | 37 | /* Lists of RF and BB attenuation values for this device. |
59 | #define B43_NR_RF 16 | 38 | * Used for building hardware power control tables. */ |
60 | /* LO Control values, with PAD Mixer */ | ||
61 | struct b43_loctl with_padmix[B43_NR_BB][B43_NR_RF]; | ||
62 | /* LO Control values, without PAD Mixer */ | ||
63 | struct b43_loctl no_padmix[B43_NR_BB][B43_NR_RF]; | ||
64 | |||
65 | /* Flag to indicate a complete rebuild of the two tables above | ||
66 | * to the LO measuring code. */ | ||
67 | bool rebuild; | ||
68 | |||
69 | /* Lists of valid RF and BB attenuation values for this device. */ | ||
70 | struct b43_rfatt_list rfatt_list; | 39 | struct b43_rfatt_list rfatt_list; |
71 | struct b43_bbatt_list bbatt_list; | 40 | struct b43_bbatt_list bbatt_list; |
72 | 41 | ||
42 | /* The DC Lookup Table is cached in memory here. | ||
43 | * Note that this is only used for Hardware Power Control. */ | ||
44 | u16 dc_lt[B43_DC_LT_SIZE]; | ||
45 | |||
46 | /* List of calibrated control values (struct b43_lo_calib). */ | ||
47 | struct list_head calib_list; | ||
48 | /* Last time the power vector was read (jiffies). */ | ||
49 | unsigned long pwr_vec_read_time; | ||
50 | /* Last time the txctl values were measured (jiffies). */ | ||
51 | unsigned long txctl_measured_time; | ||
52 | |||
73 | /* Current TX Bias value */ | 53 | /* Current TX Bias value */ |
74 | u8 tx_bias; | 54 | u8 tx_bias; |
75 | /* Current TX Magnification Value (if used by the device) */ | 55 | /* Current TX Magnification Value (if used by the device) */ |
76 | u8 tx_magn; | 56 | u8 tx_magn; |
77 | 57 | ||
78 | /* GPHY LO is measured. */ | ||
79 | bool lo_measured; | ||
80 | |||
81 | /* Saved device PowerVector */ | 58 | /* Saved device PowerVector */ |
82 | u64 power_vector; | 59 | u64 power_vector; |
83 | }; | 60 | }; |
84 | 61 | ||
85 | /* Measure the BPHY Local Oscillator. */ | 62 | /* Calibration expire timeouts. |
86 | void b43_lo_b_measure(struct b43_wldev *dev); | 63 | * Timeouts must be multiple of 15 seconds. To make sure |
87 | /* Measure the BPHY/GPHY Local Oscillator. */ | 64 | * the item really expired when the 15 second timer hits, we |
88 | void b43_lo_g_measure(struct b43_wldev *dev); | 65 | * subtract two additional seconds from the timeout. */ |
66 | #define B43_LO_CALIB_EXPIRE (HZ * (30 - 2)) | ||
67 | #define B43_LO_PWRVEC_EXPIRE (HZ * (30 - 2)) | ||
68 | #define B43_LO_TXCTL_EXPIRE (HZ * (180 - 4)) | ||
69 | |||
89 | 70 | ||
90 | /* Adjust the Local Oscillator to the saved attenuation | 71 | /* Adjust the Local Oscillator to the saved attenuation |
91 | * and txctl values. | 72 | * and txctl values. |
@@ -95,18 +76,10 @@ void b43_lo_g_adjust(struct b43_wldev *dev); | |||
95 | void b43_lo_g_adjust_to(struct b43_wldev *dev, | 76 | void b43_lo_g_adjust_to(struct b43_wldev *dev, |
96 | u16 rfatt, u16 bbatt, u16 tx_control); | 77 | u16 rfatt, u16 bbatt, u16 tx_control); |
97 | 78 | ||
98 | /* Mark all possible b43_lo_g_ctl as "unused" */ | 79 | void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all); |
99 | void b43_lo_g_ctl_mark_all_unused(struct b43_wldev *dev); | ||
100 | /* Mark the b43_lo_g_ctl corresponding to the current | ||
101 | * attenuation values as used. | ||
102 | */ | ||
103 | void b43_lo_g_ctl_mark_cur_used(struct b43_wldev *dev); | ||
104 | 80 | ||
105 | /* Get a reference to a LO Control value pair in the | 81 | void b43_lo_g_maintanance_work(struct b43_wldev *dev); |
106 | * TX Power LO Control Array. | 82 | void b43_lo_g_cleanup(struct b43_wldev *dev); |
107 | */ | 83 | void b43_lo_g_init(struct b43_wldev *dev); |
108 | struct b43_loctl *b43_get_lo_g_ctl(struct b43_wldev *dev, | ||
109 | const struct b43_rfatt *rfatt, | ||
110 | const struct b43_bbatt *bbatt); | ||
111 | 84 | ||
112 | #endif /* B43_LO_H_ */ | 85 | #endif /* B43_LO_H_ */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8fdba9415c04..e3d8555d4a99 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2308,7 +2308,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) | |||
2308 | } | 2308 | } |
2309 | 2309 | ||
2310 | /* http://bcm-specs.sipsolutions.net/EnableMac */ | 2310 | /* http://bcm-specs.sipsolutions.net/EnableMac */ |
2311 | static void b43_mac_enable(struct b43_wldev *dev) | 2311 | void b43_mac_enable(struct b43_wldev *dev) |
2312 | { | 2312 | { |
2313 | dev->mac_suspended--; | 2313 | dev->mac_suspended--; |
2314 | B43_WARN_ON(dev->mac_suspended < 0); | 2314 | B43_WARN_ON(dev->mac_suspended < 0); |
@@ -2331,7 +2331,7 @@ static void b43_mac_enable(struct b43_wldev *dev) | |||
2331 | } | 2331 | } |
2332 | 2332 | ||
2333 | /* http://bcm-specs.sipsolutions.net/SuspendMAC */ | 2333 | /* http://bcm-specs.sipsolutions.net/SuspendMAC */ |
2334 | static void b43_mac_suspend(struct b43_wldev *dev) | 2334 | void b43_mac_suspend(struct b43_wldev *dev) |
2335 | { | 2335 | { |
2336 | int i; | 2336 | int i; |
2337 | u32 tmp; | 2337 | u32 tmp; |
@@ -2503,6 +2503,7 @@ static void b43_chip_exit(struct b43_wldev *dev) | |||
2503 | { | 2503 | { |
2504 | b43_radio_turn_off(dev, 1); | 2504 | b43_radio_turn_off(dev, 1); |
2505 | b43_gpio_cleanup(dev); | 2505 | b43_gpio_cleanup(dev); |
2506 | b43_lo_g_cleanup(dev); | ||
2506 | /* firmware is released later */ | 2507 | /* firmware is released later */ |
2507 | } | 2508 | } |
2508 | 2509 | ||
@@ -2609,28 +2610,12 @@ err_gpio_clean: | |||
2609 | return err; | 2610 | return err; |
2610 | } | 2611 | } |
2611 | 2612 | ||
2612 | static void b43_periodic_every120sec(struct b43_wldev *dev) | ||
2613 | { | ||
2614 | struct b43_phy *phy = &dev->phy; | ||
2615 | |||
2616 | if (phy->type != B43_PHYTYPE_G || phy->rev < 2) | ||
2617 | return; | ||
2618 | |||
2619 | b43_mac_suspend(dev); | ||
2620 | b43_lo_g_measure(dev); | ||
2621 | b43_mac_enable(dev); | ||
2622 | if (b43_has_hardware_pctl(phy)) | ||
2623 | b43_lo_g_ctl_mark_all_unused(dev); | ||
2624 | } | ||
2625 | |||
2626 | static void b43_periodic_every60sec(struct b43_wldev *dev) | 2613 | static void b43_periodic_every60sec(struct b43_wldev *dev) |
2627 | { | 2614 | { |
2628 | struct b43_phy *phy = &dev->phy; | 2615 | struct b43_phy *phy = &dev->phy; |
2629 | 2616 | ||
2630 | if (phy->type != B43_PHYTYPE_G) | 2617 | if (phy->type != B43_PHYTYPE_G) |
2631 | return; | 2618 | return; |
2632 | if (!b43_has_hardware_pctl(phy)) | ||
2633 | b43_lo_g_ctl_mark_all_unused(dev); | ||
2634 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { | 2619 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { |
2635 | b43_mac_suspend(dev); | 2620 | b43_mac_suspend(dev); |
2636 | b43_calc_nrssi_slope(dev); | 2621 | b43_calc_nrssi_slope(dev); |
@@ -2682,6 +2667,7 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) | |||
2682 | } | 2667 | } |
2683 | } | 2668 | } |
2684 | b43_phy_xmitpower(dev); //FIXME: unless scanning? | 2669 | b43_phy_xmitpower(dev); //FIXME: unless scanning? |
2670 | b43_lo_g_maintanance_work(dev); | ||
2685 | //TODO for APHY (temperature?) | 2671 | //TODO for APHY (temperature?) |
2686 | 2672 | ||
2687 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | 2673 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); |
@@ -2693,8 +2679,6 @@ static void do_periodic_work(struct b43_wldev *dev) | |||
2693 | unsigned int state; | 2679 | unsigned int state; |
2694 | 2680 | ||
2695 | state = dev->periodic_state; | 2681 | state = dev->periodic_state; |
2696 | if (state % 8 == 0) | ||
2697 | b43_periodic_every120sec(dev); | ||
2698 | if (state % 4 == 0) | 2682 | if (state % 4 == 0) |
2699 | b43_periodic_every60sec(dev); | 2683 | b43_periodic_every60sec(dev); |
2700 | if (state % 2 == 0) | 2684 | if (state % 2 == 0) |
@@ -3668,8 +3652,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev, | |||
3668 | lo = phy->lo_control; | 3652 | lo = phy->lo_control; |
3669 | if (lo) { | 3653 | if (lo) { |
3670 | memset(lo, 0, sizeof(*(phy->lo_control))); | 3654 | memset(lo, 0, sizeof(*(phy->lo_control))); |
3671 | lo->rebuild = 1; | ||
3672 | lo->tx_bias = 0xFF; | 3655 | lo->tx_bias = 0xFF; |
3656 | INIT_LIST_HEAD(&lo->calib_list); | ||
3673 | } | 3657 | } |
3674 | phy->max_lb_gain = 0; | 3658 | phy->max_lb_gain = 0; |
3675 | phy->trsw_rx_gain = 0; | 3659 | phy->trsw_rx_gain = 0; |
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 5230aeca78bf..dad23c42b422 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -114,4 +114,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason); | |||
114 | #define B43_PS_ASLEEP (1 << 3) /* Force device asleep */ | 114 | #define B43_PS_ASLEEP (1 << 3) /* Force device asleep */ |
115 | void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); | 115 | void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); |
116 | 116 | ||
117 | void b43_mac_suspend(struct b43_wldev *dev); | ||
118 | void b43_mac_enable(struct b43_wldev *dev); | ||
119 | |||
117 | #endif /* B43_MAIN_H_ */ | 120 | #endif /* B43_MAIN_H_ */ |
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index de024dc03718..fd1f301748c2 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c | |||
@@ -145,8 +145,7 @@ static void generate_rfatt_list(struct b43_wldev *dev, | |||
145 | {.att = 9,.with_padmix = 1,}, | 145 | {.att = 9,.with_padmix = 1,}, |
146 | }; | 146 | }; |
147 | 147 | ||
148 | if ((phy->type == B43_PHYTYPE_A && phy->rev < 5) || | 148 | if (!b43_has_hardware_pctl(phy)) { |
149 | (phy->type == B43_PHYTYPE_G && phy->rev < 6)) { | ||
150 | /* Software pctl */ | 149 | /* Software pctl */ |
151 | list->list = rfatt_0; | 150 | list->list = rfatt_0; |
152 | list->len = ARRAY_SIZE(rfatt_0); | 151 | list->len = ARRAY_SIZE(rfatt_0); |
@@ -158,7 +157,7 @@ static void generate_rfatt_list(struct b43_wldev *dev, | |||
158 | /* Hardware pctl */ | 157 | /* Hardware pctl */ |
159 | list->list = rfatt_1; | 158 | list->list = rfatt_1; |
160 | list->len = ARRAY_SIZE(rfatt_1); | 159 | list->len = ARRAY_SIZE(rfatt_1); |
161 | list->min_val = 2; | 160 | list->min_val = 0; |
162 | list->max_val = 14; | 161 | list->max_val = 14; |
163 | return; | 162 | return; |
164 | } | 163 | } |
@@ -346,6 +345,7 @@ void b43_set_txpower_g(struct b43_wldev *dev, | |||
346 | /* Save the values for later */ | 345 | /* Save the values for later */ |
347 | phy->tx_control = tx_control; | 346 | phy->tx_control = tx_control; |
348 | memcpy(&phy->rfatt, rfatt, sizeof(*rfatt)); | 347 | memcpy(&phy->rfatt, rfatt, sizeof(*rfatt)); |
348 | phy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX); | ||
349 | memcpy(&phy->bbatt, bbatt, sizeof(*bbatt)); | 349 | memcpy(&phy->bbatt, bbatt, sizeof(*bbatt)); |
350 | 350 | ||
351 | if (b43_debug(dev, B43_DBG_XMITPOWER)) { | 351 | if (b43_debug(dev, B43_DBG_XMITPOWER)) { |
@@ -559,11 +559,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev) | |||
559 | u16 tmp; | 559 | u16 tmp; |
560 | u8 rf, bb; | 560 | u8 rf, bb; |
561 | 561 | ||
562 | if (!lo->lo_measured) { | ||
563 | b43_phy_write(dev, 0x3FF, 0); | ||
564 | return; | ||
565 | } | ||
566 | |||
567 | for (rf = 0; rf < lo->rfatt_list.len; rf++) { | 562 | for (rf = 0; rf < lo->rfatt_list.len; rf++) { |
568 | for (bb = 0; bb < lo->bbatt_list.len; bb++) { | 563 | for (bb = 0; bb < lo->bbatt_list.len; bb++) { |
569 | if (nr_written >= 0x40) | 564 | if (nr_written >= 0x40) |
@@ -581,42 +576,6 @@ static void b43_gphy_gain_lt_init(struct b43_wldev *dev) | |||
581 | } | 576 | } |
582 | } | 577 | } |
583 | 578 | ||
584 | /* GPHY_DC_Lookup_Table */ | ||
585 | void b43_gphy_dc_lt_init(struct b43_wldev *dev) | ||
586 | { | ||
587 | struct b43_phy *phy = &dev->phy; | ||
588 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
589 | struct b43_loctl *loctl0; | ||
590 | struct b43_loctl *loctl1; | ||
591 | int i; | ||
592 | int rf_offset, bb_offset; | ||
593 | u16 tmp; | ||
594 | |||
595 | for (i = 0; i < lo->rfatt_list.len + lo->bbatt_list.len; i += 2) { | ||
596 | rf_offset = i / lo->rfatt_list.len; | ||
597 | bb_offset = i % lo->rfatt_list.len; | ||
598 | |||
599 | loctl0 = b43_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset], | ||
600 | &lo->bbatt_list.list[bb_offset]); | ||
601 | if (i + 1 < lo->rfatt_list.len * lo->bbatt_list.len) { | ||
602 | rf_offset = (i + 1) / lo->rfatt_list.len; | ||
603 | bb_offset = (i + 1) % lo->rfatt_list.len; | ||
604 | |||
605 | loctl1 = | ||
606 | b43_get_lo_g_ctl(dev, | ||
607 | &lo->rfatt_list.list[rf_offset], | ||
608 | &lo->bbatt_list.list[bb_offset]); | ||
609 | } else | ||
610 | loctl1 = loctl0; | ||
611 | |||
612 | tmp = ((u16) loctl0->q & 0xF); | ||
613 | tmp |= ((u16) loctl0->i & 0xF) << 4; | ||
614 | tmp |= ((u16) loctl1->q & 0xF) << 8; | ||
615 | tmp |= ((u16) loctl1->i & 0xF) << 12; //FIXME? | ||
616 | b43_phy_write(dev, 0x3A0 + (i / 2), tmp); | ||
617 | } | ||
618 | } | ||
619 | |||
620 | static void hardware_pctl_init_aphy(struct b43_wldev *dev) | 579 | static void hardware_pctl_init_aphy(struct b43_wldev *dev) |
621 | { | 580 | { |
622 | //TODO | 581 | //TODO |
@@ -643,7 +602,7 @@ static void hardware_pctl_init_gphy(struct b43_wldev *dev) | |||
643 | b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) | 602 | b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) |
644 | & 0xFFBF); | 603 | & 0xFFBF); |
645 | 604 | ||
646 | b43_gphy_dc_lt_init(dev); | 605 | b43_gphy_dc_lt_init(dev, 1); |
647 | } | 606 | } |
648 | 607 | ||
649 | /* HardwarePowerControl init for A and G PHY */ | 608 | /* HardwarePowerControl init for A and G PHY */ |
@@ -967,7 +926,7 @@ static void b43_phy_initb2(struct b43_wldev *dev) | |||
967 | b43_phy_write(dev, 0x0032, 0x00CA); | 926 | b43_phy_write(dev, 0x0032, 0x00CA); |
968 | b43_phy_write(dev, 0x0032, 0x00CC); | 927 | b43_phy_write(dev, 0x0032, 0x00CC); |
969 | b43_phy_write(dev, 0x0035, 0x07C2); | 928 | b43_phy_write(dev, 0x0035, 0x07C2); |
970 | b43_lo_b_measure(dev); | 929 | //XXX won't trigger b43_lo_b_measure(dev); |
971 | b43_phy_write(dev, 0x0026, 0xCC00); | 930 | b43_phy_write(dev, 0x0026, 0xCC00); |
972 | if (phy->radio_ver != 0x2050) | 931 | if (phy->radio_ver != 0x2050) |
973 | b43_phy_write(dev, 0x0026, 0xCE00); | 932 | b43_phy_write(dev, 0x0026, 0xCE00); |
@@ -1017,7 +976,7 @@ static void b43_phy_initb4(struct b43_wldev *dev) | |||
1017 | b43_phy_write(dev, 0x0032, 0x00E0); | 976 | b43_phy_write(dev, 0x0032, 0x00E0); |
1018 | b43_phy_write(dev, 0x0035, 0x07C2); | 977 | b43_phy_write(dev, 0x0035, 0x07C2); |
1019 | 978 | ||
1020 | b43_lo_b_measure(dev); | 979 | //XXX won't trigger b43_lo_b_measure(dev); |
1021 | 980 | ||
1022 | b43_phy_write(dev, 0x0026, 0xCC00); | 981 | b43_phy_write(dev, 0x0026, 0xCC00); |
1023 | if (phy->radio_ver == 0x2050) | 982 | if (phy->radio_ver == 0x2050) |
@@ -1259,19 +1218,9 @@ static void b43_phy_initb6(struct b43_wldev *dev) | |||
1259 | b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0) | 1218 | b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0) |
1260 | | 0x0004); | 1219 | | 0x0004); |
1261 | } | 1220 | } |
1262 | if (phy->type == B43_PHYTYPE_B) { | 1221 | if (phy->type == B43_PHYTYPE_B) |
1263 | b43_write16(dev, 0x03E6, 0x8140); | 1222 | B43_WARN_ON(1); |
1264 | b43_phy_write(dev, 0x0016, 0x0410); | 1223 | else if (phy->type == B43_PHYTYPE_G) |
1265 | b43_phy_write(dev, 0x0017, 0x0820); | ||
1266 | b43_phy_write(dev, 0x0062, 0x0007); | ||
1267 | b43_radio_init2050(dev); | ||
1268 | b43_lo_g_measure(dev); | ||
1269 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { | ||
1270 | b43_calc_nrssi_slope(dev); | ||
1271 | b43_calc_nrssi_threshold(dev); | ||
1272 | } | ||
1273 | b43_phy_init_pctl(dev); | ||
1274 | } else if (phy->type == B43_PHYTYPE_G) | ||
1275 | b43_write16(dev, 0x03E6, 0x0); | 1224 | b43_write16(dev, 0x03E6, 0x0); |
1276 | } | 1225 | } |
1277 | 1226 | ||
@@ -1534,34 +1483,31 @@ static void b43_phy_initg(struct b43_wldev *dev) | |||
1534 | else | 1483 | else |
1535 | b43_radio_write16(dev, 0x0078, phy->initval); | 1484 | b43_radio_write16(dev, 0x0078, phy->initval); |
1536 | } | 1485 | } |
1537 | if (phy->lo_control->tx_bias == 0xFF) { | 1486 | b43_lo_g_init(dev); |
1538 | b43_lo_g_measure(dev); | 1487 | if (has_tx_magnification(phy)) { |
1488 | b43_radio_write16(dev, 0x52, | ||
1489 | (b43_radio_read16(dev, 0x52) & 0xFF00) | ||
1490 | | phy->lo_control->tx_bias | phy-> | ||
1491 | lo_control->tx_magn); | ||
1539 | } else { | 1492 | } else { |
1540 | if (has_tx_magnification(phy)) { | 1493 | b43_radio_write16(dev, 0x52, |
1541 | b43_radio_write16(dev, 0x52, | 1494 | (b43_radio_read16(dev, 0x52) & 0xFFF0) |
1542 | (b43_radio_read16(dev, 0x52) & 0xFF00) | 1495 | | phy->lo_control->tx_bias); |
1543 | | phy->lo_control->tx_bias | phy-> | ||
1544 | lo_control->tx_magn); | ||
1545 | } else { | ||
1546 | b43_radio_write16(dev, 0x52, | ||
1547 | (b43_radio_read16(dev, 0x52) & 0xFFF0) | ||
1548 | | phy->lo_control->tx_bias); | ||
1549 | } | ||
1550 | if (phy->rev >= 6) { | ||
1551 | b43_phy_write(dev, B43_PHY_CCK(0x36), | ||
1552 | (b43_phy_read(dev, B43_PHY_CCK(0x36)) | ||
1553 | & 0x0FFF) | (phy->lo_control-> | ||
1554 | tx_bias << 12)); | ||
1555 | } | ||
1556 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) | ||
1557 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); | ||
1558 | else | ||
1559 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); | ||
1560 | if (phy->rev < 2) | ||
1561 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101); | ||
1562 | else | ||
1563 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202); | ||
1564 | } | 1496 | } |
1497 | if (phy->rev >= 6) { | ||
1498 | b43_phy_write(dev, B43_PHY_CCK(0x36), | ||
1499 | (b43_phy_read(dev, B43_PHY_CCK(0x36)) | ||
1500 | & 0x0FFF) | (phy->lo_control-> | ||
1501 | tx_bias << 12)); | ||
1502 | } | ||
1503 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) | ||
1504 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); | ||
1505 | else | ||
1506 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); | ||
1507 | if (phy->rev < 2) | ||
1508 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101); | ||
1509 | else | ||
1510 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202); | ||
1565 | if (phy->gmode || phy->rev >= 2) { | 1511 | if (phy->gmode || phy->rev >= 2) { |
1566 | b43_lo_g_adjust(dev); | 1512 | b43_lo_g_adjust(dev); |
1567 | b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); | 1513 | b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); |
@@ -1821,10 +1767,8 @@ void b43_phy_xmitpower(struct b43_wldev *dev) | |||
1821 | bbatt_delta -= 4 * rfatt_delta; | 1767 | bbatt_delta -= 4 * rfatt_delta; |
1822 | 1768 | ||
1823 | /* So do we finally need to adjust something? */ | 1769 | /* So do we finally need to adjust something? */ |
1824 | if ((rfatt_delta == 0) && (bbatt_delta == 0)) { | 1770 | if ((rfatt_delta == 0) && (bbatt_delta == 0)) |
1825 | b43_lo_g_ctl_mark_cur_used(dev); | ||
1826 | return; | 1771 | return; |
1827 | } | ||
1828 | 1772 | ||
1829 | /* Calculate the new attenuation values. */ | 1773 | /* Calculate the new attenuation values. */ |
1830 | bbatt = phy->bbatt.att; | 1774 | bbatt = phy->bbatt.att; |
@@ -1870,7 +1814,6 @@ void b43_phy_xmitpower(struct b43_wldev *dev) | |||
1870 | b43_radio_lock(dev); | 1814 | b43_radio_lock(dev); |
1871 | b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, | 1815 | b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, |
1872 | phy->tx_control); | 1816 | phy->tx_control); |
1873 | b43_lo_g_ctl_mark_cur_used(dev); | ||
1874 | b43_radio_unlock(dev); | 1817 | b43_radio_unlock(dev); |
1875 | b43_phy_unlock(dev); | 1818 | b43_phy_unlock(dev); |
1876 | break; | 1819 | break; |
diff --git a/drivers/net/wireless/b43/phy.h b/drivers/net/wireless/b43/phy.h index 6d165d822175..4aab10903529 100644 --- a/drivers/net/wireless/b43/phy.h +++ b/drivers/net/wireless/b43/phy.h | |||
@@ -225,7 +225,6 @@ int b43_phy_init(struct b43_wldev *dev); | |||
225 | void b43_set_rx_antenna(struct b43_wldev *dev, int antenna); | 225 | void b43_set_rx_antenna(struct b43_wldev *dev, int antenna); |
226 | 226 | ||
227 | void b43_phy_xmitpower(struct b43_wldev *dev); | 227 | void b43_phy_xmitpower(struct b43_wldev *dev); |
228 | void b43_gphy_dc_lt_init(struct b43_wldev *dev); | ||
229 | 228 | ||
230 | /* Returns the boolean whether the board has HardwarePowerControl */ | 229 | /* Returns the boolean whether the board has HardwarePowerControl */ |
231 | bool b43_has_hardware_pctl(struct b43_phy *phy); | 230 | bool b43_has_hardware_pctl(struct b43_phy *phy); |
@@ -252,6 +251,14 @@ struct b43_rfatt_list { | |||
252 | u8 max_val; | 251 | u8 max_val; |
253 | }; | 252 | }; |
254 | 253 | ||
254 | /* Returns true, if the values are the same. */ | ||
255 | static inline bool b43_compare_rfatt(const struct b43_rfatt *a, | ||
256 | const struct b43_rfatt *b) | ||
257 | { | ||
258 | return ((a->att == b->att) && | ||
259 | (a->with_padmix == b->with_padmix)); | ||
260 | } | ||
261 | |||
255 | /* Baseband Attenuation */ | 262 | /* Baseband Attenuation */ |
256 | struct b43_bbatt { | 263 | struct b43_bbatt { |
257 | u8 att; /* Attenuation value */ | 264 | u8 att; /* Attenuation value */ |
@@ -265,6 +272,13 @@ struct b43_bbatt_list { | |||
265 | u8 max_val; | 272 | u8 max_val; |
266 | }; | 273 | }; |
267 | 274 | ||
275 | /* Returns true, if the values are the same. */ | ||
276 | static inline bool b43_compare_bbatt(const struct b43_bbatt *a, | ||
277 | const struct b43_bbatt *b) | ||
278 | { | ||
279 | return (a->att == b->att); | ||
280 | } | ||
281 | |||
268 | /* tx_control bits. */ | 282 | /* tx_control bits. */ |
269 | #define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */ | 283 | #define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */ |
270 | #define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */ | 284 | #define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */ |