diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c index 2c0d5c8d80..aa767d17a3 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c @@ -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); diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h index 1361912e1a..692614e239 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h @@ -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 */ diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c index 07e14bce34..825502514e 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c @@ -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 */ diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c index c5e0f0419a..a964ad6102 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c @@ -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) */ diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h index 1eb3db80e8..bcbe427e24 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h @@ -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