/** * @brief Changes ownership of the dev * * @param name pointer to character * @param user uid_t type data * @param group gid_t type data * @return 0--success otherwise failure */ int mbtchar_chown(char *name, uid_t user, gid_t group) { struct path path; struct inode *inode = NULL; struct iattr newattrs; int ret = 0; int retrycount = 0; ENTER(); do { os_sched_timeout(30); ret = kern_path(name, LOOKUP_FOLLOW, &path); if (++retrycount >= 10) { PRINTM(ERROR, "mbtchar_chown(): fail to get kern_path\n"); LEAVE(); return -EFAULT; } } while (ret); inode = path.dentry->d_inode; mutex_lock(&inode->i_mutex); ret = mnt_want_write(path.mnt); if (ret) goto out_unlock; newattrs.ia_valid = ATTR_CTIME; if (user != (uid_t) (-1)) { newattrs.ia_valid |= ATTR_UID; newattrs.ia_uid = user; } if (group != (gid_t) (-1)) { newattrs.ia_valid |= ATTR_GID; newattrs.ia_gid = group; } if (!S_ISDIR(inode->i_mode)) newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; if (inode->i_op->setattr) ret = inode->i_op->setattr(path.dentry, &newattrs); else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ret = simple_setattr(path.dentry, &newattrs); #else ret = inode_setattr(inode, &newattrs); #endif mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); LEAVE(); return ret; out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); return ret; }
/** * @brief Changes permissions of the dev * * @param name pointer to character * @param mode mode_t type data * @return 0--success otherwise failure */ int mbtchar_chmod(char *name, mode_t mode) { struct path path; struct inode *inode; struct iattr newattrs; int ret; int retrycount = 0; ENTER(); do { os_sched_timeout(30); ret = kern_path(name, LOOKUP_FOLLOW, &path); if (++retrycount >= 10) { PRINTM(ERROR, "mbtchar_chmod(): fail to get kern_path\n"); LEAVE(); return -EFAULT; } } while (ret); inode = path.dentry->d_inode; mutex_lock(&inode->i_mutex); ret = mnt_want_write(path.mnt); if (ret) goto out_unlock; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; if (inode->i_op->setattr) ret = inode->i_op->setattr(path.dentry, &newattrs); else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ret = simple_setattr(path.dentry, &newattrs); #else ret = inode_setattr(inode, &newattrs); #endif mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); LEAVE(); return ret; out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); return ret; }
/** * @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 request_firmware callback * * @param fw_firmware A pointer to firmware structure * @param context A Pointer to bt_private structure * @return BT_STATUS_SUCCESS or BT_STATUS_FAILURE */ static int sd_request_fw_dpc(const struct firmware *fw_firmware, void *context) { int ret = BT_STATUS_SUCCESS; bt_private *priv = (bt_private *) context; struct sdio_mmc_card *card = NULL; struct hci_dev *hdev = NULL; struct timeval tstamp; ENTER(); if ((priv == NULL) || (priv->adapter == NULL) || (priv->bt_dev.card == NULL) || (priv->bt_dev.hcidev == NULL)) { LEAVE(); return BT_STATUS_FAILURE; } card = (struct sdio_mmc_card *) priv->bt_dev.card; hdev = priv->bt_dev.hcidev; if (!fw_firmware) { do_gettimeofday(&tstamp); if (tstamp.tv_sec > (priv->req_fw_time.tv_sec + REQUEST_FW_TIMEOUT)) { PRINTM(ERROR, "BT: No firmware image found. Skipping download\n"); ret = BT_STATUS_FAILURE; goto done; } PRINTM(ERROR, "BT: No firmware image found! Retrying download\n"); /* Wait a second here before calling the callback again */ os_sched_timeout(1000); sd_download_firmware_w_helper(priv); LEAVE(); return ret; } priv->firmware = fw_firmware; if (BT_STATUS_FAILURE == sd_init_fw_dpc(priv)) { PRINTM(ERROR, "BT: sd_init_fw_dpc failed (download fw with nowait: %d). Terminating download\n", req_fw_nowait); ret = BT_STATUS_FAILURE; goto done; } /* check if the fimware is downloaded successfully or not */ if (sd_verify_fw_download(priv, MAX_FIRMWARE_POLL_TRIES)) { PRINTM(ERROR, "BT: FW failed to be active in time!\n"); ret = BT_STATUS_FAILURE; goto done; } sdio_release_host(card->func); sbi_enable_host_int(priv); if (BT_STATUS_FAILURE == sd_register_conf_dpc(priv)) { PRINTM(ERROR, "BT: sd_register_conf_dpc failed. Terminating download\n"); ret = BT_STATUS_FAILURE; goto done; } if (fw_firmware) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) if (!req_fw_nowait) #endif release_firmware(fw_firmware); } LEAVE(); return ret; done: if (fw_firmware) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) if (!req_fw_nowait) #endif release_firmware(fw_firmware); } hdev->dev = *priv->hotplug_device; /* For synchronous download cleanup will be done in add_card */ if (!req_fw_nowait) return ret; sdio_release_host(card->func); PRINTM(INFO, "unregister device\n"); sbi_unregister_dev(priv); ((struct sdio_mmc_card *) card)->priv = NULL; /* Stop the thread servicing the interrupts */ priv->adapter->SurpriseRemoved = TRUE; wake_up_interruptible(&priv->MainThread.waitQ); while (priv->MainThread.pid) { os_sched_timeout(1); } if (hdev) hci_free_dev(hdev); if (priv->adapter) bt_free_adapter(priv); kfree(priv); 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; }