Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
/*
* 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);
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
/*
* 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_PM
int 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);
/*
* 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))
/*
* 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);
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
/*
* 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");