⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	INIT_LIST_HEAD(&adapter->cmdfreeq);	INIT_LIST_HEAD(&adapter->cmdpendingq);	spin_lock_init(&adapter->driver_lock);	init_waitqueue_head(&adapter->cmd_pending);	adapter->nr_cmd_pending = 0;	/* Allocate the command buffers */	if (libertas_allocate_cmd_buffer(priv)) {		lbs_pr_err("Out of memory allocating command buffers\n");		ret = -1;	}out:	return ret;}static void libertas_free_adapter(wlan_private * priv){	wlan_adapter *adapter = priv->adapter;	if (!adapter) {		lbs_deb_fw("why double free adapter?\n");		return;	}	lbs_deb_fw("free command buffer\n");	libertas_free_cmd_buffer(priv);	lbs_deb_fw("free command_timer\n");	del_timer(&adapter->command_timer);	lbs_deb_fw("free scan results table\n");	kfree(adapter->networks);	adapter->networks = NULL;	/* Free the adapter object itself */	lbs_deb_fw("free adapter\n");	kfree(adapter);	priv->adapter = NULL;}/** * @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 *libertas_add_card(void *card, struct device *dmdev){	struct net_device *dev = NULL;	wlan_private *priv = NULL;	lbs_deb_enter(LBS_DEB_NET);	/* Allocate an Ethernet device and register it */	if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {		lbs_pr_err("init ethX device failed\n");		goto done;	}	priv = dev->priv;	/* allocate buffer for wlan_adapter */	if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) {		lbs_pr_err("allocate buffer for wlan_adapter failed\n");		goto err_kzalloc;	}	if (libertas_init_adapter(priv)) {		lbs_pr_err("failed to initialize adapter structure.\n");		goto err_init_adapter;	}	priv->dev = dev;	priv->card = card;	priv->mesh_open = 0;	priv->infra_open = 0;	priv->hotplug_device = dmdev;	/* Setup the OS Interface to our functions */	dev->open = libertas_open;	dev->hard_start_xmit = libertas_pre_start_xmit;	dev->stop = libertas_close;	dev->set_mac_address = libertas_set_mac_address;	dev->tx_timeout = libertas_tx_timeout;	dev->get_stats = libertas_get_stats;	dev->watchdog_timeo = 5 * HZ;	dev->ethtool_ops = &libertas_ethtool_ops;#ifdef	WIRELESS_EXT	dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;#endif	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;	dev->set_multicast_list = libertas_set_multicast_list;	SET_NETDEV_DEV(dev, dmdev);	priv->rtap_net_dev = NULL;	if (device_create_file(dmdev, &dev_attr_libertas_rtap))		goto err_init_adapter;	lbs_deb_thread("Starting main thread...\n");	init_waitqueue_head(&priv->waitq);	priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main");	if (IS_ERR(priv->main_thread)) {		lbs_deb_thread("Error creating main thread.\n");		goto err_kthread_run;	}	priv->work_thread = create_singlethread_workqueue("libertas_worker");	INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);	INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker);	INIT_WORK(&priv->sync_channel, libertas_sync_channel);	goto done;err_kthread_run:	device_remove_file(dmdev, &dev_attr_libertas_rtap);err_init_adapter:	libertas_free_adapter(priv);err_kzalloc:	free_netdev(dev);	priv = NULL;done:	lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv);	return priv;}EXPORT_SYMBOL_GPL(libertas_add_card);int libertas_remove_card(wlan_private *priv){	wlan_adapter *adapter = priv->adapter;	struct net_device *dev = priv->dev;	union iwreq_data wrqu;	lbs_deb_enter(LBS_DEB_MAIN);	libertas_remove_rtap(priv);	dev = priv->dev;	device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap);	cancel_delayed_work(&priv->scan_work);	cancel_delayed_work(&priv->assoc_work);	destroy_workqueue(priv->work_thread);	if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) {		adapter->psmode = WLAN802_11POWERMODECAM;		libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);	}	memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);	wrqu.ap_addr.sa_family = ARPHRD_ETHER;	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);	/* Stop the thread servicing the interrupts */	adapter->surpriseremoved = 1;	kthread_stop(priv->main_thread);	libertas_free_adapter(priv);	priv->dev = NULL;	free_netdev(dev);	lbs_deb_leave(LBS_DEB_MAIN);	return 0;}EXPORT_SYMBOL_GPL(libertas_remove_card);int libertas_start_card(wlan_private *priv){	struct net_device *dev = priv->dev;	int ret = -1;	lbs_deb_enter(LBS_DEB_MAIN);	/* poke the firmware */	ret = wlan_setup_firmware(priv);	if (ret)		goto done;	/* init 802.11d */	libertas_init_11d(priv);	if (register_netdev(dev)) {		lbs_pr_err("cannot register ethX device\n");		goto done;	}	libertas_debugfs_init_one(priv, dev);	lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);	ret = 0;done:	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);	return ret;}EXPORT_SYMBOL_GPL(libertas_start_card);int libertas_stop_card(wlan_private *priv){	struct net_device *dev = priv->dev;	int ret = -1;	struct cmd_ctrl_node *cmdnode;	unsigned long flags;	lbs_deb_enter(LBS_DEB_MAIN);	netif_stop_queue(priv->dev);	netif_carrier_off(priv->dev);	libertas_debugfs_remove_one(priv);	/* Flush pending command nodes */	spin_lock_irqsave(&priv->adapter->driver_lock, flags);	list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {		cmdnode->cmdwaitqwoken = 1;		wake_up_interruptible(&cmdnode->cmdwait_q);	}	spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);	unregister_netdev(dev);	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);	return ret;}EXPORT_SYMBOL_GPL(libertas_stop_card);/** * @brief This function adds mshX interface * *  @param priv    A pointer to the wlan_private structure *  @return 	   0 if successful, -X otherwise */int libertas_add_mesh(wlan_private *priv, struct device *dev){	struct net_device *mesh_dev = NULL;	int ret = 0;	lbs_deb_enter(LBS_DEB_MESH);	/* Allocate a virtual mesh device */	if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {		lbs_deb_mesh("init mshX device failed\n");		ret = -ENOMEM;		goto done;	}	mesh_dev->priv = priv;	priv->mesh_dev = mesh_dev;	mesh_dev->open = libertas_mesh_open;	mesh_dev->hard_start_xmit = libertas_mesh_pre_start_xmit;	mesh_dev->stop = libertas_mesh_close;	mesh_dev->get_stats = libertas_get_stats;	mesh_dev->set_mac_address = libertas_set_mac_address;	mesh_dev->ethtool_ops = &libertas_ethtool_ops;	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,			sizeof(priv->dev->dev_addr));	SET_NETDEV_DEV(priv->mesh_dev, dev);#ifdef	WIRELESS_EXT	mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;#endif	/* Register virtual mesh interface */	ret = register_netdev(mesh_dev);	if (ret) {		lbs_pr_err("cannot register mshX virtual interface\n");		goto err_free;	}	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &libertas_mesh_attr_group);	if (ret)		goto err_unregister;	/* Everything successful */	ret = 0;	goto done;err_unregister:	unregister_netdev(mesh_dev);err_free:	free_netdev(mesh_dev);done:	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);	return ret;}EXPORT_SYMBOL_GPL(libertas_add_mesh);void libertas_remove_mesh(wlan_private *priv){	struct net_device *mesh_dev;	lbs_deb_enter(LBS_DEB_MAIN);	if (!priv)		goto out;	mesh_dev = priv->mesh_dev;	netif_stop_queue(mesh_dev);	netif_carrier_off(priv->mesh_dev);	sysfs_remove_group(&(mesh_dev->dev.kobj), &libertas_mesh_attr_group);	unregister_netdev(mesh_dev);	priv->mesh_dev = NULL ;	free_netdev(mesh_dev);out:	lbs_deb_leave(LBS_DEB_MAIN);}EXPORT_SYMBOL_GPL(libertas_remove_mesh);/** *  @brief This function finds the CFP in *  region_cfp_table based on region and band parameter. * *  @param region  The region code *  @param band	   The band *  @param cfp_no  A pointer to CFP number *  @return 	   A pointer to CFP */struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *cfp_no){	int i, end;	lbs_deb_enter(LBS_DEB_MAIN);	end = ARRAY_SIZE(region_cfp_table);	for (i = 0; i < end ; i++) {		lbs_deb_main("region_cfp_table[i].region=%d\n",			region_cfp_table[i].region);		if (region_cfp_table[i].region == region) {			*cfp_no = region_cfp_table[i].cfp_no_BG;			lbs_deb_leave(LBS_DEB_MAIN);			return region_cfp_table[i].cfp_BG;		}	}	lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");	return NULL;}int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band){	wlan_adapter *adapter = priv->adapter;	int ret = 0;	int i = 0;	struct chan_freq_power *cfp;	int cfp_no;	lbs_deb_enter(LBS_DEB_MAIN);	memset(adapter->region_channel, 0, sizeof(adapter->region_channel));	{		cfp = libertas_get_region_cfp_table(region, band, &cfp_no);		if (cfp != NULL) {			adapter->region_channel[i].nrcfp = cfp_no;			adapter->region_channel[i].CFP = cfp;		} else {			lbs_deb_main("wrong region code %#x in band B/G\n",			       region);			ret = -1;			goto out;		}		adapter->region_channel[i].valid = 1;		adapter->region_channel[i].region = region;		adapter->region_channel[i].band = band;		i++;	}out:	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);	return ret;}/** *  @brief This function handles the interrupt. it will change PS *  state if applicable. it will wake up main_thread to handle *  the interrupt event as well. * *  @param dev     A pointer to net_device structure *  @return 	   n/a */void libertas_interrupt(struct net_device *dev){	wlan_private *priv = dev->priv;	lbs_deb_enter(LBS_DEB_THREAD);	lbs_deb_thread("libertas_interrupt: intcounter=%d\n",	       priv->adapter->intcounter);	priv->adapter->intcounter++;	if (priv->adapter->psstate == PS_STATE_SLEEP) {		priv->adapter->psstate = PS_STATE_AWAKE;		netif_wake_queue(dev);		if (priv->mesh_dev)			netif_wake_queue(priv->mesh_dev);	}	wake_up_interruptible(&priv->waitq);	lbs_deb_leave(LBS_DEB_THREAD);}EXPORT_SYMBOL_GPL(libertas_interrupt);int libertas_reset_device(wlan_private *priv){	int ret;	lbs_deb_enter(LBS_DEB_MAIN);	ret = libertas_prepare_and_send_command(priv, CMD_802_11_RESET,				    CMD_ACT_HALT, 0, 0, NULL);	msleep_interruptible(10);	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);	return ret;}EXPORT_SYMBOL_GPL(libertas_reset_device);static int libertas_init_module(void){	lbs_deb_enter(LBS_DEB_MAIN);	libertas_debugfs_init();	lbs_deb_leave(LBS_DEB_MAIN);	return 0;}static void libertas_exit_module(void){	lbs_deb_enter(LBS_DEB_MAIN);	libertas_debugfs_remove();	lbs_deb_leave(LBS_DEB_MAIN);}/* * rtap interface support fuctions */static int libertas_rtap_open(struct net_device *dev){        netif_carrier_off(dev);        netif_stop_queue(dev);        return 0;}static int libertas_rtap_stop(struct net_device *dev){        return 0;}static int libertas_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev){        netif_stop_queue(dev);        return -EOPNOTSUPP;}static struct net_device_stats *libertas_rtap_get_stats(struct net_device *dev){	wlan_private *priv = dev->priv;	return &priv->ieee->stats;}void libertas_remove_rtap(wlan_private *priv){	if (priv->rtap_net_dev == NULL)		return;	unregister_netdev(priv->rtap_net_dev);	free_ieee80211(priv->rtap_net_dev);	priv->rtap_net_dev = NULL;}int libertas_add_rtap(wlan_private *priv){	int rc = 0;	if (priv->rtap_net_dev)		return -EPERM;	priv->rtap_net_dev = alloc_ieee80211(0);	if (priv->rtap_net_dev == NULL)		return -ENOMEM;	priv->ieee = netdev_priv(priv->rtap_net_dev);	strcpy(priv->rtap_net_dev->name, "rtap%d");	priv->rtap_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;	priv->rtap_net_dev->open = libertas_rtap_open;	priv->rtap_net_dev->stop = libertas_rtap_stop;	priv->rtap_net_dev->get_stats = libertas_rtap_get_stats;	priv->rtap_net_dev->hard_start_xmit = libertas_rtap_hard_start_xmit;	priv->rtap_net_dev->set_multicast_list = libertas_set_multicast_list;	priv->rtap_net_dev->priv = priv;	priv->ieee->iw_mode = IW_MODE_MONITOR;	rc = register_netdev(priv->rtap_net_dev);	if (rc) {		free_ieee80211(priv->rtap_net_dev);		priv->rtap_net_dev = NULL;		return rc;	}	return 0;}module_init(libertas_init_module);module_exit(libertas_exit_module);MODULE_DESCRIPTION("Libertas WLAN Driver Library");MODULE_AUTHOR("Marvell International Ltd.");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -