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>
This commit is contained in:
Michael Buesch 2008-09-02 13:00:34 +02:00 committed by John W. Linville
parent 7cb770729b
commit fb11137af8
11 changed files with 193 additions and 124 deletions

View File

@ -1091,8 +1091,12 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
msleep(1); msleep(1);
/* Turn Analog ON */ /* Turn Analog ON, but only if we already know the PHY-type.
b43_switch_analog(dev, 1); * This protects against very early setup where we don't know the
* PHY-type, yet. wireless_core_reset will be called once again later,
* when we know the PHY-type. */
if (dev->phy.ops)
b43_switch_analog(dev, 1);
macctl = b43_read32(dev, B43_MMIO_MACCTL); macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl &= ~B43_MACCTL_GMODE; macctl &= ~B43_MACCTL_GMODE;
@ -2694,6 +2698,7 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
/* This is the opposite of b43_chip_init() */ /* This is the opposite of b43_chip_init() */
static void b43_chip_exit(struct b43_wldev *dev) static void b43_chip_exit(struct b43_wldev *dev)
{ {
b43_phy_exit(dev);
b43_gpio_cleanup(dev); b43_gpio_cleanup(dev);
/* firmware is released later */ /* firmware is released later */
} }
@ -3952,7 +3957,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
dev_kfree_skb_any(dev->wl->current_beacon); dev_kfree_skb_any(dev->wl->current_beacon);
dev->wl->current_beacon = NULL; dev->wl->current_beacon = NULL;
} }
b43_phy_exit(dev);
ssb_device_disable(dev->dev, 0); ssb_device_disable(dev->dev, 0);
ssb_bus_may_powerdown(dev->dev->bus); ssb_bus_may_powerdown(dev->dev->bus);
@ -3979,24 +3983,23 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_wireless_core_reset(dev, tmp); b43_wireless_core_reset(dev, tmp);
} }
/* Reset all data structures. */
setup_struct_wldev_for_init(dev); setup_struct_wldev_for_init(dev);
err = b43_phy_operations_setup(dev); phy->ops->prepare_structs(dev);
if (err)
goto err_busdown;
/* Enable IRQ routing to this device. */ /* Enable IRQ routing to this device. */
ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
b43_imcfglo_timeouts_workaround(dev); b43_imcfglo_timeouts_workaround(dev);
b43_bluetooth_coext_disable(dev); b43_bluetooth_coext_disable(dev);
if (phy->ops->prepare) { if (phy->ops->prepare_hardware) {
err = phy->ops->prepare(dev); err = phy->ops->prepare_hardware(dev);
if (err) if (err)
goto err_phy_exit; goto err_busdown;
} }
err = b43_chip_init(dev); err = b43_chip_init(dev);
if (err) if (err)
goto err_phy_exit; goto err_busdown;
b43_shm_write16(dev, B43_SHM_SHARED, b43_shm_write16(dev, B43_SHM_SHARED,
B43_SHM_SH_WLCOREREV, dev->dev->id.revision); B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
hf = b43_hf_read(dev); hf = b43_hf_read(dev);
@ -4064,8 +4067,6 @@ out:
err_chip_exit: err_chip_exit:
b43_chip_exit(dev); b43_chip_exit(dev);
err_phy_exit:
b43_phy_exit(dev);
err_busdown: err_busdown:
ssb_bus_may_powerdown(bus); ssb_bus_may_powerdown(bus);
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
@ -4342,6 +4343,7 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)
/* We release firmware that late to not be required to re-request /* We release firmware that late to not be required to re-request
* is all the time when we reinit the core. */ * is all the time when we reinit the core. */
b43_release_firmware(dev); b43_release_firmware(dev);
b43_phy_free(dev);
} }
static int b43_wireless_core_attach(struct b43_wldev *dev) static int b43_wireless_core_attach(struct b43_wldev *dev)
@ -4415,16 +4417,20 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
} }
} }
err = b43_phy_allocate(dev);
if (err)
goto err_powerdown;
dev->phy.gmode = have_2ghz_phy; dev->phy.gmode = have_2ghz_phy;
tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
b43_wireless_core_reset(dev, tmp); b43_wireless_core_reset(dev, tmp);
err = b43_validate_chipaccess(dev); err = b43_validate_chipaccess(dev);
if (err) if (err)
goto err_powerdown; goto err_phy_free;
err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy); err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
if (err) if (err)
goto err_powerdown; goto err_phy_free;
/* Now set some default "current_dev" */ /* Now set some default "current_dev" */
if (!wl->current_dev) if (!wl->current_dev)
@ -4438,6 +4444,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
out: out:
return err; return err;
err_phy_free:
b43_phy_free(dev);
err_powerdown: err_powerdown:
ssb_bus_may_powerdown(bus); ssb_bus_may_powerdown(bus);
return err; return err;

