/*
 * Callback from TSF Timer when time is re-sync.
 */
static void
my_tsftimer_resync(tsftimer_handle_t h_tsftime, int arg1, void *arg2, u_int32_t curr_tsf)
{
    ieee80211_p2p_go_schedule_t h_schedule;
    struct ieee80211com         *ic;

    ASSERT(arg1 == P2P_GO_SCH_CB_ID);
    
    h_schedule = (ieee80211_p2p_go_schedule_t)arg2;

    IEEE80211_P2P_GOSCHE_LOCK(h_schedule);

    ic = h_schedule->ic;

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: TSF Resync. Re-process the current schedule.\n", __func__);

    if (!h_schedule->paused) {
        bool        one_shot_noa;   /* Is this a one-shot NOA? */

        process_schedule(h_schedule, curr_tsf, &one_shot_noa);
    }
    else {
        IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_NORMAL, IEEE80211_MSG_P2P_GO_SCH,
            "%s: TSF Resync but paused. Do nothing.\n", __func__);
    }

    IEEE80211_P2P_GOSCHE_UNLOCK(h_schedule);
}
static void deferred_unpause(ieee80211_p2p_go_schedule_t go_schedule)
{
    bool                prev_GO_state;
    u_int32_t           curr_tsf;
    struct ieee80211com *ic;
    bool                one_shot_noa;

    IEEE80211_P2P_GOSCHE_LOCK(go_schedule);

    if (!go_schedule->paused) {
        /* Already paused. Do nothing. */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_NORMAL, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Not paused; do nothing.\n", __func__);
        IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);
        return;
    }

    go_schedule->paused = false;

    /* Process the schedule to kick start it. */
    prev_GO_state = go_schedule->go_present;    /* Remember this state before calling process_schedule() */
    ic = go_schedule->vap->iv_ic;
    curr_tsf = ic->ic_get_TSF32(ic);
    process_schedule(go_schedule, curr_tsf, &one_shot_noa);

    if (go_schedule->go_present == prev_GO_state) {
        /* There is no change in GO state. This means that we did not do a callback. Force a callback. */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_DETAILED, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Do a forced callback.\n", __func__);
        notify_GO_state_change(go_schedule, go_schedule->go_present, one_shot_noa, true);
    }

    IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);
}
/*
 * Find the next events for requests starting from the highest priority one
 * to the first active one. Subsequent lower priority requests are not processed.
 * Note: earliest_next_event returns the request that has the earliest
 * next event but only for requests equal or greater than highest_pri_active.
 */
static void
find_all_next_events(
    ieee80211_p2p_go_schedule_t go_schedule,
    u_int32_t                   event_time,
    int                         *highest_pri_active,
    int                         *earliest_next_event)
{
    int                     i, earliest_event;
    u_int32_t               earliest_next_time = 0;

    earliest_event = -1;
    OS_MEMZERO(&go_schedule->req_state[0], P2P_GO_PS_MAX_NUM_SCHEDULE_REQ * sizeof(struct request_state));
    for (i=(go_schedule->num_schedules-1); i>=0; i--) {
        int                     sort_idx;
        struct request_state    *req = &go_schedule->req_state[i];

        sort_idx = go_schedule->sorted_sch_idx[i];
        req->valid = true;
        req->expired = find_next_event(go_schedule, event_time, &(go_schedule->request[sort_idx]),
                              &req->is_active, &req->next_event_time);

        if (req->expired) {
            continue;
        }

        if (earliest_event == -1) {
            /* Init. the earliest time for next event */
            earliest_next_time = req->next_event_time;
            earliest_event = i;
        }
        else {
            if (TSFTIME_IS_GREATER(earliest_next_time, req->next_event_time)) {
                /* Found an earlier next event */
                earliest_event = i;
                earliest_next_time = req->next_event_time;
            }
        }

        if (req->is_active) {
            /* Find the highest priority request that is active */
            *highest_pri_active = i;
            *earliest_next_event = earliest_event;

            IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_DETAILED, IEEE80211_MSG_P2P_GO_SCH,
                    "%s: highest_pri_active=%d, earliest_next_event=%d\n",
                    __func__, *highest_pri_active, *earliest_next_event);

            return;
        }
    }

    *highest_pri_active = -1;
    *earliest_next_event = earliest_event;

    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
            "%s: highest_pri_active=%d, earliest_next_event=%d\n",
            __func__, *highest_pri_active, *earliest_next_event);

    return;
}
/*
 * register event handler with go scheduler.
 */
int
ieee80211_p2p_go_schedule_register_event_handler(
    ieee80211_p2p_go_schedule_t go_schedule, 
    ieee80211_go_schedule_event_handler evhandler,
    void *Arg)
{
    ASSERT(go_schedule);
    ASSERT(evhandler);

    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: called.\n", __func__);

    IEEE80211_P2P_GOSCHE_LOCK(go_schedule);

    if (go_schedule->evhandler != NULL) {
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_NORMAL, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Warning, there is already a event handler registered.\n", __func__);
    }
    ASSERT(!go_schedule->callback_active);

    // add this event callback to the struc.
    go_schedule->evhandler = evhandler;
    go_schedule->event_arg = Arg;

    IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);

    return 0;
}
/*
 * unregister event handler with go scheduler.
 */
