Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Michael Buesch and committed by
John W. Linville
fb11137a 7cb77072

+193 -124
+22 -14
drivers/net/wireless/b43/main.c
··· 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; ··· 2698 2694 /* This is the opposite of b43_chip_init() */ 2699 2695 static void b43_chip_exit(struct b43_wldev *dev) 2700 2696 { 2697 + b43_phy_exit(dev); 2701 2698 b43_gpio_cleanup(dev); 2702 2699 /* firmware is released later */ 2703 2700 } ··· 3957 3952 dev_kfree_skb_any(dev->wl->current_beacon); 3958 3953 dev->wl->current_beacon = NULL; 3959 3954 } 3960 - b43_phy_exit(dev); 3961 3955 3962 3956 ssb_device_disable(dev->dev, 0); 3963 3957 ssb_bus_may_powerdown(dev->dev->bus); ··· 3983 3979 b43_wireless_core_reset(dev, tmp); 3984 3980 } 3985 3981 3982 + /* Reset all data structures. */ 3986 3983 setup_struct_wldev_for_init(dev); 3987 - err = b43_phy_operations_setup(dev); 3988 - if (err) 3989 - goto err_busdown; 3984 + phy->ops->prepare_structs(dev); 3990 3985 3991 3986 /* Enable IRQ routing to this device. */ 3992 3987 ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); 3993 3988 3994 3989 b43_imcfglo_timeouts_workaround(dev); 3995 3990 b43_bluetooth_coext_disable(dev); 3996 - if (phy->ops->prepare) { 3997 - err = phy->ops->prepare(dev); 3991 + if (phy->ops->prepare_hardware) { 3992 + err = phy->ops->prepare_hardware(dev); 3998 3993 if (err) 3999 - goto err_phy_exit; 3994 + goto err_busdown; 4000 3995 } 4001 3996 err = b43_chip_init(dev); 4002 3997 if (err) 4003 - goto err_phy_exit; 3998 + goto err_busdown; 4004 3999 b43_shm_write16(dev, B43_SHM_SHARED, 4005 4000 B43_SHM_SH_WLCOREREV, dev->dev->id.revision); 4006 4001 hf = b43_hf_read(dev); ··· 4067 4064 4068 4065 err_chip_exit: 4069 4066 b43_chip_exit(dev); 4070 - err_phy_exit: 4071 - b43_phy_exit(dev); 4072 4067 err_busdown: 4073 4068 ssb_bus_may_powerdown(bus); 4074 4069 B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); ··· 4343 4342 /* We release firmware that late to not be required to re-request 4344 4343 * is all the time when we reinit the core. */ 4345 4344 b43_release_firmware(dev); 4345 + b43_phy_free(dev); 4346 4346 } 4347 4347 4348 4348 static int b43_wireless_core_attach(struct b43_wldev *dev) ··· 4417 4415 } 4418 4416 } 4419 4417 4418 + err = b43_phy_allocate(dev); 4419 + if (err) 4420 + goto err_powerdown; 4421 + 4420 4422 dev->phy.gmode = have_2ghz_phy; 4421 4423 tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; 4422 4424 b43_wireless_core_reset(dev, tmp); 4423 4425 4424 4426 err = b43_validate_chipaccess(dev); 4425 4427 if (err) 4426 - goto err_powerdown; 4428 + goto err_phy_free; 4427 4429 err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy); 4428 4430 if (err) 4429 - goto err_powerdown; 4431 + goto err_phy_free; 4430 4432 4431 4433 /* Now set some default "current_dev" */ 4432 4434 if (!wl->current_dev) ··· 4444 4438 out: 4445 4439 return err; 4446 4440 4441 + err_phy_free: 4442 + b43_phy_free(dev); 4447 4443 err_powerdown: 4448 4444 ssb_bus_may_powerdown(bus); 4449 4445 return err;
+31 -15
drivers/net/wireless/b43/phy_a.c
··· 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; ··· 404 406 return err; 405 407 } 406 408 407 - static int b43_aphy_op_init(struct b43_wldev *dev) 409 + static void b43_aphy_op_prepare_structs(struct b43_wldev *dev) 408 410 { 409 - struct b43_phy_a *aphy = dev->phy.a; 411 + struct b43_phy *phy = &dev->phy; 412 + struct b43_phy_a *aphy = phy->a; 413 + const void *tssi2dbm; 414 + int tgt_idle_tssi; 410 415 411 - b43_phy_inita(dev); 412 - aphy->initialised = 1; 416 + /* tssi2dbm table is constant, so it is initialized at alloc time. 417 + * Save a copy of the pointer. */ 418 + tssi2dbm = aphy->tssi2dbm; 419 + tgt_idle_tssi = aphy->tgt_idle_tssi; 413 420 414 - return 0; 421 + /* Zero out the whole PHY structure. */ 422 + memset(aphy, 0, sizeof(*aphy)); 423 + 424 + aphy->tssi2dbm = tssi2dbm; 425 + aphy->tgt_idle_tssi = tgt_idle_tssi; 426 + 427 + //TODO init struct b43_phy_a 428 + 415 429 } 416 430 417 - static void b43_aphy_op_exit(struct b43_wldev *dev) 431 + static void b43_aphy_op_free(struct b43_wldev *dev) 418 432 { 419 - struct b43_phy_a *aphy = dev->phy.a; 433 + struct b43_phy *phy = &dev->phy; 434 + struct b43_phy_a *aphy = phy->a; 420 435 421 - if (aphy->initialised) { 422 - //TODO 423 - aphy->initialised = 0; 424 - } 425 - //TODO 426 436 kfree(aphy->tssi2dbm); 437 + aphy->tssi2dbm = NULL; 438 + 427 439 kfree(aphy); 428 440 dev->phy.a = NULL; 441 + } 442 + 443 + static int b43_aphy_op_init(struct b43_wldev *dev) 444 + { 445 + b43_phy_inita(dev); 446 + 447 + return 0; 429 448 } 430 449 431 450 static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset) ··· 623 608 624 609 const struct b43_phy_operations b43_phyops_a = { 625 610 .allocate = b43_aphy_op_allocate, 611 + .free = b43_aphy_op_free, 612 + .prepare_structs = b43_aphy_op_prepare_structs, 626 613 .init = b43_aphy_op_init, 627 - .exit = b43_aphy_op_exit, 628 614 .phy_read = b43_aphy_op_read, 629 615 .phy_write = b43_aphy_op_write, 630 616 .radio_read = b43_aphy_op_radio_read,
-2
drivers/net/wireless/b43/phy_a.h
··· 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;
+7 -1
drivers/net/wireless/b43/phy_common.c
··· 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 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)
+23 -6
drivers/net/wireless/b43/phy_common.h
··· 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. ··· 143 133 struct b43_phy_operations { 144 134 /* Initialisation */ 145 135 int (*allocate)(struct b43_wldev *dev); 146 - int (*prepare)(struct b43_wldev *dev); 136 + void (*free)(struct b43_wldev *dev); 137 + void (*prepare_structs)(struct b43_wldev *dev); 138 + int (*prepare_hardware)(struct b43_wldev *dev); 147 139 int (*init)(struct b43_wldev *dev); 148 140 void (*exit)(struct b43_wldev *dev); 149 141 ··· 249 237 250 238 251 239 /** 252 - * b43_phy_operations_setup - Initialize the PHY operations datastructure 253 - * based on the current PHY type. 240 + * b43_phy_allocate - Allocate PHY structs 241 + * Allocate the PHY data structures, based on the current dev->phy.type 254 242 */ 255 - int b43_phy_operations_setup(struct b43_wldev *dev); 243 + int b43_phy_allocate(struct b43_wldev *dev); 244 + 245 + /** 246 + * b43_phy_free - Free PHY structs 247 + */ 248 + void b43_phy_free(struct b43_wldev *dev); 256 249 257 250 /** 258 251 * b43_phy_init - Initialise the PHY
+67 -37
drivers/net/wireless/b43/phy_g.c
··· 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) { ··· 2643 2643 goto error; 2644 2644 } 2645 2645 dev->phy.g = gphy; 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; 2646 2691 2647 2692 memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig)); 2648 2693 ··· 2707 2662 2708 2663 gphy->average_tssi = 0xFF; 2709 2664 2710 - lo = kzalloc(sizeof(*lo), GFP_KERNEL); 2711 - if (!lo) { 2712 - err = -ENOMEM; 2713 - goto err_free_gphy; 2714 - } 2715 - gphy->lo_control = lo; 2716 - 2665 + /* Local Osciallator structure */ 2717 2666 lo->tx_bias = 0xFF; 2718 2667 INIT_LIST_HEAD(&lo->calib_list); 2719 - 2720 - err = b43_gphy_init_tssi2dbm_table(dev); 2721 - if (err) 2722 - goto err_free_lo; 2723 - 2724 - return 0; 2725 - 2726 - err_free_lo: 2727 - kfree(lo); 2728 - err_free_gphy: 2729 - kfree(gphy); 2730 - error: 2731 - return err; 2732 2668 } 2733 2669 2734 - static int b43_gphy_op_prepare(struct b43_wldev *dev) 2670 + static void b43_gphy_op_free(struct b43_wldev *dev) 2671 + { 2672 + struct b43_phy *phy = &dev->phy; 2673 + struct b43_phy_g *gphy = phy->g; 2674 + 2675 + kfree(gphy->lo_control); 2676 + 2677 + if (gphy->dyn_tssi_tbl) 2678 + kfree(gphy->tssi2dbm); 2679 + gphy->dyn_tssi_tbl = 0; 2680 + gphy->tssi2dbm = NULL; 2681 + 2682 + kfree(gphy); 2683 + dev->phy.g = NULL; 2684 + } 2685 + 2686 + static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev) 2735 2687 { 2736 2688 struct b43_phy *phy = &dev->phy; 2737 2689 struct b43_phy_g *gphy = phy->g; ··· 2760 2718 2761 2719 static int b43_gphy_op_init(struct b43_wldev *dev) 2762 2720 { 2763 - struct b43_phy_g *gphy = dev->phy.g; 2764 - 2765 2721 b43_phy_initg(dev); 2766 - gphy->initialised = 1; 2767 2722 2768 2723 return 0; 2769 2724 } 2770 2725 2771 2726 static void b43_gphy_op_exit(struct b43_wldev *dev) 2772 2727 { 2773 - struct b43_phy_g *gphy = dev->phy.g; 2774 - 2775 - if (gphy->initialised) { 2776 - //TODO 2777 - gphy->initialised = 0; 2778 - } 2779 2728 b43_lo_g_cleanup(dev); 2780 - kfree(gphy->lo_control); 2781 - if (gphy->dyn_tssi_tbl) 2782 - kfree(gphy->tssi2dbm); 2783 - kfree(gphy); 2784 - dev->phy.g = NULL; 2785 2729 } 2786 2730 2787 2731 static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg) ··· 3260 3232 3261 3233 const struct b43_phy_operations b43_phyops_g = { 3262 3234 .allocate = b43_gphy_op_allocate, 3263 - .prepare = b43_gphy_op_prepare, 3235 + .free = b43_gphy_op_free, 3236 + .prepare_structs = b43_gphy_op_prepare_structs, 3237 + .prepare_hardware = b43_gphy_op_prepare_hardware, 3264 3238 .init = b43_gphy_op_init, 3265 3239 .exit = b43_gphy_op_exit, 3266 3240 .phy_read = b43_gphy_op_read,
-2
drivers/net/wireless/b43/phy_g.h
··· 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;
+20 -19
drivers/net/wireless/b43/phy_lp.c
··· 36 36 return -ENOMEM; 37 37 dev->phy.lp = lpphy; 38 38 39 - //TODO 40 - 41 39 return 0; 40 + } 41 + 42 + static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev) 43 + { 44 + struct b43_phy *phy = &dev->phy; 45 + struct b43_phy_lp *lpphy = phy->lp; 46 + 47 + memset(lpphy, 0, sizeof(*lpphy)); 48 + 49 + //TODO 50 + } 51 + 52 + static void b43_lpphy_op_free(struct b43_wldev *dev) 53 + { 54 + struct b43_phy_lp *lpphy = dev->phy.lp; 55 + 56 + kfree(lpphy); 57 + dev->phy.lp = NULL; 42 58 } 43 59 44 60 static int b43_lpphy_op_init(struct b43_wldev *dev) 45 61 { 46 - struct b43_phy_lp *lpphy = dev->phy.lp; 47 - 48 62 //TODO 49 - lpphy->initialised = 1; 50 63 51 64 return 0; 52 - } 53 - 54 - static void b43_lpphy_op_exit(struct b43_wldev *dev) 55 - { 56 - struct b43_phy_lp *lpphy = dev->phy.lp; 57 - 58 - if (lpphy->initialised) { 59 - //TODO 60 - lpphy->initialised = 0; 61 - } 62 - 63 - kfree(lpphy); 64 - dev->phy.lp = NULL; 65 65 } 66 66 67 67 static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg) ··· 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,
+1 -1
drivers/net/wireless/b43/phy_lp.h
··· 530 530 531 531 532 532 struct b43_phy_lp { 533 - bool initialised; 533 + //TODO 534 534 }; 535 535 536 536
+22 -25
drivers/net/wireless/b43/phy_n.c
··· 499 499 return -ENOMEM; 500 500 dev->phy.n = nphy; 501 501 502 - //TODO init struct b43_phy_n 503 - 504 502 return 0; 503 + } 504 + 505 + static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) 506 + { 507 + struct b43_phy *phy = &dev->phy; 508 + struct b43_phy_n *nphy = phy->n; 509 + 510 + memset(nphy, 0, sizeof(*nphy)); 511 + 512 + //TODO init struct b43_phy_n 513 + } 514 + 515 + static void b43_nphy_op_free(struct b43_wldev *dev) 516 + { 517 + struct b43_phy *phy = &dev->phy; 518 + struct b43_phy_n *nphy = phy->n; 519 + 520 + kfree(nphy); 521 + phy->n = NULL; 505 522 } 506 523 507 524 static int b43_nphy_op_init(struct b43_wldev *dev) 508 525 { 509 - struct b43_phy_n *nphy = dev->phy.n; 510 - int err; 511 - 512 - err = b43_phy_initn(dev); 513 - if (err) 514 - return err; 515 - nphy->initialised = 1; 516 - 517 - return 0; 518 - } 519 - 520 - static void b43_nphy_op_exit(struct b43_wldev *dev) 521 - { 522 - struct b43_phy_n *nphy = dev->phy.n; 523 - 524 - if (nphy->initialised) { 525 - //TODO 526 - nphy->initialised = 0; 527 - } 528 - //TODO 529 - kfree(nphy); 530 - dev->phy.n = NULL; 526 + return b43_phy_initn(dev); 531 527 } 532 528 533 529 static inline void check_phyreg(struct b43_wldev *dev, u16 offset) ··· 606 610 607 611 const struct b43_phy_operations b43_phyops_n = { 608 612 .allocate = b43_nphy_op_allocate, 613 + .free = b43_nphy_op_free, 614 + .prepare_structs = b43_nphy_op_prepare_structs, 609 615 .init = b43_nphy_op_init, 610 - .exit = b43_nphy_op_exit, 611 616 .phy_read = b43_nphy_op_read, 612 617 .phy_write = b43_nphy_op_write, 613 618 .radio_read = b43_nphy_op_radio_read,
-2
drivers/net/wireless/b43/phy_n.h
··· 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