📄 rt2x00dev.c
字号:
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 + -