int
ieee80211_p2p_go_schedule_unregister_event_handler(
    ieee80211_p2p_go_schedule_t go_schedule, 
    ieee80211_go_schedule_event_handler evhandler,
    void *Arg)
{
    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: called.\n", __func__);
    
    ASSERT(go_schedule);

    IEEE80211_P2P_GOSCHE_LOCK(go_schedule);

    if (go_schedule->evhandler != NULL) {
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Warning, no event handler registered.\n", __func__);
    }
    if (go_schedule->evhandler != evhandler) {
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Warning, event handler mismatched 0x%x != 0x%x.\n", 
               __func__, go_schedule->evhandler, evhandler);
    }
    ASSERT(!go_schedule->callback_active);

    go_schedule->evhandler = NULL;
    go_schedule->event_arg = NULL;

    IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);

    return 0;
}
static int
deferred_schedule_setup(
    ieee80211_p2p_go_schedule_t         go_schedule,
    u_int8_t                            num_schedules,
    ieee80211_p2p_go_schedule_req       *sch_req)
{

    u_int32_t           curr_tsf;
    struct ieee80211com *ic;
    bool                one_shot_noa;   /* Is this a one-shot NOA? */

    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: called.\n", __func__);

    IEEE80211_P2P_GOSCHE_LOCK(go_schedule);

    /* Keep a copy of the new schedule */
    go_schedule->num_schedules = num_schedules;
    if (num_schedules) {
        /* Copy over the schedule */
        OS_MEMCPY(go_schedule->request, sch_req,
                  sizeof(ieee80211_p2p_go_schedule_req) * num_schedules);

        /* Sort the list of schedules by priority (lowest to highest) */
        sort_schedule_req(go_schedule);
    }

    if (go_schedule->paused) {
        /* Already paused. Do nothing. */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_NORMAL, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Already paused; do nothing but keep copy of new schedule.\n", __func__);
        IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);
        return 0;
    }

    if (num_schedules == 0) {
        /* Empty schedule. We are done. */
        no_more_events(go_schedule);

        IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);

        return 0;
    }

    ASSERT(sch_req);

    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: num_schedules=%d.\n", __func__, num_schedules);

    ic = go_schedule->vap->iv_ic;
    curr_tsf = ic->ic_get_TSF32(ic);

    process_schedule(go_schedule, curr_tsf, &one_shot_noa);

    IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);

    return 0;
}
/*
 * Do a callback when the GO state has changed since last notification.
 * Assumed the lock is held.
 */
static void
notify_GO_state_change(
    ieee80211_p2p_go_schedule_t go_schedule, 
    bool                        GO_awake,
    bool                        one_shot_noa,    /* Is this a one-shot NOA? */
    bool                        forced_callback  /* Do a callback even if state is not changed */
    )
{
    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: GO_awake=%d\n", __func__, GO_awake);

    if ((go_schedule->evhandler && (go_schedule->go_present != GO_awake)) ||
        forced_callback)
    {

        /* New schedule state is different from current state. Do a callback. */
        ieee80211_p2p_go_schedule_event     new_event;

        if (GO_awake) {
            new_event.type = IEEE80211_P2P_GO_SCHEDULE_EVENT_GO_PRESENT;
        }
        else {
            new_event.type = IEEE80211_P2P_GO_SCHEDULE_EVENT_GO_ABSENT;
        }

        // TODO: need to double-check that we are handling the lock and re-entrancy issues

        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
                            "%s: Diff. state. Old=%d, New=%d. One-shot=%d, Do the event callback.\n",
                             __func__, go_schedule->go_present, GO_awake, one_shot_noa);

        if (go_schedule->callback_active) {
            /* Already in the middle of a callback. */
            // TODO: need to handle this error case.
            IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
                                 "%s: ERROR: Callback already active.\n", __func__);
            return;
        }

        go_schedule->go_present = GO_awake;
        go_schedule->callback_active = true;

        IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);

        /* NOTE: Call the callback but without spinlock */
        (*go_schedule->evhandler)(go_schedule, &new_event, go_schedule->event_arg, one_shot_noa);

        IEEE80211_P2P_GOSCHE_LOCK(go_schedule);

        ASSERT(go_schedule->callback_active);
        go_schedule->callback_active = false;
    }
    else {
        go_schedule->go_present = GO_awake;
    }
}
Beispiel #8
0
/*
 * External UMAC Interface
 */
wlan_if_t
wlan_vap_create(wlan_dev_t            devhandle,
                enum ieee80211_opmode opmode,
                int                   scan_priority_base,
                int                   flags,
                u_int8_t              *bssid,
                u_int8_t              *mataddr,
                int                     unit)
{
    struct ieee80211com *ic = devhandle;
    struct ieee80211vap *vap;

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_LOUD, IEEE80211_MSG_DEBUG,
                         "%s : enter. devhandle=0x%x, opmode=%s, flags=0x%x\n", 
             __func__, 
             devhandle,
             ieee80211_opmode2string(opmode),
             flags
             );

    vap = ic->ic_vap_create(ic, opmode, scan_priority_base, flags, bssid, mataddr,unit);
    if (vap == NULL) {
        printk("%s: failed to create a vap object\n", __func__);
        return NULL;
    }

    ieee80211_vap_pause_late_vattach(ic,vap); 
    ieee80211_resmgr_vattach(ic->ic_resmgr, vap);

    ieee80211_vap_deleted_clear(vap); /* clear the deleted */

    /* when all  done,  add vap to queue */
    IEEE80211_COMM_LOCK(ic);
    TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next);
    IEEE80211_COMM_UNLOCK(ic);

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_LOUD, IEEE80211_MSG_DEBUG,
             "%s : exit. devhandle=0x%x, opmode=%s, flags=0x%x.\n",
             __func__, 
             devhandle,
             ieee80211_opmode2string(opmode),
             flags
             );
#if ATH_SUPPORT_FLOWMAC_MODULE
    /* 
     * Due to platform dependency the flow control need to check the status
     * of the lmac layer before enabling the flow mac at vap layer.
     * 
     * Enabling of the flowmac happens after creating the wifi interface
     */
    vap->iv_flowmac = ic->ic_get_flowmac_enabled_State(ic);
#endif
    return vap;
}
Beispiel #9
0
int
wlan_vap_delete(wlan_if_t vaphandle)
{
    struct ieee80211vap *vap = vaphandle;
    struct ieee80211com *ic = vap->iv_ic;

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_LOUD,IEEE80211_MSG_DEBUG,
                         "%s : enter. vaphandle=0x%x\n", 
             __func__, 
             vaphandle
             );

    ieee80211_vap_pause_vdetach(ic,vap);

    IEEE80211_COMM_LOCK(ic);
