Commit fb11137af83b7b66c7aab8dbc5f09d2c95684fed

Authored by Michael Buesch
Committed by John W. Linville
1 parent 7cb770729b

b43: Split PHY alloc and init

This splits the PHY allocation from the PHY init.
This is needed in order to properly support Analog handling.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 11 changed files with 178 additions and 109 deletions Side-by-side Diff

drivers/net/wireless/b43/main.c
... ... @@ -1091,8 +1091,12 @@
1091 1091 ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
1092 1092 msleep(1);
1093 1093  
1094   - /* Turn Analog ON */
1095   - b43_switch_analog(dev, 1);
  1094 + /* Turn Analog ON, but only if we already know the PHY-type.
  1095 + * This protects against very early setup where we don't know the
  1096 + * PHY-type, yet. wireless_core_reset will be called once again later,
  1097 + * when we know the PHY-type. */
  1098 + if (dev->phy.ops)
  1099 + b43_switch_analog(dev, 1);
1096 1100  
1097 1101 macctl = b43_read32(dev, B43_MMIO_MACCTL);
1098 1102 macctl &= ~B43_MACCTL_GMODE;
... ... @@ -2694,6 +2698,7 @@
2694 2698 /* This is the opposite of b43_chip_init() */
2695 2699 static void b43_chip_exit(struct b43_wldev *dev)
2696 2700 {
  2701 + b43_phy_exit(dev);
2697 2702 b43_gpio_cleanup(dev);
2698 2703 /* firmware is released later */
2699 2704 }
... ... @@ -3952,7 +3957,6 @@
3952 3957 dev_kfree_skb_any(dev->wl->current_beacon);
3953 3958 dev->wl->current_beacon = NULL;
3954 3959 }
3955   - b43_phy_exit(dev);
3956 3960  
3957 3961 ssb_device_disable(dev->dev, 0);
3958 3962 ssb_bus_may_powerdown(dev->dev->bus);
3959 3963  
3960 3964  
3961 3965  
3962 3966  
... ... @@ -3979,24 +3983,23 @@
3979 3983 b43_wireless_core_reset(dev, tmp);
3980 3984 }
3981 3985  
  3986 + /* Reset all data structures. */
3982 3987 setup_struct_wldev_for_init(dev);
3983   - err = b43_phy_operations_setup(dev);
3984   - if (err)
3985   - goto err_busdown;
  3988 + phy->ops->prepare_structs(dev);
3986 3989  
3987 3990 /* Enable IRQ routing to this device. */
3988 3991 ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
3989 3992  
3990 3993 b43_imcfglo_timeouts_workaround(dev);
3991 3994 b43_bluetooth_coext_disable(dev);
3992   - if (phy->ops->prepare) {
3993   - err = phy->ops->prepare(dev);
  3995 + if (phy->ops->prepare_hardware) {
  3996 + err = phy->ops->prepare_hardware(dev);
3994 3997 if (err)
3995   - goto err_phy_exit;
  3998 + goto err_busdown;
3996 3999 }
3997 4000 err = b43_chip_init(dev);
3998 4001 if (err)
3999   - goto err_phy_exit;
  4002 + goto err_busdown;
4000 4003 b43_shm_write16(dev, B43_SHM_SHARED,
4001 4004 B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
4002 4005 hf = b43_hf_read(dev);
... ... @@ -4064,8 +4067,6 @@
4064 4067  
4065 4068 err_chip_exit:
4066 4069 b43_chip_exit(dev);
4067   -err_phy_exit:
4068   - b43_phy_exit(dev);
4069 4070 err_busdown:
4070 4071 ssb_bus_may_powerdown(bus);
4071 4072 B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
... ... @@ -4342,6 +4343,7 @@
4342 4343 /* We release firmware that late to not be required to re-request
4343 4344 * is all the time when we reinit the core. */
4344 4345 b43_release_firmware(dev);
  4346 + b43_phy_free(dev);
4345 4347 }
4346 4348  
4347 4349 static int b43_wireless_core_attach(struct b43_wldev *dev)
4348 4350  
4349 4351  
... ... @@ -4415,16 +4417,20 @@
4415 4417 }
4416 4418 }
4417 4419  
  4420 + err = b43_phy_allocate(dev);
  4421 + if (err)
  4422 + goto err_powerdown;
  4423 +
