wireless/bcm43xxx: enable power saving on netdev up/down
Move sdio/firmware de/initialize to ifup/down Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
parent
2827b2beb3
commit
fa6ea23101
5 changed files with 193 additions and 131 deletions
|
|
@ -433,13 +433,19 @@ int bcmf_driver_download_clm(FAR struct bcmf_dev_s *priv)
|
|||
#endif
|
||||
#endif /* CONFIG_IEEE80211_BROADCOM_HAVE_CLM */
|
||||
|
||||
int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
||||
int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active)
|
||||
{
|
||||
int ret;
|
||||
int interface = CHIP_STA_INTERFACE;
|
||||
uint8_t tmp_buf[64];
|
||||
uint32_t out_len;
|
||||
uint32_t value;
|
||||
uint8_t tmp_buf[64];
|
||||
int interface = CHIP_STA_INTERFACE;
|
||||
int ret;
|
||||
|
||||
ret = bcmf_bus_sdio_active(priv, active);
|
||||
if (ret != OK || !active)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211_BROADCOM_HAVE_CLM
|
||||
/* Download CLM blob if needed */
|
||||
|
|
@ -447,7 +453,7 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
ret = bcmf_driver_download_clm(priv);
|
||||
if (ret != OK)
|
||||
{
|
||||
return -EIO;
|
||||
goto errout_in_sdio_active;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -460,7 +466,7 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
&out_len);
|
||||
if (ret != OK)
|
||||
{
|
||||
return -EIO;
|
||||
goto errout_in_sdio_active;
|
||||
}
|
||||
|
||||
/* FIXME disable power save mode */
|
||||
|
|
@ -471,7 +477,7 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
(uint8_t *)&value, &out_len);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
goto errout_in_sdio_active;
|
||||
}
|
||||
|
||||
/* Set the GMode to auto */
|
||||
|
|
@ -482,7 +488,7 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
(uint8_t *)&value, &out_len);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
goto errout_in_sdio_active;
|
||||
}
|
||||
|
||||
/* TODO configure roaming if needed. Disable for now */
|
||||
|
|
@ -493,6 +499,10 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
IOVAR_STR_ROAM_OFF,
|
||||
(FAR uint8_t *)&value,
|
||||
&out_len);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_in_sdio_active;
|
||||
}
|
||||
|
||||
/* TODO configure EAPOL version to default */
|
||||
|
||||
|
|
@ -500,11 +510,12 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
((FAR uint32_t *)tmp_buf)[0] = interface;
|
||||
((FAR uint32_t *)tmp_buf)[1] = (uint32_t)-1;
|
||||
|
||||
if (bcmf_cdc_iovar_request(priv, interface, true,
|
||||
"bsscfg:"IOVAR_STR_SUP_WPA2_EAPVER, tmp_buf,
|
||||
&out_len))
|
||||
ret = bcmf_cdc_iovar_request(priv, interface, true,
|
||||
"bsscfg:"IOVAR_STR_SUP_WPA2_EAPVER,
|
||||
tmp_buf, &out_len);
|
||||
if (ret != OK)
|
||||
{
|
||||
return -EIO;
|
||||
goto errout_in_sdio_active;
|
||||
}
|
||||
|
||||
/* Query firmware version string */
|
||||
|
|
@ -515,7 +526,7 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
&out_len);
|
||||
if (ret != OK)
|
||||
{
|
||||
return -EIO;
|
||||
goto errout_in_sdio_active;
|
||||
}
|
||||
|
||||
tmp_buf[sizeof(tmp_buf)-1] = 0;
|
||||
|
|
@ -530,11 +541,26 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
|
||||
wlinfo("fw version <%s>\n", tmp_buf);
|
||||
|
||||
ret = bcmf_event_push_config(priv);
|
||||
|
||||
errout_in_sdio_active:
|
||||
if (ret != OK)
|
||||
{
|
||||
bcmf_bus_sdio_active(priv, false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* FIXME Configure event mask to enable all asynchronous events */
|
||||
|
||||
for (ret = 0; ret < BCMF_EVENT_COUNT; ret++)
|
||||
for (i = 0; i < BCMF_EVENT_COUNT; i++)
|
||||
{
|
||||
bcmf_event_register(priv, bcmf_wl_default_event_handler, ret);
|
||||
bcmf_event_register(priv, bcmf_wl_default_event_handler, i);
|
||||
}
|
||||
|
||||
/* Register radio event */
|
||||
|
|
@ -568,11 +594,6 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
|
|||
bcmf_event_register(priv, bcmf_wl_auth_event_handler,
|
||||
WLC_E_DISASSOC_IND);
|
||||
|
||||
if (bcmf_event_push_config(priv))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Register network driver */
|
||||
|
||||
return bcmf_netdev_register(priv);
|
||||
|
|
|
|||
|
|
@ -169,4 +169,6 @@ int bcmf_wl_get_rssi(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
|
|||
|
||||
int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
|
||||
|
||||
int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active);
|
||||
|
||||
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_DRIVER_H */
|
||||
|
|
|
|||
|
|
@ -637,20 +637,55 @@ void bcmf_netdev_notify_rx(FAR struct bcmf_dev_s *priv)
|
|||
static int bcmf_ifup(FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct bcmf_dev_s *priv = (FAR struct bcmf_dev_s *)dev->d_private;
|
||||
irqstate_t flags;
|
||||
uint32_t out_len;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
ninfo("Bringing up: %d.%d.%d.%d\n",
|
||||
(int)(dev->d_ipaddr & 0xff),
|
||||
(int)((dev->d_ipaddr >> 8) & 0xff),
|
||||
(int)((dev->d_ipaddr >> 16) & 0xff),
|
||||
(int)(dev->d_ipaddr >> 24));
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2],
|
||||
dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5],
|
||||
dev->d_ipv6addr[6], dev->d_ipv6addr[7]);
|
||||
#endif
|
||||
/* Disable the hardware interrupt */
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (priv->bc_bifup)
|
||||
{
|
||||
goto errout_in_critical_section;
|
||||
}
|
||||
|
||||
ret = bcmf_wl_active(priv, true);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_in_critical_section;
|
||||
}
|
||||
|
||||
/* Enable chip */
|
||||
|
||||
ret = bcmf_wl_enable(priv, true);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_in_wl_active;
|
||||
}
|
||||
|
||||
/* Set customized MAC address */
|
||||
|
||||
if (bcmf_board_etheraddr(&priv->bc_dev.d_mac.ether))
|
||||
{
|
||||
out_len = ETHER_ADDR_LEN;
|
||||
bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, true,
|
||||
IOVAR_STR_CUR_ETHERADDR,
|
||||
priv->bc_dev.d_mac.ether.ether_addr_octet,
|
||||
&out_len);
|
||||
}
|
||||
|
||||
/* Query MAC address */
|
||||
|
||||
out_len = ETHER_ADDR_LEN;
|
||||
ret = bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, false,
|
||||
IOVAR_STR_CUR_ETHERADDR,
|
||||
priv->bc_dev.d_mac.ether.ether_addr_octet,
|
||||
&out_len);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_in_wl_active;
|
||||
}
|
||||
|
||||
/* Instantiate MAC address from priv->bc_dev.d_mac.ether.ether_addr_octet */
|
||||
|
||||
|
|
@ -663,6 +698,16 @@ static int bcmf_ifup(FAR struct net_driver_s *dev)
|
|||
/* Enable the hardware interrupt */
|
||||
|
||||
priv->bc_bifup = true;
|
||||
|
||||
goto errout_in_critical_section;
|
||||
|
||||
errout_in_wl_active:
|
||||
bcmf_wl_active(priv, false);
|
||||
|
||||
errout_in_critical_section:
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
@ -690,17 +735,19 @@ static int bcmf_ifdown(FAR struct net_driver_s *dev)
|
|||
/* Disable the hardware interrupt */
|
||||
|
||||
flags = enter_critical_section();
|
||||
#warning Missing logic
|
||||
|
||||
/* Put the EMAC in its reset, non-operational state. This should be
|
||||
* a known configuration that will guarantee the bcmf_ifup() always
|
||||
* successfully brings the interface back up.
|
||||
*/
|
||||
if (priv->bc_bifup)
|
||||
{
|
||||
bcmf_wl_enable(priv, false);
|
||||
bcmf_wl_active(priv, false);
|
||||
|
||||
/* Mark the device "down" */
|
||||
/* Mark the device "down" */
|
||||
|
||||
priv->bc_bifup = false;
|
||||
}
|
||||
|
||||
priv->bc_bifup = false;
|
||||
leave_critical_section(flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
@ -883,8 +930,15 @@ static void bcmf_ipv6multicast(FAR struct bcmf_dev_s *priv)
|
|||
static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
FAR struct bcmf_dev_s *priv = (FAR struct bcmf_dev_s *)dev->d_private;
|
||||
int ret;
|
||||
|
||||
if (!priv->bc_bifup)
|
||||
{
|
||||
wlerr("ERROR: invaild state "
|
||||
"(IFF_DOWN, unable to execute command: %x)\n", cmd);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* Decode and dispatch the driver-specific IOCTL command */
|
||||
|
||||
|
|
@ -970,7 +1024,7 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
|
|||
break;
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized IOCTL command: %d\n", cmd);
|
||||
nerr("ERROR: Unrecognized IOCTL command: %x\n", cmd);
|
||||
ret = -ENOTTY; /* Special return value for this case */
|
||||
break;
|
||||
}
|
||||
|
|
@ -1001,8 +1055,6 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
|
|||
|
||||
int bcmf_netdev_register(FAR struct bcmf_dev_s *priv)
|
||||
{
|
||||
uint32_t out_len;
|
||||
|
||||
/* Initialize network driver structure */
|
||||
|
||||
memset(&priv->bc_dev, 0, sizeof(priv->bc_dev));
|
||||
|
|
@ -1023,38 +1075,9 @@ int bcmf_netdev_register(FAR struct bcmf_dev_s *priv)
|
|||
priv->cur_tx_frame = NULL;
|
||||
priv->bc_dev.d_buf = NULL;
|
||||
|
||||
/* Put the interface in the down state. This usually amounts to resetting
|
||||
* the device and/or calling bcmf_ifdown().
|
||||
*/
|
||||
/* Initialize MAC address */
|
||||
|
||||
/* Enable chip */
|
||||
|
||||
if (bcmf_wl_enable(priv, true) != OK)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set customized MAC address */
|
||||
|
||||
if (bcmf_board_etheraddr(&priv->bc_dev.d_mac.ether))
|
||||
{
|
||||
out_len = ETHER_ADDR_LEN;
|
||||
bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, true,
|
||||
IOVAR_STR_CUR_ETHERADDR,
|
||||
priv->bc_dev.d_mac.ether.ether_addr_octet,
|
||||
&out_len);
|
||||
}
|
||||
|
||||
/* Query MAC address */
|
||||
|
||||
out_len = ETHER_ADDR_LEN;
|
||||
if (bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, false,
|
||||
IOVAR_STR_CUR_ETHERADDR,
|
||||
priv->bc_dev.d_mac.ether.ether_addr_octet,
|
||||
&out_len) != OK)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
bcmf_board_etheraddr(&priv->bc_dev.d_mac.ether);
|
||||
|
||||
/* Register the device with the OS so that socket IOCTLs can be performed */
|
||||
|
||||
|
|
|
|||
|
|
@ -456,6 +456,10 @@ int bcmf_bus_setup_interrupts(FAR struct bcmf_sdio_dev_s *sbus)
|
|||
|
||||
int bcmf_hwinitialize(FAR struct bcmf_sdio_dev_s *sbus)
|
||||
{
|
||||
/* Power device */
|
||||
|
||||
bcmf_board_power(sbus->minor, true);
|
||||
|
||||
/* Attach and prepare SDIO interrupts */
|
||||
|
||||
SDIO_ATTACH(sbus->sdio_dev);
|
||||
|
|
@ -464,14 +468,9 @@ int bcmf_hwinitialize(FAR struct bcmf_sdio_dev_s *sbus)
|
|||
|
||||
SDIO_CLOCK(sbus->sdio_dev, CLOCK_IDMODE);
|
||||
|
||||
/* Configure hardware */
|
||||
|
||||
bcmf_board_initialize(sbus->minor);
|
||||
|
||||
/* Reset and power device */
|
||||
/* Reset device */
|
||||
|
||||
bcmf_board_reset(sbus->minor, true);
|
||||
bcmf_board_power(sbus->minor, true);
|
||||
nxsig_usleep(BCMF_DEVICE_RESET_DELAY_MS * 1000);
|
||||
bcmf_board_reset(sbus->minor, false);
|
||||
|
||||
|
|
@ -650,6 +649,67 @@ int bcmf_write_reg(FAR struct bcmf_sdio_dev_s *sbus, uint8_t function,
|
|||
return bcmf_transfer_bytes(sbus, true, function, address, ®, 1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bcmf_bus_sdio_active
|
||||
****************************************************************************/
|
||||
|
||||
int bcmf_bus_sdio_active(FAR struct bcmf_dev_s *priv, bool active)
|
||||
{
|
||||
FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
|
||||
int ret = OK;
|
||||
|
||||
if (!active)
|
||||
{
|
||||
goto exit_uninit_hw;
|
||||
}
|
||||
|
||||
/* Initialize device hardware */
|
||||
|
||||
ret = bcmf_hwinitialize(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Probe device */
|
||||
|
||||
ret = bcmf_probe(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto exit_uninit_hw;
|
||||
}
|
||||
|
||||
/* Initialize device bus */
|
||||
|
||||
ret = bcmf_businitialize(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto exit_uninit_hw;
|
||||
}
|
||||
|
||||
nxsig_usleep(100 * 1000);
|
||||
|
||||
sbus->ready = active;
|
||||
|
||||
ret = bcmf_bus_setup_interrupts(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto exit_uninit_hw;
|
||||
}
|
||||
|
||||
ret = bcmf_sdio_sr_init(sbus);
|
||||
if (ret == OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
exit_uninit_hw:
|
||||
sbus->ready = false;
|
||||
bcmf_hwuninitialize(sbus);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bcmf_bus_sdio_initialize
|
||||
****************************************************************************/
|
||||
|
|
@ -718,55 +778,14 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
|
|||
goto exit_free_bus;
|
||||
}
|
||||
|
||||
/* Initialize device hardware */
|
||||
/* Configure hardware */
|
||||
|
||||
ret = bcmf_hwinitialize(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto exit_free_bus;
|
||||
}
|
||||
|
||||
/* Probe device */
|
||||
|
||||
ret = bcmf_probe(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto exit_uninit_hw;
|
||||
}
|
||||
|
||||
/* Initialize device bus */
|
||||
|
||||
ret = bcmf_businitialize(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto exit_uninit_hw;
|
||||
}
|
||||
|
||||
nxsig_usleep(100 * 1000);
|
||||
|
||||
sbus->ready = true;
|
||||
|
||||
ret = bcmf_bus_setup_interrupts(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto exit_uninit_hw;
|
||||
}
|
||||
|
||||
ret = bcmf_sdio_sr_init(sbus);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto exit_uninit_hw;
|
||||
}
|
||||
bcmf_board_initialize(sbus->minor);
|
||||
|
||||
/* Register sdio bus */
|
||||
|
||||
priv->bus = &sbus->bus;
|
||||
|
||||
/* Start the waitdog timer */
|
||||
|
||||
wd_start(&sbus->waitdog, BCMF_WAITDOG_TIMEOUT_TICK,
|
||||
bcmf_sdio_waitdog_timeout, (wdparm_t)priv);
|
||||
|
||||
/* Spawn bcmf daemon thread */
|
||||
|
||||
snprintf(arg1, sizeof(arg1), "%p", priv);
|
||||
|
|
@ -780,18 +799,13 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
|
|||
{
|
||||
wlerr("Cannot spawn bcmf thread\n");
|
||||
ret = -EBADE;
|
||||
goto exit_uninit_hw;
|
||||
goto exit_free_bus;
|
||||
}
|
||||
|
||||
sbus->thread_id = (pid_t)ret;
|
||||
|
||||
/* SDIO bus is up and running */
|
||||
|
||||
return OK;
|
||||
|
||||
exit_uninit_hw:
|
||||
bcmf_hwuninitialize(sbus);
|
||||
|
||||
exit_free_bus:
|
||||
kmm_free(sbus);
|
||||
priv->bus = NULL;
|
||||
|
|
@ -876,7 +890,7 @@ int bcmf_sdio_thread(int argc, char **argv)
|
|||
|
||||
nxsig_usleep(50 * 1000);
|
||||
|
||||
while (sbus->ready)
|
||||
while (true)
|
||||
{
|
||||
/* Wait for event (device interrupt, user request or waitdog timer) */
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,8 @@ struct bcmf_sdio_frame
|
|||
int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
|
||||
int minor, FAR struct sdio_dev_s *dev);
|
||||
|
||||
int bcmf_bus_sdio_active(FAR struct bcmf_dev_s *priv, bool active);
|
||||
|
||||
/* FIXME: Low level bus data transfer function
|
||||
* To avoid bus error, len will be aligned to:
|
||||
* - upper power of 2 iflen is lesser than 64
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue