/** * @brief This function opens the network device * * @param dev A pointer to net_device structure * @return WLAN_STATUS_SUCCESS */ static int wlan_open(struct net_device *dev) { wlan_private *priv = (wlan_private *) netdev_priv(dev); wlan_adapter *adapter = priv->adapter; ENTER(); /* On some systems the device open handler will be called before HW ready. Use the following flag check and wait function to work around the issue. */ { int i = 0; while ((adapter->HardwareStatus != WlanHardwareStatusReady) && (i < MAX_WAIT_DEVICE_READY_COUNT)) { i++; os_sched_timeout(100); } if (i >= MAX_WAIT_DEVICE_READY_COUNT) { PRINTM(FATAL, "HW not ready, wlan_open() return failure\n"); LEAVE(); return WLAN_STATUS_FAILURE; } } if (MODULE_GET == 0) { LEAVE(); return WLAN_STATUS_FAILURE; } priv->open = TRUE; if ((adapter->MediaConnectStatus == WlanMediaStateConnected) && (adapter->InfrastructureMode != Wlan802_11IBSS || adapter->AdhocLinkSensed == TRUE)) os_carrier_on(priv); else os_carrier_off(priv); os_start_queue(priv); wmm_start_queue(priv); LEAVE(); return WLAN_STATUS_SUCCESS; }
/** * @brief This function opens the network device * * @param dev A pointer to net_device structure * @return WLAN_STATUS_SUCCESS */ int wlan_open(struct eth_drv_sc *sc) { wlan_private *priv = (wlan_private *) sc->driver_private; wlan_adapter *adapter = priv->adapter; ENTER(); // MODULE_GET; priv->open = TRUE; #if 0 if (adapter->MediaConnectStatus == WlanMediaStateConnected) os_carrier_on(priv); else os_carrier_off(priv); os_start_queue(priv); #endif LEAVE(); return WLAN_STATUS_SUCCESS; }
/** * @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; }