Skip to content

Commit

Permalink
[pcie] Rip out kernel mode pcie drivers.
Browse files Browse the repository at this point in the history
Get rid of the concept of kernel mode pcie drivers.  Start to lay the
groundwork for re-defining the concept of "claimed" in order to allow
user mode code to hold multiple references to a PCI device, at most
one of which may have the device claimed at any point in time.

Change-Id: I7596de831f40feca6f846c5f78d5f9283a673abc
  • Loading branch information
johngro committed Nov 1, 2016
1 parent 27bdfd9 commit 544684b
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 346 deletions.
13 changes: 6 additions & 7 deletions kernel/dev/pcie/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ static void dump_pcie_hdr(const pcie_device_state_t& dev, lspci_params_t* params
if (dev.disabled)
printf(" [DISABLED]");

if (dev.driver)
printf(" [driver = \"%s\"]", pcie_driver_name(dev.driver));
if (dev.claimed)
printf(" [CLAIMED]");

printf("\n");
}
Expand Down Expand Up @@ -612,9 +612,8 @@ static int cmd_pciunplug(int argc, const cmd_args *argv)
if (!dev) {
printf("Failed to find PCI device %02x:%02x.%01x\n", bus_id, dev_id, func_id);
} else {
printf("Shutting down and unplugging PCI device %02x:%02x.%x (%s)...\n",
bus_id, dev_id, func_id, pcie_driver_name(dev->driver));
pcie_shutdown_device(dev);
printf("Unplugging PCI device %02x:%02x.%x...\n",
bus_id, dev_id, func_id);
dev->Unplug();
dev = nullptr;
printf("done\n");
Expand Down Expand Up @@ -673,7 +672,7 @@ static int cmd_pcirescan(int argc, const cmd_args *argv)
if (bus_drv == nullptr)
return ERR_BAD_STATE;

bus_drv->ScanAndStartDevices();
bus_drv->ScanDevices();

return NO_ERROR;
}
Expand All @@ -683,7 +682,7 @@ STATIC_COMMAND("lspci",
"Enumerate the devices detected in PCIe ECAM space",
&cmd_lspci)
STATIC_COMMAND("pciunplug",
"Unplug the specified PCIe device (shutting down the driver if needed)",
"Force \"unplug\" the specified PCIe device",
&cmd_pciunplug)
STATIC_COMMAND("pcireset",
"Initiate a Function Level Reset of the specified device.",
Expand Down
97 changes: 4 additions & 93 deletions kernel/dev/pcie/include/dev/pcie.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ struct pcie_config_t {
} __PACKED;

/* Fwd decls */
struct pcie_driver_registration;
struct pcie_legacy_irq_handler_state;

struct pcie_bridge_state_t;
struct pcie_device_state_t;

Expand All @@ -51,58 +49,6 @@ struct pcie_bar_info_t {
RegionAllocator::Region::UPtr allocation;
};

/* Function table registered by a device driver. Method requirements and device
* lifecycle are described below.
*
* + pcie_probe_fn
* Called by the bus driver during bus scanning/probing to determine which
* registered driver (if any) wishes to claim and manage a device. Drivers
* who wish to claim a device must return a non-NULL void* context pointer
* which will be made available as the driver_ctx member of the
* pcie_device_state_t structure and provided to subsequent callbacks via
* the pci_device member.
*
* + startup_hook
* Called by the bus driver in order to start a device after it has been
* claimed. All MMIO/PIO registers will be allocated, but un-mapped in at the
* time the startup hook is invoked, and the device IRQ will be masked.
* Devices should not enable their IRQ during startup. Device IRQs will be
* automatically enabled at the PCI level following a successful startup if a
* device has registered an IRQ hook.
*
* + shutdown_hook
* Called by the bus driver on a successfully started device when it is time
* to shut down. Device registers are guaranteed to be mapped when shutdown
* is called. Shutdown will not be called for devices who fail to start-up,
* so devices which encounter problems during start-up should take care to
* leave their device in a quiescent state before returning their error code
* to the bus driver. Devices may use pcie_enable_irq to mask their IRQ and
* synchronize with the bus's IRQ dispatcher at the appropriate point in their
* shutdown sequence.
*
* + release_hook
* Called on a non-started device when it is time to release any resources
* which may have been allocated during its life cycle. At a minimum, drivers
* who dynamically allocate context during pcie_probe_fn should register a
* release_hook in order to clean up their dynamically allocated resources. A
* driver's release hook will always be called if the driver attempted to
* claim a device during probe. Note that it is possible that the device was
* never started, or possibly never even claimed (due to hotplug or
* multithreaded races). Drivers should use the only as a chance to free any
* internal state associated with an attempt to claim a device.
*/
typedef struct pcie_driver_fn_table {
void* (*pcie_probe_fn) (const mxtl::RefPtr<pcie_device_state_t>& pci_device);
status_t (*pcie_startup_fn) (const mxtl::RefPtr<pcie_device_state_t>& pci_device);
void (*pcie_shutdown_fn)(const mxtl::RefPtr<pcie_device_state_t>& pci_device);
void (*pcie_release_fn) (void* ctx);
} pcie_driver_fn_table_t;

typedef struct pcie_driver_registration {
const char* name;
const pcie_driver_fn_table_t* fn_table;
} pcie_driver_registration_t;

/*
* Struct used to manage the relationship between a PCIe device/function and its
* associated driver. During a bus scan/probe operation, all drivers will have
Expand Down Expand Up @@ -138,14 +84,9 @@ struct pcie_device_state_t : public mxtl::RefCounted<pcie_device_state_t> {

/* State related to lifetime management */
mutable Mutex dev_lock;
mutable Mutex start_claim_lock;
bool plugged_in;
bool disabled;

/* State tracking for this device's driver (if this device has been claimed by a driver) */
const pcie_driver_registration_t* driver;
void* driver_ctx;
bool started;
bool claimed;

/* Info about the BARs computed and cached during the initial setup/probe,
* indexed by starting BAR register index */
Expand Down Expand Up @@ -284,15 +225,12 @@ mxtl::RefPtr<pcie_device_state_t> pcie_get_nth_device(uint32_t index);
* Attaches a driver to a PCI device. Returns ERR_ALREADY_BOUND if the device has already been
* claimed by another driver.
*/
status_t pcie_claim_and_start_device(const mxtl::RefPtr<pcie_device_state_t>& device,
const pcie_driver_registration_t* driver,
void* driver_ctx);
status_t pcie_claim_device(const mxtl::RefPtr<pcie_device_state_t>& device);

/*
* Shutdown and unclaim a device had been successfully claimed with
* pcie_claim_and_start_device()
* Unclaim a device had been successfully claimed with pcie_claim_device().
*/
void pcie_shutdown_device(const mxtl::RefPtr<pcie_device_state_t>& device);
void pcie_unclaim_device(const mxtl::RefPtr<pcie_device_state_t>& device);

/*
* Trigger a function level reset (if possible)
Expand Down Expand Up @@ -385,30 +323,3 @@ static inline status_t pcie_enable_mmio(const mxtl::RefPtr<pcie_device_state_t>&
enabled ? 0 : PCI_COMMAND_MEM_EN,
enabled ? PCI_COMMAND_MEM_EN : 0);
}

/*
* Simple inline helper which fetches a device driver's name, or substitutes
* "<unknown>" if the driver didn't supply a name, or for some mysterious
* reason, is NULL.
*/
static inline const char* pcie_driver_name(const pcie_driver_registration_t* driver) {
return (driver && driver->name) ? driver->name : "<unknown>";
}

#if WITH_DEV_PCIE
#define STATIC_PCIE_DRIVER(var_name, drv_name, drv_fn_table) \
extern const pcie_driver_registration_t __pcie_drv_reg_##var_name; \
const pcie_driver_registration_t __pcie_drv_reg_##var_name \
__ALIGNED(sizeof(void *)) __SECTION("pcie_builtin_drivers") = \
{ \
.name = drv_name, \
.fn_table = &drv_fn_table, \
};
#else // WITH_DEV_PCIE
#define STATIC_PCIE_DRIVER(var_name, drv_name, drv_fn_table)
#endif // WITH_DEV_PCIE

/**
* Temporary hack; do not use!
*/
void pcie_rescan_bus(void);
2 changes: 1 addition & 1 deletion kernel/dev/pcie/include/dev/pcie_bus_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class PcieBusDriver : public mxtl::RefCounted<PcieBusDriver> {

// TODO(johngro) : Make these private when we can.
void ForeachDevice(ForeachCallback cbk, void* ctx);
void ScanAndStartDevices();
void ScanDevices();
mxtl::RefPtr<SharedLegacyIrqHandler> FindLegacyIrqHandler(uint irq_id);
// TODO(johngro) : end TODO section

Expand Down
Loading

0 comments on commit 544684b

Please sign in to comment.