#ifdef MAGPIE_HIF_GMAC
    if (ic->ic_chanchange_cnt)
        ic->ic_chanchange_cnt -= ic->ic_chanchange_tbtt;
#endif    
    if (ieee80211_vap_deleted_is_clear(vap)) /* if not deleted then it is on the list */
    {
        TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
        if (TAILQ_EMPTY(&ic->ic_vaps))      /* reset to supported mode */
            ic->ic_opmode = IEEE80211_M_STA;
        ieee80211_vap_deleted_set(vap); /* mark it as deleted */
        IEEE80211_COMM_UNLOCK(ic);

        /*
         * In case iv_bss was not stopped or is in scanning.
         * TBD: BSS should have been stopped now. We can save the time for stop bss again.
         */
        wlan_mlme_stop_bss(vap,
                           WLAN_MLME_STOP_BSS_F_SEND_DEAUTH        | 
                           WLAN_MLME_STOP_BSS_F_CLEAR_ASSOC_STATE  |
                           WLAN_MLME_STOP_BSS_F_WAIT_RX_DONE       |
                           WLAN_MLME_STOP_BSS_F_NO_RESET);

        ieee80211_sta_leave(vap->iv_bss);
        ieee80211_node_vdetach(vap);
    } else {
        IEEE80211_COMM_UNLOCK(ic);
    }

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_LOUD,IEEE80211_MSG_DEBUG,
                         "%s : exit. vaphandle=0x%x\n", 
             __func__, 
             vaphandle
             );
    return 0;
}
/*
 * unpause P2p GO scheduler. the scheduler should restart all the timers.
 * it should also generate a go event idicating the current state of the GO.
 */
void ieee80211_p2p_go_schedule_unpause(ieee80211_p2p_go_schedule_t go_schedule)
{
    if (OS_MESGQ_SEND(&go_schedule->cmd_mesg_q, IEEE80211_P2P_GO_SCH_UNPAUSE, 0, NULL) != 0) {
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
            "%s: message queue send failed \n", __func__);
    }
}
Beispiel #11
0
static void ieee80211_resmgr_reset_power_state(ieee80211_resmgr_t resmgr)
{
    int pm_state;
    struct ieee80211com *ic = resmgr->ic;
    ieee80211_resmgr_vap_pmstate_t combined_state = VAP_PM_FULL_SLEEP;

    IEEE80211_RESMGR_LOCK(resmgr);

    if (resmgr->is_scan_in_progress) {
        combined_state = VAP_PM_ACTIVE;
    } else {
        wlan_iterate_vap_list(ic, ieee80211_vap_iter_pm_state, (void *)&combined_state);
    }

    switch(combined_state) {
    case VAP_PM_FULL_SLEEP:
        pm_state = IEEE80211_PWRSAVE_FULL_SLEEP;
        break;
    case VAP_PM_NW_SLEEP:
        pm_state = IEEE80211_PWRSAVE_NETWORK_SLEEP;
        break;
    default:
        pm_state = IEEE80211_PWRSAVE_AWAKE;
        break;
    }
    if (pm_state != resmgr->pm_state) {
        IEEE80211_DPRINTF_IC(ic, IEEE80211_MSG_POWER, IEEE80211_VERBOSE_LOUD,
                "%s: changing chip power state from %s to %s \n",
                __func__, state_to_name[resmgr->pm_state],
                state_to_name[pm_state]);
        resmgr->pm_state = pm_state;
        ic->ic_pwrsave_set_state(ic, pm_state);
    }
    IEEE80211_RESMGR_UNLOCK(resmgr);
}
/*
 * Callback from TSF Timer for timer expiry.
 */
static void
my_tsftimer_timeout(tsftimer_handle_t h_tsftime, int arg1, void *arg2, u_int32_t curr_tsf)
{
    ieee80211_p2p_go_schedule_t h_schedule;

    ASSERT(arg1 == P2P_GO_SCH_CB_ID);
    
    h_schedule = (ieee80211_p2p_go_schedule_t)arg2;

    IEEE80211_P2P_GOSCHE_LOCK(h_schedule);

    ASSERT(h_schedule->h_tsftimer == h_tsftime);
    
    ASSERT(h_schedule->evhandler != NULL);

    // TODO: need to do the callback. Need to unlock before calling too.

    IEEE80211_DPRINTF_IC(h_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: called. GO is currently %s. curr_tsf=0x%x\n", __func__, 
           (h_schedule->go_present? "awaked" : "asleep"),
           curr_tsf);

    if (h_schedule->tsftimer_started) {

        h_schedule->tsftimer_started = false;
    
        if (!h_schedule->paused) {
            /* Process the schedule based on new TSF. Any callback will be done in this function. */
            bool        one_shot_noa;   /* Is this a one-shot NOA? */
    
            process_schedule(h_schedule, curr_tsf, &one_shot_noa);
        }
        else {
            IEEE80211_DPRINTF_IC(h_schedule->ic, IEEE80211_VERBOSE_NORMAL, IEEE80211_MSG_P2P_GO_SCH,
                "%s: TSF Timer triggered but paused. Do nothing.\n", __func__);
        }
    }
    else {
        IEEE80211_DPRINTF_IC(h_schedule->ic, IEEE80211_VERBOSE_NORMAL, IEEE80211_MSG_P2P_GO_SCH,
            "%s: TSF Timer triggered but timer stopped. Do nothing.\n", __func__);
    }

    IEEE80211_P2P_GOSCHE_UNLOCK(h_schedule);
}
/*
 * This function will sort the array of schedule requests from lowest to highest.
 * A 0 value in pri field is highest priority and 1 is lower priority than 0 and so on.
 * Note: we do not move the array elements but just update the index, sorted_sch.
 */