4418 4424 dev->phy.gmode = have_2ghz_phy;
4419 4425 tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
4420 4426 b43_wireless_core_reset(dev, tmp);
4421 4427  
4422 4428 err = b43_validate_chipaccess(dev);
4423 4429 if (err)
4424   - goto err_powerdown;
  4430 + goto err_phy_free;
4425 4431 err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
4426 4432 if (err)
4427   - goto err_powerdown;
  4433 + goto err_phy_free;
4428 4434  
4429 4435 /* Now set some default "current_dev" */
4430 4436 if (!wl->current_dev)
... ... @@ -4438,6 +4444,8 @@
4438 4444 out:
4439 4445 return err;
4440 4446  
  4447 +err_phy_free:
  4448 + b43_phy_free(dev);
4441 4449 err_powerdown:
4442 4450 ssb_bus_may_powerdown(bus);
4443 4451 return err;
drivers/net/wireless/b43/phy_a.c
... ... @@ -391,8 +391,6 @@
391 391 return -ENOMEM;
392 392 dev->phy.a = aphy;
393 393  
394   - //TODO init struct b43_phy_a
395   -
396 394 err = b43_aphy_init_tssi2dbm_table(dev);
397 395 if (err)
398 396 goto err_free_aphy;
399 397  
400 398  
401 399  
402 400  
403 401  
404 402  
405 403  
406 404  
... ... @@ -406,30 +404,47 @@
406 404 return err;
407 405 }
408 406  
409   -static int b43_aphy_op_init(struct b43_wldev *dev)
  407 +static void b43_aphy_op_prepare_structs(struct b43_wldev *dev)
410 408 {
411   - struct b43_phy_a *aphy = dev->phy.a;
  409 + struct b43_phy *phy = &dev->phy;
  410 + struct b43_phy_a *aphy = phy->a;
  411 + const void *tssi2dbm;
  412 + int tgt_idle_tssi;
412 413  
413   - b43_phy_inita(dev);
414   - aphy->initialised = 1;
  414 + /* tssi2dbm table is constant, so it is initialized at alloc time.
  415 + * Save a copy of the pointer. */
  416 + tssi2dbm = aphy->tssi2dbm;
  417 + tgt_idle_tssi = aphy->tgt_idle_tssi;
415 418  
416   - return 0;
  419 + /* Zero out the whole PHY structure. */
  420 + memset(aphy, 0, sizeof(*aphy));
  421 +
  422 + aphy->tssi2dbm = tssi2dbm;
  423 + aphy->tgt_idle_tssi = tgt_idle_tssi;
  424 +
  425 + //TODO init struct b43_phy_a
  426 +
417 427 }
418 428  
419   -static void b43_aphy_op_exit(struct b43_wldev *dev)
  429 +static void b43_aphy_op_free(struct b43_wldev *dev)
420 430 {
421   - struct b43_phy_a *aphy = dev->phy.a;
  431 + struct b43_phy *phy = &dev->phy;
  432 + struct b43_phy_a *aphy = phy->a;
422 433  
423   - if (aphy->initialised) {
424   - //TODO
425   - aphy->initialised = 0;
426   - }
427   - //TODO
428 434 kfree(aphy->tssi2dbm);
  435 + aphy->tssi2dbm = NULL;
  436 +
429 437 kfree(aphy);
430 438 dev->phy.a = NULL;
431 439 }
432 440  
  441 +static int b43_aphy_op_init(struct b43_wldev *dev)
  442 +{
  443 + b43_phy_inita(dev);
  444 +
  445 + return 0;
  446 +}
  447 +