View File

@ -391,8 +391,6 @@ static int b43_aphy_op_allocate(struct b43_wldev *dev)
return -ENOMEM; return -ENOMEM;
dev->phy.a = aphy; dev->phy.a = aphy;
//TODO init struct b43_phy_a
err = b43_aphy_init_tssi2dbm_table(dev); err = b43_aphy_init_tssi2dbm_table(dev);
if (err) if (err)
goto err_free_aphy; goto err_free_aphy;
@ -406,30 +404,47 @@ err_free_aphy:
return err; return err;
} }
static int b43_aphy_op_init(struct b43_wldev *dev) static void b43_aphy_op_prepare_structs(struct b43_wldev *dev)
{ {
struct b43_phy_a *aphy = dev->phy.a; struct b43_phy *phy = &dev->phy;
struct b43_phy_a *aphy = phy->a;
const void *tssi2dbm;
int tgt_idle_tssi;
b43_phy_inita(dev); /* tssi2dbm table is constant, so it is initialized at alloc time.
aphy->initialised = 1; * Save a copy of the pointer. */
tssi2dbm = aphy->tssi2dbm;
tgt_idle_tssi = aphy->tgt_idle_tssi;
/* Zero out the whole PHY structure. */
memset(aphy, 0, sizeof(*aphy));
aphy->tssi2dbm = tssi2dbm;
aphy->tgt_idle_tssi = tgt_idle_tssi;
//TODO init struct b43_phy_a
return 0;
} }
static void b43_aphy_op_exit(struct b43_wldev *dev) static void b43_aphy_op_free(struct b43_wldev *dev)
{ {
struct b43_phy_a *aphy = dev->phy.a; struct b43_phy *phy = &dev->phy;
struct b43_phy_a *aphy = phy->a;
if (aphy->initialised) {
//TODO
aphy->initialised = 0;
}
//TODO
kfree(aphy->tssi2dbm); kfree(aphy->tssi2dbm);
aphy->tssi2dbm = NULL;
kfree(aphy); kfree(aphy);
dev->phy.a = NULL; dev->phy.a = NULL;
} }
static int b43_aphy_op_init(struct b43_wldev *dev)
{
b43_phy_inita(dev);
return 0;
}
static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset) static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset)
{ {
/* OFDM registers are base-registers for the A-PHY. */ /* OFDM registers are base-registers for the A-PHY. */
@ -608,8 +623,9 @@ static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev)
const struct b43_phy_operations b43_phyops_a = { const struct b43_phy_operations b43_phyops_a = {
.allocate = b43_aphy_op_allocate, .allocate = b43_aphy_op_allocate,
.free = b43_aphy_op_free,
.prepare_structs = b43_aphy_op_prepare_structs,
.init = b43_aphy_op_init, .init = b43_aphy_op_init,
.exit = b43_aphy_op_exit,
.phy_read = b43_aphy_op_read, .phy_read = b43_aphy_op_read,
.phy_write = b43_aphy_op_write, .phy_write = b43_aphy_op_write,
.radio_read = b43_aphy_op_radio_read, .radio_read = b43_aphy_op_radio_read,

View File

@ -103,8 +103,6 @@ void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
struct b43_phy_a { struct b43_phy_a {
bool initialised;
/* Pointer to the table used to convert a /* Pointer to the table used to convert a
* TSSI value to dBm-Q5.2 */ * TSSI value to dBm-Q5.2 */
const s8 *tssi2dbm; const s8 *tssi2dbm;

View File

@ -35,7 +35,7 @@
#include "main.h" #include "main.h"
int b43_phy_operations_setup(struct b43_wldev *dev) int b43_phy_allocate(struct b43_wldev *dev)
{ {
struct b43_phy *phy = &(dev->phy); struct b43_phy *phy = &(dev->phy);
int err; int err;
@ -70,6 +70,12 @@ int b43_phy_operations_setup(struct b43_wldev *dev)
return err; return err;
} }
void b43_phy_free(struct b43_wldev *dev)
{
dev->phy.ops->free(dev);
dev->phy.ops = NULL;
}
int b43_phy_init(struct b43_wldev *dev) int b43_phy_init(struct b43_wldev *dev)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;

View File

@ -74,11 +74,21 @@ enum b43_txpwr_result {
/** /**
* struct b43_phy_operations - Function pointers for PHY ops. * struct b43_phy_operations - Function pointers for PHY ops.
* *
* @prepare: Prepare the PHY. This is called before @init. * @allocate: Allocate and initialise the PHY data structures.
* Must not be NULL.
* @free: Destroy and free the PHY data structures.
* Must not be NULL.
*
* @prepare_structs: Prepare the PHY data structures.
* The data structures allocated in @allocate are
* initialized here.
* Must not be NULL.
* @prepare_hardware: Prepare the PHY. This is called before b43_chip_init to
* do some early early PHY hardware init.
* Can be NULL, if not required. * Can be NULL, if not required.
* @init: Initialize the PHY. * @init: Initialize the PHY.
* Must not be NULL. * Must not be NULL.
* @exit: Shutdown the PHY and free all data structures. * @exit: Shutdown the PHY.
* Can be NULL, if not required. * Can be NULL, if not required.
* *
* @phy_read: Read from a PHY register. * @phy_read: Read from a PHY register.
@ -133,7 +143,9 @@ enum b43_txpwr_result {
struct b43_phy_operations { struct b43_phy_operations {
/* Initialisation */ /* Initialisation */
int (*allocate)(struct b43_wldev *dev); int (*allocate)(struct b43_wldev *dev);
int (*prepare)(struct b43_wldev *dev); void (*free)(struct b43_wldev *dev);
void (*prepare_structs)(struct b43_wldev *dev);
int (*prepare_hardware)(struct b43_wldev *dev);
int (*init)(struct b43_wldev *dev); int (*init)(struct b43_wldev *dev);
void (*exit)(struct b43_wldev *dev); void (*exit)(struct b43_wldev *dev);
@ -237,10 +249,15 @@ struct b43_phy {
/** /**
* b43_phy_operations_setup - Initialize the PHY operations datastructure * b43_phy_allocate - Allocate PHY structs
* based on the current PHY type. * Allocate the PHY data structures, based on the current dev->phy.type
*/ */
int b43_phy_operations_setup(struct b43_wldev *dev); int b43_phy_allocate(struct b43_wldev *dev);
/**
* b43_phy_free - Free PHY structs
*/
void b43_phy_free(struct b43_wldev *dev);
/** /**
* b43_phy_init - Initialise the PHY * b43_phy_init - Initialise the PHY

View File

@ -2635,7 +2635,7 @@ static int b43_gphy_op_allocate(struct b43_wldev *dev)
{ {
struct b43_phy_g *gphy; struct b43_phy_g *gphy;
struct b43_txpower_lo_control *lo; struct b43_txpower_lo_control *lo;
int err, i; int err;
gphy = kzalloc(sizeof(*gphy), GFP_KERNEL); gphy = kzalloc(sizeof(*gphy), GFP_KERNEL);
if (!gphy) { if (!gphy) {
@ -2644,6 +2644,51 @@ static int b43_gphy_op_allocate(struct b43_wldev *dev)
} }
dev->phy.g = gphy; dev->phy.g = gphy;
lo = kzalloc(sizeof(*lo), GFP_KERNEL);
if (!lo) {
err = -ENOMEM;
goto err_free_gphy;
}
gphy->lo_control = lo;
err = b43_gphy_init_tssi2dbm_table(dev);
if (err)
goto err_free_lo;
return 0;
err_free_lo:
kfree(lo);
err_free_gphy:
kfree(gphy);
error:
return err;
}
static void b43_gphy_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
const void *tssi2dbm;
int tgt_idle_tssi;
struct b43_txpower_lo_control *lo;
unsigned int i;
/* tssi2dbm table is constant, so it is initialized at alloc time.
* Save a copy of the pointer. */
tssi2dbm = gphy->tssi2dbm;
tgt_idle_tssi = gphy->tgt_idle_tssi;
/* Save the LO pointer. */
lo = gphy->lo_control;
/* Zero out the whole PHY structure. */
memset(gphy, 0, sizeof(*gphy));
/* Restore pointers. */
gphy->tssi2dbm = tssi2dbm;
gphy->tgt_idle_tssi = tgt_idle_tssi;
gphy->lo_control = lo;
memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig)); memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig));
/* NRSSI */ /* NRSSI */
@ -2662,31 +2707,28 @@ static int b43_gphy_op_allocate(struct b43_wldev *dev)
gphy->average_tssi = 0xFF; gphy->average_tssi = 0xFF;
lo = kzalloc(sizeof(*lo), GFP_KERNEL); /* Local Osciallator structure */
if (!lo) {
err = -ENOMEM;
goto err_free_gphy;
}
gphy->lo_control = lo;
lo->tx_bias = 0xFF; lo->tx_bias = 0xFF;
INIT_LIST_HEAD(&lo->calib_list); INIT_LIST_HEAD(&lo->calib_list);
err = b43_gphy_init_tssi2dbm_table(dev);
if (err)
goto err_free_lo;
return 0;
err_free_lo:
kfree(lo);
err_free_gphy:
kfree(gphy);
error:
return err;
} }
static int b43_gphy_op_prepare(struct b43_wldev *dev) static void b43_gphy_op_free(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
kfree(gphy->lo_control);
if (gphy->dyn_tssi_tbl)
kfree(gphy->tssi2dbm);
gphy->dyn_tssi_tbl = 0;
gphy->tssi2dbm = NULL;
kfree(gphy);
dev->phy.g = NULL;
}
static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g; struct b43_phy_g *gphy = phy->g;
@ -2718,28 +2760,14 @@ static int b43_gphy_op_prepare(struct b43_wldev *dev)
static int b43_gphy_op_init(struct b43_wldev *dev) static int b43_gphy_op_init(struct b43_wldev *dev)
{ {
struct b43_phy_g *gphy = dev->phy.g;
b43_phy_initg(dev); b43_phy_initg(dev);
gphy->initialised = 1;
return 0; return 0;
} }
static void b43_gphy_op_exit(struct b43_wldev *dev) static void b43_gphy_op_exit(struct b43_wldev *dev)
{ {
struct b43_phy_g *gphy = dev->phy.g;
if (gphy->initialised) {
//TODO
gphy->initialised = 0;
}
b43_lo_g_cleanup(dev); b43_lo_g_cleanup(dev);
kfree(gphy->lo_control);
if (gphy->dyn_tssi_tbl)
kfree(gphy->tssi2dbm);
kfree(gphy);
dev->phy.g = NULL;
} }
static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg) static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg)
@ -3232,7 +3260,9 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
const struct b43_phy_operations b43_phyops_g = { const struct b43_phy_operations b43_phyops_g = {
.allocate = b43_gphy_op_allocate, .allocate = b43_gphy_op_allocate,
.prepare = b43_gphy_op_prepare, .free = b43_gphy_op_free,
.prepare_structs = b43_gphy_op_prepare_structs,
.prepare_hardware = b43_gphy_op_prepare_hardware,
.init = b43_gphy_op_init, .init = b43_gphy_op_init,
.exit = b43_gphy_op_exit, .exit = b43_gphy_op_exit,
.phy_read = b43_gphy_op_read, .phy_read = b43_gphy_op_read,

View File

@ -114,8 +114,6 @@ static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
struct b43_txpower_lo_control; struct b43_txpower_lo_control;
struct b43_phy_g { struct b43_phy_g {
bool initialised;
/* ACI (adjacent channel interference) flags. */ /* ACI (adjacent channel interference) flags. */
bool aci_enable; bool aci_enable;
bool aci_wlan_automatic; bool aci_wlan_automatic;

View File

@ -36,34 +36,34 @@ static int b43_lpphy_op_allocate(struct b43_wldev *dev)
return -ENOMEM; return -ENOMEM;
dev->phy.lp = lpphy; dev->phy.lp = lpphy;
//TODO
return 0; return 0;
} }
static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_lp *lpphy = phy->lp;
memset(lpphy, 0, sizeof(*lpphy));
//TODO
}
static void b43_lpphy_op_free(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
kfree(lpphy);
dev->phy.lp = NULL;
}
static int b43_lpphy_op_init(struct b43_wldev *dev) static int b43_lpphy_op_init(struct b43_wldev *dev)
{ {
struct b43_phy_lp *lpphy = dev->phy.lp;
//TODO //TODO
lpphy->initialised = 1;
return 0; return 0;
} }
static void b43_lpphy_op_exit(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
if (lpphy->initialised) {
//TODO
lpphy->initialised = 0;
}
kfree(lpphy);
dev->phy.lp = NULL;
}
static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg) static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
{ {
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
@ -138,8 +138,9 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
const struct b43_phy_operations b43_phyops_lp = { const struct b43_phy_operations b43_phyops_lp = {
.allocate = b43_lpphy_op_allocate, .allocate = b43_lpphy_op_allocate,
.free = b43_lpphy_op_free,
.prepare_structs = b43_lpphy_op_prepare_structs,
.init = b43_lpphy_op_init, .init = b43_lpphy_op_init,
.exit = b43_lpphy_op_exit,
.phy_read = b43_lpphy_op_read, .phy_read = b43_lpphy_op_read,
.phy_write = b43_lpphy_op_write, .phy_write = b43_lpphy_op_write,
.radio_read = b43_lpphy_op_radio_read, .radio_read = b43_lpphy_op_radio_read,

View File

@ -530,7 +530,7 @@
struct b43_phy_lp { struct b43_phy_lp {
bool initialised; //TODO
}; };

View File

@ -499,35 +499,31 @@ static int b43_nphy_op_allocate(struct b43_wldev *dev)
return -ENOMEM; return -ENOMEM;
dev->phy.n = nphy; dev->phy.n = nphy;
//TODO init struct b43_phy_n
return 0; return 0;
} }
static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
memset(nphy, 0, sizeof(*nphy));
//TODO init struct b43_phy_n
}
static void b43_nphy_op_free(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
kfree(nphy);
phy->n = NULL;
}
static int b43_nphy_op_init(struct b43_wldev *dev) static int b43_nphy_op_init(struct b43_wldev *dev)
{ {
struct b43_phy_n *nphy = dev->phy.n; return b43_phy_initn(dev);
int err;
err = b43_phy_initn(dev);
if (err)
return err;
nphy->initialised = 1;
return 0;
}
static void b43_nphy_op_exit(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
if (nphy->initialised) {
//TODO
nphy->initialised = 0;
}
//TODO
kfree(nphy);
dev->phy.n = NULL;
} }
static inline void check_phyreg(struct b43_wldev *dev, u16 offset) static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
@ -610,8 +606,9 @@ static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
const struct b43_phy_operations b43_phyops_n = { const struct b43_phy_operations b43_phyops_n = {
.allocate = b43_nphy_op_allocate, .allocate = b43_nphy_op_allocate,
.free = b43_nphy_op_free,
.prepare_structs = b43_nphy_op_prepare_structs,
.init = b43_nphy_op_init, .init = b43_nphy_op_init,
.exit = b43_nphy_op_exit,
.phy_read = b43_nphy_op_read, .phy_read = b43_nphy_op_read,
.phy_write = b43_nphy_op_write, .phy_write = b43_nphy_op_write,
.radio_read = b43_nphy_op_radio_read, .radio_read = b43_nphy_op_radio_read,

View File

@ -920,8 +920,6 @@
struct b43_wldev; struct b43_wldev;
struct b43_phy_n { struct b43_phy_n {
bool initialised;
//TODO lots of missing stuff //TODO lots of missing stuff
}; };