static void
sort_schedule_req(
    ieee80211_p2p_go_schedule_t     go_schedule)
{
    int     *sort_idx;
    int     i;
    int     num_schedules = go_schedule->num_schedules;

    sort_idx = go_schedule->sorted_sch_idx;

    for (i=0; i<num_schedules; i++) {
        sort_idx[i] = i;
    }
    for (i=0; i<num_schedules; i++) {
        int         tmp, lowest_idx, j;
        u_int8_t    lowest_pri;

        /* Find the lowest priority to put infront */
        lowest_pri = go_schedule->request[sort_idx[i]].pri;
        lowest_idx = i;
        for (j=i+1; j<num_schedules; j++) {
            /* Note: the lower the priority, the bigger the pri field value. */
            if (lowest_pri < go_schedule->request[sort_idx[j]].pri) {
                lowest_pri = go_schedule->request[sort_idx[j]].pri;
                lowest_idx = j;
            }
        }
        /* swap the lowest to index i */
        if (lowest_idx != i) {
            tmp = sort_idx[i];
            sort_idx[i] = sort_idx[lowest_idx];
            sort_idx[lowest_idx] = tmp;
        }
    }

#ifdef DBG
    /* For Debugging purposes, dump out the list. */
    for (i=0; i<num_schedules; i++) {
        int         sort_idx;

        sort_idx = go_schedule->sorted_sch_idx[i];

        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
            "%s: [%d->%d]: pri=%d, type=%s, cnt=%d, dur=0x%x,int=0x%x,start=0x%x\n",
               __func__, i, sort_idx, 
               go_schedule->request[sort_idx].pri, 
               go_schedule->request[sort_idx].type==IEEE80211_P2P_GO_SCHEDULE_EVENT_GO_ABSENT?"NOA ":"Pres",
               go_schedule->request[sort_idx].noa_descriptor.type_count,
               go_schedule->request[sort_idx].noa_descriptor.duration,
               go_schedule->request[sort_idx].noa_descriptor.interval,
               go_schedule->request[sort_idx].noa_descriptor.start_time
            );
    }
#endif

}
/* Stop the TSF timer if it is running. */
static int
stop_tsftimer(ieee80211_p2p_go_schedule_t go_schedule)
{
    int     ret = 0;

    if (go_schedule->tsftimer_started) {
        /* Stop this timer. */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_DETAILED, IEEE80211_MSG_P2P_GO_SCH,
                             "%s: stop timer.\n", __func__);
        ret = ieee80211_tsftimer_stop(go_schedule->h_tsftimer);
        if (ret != 0) {
            IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
                                 "%s: ERROR: ieee80211_tsftimer_stop returns error=%d\n", __func__, ret);
        }

        go_schedule->tsftimer_started = false;
    }
    return ret;
}
/*
 * delete the p2p schedule module.
 */
int
ieee80211_p2p_go_schedule_delete(
    ieee80211_p2p_go_schedule_t go_scheduler)
{
    IEEE80211_DPRINTF_IC(go_scheduler->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: called.\n", __func__);

    // free the tsf timer. Blocked to wait for any existing callbacks to end.
    if (ieee80211_tsftimer_free(go_scheduler->h_tsftimer, true)) {
       IEEE80211_DPRINTF_IC(go_scheduler->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
             "%s: 0 ieee80211_tsftimer_free returns error.\n", __func__);
    }

    ASSERT(!go_scheduler->callback_active);

    OS_MESGQ_DESTROY(&go_scheduler->cmd_mesg_q);

    IEEE80211_P2P_GOSCHE_LOCK_DESTROY(go_scheduler);

    // free the structure ieee80211_p2p_go_schedule_t
    OS_FREE(go_scheduler);

    return 0;
}
/*
 * Set up p2p go schedules. will start generating the events.  
 * if there was an old schedule in place, it will restart with the new schedule.
 * if num_schdules is 0 then will stop.   
 */
int
ieee80211_p2p_go_schedule_setup(
    ieee80211_p2p_go_schedule_t         go_schedule,
    u_int8_t                            num_schedules,
    ieee80211_p2p_go_schedule_req       *sch_req)
{
    ASSERT(go_schedule);

    if (num_schedules > P2P_GO_PS_MAX_NUM_SCHEDULE_REQ) {
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Too many schedules=%d, max=%d\n", __func__, 
               num_schedules, P2P_GO_PS_MAX_NUM_SCHEDULE_REQ);
        return EINVAL;
    }

    if (OS_MESGQ_SEND(&go_schedule->cmd_mesg_q, IEEE80211_P2P_GO_SCH_SETUP,
                      (num_schedules * sizeof(ieee80211_p2p_go_schedule_req)),
                      (void *)sch_req) != 0)
    {
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
            "%s: message queue send failed \n", __func__);
    }
    return 0;
}
/*
 * pause P2p GO scheduler. the scheduler should cancel all timers and pause.
 */
void ieee80211_p2p_go_schedule_pause(ieee80211_p2p_go_schedule_t go_schedule)
{
    IEEE80211_P2P_GOSCHE_LOCK(go_schedule);

    if (go_schedule->paused) {
        /* Already paused. Do nothing. */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_NORMAL, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Already paused; do nothing.\n", __func__);
        IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);
        return;
    }

    go_schedule->paused = true;

    // cancel timers (if any)
    stop_tsftimer(go_schedule);
    go_schedule->tsftimer_started = false;

    IEEE80211_P2P_GOSCHE_UNLOCK(go_schedule);
}
static void  ieee80211_p2p_go_schedule_mesgq_event_handler(void *ctx, u_int16_t event,
                                           u_int16_t event_data_len, void *event_data)
{
    ieee80211_p2p_go_schedule_t go_schedule = (ieee80211_p2p_go_schedule_t)ctx;

    if (event == IEEE80211_P2P_GO_SCH_UNPAUSE) {
        deferred_unpause(go_schedule);
    }
    else if (event == IEEE80211_P2P_GO_SCH_SETUP) {
        int         ret;
        u_int8_t    num_schedules;

        num_schedules = (u_int8_t)(event_data_len / sizeof(ieee80211_p2p_go_schedule_req));
        ASSERT((event_data_len % sizeof(ieee80211_p2p_go_schedule_req)) == 0);
        ret = deferred_schedule_setup(go_schedule, num_schedules, 
                                      (ieee80211_p2p_go_schedule_req *)event_data);
        ASSERT(ret == 0);   /* Should not fail */
    }
    else {
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Error: unknown event=%d\n", __func__, event);
        ASSERT(false);
    }
}
/*
 * To calculate the new schedule. Update the current "GO Present" state.
 * Assumed that lock is held.
 * Returns 1 if the next TSF Timer needs to be set. The TSF Time for the 
 * next timer expiry is returned in the next_timeout parameter.
 * highest_active_index is the index in the requested schedules where this event is based on.
 * Returns 0 if there is no more timer to set.
 */