433 448 static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset)
434 449 {
435 450 /* OFDM registers are base-registers for the A-PHY. */
436 451  
... ... @@ -608,8 +623,9 @@
608 623  
609 624 const struct b43_phy_operations b43_phyops_a = {
610 625 .allocate = b43_aphy_op_allocate,
  626 + .free = b43_aphy_op_free,
  627 + .prepare_structs = b43_aphy_op_prepare_structs,
611 628 .init = b43_aphy_op_init,
612   - .exit = b43_aphy_op_exit,
613 629 .phy_read = b43_aphy_op_read,
614 630 .phy_write = b43_aphy_op_write,
615 631 .radio_read = b43_aphy_op_radio_read,
drivers/net/wireless/b43/phy_a.h
... ... @@ -103,8 +103,6 @@
103 103  
104 104  
105 105 struct b43_phy_a {
106   - bool initialised;
107   -
108 106 /* Pointer to the table used to convert a
109 107 * TSSI value to dBm-Q5.2 */
110 108 const s8 *tssi2dbm;
drivers/net/wireless/b43/phy_common.c
... ... @@ -35,7 +35,7 @@
35 35 #include "main.h"
36 36  
37 37  
38   -int b43_phy_operations_setup(struct b43_wldev *dev)
  38 +int b43_phy_allocate(struct b43_wldev *dev)
39 39 {
40 40 struct b43_phy *phy = &(dev->phy);
41 41 int err;
... ... @@ -68,6 +68,12 @@
68 68 phy->ops = NULL;
69 69  
70 70 return err;
  71 +}
  72 +
  73 +void b43_phy_free(struct b43_wldev *dev)
  74 +{
  75 + dev->phy.ops->free(dev);
  76 + dev->phy.ops = NULL;
71 77 }
72 78  
73 79 int b43_phy_init(struct b43_wldev *dev)
drivers/net/wireless/b43/phy_common.h
... ... @@ -74,11 +74,21 @@
74 74 /**
75 75 * struct b43_phy_operations - Function pointers for PHY ops.
76 76 *
77   - * @prepare: Prepare the PHY. This is called before @init.
  77 + * @allocate: Allocate and initialise the PHY data structures.
  78 + * Must not be NULL.
  79 + * @free: Destroy and free the PHY data structures.
  80 + * Must not be NULL.
  81 + *
  82 + * @prepare_structs: Prepare the PHY data structures.
  83 + * The data structures allocated in @allocate are
  84 + * initialized here.
  85 + * Must not be NULL.
  86 + * @prepare_hardware: Prepare the PHY. This is called before b43_chip_init to
  87 + * do some early early PHY hardware init.
78 88 * Can be NULL, if not required.
79 89 * @init: Initialize the PHY.
80 90 * Must not be NULL.
81   - * @exit: Shutdown the PHY and free all data structures.
  91 + * @exit: Shutdown the PHY.
82 92 * Can be NULL, if not required.
83 93 *
84 94 * @phy_read: Read from a PHY register.
... ... @@ -133,7 +143,9 @@
133 143 struct b43_phy_operations {
134 144 /* Initialisation */
135 145 int (*allocate)(struct b43_wldev *dev);
136   - int (*prepare)(struct b43_wldev *dev);
  146 + void (*free)(struct b43_wldev *dev);
  147 + void (*prepare_structs)(struct b43_wldev *dev);
  148 + int (*prepare_hardware)(struct b43_wldev *dev);
137 149 int (*init)(struct b43_wldev *dev);
138 150 void (*exit)(struct b43_wldev *dev);
139 151  
140 152  
... ... @@ -237,10 +249,15 @@
237 249  
238 250  
239 251 /**
240   - * b43_phy_operations_setup - Initialize the PHY operations datastructure
241   - * based on the current PHY type.
  252 + * b43_phy_allocate - Allocate PHY structs
  253 + * Allocate the PHY data structures, based on the current dev->phy.type
242 254 */
243   -int b43_phy_operations_setup(struct b43_wldev *dev);
  255 +int b43_phy_allocate(struct b43_wldev *dev);
  256 +
  257 +/**
  258 + * b43_phy_free - Free PHY structs
  259 + */
  260 +void b43_phy_free(struct b43_wldev *dev);
244 261  
245 262 /**
246 263 * b43_phy_init - Initialise the PHY
drivers/net/wireless/b43/phy_g.c
... ... @@ -2635,7 +2635,7 @@
2635 2635 {
2636 2636 struct b43_phy_g *gphy;
2637 2637 struct b43_txpower_lo_control *lo;
2638   - int err, i;
  2638 + int err;
2639 2639  
2640 2640 gphy = kzalloc(sizeof(*gphy), GFP_KERNEL);
2641 2641 if (!gphy) {
... ... @@ -2644,6 +2644,51 @@
2644 2644 }
2645 2645 dev->phy.g = gphy;
2646 2646  
  2647 + lo = kzalloc(sizeof(*lo), GFP_KERNEL);
  2648 + if (!lo) {
  2649 + err = -ENOMEM;
  2650 + goto err_free_gphy;
  2651 + }
  2652 + gphy->lo_control = lo;
  2653 +
  2654 + err = b43_gphy_init_tssi2dbm_table(dev);
  2655 + if (err)
  2656 + goto err_free_lo;
  2657 +
  2658 + return 0;
  2659 +
  2660 +err_free_lo:
  2661 + kfree(lo);
  2662 +err_free_gphy:
  2663 + kfree(gphy);
  2664 +error:
  2665 + return err;
  2666 +}
  2667 +
  2668 +static void b43_gphy_op_prepare_structs(struct b43_wldev *dev)
  2669 +{
  2670 + struct b43_phy *phy = &dev->phy;
  2671 + struct b43_phy_g *gphy = phy->g;
  2672 + const void *tssi2dbm;
  2673 + int tgt_idle_tssi;
  2674 + struct b43_txpower_lo_control *lo;
  2675 + unsigned int i;
  2676 +
  2677 + /* tssi2dbm table is constant, so it is initialized at alloc time.
  2678 + * Save a copy of the pointer. */
  2679 + tssi2dbm = gphy->tssi2dbm;
  2680 + tgt_idle_tssi = gphy->tgt_idle_tssi;
  2681 + /* Save the LO pointer. */
  2682 + lo = gphy->lo_control;
  2683 +
  2684 + /* Zero out the whole PHY structure. */
  2685 + memset(gphy, 0, sizeof(*gphy));
  2686 +
  2687 + /* Restore pointers. */
  2688 + gphy->tssi2dbm = tssi2dbm;
  2689 + gphy->tgt_idle_tssi = tgt_idle_tssi;
  2690 + gphy->lo_control = lo;
  2691 +
2647 2692 memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig));
2648 2693  
2649 2694 /* NRSSI */
2650 2695  
2651 2696  
2652 2697  
2653 2698  
2654 2699  
2655 2700  
... ... @@ -2662,31 +2707,28 @@
2662 2707  
2663 2708 gphy->average_tssi = 0xFF;
2664 2709  
2665   - lo = kzalloc(sizeof(*lo), GFP_KERNEL);
2666   - if (!lo) {
2667   - err = -ENOMEM;
2668   - goto err_free_gphy;
2669   - }
2670   - gphy->lo_control = lo;
2671   -
  2710 + /* Local Osciallator structure */
2672 2711 lo->tx_bias = 0xFF;
2673 2712 INIT_LIST_HEAD(&lo->calib_list);
  2713 +}
