pciio_error(D3)pciio_error(D3)NAME
pciio_error: pciio_error_register - PCI error handling function
SYNOPSIS
#include <sys/PCI/pciio.h>
#include <sys/ioerror.h>
int
pciio_error_register(
vertex_hdl_t vhdl,
error_handler_f *func,
error_handler_arg_t arg)
Arguments
vhdl The connection point of the PCI device, as passed to the driver's
attach() entry point.
func Address of a function to be called when an error is diagnosed on
a PIO to or a DMA from this PCI device.
arg A parameter to pass as the first argument to func().
DESCRIPTION
Some devices may, from time to time, either trigger a PIO error or
encounter a DMA error that is anticipated by the driver.
pciio_error_register() provides a mechanism whereby the driver can be
informed that such an error has occurred, and gives the driver the
ability to either recover from the error, or to do a more precise
diagnosis of the problem than is possible in the generic error handling
code.
There is no explicit unregistration function; to stop receiving error
reports, call pciio_error_register() with NULL values for func and arg.
The error handler for a device is typically registered at the same time
as an interrupt handler (as described in pciio_intr(D3)).
The error handler must be unregistered when a loadable driver is
unloaded. If this is not done, an error could cause the kernel to call
an error handler that no longer actually existed at the given address.
Although some drivers may connect and disconnect interrupt handlers in
their open() and close() entry points (see pciio_intr(D3)), there is no
benefit to doing this with an error handler. An error handler is
normally registered when the device is attached and unregistered when the
device is detached.
Handler Actions
The prototype of the error handling function is declared in sys/ioerror.h
along with the types of data that can be passed to the function. These
error codes, return codes, and fields within the ioerror structure may be
expanded from time to time.
Page 1
pciio_error(D3)pciio_error(D3)
The handler's first argument is supplied as arg. This is normally a
driver data structure unique to the device, containing the PIO maps, DMA
maps, and other global data needed to control the device.
The error handler has responsibilities in two directions: to the kernel,
to handle the error in such a way as to have the least impact on other
devices and on system performance; and to the rest of the device driver,
to properly terminate pending operations so that driver threads do not
sleep indefinitely, memory is not leaked, and so that a reasonable error
code is returned for a pending user-process read or write. Drivers that
support the poll() entry point must also consider whether to call
pollwakeup() on an error; for example, a nonrecoverable error is a
POLLERR event.
The error handler reports its success to the kernel in its return code:
IOERROR_HANDLED
The handler has noticed, logged, and dealt with the error.
No further system log entries or console messages are wanted.
If the error was detected on a synchronous operation (for
example a bus error on a PIO load or store) the operation
will be reexecuted. It is still possible that an
intermediate layer could declare the error to be fatal; for
instance, if a PCI device initiated a DMA and subsequently
reported a recoverable error, but the root cause was an
unrecoverable error elsewhere in the system.
IOERROR_UNHANDLED
The handler did not do anything, possibly because the error
did not really relate to the given driver, or because default
error handling is sufficient -- most error handlers really
exist only to notice errors that their devices can recover
from. The calling infrastructure will continue processing
just as if the error handler did not exist.
IOERROR_PANIC
The handler has done the primary diagnosis of the problem,
and printed out some descriptive information. As the error
handling substructure unwinds back toward the hardware that
reported the error, various portions of the system state
relating to the error will be reported, and upon return to
the outermost layer, the system will panic.
EXAMPLES
Here is an example of how a driver might set up an error handler.
pcifoo_attach(vertex_hdl_t pconn_vhdl)
{
...
pciio_error_register(pconn_vhdl
pcifoo_error_handler,
pcifoo_soft);
Page 2
pciio_error(D3)pciio_error(D3)
...
}
static int
pcifoo_error_handler(error_handler_arg_t einfo,
int error_code,
ioerror_mode_t mode,
ioerror_t *ioe)
{
...
if (recoverable) {
recover the error;
return IOERROR_HANDLED;
}
diagnose the error into the console log;
return IOERROR_PANIC;
}
SEE ALSOpciio(D3), pciio_config(D3), pciio_dma(D3), pciio_get(D3),
pciio_intr(D3), pciio_pio(D3).
Page 3