static int
calc_schedules(
    ieee80211_p2p_go_schedule_t go_schedule,
    u_int32_t                   curr_tsf,
    u_int32_t                   *next_timeout,
    bool                        *GO_awake,
    int                         *highest_active_index)
{
    u_int32_t               event_time;
    int                     highest_active, earliest_event;
    int                     earliest_next_idx;
    int                     sanity_count = 64;
    struct request_state    *req = &go_schedule->req_state[0];

    *highest_active_index = NO_ACTIVE_SCHEDULE;

    if (go_schedule->num_schedules == 0) {
        /* Nothing to do next. Schedule is empty. */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
            "%s: num_schedules==0. Nothing to do.\n", __func__);
        *GO_awake = true;   /* Assume that GO is awake when no schedule */
        return 0;
    }
    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: curr_tsf=0x%x, num_schedules=%d\n", __func__, curr_tsf, go_schedule->num_schedules);
    
    /* 
     * The array of schedule is already sorted by priority (lowest first)
     * using go_schedule->sorted_sch_idx[i].
     */
    
    event_time = curr_tsf;
    
    /* Find the earliest and active event at time==event_time */
    find_all_next_events(go_schedule, event_time, &highest_active, &earliest_event);
    if (highest_active == -1) {
        /* No requests are currently active */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Init: No requests are currently active, assumed GO is awake, earliest_event=%d\n",
               __func__, earliest_event);
        *GO_awake = true;       /* Assumed is awake when no outstanding request */

        if (earliest_event == -1) {
            IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
                "%s: Init: No next event. Nothing to do.\n", __func__);
            return 0;   // nothing to do.
        }
    }
    else {
        /* Init. the GO state to this active request */
        ASSERT(req[highest_active].is_active);
        *GO_awake = get_GO_wake_state(go_schedule, highest_active);

        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
            "%s: Init: highest active event=%d, GO_awake=0x%x.\n",
               __func__, highest_active, *GO_awake);

        /* Return the index of the highest priority and currently active schedule request */
        *highest_active_index = go_schedule->sorted_sch_idx[highest_active];
    }

    /* Find the next event time */
    while (sanity_count--) {
    
        ASSERT(((highest_active != -1) && req[highest_active].is_active && (!req[highest_active].expired)) ||
               ((highest_active == -1) && (earliest_event != -1)));

        earliest_next_idx = find_earliest_next_event(go_schedule, highest_active);
        ASSERT(earliest_next_idx != -1);
        if (earliest_next_idx == highest_active) {
            /* No higher priority request with earlier next event */
            event_time = req[earliest_next_idx].next_event_time;
        }
        else {
            /* Move time forward to the earliest event */
            event_time = req[earliest_next_idx].next_event_time;
        }

        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
            "%s: While Loop: highest_active=%d, earliest_next_idx=%d, event_time=0x%x\n",
               __func__, highest_active, earliest_next_idx, event_time);

        find_all_next_events(go_schedule, event_time, &highest_active, &earliest_event);
        if (highest_active == -1) {
            /* No active request schedules or all have expired */
            if (*GO_awake) {
                /* Note: we consider GO to be awake when no active requests */
                if (earliest_event != -1) {
                    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
                        "%s: GO awake and earliest_event=%d\n", __func__, earliest_event);
                }
                else {
                    /* No more events */
                    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
                        "%s: No more events and GO awake\n", __func__);
                    return 0;
                }
            }
            else {
                *next_timeout = event_time;
                IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
                    "%s: No active requests, earliest_event=%d, GO is asleep and return next_timeout=0x%x\n",
                       __func__, earliest_event, *next_timeout);
                return 1;
            }
        }
        else {
            bool    new_GO_awake;

            ASSERT(req[highest_active].is_active);
            new_GO_awake = get_GO_wake_state(go_schedule, highest_active);
            
            IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
                "%s: Have active requests, GO new=%d, current=%d\n",
                   __func__, new_GO_awake, *GO_awake);

            if (new_GO_awake != *GO_awake) {
                *next_timeout = event_time;
                ASSERT(curr_tsf != event_time);
                return 1;
            }
            else {
                ASSERT(!req[highest_active].expired);
            }
        }
    }
    
    /* 
     * We have processed at least "sanity_count" number of next events without
     * GO state changing. We presumed that it is not going to change anymore.
     * E.g. if you have one single Presence request, then we could get here.
     */

    ASSERT(sanity_count==-1);
    ASSERT(*GO_awake);
    
    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
        "%s: the GO state=%d did not change after %d iterations.\n", 
           __func__, *GO_awake, sanity_count);

    /* No more events */
    return 0;    
}
/*
 * Return false if successful. true if the schedule request is already over (expired).
 * The is_active parameter will return if this current request is currently active.
 * The next_event_time parameter will return the next event time. The said event can be 
 * when the NOA/Presence is going to start or stop.
 * Assumed that the lock is held.
 */
