struct tasklet_struct tasklet;
spinlock_t sdlock;
spinlock_t txqlock;
+ spinlock_t dhd_lock;
+
/* Thread based operation */
bool threads_only;
struct semaphore sdsem;
#ifdef SOFTAP
extern struct net_device *ap_net_dev;
+/* semaphore that the soft AP CODE waits on */
+extern struct semaphore ap_eth_sema;
#endif
static void
dhd_op_if(dhd_if_t *ifp)
{
- dhd_info_t *dhd;
- int ret = 0, err = 0;
+ dhd_info_t *dhd;
+ int ret = 0, err = 0;
+#ifdef SOFTAP
+ unsigned long flags;
+#endif
ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */
ret = -EOPNOTSUPP;
} else {
#ifdef SOFTAP
- /* semaphore that the soft AP CODE waits on */
- extern struct semaphore ap_eth_sema;
-
+ flags = dhd_os_spin_lock(&dhd->pub);
/* save ptr to wl0.1 netdev for use in wl_iw.c */
ap_net_dev = ifp->net;
/* signal to the SOFTAP 'sleeper' thread, wl0.1 is ready */
up(&ap_eth_sema);
+ dhd_os_spin_unlock(&dhd->pub, flags);
#endif
DHD_TRACE(("\n ==== pid:%x, net_device for if:%s created ===\n\n",
current->pid, ifp->net->name));
dhd->iflist[ifp->idx] = NULL;
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
#ifdef SOFTAP
+ flags = dhd_os_spin_lock(&dhd->pub);
if (ifp->net == ap_net_dev)
ap_net_dev = NULL; /* NULL SOFTAP global as well */
+ dhd_os_spin_unlock(&dhd->pub, flags);
#endif /* SOFTAP */
}
}
int i;
#ifdef SOFTAP
bool in_ap = FALSE;
+ unsigned long flags;
#endif
DAEMONIZE("dhd_sysioc");
if (dhd->iflist[i]) {
DHD_TRACE(("%s: interface %d\n",__FUNCTION__, i));
#ifdef SOFTAP
+ flags = dhd_os_spin_lock(&dhd->pub);
in_ap = (ap_net_dev != NULL);
+ dhd_os_spin_unlock(&dhd->pub, flags);
#endif /* SOFTAP */
if (dhd->iflist[i]->state)
dhd_op_if(dhd->iflist[i]);
dhd_os_wake_unlock(&dhd->pub);
dhd_os_start_unlock(&dhd->pub);
}
+ DHD_TRACE(("%s: stopped\n",__FUNCTION__));
complete_and_exit(&dhd->sysioc_exited, 0);
}
/* Initialize the spinlocks */
spin_lock_init(&dhd->sdlock);
spin_lock_init(&dhd->txqlock);
+ spin_lock_init(&dhd->dhd_lock);
/* Initialize Wakelock stuff */
spin_lock_init(&dhd->wl_lock);
/* Attach and link in the iw */
wl_iw_detach();
#endif
-
- for (i = 1; i < DHD_MAX_IFS; i++)
- if (dhd->iflist[i])
- dhd_del_if(dhd, i);
-
if (dhd->sysioc_pid >= 0) {
KILL_PROC(dhd->sysioc_pid, SIGTERM);
wait_for_completion(&dhd->sysioc_exited);
}
+ for (i = 1; i < DHD_MAX_IFS; i++)
+ if (dhd->iflist[i]) {
+ dhd->iflist[i]->state = WLC_E_IF_DEL;
+ dhd->iflist[i]->idx = i;
+ dhd_op_if(dhd->iflist[i]);
+ }
+
ifp = dhd->iflist[0];
ASSERT(ifp);
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
ret = dhd_os_wake_unlock(&dhd->pub);
return ret;
}
+
+unsigned long dhd_os_spin_lock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags = 0;
+
+ if (dhd)
+ spin_lock_irqsave(&dhd->dhd_lock, flags);
+
+ return flags;
+}
+
+void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags)
+{
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+
+ if (dhd)
+ spin_unlock_irqrestore(&dhd->dhd_lock, flags);
+}
static struct net_device *priv_dev;
static bool ap_cfg_running = FALSE;
bool ap_fw_loaded = FALSE;
+static long ap_cfg_pid = -1;
struct net_device *ap_net_dev = NULL;
struct semaphore ap_eth_sema;
+static struct completion ap_cfg_exited;
static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap);
static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac);
#endif
static int thr_wait_for_2nd_eth_dev(void *data)
{
+ struct net_device *dev = (struct net_device *)data;
+ wl_iw_t *iw;
int ret = 0;
+ unsigned long flags;
+
+ net_os_wake_lock(dev);
DAEMONIZE("wl0_eth_wthread");
goto fail;
}
+ iw = *(wl_iw_t **)netdev_priv(dev);
+ flags = dhd_os_spin_lock(iw->pub);
if (!ap_net_dev) {
WL_ERROR((" ap_net_dev is null !!!"));
ret = -1;
+ dhd_os_spin_unlock(iw->pub, flags);
goto fail;
}
ap_cfg_running = TRUE;
+ dhd_os_spin_unlock(iw->pub, flags);
+
bcm_mdelay(500);
wl_iw_send_priv_event(priv_dev, "AP_SET_CFG_OK");
fail:
WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__));
+ net_os_wake_unlock(dev);
+
+ complete_and_exit(&ap_cfg_exited, 0);
return ret;
}
#endif
goto fail;
}
if (ap_cfg_running == FALSE) {
- kernel_thread(thr_wait_for_2nd_eth_dev, 0, 0);
+ init_completion(&ap_cfg_exited);
+ ap_cfg_pid = kernel_thread(thr_wait_for_2nd_eth_dev, dev, 0);
} else {
+ ap_cfg_pid = -1;
if (ap_net_dev == NULL) {
WL_ERROR(("%s ERROR: ap_net_dev is NULL !!!\n", __FUNCTION__));
goto fail;
if ((ap_cfg_running == TRUE)) {
#ifdef AP_ONLY
- wl_iw_softap_deassoc_stations(dev, NULL);
+ wl_iw_softap_deassoc_stations(dev, NULL);
#else
- wl_iw_softap_deassoc_stations(ap_net_dev, NULL);
+ wl_iw_softap_deassoc_stations(ap_net_dev, NULL);
if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0)
WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res));
net_os_wake_lock(dev);
- WL_TRACE(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name));
+ WL_SOFTAP(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name));
#ifndef AP_ONLY
+ if (ap_cfg_pid >= 0) {
+ wait_for_completion(&ap_cfg_exited);
+ ap_cfg_pid = -1;
+ }
+
if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res));
}