summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-02-25 11:55:27 +0100
committerThomas Haller <thaller@redhat.com>2022-02-25 11:55:27 +0100
commit1a5b85ad5e5c8411cb9c36dec9fb114d05c1f032 (patch)
tree36068552eb99604fc33228db6ae35ae873023e5f
parent2c9d3ef6c7f8604e9ba1fad81e0d1f316e2fc7d7 (diff)
parent72102011e91621cf3080d5fb32f929aa1d34949d (diff)
downloadNetworkManager-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.c26
-rw-r--r--src/core/nm-rfkill-manager.c24
-rw-r--r--src/core/nm-rfkill-manager.h7
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 {