struct sk_buff *skb;
uchar *eth;
uint len;
- void *data, *pnext, *save_pktbuf;
+ void *data, *pnext = NULL, *save_pktbuf;
int i;
dhd_if_t *ifp;
wl_event_msg_t event;
struct ether_header *eh;
struct dot11_llc_snap_header *lsh;
+ ifp = dhd->iflist[ifidx];
+
+ /* Dropping packets before registering net device to avoid kernel panic */
+ if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) {
+ DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n",
+ __FUNCTION__));
+ PKTFREE(dhdp->osh, pktbuf, TRUE);
+ continue;
+ }
+
pnext = PKTNEXT(dhdp->osh, pktbuf);
PKTSETNEXT(wl->sh.osh, pktbuf, NULL);
dhdp->dstats.rx_bytes += skb->len;
dhdp->rx_packets++; /* Local count */
- /* Dropping packets before registering net device to avoid kernel panic */
- if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) {
- DHD_ERROR(("%s: net device is NOT registered yet. drop [%s] packet\n",
- __FUNCTION__, (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) ? "event" : "data"));
- PKTFREE(dhdp->osh, pktbuf, TRUE);
- continue;
- }
-
if (in_interrupt()) {
netif_rx(skb);
} else {
{
dhd_info_t *dhd;
unsigned long flags;
+ int timer_valid = FALSE;
if (!dhdp)
return;
if (ifp->net->netdev_ops == &dhd_ops_pri)
#endif
{
- unregister_netdev(ifp->net);
+ if (ifp->net) {
+ unregister_netdev(ifp->net);
+ free_netdev(ifp->net);
+ ifp->net = NULL;
+ }
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
-
+ dhd->iflist[0] = NULL;
}
}
/* Clear the watchdog timer */
flags = dhd_os_spin_lock(&dhd->pub);
+ timer_valid = dhd->wd_timer_valid;
dhd->wd_timer_valid = FALSE;
dhd_os_spin_unlock(&dhd->pub, flags);
- del_timer_sync(&dhd->timer);
+ if (timer_valid)
+ del_timer_sync(&dhd->timer);
if (dhd->dhd_state & DHD_ATTACH_STATE_THREADS_CREATED) {
#ifdef DHDTHREAD
}
}
wiphy_unregister(wdev->wiphy);
+ wdev->wiphy->dev.parent = NULL;
wiphy_free(wdev->wiphy);
kfree(wdev);
- wl_to_wdev(wl) = NULL;
}
static s32 wl_inform_bss(struct wl_priv *wl)
WL_ERR(("Ioctl buf alloc failed\n"));
goto init_priv_mem_out;
}
- wl->escan_ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
+ wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
if (unlikely(!wl->escan_ioctl_buf)) {
WL_ERR(("Ioctl buf alloc failed\n"));
goto init_priv_mem_out;
static s32 wl_create_event_handler(struct wl_priv *wl)
{
+ int ret = 0;
WL_DBG(("Enter \n"));
- sema_init(&wl->event_sync, 0);
- wl->event_tsk = kthread_run(wl_event_handler, wl, "wl_event_handler");
- if (IS_ERR(wl->event_tsk)) {
- wl->event_tsk = NULL;
- WL_ERR(("failed to create event thread\n"));
- return -ENOMEM;
- }
- return 0;
+
+ wl->event_tsk.thr_pid = DHD_PID_KT_INVALID;
+ PROC_START(wl_event_handler, wl, &wl->event_tsk, 0);
+ if (wl->event_tsk.thr_pid < 0)
+ ret = -ENOMEM;
+ return ret;
}
static void wl_destroy_event_handler(struct wl_priv *wl)
{
- if (wl->event_tsk) {
- send_sig(SIGTERM, wl->event_tsk, 1);
- kthread_stop(wl->event_tsk);
- wl->event_tsk = NULL;
- }
+ if (wl->event_tsk.thr_pid >= 0)
+ PROC_STOP(&wl->event_tsk);
}
static void wl_term_iscan(struct wl_priv *wl)
if (wl->p2p_supported)
wl_cfgp2p_deinit_priv(wl);
wl_deinit_priv(wl);
- wl_free_wdev(wl);
wl_set_drvdata(wl_cfg80211_dev, NULL);
kfree(wl_cfg80211_dev);
wl_cfg80211_dev = NULL;
wl_clear_sdio_func();
+ wl_free_wdev(wl);
}
static void wl_wakeup_event(struct wl_priv *wl)
{
- up(&wl->event_sync);
+ if (wl->event_tsk.thr_pid >= 0)
+ up(&wl->event_tsk.sema);
}
static s32 wl_event_handler(void *data)
{
struct net_device *netdev;
- struct wl_priv *wl = (struct wl_priv *)data;
- struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
+ struct wl_priv *wl = NULL;
struct wl_event_q *e;
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;
- sched_setscheduler(current, SCHED_FIFO, ¶m);
- allow_signal(SIGTERM);
- while (likely(!down_interruptible(&wl->event_sync))) {
- if (kthread_should_stop())
+ wl = (struct wl_priv *)tsk->parent;
+ complete(&tsk->completed);
+
+ while (down_interruptible (&tsk->sema) == 0) {
+ SMP_RD_BARRIER_DEPENDS();
+ if (tsk->terminated)
break;
e = wl_deq_event(wl);
if (unlikely(!e)) {
netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx);
if (!netdev)
netdev = wl_to_prmry_ndev(wl);
- if (wl->evt_handler[e->etype]) {
+ if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
wl->evt_handler[e->etype] (wl, netdev, &e->emsg, e->edata);
} else {
WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
}
wl_put_event(e);
}
+
WL_DBG(("%s was terminated\n", __func__));
+ complete_and_exit(&tsk->completed, 0);
return 0;
}
struct ether_addr bssid; /* bssid of currently engaged network */
/* for synchronization of main event thread */
- struct semaphore event_sync;
struct wl_profile *profile; /* holding dongle profile */
struct wl_iscan_ctrl *iscan; /* iscan controller */
/* control firwmare and nvram paramter downloading */
struct wl_fw_ctrl *fw;
struct wl_pmk_list *pmk_list; /* wpa2 pmk list */
- struct task_struct *event_tsk; /* task of main event handler thread */
+ tsk_ctl_t event_tsk; /* task of main event handler thread */
unsigned long status; /* current dongle status */
void *pub;
u32 channel; /* current channel */