summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2015-01-21 17:28:12 -0600
committerDan Williams <dcbw@redhat.com>2015-01-21 17:28:12 -0600
commit6bb0cffba32ec925743c4d491b75474d4e855198 (patch)
tree0b2008d15962e8a385140f6e8ac6be6a9c81faa4
parent7bdc6f5de53584414ccec3be47f16d909ae92bb6 (diff)
parenta428de82158fc9006820a2b4888e7260dfbfdbda (diff)
downloadNetworkManager-6bb0cffba32ec925743c4d491b75474d4e855198.tar.gz
merge: add support for Wi-Fi powersave (bgo #739084)
-rw-r--r--clients/cli/settings.c47
-rw-r--r--libnm-core/nm-setting-wireless.c41
-rw-r--r--libnm-core/nm-setting-wireless.h3
-rw-r--r--libnm-util/libnm-util.ver1
-rw-r--r--libnm-util/nm-setting-wireless.c41
-rw-r--r--libnm-util/nm-setting-wireless.h3
-rw-r--r--libnm/libnm.ver1
-rw-r--r--src/devices/wifi/nm-device-wifi.c7
-rw-r--r--src/platform/nm-linux-platform.c10
-rw-r--r--src/platform/nm-platform.c18
-rw-r--r--src/platform/nm-platform.h2
-rw-r--r--src/platform/wifi/wifi-utils-nl80211.c19
-rw-r--r--src/platform/wifi/wifi-utils-private.h3
-rw-r--r--src/platform/wifi/wifi-utils-wext.c25
-rw-r--r--src/platform/wifi/wifi-utils.c8
-rw-r--r--src/platform/wifi/wifi-utils.h2
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c5
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.c1
18 files changed, 236 insertions, 1 deletions
diff --git a/clients/cli/settings.c b/clients/cli/settings.c
index 8df57fb6ee..5d003fad92 100644
--- a/clients/cli/settings.c
+++ b/clients/cli/settings.c
@@ -190,6 +190,7 @@ NmcOutputField nmc_fields_setting_wireless[] = {
SETTING_FIELD (NM_SETTING_WIRELESS_MTU, 6), /* 11 */
SETTING_FIELD (NM_SETTING_WIRELESS_SEEN_BSSIDS, 35), /* 12 */
SETTING_FIELD (NM_SETTING_WIRELESS_HIDDEN, 10), /* 13 */
+ SETTING_FIELD (NM_SETTING_WIRELESS_POWERSAVE, 10), /* 14 */
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
};
#define NMC_FIELDS_SETTING_WIRELESS_ALL "name"","\
@@ -205,7 +206,8 @@ NmcOutputField nmc_fields_setting_wireless[] = {
NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST","\
NM_SETTING_WIRELESS_MTU","\
NM_SETTING_WIRELESS_SEEN_BSSIDS","\
- NM_SETTING_WIRELESS_HIDDEN
+ NM_SETTING_WIRELESS_HIDDEN"," \
+ NM_SETTING_WIRELESS_POWERSAVE
#define NMC_FIELDS_SETTING_WIRELESS_COMMON NMC_FIELDS_SETTING_WIRELESS_ALL
/* Available fields for NM_SETTING_WIRELESS_SECURITY_SETTING_NAME */
@@ -1525,6 +1527,20 @@ nmc_property_wireless_get_mtu (NMSetting *setting)
return g_strdup_printf ("%d", mtu);
}
+static char *
+nmc_property_wireless_get_powersave (NMSetting *setting)
+{
+ NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (setting);
+ guint powersave = nm_setting_wireless_get_powersave (s_wireless);
+
+ if (powersave == 0)
+ return g_strdup (_("no"));
+ else if (powersave == 1)
+ return g_strdup (_("yes"));
+ else
+ return g_strdup_printf (_("yes (%u)"), powersave);
+}
+
/* --- NM_SETTING_WIRELESS_SECURITY_SETTING_NAME property get functions --- */
DEFINE_GETTER (nmc_property_wifi_sec_get_key_mgmt, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)
DEFINE_GETTER (nmc_property_wifi_sec_get_wep_tx_keyidx, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX)
@@ -4206,6 +4222,27 @@ DEFINE_REMOVER_INDEX_OR_VALUE (nmc_property_wireless_remove_mac_address_blacklis
nm_setting_wireless_remove_mac_blacklist_item,
_validate_and_remove_wifi_mac_blacklist_item)
+/* 'powersave' */
+static gboolean
+nmc_property_wireless_set_powersave (NMSetting *setting, const char *prop, const char *val, GError **error)
+{
+ unsigned long powersave_int;
+ gboolean val_bool = FALSE;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (!nmc_string_to_uint (val, TRUE, 0, G_MAXUINT32, &powersave_int)) {
+ if (!nmc_string_to_bool (val, &val_bool, NULL)) {
+ g_set_error (error, 1, 0, _("'%s' is not a valid powersave value"), val);
+ return FALSE;
+ }
+ powersave_int = val_bool ? 1 : 0;
+ }
+
+ g_object_set (setting, prop, (guint32) powersave_int, NULL);
+ return TRUE;
+}
+
/* --- NM_SETTING_WIRELESS_SECURITY_SETTING_NAME property setter functions --- */
/* 'key-mgmt' */
static const char *wifi_sec_valid_key_mgmts[] = { "none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap", NULL };
@@ -6172,6 +6209,13 @@ nmc_properties_init (void)
NULL,
NULL,
NULL);
+ nmc_add_prop_funcs (GLUE (WIRELESS, POWERSAVE),
+ nmc_property_wireless_get_powersave,
+ nmc_property_wireless_set_powersave,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
/* Add editable properties for NM_SETTING_WIRELESS_SECURITY_SETTING_NAME */
nmc_add_prop_funcs (GLUE (WIRELESS_SECURITY, KEY_MGMT),
@@ -6757,6 +6801,7 @@ setting_wireless_details (NMSetting *setting, NmCli *nmc, const char *one_prop,
set_val_str (arr, 11, nmc_property_wireless_get_mtu (setting));
set_val_str (arr, 12, nmc_property_wireless_get_seen_bssids (setting));
set_val_str (arr, 13, nmc_property_wireless_get_hidden (setting));
+ set_val_str (arr, 14, nmc_property_wireless_get_powersave (setting));
g_ptr_array_add (nmc->output_data, arr);
print_data (nmc); /* Print all data */
diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c
index f8d22c2d00..075af10224 100644
--- a/libnm-core/nm-setting-wireless.c
+++ b/libnm-core/nm-setting-wireless.c
@@ -60,6 +60,7 @@ typedef struct {
guint32 mtu;
GSList *seen_bssids;
gboolean hidden;
+ guint32 powersave;
} NMSettingWirelessPrivate;
enum {
@@ -77,6 +78,7 @@ enum {
PROP_MTU,
PROP_SEEN_BSSIDS,
PROP_HIDDEN,
+ PROP_POWERSAVE,
LAST_PROP
};
@@ -602,6 +604,22 @@ nm_setting_wireless_get_hidden (NMSettingWireless *setting)
}
/**
+ * nm_setting_wireless_get_powersave:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:powersave property of the setting
+ *
+ * Since: 1.2
+ **/
+guint32
+nm_setting_wireless_get_powersave (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->powersave;
+}
+
+/**
* nm_setting_wireless_add_seen_bssid:
* @setting: the #NMSettingWireless
* @bssid: the new BSSID to add to the list
@@ -916,6 +934,9 @@ set_property (GObject *object, guint prop_id,
case PROP_HIDDEN:
priv->hidden = g_value_get_boolean (value);
break;
+ case PROP_POWERSAVE:
+ priv->powersave = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -969,6 +990,9 @@ get_property (GObject *object, guint prop_id,
case PROP_HIDDEN:
g_value_set_boolean (value, nm_setting_wireless_get_hidden (setting));
break;
+ case PROP_POWERSAVE:
+ g_value_set_uint (value, nm_setting_wireless_get_powersave (setting));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1315,6 +1339,23 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ /**
+ * NMSettingWireless:powersave:
+ *
+ * If set to %FALSE, Wi-Fi power saving behavior is disabled. If set to
+ * %TRUE, Wi-Fi power saving behavior is enabled. All other values are
+ * reserved. Note that even though only boolean values are allowed, the
+ * property type is an unsigned integer to allow for future expansion.
+ *
+ * Since: 1.2
+ **/
+ g_object_class_install_property
+ (object_class, PROP_POWERSAVE,
+ g_param_spec_uint (NM_SETTING_WIRELESS_POWERSAVE, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
/* Compatibility for deprecated property */
/* ---ifcfg-rh---
* property: security
diff --git a/libnm-core/nm-setting-wireless.h b/libnm-core/nm-setting-wireless.h
index 98fa98dc6c..46ae6e6dba 100644
--- a/libnm-core/nm-setting-wireless.h
+++ b/libnm-core/nm-setting-wireless.h
@@ -55,6 +55,7 @@ G_BEGIN_DECLS
#define NM_SETTING_WIRELESS_MTU "mtu"
#define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids"
#define NM_SETTING_WIRELESS_HIDDEN "hidden"
+#define NM_SETTING_WIRELESS_POWERSAVE "powersave"
/**
* NM_SETTING_WIRELESS_MODE_ADHOC:
@@ -118,6 +119,8 @@ void nm_setting_wireless_clear_mac_blacklist_items (NMSettingWire
guint32 nm_setting_wireless_get_mtu (NMSettingWireless *setting);
gboolean nm_setting_wireless_get_hidden (NMSettingWireless *setting);
+NM_AVAILABLE_IN_1_2
+guint32 nm_setting_wireless_get_powersave (NMSettingWireless *setting);
gboolean nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting,
const char *bssid);
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index 9d78e5024d..ae34142073 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -562,6 +562,7 @@ global:
nm_setting_wireless_get_mtu;
nm_setting_wireless_get_num_mac_blacklist_items;
nm_setting_wireless_get_num_seen_bssids;
+ nm_setting_wireless_get_powersave;
nm_setting_wireless_get_rate;
nm_setting_wireless_get_security;
nm_setting_wireless_get_seen_bssid;
diff --git a/libnm-util/nm-setting-wireless.c b/libnm-util/nm-setting-wireless.c
index 99f4c9b14c..84f1c77c72 100644
--- a/libnm-util/nm-setting-wireless.c
+++ b/libnm-util/nm-setting-wireless.c
@@ -87,6 +87,7 @@ typedef struct {
GSList *seen_bssids;
char *security;
gboolean hidden;
+ guint32 powersave;
} NMSettingWirelessPrivate;
enum {
@@ -105,6 +106,7 @@ enum {
PROP_SEEN_BSSIDS,
PROP_SEC,
PROP_HIDDEN,
+ PROP_POWERSAVE,
LAST_PROP
};
@@ -662,6 +664,22 @@ nm_setting_wireless_get_hidden (NMSettingWireless *setting)
}
/**
+ * nm_setting_wireless_get_powersave:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:powersave property of the setting
+ *
+ * Since: 1.2
+ **/
+guint32
+nm_setting_wireless_get_powersave (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->powersave;
+}
+
+/**
* nm_setting_wireless_add_seen_bssid:
* @setting: the #NMSettingWireless
* @bssid: the new BSSID to add to the list
@@ -953,6 +971,9 @@ set_property (GObject *object, guint prop_id,
case PROP_HIDDEN:
priv->hidden = g_value_get_boolean (value);
break;
+ case PROP_POWERSAVE:
+ priv->powersave = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1008,6 +1029,9 @@ get_property (GObject *object, guint prop_id,
case PROP_HIDDEN:
g_value_set_boolean (value, nm_setting_wireless_get_hidden (setting));
break;
+ case PROP_POWERSAVE:
+ g_value_set_uint (value, nm_setting_wireless_get_powersave (setting));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1244,4 +1268,21 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:powersave:
+ *
+ * If set to %FALSE, Wi-Fi power saving behavior is disabled. If set to
+ * %TRUE, Wi-Fi power saving behavior is enabled. All other values are
+ * reserved. Note that even though only boolean values are allowed, the
+ * property type is an unsigned integer to allow for future expansion.
+ *
+ * Since: 1.2
+ **/
+ g_object_class_install_property
+ (object_class, PROP_POWERSAVE,
+ g_param_spec_uint (NM_SETTING_WIRELESS_POWERSAVE, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
}
diff --git a/libnm-util/nm-setting-wireless.h b/libnm-util/nm-setting-wireless.h
index 18f78cff66..77eff73e30 100644
--- a/libnm-util/nm-setting-wireless.h
+++ b/libnm-util/nm-setting-wireless.h
@@ -73,6 +73,7 @@ GQuark nm_setting_wireless_error_quark (void);
#define NM_SETTING_WIRELESS_MTU "mtu"
#define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids"
#define NM_SETTING_WIRELESS_HIDDEN "hidden"
+#define NM_SETTING_WIRELESS_POWERSAVE "powersave"
/* Deprecated */
#define NM_SETTING_WIRELESS_SEC "security"
@@ -150,6 +151,8 @@ void nm_setting_wireless_clear_mac_blacklist_items (NMSettingWire
guint32 nm_setting_wireless_get_mtu (NMSettingWireless *setting);
gboolean nm_setting_wireless_get_hidden (NMSettingWireless *setting);
+NM_AVAILABLE_IN_1_2
+guint32 nm_setting_wireless_get_powersave (NMSettingWireless *setting);
gboolean nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting,
const char *bssid);
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index aba84f4a83..b56fe77321 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -705,6 +705,7 @@ global:
nm_setting_wireless_get_mtu;
nm_setting_wireless_get_num_mac_blacklist_items;
nm_setting_wireless_get_num_seen_bssids;
+ nm_setting_wireless_get_powersave;
nm_setting_wireless_get_rate;
nm_setting_wireless_get_seen_bssid;
nm_setting_wireless_get_ssid;
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 7d3dc9a1d7..403b01af9d 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -743,6 +743,8 @@ deactivate (NMDevice *device)
if (priv->initial_hw_addr)
nm_device_set_hw_addr (device, priv->initial_hw_addr, "reset", LOGD_WIFI);
+ nm_platform_wifi_set_powersave (ifindex, 0);
+
/* Ensure we're in infrastructure mode after deactivation; some devices
* (usually older ones) don't scan well in adhoc mode.
*/
@@ -2758,6 +2760,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
if ((nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) || nm_ap_is_hotspot (ap))
ensure_hotspot_frequency (self, s_wireless, ap);
+ if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) {
+ nm_platform_wifi_set_powersave (nm_device_get_ifindex (device),
+ nm_setting_wireless_get_powersave (s_wireless));
+ }
+
/* Build up the supplicant configuration */
config = build_supplicant_config (self, connection, nm_ap_get_freq (ap));
if (config == NULL) {
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 4ce792a1a0..a03abbebb3 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -3372,6 +3372,15 @@ wifi_set_mode (NMPlatform *platform, int ifindex, NM80211Mode mode)
wifi_utils_set_mode (wifi_data, mode);
}
+static void
+wifi_set_powersave (NMPlatform *platform, int ifindex, guint32 powersave)
+{
+ WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex);
+
+ if (wifi_data)
+ wifi_utils_set_powersave (wifi_data, powersave);
+}
+
static guint32
wifi_find_frequency (NMPlatform *platform, int ifindex, const guint32 *freqs)
{
@@ -4586,6 +4595,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->wifi_get_rate = wifi_get_rate;
platform_class->wifi_get_mode = wifi_get_mode;
platform_class->wifi_set_mode = wifi_set_mode;
+ platform_class->wifi_set_powersave = wifi_set_powersave;
platform_class->wifi_find_frequency = wifi_find_frequency;
platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 14fc44c5fa..a2fd8f39a4 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1399,6 +1399,22 @@ nm_platform_wifi_set_mode (int ifindex, NM80211Mode mode)
klass->wifi_set_mode (platform, ifindex, mode);
}
+static void
+wifi_set_powersave (NMPlatform *p, int ifindex, guint32 powersave)
+{
+ /* empty */
+}
+
+void
+nm_platform_wifi_set_powersave (int ifindex, guint32 powersave)
+{
+ reset_error ();
+
+ g_return_if_fail (ifindex > 0);
+
+ klass->wifi_set_powersave (platform, ifindex, powersave);
+}
+
guint32
nm_platform_wifi_find_frequency (int ifindex, const guint32 *freqs)
{
@@ -2756,6 +2772,8 @@ nm_platform_class_init (NMPlatformClass *platform_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (platform_class);
+ platform_class->wifi_set_powersave = wifi_set_powersave;
+
/* Signals */
SIGNAL (SIGNAL_LINK_CHANGED, log_link)
SIGNAL (SIGNAL_IP4_ADDRESS_CHANGED, log_ip4_address)
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 3f37ed6048..b202de32a1 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -405,6 +405,7 @@ typedef struct {
guint32 (*wifi_get_rate) (NMPlatform *, int ifindex);
NM80211Mode (*wifi_get_mode) (NMPlatform *, int ifindex);
void (*wifi_set_mode) (NMPlatform *, int ifindex, NM80211Mode mode);
+ void (*wifi_set_powersave) (NMPlatform *, int ifindex, guint32 powersave);
guint32 (*wifi_find_frequency) (NMPlatform *, int ifindex, const guint32 *freqs);
void (*wifi_indicate_addressing_running) (NMPlatform *, int ifindex, gboolean running);
@@ -551,6 +552,7 @@ int nm_platform_wifi_get_quality (int ifindex);
guint32 nm_platform_wifi_get_rate (int ifindex);
NM80211Mode nm_platform_wifi_get_mode (int ifindex);
void nm_platform_wifi_set_mode (int ifindex, NM80211Mode mode);
+void nm_platform_wifi_set_powersave (int ifindex, guint32 powersave);
guint32 nm_platform_wifi_find_frequency (int ifindex, const guint32 *freqs);
void nm_platform_wifi_indicate_addressing_running (int ifindex, gboolean running);
diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c
index 752da926a9..fd69d17a71 100644
--- a/src/platform/wifi/wifi-utils-nl80211.c
+++ b/src/platform/wifi/wifi-utils-nl80211.c
@@ -265,6 +265,24 @@ wifi_nl80211_set_mode (WifiData *data, const NM80211Mode mode)
return FALSE;
}
+static gboolean
+wifi_nl80211_set_powersave (WifiData *data, guint32 powersave)
+{
+ WifiDataNl80211 *nl80211 = (WifiDataNl80211 *) data;
+ struct nl_msg *msg;
+ int err;
+
+ msg = nl80211_alloc_msg (nl80211, NL80211_CMD_SET_POWER_SAVE, 0);
+ NLA_PUT_U32 (msg, NL80211_ATTR_PS_STATE,
+ powersave == 1 ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);
+ err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
+ return err ? FALSE : TRUE;
+
+nla_put_failure:
+ nlmsg_free (msg);
+ return FALSE;
+}
+
/* @divisor: pass what value @xbm should be divided by to get dBm */
static guint32
nl80211_xbm_to_percent (gint32 xbm, guint32 divisor)
@@ -842,6 +860,7 @@ wifi_nl80211_init (const char *iface, int ifindex)
nl80211 = wifi_data_new (iface, ifindex, sizeof (*nl80211));
nl80211->parent.get_mode = wifi_nl80211_get_mode;
nl80211->parent.set_mode = wifi_nl80211_set_mode;
+ nl80211->parent.set_powersave = wifi_nl80211_set_powersave;
nl80211->parent.get_freq = wifi_nl80211_get_freq;
nl80211->parent.find_freq = wifi_nl80211_find_freq;
nl80211->parent.get_ssid = wifi_nl80211_get_ssid;
diff --git a/src/platform/wifi/wifi-utils-private.h b/src/platform/wifi/wifi-utils-private.h
index aaedd5b7a7..9d9af69248 100644
--- a/src/platform/wifi/wifi-utils-private.h
+++ b/src/platform/wifi/wifi-utils-private.h
@@ -35,6 +35,9 @@ struct WifiData {
gboolean (*set_mode) (WifiData *data, const NM80211Mode mode);
+ /* Set power saving mode on an interface */
+ gboolean (*set_powersave) (WifiData *data, guint32 powersave);
+
/* Return current frequency in MHz (really associated BSS frequency) */
guint32 (*get_freq) (WifiData *data);
diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c
index e0331de7c6..8be36770ef 100644
--- a/src/platform/wifi/wifi-utils-wext.c
+++ b/src/platform/wifi/wifi-utils-wext.c
@@ -165,6 +165,30 @@ wifi_wext_set_mode (WifiData *data, const NM80211Mode mode)
return TRUE;
}
+static gboolean
+wifi_wext_set_powersave (WifiData *data, guint32 powersave)
+{
+ WifiDataWext *wext = (WifiDataWext *) data;
+ struct iwreq wrq;
+
+ memset (&wrq, 0, sizeof (struct iwreq));
+ if (powersave == 1) {
+ wrq.u.power.flags = IW_POWER_ALL_R;
+ } else
+ wrq.u.power.disabled = 1;
+
+ strncpy (wrq.ifr_name, wext->parent.iface, IFNAMSIZ);
+ if (ioctl (wext->fd, SIOCSIWPOWER, &wrq) < 0) {
+ if (errno != ENODEV) {
+ nm_log_err (LOGD_HW | LOGD_WIFI, "(%s): error setting powersave %" G_GUINT32_FORMAT,
+ wext->parent.iface, powersave);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static guint32
wifi_wext_get_freq (WifiData *data)
{
@@ -573,6 +597,7 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan)
wext = wifi_data_new (iface, ifindex, sizeof (*wext));
wext->parent.get_mode = wifi_wext_get_mode;
wext->parent.set_mode = wifi_wext_set_mode;
+ wext->parent.set_powersave = wifi_wext_set_powersave;
wext->parent.get_freq = wifi_wext_get_freq;
wext->parent.find_freq = wifi_wext_find_freq;
wext->parent.get_ssid = wifi_wext_get_ssid;
diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c
index daef881bf9..a67a7b05c9 100644
--- a/src/platform/wifi/wifi-utils.c
+++ b/src/platform/wifi/wifi-utils.c
@@ -98,6 +98,14 @@ wifi_utils_set_mode (WifiData *data, const NM80211Mode mode)
return data->set_mode ? data->set_mode (data, mode) : TRUE;
}
+gboolean
+wifi_utils_set_powersave (WifiData *data, guint32 powersave)
+{
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ return data->set_powersave ? data->set_powersave (data, powersave) : TRUE;
+}
+
guint32
wifi_utils_get_freq (WifiData *data)
{
diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h
index f1b57acedc..ea58f89043 100644
--- a/src/platform/wifi/wifi-utils.h
+++ b/src/platform/wifi/wifi-utils.h
@@ -65,6 +65,8 @@ gboolean wifi_utils_indicate_addressing_running (WifiData *data, gboolean runnin
/* Returns true if WoWLAN is enabled on device */
gboolean wifi_utils_get_wowlan (WifiData *data);
+gboolean wifi_utils_set_powersave (WifiData *data, guint32 powersave);
+
/* OLPC Mesh-only functions */
guint32 wifi_utils_get_mesh_channel (WifiData *data);
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index 2ce9e05217..5b60934608 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -3415,6 +3415,11 @@ make_wireless_setting (shvarFile *ifcfg,
svTrueValue (ifcfg, "SSID_HIDDEN", FALSE),
NULL);
+ g_object_set (s_wireless,
+ NM_SETTING_WIRELESS_POWERSAVE,
+ svTrueValue (ifcfg, "POWERSAVE", FALSE) ? 1 : 0,
+ NULL);
+
return NM_SETTING (s_wireless);
error:
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index 86b56cce47..383bee0811 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -972,6 +972,7 @@ write_wireless_setting (NMConnection *connection,
}
svSetValue (ifcfg, "SSID_HIDDEN", nm_setting_wireless_get_hidden (s_wireless) ? "yes" : NULL, TRUE);
+ svSetValue (ifcfg, "POWERSAVE", nm_setting_wireless_get_powersave (s_wireless) ? "yes" : NULL, TRUE);
svSetValue (ifcfg, "TYPE", TYPE_WIRELESS, FALSE);