Contenues dansTrouver plus de documentationRessources d'assistance comprises | Télécharger cet ouvrage au format PDF (1004 Ko)
Appendix H Converting Device Drivers to Support HotpluggingThis appendix provides the information device driver writers need to convert device drivers to be hotplug-capable, which is applicable to the Solaris 7 operating environment. IntroductionThis appendix offers a basic guide to writing drivers which can function in a hotplugging environment. The focus is on bus interfaces which provide a controlled environment for hot removal and insertion of cards. The focus is on bus interfaces which provide a controlled environment for hot removal and insertion of cards. Before you can convert a driver to be hotplug-capable, you need to understand hotplug scenarios and how they affect device drivers. "Solaris Hotplugging Driver Issues" describes the requirements on device drivers and the flow of control during hot removal and insertion. "Hotplug-Capable Device Driver Development" outlines the steps required to make a device driver hotplug-capable. "Device Driver Testing" provides guidelines for testing hotplug-capable device drivers in Solaris 7. For more information refer to the Solaris Sample Drivers. This package contains a number of sample drivers that are hotplug-capable and provide greater insight into the process. Overview of HotpluggingThis section summarizes the sequence of events in hot removal and hot insertion that are relevant to the device driver. Hotplugging typically involves:
Hot Removal With No ReplacementThis operation is used to remove a card. You may want to remove a card because, for example, its failure mode affects system operation. To perform a hotplug removal:
Hot InsertionThis procedure is used to insert a card in a previously unused slot.
Hot Removal Followed by InsertionThis procedure is used to replace a card with either an identical or a different card.
Solaris Hotplugging Driver IssuesThis section describes the flow of control from a device driver perspective. Most device drivers can support hotplugging with minimal changes. Hot RemovalThe kernel checks the driver state, and if the driver instance is not open, the kernel can invoke the driver's detach(9E) entry point with the command DDI_DETACH. The driver instance checks its internal state and verifies whether it is safe to detach. If so, the driver frees resources, cancels timeouts, and returns success. At this point, the kernel can remove power from the slot and the hardware can be removed. Hot InsertionHot insertion uses the normal probe(9E) and attach(9E) entry points of a driver after the hardware has been inserted into the slot in a controlled manner. Hotplug-Capable Device Driver DevelopmentThis section briefly discusses how to make Solaris device drivers compliant with the new Solaris technologies of Dynamic Reconfiguration and future Solaris hotplug technologies. D_HOTPLUG FlagHotplug-capable drivers should set D_HOTPLUG in their cb_ops cb_flag. Detach Entry PointThe driver's detach entry point can be called with these commands:
It is strongly recommended to fully implement support for all detach commands. Note the following uses are possible:
During Dynamic Reconfiguration, there are two possible detach scenarios.
DDI_DETACH CommandThe DDI_DETACH operation is the inverse of DDI_ATTACH. The DDI_DETACH handling should only deallocate the data structures for the specified instance. Driver global resources must only be deallocated in _fini(9E). Since instances are assigned in arbitrary order, the driver must be able to handle out-of-sequence presentation of instances. In fact, no assumption should be made about the instance number. The DDI_DETACH command code should perform the following actions.
When there is failure during detach, the driver must decide whether to continue the detach and return success or undo the detach actions completed to that point and return failure. Undoing might be risky and it is usually preferable to continue the detach operation. DDI_DETACH may be followed by power interruption; any further references to the device will need to be preceeded by a DDI_ATTACH. Note the following when using timeout() routines:
The timeout routine should take the form of: static void
XX_timeout(caddr_t arg)
{
struct xx *un = (struct un *)arg;
mutex_enter(&un->un_lock);
.....
XX_start_timeout(un);
mutex_exit(&un->un_lock);
}
static void
XX_start_timeout(struct xx *un)
{
ASSERT(MUTEX_HELD(&un->un_lock));
if ((un->un_tid == 0) && ((un->un_flags & XXSTOP) ==
0)){un->un_tid = timeout(XX_to, arg, ticks);
}
}
static void
XX_stop_timeout(struct xx *un)
{
int tid;
mutex_enter(&un->un_lock);
if ((tid = un->un_tid) != 0) {
/* do not reschedule timeout */
un->un_flags |= XXSTOP;
/* do not hold across untimeout() */
mutex_exit(&un->un_lock);
(void) untimeout(tid);
mutex_enter(&un->un_lock);
un->un_flags &= ~XXSTOP;
mutex_exit(&un->un_lock);
} else {
mutex_exit(&un->un_lock);
}
}
When deallocating memory, always verify first that the pointer is valid: #if NONONONO
kmem_free(un->un_buf, un->un_buf_len);
#else
if (un->un_buf) {
kmem_free(un->un_buf, un->un_buf_len);
un->un_buf = NULL;
}
#endif
DDI_SUSPEND CommandSystem power management and the Dynamic Reconfiguration framework pass the command DDI_SUSPEND to the detach(9E) driver entry point to request that the driver save the device hardware state. The driver may fail the suspend operation if outstanding operations cannot be completed soon or aborted, or if non-cancellable callbacks are outstanding, in which case the system will abort the suspend operation. Note that the driver instance may already have been power managed using DDI_PM_SUSPEND. To process the DDI_SUSPEND command, the driver must:
DDI_SUSPEND is always followed by DDI_RESUME. There may or may not be power interruption. Attach Entry PointThe system calls attach(9E) to attach a device instance to the system or to resume operation after power has been suspended. The driver's attach(9E) entry point should handle these commands:
DDI_PM_RESUME CommandWhen power is restored to the device that was suspended with DDI_PM_SUSPEND, that device is resumed using the DDI_PM_RESUME command. The device driver should restore the hardware state, set up timeouts again if necessary, and enable interrupts again. The DDI_PM_RESUME code should make no assumptions about the state of the hardware, which may or may not have lost power. DDI_RESUME CommandWhen power is restored to the system or the system is unquiesced, each device that was suspended will be resumed using the DDI_RESUME command. The device driver should restore the hardware state, set up timeouts again if necessary, and enable interrupts again. If the device is still suspended by DDI_PM_SUSPEND, the driver has to enter a state where it will call ddi_dev_is_needed(9F) for any new or pending requests, since an attach(9E) with DDI_PM_RESUME is still forthcoming. The resume code should make no assumptions about the state of the hardware, which may or may not have lost power. Special Issues With SCSI HBA DriversSCSI HBA drivers usually do not have a cb_ops(9S) structure, so to enable hotplugging, a minimal cb_ops(9S) structure must be created and exported in the dev_ops(9S). /*
* autoconfiguration routines.
*/
static struct dev_ops xx_dev_ops = {
....
&xx_cb_ops, /* devo_cb_ops */
....
};
static struct cb_ops xx_cb_ops = {
nodev, /* open */
nodev, /* close */
nodev, /* strategy */
nodev, /* print */
nodev, /* dump */
nodev, /* read */
nodev, /* write */
nodev, /* ioctl */
nodev, /* devmap */
nodev, /* mmap */
nodev, /* segmap */
nochpoll, /* poll */
nodev, /* cb_prop_op */
0, /* streamtab */
D_MP | D_HOTPLUG, /* Driver compatibility flag */
CB_REV, /* cb_rev */
nodev, /* async I/O read entry point */
nodev /* async I/O write entry point */
};
The DDI_DETACH and DDI_SUSPEND/RESUME requirements are very similar to those of leaf drivers described above. Device Driver TestingThis section provides some hints for driver testing. UnloadingThe driver should be able to sustain heavy driver activity, followed by module unload, without errors or memory leaks. This can be loop tested as follows (using C shell):
Alternatively:
Suspend/Resume TestingStart up a test on your driver and simultaneously run:
You can also test Suspend/Resume by generating I/O to your device, and then pressing the top-right button on the keyboard to suspend the machine. Then resume the machine; there should be no panics, error messages, or data corruption. If you have access to a server system that supports Dynamic Reconfiguration, you may also want to test your driver on this configuration. ConclusionThe Solaris 7 driver framework provides the necessary hooks to make drivers hotplug-capable with minimal changes to the driver code. If a driver already supports the detach commands DDI_DETACH and DDI_SUSPEND and the attach command DDI_RESUME, simply adding the D_HOTPLUG flag to the cb_ops cb_flag makes the driver hotplug-capable. |
|||