/**
 *  @brief This function unregisters MOAL from MLAN module.
 *
 *  @param pmlan_adapter   A pointer to a mlan_device structure
 *                         allocated in MOAL
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The deregistration succeeded.
 */
mlan_status
mlan_unregister(IN t_void * pmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    pmlan_callbacks pcb;
    t_s32 i = 0;

    MASSERT(pmlan_adapter);

    ENTER();

    pcb = &pmadapter->callbacks;

    /* Free adapter structure */
    wlan_free_adapter(pmadapter);

    /* Free timers */
    wlan_free_timer(pmadapter);

    /* Free lock variables */
    wlan_free_lock_list(pmadapter);

    /* Free private structures */
    for (i = 0; i < pmadapter->priv_num; i++) {
        if (pmadapter->priv[i]) {
            if (pcb->moal_vmalloc && pcb->moal_vfree)
                pcb->moal_vfree(pmadapter->pmoal_handle,
                                (t_u8 *) pmadapter->priv[i]);
            else
                pcb->moal_mfree(pmadapter->pmoal_handle,
                                (t_u8 *) pmadapter->priv[i]);
        }
    }

    /* Free mlan_adapter */
    if (pcb->moal_vmalloc && pcb->moal_vfree)
        pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter);
    else
        pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter);

    LEAVE();
    return ret;
}
/**
 * @brief This function adds the card. it will probe the
 * card, allocate the wlan_priv and initialize the device. 
 *  
 *  @param card    A pointer to card
 *  @return        A pointer to wlan_private structure
 */
wlan_private *
wlan_add_card(void *card)
{
    struct net_device *dev = NULL;
    wlan_private *priv = NULL;

    ENTER();

    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
        goto exit_sem_err;

    /* Allocate an Ethernet device and register it */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
    if (!(dev = init_etherdev(dev, sizeof(wlan_private)))) {
#else
    if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
#endif
        PRINTM(MSG, "Init ethernet device failed!\n");
        goto exit_add_err;
    }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
    /* Allocate device name */
    if (dev_alloc_name(dev, "mlan%d") < 0) {
        PRINTM(ERROR, "Could not allocate device name!\n");
        goto err_kmalloc;
    }
#endif

    priv = (wlan_private *) netdev_priv(dev);

    /* allocate buffer for wlan_adapter */
    if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
        PRINTM(MSG, "Allocate buffer for wlan_adapter failed!\n");
        goto err_kmalloc;
    }

    /* init wlan_adapter */
    memset(priv->adapter, 0, sizeof(wlan_adapter));

    priv->wlan_dev.netdev = dev;
    priv->wlan_dev.card = card;
    ((struct sdio_mmc_card *) card)->priv = priv;
    wlanpriv = priv; //XXX FB global var a virer ?

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    SET_MODULE_OWNER(dev);
#endif

    /* Setup the OS Interface to our functions */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
    dev->open = wlan_open;
    dev->hard_start_xmit = wlan_hard_start_xmit;
    dev->stop = wlan_close;
    dev->do_ioctl = wlan_do_ioctl;
    dev->set_mac_address = wlan_set_mac_address;
    dev->set_multicast_list = wlan_set_multicast_list;
    dev->tx_timeout = wlan_tx_timeout;
    dev->get_stats = wlan_get_stats;
#else
    dev->netdev_ops = &wlan_netdev_ops;
#endif
    dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
    dev->hard_header_len += sizeof(TxPD);
    dev->hard_header_len += SDIO_HEADER_LEN;
    dev->hard_header_len += HEADER_ALIGNMENT;

#ifdef  WIRELESS_EXT
#if WIRELESS_EXT < 21
    dev->get_wireless_stats = wlan_get_wireless_stats;
#endif
    dev->wireless_handlers = (struct iw_handler_def *) &wlan_handler_def;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
    dev->features |= NETIF_F_DYNALLOC;
#endif
    dev->flags |= IFF_BROADCAST | IFF_MULTICAST;

    /* init SW */
    if (wlan_init_sw(priv)) {
        PRINTM(FATAL, "Software Init Failed\n");
        goto err_kmalloc;
    }

    PRINTM(INFO, "Starting kthread...\n");
    priv->MainThread.priv = priv;
    wlan_create_thread(wlan_service_main_thread,
                       &priv->MainThread, "wlan_main_service");

    ConfigureThreadPriority();