2674 2714  
2675   - err = b43_gphy_init_tssi2dbm_table(dev);
2676   - if (err)
2677   - goto err_free_lo;
  2715 +static void b43_gphy_op_free(struct b43_wldev *dev)
  2716 +{
  2717 + struct b43_phy *phy = &dev->phy;
  2718 + struct b43_phy_g *gphy = phy->g;
2678 2719  
2679   - return 0;
  2720 + kfree(gphy->lo_control);
2680 2721  
2681   -err_free_lo:
2682   - kfree(lo);
2683   -err_free_gphy:
  2722 + if (gphy->dyn_tssi_tbl)
  2723 + kfree(gphy->tssi2dbm);
  2724 + gphy->dyn_tssi_tbl = 0;
  2725 + gphy->tssi2dbm = NULL;
  2726 +
2684 2727 kfree(gphy);
2685   -error:
2686   - return err;
  2728 + dev->phy.g = NULL;
2687 2729 }
2688 2730  
2689   -static int b43_gphy_op_prepare(struct b43_wldev *dev)
  2731 +static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
2690 2732 {
2691 2733 struct b43_phy *phy = &dev->phy;
2692 2734 struct b43_phy_g *gphy = phy->g;
2693 2735  
2694 2736  
2695 2737  
... ... @@ -2718,28 +2760,14 @@
2718 2760  
2719 2761 static int b43_gphy_op_init(struct b43_wldev *dev)
2720 2762 {
2721   - struct b43_phy_g *gphy = dev->phy.g;
2722   -
2723 2763 b43_phy_initg(dev);
2724   - gphy->initialised = 1;
2725 2764  
2726 2765 return 0;
2727 2766 }
2728 2767  
2729 2768 static void b43_gphy_op_exit(struct b43_wldev *dev)
2730 2769 {
2731   - struct b43_phy_g *gphy = dev->phy.g;
2732   -
2733   - if (gphy->initialised) {
2734   - //TODO
2735   - gphy->initialised = 0;
2736   - }
2737 2770 b43_lo_g_cleanup(dev);
2738   - kfree(gphy->lo_control);
2739   - if (gphy->dyn_tssi_tbl)
2740   - kfree(gphy->tssi2dbm);
2741   - kfree(gphy);
2742   - dev->phy.g = NULL;
2743 2771 }
2744 2772  
2745 2773 static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg)
... ... @@ -3232,7 +3260,9 @@
3232 3260  
3233 3261 const struct b43_phy_operations b43_phyops_g = {
3234 3262 .allocate = b43_gphy_op_allocate,
3235   - .prepare = b43_gphy_op_prepare,
  3263 + .free = b43_gphy_op_free,
  3264 + .prepare_structs = b43_gphy_op_prepare_structs,
  3265 + .prepare_hardware = b43_gphy_op_prepare_hardware,
3236 3266 .init = b43_gphy_op_init,
3237 3267 .exit = b43_gphy_op_exit,
3238 3268 .phy_read = b43_gphy_op_read,
drivers/net/wireless/b43/phy_g.h
... ... @@ -114,8 +114,6 @@
114 114 struct b43_txpower_lo_control;
115 115  
116 116 struct b43_phy_g {
117   - bool initialised;
118   -
119 117 /* ACI (adjacent channel interference) flags. */
120 118 bool aci_enable;
121 119 bool aci_wlan_automatic;
drivers/net/wireless/b43/phy_lp.c
... ... @@ -36,34 +36,34 @@
36 36 return -ENOMEM;
37 37 dev->phy.lp = lpphy;
38 38  
39   - //TODO
40   -
41 39 return 0;
42 40 }
43 41  
44   -static int b43_lpphy_op_init(struct b43_wldev *dev)
  42 +static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
45 43 {
46   - struct b43_phy_lp *lpphy = dev->phy.lp;
  44 + struct b43_phy *phy = &dev->phy;
  45 + struct b43_phy_lp *lpphy = phy->lp;
47 46  
48   - //TODO
49   - lpphy->initialised = 1;
  47 + memset(lpphy, 0, sizeof(*lpphy));
50 48  
51   - return 0;
  49 + //TODO
52 50 }
53 51  
54   -static void b43_lpphy_op_exit(struct b43_wldev *dev)
  52 +static void b43_lpphy_op_free(struct b43_wldev *dev)
55 53 {
56 54 struct b43_phy_lp *lpphy = dev->phy.lp;
57 55  
58   - if (lpphy->initialised) {
59   - //TODO
60   - lpphy->initialised = 0;
61   - }
62   -
63 56 kfree(lpphy);
64 57 dev->phy.lp = NULL;
65 58 }
66 59  
  60 +static int b43_lpphy_op_init(struct b43_wldev *dev)
  61 +{
  62 + //TODO
  63 +
  64 + return 0;
  65 +}
  66 +
67 67 static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
68 68 {
69 69 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
70 70  
... ... @@ -138,8 +138,9 @@
138 138  
139 139 const struct b43_phy_operations b43_phyops_lp = {
140 140 .allocate = b43_lpphy_op_allocate,
  141 + .free = b43_lpphy_op_free,
  142 + .prepare_structs = b43_lpphy_op_prepare_structs,
141 143 .init = b43_lpphy_op_init,
142   - .exit = b43_lpphy_op_exit,
143 144 .phy_read = b43_lpphy_op_read,
144 145 .phy_write = b43_lpphy_op_write,
145 146 .radio_read = b43_lpphy_op_radio_read,
drivers/net/wireless/b43/phy_lp.h
... ... @@ -530,7 +530,7 @@
530 530  
531 531  
532 532 struct b43_phy_lp {
533   - bool initialised;
  533 + //TODO
534 534 };
535 535  
536 536  
drivers/net/wireless/b43/phy_n.c
... ... @@ -499,37 +499,33 @@
499 499 return -ENOMEM;
500 500 dev->phy.n = nphy;
501 501  
502   - //TODO init struct b43_phy_n
503   -
504 502 return 0;
505 503 }
506 504  
507   -static int b43_nphy_op_init(struct b43_wldev *dev)
  505 +static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
508 506 {
509   - struct b43_phy_n *nphy = dev->phy.n;
510   - int err;
  507 + struct b43_phy *phy = &dev->phy;
  508 + struct b43_phy_n *nphy = phy->n;
511 509  
512   - err = b43_phy_initn(dev);
513   - if (err)
514   - return err;
515   - nphy->initialised = 1;
  510 + memset(nphy, 0, sizeof(*nphy));
516 511  
517   - return 0;
  512 + //TODO init struct b43_phy_n
518 513 }
519 514  
520   -static void b43_nphy_op_exit(struct b43_wldev *dev)
  515 +static void b43_nphy_op_free(struct b43_wldev *dev)
521 516 {
522   - struct b43_phy_n *nphy = dev->phy.n;
  517 + struct b43_phy *phy = &dev->phy;
  518 + struct b43_phy_n *nphy = phy->n;
523 519  
524   - if (nphy->initialised) {
525   - //TODO
526   - nphy->initialised = 0;
527   - }
528   - //TODO
529 520 kfree(nphy);
530   - dev->phy.n = NULL;
  521 + phy->n = NULL;
531 522 }
532 523  
  524 +static int b43_nphy_op_init(struct b43_wldev *dev)
  525 +{
  526 + return b43_phy_initn(dev);
  527 +}
  528 +
533 529 static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
534 530 {
535 531 #if B43_DEBUG
536 532  
... ... @@ -610,8 +606,9 @@
610 606  
611 607 const struct b43_phy_operations b43_phyops_n = {
612 608 .allocate = b43_nphy_op_allocate,
  609 + .free = b43_nphy_op_free,
  610 + .prepare_structs = b43_nphy_op_prepare_structs,
613 611 .init = b43_nphy_op_init,
614   - .exit = b43_nphy_op_exit,
615 612 .phy_read = b43_nphy_op_read,
616 613 .phy_write = b43_nphy_op_write,
617 614 .radio_read = b43_nphy_op_radio_read,
drivers/net/wireless/b43/phy_n.h
... ... @@ -920,8 +920,6 @@
920 920 struct b43_wldev;
921 921  
922 922 struct b43_phy_n {
923   - bool initialised;
924   -
925 923 //TODO lots of missing stuff
926 924 };
927 925