Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
15.  SCSI Host Bus Adapter Drivers SCSA HBA Entry Points Capability Management tran_setcap() Entry Point  Previous   Contents   Next 
   
 

Abort and Reset Management

The following sections discuss the abort and reset entry points for SCSI HBA.

tran_abort() Entry Point

The tran_abort(9E) entry point for a SCSI HBA driver is called to abort one or all the commands currently in transport for a particular target. This entry point is called when a target driver calls scsi_abort(9F).

The tran_abort() entry point should attempt to abort the command denoted by the pkt parameter. If the pkt parameter is NULL, tran_abort() should attempt to abort all outstanding commands in the transport layer for the particular target or logical unit.

Each command successfully aborted must be marked with pkt_reason CMD_ABORTED and pkt_statistics OR'd with STAT_ABORTED.

tran_reset() Entry Point

The tran_reset(9E) entry point for a SCSI HBA driver is called to reset either the SCSI bus or a particular SCSI target device. This entry point is called when a target driver calls scsi_reset(9F).

The tran_reset() entry point must reset the SCSI bus if level is RESET_ALL. If level is RESET_TARGET, just the particular target or logical unit must be reset.

Active commands affected by the reset must be marked with pkt_reason CMD_RESET, and with pkt_statistics OR'd with either STAT_BUS_RESET or STAT_DEV_RESET, depending on the type of reset.

Commands in the transport layer, but not yet active on the target, must be marked with pkt_reason CMD_RESET, and pkt_statistics OR'd with STAT_ABORTED.

tran_bus_reset() Entry Point

tran_bus_reset(9E) must reset the SCSI bus without resetting targets.

#include <sys/scsi/scsi.h>

int tran_bus_reset(dev_info_t *hba_dip, int level);

Where level must be the following:

RESET_BUS

Reset the SCSI bus only, not the targets

The tran_bus_reset() vector in the scsi_hba_tran(9S) structure should be initialized during the HBA driver's attach(9E) to point to an HBA entry point to be called when a user initiates a bus reset.

Implementation is hardware specific. If it cannot reset the SCSI bus without affecting the targets, the HBA driver should fail RESET_BUS or not initialize this vector.

tran_reset_notify() Entry Point

The tran_reset_notify(9E) entry point for a SCSI HBA driver is called to request that the HBA driver notify the target driver by callback when a SCSI bus reset occurs.


Example 15-12 HBA Driver tran_reset_notify(9E) Entry Point

isp_scsi_reset_notify(
    struct scsi_address     *ap,
    int                     flag,
    void                    (*callback)(caddr_t),
    caddr_t                 arg)
{
    struct isp              *isp;
    struct isp_reset_notify_entry    *p, *beforep;
    int                              rval = DDI_FAILURE;

    isp = (struct isp *)ap->a_hba_tran->tran_hba_private;

    mutex_enter(ISP_REQ_MUTEX(isp));

    /*
     * Try to find an existing entry for this target
     */
    p = isp->isp_reset_notify_listf;
    beforep = NULL;

    while (p) {
        if (p->ap == ap)
            break;
        beforep = p;
        p = p->next;
    }

    if ((flag & SCSI_RESET_CANCEL) && (p != NULL)) {
        if (beforep == NULL) {
            isp->isp_reset_notify_listf = p->next;
        } else {
            beforep->next = p->next;
        }
        kmem_free((caddr_t)p, sizeof (struct
                    isp_reset_notify_entry));
        rval = DDI_SUCCESS;

    } else if ((flag & SCSI_RESET_NOTIFY) && (p == NULL)) {
        p = kmem_zalloc(sizeof (struct isp_reset_notify_entry),
                KM_SLEEP);
        p->ap = ap;
        p->callback = callback;
        p->arg = arg;
        p->next = isp->isp_reset_notify_listf;
        isp->isp_reset_notify_listf = p;
        rval = DDI_SUCCESS;
    }

    mutex_exit(ISP_REQ_MUTEX(isp));

    return (rval);
} 

Dynamic Reconfiguration

To support the minimal set of hot-plugging operations, drivers might need to implement support for bus quiesce, bus unquiesce, and bus reset. The scsi_hba_tran(9S) structure supports these operations. If quiesce/unquiesce/reset is not required by hardware, no driver changes are needed.

The scsi_hba_tran structure includes the following fields:

        int (*tran_quiesce)(dev_info_t *hba_dip);
        int (*tran_unquiesce)(dev_info_t *hba_dip);
        int (*tran_bus_reset)(dev_info_t *hba_dip, int level);

These interfaces quiesce and unquiesce a SCSI bus.

        #include <sys/scsi/scsi.h>

        int prefixtran_quiesce(dev_info_t *hba_dip);

        int prefixtran_unquiesce(dev_info_t *hba_dip);

tran_quiesce(9E) and tran_unquiesce(9E) must be implemented by an HBA driver to support dynamic reconfiguration (DR) of SCSI devices on buses that were not designed to support hot-plugging.

The tran_quiesce(9E) and tran_unquiesce(9E) vectors in the scsi_hba_tran(9S) structure should be initialized during the HBA driver's attach(9E) to point to HBA entry points so they are called when a user initiates quiesce and unquiesce operations.

tran_quiesce(9E) is called by the SCSA framework to stop all activity on a SCSI bus prior to and during the reconfiguration of devices attached to the SCSI bus. tran_unquiesce(9E) is called by the SCSA framework to resume activity on the SCSI bus after the reconfiguration operation has been completed.

HBA drivers are required to handle tran_quiesce(9E) by waiting for all outstanding commands to complete before returning success. After the HBA has quiesced the bus, it must queue any new I/O requests from target drivers until the SCSA framework calls the corresponding tran_unquiesce(9E) entry point.

HBA drivers handle calls to tran_unquiesce(9E) by starting any target driver I/O requests that were queued by the HBA during the time the bus was quiesced.

 
 
 
  Previous   Contents   Next