Page MenuHomeFreeBSD

newbus: Only call suspend / resume for attached devices
Needs ReviewPublic

Authored by imp on Wed, Nov 20, 5:57 PM.
Tags
None
Referenced Files
Unknown Object (File)
Mon, Dec 2, 10:06 AM
Unknown Object (File)
Mon, Dec 2, 5:32 AM
Unknown Object (File)
Mon, Dec 2, 3:21 AM
Unknown Object (File)
Sat, Nov 30, 1:14 AM
Unknown Object (File)
Sat, Nov 23, 1:32 AM
Subscribers

Details

Reviewers
adrian
jhb
Summary

If a device is disabled, then it will be in state DS_ALIVE with an
attached method table, but most drivers can't handle calls to anything
other than the attach method until the attach method completes
successfully. Don't call suspend / resume if the driver isn't completely
attached.

Sponsored by: Netflix

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 60710
Build 57594: arc lint + arc unit

Event Timeline

imp requested review of this revision.Wed, Nov 20, 5:57 PM
This revision is now accepted and ready to land.Wed, Nov 20, 5:59 PM
sys/kern/subr_bus.c
3572

So is this the right test, or device_is_enabled?

Hmm, I'm not sure this is what you want. I think you want bus drivers able to still perform bus-specific actions during system suspend, e.g. PCI might want to power down devices that don't have an attached driver.

I think instead what you want to do is patch bus_generic_suspend_child and bus_generic_resume_child perhaps like so:

/**
 * @brief Default function for suspending a child device.
 *
 * This function is to be used by a bus's DEVICE_SUSPEND_CHILD().
 */
int
bus_generic_suspend_child(device_t dev, device_t child)
{
	int	error;

+	if (!device_is_attached(child))
+		return (0);

	error = DEVICE_SUSPEND(child);

	if (error == 0) {
		child->flags |= DF_SUSPENDED;
	} else {
		printf("DEVICE_SUSPEND(%s) failed: %d\n",
		    device_get_nameunit(child), error);
	}

	return (error);
}

/**
 * @brief Default function for resuming a child device.
 *
 * This function is to be used by a bus's DEVICE_RESUME_CHILD().
 */
int
bus_generic_resume_child(device_t dev, device_t child)
{
+	if ((child->flags & DF_SUSPENDED) != 0) {
+		DEVICE_RESUME(child);
+		child->flags &= ~DF_SUSPENDED;
+	}
-	DEVICE_RESUME(child);
-	child->flags &= ~DF_SUSPENDED;

	return (0);
}

jhb's suggestion, if I understand it

This revision now requires review to proceed.Wed, Nov 20, 9:41 PM

Tested by me, works 10/10 thanks