static bool
find_next_event(
    ieee80211_p2p_go_schedule_t         go_schedule,
    u_int32_t                           curr_tsf,           /* current TSF Time */
    ieee80211_p2p_go_schedule_req       *schedule,          /* current NOA or Presence Request */
    bool                                *is_active,         /* Return to indicate if NOA/Presence is active right now */
    u_int32_t                           *next_event_time)   /* Return the next event time; can be the time to stop or start NOA */
{
    u_int32_t                           no_intervals, interval_start;
    struct ieee80211_p2p_noa_descriptor *noa;   /* Note: NOA can also be a Request for Presence. */

    noa = &(schedule->noa_descriptor);

    if ((TSFTIME_IS_SMALLER(curr_tsf, noa->start_time))) {
        /* This request has not started yet */
        *is_active = false;
        *next_event_time = noa->start_time;
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_DETAILED, IEEE80211_MSG_P2P_GO_SCH,
                "%s: req has not started yet. curr_tsf=0x%x, noa->start_time=%d, is_active=%d\n", 
                __func__, curr_tsf, noa->start_time, *is_active);
        return false;
    }

    ASSERT((noa->type_count <= 1) || TSFTIME_IS_SMALLER(noa->duration , noa->interval));

    if (noa->type_count != 255) {
        /* Non-continuous schedule. Check if this request is already over. */
        u_int32_t end_time;

        if (noa->type_count == 1) {
            /* For one-shot NOA, the interval may not be valid. */
            noa->interval = noa->duration;
        }

        ASSERT(TSFTIME_IS_SMALLER((noa->interval * noa->type_count), (0x7FFFFFFF)));

        end_time = noa->start_time + (noa->type_count * noa->interval);

        if (TSFTIME_IS_GREATER_EQ(curr_tsf, end_time)) {
            /* This request has already completed. */
            *is_active = false;
            *next_event_time = curr_tsf;
            IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_DETAILED, IEEE80211_MSG_P2P_GO_SCH,
                    "%s: req has ended. curr_tsf=0x%x, pri=%d, is_active=%d, next_event_time=0x%x\n", 
                    __func__, curr_tsf, schedule->pri, *is_active, *next_event_time);
            return true;
        }
    }

    no_intervals = (curr_tsf - noa->start_time) / noa->interval;
    ASSERT((noa->type_count == 255) || (no_intervals < noa->type_count));
    interval_start = noa->start_time + (no_intervals * noa->interval);

    ASSERT(TSFTIME_IS_GREATER_EQ(curr_tsf, interval_start));

    if (TSFTIME_IS_SMALLER(curr_tsf, (interval_start + noa->duration))) {
        /* Currently in the middle of an NOA */
        *is_active = true;
        *next_event_time = (interval_start + noa->duration);
    }
    else {
        /* The NOA has completed */
        *is_active = false;
        *next_event_time = (interval_start + noa->interval);
    }

    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_DETAILED, IEEE80211_MSG_P2P_GO_SCH,
            "%s: curr_tsf=0x%x, pri=%d, no_intervals=0x%x. interval_start=0x%x, is_active=%d, next_event_time=0x%x\n", 
            __func__, curr_tsf, schedule->pri, no_intervals, interval_start, *is_active, *next_event_time);

    return false;
}
/*
 * crete an instance of the p2p schedule module.
 */
ieee80211_p2p_go_schedule_t
ieee80211_p2p_go_schedule_create(
    osdev_t os_handle, wlan_if_t vap)
{
    struct ieee80211com         *ic;
    ieee80211_p2p_go_schedule_t h_schedule = NULL;
    bool                        bad_return = false;
    tsftimer_handle_t           h_tsftimer = NULL;
    bool                        msg_queue_init = false;

    ASSERT(vap);
    ic = vap->iv_ic;

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: called.\n", __func__);

    do {
        // alloc the mem for structure of ieee80211_p2p_go_schedule
        h_schedule = (ieee80211_p2p_go_schedule_t)
                        OS_MALLOC(os_handle, sizeof(struct ieee80211_p2p_go_schedule), 0);
        if (h_schedule == NULL) {
            IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
                "%s: Failed to alloc memory (size=%d).\n", __func__,
                   sizeof(struct ieee80211_p2p_go_schedule));
            bad_return = true;
            break;
        }

        // zero out and then init. the contents
        OS_MEMZERO(h_schedule, sizeof(struct ieee80211_p2p_go_schedule));
        h_schedule->vap = vap;
        h_schedule->ic = ic;
        h_schedule->os_handle = os_handle;
        IEEE80211_P2P_GOSCHE_LOCK_INIT(h_schedule);

        h_schedule->go_present = true;   /* GO start off from being awake */

        if (OS_MESGQ_INIT(os_handle, &h_schedule->cmd_mesg_q,
                          sizeof(ieee80211_p2p_go_schedule_req) * P2P_GO_PS_MAX_NUM_SCHEDULE_REQ,
                          P2P_GO_SCH_MAX_EVENT_QUEUE_DEPTH, 
                          ieee80211_p2p_go_schedule_mesgq_event_handler,
                          h_schedule, 
                          MESGQ_PRIORITY_NORMAL, 
                          MESGQ_ASYNCHRONOUS_EVENT_DELIVERY) != 0)
        {
            IEEE80211_DPRINTF_IC(h_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
                "%s : OS_MESGQ_INIT  failed.\n", __func__);
            bad_return = true;
            break;
        }
        msg_queue_init = true;

        /* alloc a tsf timer */
        h_tsftimer = ieee80211_tsftimer_alloc(ic->ic_tsf_timer, 0, my_tsftimer_timeout,
                                              P2P_GO_SCH_CB_ID, h_schedule, my_tsftimer_resync);
        if (h_tsftimer == NULL) {
            IEEE80211_DPRINTF_IC(h_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
                "%s: 0 ieee80211_tsftimer_alloc returns error.\n", __func__);
            bad_return = true;
            break;
        }
        h_schedule->h_tsftimer = h_tsftimer;
        h_schedule->tsftimer_started = false;
        h_schedule->paused = false;

    } while ( FALSE );

    if (!bad_return) {
        return h_schedule;
    }
    else {
    
        /* Free the TSF Timer */
        if (h_tsftimer) {
            if (ieee80211_tsftimer_free(h_tsftimer, true)) {
               IEEE80211_DPRINTF_IC(h_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
                "%s: 0 ieee80211_tsftimer_free returns error.\n", __func__);
            }
            h_tsftimer = NULL;
        }

        if (msg_queue_init) {
            OS_MESGQ_DESTROY(&h_schedule->cmd_mesg_q);
            msg_queue_init = false;
        }

        /* Free structure of ieee80211_p2p_go_schedule */
        if (h_schedule) {
            IEEE80211_P2P_GOSCHE_LOCK_DESTROY(h_schedule);
            OS_FREE(h_schedule);
            h_schedule = NULL;
        }
    
        return NULL;
    }
}
Beispiel #22
0
/* End: gengzj added end */
int
wlan_vap_delete(wlan_if_t vaphandle)
{
    struct ieee80211vap *vap = vaphandle;
    struct ieee80211com *ic = vap->iv_ic;

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_LOUD,IEEE80211_MSG_DEBUG,
                         "%s : enter. vaphandle=0x%x\n",
                         __func__,
                         vaphandle
                        );

    ieee80211_vap_pause_vdetach(ic,vap);

    IEEE80211_COMM_LOCK(ic);
    /* Begin: gengzj added for wifipos 2013-11-26 */
    /*AUTELAN-Added-begin:Added by pengdecai for wifi scan locate function*/
