freebsd_network: Reinstate _fbsd_init_hardware and refactor probing.

Previously we just probed and then immediately attached if any devices
were found, after all initialization was done. Now we cannot do that,
as after calling SYSINIT() on certain drivers (e.g. the new ipro1000
driver), certain threads will be created that there is no good way
of tearing down.

Fortunately, it is valid to call probe() on a device before SYSINIT()
(and most other things) have been initialized, and so now we do that
in init_hardware, and then init_driver is called only if we've found
devices we support.

While we're at it, also call pci->reserve_device, which will mark us as
the driver handling said device and prevent other drivers from
using it.
This commit is contained in:
Augustin Cavalier 2019-01-03 15:40:18 -05:00
parent 83c8026372
commit db4f8332f0
2 changed files with 97 additions and 43 deletions

View File

@ -80,6 +80,7 @@ typedef struct {
__fbsd_ ## name ## _ ## busname
status_t _fbsd_init_hardware(driver_t *driver[]);
status_t _fbsd_init_drivers(driver_t *driver[]);
status_t _fbsd_uninit_drivers(driver_t *driver[]);
@ -106,7 +107,9 @@ status_t wlan_close(void*);
const char *gDriverName = #publicname; \
int32 api_version = B_CUR_DRIVER_API_VERSION; \
status_t init_hardware() \
{ return B_OK; } \
{ \
return __haiku_handle_fbsd_drivers_list(_fbsd_init_hardware); \
} \
status_t init_driver() \
{ \
return __haiku_handle_fbsd_drivers_list(_fbsd_init_drivers); \

View File

@ -37,8 +37,13 @@
#endif
const char *gDeviceNameList[MAX_DEVICES + 1];
struct ifnet *gDevices[MAX_DEVICES];
static struct {
driver_t* driver;
pci_info info;
} sProbedDevices[MAX_DEVICES];
const char* gDeviceNameList[MAX_DEVICES + 1];
struct ifnet* gDevices[MAX_DEVICES];
int32 gDeviceCount;
@ -98,22 +103,86 @@ get_pci_info(struct device *device)
status_t
_fbsd_init_drivers(driver_t *drivers[])
_fbsd_init_hardware(driver_t *drivers[])
{
status_t status;
int i = 0;
int index = 0;
pci_info *info;
int i = 0, p = 0, index = 0;
pci_info* info;
device_t root;
status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci);
if (status < B_OK)
if (status != B_OK)
return status;
// if it fails we just don't support x86 specific features (like MSIs)
if (get_module(B_PCI_X86_MODULE_NAME, (module_info **)&gPCIx86) != B_OK)
gPCIx86 = NULL;
status = init_root_device(&root);
if (status != B_OK)
return status;
for (p = 0; p <= MAX_DEVICES; p++)
sProbedDevices[i].driver = NULL;
p = 0;
for (info = get_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK;
i++) {
int best = 0;
driver_t* driver = NULL;
for (index = 0; drivers[index] && gDeviceCount < MAX_DEVICES; index++) {
int result;
device_t device = NULL;
status = add_child_device(drivers[index], root, &device);
if (status < B_OK)
break;
result = device->methods.probe(device);
if (result >= 0 && (driver == NULL || result > best)) {
TRACE(("%s, found %s at %d (%d)\n", gDriverName,
device_get_desc(device), i, result));
driver = drivers[index];
best = result;
}
device_delete_child(root, device);
}
if (driver == NULL)
continue;
// We've found a driver; now try to reserve the device and store it
if (gPci->reserve_device(info->bus, info->device, info->function,
gDriverName, NULL) != B_OK) {
dprintf("%s: Failed to reserve PCI:%d:%d:%d\n",
gDriverName, info->bus, info->device, info->function);
continue;
}
sProbedDevices[p].driver = driver;
sProbedDevices[p].info = *info;
p++;
}
device_delete_child(NULL, root);
if (p > 0)
return B_OK;
put_module(B_PCI_MODULE_NAME);
if (gPCIx86 != NULL)
put_module(B_PCI_X86_MODULE_NAME);
return B_NOT_SUPPORTED;
}
status_t
_fbsd_init_drivers(driver_t *drivers[])
{
status_t status;
int p = 0;
pci_info* info;
device_t root;
status = init_mutexes();
if (status < B_OK)
goto err2;
@ -143,46 +212,28 @@ _fbsd_init_drivers(driver_t *drivers[])
status = init_root_device(&root);
if (status != B_OK)
goto err7;
info = get_pci_info(root);
for (info = get_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK;
i++) {
int best = 0;
driver_t *driver = NULL;
for (p = 0; sProbedDevices[p].driver != NULL; p++) {
device_t device = NULL;
*info = sProbedDevices[p].info;
for (index = 0; drivers[index] && gDeviceCount < MAX_DEVICES; index++) {
int result;
device_t device;
status = add_child_device(drivers[index], root, &device);
if (status < B_OK)
break;
status = add_child_device(sProbedDevices[p].driver, root, &device);
if (status != B_OK)
break;
result = device->methods.probe(device);
if (result >= 0 && (driver == NULL || result > best)) {
TRACE(("%s, found %s at %d (%d)\n", gDriverName,
device_get_desc(device), i, result));
driver = drivers[index];
best = result;
}
device_delete_child(root, device);
}
if (driver != NULL) {
device_t device;
status = add_child_device(driver, root, &device);
// some drivers expect probe() to be called before attach()
// (i.e. they set driver softc in probe(), etc.)
if (device->methods.probe(device) >= 0
&& device_attach(device) == 0) {
dprintf("%s: init_driver(%p)\n", gDriverName,
sProbedDevices[p].driver);
status = init_root_device(&root);
if (status != B_OK)
break;
// some drivers expect probe() to be called before attach()
// (i.e. they set driver softc in probe(), etc.)
if (device->methods.probe(device) >= 0
&& device_attach(device) == 0) {
dprintf("%s: init_driver(%p) at %d\n", gDriverName, driver, i);
status = init_root_device(&root);
if (status != B_OK)
break;
info = get_pci_info(root);
} else
device_delete_child(root, device);
}
info = get_pci_info(root);
} else
device_delete_child(root, device);
}
if (gDeviceCount > 0)