diff options
-rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 7 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 10 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 18 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 2 | ||||
-rw-r--r-- | src/platform/wifi/wifi-utils-nl80211.c | 19 | ||||
-rw-r--r-- | src/platform/wifi/wifi-utils-private.h | 3 | ||||
-rw-r--r-- | src/platform/wifi/wifi-utils-wext.c | 25 | ||||
-rw-r--r-- | src/platform/wifi/wifi-utils.c | 8 | ||||
-rw-r--r-- | src/platform/wifi/wifi-utils.h | 2 |
9 files changed, 94 insertions, 0 deletions
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); |