#ifdef REASSOCIATION
    priv->ReassocThread.priv = priv;
    wlan_create_thread(wlan_reassociation_thread,
                       &priv->ReassocThread, "wlan_reassoc_service");
#endif /* REASSOCIATION */

    while ((priv->MainThread.pid == 0)
#ifdef REASSOCIATION
           || (priv->ReassocThread.pid == 0)
#endif
        ) {
        os_sched_timeout(2);
    }

    /* 
     * Register the device. Fill up the private data structure with
     * relevant information from the card and request for the required
     * IRQ. 
     */

    if (sbi_register_dev(priv) < 0) {
        PRINTM(FATAL, "Failed to register wlan device!\n");
        goto err_registerdev;
    }

    SET_NETDEV_DEV(dev, priv->hotplug_device);

    /* init FW and HW */
    if (wlan_init_fw(priv)) {
        PRINTM(FATAL, "Firmware Init Failed\n");
        goto err_init_fw;
    }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    SET_NETDEV_DEVTYPE(dev, &wlan_type);
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    if (register_netdev(dev)) {
        printk(KERN_ERR "Cannot register network device!\n");
        goto err_init_fw;
    }
#endif
    os_carrier_off(priv);
    os_stop_queue(priv);

    PRINTM(INFO, "%s: WLAN 802.11 Adapter revision 0x%02X\n",
           dev->name, priv->adapter->chip_rev);

#ifdef CONFIG_PROC_FS
    wlan_proc_entry(priv, dev);
#ifdef PROC_DEBUG
    wlan_debug_entry(priv, dev);
#endif
#endif /* CONFIG_PROC_FS */

    OS_REL_SEMAPHORE(&AddRemoveCardSem);
    LEAVE();
    return priv;

  err_init_fw:
    sbi_unregister_dev(priv);

  err_registerdev:
    priv->adapter->SurpriseRemoved = TRUE;
    if (priv->MainThread.pid) {
        /* Stop the thread servicing the interrupts */
        wake_up_interruptible(&priv->MainThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->MainThread);
#endif
    }
#ifdef REASSOCIATION
    if (priv->ReassocThread.pid) {
        wake_up_interruptible(&priv->ReassocThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->ReassocThread);
#endif
    }
#endif /* REASSOCIATION */

    /* waiting for main thread quit */
    while (priv->MainThread.pid
#ifdef REASSOCIATION
           || priv->ReassocThread.pid
#endif
        ) {
        os_sched_timeout(2);
    }
  err_kmalloc:
    if (dev->reg_state == NETREG_REGISTERED)
        unregister_netdev(dev);
    wlan_free_adapter(priv);
    priv->wlan_dev.netdev = NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    free_netdev(dev);
#endif
    ((struct sdio_mmc_card *) card)->priv = NULL;
    wlanpriv = NULL;

  exit_add_err:
    OS_REL_SEMAPHORE(&AddRemoveCardSem);
  exit_sem_err:
    LEAVE();
    return NULL;
}

/** 
 *  @brief This function removes the card.
 *  
 *  @param card    A pointer to card
 *  @return        WLAN_STATUS_SUCCESS
 */
int
wlan_remove_card(void *card)
{
    wlan_private *priv = ((struct sdio_mmc_card *) card)->priv;
    wlan_adapter *Adapter = NULL;
    struct net_device *dev;
    union iwreq_data wrqu;

    ENTER();

    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
        goto exit_sem_err;

    if (!priv || !(Adapter = priv->adapter))
        goto exit_remove;

    Adapter->SurpriseRemoved = TRUE;

#ifdef REASSOCIATION
    if (Adapter->ReassocTimerIsSet == TRUE) {
        wlan_cancel_timer(&Adapter->MrvDrvTimer);
        Adapter->ReassocTimerIsSet = FALSE;
    }
#endif

    if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
        Adapter->MediaConnectStatus = WlanMediaStateDisconnected;
        memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
        wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
        wlan_clean_txrx(priv);
    }

    /* Release all pending commands */
    wlan_clear_pending_cmd(priv);

    dev = priv->wlan_dev.netdev;
    /* Last reference is our one */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
    PRINTM(INFO, "refcnt = %d\n", atomic_read(&dev->refcnt));
#else
    PRINTM(INFO, "refcnt = %d\n", netdev_refcnt_read(dev));
