diff options
author | Thomas Haller <thaller@redhat.com> | 2022-02-25 11:55:27 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-02-25 11:55:27 +0100 |
commit | 1a5b85ad5e5c8411cb9c36dec9fb114d05c1f032 (patch) | |
tree | 36068552eb99604fc33228db6ae35ae873023e5f | |
parent | 2c9d3ef6c7f8604e9ba1fad81e0d1f316e2fc7d7 (diff) | |
parent | 72102011e91621cf3080d5fb32f929aa1d34949d (diff) | |
download | NetworkManager-1a5b85ad5e5c8411cb9c36dec9fb114d05c1f032.tar.gz |
core/rfkill: merge branch 'egrumbach:rfkill-reasons'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1105
-rw-r--r-- | src/core/nm-manager.c | 26 | ||||
-rw-r--r-- | src/core/nm-rfkill-manager.c | 24 | ||||
-rw-r--r-- | src/core/nm-rfkill-manager.h | 7 |
3 files changed, 49 insertions, 8 deletions
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 003552bc47..b459e74e8d 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -63,6 +63,7 @@ typedef struct { bool user_enabled : 1; bool sw_enabled : 1; bool hw_enabled : 1; + bool os_owner : 1; } RfkillRadioState; typedef enum { @@ -2299,6 +2300,9 @@ _rfkill_radio_state_get_enabled(const RfkillRadioState *rstate, gboolean check_c { gboolean enabled; + /* If the device is not owned by the os, hw_enabled will be FALSE, hence + * we don't need to consider os_owner here. + */ enabled = rstate->user_enabled && rstate->hw_enabled; if (check_changeable) enabled &= rstate->sw_enabled; @@ -2314,14 +2318,23 @@ _rfkill_radio_state_set_from_manager(NMRfkillManager *rfkill_mgr, case NM_RFKILL_STATE_UNBLOCKED: rstate->sw_enabled = TRUE; rstate->hw_enabled = TRUE; + rstate->os_owner = TRUE; return; case NM_RFKILL_STATE_SOFT_BLOCKED: rstate->sw_enabled = FALSE; rstate->hw_enabled = TRUE; + rstate->os_owner = TRUE; return; case NM_RFKILL_STATE_HARD_BLOCKED: rstate->sw_enabled = FALSE; rstate->hw_enabled = FALSE; + /* In case the OS doesn't own the NIC, we would be in NM_RFKILL_STATE_HARD_BLOCKED */ + rstate->os_owner = TRUE; + return; + case NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER: + rstate->sw_enabled = FALSE; + rstate->hw_enabled = FALSE; + rstate->os_owner = FALSE; return; } nm_assert_not_reached(); @@ -2383,10 +2396,11 @@ _rfkill_update_one_type(NMManager *self, NMRfkillType rtype) /* Print out all states affecting device enablement */ _LOGD(LOGD_RFKILL, - "rfkill: %s hw-enabled %d sw-enabled %d", + "rfkill: %s hw-enabled %d sw-enabled %d os-owner %d", nm_rfkill_type_to_string(rtype), rstate->hw_enabled, - rstate->sw_enabled); + rstate->sw_enabled, + rstate->os_owner); /* Log new killswitch state */ new_rfkilled = rstate->hw_enabled && rstate->sw_enabled; @@ -6469,12 +6483,14 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) gboolean enabled = _rfkill_radio_state_get_enabled(rstate, TRUE); _LOGD(LOGD_RFKILL, - "rfkill: %s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)", + "rfkill: %s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d, " + "os_owner %d)", enabled ? "enabling" : "disabling", nm_rfkill_type_to_string(rtype), rstate->hw_enabled, rstate->sw_enabled, - rstate->user_enabled); + rstate->user_enabled, + rstate->os_owner); if (nm_device_get_rfkill_type(device) == rtype) nm_device_set_enabled(device, enabled); } @@ -7936,11 +7952,13 @@ nm_manager_init(NMManager *self) .user_enabled = TRUE, .sw_enabled = FALSE, .hw_enabled = TRUE, + .os_owner = TRUE, }; priv->radio_states[NM_RFKILL_TYPE_WWAN] = (RfkillRadioState){ .user_enabled = TRUE, .sw_enabled = FALSE, .hw_enabled = TRUE, + .os_owner = TRUE, }; priv->sleeping = FALSE; diff --git a/src/core/nm-rfkill-manager.c b/src/core/nm-rfkill-manager.c index bb6dcfd72c..2315973d85 100644 --- a/src/core/nm-rfkill-manager.c +++ b/src/core/nm-rfkill-manager.c @@ -90,6 +90,8 @@ nm_rfkill_state_to_string(NMRfkillState state) return "soft-blocked"; case NM_RFKILL_STATE_HARD_BLOCKED: return "hard-blocked"; + case NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER: + return "hard-blocked-os-not-owner"; } return nm_assert_unreachable_val("unknown"); } @@ -153,7 +155,7 @@ killswitch_destroy(Killswitch *ks) } static NMRfkillState -sysfs_state_to_nm_state(int sysfs_state) +sysfs_state_to_nm_state(int sysfs_state, int sysfs_reason) { switch (sysfs_state) { case 0: @@ -161,6 +163,11 @@ sysfs_state_to_nm_state(int sysfs_state) case 1: return NM_RFKILL_STATE_UNBLOCKED; case 2: + /* sysfs reason is a bitmap, in case we have both reasons (SIGNAL and NOT_OWNER), we want + * to consider the device as not owned. + */ + if (sysfs_reason & 2) + return NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER; return NM_RFKILL_STATE_HARD_BLOCKED; default: nm_log_warn(LOGD_RFKILL, "unhandled rfkill state %d", sysfs_state); @@ -191,6 +198,7 @@ recheck_killswitches(NMRfkillManager *self) struct udev_device *device; NMRfkillState dev_state; int sysfs_state; + int sysfs_reason; device = udev_device_new_from_subsystem_sysname(nm_udev_client_get_udev(priv->udev_client), "rfkill", @@ -203,15 +211,23 @@ recheck_killswitches(NMRfkillManager *self) G_MININT, G_MAXINT, -1); - dev_state = sysfs_state_to_nm_state(sysfs_state); + sysfs_reason = _nm_utils_ascii_str_to_int64( + udev_device_get_property_value(device, "RFKILL_STATE_REASON"), + 10, + G_MININT, + G_MAXINT, + 1); /* defaults to SIGNAL in case the kernel does not support this */ + + dev_state = sysfs_state_to_nm_state(sysfs_state, sysfs_reason); nm_log_dbg(LOGD_RFKILL, - "%s rfkill%s switch %s state now %d/%u", + "%s rfkill%s switch %s state now %d/%u reason: 0x%x", nm_rfkill_type_to_string(ks->rtype), ks->platform ? " platform" : "", ks->name, sysfs_state, - dev_state); + dev_state, + sysfs_reason); if (ks->platform == FALSE) { if (dev_state > poll_states[ks->rtype]) diff --git a/src/core/nm-rfkill-manager.h b/src/core/nm-rfkill-manager.h index db1385ea6a..a9c723f154 100644 --- a/src/core/nm-rfkill-manager.h +++ b/src/core/nm-rfkill-manager.h @@ -11,6 +11,13 @@ typedef enum { NM_RFKILL_STATE_UNBLOCKED = 0, NM_RFKILL_STATE_SOFT_BLOCKED = 1, NM_RFKILL_STATE_HARD_BLOCKED = 2, + /* NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER means that the CSME firmware + * is currently controlling the device. This feature is implmented on Intel + * wifi devices only. + * The NetworkManager can get ownership on the device, but it requires to + * first ask ownership through the iwlmei kernel module. + */ + NM_RFKILL_STATE_HARD_BLOCKED_OS_NOT_OWNER = 3, } NMRfkillState; typedef enum { |