#if 0
    if((NULL != vap->iv_scan_locate) && \
            (NULL != vap->iv_scan_locate->sl_sock))
    {
        //	printk("driver:fun %s  vap->iv_scan_locate->sl_sock= %p\n",__func__, vap->iv_scan_locate->sl_sock);
        vap->iv_locate = 0;
        if(NULL != vap->iv_scan_locate->sl_sock) {
            OS_SOCKET_RELEASE(vap->iv_scan_locate->sl_sock);
        }
        //free scan locate struct
        OS_FREE(vap->iv_scan_locate);
        vap->iv_scan_locate = NULL;
    }
#endif
    /*AUTELAN-Added-end:Added by pengdecai for wifi scan locate function*/
    /* End: gengzj added end */

#ifdef MAGPIE_HIF_GMAC
    if (ic->ic_chanchange_cnt)
        ic->ic_chanchange_cnt -= ic->ic_chanchange_tbtt;
#endif
    if (ieee80211_vap_deleted_is_clear(vap)) /* if not deleted then it is on the list */
    {
        TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
        if (TAILQ_EMPTY(&ic->ic_vaps))      /* reset to supported mode */
            ic->ic_opmode = IEEE80211_M_STA;
        ieee80211_vap_deleted_set(vap); /* mark it as deleted */
        IEEE80211_COMM_UNLOCK(ic);

        /*
         * In case iv_bss was not stopped or is in scanning.
         * TBD: BSS should have been stopped now. We can save the time for stop bss again.
         */
        wlan_mlme_stop_bss(vap,
                           WLAN_MLME_STOP_BSS_F_SEND_DEAUTH        |
                           WLAN_MLME_STOP_BSS_F_CLEAR_ASSOC_STATE  |
                           WLAN_MLME_STOP_BSS_F_WAIT_RX_DONE       |
                           WLAN_MLME_STOP_BSS_F_NO_RESET);

        /*zhaoyang1 transplant from 717*/
        /*suzhaoyu add for customer online-traffic limit*/
        OS_FREE_TIMER(&vap->online_traffic_timer);
        /*suzhaoyu addend*/
        /*zhaoyang1 transplant end*/
        ieee80211_sta_leave(vap->iv_bss);
        ieee80211_node_vdetach(vap);
    } else {
        IEEE80211_COMM_UNLOCK(ic);
    }

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_LOUD,IEEE80211_MSG_DEBUG,
                         "%s : exit. vaphandle=0x%x\n",
                         __func__,
                         vaphandle
                        );
    return 0;
}
/*
 * Process the given schedule and reschedule the timer for the next callback event.
 * Assumed that the lock is held.
 */
static void
process_schedule(
    ieee80211_p2p_go_schedule_t     go_schedule,
    u_int32_t                       curr_tsf,
    bool                            *one_shot_noa    /* Is this a one-shot NOA? */
    )
{
    u_int32_t           next_timeout = 0;
    bool                GO_awake=false;
    int                 ret;
    int                 highest_active_index;

    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: curr_tsf=0x%x, num_schedules=%d\n", __func__, curr_tsf, go_schedule->num_schedules);
    
    *one_shot_noa = false;

    /* Calculate the time for next event and current GO state. */
    ret = calc_schedules(go_schedule, curr_tsf, &next_timeout, &GO_awake, &highest_active_index);

    IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
        "%s: calc_schedules ret/More Req.=%d, curr_tsf=0x%x, next_timeout=0x%x, GO_awake=%d\n",
           __func__, ret, curr_tsf, next_timeout, GO_awake);

    if (ret == 0) {
        /* No more active requests. Stop the timer (if started). */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_DETAILED, IEEE80211_MSG_P2P_GO_SCH,
            "%s: No more active requests. Stop the timer. GO_awake=%d\n", __func__, GO_awake);
        ASSERT(GO_awake);
        no_more_events(go_schedule);
        return;
    }
    else if (ret == 1) {
        /* More pending request. Check if we need to adjust the next TSF Timeout. */
        bool restart_timer = false;

        if (!go_schedule->tsftimer_started) {
            /* Start a new timer */
            restart_timer = true;
        }
        else {
            /* Timer is already started. Check if the timeout is still the same. Else Rescheduled. */
            if (go_schedule->tsftimer_timeout != next_timeout) {
                IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
                    "%s: stop old timer. Will restart again with new timeout=0x%x\n", __func__, next_timeout);
                stop_tsftimer(go_schedule);
                go_schedule->tsftimer_started = false;

                restart_timer = true;
            }
            else {
                /* No change in current Timeout. Just notify if GO state changes */
            }
        }

        if (!GO_awake) {
            /* Find out if this is a one-shot NOA */
            if (highest_active_index != NO_ACTIVE_SCHEDULE) {

                ieee80211_p2p_go_schedule_req   *req;

                req = &(go_schedule->request[highest_active_index]);

                if ((req->type == IEEE80211_P2P_GO_ABSENT_SCHEDULE) &&
                    (req->noa_descriptor.type_count == 1)) 
                {
                    *one_shot_noa = true;
                }
            }
        }

        notify_GO_state_change(go_schedule, GO_awake, *one_shot_noa, false);

        if ((!go_schedule->paused) && restart_timer) {
            IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_FUNCTION, IEEE80211_MSG_P2P_GO_SCH,
                "%s: start timer, timeout=0x%x\n", __func__, next_timeout);
            ret = ieee80211_tsftimer_start(go_schedule->h_tsftimer, next_timeout, 0);
            if (ret != 0) {
                IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
                    "%s: ERROR: ieee80211_tsftimer_start returns error=%d\n", __func__, ret);
                go_schedule->tsftimer_started = false;
                return;
            }
            go_schedule->tsftimer_started = true;
            go_schedule->tsftimer_timeout = next_timeout;
        }
        else if (restart_timer) {
            IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_NORMAL, IEEE80211_MSG_P2P_GO_SCH,
                "%s: Paused: do not restart timer\n", __func__);
        }
    }
    else {
        /* TODO: handle this error condition */
        IEEE80211_DPRINTF_IC(go_schedule->ic, IEEE80211_VERBOSE_SERIOUS, IEEE80211_MSG_P2P_GO_SCH,
            "%s: ERROR: calc_schedules return %d\n", __func__, ret);
    }

}
Beispiel #24
0
/*
 * External UMAC Interface
 */