#endif

    PRINTM(INFO, "netdev_finish_unregister: %s\n", dev->name);
    if (dev->reg_state == NETREG_REGISTERED)
        unregister_netdev(dev);
    PRINTM(INFO, "Unregister finish\n");

    if (priv->MainThread.pid) {
        /* Stop the thread servicing the interrupts */
        wake_up_interruptible(&priv->MainThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->MainThread);
#endif
    }
#ifdef REASSOCIATION
    if (priv->ReassocThread.pid) {
        wake_up_interruptible(&priv->ReassocThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->ReassocThread);
#endif
    }
#endif /* REASSOCIATION */

    /* waiting for thread quit */
    while (priv->MainThread.pid
#ifdef REASSOCIATION
           || priv->ReassocThread.pid
#endif
        ) {
        os_sched_timeout(1);
    }

    wake_up_interruptible(&Adapter->HS_wait_q);

    if (Adapter->IsDeepSleep == TRUE) {
        Adapter->IsDeepSleep = FALSE;
        wake_up_interruptible(&Adapter->ds_awake_q);
    }

#ifdef CONFIG_PROC_FS
#ifdef PROC_DEBUG
    wlan_debug_remove(priv);
#endif
    wlan_proc_remove(priv);
#endif

    PRINTM(INFO, "unregister device\n");
    sbi_unregister_dev(priv);

    PRINTM(INFO, "Free Adapter\n");
    wlan_free_adapter(priv);
    priv->wlan_dev.netdev = NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    free_netdev(dev);
#endif
    wlanpriv = NULL;

  exit_remove:
    OS_REL_SEMAPHORE(&AddRemoveCardSem);

  exit_sem_err:
    LEAVE();
    return WLAN_STATUS_SUCCESS;
}
Beispiel #3
0
/**
 *  @brief Shutdown firmware
 *
 *  @param pmlan_adapter	A pointer to mlan_adapter structure
 *
 *  @return			MLAN_STATUS_SUCCESS
 *                      		The firmware shutdown call succeeded.
 *				MLAN_STATUS_PENDING
 *      	                	The firmware shutdown call is pending.
 *				MLAN_STATUS_FAILURE
 *      	                	The firmware shutdown call failed.
 */
mlan_status
mlan_shutdown_fw(IN t_void * pmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_PENDING;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    mlan_private *priv = MNULL;
    pmlan_callbacks pcb;
    t_s32 i = 0;

    ENTER();
    MASSERT(pmlan_adapter);
    /* mlan already shutdown */
    if (pmadapter->hw_status == WlanHardwareStatusNotReady)
        return MLAN_STATUS_SUCCESS;

    pmadapter->hw_status = WlanHardwareStatusClosing;
    /* wait for mlan_process to complete */
    if (pmadapter->mlan_processing) {
        PRINTM(MWARN, "mlan main processing is still running\n");
        return ret;
    }

    /* shut down mlan */
    PRINTM(MINFO, "Shutdown mlan...\n");

    pcb = &pmadapter->callbacks;
    /* Clean up Tx/Rx queues and delete BSS priority table */
    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        if (pmadapter->priv[i]) {
            priv = pmadapter->priv[i];

            wlan_clean_txrx(priv);
            wlan_wmm_cleanup_node(priv);
            pcb->moal_free_lock(pmadapter->pmoal_handle, priv->rx_pkt_lock);
            wlan_delete_bsspriotbl(priv);
            pcb->moal_free_lock(pmadapter->pmoal_handle,
                                priv->wmm.ra_list_spinlock);
#ifdef UAP_SUPPORT
            if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
                wlan_delete_station_list(priv);
                util_free_list_head((t_void *) pmadapter->pmoal_handle,
                                    &priv->sta_list,
                                    priv->adapter->callbacks.moal_free_lock);
            }
#endif /* UAP_SUPPORT */
        }
    }

    for (i = 0; i < MLAN_MAX_BSS_NUM; i++)
        util_free_list_head((t_void *) pmadapter->pmoal_handle,
                            &pmadapter->bssprio_tbl[i].bssprio_head,
                            pcb->moal_free_lock);

    if (pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmlan_lock)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto exit_shutdown_fw;
    }

    /* Free adapter structure */
    wlan_free_adapter(pmadapter);

    if (pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmlan_lock)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto exit_shutdown_fw;
    }

    /* Notify completion */
    ret = wlan_shutdown_fw_complete(pmadapter);

  exit_shutdown_fw:
    LEAVE();
    return ret;
}
/**
 *  @brief This function registers MOAL to MLAN module.
 *
 *  @param pmdevice        A pointer to a mlan_device structure
 *                         allocated in MOAL
 *  @param ppmlan_adapter  A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer as the context
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The registration succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The registration failed.
 *
 * mlan_status mlan_register (
 *   IN pmlan_device     pmdevice,
 *   OUT t_void          **ppmlan_adapter
 * );
 *
 * Comments
 *   MOAL constructs mlan_device data structure to pass moal_handle and
 *   mlan_callback table to MLAN. MLAN returns mlan_adapter pointer to
 *   the ppmlan_adapter buffer provided by MOAL.
 * Headers:
 *   declared in mlan_decl.h
 * See Also
 *   mlan_unregister
 */
