The kernel calls a driver's detach(9E) entry point to detach an instance of a device or to suspend operation for an instance of a device by power management. This section discusses the operation of detaching device instances. Refer to Chapter 9, Power Management for a discussion of power management issues.
A driver's detach() entry point is called to detach an instance of a device that is bound to the driver. The entry point is called with the instance of the device node to detach and DDI_DETACH specified as the cmd argument to the entry point.
A driver is required to cancel or wait for any time-outs or callbacks to complete, then release any resources that are allocated to the device instance before returning. If for some reason a driver cannot cancel outstanding callbacks for free resources, the driver is required to return the device to its original state and return DDI_FAILURE from the entry point, leaving the device instance in the attached state.
There are two types of callback routines: those that can be canceled and those that cannot. timeout(9F) and bufcall(9F) callbacks can be atomically cancelled by the driver during detach(9E). Other types of callbacks such as scsi_init_pkt(9F) and ddi_dma_buf_bind_handle(9F) cannot be canceled, requiring the driver to either block in detach() until the callback completes or to fail the request to detach.
/* * detach(9e) * free the resources that were allocated in attach(9e) */ static int xxdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) { Pio *pio_p; int instance; switch (cmd) { case DDI_DETACH: instance = ddi_get_instance(dip); pio_p = ddi_get_soft_state(pio_softstate, instance); /* * turn off the device * free any resources allocated in attach */ ddi_put8(pio_p->csr_handle, pio_p->csr, PIO_RESET); ddi_remove_minor_node(dip, NULL); ddi_regs_map_free(&pio_p->csr_handle); ddi_regs_map_free(&pio_p->data_handle); ddi_remove_intr(pio_p->dip, 0, pio_p->iblock_cookie); mutex_destroy(&pio_p->mutex); ddi_soft_state_free(pio_softstate, instance); return (DDI_SUCCESS); case DDI_SUSPEND: default: return (DDI_FAILURE); } }