wlan_if_t
wlan_vap_create(wlan_dev_t            devhandle,
                enum ieee80211_opmode opmode,
                int                   scan_priority_base,
                int                   flags,
                u_int8_t              *bssid)
{
#if ATH_SUPPORT_FLOWMAC_MODULE
#define FLOWMAC_FLOWCONTROL_VAP 1
#define FLOWMAC_FLOWCONTROL_ETH 2
#endif
    struct ieee80211com *ic = devhandle;
    struct ieee80211vap *vap;

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_LOUD, IEEE80211_MSG_DEBUG,
                         "%s : enter. devhandle=0x%x, opmode=%s, flags=0x%x\n",
                         __func__,
                         devhandle,
                         ieee80211_opmode2string(opmode),
                         flags
                        );

    vap = ic->ic_vap_create(ic, opmode, scan_priority_base, flags, bssid);
    if (vap == NULL) {
        printk("%s: failed to create a vap object\n", __func__);
        return NULL;
    }

    ieee80211_vap_pause_late_vattach(ic,vap);
    ieee80211_resmgr_vattach(ic->ic_resmgr, vap);

    ieee80211_vap_deleted_clear(vap); /* clear the deleted */

    /* when all  done,  add vap to queue */
    IEEE80211_COMM_LOCK(ic);
    TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next);
    IEEE80211_COMM_UNLOCK(ic);

    IEEE80211_DPRINTF_IC(ic, IEEE80211_VERBOSE_LOUD, IEEE80211_MSG_DEBUG,
                         "%s : exit. devhandle=0x%x, opmode=%s, flags=0x%x.\n",
                         __func__,
                         devhandle,
                         ieee80211_opmode2string(opmode),
                         flags
                        );
    /* Begin: gengzj added for wifipos 2013-11-26 */
    /*AUTELAN-Added-begin:Added by pengdecai for wifi scan locate function*/
    vap->iv_locate = 0;
    vap->iv_sl_debug = 0;
    vap->iv_sl_asinfo = 0;
    vap->iv_sl_pckcnt = 0;
    /*AUTELAN-Added-end:Added by pengdecai for wifi scan locate function*/
    /* End: gengzj added end */
    /* TODO FIXME
    *  To check the ath layer flow control status in softc and the create
    *  enable or disable the flow control status in vap
    */
#if ATH_SUPPORT_FLOWMAC_MODULE
    vap->iv_flowmac = FLOWMAC_FLOWCONTROL_VAP | FLOWMAC_FLOWCONTROL_ETH;
#endif
    ieee80211_vap_cache_attach(vap); //added by duanmingzhe for 80211 cache

    /* Begin: Added by wangjia, for traffic limit. 2012-10-25. */
    ieee80211_tl_vap_init(vap);
    /* End: Added by wangjia, for traffic limit. 2012-10-25. */

    /*zhaoyang1 transplant from 717*/
    /*Begin:Added by duanmingzhe for user isolation*/
    vap->iv_switch = 0;
    /*End:Added by duanmingzhe for user isolation*/
    /*Begin:Add by duanmingzhe for develop the policy of mac binding*/
    vap->vap_dhcp_enable = 0;
    vap->vap_ip_auto_learning = 0;
    vap->vap_pppoe_enable = 0;
    /*End:Add by duanmingzhe for develop the policy of mac binding*/
    /*zhaoyang add for noisefloor switch when channel 0*/
    vap->noisefloor_enable = 1;
    /*zhaoyang add end*/
    /*zhaoyang modify for add rd_trap switch*/
#if ATH_SUPPORT_WAPI
    vap->rd_trap = 0;
#endif
    /*zhaoyang modify end*/
    /*suzhaoyu add for customer online-traffic limit*/
    vap->lowest_traffic_limit_switch = 0;
    vap->lowest_traffic_limit_threshold = 0;
    vap->lowest_traffic_limit_timelength =5;
    OS_INIT_TIMER(ic->ic_osdev, &(vap->online_traffic_timer), ieee80211_online_traffic_check, (void *) (vap));
    /*suzhaoyu addend*/
    /*zhaoyang1 transplant end*/
    /*<begin : transplant by caizhibang  from apv5*/
    /*yanggs add for thinap wds*/
    vap->vap_wds = 0;
    /*yanggs add end*/
    /*end : transplant by caizhibang from apv5 >*/
    /*zhaoyang modify for default disable UAPSD*/
    IEEE80211_VAP_UAPSD_DISABLE(vap);
    /*zhaoyang modify end*/
    return vap;
}