mlan_status
mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    pmlan_adapter pmadapter = MNULL;
    pmlan_callbacks pcb = MNULL;
    t_u8 i = 0;
    t_u32 j = 0;

    MASSERT(pmdevice);
    MASSERT(ppmlan_adapter);
    MASSERT(pmdevice->callbacks.moal_print);
#ifdef DEBUG_LEVEL1
    print_callback = pmdevice->callbacks.moal_print;
    get_sys_time_callback = pmdevice->callbacks.moal_get_system_time;
#endif
    assert_callback = pmdevice->callbacks.moal_assert;

    ENTER();

    MASSERT(pmdevice->callbacks.moal_malloc);
    MASSERT(pmdevice->callbacks.moal_memset);
    MASSERT(pmdevice->callbacks.moal_memmove);

    /* Allocate memory for adapter structure */
    if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree)
        ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle,
                                               sizeof(mlan_adapter),
                                               (t_u8 **) & pmadapter);
    else
        ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle,
                                              sizeof(mlan_adapter),
                                              MLAN_MEM_DEF,
                                              (t_u8 **) & pmadapter);
    if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) {
        ret = MLAN_STATUS_FAILURE;
        goto exit_register;
    }

    pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter,
                                    0, sizeof(mlan_adapter));

    pcb = &pmadapter->callbacks;

    /* Save callback functions */
    pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
                                     &pmdevice->callbacks,
                                     sizeof(mlan_callbacks));

    /* Assertion for all callback functions */
    MASSERT(pcb->moal_init_fw_complete);
    MASSERT(pcb->moal_shutdown_fw_complete);
    MASSERT(pcb->moal_send_packet_complete);
    MASSERT(pcb->moal_recv_packet);
    MASSERT(pcb->moal_recv_event);
    MASSERT(pcb->moal_ioctl_complete);

    MASSERT(pcb->moal_write_reg);
    MASSERT(pcb->moal_read_reg);
    MASSERT(pcb->moal_alloc_mlan_buffer);
    MASSERT(pcb->moal_free_mlan_buffer);
    MASSERT(pcb->moal_write_data_sync);
    MASSERT(pcb->moal_read_data_sync);
    MASSERT(pcb->moal_mfree);
    MASSERT(pcb->moal_memcpy);
    MASSERT(pcb->moal_memcmp);
    MASSERT(pcb->moal_get_system_time);
    MASSERT(pcb->moal_init_timer);
    MASSERT(pcb->moal_free_timer);
    MASSERT(pcb->moal_start_timer);
    MASSERT(pcb->moal_stop_timer);
    MASSERT(pcb->moal_init_lock);
    MASSERT(pcb->moal_free_lock);
    MASSERT(pcb->moal_spin_lock);
    MASSERT(pcb->moal_spin_unlock);
    MASSERT(pcb->moal_tcp_ack_tx_ind);

    /* Save pmoal_handle */
    pmadapter->pmoal_handle = pmdevice->pmoal_handle;

    if ((pmdevice->int_mode == INT_MODE_GPIO) && (pmdevice->gpio_pin == 0)) {
        PRINTM(MERROR, "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n");
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    pmadapter->init_para.int_mode = pmdevice->int_mode;
    pmadapter->init_para.gpio_pin = pmdevice->gpio_pin;
    /* card specific probing has been deferred until now .. */
    ret = wlan_sdio_probe(pmadapter);
    if (MLAN_STATUS_SUCCESS != ret) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
#ifdef DEBUG_LEVEL1
    mlan_drvdbg = pmdevice->drvdbg;
#endif

#ifdef MFG_CMD_SUPPORT
    pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
#endif

#ifdef SDIO_MULTI_PORT_TX_AGGR
    pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
#endif
#ifdef SDIO_MULTI_PORT_RX_AGGR
    pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
#endif
    pmadapter->init_para.auto_ds = pmdevice->auto_ds;
    pmadapter->init_para.ps_mode = pmdevice->ps_mode;
    if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
            pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
            pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
        pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
#ifdef STA_SUPPORT
    pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
#else
    pmadapter->init_para.cfg_11d = 0;
#endif
    pmadapter->init_para.dfs_master_radar_det_en =
        DFS_MASTER_RADAR_DETECT_EN;
    pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN;
    pmadapter->init_para.fw_crc_check = pmdevice->fw_crc_check;
    pmadapter->rx_work_flag = pmdevice->rx_work;

    pmadapter->priv_num = 0;
    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        pmadapter->priv[i] = MNULL;
        if (pmdevice->bss_attr[i].active == MTRUE) {
            /* For valid bss_attr, allocate memory for private
               structure */
            if (pcb->moal_vmalloc && pcb->moal_vfree)
                ret = pcb->moal_vmalloc(pmadapter->pmoal_handle,
                                        sizeof(mlan_private),
                                        (t_u8 **) & pmadapter->
                                        priv[i]);
            else
                ret = pcb->moal_malloc(pmadapter->pmoal_handle,
                                       sizeof(mlan_private),
                                       MLAN_MEM_DEF,
                                       (t_u8 **) & pmadapter->
                                       priv[i]);
            if (ret != MLAN_STATUS_SUCCESS || !pmadapter->priv[i]) {
                ret = MLAN_STATUS_FAILURE;
                goto error;
            }

            pmadapter->priv_num++;
            memset(pmadapter, pmadapter->priv[i], 0,
                   sizeof(mlan_private));

            pmadapter->priv[i]->adapter = pmadapter;

            /* Save bss_type, frame_type & bss_priority */
            pmadapter->priv[i]->bss_type =
                (t_u8) pmdevice->bss_attr[i].bss_type;
            pmadapter->priv[i]->frame_type =
                (t_u8) pmdevice->bss_attr[i].frame_type;
            pmadapter->priv[i]->bss_priority =
                (t_u8) pmdevice->bss_attr[i].bss_priority;
            if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_STA)
                pmadapter->priv[i]->bss_role =
                    MLAN_BSS_ROLE_STA;
            else if (pmdevice->bss_attr[i].bss_type ==
                     MLAN_BSS_TYPE_UAP)
                pmadapter->priv[i]->bss_role =
                    MLAN_BSS_ROLE_UAP;
#ifdef WIFI_DIRECT_SUPPORT
            else if (pmdevice->bss_attr[i].bss_type ==
                     MLAN_BSS_TYPE_WIFIDIRECT) {
                pmadapter->priv[i]->bss_role =
                    MLAN_BSS_ROLE_STA;
                if (pmdevice->bss_attr[i].bss_virtual)
                    pmadapter->priv[i]->bss_virtual = MTRUE;
            }
#endif
            /* Save bss_index and bss_num */
            pmadapter->priv[i]->bss_index = i;
            pmadapter->priv[i]->bss_num =
                (t_u8) pmdevice->bss_attr[i].bss_num;

            /* init function table */
            for (j = 0; mlan_ops[j]; j++) {
                if (mlan_ops[j]->bss_role ==
                        GET_BSS_ROLE(pmadapter->priv[i])) {
                    memcpy(pmadapter,
                           &pmadapter->priv[i]->ops,
                           mlan_ops[j],
                           sizeof(mlan_operations));
                }
            }
        }
    }

    /* Initialize lock variables */
    if (wlan_init_lock_list(pmadapter) != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }

    /* Allocate memory for member of adapter structure */
    if (wlan_allocate_adapter(pmadapter)) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }

    /* Initialize timers */
    if (wlan_init_timer(pmadapter) != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    /* Return pointer of mlan_adapter to MOAL */
    *ppmlan_adapter = pmadapter;

    goto exit_register;

error:
    PRINTM(MINFO, "Leave mlan_register with error\n");
    /* Free timers */
    wlan_free_timer(pmadapter);
    /* Free adapter structure */
    wlan_free_adapter(pmadapter);
    /* Free lock variables */
    wlan_free_lock_list(pmadapter);
    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        if (pmadapter->priv[i]) {
            if (pcb->moal_vmalloc && pcb->moal_vfree)
                pcb->moal_vfree(pmadapter->pmoal_handle,
                                (t_u8 *) pmadapter->priv[i]);
            else
                pcb->moal_mfree(pmadapter->pmoal_handle,
                                (t_u8 *) pmadapter->priv[i]);
        }
    }
    if (pcb->moal_vmalloc && pcb->moal_vfree)
        pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter);
    else
        pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter);

