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:
parent
83c8026372
commit
db4f8332f0
@ -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); \
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user