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

📄 rt2x00dev.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	entry->flags = flags;	entry->val2 = entry->val;	if (entry->flags & IEEE80211_RATE_PREAMBLE2)		entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);	entry->min_rssi_ack = 0;	entry->min_rssi_ack_delta = 0;}static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,				    struct hw_mode_spec *spec){	struct ieee80211_hw *hw = rt2x00dev->hw;	struct ieee80211_hw_mode *hwmodes;	struct ieee80211_channel *channels;	struct ieee80211_rate *rates;	unsigned int i;	unsigned char tx_power;	hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL);	if (!hwmodes)		goto exit;	channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL);	if (!channels)		goto exit_free_modes;	rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL);	if (!rates)		goto exit_free_channels;	/*	 * Initialize Rate list.	 */	rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB,		       0x00, IEEE80211_RATE_CCK);	rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB,		       0x01, IEEE80211_RATE_CCK_2);	rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB,		       0x02, IEEE80211_RATE_CCK_2);	rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB,		       0x03, IEEE80211_RATE_CCK_2);	if (spec->num_rates > 4) {		rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB,			       0x0b, IEEE80211_RATE_OFDM);		rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB,			       0x0f, IEEE80211_RATE_OFDM);		rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB,			       0x0a, IEEE80211_RATE_OFDM);		rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB,			       0x0e, IEEE80211_RATE_OFDM);		rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB,			       0x09, IEEE80211_RATE_OFDM);		rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB,			       0x0d, IEEE80211_RATE_OFDM);		rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB,			       0x08, IEEE80211_RATE_OFDM);		rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB,			       0x0c, IEEE80211_RATE_OFDM);	}	/*	 * Initialize Channel list.	 */	for (i = 0; i < spec->num_channels; i++) {		if (spec->channels[i].channel <= 14)			tx_power = spec->tx_power_bg[i];		else if (spec->tx_power_a)			tx_power = spec->tx_power_a[i];		else			tx_power = spec->tx_power_default;		rt2x00lib_channel(&channels[i],				  spec->channels[i].channel, tx_power, i);	}	/*	 * Intitialize 802.11b	 * Rates: CCK.	 * Channels: OFDM.	 */	if (spec->num_modes > HWMODE_B) {		hwmodes[HWMODE_B].mode = MODE_IEEE80211B;		hwmodes[HWMODE_B].num_channels = 14;		hwmodes[HWMODE_B].num_rates = 4;		hwmodes[HWMODE_B].channels = channels;		hwmodes[HWMODE_B].rates = rates;	}	/*	 * Intitialize 802.11g	 * Rates: CCK, OFDM.	 * Channels: OFDM.	 */	if (spec->num_modes > HWMODE_G) {		hwmodes[HWMODE_G].mode = MODE_IEEE80211G;		hwmodes[HWMODE_G].num_channels = 14;		hwmodes[HWMODE_G].num_rates = spec->num_rates;		hwmodes[HWMODE_G].channels = channels;		hwmodes[HWMODE_G].rates = rates;	}	/*	 * Intitialize 802.11a	 * Rates: OFDM.	 * Channels: OFDM, UNII, HiperLAN2.	 */	if (spec->num_modes > HWMODE_A) {		hwmodes[HWMODE_A].mode = MODE_IEEE80211A;		hwmodes[HWMODE_A].num_channels = spec->num_channels - 14;		hwmodes[HWMODE_A].num_rates = spec->num_rates - 4;		hwmodes[HWMODE_A].channels = &channels[14];		hwmodes[HWMODE_A].rates = &rates[4];	}	if (spec->num_modes > HWMODE_G &&	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G]))		goto exit_free_rates;	if (spec->num_modes > HWMODE_B &&	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B]))		goto exit_free_rates;	if (spec->num_modes > HWMODE_A &&	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A]))		goto exit_free_rates;	rt2x00dev->hwmodes = hwmodes;	return 0;exit_free_rates:	kfree(rates);exit_free_channels:	kfree(channels);exit_free_modes:	kfree(hwmodes);exit:	ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");	return -ENOMEM;}static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev){	if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))		ieee80211_unregister_hw(rt2x00dev->hw);	if (likely(rt2x00dev->hwmodes)) {		kfree(rt2x00dev->hwmodes->channels);		kfree(rt2x00dev->hwmodes->rates);		kfree(rt2x00dev->hwmodes);		rt2x00dev->hwmodes = NULL;	}}static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev){	struct hw_mode_spec *spec = &rt2x00dev->spec;	int status;	/*	 * Initialize HW modes.	 */	status = rt2x00lib_probe_hw_modes(rt2x00dev, spec);	if (status)		return status;	/*	 * Register HW.	 */	status = ieee80211_register_hw(rt2x00dev->hw);	if (status) {		rt2x00lib_remove_hw(rt2x00dev);		return status;	}	__set_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags);	return 0;}/* * Initialization/uninitialization handlers. */static int rt2x00lib_alloc_entries(struct data_ring *ring,				   const u16 max_entries, const u16 data_size,				   const u16 desc_size){	struct data_entry *entry;	unsigned int i;	ring->stats.limit = max_entries;	ring->data_size = data_size;	ring->desc_size = desc_size;	/*	 * Allocate all ring entries.	 */	entry = kzalloc(ring->stats.limit * sizeof(*entry), GFP_KERNEL);	if (!entry)		return -ENOMEM;	for (i = 0; i < ring->stats.limit; i++) {		entry[i].flags = 0;		entry[i].ring = ring;		entry[i].skb = NULL;	}	ring->entry = entry;	return 0;}static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev){	struct data_ring *ring;	/*	 * Allocate the RX ring.	 */	if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE,				    rt2x00dev->ops->rxd_size))		return -ENOMEM;	/*	 * First allocate the TX rings.	 */	txring_for_each(rt2x00dev, ring) {		if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE,					    rt2x00dev->ops->txd_size))			return -ENOMEM;	}	if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))		return 0;	/*	 * Allocate the BEACON ring.	 */	if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES,				    MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size))		return -ENOMEM;	/*	 * Allocate the Atim ring.	 */	if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES,				    DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))		return -ENOMEM;	return 0;}static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev){	struct data_ring *ring;	ring_for_each(rt2x00dev, ring) {		kfree(ring->entry);		ring->entry = NULL;	}}void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev){	if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))		return;	/*	 * Unregister rfkill.	 */	rt2x00rfkill_unregister(rt2x00dev);	/*	 * Allow the HW to uninitialize.	 */	rt2x00dev->ops->lib->uninitialize(rt2x00dev);	/*	 * Free allocated ring entries.	 */	rt2x00lib_free_ring_entries(rt2x00dev);}int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev){	int status;	if (test_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))		return 0;	/*	 * Allocate all ring entries.	 */	status = rt2x00lib_alloc_ring_entries(rt2x00dev);	if (status) {		ERROR(rt2x00dev, "Ring entries allocation failed.\n");		return status;	}	/*	 * Initialize the device.	 */	status = rt2x00dev->ops->lib->initialize(rt2x00dev);	if (status)		goto exit;	__set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags);	/*	 * Register the rfkill handler.	 */	status = rt2x00rfkill_register(rt2x00dev);	if (status)		goto exit_unitialize;	return 0;exit_unitialize:	rt2x00lib_uninitialize(rt2x00dev);exit:	rt2x00lib_free_ring_entries(rt2x00dev);	return status;}/* * driver allocation handlers. */static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev){	struct data_ring *ring;	/*	 * We need the following rings:	 * RX: 1	 * TX: hw->queues	 * Beacon: 1 (if required)	 * Atim: 1 (if required)	 */	rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues +	    (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags));	ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL);	if (!ring) {		ERROR(rt2x00dev, "Ring allocation failed.\n");		return -ENOMEM;	}	/*	 * Initialize pointers	 */	rt2x00dev->rx = ring;	rt2x00dev->tx = &rt2x00dev->rx[1];	if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))		rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues];	/*	 * Initialize ring parameters.	 * cw_min: 2^5 = 32.	 * cw_max: 2^10 = 1024.	 */	ring_for_each(rt2x00dev, ring) {		ring->rt2x00dev = rt2x00dev;		ring->tx_params.aifs = 2;		ring->tx_params.cw_min = 5;		ring->tx_params.cw_max = 10;	}	return 0;}static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev){	kfree(rt2x00dev->rx);	rt2x00dev->rx = NULL;	rt2x00dev->tx = NULL;	rt2x00dev->bcn = NULL;}int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev){	int retval = -ENOMEM;	/*	 * Let the driver probe the device to detect the capabilities.	 */	retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev);	if (retval) {		ERROR(rt2x00dev, "Failed to allocate device.\n");		goto exit;	}	/*	 * Initialize configuration work.	 */	INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled);	INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);	INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled);	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);	/*	 * Reset current working type.	 */	rt2x00dev->interface.type = INVALID_INTERFACE;	/*	 * Allocate ring array.	 */	retval = rt2x00lib_alloc_rings(rt2x00dev);	if (retval)		goto exit;	/*	 * Initialize ieee80211 structure.	 */	retval = rt2x00lib_probe_hw(rt2x00dev);	if (retval) {		ERROR(rt2x00dev, "Failed to initialize hw.\n");		goto exit;	}	/*	 * Allocatie rfkill.	 */	retval = rt2x00rfkill_allocate(rt2x00dev);	if (retval)		goto exit;	/*	 * Open the debugfs entry.	 */	rt2x00debug_register(rt2x00dev);	__set_bit(DEVICE_PRESENT, &rt2x00dev->flags);	return 0;exit:	rt2x00lib_remove_dev(rt2x00dev);	return retval;}EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev);void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev){	__clear_bit(DEVICE_PRESENT, &rt2x00dev->flags);	/*	 * Disable radio.	 */	rt2x00lib_disable_radio(rt2x00dev);	/*	 * Uninitialize device.	 */	rt2x00lib_uninitialize(rt2x00dev);	/*	 * Close debugfs entry.	 */	rt2x00debug_deregister(rt2x00dev);	/*	 * Free rfkill	 */	rt2x00rfkill_free(rt2x00dev);	/*	 * Free ieee80211_hw memory.	 */	rt2x00lib_remove_hw(rt2x00dev);	/*	 * Free firmware image.	 */	rt2x00lib_free_firmware(rt2x00dev);	/*	 * Free ring structures.	 */	rt2x00lib_free_rings(rt2x00dev);}EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);/* * Device state handlers */#ifdef CONFIG_PMint rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state){	int retval;	NOTICE(rt2x00dev, "Going to sleep.\n");	__clear_bit(DEVICE_PRESENT, &rt2x00dev->flags);	/*	 * Only continue if mac80211 has open interfaces.	 */	if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))		goto exit;	__set_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags);	/*	 * Disable radio and unitialize all items	 * that must be recreated on resume.	 */	rt2x00mac_stop(rt2x00dev->hw);	rt2x00lib_uninitialize(rt2x00dev);	rt2x00debug_deregister(rt2x00dev);exit:	/*	 * Set device mode to sleep for power management.	 */	retval = rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP);	if (retval)		return retval;	return 0;}EXPORT_SYMBOL_GPL(rt2x00lib_suspend);int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev){	struct interface *intf = &rt2x00dev->interface;	int retval;	NOTICE(rt2x00dev, "Waking up.\n");	__set_bit(DEVICE_PRESENT, &rt2x00dev->flags);	/*	 * Open the debugfs entry.	 */	rt2x00debug_register(rt2x00dev);	/*	 * Only continue if mac80211 had open interfaces.	 */	if (!__test_and_clear_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags))		return 0;	/*	 * Reinitialize device and all active interfaces.	 */	retval = rt2x00mac_start(rt2x00dev->hw);	if (retval)		goto exit;	/*	 * Reconfigure device.	 */	rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf, 1);	if (!rt2x00dev->hw->conf.radio_enabled)		rt2x00lib_disable_radio(rt2x00dev);	rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);	rt2x00lib_config_bssid(rt2x00dev, intf->bssid);	rt2x00lib_config_type(rt2x00dev, intf->type);	/*	 * It is possible that during that mac80211 has attempted	 * to send frames while we were suspending or resuming.	 * In that case we have disabled the TX queue and should	 * now enable it again	 */	ieee80211_start_queues(rt2x00dev->hw);	/*	 * When in Master or Ad-hoc mode,	 * restart Beacon transmitting by faking a beacondone event.	 */	if (intf->type == IEEE80211_IF_TYPE_AP ||	    intf->type == IEEE80211_IF_TYPE_IBSS)		rt2x00lib_beacondone(rt2x00dev);	return 0;exit:	rt2x00lib_disable_radio(rt2x00dev);	rt2x00lib_uninitialize(rt2x00dev);	rt2x00debug_deregister(rt2x00dev);	return retval;}EXPORT_SYMBOL_GPL(rt2x00lib_resume);#endif /* CONFIG_PM *//* * rt2x00lib module information. */MODULE_AUTHOR(DRV_PROJECT);MODULE_VERSION(DRV_VERSION);MODULE_DESCRIPTION("rt2x00 library");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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