exit_register:
    LEAVE();
    return ret;
}
Beispiel #5
0
/** 
 *  @brief This function removes the card.
 *  
 *  @param priv    A pointer to card
 *  @return 	   WLAN_STATUS_SUCCESS
 */
static int
wlan_remove_card(void *card)
{
    wlan_private *priv = &w99702_priv_data0;
    wlan_adapter *Adapter;
    //struct net_device *dev;
    struct cyg_netdevtab_entry *dev;
	struct eth_drv_sc *sc;
    union iwreq_data wrqu;

    ENTER();

    if (!priv) {
        LEAVE();
        return WLAN_STATUS_SUCCESS;
    }

    Adapter = priv->adapter;

    if (!Adapter) {
        LEAVE();
        return WLAN_STATUS_SUCCESS;
    }

    dev = priv->wlan_dev.netdev;
	sc = (struct eth_drv_sc *)dev->device_instance;
	
   // wake_up_interruptible(&Adapter->ds_awake_q);
   cyg_cond_broadcast(&Adapter->ds_cond_q);

    if (Adapter->CurCmd) {
        diag_printf("Wake up current cmdwait_q\n");
//        wake_up_interruptible(&Adapter->CurCmd->cmdwait_q);
		cyg_flag_setbits( &Adapter->CurCmd->cmdwait_flag_q, 3 );
    }

    Adapter->CurCmd = NULL;

    if (Adapter->PSMode == Wlan802_11PowerModeMAX_PSP) {
        Adapter->PSMode = Wlan802_11PowerModeCAM;
        PSWakeup(priv, HostCmd_OPTION_WAITFORRSP);
    }
    if (Adapter->IsDeepSleep == TRUE) {
        Adapter->IsDeepSleep = FALSE;
        sbi_exit_deep_sleep(priv);
    }

    memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
    wrqu.ap_addr.sa_family = ARPHRD_ETHER;
    wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);

    /* Disable interrupts on the card as we cannot handle them after RESET */
    sbi_disable_host_int(priv);

    PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RESET, 0, 0, 0, NULL);

    cyg_thread_delay(20);
    //udelay(200*1000);

#ifdef ENABLE_PM
    pm_unregister(wlan_pm_dev);
#endif

    /* Flush all the packets upto the OS before stopping */
   // wlan_send_rxskbQ(priv);
   eth_drv_dsr(0, 0, (cyg_addrword_t)sc);
    cleanup_txqueues(priv);
   // os_stop_queue(priv);
   // os_carrier_off(priv);

    Adapter->SurpriseRemoved = TRUE;

    /* Stop the thread servicing the interrupts */
    //wake_up_interruptible(&priv->MainThread.waitQ);
    cyg_flag_setbits( &priv->MainThread.waitQ_flag_q, 1 );

#ifdef REASSOCIATION
    //wake_up_interruptible(&priv->ReassocThread.waitQ);
    cyg_flag_setbits( &priv->ReassocThread.waitQ_flag_q, 1 );
#endif /* REASSOCIATION */

#ifdef PROC_DEBUG
    wlan_debug_remove(priv);
#endif
   // wlan_proc_remove(priv);

    diag_printf("unregester dev\n");
    sbi_unregister_dev(priv);

    diag_printf("Free Adapter\n");
    wlan_free_adapter(priv);

    /* Last reference is our one */
//    diag_printf("refcnt = %d\n", atomic_read(&dev->refcnt));

 //   diag_printf("netdev_finish_unregister: %s%s.\n", dev->name,
 //          (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style");

 //   unregister_netdev(dev);

    diag_printf("Unregister finish\n");

    priv->wlan_dev.netdev = NULL;
    //free_netdev(dev);
    //wlanpriv = NULL;

    LEAVE();
    return WLAN_STATUS_SUCCESS;
}