Commit fb11137a authored by Michael Buesch's avatar Michael Buesch Committed by John W. Linville

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: default avatarMichael Buesch <mb@bu3sch.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 7cb77072
......@@ -1091,8 +1091,12 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
msleep(1);
/* Turn Analog ON */
b43_switch_analog(dev, 1);
/* Turn Analog ON, but only if we already know the PHY-type.
* 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_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() */
static void b43_chip_exit(struct b43_wldev *dev)
{
b43_phy_exit(dev);
b43_gpio_cleanup(dev);
/* 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->wl->current_beacon = NULL;
}
b43_phy_exit(dev);
ssb_device_disable(dev->dev, 0);
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);
}
/* Reset all data structures. */
setup_struct_wldev_for_init(dev);
err = b43_phy_operations_setup(dev);
if (err)
goto err_busdown;
phy->ops->prepare_structs(dev);
/* Enable IRQ routing to this device. */
ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
b43_imcfglo_timeouts_workaround(dev);
b43_bluetooth_coext_disable(dev);
if (phy->ops->prepare) {
err = phy->ops->prepare(dev);
if (phy->ops->prepare_hardware) {
err = phy->ops->prepare_hardware(dev);
if (err)
goto err_phy_exit;
goto err_busdown;
}
err = b43_chip_init(dev);
if (err)
goto err_phy_exit;
goto err_busdown;
b43_shm_write16(dev, B43_SHM_SHARED,
B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
hf = b43_hf_read(dev);
......@@ -4064,8 +4067,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
err_chip_exit:
b43_chip_exit(dev);
err_phy_exit:
b43_phy_exit(dev);
err_busdown:
ssb_bus_may_powerdown(bus);
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
* is all the time when we reinit the core. */
b43_release_firmware(dev);
b43_phy_free(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;
tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
b43_wireless_core_reset(dev, tmp);
err = b43_validate_chipaccess(dev);
if (err)
goto err_powerdown;
goto err_phy_free;
err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
if (err)
goto err_powerdown;
goto err_phy_free;
/* Now set some default "current_dev" */
if (!wl->current_dev)
......@@ -4438,6 +4444,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
out:
return err;
err_phy_free:
b43_phy_free(dev);
err_powerdown:
ssb_bus_may_powerdown(bus);
return err;
......
......@@ -391,8 +391,6 @@ static int b43_aphy_op_allocate(struct b43_wldev *dev)
return -ENOMEM;
dev->phy.a = aphy;
//TODO init struct b43_phy_a
err = b43_aphy_init_tssi2dbm_table(dev);
if (err)
goto err_free_aphy;
......@@ -406,30 +404,47 @@ static int b43_aphy_op_allocate(struct b43_wldev *dev)
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);
aphy->initialised = 1;
/* tssi2dbm table is constant, so it is initialized at alloc time.
* 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);
aphy->tssi2dbm = NULL;
kfree(aphy);
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)
{
/* 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 = {
.allocate = b43_aphy_op_allocate,
.free = b43_aphy_op_free,
.prepare_structs = b43_aphy_op_prepare_structs,
.init = b43_aphy_op_init,
.exit = b43_aphy_op_exit,
.phy_read = b43_aphy_op_read,
.phy_write = b43_aphy_op_write,
.radio_read = b43_aphy_op_radio_read,
......
......@@ -103,8 +103,6 @@ void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
struct b43_phy_a {
bool initialised;
/* Pointer to the table used to convert a
* TSSI value to dBm-Q5.2 */
const s8 *tssi2dbm;
......
......@@ -35,7 +35,7 @@
#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);
int err;
......@@ -70,6 +70,12 @@ int b43_phy_operations_setup(struct b43_wldev *dev)
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)
{
struct b43_phy *phy = &dev->phy;
......
......@@ -74,11 +74,21 @@ enum b43_txpwr_result {
/**
* 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.
* @init: Initialize the PHY.
* Must not be NULL.
* @exit: Shutdown the PHY and free all data structures.
* @exit: Shutdown the PHY.
* Can be NULL, if not required.
*
* @phy_read: Read from a PHY register.
......@@ -133,7 +143,9 @@ enum b43_txpwr_result {
struct b43_phy_operations {
/* Initialisation */
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);
void (*exit)(struct b43_wldev *dev);
......@@ -237,10 +249,15 @@ struct b43_phy {
/**
* b43_phy_operations_setup - Initialize the PHY operations datastructure
* based on the current PHY type.
* b43_phy_allocate - Allocate PHY structs
* Allocate the PHY data structures, based on the current dev->phy.type
*/
int b43_phy_allocate(struct b43_wldev *dev);
/**
* b43_phy_free - Free PHY structs
*/
int b43_phy_operations_setup(struct b43_wldev *dev);
void b43_phy_free(struct b43_wldev *dev);
/**
* b43_phy_init - Initialise the PHY
......
......@@ -2635,7 +2635,7 @@ static int b43_gphy_op_allocate(struct b43_wldev *dev)
{
struct b43_phy_g *gphy;
struct b43_txpower_lo_control *lo;
int err, i;
int err;
gphy = kzalloc(sizeof(*gphy), GFP_KERNEL);
if (!gphy) {
......@@ -2644,6 +2644,51 @@ static int b43_gphy_op_allocate(struct b43_wldev *dev)
}
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));
/* NRSSI */
......@@ -2662,31 +2707,28 @@ static int b43_gphy_op_allocate(struct b43_wldev *dev)
gphy->average_tssi = 0xFF;
lo = kzalloc(sizeof(*lo), GFP_KERNEL);
if (!lo) {
err = -ENOMEM;
goto err_free_gphy;
}
gphy->lo_control = lo;
/* Local Osciallator structure */
lo->tx_bias = 0xFF;
INIT_LIST_HEAD(&lo->calib_list);
}
err = b43_gphy_init_tssi2dbm_table(dev);
if (err)
goto err_free_lo;
static void b43_gphy_op_free(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
return 0;
kfree(gphy->lo_control);
if (gphy->dyn_tssi_tbl)
kfree(gphy->tssi2dbm);
gphy->dyn_tssi_tbl = 0;
gphy->tssi2dbm = NULL;
err_free_lo:
kfree(lo);
err_free_gphy:
kfree(gphy);
error:
return err;
dev->phy.g = NULL;
}
static int b43_gphy_op_prepare(struct b43_wldev *dev)
static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
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)
{
struct b43_phy_g *gphy = dev->phy.g;
b43_phy_initg(dev);
gphy->initialised = 1;
return 0;
}
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);
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)
......@@ -3232,7 +3260,9 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
const struct b43_phy_operations b43_phyops_g = {
.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,
.exit = b43_gphy_op_exit,
.phy_read = b43_gphy_op_read,
......
......@@ -114,8 +114,6 @@ static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
struct b43_txpower_lo_control;
struct b43_phy_g {
bool initialised;
/* ACI (adjacent channel interference) flags. */
bool aci_enable;
bool aci_wlan_automatic;
......
......@@ -36,34 +36,34 @@ static int b43_lpphy_op_allocate(struct b43_wldev *dev)
return -ENOMEM;
dev->phy.lp = lpphy;
//TODO
return 0;
}
static int b43_lpphy_op_init(struct b43_wldev *dev)
static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
struct b43_phy *phy = &dev->phy;
struct b43_phy_lp *lpphy = phy->lp;
//TODO
lpphy->initialised = 1;
memset(lpphy, 0, sizeof(*lpphy));
return 0;
//TODO
}
static void b43_lpphy_op_exit(struct b43_wldev *dev)
static void b43_lpphy_op_free(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 int b43_lpphy_op_init(struct b43_wldev *dev)
{
//TODO
return 0;
}
static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 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 = {
.allocate = b43_lpphy_op_allocate,
.free = b43_lpphy_op_free,
.prepare_structs = b43_lpphy_op_prepare_structs,
.init = b43_lpphy_op_init,
.exit = b43_lpphy_op_exit,
.phy_read = b43_lpphy_op_read,
.phy_write = b43_lpphy_op_write,
.radio_read = b43_lpphy_op_radio_read,
......
......@@ -530,7 +530,7 @@
struct b43_phy_lp {
bool initialised;
//TODO
};
......
......@@ -499,35 +499,31 @@ static int b43_nphy_op_allocate(struct b43_wldev *dev)
return -ENOMEM;
dev->phy.n = nphy;
//TODO init struct b43_phy_n
return 0;
}
static int b43_nphy_op_init(struct b43_wldev *dev)
static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
int err;
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
err = b43_phy_initn(dev);
if (err)
return err;
nphy->initialised = 1;
memset(nphy, 0, sizeof(*nphy));
return 0;
//TODO init struct b43_phy_n
}
static void b43_nphy_op_exit(struct b43_wldev *dev)
static void b43_nphy_op_free(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
if (nphy->initialised) {
//TODO
nphy->initialised = 0;
}
//TODO
kfree(nphy);
dev->phy.n = NULL;
phy->n = NULL;
}
static int b43_nphy_op_init(struct b43_wldev *dev)
{
return b43_phy_initn(dev);
}
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 = {
.allocate = b43_nphy_op_allocate,
.free = b43_nphy_op_free,
.prepare_structs = b43_nphy_op_prepare_structs,
.init = b43_nphy_op_init,
.exit = b43_nphy_op_exit,
.phy_read = b43_nphy_op_read,
.phy_write = b43_nphy_op_write,
.radio_read = b43_nphy_op_radio_read,
......
......@@ -920,8 +920,6 @@
struct b43_wldev;
struct b43_phy_n {
bool initialised;
//TODO lots of missing stuff
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment