diff --git a/ChangeLog b/ChangeLog index e03adf403c..3f86c36a6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2008-08-18 Dan Williams + + * include/NetworkManager.h + introspection/nm-device.xml + - Add a "missing firmware" device state reason + + * src/NetworkManagerSystem.c + src/NetworkManagerSystem.h + - (nm_system_device_set_up_down): add a no_firmware argument + - (nm_system_device_set_up_down_with_iface): if the result of setting + IFF_UP is ENOENT, that almost always means missing firmware + + * src/backends/NetworkManagerGeneric.c + src/nm-device-ethernet.c + src/nm-device-private.h + src/nm-device-wifi.c + src/nm-device.c + src/nm-device.h + src/nm-hso-gsm-device.c + src/vpn-manager/nm-vpn-connection.c + - Pass no_firmware along; check it where appropriate + 2008-08-18 Dan Williams Patch from Robert Buchholz diff --git a/include/NetworkManager.h b/include/NetworkManager.h index 825c22af5c..39358ed623 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -322,6 +322,9 @@ typedef enum { /* PIN check failed */ NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, + /* Necessary firmware for the device may be missing */ + NM_DEVICE_STATE_REASON_FIRMWARE_MISSING, + /* Unused */ NM_DEVICE_STATE_REASON_LAST = 0xFFFF } NMDeviceStateReason; diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml index 22b636cbc2..c5d785e73d 100644 --- a/introspection/nm-device.xml +++ b/introspection/nm-device.xml @@ -314,6 +314,11 @@ PIN check failed. + + + + Necessary firmware for the device may be missing. + diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c index c97d18ded2..c736507bcc 100644 --- a/src/NetworkManagerSystem.c +++ b/src/NetworkManagerSystem.c @@ -358,7 +358,7 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device, if (!iface || !strlen (iface)) goto out; - nm_system_device_set_up_down_with_iface (iface, TRUE); + nm_system_device_set_up_down_with_iface (iface, TRUE, NULL); if (!add_ip4_addresses (config, iface)) goto out; @@ -419,14 +419,20 @@ gboolean nm_system_vpn_device_unset_from_ip4_config (NMDevice *active_device, co * Mark the device as up or down. * */ -gboolean nm_system_device_set_up_down (NMDevice *dev, gboolean up) +gboolean +nm_system_device_set_up_down (NMDevice *dev, + gboolean up, + gboolean *no_firmware) { g_return_val_if_fail (dev != NULL, FALSE); - return nm_system_device_set_up_down_with_iface (nm_device_get_iface (dev), up); + return nm_system_device_set_up_down_with_iface (nm_device_get_iface (dev), up, no_firmware); } -gboolean nm_system_device_set_up_down_with_iface (const char *iface, gboolean up) +gboolean +nm_system_device_set_up_down_with_iface (const char *iface, + gboolean up, + gboolean *no_firmware) { struct rtnl_link *request = NULL, *old = NULL; struct nl_handle *nlh; @@ -434,6 +440,8 @@ gboolean nm_system_device_set_up_down_with_iface (const char *iface, gboolean up guint32 idx; g_return_val_if_fail (iface != NULL, FALSE); + if (no_firmware) + g_return_val_if_fail (*no_firmware == FALSE, FALSE); if (!(request = rtnl_link_alloc ())) goto out; @@ -447,8 +455,12 @@ gboolean nm_system_device_set_up_down_with_iface (const char *iface, gboolean up old = nm_netlink_index_to_rtnl_link (idx); if (old) { nlh = nm_netlink_get_default_handle (); - if (nlh) - success = (rtnl_link_change (nlh, old, request, 0) == 0) ? TRUE : FALSE; + if (nlh) { + if (rtnl_link_change (nlh, old, request, 0) == 0) + success = TRUE; + else if ((nl_get_errno () == ENOENT) && no_firmware && up) + *no_firmware = TRUE; + } } rtnl_link_put (old); diff --git a/src/NetworkManagerSystem.h b/src/NetworkManagerSystem.h index 60e24c6abb..eb321df5af 100644 --- a/src/NetworkManagerSystem.h +++ b/src/NetworkManagerSystem.h @@ -56,8 +56,12 @@ gboolean nm_system_vpn_device_unset_from_ip4_config (NMDevice *active_device, const char *iface, NMIP4Config *config); -gboolean nm_system_device_set_up_down (NMDevice *dev, gboolean up); -gboolean nm_system_device_set_up_down_with_iface (const char *iface, gboolean up); +gboolean nm_system_device_set_up_down (NMDevice *dev, + gboolean up, + gboolean *no_firmware); +gboolean nm_system_device_set_up_down_with_iface (const char *iface, + gboolean up, + gboolean *no_firmware); gboolean nm_system_device_is_up (NMDevice *device); gboolean nm_system_device_is_up_with_iface (const char *iface); diff --git a/src/backends/NetworkManagerGeneric.c b/src/backends/NetworkManagerGeneric.c index 93b1e1262d..1cf0021b19 100644 --- a/src/backends/NetworkManagerGeneric.c +++ b/src/backends/NetworkManagerGeneric.c @@ -58,7 +58,7 @@ void nm_generic_enable_loopback (void) int iface_idx = -1; int err; - nm_system_device_set_up_down_with_iface ("lo", TRUE); + nm_system_device_set_up_down_with_iface ("lo", TRUE, NULL); nlh = nm_netlink_get_default_handle (); if (!nlh) diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index 7db4063320..b00ce2cb21 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -357,15 +357,15 @@ real_hw_is_up (NMDevice *device) } static gboolean -real_hw_bring_up (NMDevice *dev) +real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) { - return nm_system_device_set_up_down (dev, TRUE); + return nm_system_device_set_up_down (dev, TRUE, no_firmware); } static void real_hw_take_down (NMDevice *dev) { - nm_system_device_set_up_down (dev, FALSE); + nm_system_device_set_up_down (dev, FALSE, NULL); } NMDeviceEthernet * diff --git a/src/nm-device-private.h b/src/nm-device-private.h index 698f273197..97c8bff68e 100644 --- a/src/nm-device-private.h +++ b/src/nm-device-private.h @@ -34,9 +34,9 @@ void nm_device_state_changed (NMDevice *device, NMDeviceState state, NMDeviceStateReason reason); -gboolean nm_device_hw_bring_up (NMDevice *self, gboolean wait); +gboolean nm_device_hw_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmware); -void nm_device_hw_take_down (NMDevice *self, gboolean wait); +void nm_device_hw_take_down (NMDevice *self, gboolean block); void nm_device_handle_autoip4_event (NMDevice *self, const char *event, diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 744c3b0d7d..4011475772 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -797,15 +797,15 @@ real_hw_is_up (NMDevice *device) } static gboolean -real_hw_bring_up (NMDevice *dev) +real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) { - return nm_system_device_set_up_down (dev, TRUE); + return nm_system_device_set_up_down (dev, TRUE, no_firmware); } static void real_hw_take_down (NMDevice *dev) { - nm_system_device_set_up_down (dev, FALSE); + nm_system_device_set_up_down (dev, FALSE, NULL); } static gboolean @@ -3416,10 +3416,12 @@ nm_device_wifi_set_enabled (NMDeviceWifi *self, gboolean enabled) return; if (enabled) { + gboolean no_firmware = FALSE; + if (state != NM_DEVICE_STATE_UNAVAILABLE); nm_warning ("not in expected unavailable state!"); - if (!nm_device_hw_bring_up (NM_DEVICE (self), TRUE)) { + if (!nm_device_hw_bring_up (NM_DEVICE (self), TRUE, &no_firmware)) { /* The device sucks, or HAL was lying to us about the killswitch state */ priv->enabled = FALSE; return; diff --git a/src/nm-device.c b/src/nm-device.c index 37cb500496..6628bc374c 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -116,7 +116,7 @@ static gboolean nm_device_activate (NMDeviceInterface *device, static void nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self); static void nm_device_deactivate (NMDeviceInterface *device); -static gboolean nm_device_bring_up (NMDevice *self, gboolean wait); +static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware); static gboolean nm_device_is_up (NMDevice *self); static void @@ -480,6 +480,7 @@ nm_device_activate_stage2_device_config (gpointer user_data) const char * iface; NMActStageReturn ret; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + gboolean no_firmware = FALSE; /* Clear the activation source ID now that this stage has run */ if (self->priv->act_source_id > 0) @@ -489,8 +490,11 @@ nm_device_activate_stage2_device_config (gpointer user_data) nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) starting...", iface); nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); - if (!nm_device_bring_up (self, FALSE)) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + if (!nm_device_bring_up (self, FALSE, &no_firmware)) { + if (no_firmware) + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING); + else + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); goto out; } @@ -1044,7 +1048,7 @@ real_act_stage4_get_ip4_config (NMDevice *self, if (!*config) { /* Make sure device is up even if config fails */ - nm_device_bring_up (self, FALSE); + nm_device_bring_up (self, FALSE, NULL); } else ret = NM_ACT_STAGE_RETURN_SUCCESS; @@ -1946,7 +1950,7 @@ nm_device_is_up (NMDevice *self) } gboolean -nm_device_hw_bring_up (NMDevice *self, gboolean do_wait) +nm_device_hw_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) { gboolean success; guint32 tries = 0; @@ -1959,13 +1963,13 @@ nm_device_hw_bring_up (NMDevice *self, gboolean do_wait) nm_info ("(%s): bringing up device.", nm_device_get_iface (self)); if (NM_DEVICE_GET_CLASS (self)->hw_bring_up) { - success = NM_DEVICE_GET_CLASS (self)->hw_bring_up (self); + success = NM_DEVICE_GET_CLASS (self)->hw_bring_up (self, no_firmware); if (!success) return FALSE; } /* Wait for the device to come up if requested */ - while (do_wait && !nm_device_hw_is_up (self) && (tries++ < 50)) + while (block && !nm_device_hw_is_up (self) && (tries++ < 50)) g_usleep (200); if (!nm_device_hw_is_up (self)) { @@ -1983,7 +1987,7 @@ out: } void -nm_device_hw_take_down (NMDevice *self, gboolean do_wait) +nm_device_hw_take_down (NMDevice *self, gboolean block) { guint32 tries = 0; @@ -1998,18 +2002,18 @@ nm_device_hw_take_down (NMDevice *self, gboolean do_wait) NM_DEVICE_GET_CLASS (self)->hw_take_down (self); /* Wait for the device to come up if requested */ - while (do_wait && nm_device_hw_is_up (self) && (tries++ < 50)) + while (block && nm_device_hw_is_up (self) && (tries++ < 50)) g_usleep (200); } static gboolean -nm_device_bring_up (NMDevice *self, gboolean do_wait) +nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) { - gboolean success; + gboolean success = FALSE; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - if (!nm_device_hw_bring_up (self, do_wait)) + if (!nm_device_hw_bring_up (self, block, no_firmware)) return FALSE; if (nm_device_is_up (self)) @@ -2017,17 +2021,14 @@ nm_device_bring_up (NMDevice *self, gboolean do_wait) nm_info ("(%s): preparing device.", nm_device_get_iface (self)); - if (NM_DEVICE_GET_CLASS (self)->bring_up) { + if (NM_DEVICE_GET_CLASS (self)->bring_up) success = NM_DEVICE_GET_CLASS (self)->bring_up (self); - if (!success) - return FALSE; - } - return TRUE; + return success; } void -nm_device_take_down (NMDevice *self, gboolean do_wait) +nm_device_take_down (NMDevice *self, gboolean block) { g_return_if_fail (NM_IS_DEVICE (self)); @@ -2041,7 +2042,7 @@ nm_device_take_down (NMDevice *self, gboolean do_wait) NM_DEVICE_GET_CLASS (self)->take_down (self); } - nm_device_hw_take_down (self, do_wait); + nm_device_hw_take_down (self, block); } static void @@ -2287,6 +2288,7 @@ nm_device_state_changed (NMDevice *device, NMDevicePrivate *priv; NMDeviceState old_state; NMActRequest *req; + gboolean no_firmware = FALSE; g_return_if_fail (NM_IS_DEVICE (device)); priv = device->priv; @@ -2315,8 +2317,10 @@ nm_info ("(%s): device state change: %d -> %d", nm_device_get_iface (device), ol nm_device_take_down (device, TRUE); break; case NM_DEVICE_STATE_UNAVAILABLE: - if (old_state == NM_DEVICE_STATE_UNMANAGED) - nm_device_bring_up (device, TRUE); + if (old_state == NM_DEVICE_STATE_UNMANAGED) { + if (!nm_device_bring_up (device, TRUE, &no_firmware) && no_firmware) + nm_warning ("%s: firmware may be missing.", nm_device_get_iface (device)); + } /* Fall through, so when the device needs to be deactivated due to * eg carrier changes we actually deactivate it */ case NM_DEVICE_STATE_DISCONNECTED: diff --git a/src/nm-device.h b/src/nm-device.h index 6a04d596d4..9412a8f095 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -66,7 +66,7 @@ struct _NMDeviceClass /* Hardware state, ie IFF_UP */ gboolean (*hw_is_up) (NMDevice *self); - gboolean (*hw_bring_up) (NMDevice *self); + gboolean (*hw_bring_up) (NMDevice *self, gboolean *no_firmware); void (*hw_take_down) (NMDevice *self); /* Additional stuff required to operate the device, like a diff --git a/src/nm-hso-gsm-device.c b/src/nm-hso-gsm-device.c index d659dcba3d..009d80323f 100644 --- a/src/nm-hso-gsm-device.c +++ b/src/nm-hso-gsm-device.c @@ -361,13 +361,19 @@ real_act_stage4_get_ip4_config (NMDevice *device, { NMHsoGsmDevice *self = NM_HSO_GSM_DEVICE (device); NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (self); + gboolean no_firmware = FALSE; g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE); nm_device_set_ip_iface (device, priv->netdev_iface); - if (!nm_device_hw_bring_up (device, TRUE)) + if (!nm_device_hw_bring_up (device, TRUE, &no_firmware)) { + if (no_firmware) + *reason = NM_DEVICE_STATE_REASON_FIRMWARE_MISSING; + else + *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; + } *config = priv->pending_ip4_config; priv->pending_ip4_config = NULL; @@ -428,7 +434,7 @@ real_deactivate (NMDevice *device) if (priv->netdev_iface) { nm_system_device_flush_ip4_routes_with_iface (priv->netdev_iface); nm_system_device_flush_ip4_addresses_with_iface (priv->netdev_iface); - nm_system_device_set_up_down_with_iface (priv->netdev_iface, FALSE); + nm_system_device_set_up_down_with_iface (priv->netdev_iface, FALSE, NULL); } nm_device_set_ip_iface (device, NULL); @@ -453,7 +459,7 @@ real_hw_is_up (NMDevice *device) } static gboolean -real_hw_bring_up (NMDevice *device) +real_hw_bring_up (NMDevice *device, gboolean *no_firmware) { NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); NMDeviceState state; @@ -463,7 +469,7 @@ real_hw_bring_up (NMDevice *device) if ( priv->pending_ip4_config || (state == NM_DEVICE_STATE_IP_CONFIG) || (state == NM_DEVICE_STATE_ACTIVATED)) - return nm_system_device_set_up_down_with_iface (priv->netdev_iface, TRUE); + return nm_system_device_set_up_down_with_iface (priv->netdev_iface, TRUE, no_firmware); return TRUE; } diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 94424e9810..b073e977ef 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -829,7 +829,7 @@ connection_state_changed (NMVPNConnection *connection, } if (priv->tundev) { - nm_system_device_set_up_down_with_iface (priv->tundev, FALSE); + nm_system_device_set_up_down_with_iface (priv->tundev, FALSE, NULL); nm_system_device_flush_ip4_routes_with_iface (priv->tundev); nm_system_device_flush_ip4_addresses_with_iface (priv->tundev); }