Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_bus.c
Show First 20 Lines • Show All 205 Lines • ▼ Show 20 Lines | |||||
#define print_driver_list(d,i) /* nop */ | #define print_driver_list(d,i) /* nop */ | ||||
#define print_devclass_short(d,i) /* nop */ | #define print_devclass_short(d,i) /* nop */ | ||||
#define print_devclass(d,i) /* nop */ | #define print_devclass(d,i) /* nop */ | ||||
#define print_devclass_list_short() /* nop */ | #define print_devclass_list_short() /* nop */ | ||||
#define print_devclass_list() /* nop */ | #define print_devclass_list() /* nop */ | ||||
#endif | #endif | ||||
/* | /* | ||||
* Preferred device list. If there's a tie, and the driver is on this list, | |||||
* it will be the one that wins the tie. | |||||
*/ | |||||
static int sysctl_preferred(SYSCTL_HANDLER_ARGS); | |||||
static const char **preferred_drivers; | |||||
static int npref; | |||||
SYSCTL_PROC(_hw_bus, OID_AUTO, preferred, CTLTYPE_STRING | CTLFLAG_RWTUN | | |||||
CTLFLAG_MPSAFE, NULL, 0, sysctl_preferred, "A", "list of preferrred drivers"); | |||||
static int | |||||
sysctl_preferred(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
int error, len, newlen; | |||||
struct sbuf *sbuf; | |||||
char *buffer, *walk1, *walk2; | |||||
error = sysctl_wire_old_buffer(req, 0); | |||||
if (error != 0) | |||||
return (error); | |||||
sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req); | |||||
for (int i = 0; i < npref; i++) { | |||||
if (i > 0) | |||||
sbuf_putc(sbuf, ','); | |||||
sbuf_printf(sbuf, "%s", preferred_drivers[i]); | |||||
} | |||||
error = sbuf_finish(sbuf); | |||||
sbuf_delete(sbuf); | |||||
if (error || req->newptr == NULL) | |||||
return (error); | |||||
len = req->newlen - req->newidx; | |||||
if (len == 0) | |||||
return (0); | |||||
walk1 = buffer = malloc(len, M_BUS, M_ZERO | M_WAITOK); | |||||
error = SYSCTL_IN(req, buffer, len); | |||||
newlen = len; | |||||
npref = 1; | |||||
for (int i = 0; i < strlen(buffer); i++) | |||||
if (buffer[i] == ',') | |||||
npref++; | |||||
free(preferred_drivers, M_BUS); | |||||
preferred_drivers = malloc(newlen + npref * sizeof(const char *), | |||||
M_BUS, M_ZERO | M_WAITOK); | |||||
walk2 = (char *)(uintptr_t)preferred_drivers + npref * sizeof(const char *); | |||||
for (int i = 0; i < npref; i++) { | |||||
preferred_drivers[i] = walk2; | |||||
jhb: I feel like using strsep would be slightly shorter as it would do the null terminate for you? | |||||
len = strcspn(walk1, ","); | |||||
memcpy(walk2, walk1, len); | |||||
walk2[len] = '\0'; | |||||
walk1 += len + 1; | |||||
walk2 += len + 1; | |||||
} | |||||
free(buffer, M_BUS); | |||||
return (error); | |||||
} | |||||
/* | |||||
* dev sysctl tree | * dev sysctl tree | ||||
*/ | */ | ||||
enum { | enum { | ||||
DEVCLASS_SYSCTL_PARENT, | DEVCLASS_SYSCTL_PARENT, | ||||
}; | }; | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | |||||
* of this belongs to the root node. | * of this belongs to the root node. | ||||
*/ | */ | ||||
#define DEVCTL_DEFAULT_QUEUE_LEN 1000 | #define DEVCTL_DEFAULT_QUEUE_LEN 1000 | ||||
static int sysctl_devctl_queue(SYSCTL_HANDLER_ARGS); | static int sysctl_devctl_queue(SYSCTL_HANDLER_ARGS); | ||||
static int devctl_queue_length = DEVCTL_DEFAULT_QUEUE_LEN; | static int devctl_queue_length = DEVCTL_DEFAULT_QUEUE_LEN; | ||||
SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_queue, CTLTYPE_INT | CTLFLAG_RWTUN | | SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_queue, CTLTYPE_INT | CTLFLAG_RWTUN | | ||||
CTLFLAG_MPSAFE, NULL, 0, sysctl_devctl_queue, "I", "devctl queue length"); | CTLFLAG_MPSAFE, NULL, 0, sysctl_devctl_queue, "I", "devctl queue length"); | ||||
Done Inline ActionsI should likely not delete this line... I'll fix locally, but not update the review unless other changes are needed since it's so trivial. imp: I should likely not delete this line... I'll fix locally, but not update the review unless… | |||||
static d_open_t devopen; | static d_open_t devopen; | ||||
static d_close_t devclose; | static d_close_t devclose; | ||||
static d_read_t devread; | static d_read_t devread; | ||||
static d_ioctl_t devioctl; | static d_ioctl_t devioctl; | ||||
static d_poll_t devpoll; | static d_poll_t devpoll; | ||||
static d_kqfilter_t devkqfilter; | static d_kqfilter_t devkqfilter; | ||||
static struct cdevsw dev_cdevsw = { | static struct cdevsw dev_cdevsw = { | ||||
▲ Show 20 Lines • Show All 1,705 Lines • ▼ Show 20 Lines | if (dev->devclass) { | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
return (TAILQ_NEXT(last, link)); | return (TAILQ_NEXT(last, link)); | ||||
} | } | ||||
/** | /** | ||||
* @internal | * @internal | ||||
*/ | */ | ||||
static bool | |||||
driver_is_preferred(const char *name) | |||||
Not Done Inline Actionss/device/driver/? ("nvme" is a driver name, "nvme0" is a device name) jhb: s/device/driver/? ("nvme" is a driver name, "nvme0" is a device name) | |||||
Done Inline Actionssure. imp: sure. | |||||
{ | |||||
for (int i = 0; i < npref; i++) | |||||
if (strcmp(name, preferred_drivers[i]) == 0) | |||||
return (true); | |||||
return (false); | |||||
} | |||||
/** | |||||
* @internal | |||||
*/ | |||||
int | int | ||||
device_probe_child(device_t dev, device_t child) | device_probe_child(device_t dev, device_t child) | ||||
{ | { | ||||
devclass_t dc; | devclass_t dc; | ||||
driverlink_t best = NULL; | driverlink_t best = NULL; | ||||
driverlink_t dl; | driverlink_t dl; | ||||
int result, pri = 0; | int result, pri = 0; | ||||
/* We should preserve the devclass (or lack of) set by the bus. */ | /* We should preserve the devclass (or lack of) set by the bus. */ | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | for (dl = first_matching_driver(dc, child); | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* A priority lower than SUCCESS, remember the | * A priority lower than SUCCESS, remember the | ||||
* best matching driver. Initialise the value | * best matching driver. Initialise the value | ||||
* of pri for the first match. | * of pri for the first match. | ||||
*/ | */ | ||||
if (best == NULL || result > pri) { | if (best == NULL || result > pri || | ||||
(result == pri && driver_is_preferred(child->driver->name))) { | |||||
best = dl; | best = dl; | ||||
pri = result; | pri = result; | ||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* If we have an unambiguous match in this devclass, | * If we have an unambiguous match in this devclass, | ||||
* don't look in the parent. | * don't look in the parent. | ||||
▲ Show 20 Lines • Show All 3,867 Lines • Show Last 20 Lines |
I feel like using strsep would be slightly shorter as it would do the null terminate for you? I think there's even an example in the strsep() manpage that is kind of like this, something like: