/*************************************************************************** * Copyright 2004 - 2012 VMware, Inc. All rights reserved. ***************************************************************************/ /* * @VMKAPIMOD_LICENSE@ */ /* *********************************************************************** * MPP */ /** * \addtogroup Storage * @{ * \defgroup MPP Multi-Pathing Plugin Interfaces * @{ *********************************************************************** */ #ifndef _VMKAPI_MPP_H_ #define _VMKAPI_MPP_H_ /** \cond never */ #ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H #error This vmkapi file should never be included directly but only via vmkapi.h #endif /** \endcond never */ #include "scsi/vmkapi_scsi.h" #include "scsi/vmkapi_scsi_mgmt_types.h" #include "scsi/vmkapi_scsi_ext.h" #include "scsi/vmkapi_scsi_const.h" #include "scsi/vmkapi_scsi_types.h" #include "mpp/vmkapi_mpp_types.h" /** \cond never */ #define VMK_SCSI_REVISION_MAJOR 1 #define VMK_SCSI_REVISION_MINOR 0 #define VMK_SCSI_REVISION_UPDATE 0 #define VMK_SCSI_REVISION_PATCH_LEVEL 0 #define VMK_SCSI_REVISION VMK_REVISION_NUMBER(VMK_SCSI) /** \endcond never */ /** \brief Max length of vendor name string including terminating nul. */ #define VMK_SCSI_VENDOR_NAME_LENGTH (VMK_SCSI_INQUIRY_VENDOR_LENGTH + 1) //** \brief Max length of model name string including terminating nul. */ #define VMK_SCSI_MODEL_NAME_LENGTH (VMK_SCSI_INQUIRY_MODEL_LENGTH + 1) /** \brief Default name used for unregistered devices */ #define VMK_SCSI_UNREGISTERED_DEV_NAME "Unregistered Device" /** * \brief Choices for probe rate for vmk_ScsiSwitchDeviceProbeRate. */ typedef enum { /** \brief For normal operation (once/5 Sec.) */ VMK_SCSI_PROBE_RATE_DEFAULT = 1, /** \brief Selected when the device is in APD (once/Sec.) */ VMK_SCSI_PROBE_RATE_FAST = 2 } vmk_ScsiDeviceProbeRate; /** * \brief Flags defined for vmk_ScsiSwitchDeviceProbeRate. */ typedef enum { /** \brief Revert to VMK_SCSI_PROBE_RATE_DEFAULT after next probe. */ VMK_SCSI_ONE_PROBE_ONLY = 0x00000001 } vmk_ScsiSetDeviceProbeRateOption; /* *********************************************************************** * vmk_ScsiGetCachedPathStandardUID -- */ /** * * \ingroup MPP * * \brief Get the cached NAA, EUI, IQN, or TIO UID for physical path. * * The function returns the cached UID saved with the path as recorded * during the last rescan (since rescans will cause UIDs of all paths * to be verified). Success may be returned even if the path to the * device is not working. Plugins can use this API function in the * plugin's \em pathClaim entrypoint. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] path Path to obtain cached UID for. * \param[out] uid Obtained UID on success. * * \retval VMK_BAD_PARAM The passed in path or uid was null. * \retval VMK_FAILURE The path does not have a standard UID. * \retval VMK_OK Otherwise. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiGetCachedPathStandardUID( vmk_ScsiPath *path, vmk_ScsiUid *uid); /* *********************************************************************** * vmk_ScsiReadPathStandardUID -- */ /** * * \ingroup MPP * * \brief Read the NAA, EUI, IQN, or TIO UID for physical path from * the device. * * This function reads the UID from the SCSI device logical unit * that the path refers to and will return failure if the path is * not working. This API function is useful to check whether the UID * for a given path has changed; for example, in the plugin's * \em pathProbe entrypoint. * * \note This will regenerate the UID saved with the path. * \note This is a blocking call. * * \param[in] path Path to acquire standard UID for. * \param[out] uid Obtained UID on success. * * \retval VMK_OK The UID was successfully obtained. * \retval VMK_BAD_PARAM The passed in path or uid was null. * \retval VMK_MEDIUM_NOT_FOUND Bad SCSI version or device class * \retval VMK_UID_CHANGED Path is connected but the existing * devclass has changed. This may indicate * a change in the existing device. * \retval VMK_PERM_DEV_LOSS LUN is no longer connected * \retval Other Failed to obtain the UID. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiReadPathStandardUID( vmk_ScsiPath *path, vmk_ScsiUid *uid); /* *********************************************************************** * vmk_ScsiVerifyPathUID -- */ /** * * \ingroup MPP * * \brief Re-read path standard or legacy UID and verify that * it did not change. * * This function will reread the standard path UID from the device and * compare it against the cached UID obtained during the last rescan. * * \note This is a blocking call. * * \param[in] path Path to check UID for. * \param[out] uid UID read from disk. * * \retval VMK_OK UID was generated and did not change. * \retval VMK_UID_CHANGED New UID was detected. * \retval VMK_PERM_DEV_LOSS LUN is no longer connected. * \retval VMK_NO_CONNECT Path connectivity has failed. * \retval VMK_BAD_PARAM vmkPath or uid is NULL. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiVerifyPathUID( vmk_ScsiPath *path, vmk_ScsiUid *uid); /* *********************************************************************** * vmk_ScsiComputeUidFromEvpd83 -- */ /** * * \ingroup MPP * * \brief Get NAA, EUI, IQN, or TIO UID for physical device using * caller supplied inquiry evpd page 0x83 data. * * This function will compute the UID from the passed in evpd83Buf. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note The size of the \em evpd83Buf has to to be at least as big as * indicated by its 16-bit page length field. * * \param[in] vmkPath Path to acquire inquiry evpd page 0x83. * \param[in] evpd83Buf Buffer to store evpd page 0x83 data. * \param[out] uid UID. * * \retval VMK_OK UID was generated and did not change. * \retval VMK_FAILURE No usable UID type (NAA/EUI/IQN/T10) * was found in the passed buffer. *********************************************************************** */ VMK_ReturnStatus vmk_ScsiComputeUidFromEvpd83( vmk_ScsiPath *vmkPath, vmk_uint8 *evpd83Buf, vmk_ScsiUid *uid); /* *********************************************************************** * vmk_ScsiGetPathTransportUID -- */ /** * * \ingroup MPP * * \brief Get Path Transport UID for the physical path. * * This function will obtain a pair of UIDs - one UID for the HBA * endpoint and one for the target endpoint of the path. The UID is * transport dependent - for FC each endpoint will be of the form * WWNN:WWPN and for other transports each endpoint will be whatever * unique identifier is used in place for traditional target IDs * (e.g. for iSCSI each endpoint will be an IQN). * * \note This is a non-blocking call. * * \note This call will fail during device unregistration and removal; * as soon as the device state changes to VMK_SCSI_DEVICE_STATE_QUIESCED * the device will become effectively invisible. * * \param[in] path Path to acquire transport uids for. * \param[out] uid Obtained UIDs on success. * * \retval VMK_OK UID successfully obtained. * \retval VMK_BAD_PARAM Either path or uid is NULL. * \retval VMK_NOT_FOUND The UIDs could not be obtained. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiGetPathTransportUID( vmk_ScsiPath *path, vmk_ScsiPathUid *uid); /* *********************************************************************** * vmk_ScsiUIDsAreEqual -- */ /** * * \ingroup MPP * * \brief compare two uids and return true if they are equal. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] uid1 First UID to compare. * \param[in] uid2 Second UID to compare. * * \retval VMK_TRUE The UIDs are equal. * \retval VMK_FALSE The UIDs are not equal. * *********************************************************************** */ vmk_Bool vmk_ScsiUIDsAreEqual( vmk_ScsiUid *uid1, vmk_ScsiUid *uid2); /* *********************************************************************** * vmk_ScsiAllocateDevice -- */ /** * * \ingroup MPP * * \brief Allocate a logical storage device data structure. * * This function will allocate space for a vmk_ScsiDevice structure. * Obtaining this structure also ensure that the call to register * the device will not fail due to max. number of devices already * registered. Since the success of this call takes up a slot for a * registered SCSI device it is important that such allocations are * not left around idle, but are either fully registered or freed * again as soon as possible through vmk_ScsiFreeDevice(). * * \see vmk_ScsiFreeDevice(). * * \see vmk_ScsiRegisterDevice(). * * \note This is a blocking call. * \note The call also allocates and initializes various associated * VMkernel private data structures. * \note This call should only be used by MP plugins. * * \post The obtained device MUST be freed through vmk_ScsiFreeDevice(). * * \param[in] plugin Plugin allocating the device. * * \return Pointer to vmk_ScsiDevice or NULL if allocation fails or * if max. number of SCSI devices are already registered. * *********************************************************************** */ vmk_ScsiDevice *vmk_ScsiAllocateDevice( vmk_ScsiPlugin *plugin); /* *********************************************************************** * vmk_ScsiRegisterDevice -- */ /** * * \ingroup MPP * * \brief Add a logical storage device. * * This function will attempt to register a logical SCSI device with * the VMkernel. There must be at least one UID passed in and precisely * one of the UIDs must have \em VMK_SCSI_UID_FLAG_PRIMARY set in its * \em uid->idFlags. The \em device->ops field must point to a structure * filled with at least the \em startCommand, \em taskMgmt, \em open, * \em close, \em probe, \em getInquiry, \em issueDumpCmd, * \em isPseudoDevice and \em u.mpDeviceOps.getPathnames function * pointers. * * \see vmk_ScsiDeviceUIDAdd(). * vmk_ScsiUnregisterDevice(). * * \note This is a blocking call. * \note The plugin will be pinned (unable to unload) until the device * has been unregistered again * \note This call should only be used by MP plugins. * * \pre The caller MUST have obtained the passed vmk_ScsiDevice * through a call to vmk_ScsiAllocatedevice(). * \pre The device MUST be ready to accept I/O when the call is made. * * \param[in] device Device to register. * \param[in] uid Pointer to an array of numUids uids * to register for this device. * \param[in] numUids Number of UIDs in the **uid list. * * \retval VMK_OK Device successfully registered. * \retval VMK_BAD_PARAM The value of numUids is less than 1, * there is not exactly one uid marked * with the VMK_SCSI_UID_FLAG_PRIMARY, * the device->ops are not specified * correctly, or same as * vmk_ScsiDeviceUIDAdd(). * \retval VMK_NOT_SUPPORTED The plugin controlling the device * is not marked as * VMK_SCSI_PLUIGN_TYPE_MULTIPATHING * or same as vmk_ScsiDeviceUIDAdd(). * \retval VMK_NOT_FOUND No paths are specified for the device. * \retval VMK_EXISTS Same as vmk_ScsiDeviceUIDAdd(). * \retval VMK_DUPLIATE_UID Same as vmk_ScsiDeviceUIDAdd(). * \retval VMK_TOO_MANY_ELEMENTS Same as vmk_ScsiDeviceUIDAdd(). * \retval VMK_FAILURE Could not determine the legacy UID * for the device. * \retval VMK_NO_CONNECT A path to the device is in the * process of being removed. * \retval VMK_TIMEOUT I/O command did not complete within * the timeout time due to a transient * errors. * \retval VMK_ABORTED I/O command did not complete and * was aborted. * \retval VMK_BUSY I/O command did not complete because * the device was busy or there was a * race to register/unregister the same * device with another thread. * \retval VMK_RESERVATION_CONFLICT I/O command did not complete due * to a SCSI reservation on the device. * \retval VMK_STORAGE_RETRY_OPERATION I/O command did not complete * due to a transient error. * \retval VMK_HBA_ERROR I/O command did not complete due * to an HBA or driver error. * \retval VMK_IO_ERROR I/O command did not complete due * to an unknown error. * \retval VMK_NOT_SUPPORTED I/O command did not complete due * to an unspecified error. * \retval VMK_MEDIUM_NOT_FOUND I/O command did not complete on a * removeable media device and media * is not present. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiRegisterDevice( vmk_ScsiDevice *device, vmk_ScsiUid **uid, vmk_int32 numUids); /* *********************************************************************** * vmk_ScsiUnregisterDevice -- */ /** * * \ingroup MPP * * \brief Remove a logical storage device. * * This function will wait for outstanding Task Management operations * on the device to drain before finally unregistering the device. * If the device is open by any world the call will fail. * * \see vmk_ScsiRegisterDevice(). * \see vmkScsiFreeDevice(). * * \note This is a blocking call. * \note The caller should not hold any semaphores. * \note This call should only be used by MP plugins. * * \pre The device MUST have been successfully registered with a call * to vmk_ScsiRegisterDevice(). * * \param[in] device Device to unregister. * * \retval VMK_OK Device successfully unregistered. * \retval VMK_BUSY Device not unregistered as the device * was busy. * \retval VMK_BAD_PARAM Device has already been unregistered. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiUnregisterDevice( vmk_ScsiDevice *device); /* *********************************************************************** * vmk_ScsiFreeDevice -- */ /** * * \ingroup MPP * * \brief Free the storage associated with a logical storage device. * * This function will undo the work of vmk_ScsiAllocateDevice() and * will both free the structure and also clean up some associated * VMkernel internal structures. Among this is the freeing of the * device "slot" that will limit the total number of allocated devices. * It is therefore important that this function is used to free the * vmk_ScsiDevice structure allocated through vmk_ScsiAllocateDevice(). * * \see vmk_ScsiUnregisterDevice(). * \see vmk_ScsiAllocateDevice(). * * \note This is a blocking call. * \note This call should only be used by MP plugins. * * \pre The device MUST have been unregistered (or never registered). * * \param[in] device Device to free. * *********************************************************************** */ void vmk_ScsiFreeDevice( vmk_ScsiDevice *device); /* *********************************************************************** * vmk_ScsiSetDeviceState-- */ /** * * \ingroup MPP * * \brief Set current device state. * * This function allows a plugin to set the state of a device. The * intent of this call is to allow the user to see the state of a * device through the UI or CLI. * * \note This is a non-blocking call except when called with * VMK_SCSI_DEVICE_STATE_QUIESCED. vmk_ScsiSetDeviceState with * VMK_SCSI_DEVICE_STATE_QUIESCED is a blocking call. * * \note Spin locks can be held while calling into this function * except when it can block (e.g. VMK_SCSI_DEVICE_STATE_QUIESCED). * * \note A device coming back after a permanent device loss event is * considered a user error. There are NO data consistency * guarantees if this occurs. MPPS must set the state to * VMK_SCSI_DEVICE_STATE_PERM_LOSS indication IFF all paths to * the device have hit a permanent device loss condition. ESX * will fail back all I/Os and abort I/Os in progress. MPP can * expect aborts (virt resets) for I/Os in flight or Qed. MPPs * may choose to return (non-VMK_SCSI_COMMAND_FLAGS_NO_CONNECT_IF_APD) * Qed I/Os but this is optional. ESX will also generate a VOB * indicating that the device is lost. * * \note The VMK_SCSI_DEVICE_STATE_QUIESCED can only be used * during device unregistration time (with info set to * VMK_SCSI_DEVICE_UNREGISTER). As part of this PSA * will drain all I/Os and after this call no MPP device * entry points will be invoked. * * \param[in] device Device whose state should be set. * \param[in] state The new state of the device. * \param[in] info Additional information about the state. * * \retval VMK_BAD_PARM Incorrect state (e.g. * state = VMK_SCSI_DEVICE_STATE_OFF) or info param. * * \retval VMK_EOPNOTSUPP Setting state not supported (e.g * VMK_SCSI_DEVICE_STATE_APD). * Others maybe added in the future. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiSetDeviceState( vmk_ScsiDevice *device, vmk_ScsiDeviceState state, vmk_ScsiDeviceStateInfo info); /* *********************************************************************** * vmk_ScsiDeviceStateToString -- */ /** * * \ingroup MPP * * \brief Convert a device state into a human readable text string. * * \see vmk_ScsiSetDeviceState(). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note The string output of this function is not recommended for * display in end-user visible tools. However, the string output * of this function is suitable for kernel logging. * * \param[in] state Device state to convert to string. * * \return String with human readable representation of device state. * * *********************************************************************** */ const char *vmk_ScsiDeviceStateToString( vmk_ScsiDeviceState state); /* *********************************************************************** * vmk_ScsiGetDeviceState -- */ /** * * \ingroup MPP * * \brief Get the current device state. * * \see vmk_ScsiSetDeviceState(). * \see vmk_ScsiDeviceStateToString(). * * \note The purpose is to have a common device state for logging * purposes. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] device Device whose state to acquire. * * \return Device's state * *********************************************************************** */ vmk_ScsiDeviceState vmk_ScsiGetDeviceState( vmk_ScsiDevice *device); /* *********************************************************************** * vmk_ScsiDeviceIsPerenniallyReserved-- */ /** * * \ingroup MPP * * \brief Get the current perennial reservation state of the device. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] device Device whose perennial reservation * state to acquire. * \param[out] perenniallyReserved Device perennial reservation state. * Valid only if return status is VMK_OK. * * \retval VMK_OK Device perennial reservation state obtained * successfully. * \retval VMK_BAD_PARAM Passed in device OR perenniallyReserved * parameter is NULL. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiDeviceIsPerenniallyReserved( vmk_ScsiDevice *device, vmk_Bool *perenniallyReserved); /* *********************************************************************** * vmk_ScsiGetDeviceClass -- */ /** * * \ingroup MPP * * \brief Get the current device class. * * This function returns the device class of the device. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] device Device whose class to acquire. * * \return Device class * *********************************************************************** */ vmk_ScsiDeviceClass vmk_ScsiGetDeviceClass( vmk_ScsiDevice *device); /* *********************************************************************** * vmk_ScsiGetDeviceNumBlocks -- */ /** * * \ingroup MPP * * \brief Return the number of blocks as reported by Read Capacity. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] device Device whose # of blocks to acquire. * * \return The number of blocks. * *********************************************************************** */ vmk_uint64 vmk_ScsiGetDeviceNumBlocks( vmk_ScsiDevice *device); /* *********************************************************************** * vmk_ScsiGetDeviceBlockSize -- */ /** * * \ingroup MPP * * \brief Return the block size as reported by Read Capacity. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] device Device whose block size to acquire. * * \return The block size used by the device. * *********************************************************************** */ vmk_ByteCountSmall vmk_ScsiGetDeviceBlockSize( vmk_ScsiDevice *device); /* *********************************************************************** * vmk_ScsiGetDeviceMaxQDepth -- */ /** * * \ingroup MPP * * \brief Return the maximum number of I/Os queueable to the MPP by * the framework. * * This function will get the queue depth of the logical device * registered with the PSA layer and will be the maximum number of * I/Os that is allowed to be outstanding to the logical device's * owning MP plugin. * * \see vmk_ScsiSetDeviceMaxQDepth(). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note This is \b not the maximum queue depth on the physical device. * * \note You may see less I/Os queued on the logical device even when * multiple VMs are very busy on a VMFS volume. This is due to * the throttling mechanism in ESX that ensure fairness. * * \param[in] device Device to acquire max. queue depth for. * * \return Device's queue depth. * *********************************************************************** */ vmk_uint32 vmk_ScsiGetDeviceMaxQDepth( vmk_ScsiDevice *device); /* *********************************************************************** * vmk_ScsiSetDeviceMaxQDepth -- */ /** * * \ingroup MPP * * \brief Set the maximum number of I/Os queuable to the MPP by * the framework. * * This function will set the queue depth of the logical device * registered with the PSA layer. It will be the maximum number of * I/Os that is allowed to be outstanding on the logical device. * A MPP plugin can use this to increase the number of I/Os if it * needs to distribute them on many paths (load balancing). * * \see vmk_ScsiGetDeviceMaxQDepth(). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note This is \b not the maximum queue depth on the physical device. * * \note You may see less I/Os queued on the logical device even when * multiple VMs are very busy on a VMFS volume. This is due to * the throttling mechanism in ESX that ensure fairness. * * \param[in] device Device whose max queueing depth to set. * \param[out] qDepth Depth to set. * * \retval VMK_OK The queue depth was successfully changed. * \retval VMK_BAD_PARAM The qDepth parameter value was 0. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiSetDeviceMaxQDepth( vmk_ScsiDevice *device, vmk_uint32 qDepth); /* *********************************************************************** * vmk_ScsiSwitchDeviceProbeRate -- */ /** * * \ingroup MPP * * \brief Set a device's periodic path state update rate and * return the current probe rate settings. * * \note This is a non-blocking call. * \note The device should be probed at least as frequently as * specified but may be probed more frequently than specified. * * \param[in] vmkDevice Targeted device. * \param[in] newProbeRate New probe rate * ("DEFAULT" or "FAST"). * \param[in] flags Options if any * (i.e. VMK_SCSI_ONE_PROBE_ONLY). * \param[out] currentProbeRate Probe rate prior to this call. * \param[out] currentProbeRateFlags Probe flags prior to this call. * * \retval VMK_OK Probe rate set successfully. * \retval VMK_BAD_PARAM A new probe rate other than * VMK_SCSI_PROBE_RATE_DEFAULT or VMK_SCSI_PROBE_RATE_FAST * was requested. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiSwitchDeviceProbeRate( vmk_ScsiDevice *vmkDevice, vmk_ScsiDeviceProbeRate newProbeRate, vmk_ScsiSetDeviceProbeRateOption flags, vmk_ScsiDeviceProbeRate *currentProbeRate, vmk_ScsiSetDeviceProbeRateOption *currentProbeRateFlags); /* *********************************************************************** * vmk_ScsiGetDeviceName -- */ /** * * \ingroup MPP * * \brief Get the logical device's name. * * This function can be used to provide a consistent device name * among logs from PSA and MP plugins. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] device Device to acquire name for. * * \return The name of the device as a human readable string. * *********************************************************************** */ const char *vmk_ScsiGetDeviceName( vmk_ScsiDevice *device); /* *********************************************************************** * vmk_ScsiDeviceUIDAdd -- */ /** * * \ingroup MPP * * \brief Add a UID to a device. * * Valid UIDs (vmk_ScsiUid.id) are nul-terminated C strings that * may contain only the following characters: * - '0' through '9' * - 'a' through 'z' * - 'A' through 'Z' * - '_', ':', ',', '.' * * Valid UIDs should be persistent across power cycles, HBA * reordering, and SAN reconfiguration. Additionally, a valid UID * should be the same on all ESX hosts that can access the same * physical storage. This function can only be called on a registered * device. Only one UID of type Primary ID is permitted. * * \note This function can only be called for registered devices. * \note This is a non-blocking call. * \note This call should only be used by MP plugins. * * \param[in] vmkDevice Device to add uid to. * \param[in] uidToAdd UID to add to device. * * \retval VMK_OK The UID was successfully added. * \retval VMK_EXISTS The UID matches the uid of a * different device. * \retval VMK_BAD_PARAM The UID has invalid flags or is * composed of disallowed characters. * \retval VMK_DUPLICATE_UID The UID to be added to the device is * already associated with the device. * \retval VMK_TOO_MANY_ELEMENTS UID to be added is a primary UID and * the device already has a primary UID. * \retval VMK_NOT_SUPPORTED The specified device is unregistered. * \retval VMK_NAME_TOO_LONG UID is too long (>128 bytes). * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiDeviceUIDAdd( vmk_ScsiDevice *vmkDevice, vmk_ScsiUid *uidToAdd); /* *********************************************************************** * vmk_ScsiDeviceUIDRemove -- */ /** * * \ingroup MPP * * \brief Remove a UID from a device. * * \see vmk_ScsiDeviceUIDAdd(). * * \note This is a non-blocking call. * \note This call should only be used by MP plugins. * * \param[in] device Device to remove UID from. * \param[in] uidToRemove UID to remove from device. * * \retval VMK_OK The UID was successfully removed. * \retval VMK_READ_ONLY The UID is the primary uid or a legacy UID * for a device and cannot be removed. * \retval VMK_NOT_FOUND The UID is not associated with the device. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiDeviceUIDRemove( vmk_ScsiDevice *device, vmk_ScsiUid *uidToRemove); /* *********************************************************************** * vmk_ScsiGetPathState-- */ /** * * \ingroup MPP * * \brief Return current path state. * * This function returns the current path state. It does not block * nor does it acquire another spin lock. So it is safe to call it * while holding a spin lock without having to worry about blocking * or lock ranking issues. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] path Path to get state for. * * \return The state of the path. * *********************************************************************** */ vmk_ScsiPathState vmk_ScsiGetPathState(vmk_ScsiPath *path); /* *********************************************************************** * vmk_ScsiSetPathState-- */ /** * * \ingroup MPP * * \brief Set PSA framework current path state. * * This function may only be called by the MP Plugin that is * managing the path. Other callers wishing to change a path's * state should instead use vmk_ScsiSetPluginPathState(). This * function exists so that an MP Plugin may notify the PSA * framework of a path state change. vmk_ScsiSetPluginPathState() * exists so that other callers can notify the MP Plugin of a * path state change (with the expectation that the MP Plugin will * duly call vmk_ScsiSetPathState() after doing any internal * bookkeeping). * * \see vmk_ScsiGetPathState(). * \see vmk_ScsiSetPluginPathState(). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] plugin Plugin that owns the path. * \param[in] path Path to set state on. * \param[in] state State to set. * * \retval VMK_OK The path state was successfully set. * \retval VMK_NO_PERMISSION The plugin is not the owner of the path. * \retval VMK_BAD_PARAM The path state was invalid. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiSetPathState( vmk_ScsiPlugin *plugin, vmk_ScsiPath *path, vmk_ScsiPathState state); /* *********************************************************************** * vmk_ScsiSetPluginPathState-- */ /** * * \ingroup MPP * * \brief Set MP Plugin current path state. * * This function may only be called by non-MP Plugin callers. An * MP Plugin wishing to change a path's state should instead use * vmk_ScsiSetPathState(). This function exists so that * non-MP Plugin callers can notify a plugin of a path state * change. vmk_ScsiSetPluginState() exists so that an MP Plugin * can notify the PSA framework of a path state change, with the * expectation that the MP Plugin will duly call * vmk_ScsiSetPathState() after its internal bookkeeping as a * of vmk_ScsiSetPluginPathState(). The path state change is * limited to admistrative change only to enable a disabled path * and vice versa. * * \see vmk_ScsiSetPathState(). * * \note This is a blocking call. * \note Only VMK_SCSI_PATH_STATE_{ON/OFF} are allowed. * * \param[in] path Path to set state on. * \param[in] state State to set. * * \retval VMK_OK Path state was successfully set. * \retval VMK_BAD_PARAM Invalid path state was passed. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiSetPluginPathState( vmk_ScsiPath *path, vmk_ScsiPathState state); /* *********************************************************************** * vmk_ScsiPathStateToString-- */ /** * * \ingroup MPP * * \brief Get a text string describing the current path state. * * \see vmk_ScsiGetPathState(). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] state State to convert to string. * * \return Human-readable string describing the path state or * "Unknown path state" in case an invalid path state is passed. * *********************************************************************** */ const char *vmk_ScsiPathStateToString( vmk_ScsiPathState state); /* *********************************************************************** * vmk_ScsiGetPathLUN -- */ /** * * \ingroup MPP * * \brief Get path LUN. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] path Path to acquire logical unit number. * * \return LUN for the given path. * *********************************************************************** */ vmk_int32 vmk_ScsiGetPathLUN( vmk_ScsiPath *path); /* *********************************************************************** * vmk_ScsiGetPathTarget -- */ /** * * \ingroup MPP * * \brief Get path target. * * \note This is the target ID as returned from the driver layer and * in case of FC/iSCSI this is thus a logical mapping of the * real target ID (which is a WWNN or IQN). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] path Path to acquire target id for. * * \return Target ID for the given path. * *********************************************************************** */ vmk_int32 vmk_ScsiGetPathTarget( vmk_ScsiPath *path); /* *********************************************************************** * vmk_ScsiGetPathChannel -- */ /** * * \ingroup MPP * * \brief Get path Channel. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] path Path to acquire channel number. * * \return Channel number for the given path. * *********************************************************************** */ vmk_int32 vmk_ScsiGetPathChannel( vmk_ScsiPath *path); /* *********************************************************************** * vmk_ScsiGetPathAdapter -- */ /** * * \ingroup MPP * * \brief Get path's Adapter name. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] path Path to acquire adapter name for. * * \return Adapter name for the given path. * *********************************************************************** */ const char *vmk_ScsiGetPathAdapter( vmk_ScsiPath *path); /* *********************************************************************** * vmk_ScsiGetAdapterTransport -- */ /** * * \ingroup MPP * * \brief Get the adapter transport type. * * \note This is a non-blocking call. * * \param[in] adapName Adapter to acquire transport from. * \param[out] transportType Transport type * * \retval VMK_OK Successfully obtained transport type. * \retval VMK_NOT_FOUND The passed adapter could not be found. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiGetAdapterTransport( const vmk_Name *adapName, vmk_StorageTransport *transportType); /* *********************************************************************** * vmk_ScsiAdapterTransportToString -- */ /** * * \ingroup MPP * * \brief Convert adapter transport type into a human readable text string * * Get printable string for adapter transport type (fc/iscsi/..). * * \see vmk_ScsiGetAdapterTransport(). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] adapterTransport Adapter Transport type * \param[out] transportString Human readable string format * * \retval VMK_BAD_PARAM Bad adapterTransport type * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiAdapterTransportToString( vmk_StorageTransport adapterTransport, const char **transportString); /* *********************************************************************** * vmk_ScsiGetAdapterPendingCmdInfo -- */ /** * * \ingroup MPP * * \brief Get the queued and active cmd counts for the adapter. * * Get the number of active and queued commands on the given adapter. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note This information is only a snapshot of the values and they * may even have changed as the function returns. * * \param[in] adapterName Adapter name. * \param[out] ioCmdCounts If this pointer is non-NULL the memory * specified will be filled in with a * snapshot of the adapter active / queued * command count structure * \em vmk_ScsiIOCmdCounts. * \param[out] queueDepthPtr If the pointer is non-NULL the memory * specified will be filled in with a * snapshot of the adapter maximum queue * depth. * * \retval VMK_OK Successfully obtained the pending cmd. info. * \retval VMK_NOT_FOUND The passed adapter could not be found. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiGetAdapterPendingCmdInfo( const vmk_Name *adapterName, vmk_ScsiIOCmdCounts *ioCmdCounts, vmk_int32 *queueDepthPtr); /* *********************************************************************** * vmk_ScsiGetPathInquiry -- */ /** * * \ingroup MPP * * \brief Get the path's cached inquiry data. * * This function is used to obtain a copy of cached inquiry data for * a path. The call can fail if the data has not yet been obtained. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note \em inqBuf may be NULL in which case only \em *pageLen is * returned. This can be used to find the right buffer size up * front and see whether the data is available at all. * * \param[in] path Scsi path from which we are retrieving * inquiry data. * \param[out] inqBuf Buffer to which inquiry data will be copied. * \param[in] inqBufLen Size of the inquiry buffer in bytes. * \param[in] vmkScsiPage Page type for the inquiry data to be * copied into the inquiry buffer. * \param[out] pageLen Optional actual page length based on page * header. * * \retval VMK_OK Successfully obtained the inquiry data. * \retval VMK_NOT_SUPPORTED The data was not yet available or the * page type was invalid. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiGetPathInquiry( vmk_ScsiPath *path, vmk_uint8 *inqBuf, vmk_ByteCountSmall inqBufLen, vmk_ScsiInqType vmkScsiPage, vmk_ByteCountSmall *pageLen); /* *********************************************************************** * vmk_ScsiGetPathVendor -- */ /** * * \ingroup MPP * * \brief Get the path's vendor from its cached inquiry data. * * This function will retrieve the vendor string from the cached * inquiry data. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note The passed string buffer must have space for at least * VMK_SCSI_VENDOR_NAME_LENGTH characters. * * \param[in] path SCSI path from which we are retrieving inq * vendor. * \param[out] vendor Buffer to which inquiry vendor will be copied. * *********************************************************************** */ void vmk_ScsiGetPathVendor( vmk_ScsiPath *path, char vendor[VMK_SCSI_VENDOR_NAME_LENGTH]); /* *********************************************************************** * vmk_ScsiGetPathModel -- */ /** * * \ingroup MPP * * \brief Get the path's model from its cached inquiry data. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note The passed string buffer must have space for at least * VMK_SCSI_MODEL_NAME_LENGTH characters. * * \param[in] path Scsi path from which we are retrieving inquiry * model. * \param[out] model Buffer to which inquiry model will be copied. * * \return Human readable string with the inquiry data's model. * *********************************************************************** */ void vmk_ScsiGetPathModel( vmk_ScsiPath *path, char model[VMK_SCSI_MODEL_NAME_LENGTH]); /* *********************************************************************** * vmk_ScsiGetPathName -- */ /** * * \ingroup MPP * * \brief Get the current path name. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note The obtained string should never be modified/freed. * * \param[in] path Path whose name to acquire. * * \return Human readable string with the path's name. * *********************************************************************** */ const char *vmk_ScsiGetPathName( vmk_ScsiPath *path); /* *********************************************************************** * vmk_ScsiGetPathInfo -- */ /** * * \ingroup MPP * * \brief Get the path's adapter/channel/target/lun info. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] vmkPath Path to get info for. * \param[out] adapterName Adapter name for the given path. * \param[in] adapterNameSize Size of adapterName array in bytes. * \param[out] channel Channel of the given path. * \param[out] target Target id of the given path. * \param[out] lun LUN id of the given path. * * \retval VMK_OK The path info was successfully obtained. * \retval VMK_BAD_PARAM One of the input parameter(s) was NULL. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiGetPathInfo( vmk_ScsiPath *vmkPath, vmk_Name *adapterName, vmk_ByteCountSmall adapterNameSize, vmk_uint32 *channel, vmk_uint32 *target, vmk_uint32 *lun); /* *********************************************************************** * vmk_ScsiGetPathPendingCmdInfo -- */ /** * * \ingroup MPP * * \brief Get the queued and active cmd counts for the path. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note This information is only a snapshot. * * \param[in] vmkPath Path to get info for. * \param[out] ioCmdCounts If this is non-NULL the memory specified * will be filled in with a snapshot of the * path active / queued command count * structure vmk_ScsiIOCmdCounts. * \param[out] queueDepthPtr If this is is non-NULL the memory specified * will be filled in with a snapshot of the * path's maximum queue depth. * * \retval VMK_OK Successfully obtained the pending cmd. info. * \retval VMK_BAD_PARAM The path was invalid or NULL. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiGetPathPendingCmdInfo( vmk_ScsiPath *vmkPath, vmk_ScsiIOCmdCounts *ioCmdCounts, vmk_int32 *queueDepthPtr); /* *********************************************************************** * vmk_ScsiIssuePathTaskMgmt-- */ /** * * \ingroup MPP * * \brief Issue a task management command on the specified path. * * This function issues a task management command to abort/reset one * or more outstanding I/Os. While a virtual reset will reset only * commands for the given world a device/LUN reset will reset all I/O * on the path. An abort is targeting a single I/O though that I/O may * have been split into several smaller ones and can thus cause several * I/Os to be aborted in the driver layer. * * Note that any I/Os aborted by the call will complete asynchronously * and may not have completed when the call returns. The abort/reset is * thus only meant as a mean to speed up completion of I/Os - normally * by returning the I/O with an error (aborted/reset status). * * The \em taskMgmt structure is obtained from a prior call to * vmk_ScsiInitTaskMgmt(). * * \note This is a blocking call. * * \param[in] path Path to issue task mgmt on. * \param[in] taskMgmt Task management request to issue. * * \retval VMK_OK Task management call was successfull. This * does \em not mean that everything will * complete since there are natural races in the * stack so retry the operation if things don't * complete soon after this (in a second or two). * \retval VMK_BAD_PARAM The task management type in the passed * taskMgmt struct is invalid. * \retval VMK_NO_MEMORY Memory needed to issue the command could * not be allocated. * \retval VMK_FAILURE Could not abort/reset for other reason, * but the operation can be retried. * \retval VMK_NOT_FOUND The I/Os could not be found. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiIssuePathTaskMgmt( vmk_ScsiPath *path, vmk_ScsiTaskMgmt *taskMgmt); /* *********************************************************************** * vmk_ScsiCreateCommand -- */ /** * * \ingroup MPP * * \brief Allocate and initialize a SCSI command. * * For performance reasons, this routine will initialize only * some of the fields of the vmk_ScsiCommand (lba, lbc, * dataDirection, cdb, cdblen will NOT be initialized). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note The command must be freed using vmk_ScsiDestroyCommand(). * * \return a pointer to vmk_ScsiCommand or NULL if allocation failed. * *********************************************************************** */ vmk_ScsiCommand *vmk_ScsiCreateCommand(void); /* *********************************************************************** * vmk_ScsiDestroyCommand -- */ /** * * \ingroup MPP * * \brief Free a SCSI command. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \pre The supplied command must have been allocated via * vmk_ScsiCreateCommand() or one of the utility * vmk_ScsiCreateXXXCommand() functions. * command->sgArray must be NULL. (the implication is that if * this field was previously set, caller has vmk_SgFree()'d it). * * \param[in] command Command to destroy. * *********************************************************************** */ void vmk_ScsiDestroyCommand(vmk_ScsiCommand *command); /* *********************************************************************** * vmk_ScsiCreateInqCommand -- */ /** * * \ingroup MPP * * \brief Allocate and initialize a SCSI inquiry command. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note The command must be freed using vmk_ScsiDestroyCommand(). * * \return a pointer to vmk_ScsiCommand or NULL if allocation failed. * *********************************************************************** */ vmk_ScsiCommand * vmk_ScsiCreateInqCommand( vmk_Bool evpd, vmk_uint8 evpdPage, vmk_uint16 minLen, vmk_uint16 maxLen); /* *********************************************************************** * vmk_ScsiCreateTURCommand -- */ /** * * \ingroup MPP * * \brief Allocate and initialize a SCSI test unit ready command. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note The command must be freed using vmk_ScsiDestroyCommand(). * * \return a pointer to vmk_ScsiCommand or NULL if allocation failed. * *********************************************************************** */ vmk_ScsiCommand *vmk_ScsiCreateTURCommand(void); /* *********************************************************************** * vmk_ScsiGetNextDeviceCommand -- */ /** * * \ingroup MPP * * \brief Get the next command for a logical device from the IO * scheduler. * * This function is meant to be used from within an MPP in its * \em startCommand entry point. This should be called in a loop since * the scheduler will automatically stop when enough I/O has been * queued (e.g. the PSA queues may still hold I/Os, but due to max. * device queue depth or throttling no more I/Os will be issued). * * \note This is a non-blocking call. * * \note This call should only be used by MP plugins. * * \pre The caller should not hold any spinlocks. * \pre The caller should have acquired any needed resources that need * to be tied to the I/O up front as I/Os cannot be returned to * the device queue again. * * \param[in] vmkDev Device for which to get the next command. * * \return Pointer to a SCSI command or NULL if there are no more * commands to send at this time. * In that case, SCSI will invoke the plugin's \em start() entry * point again when the scheduler wants to issue I/Os again. * *********************************************************************** */ vmk_ScsiCommand *vmk_ScsiGetNextDeviceCommand(vmk_ScsiDevice *vmkDev); /* *********************************************************************** * vmk_ScsiDeviceFlushAPDCommands -- */ /** * * \ingroup MPP * * \note This is a non-blocking call. * * \brief Scan the device's scheduling queues for commands tagged with * VMK_SCSI_COMMAND_FLAGS_NO_CONNECT_IF_APD and complete them * with NO_CONNECT now. * * \param[in] vmkDev The target SCSI device * *********************************************************************** */ void vmk_ScsiDeviceFlushAPDCommands(vmk_ScsiDevice *vmkDev); /* *********************************************************************** * vmk_ScsiIssueAsyncPathCommand -- */ /** * * \ingroup MPP * * \brief Issue a command on the specified path. * * This function issues a SCSI command on a specific path. The command * will complete asynchronously at a later point using the command's * \em done() completion callback. If the specified path is claimed * the function will call the owning MPP's \em pathIssueCmd entry point to * issue the command, otherwise the command is directly issued on the path. * * \note This is a non-blocking call. * * \pre The caller should not hold any spinlocks. * * \param[in] path Path to issue command to. * \param[in] command Command to issue on path. * * \retval VMK_OK Successfully issued the command. * \retval VMK_NO_CONNECT Path is in process of being removed. * \retval VMK_NO_MEMORY Unable to allocate memory for additional * resources to be associated with command. * \retval VMK_TIMEOUT The command had a timeout set and the * timeout time had already been passed when * the command was to be issued. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiIssueAsyncPathCommand( vmk_ScsiPath *path, vmk_ScsiCommand *command); /* *********************************************************************** * vmk_ScsiIssueAsyncPathCommandDirect -- */ /** * * \ingroup MPP * * \brief Issue a command on the specified path. * * This function issues a SCSI command on a specific path. The command * will complete asynchronously at a later point using the command's * \em done() completion callback. The MPP's \em pathIssueCmd entry point * is not called. * * \note This is a non-blocking call. * \note This function should be called only by the owning MPP. * * \pre The caller should not hold any spinlocks. * * \param[in] path Path to issue command to. * \param[in] command Command to issue on path. * * \retval VMK_OK Successfully issued the command. * \retval VMK_NO_CONNECT Path is in process of being removed. * \retval VMK_NO_MEMORY Unable to allocate memory for additional * resources to be associated with command. * \retval VMK_TIMEOUT The command had a timeout set and the * timeout time had already been passed when * the command was to be issued. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiIssueAsyncPathCommandDirect( vmk_ScsiPath *path, vmk_ScsiCommand *command); /* *********************************************************************** * vmk_ScsiIssueSyncPathCommand -- */ /** * * \ingroup MPP * * \brief Issue a synchronous command on the specified path. * * This function issues a command on a specific path and waits for * the command to complete before returning. If the specified path * is claimed by a MPP the function will call the owning MPP's * \em pathIssueCmd entry point to issue the command, otherwise the * command is directly issued on the path. * * \see vmk_ScsiIssueSyncPathCommandWithData(). * \see vmk_ScsiIssueSyncPathCommandWithRetries(). * * \note This is a blocking call. * \note The call specifies the buffer to use for data transfer (if * needed) using \em command->sgArray. * \note The calling world sleeps until the command completes. * * \pre The caller should not hold any spinlock. * * \param[in] path Path to issue command to. * \param[in] command Command to issue on path. * * \retval VMK_OK The command was issued successfully and * the command's status is valid. * \retval VMK_NO_CONNECT Path is in process of being removed * \retval VMK_NO_MEMORY Unable to allocate memory for additional * resources associated with command. * \retval VMK_TIMEOUT The command had a timeout set and was * already timed when it was to be issued. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiIssueSyncPathCommand( vmk_ScsiPath *path, vmk_ScsiCommand *command); /* *********************************************************************** * vmk_ScsiIssueSyncPathCommandWithData -- */ /** * * \ingroup MPP * * \brief Issue a synchronous command on the specified path. * * This function issues a command on a specific path and waits for * the command to complete before returning. If the specified path * is claimed by a MPP the function will call the owning MPP's * \em pathIssueCmd entry point to issue the command, otherwise the * command is directly issued on the path. * The caller can specify the buffer to use for data transfer using * the \em data and \em dataLen parameters. The passed data buffer is * used to create an sgArray for the command, so the * \em command->sgArray must be NULL. * * \see vmk_ScsiIssueSyncPathCommand(). * \see vmk_ScsiIssueSyncPathCommandWithRetries(). * * \note This is a blocking call. * \note The calling world sleeps until the command completes. * * \pre The caller should not hold any spinlock. * \pre The \em command->sgArray must be NULL. * * \param[in] path Path to issue command to. * \param[in] command Command to issue on path. * \param[in,out] data Data buffer. * \param[in] dataLen Length of data buffer. * * \retval VMK_OK The command was issued successfully and * the command's status is valid. * \retval VMK_NO_CONNECT Path is in process of being removed. * \retval VMK_NO_MEMORY Unable to allocate memory for additional * resources associated with command. * \retval VMK_TIMEOUT The command had a timeout set and was * already timed when it was to be issued. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiIssueSyncPathCommandWithData( vmk_ScsiPath *path, vmk_ScsiCommand *command, void *data, vmk_ByteCountSmall dataLen); /* *********************************************************************** * vmk_ScsiIssueSyncPathCommandWithRetries -- */ /** * * \ingroup MPP * * \brief Issue a synchronous command on the specified path. * * This function issues a command on a specific path and waits for * the command to complete before returning. If the specified path * is claimed by a MPP the function will call the owning MPP's * \em pathIssueCmd entry point to issue the command, otherwise the * command is directly issued on the path. * This function is same as \em vmk_ScsiIssueSyncPathCommandWithData(), * the only difference being that it retries the command on all transient * errors. Refer \em vmkapi_scsi_ext.h to read about transient errors. * * \see vmk_ScsiIssueSyncPathCommand(). * \see vmk_ScsiIssueSyncPathCommandWithData(). * * \note This is a blocking call. * \note The calling world sleeps until the command completes. * * \param[in] path The path the cmd is to be issued to. * \param[in] command Command to be issued. * \param[in] data Read/write data associated with * the command. * \param[in] dataLen Length of the read/write data * associated with the command. * * \retval VMK_OK The command was issued successfully and * the command's status is valid. * \retval VMK_NO_CONNECT Path is in process of being removed. * \retval VMK_NO_MEMORY Unable to allocate memory for additional * resources associated with command. * \retval VMK_TIMEOUT The command had a timeout set and was * already timed when it was to be issued. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiIssueSyncPathCommandWithRetries( vmk_ScsiPath *path, vmk_ScsiCommand *command, vmk_uint8 *data, vmk_ByteCountSmall dataLen); /* *********************************************************************** * vmk_ScsiIssueSyncDumpCommand -- */ /** * * \ingroup MPP * * \brief Issue a dump command to a path during a system core dump. * * This function issues a dump command on the given path and * busywaits until the command completes. It is meant for an MP plugin * to call this from it's device->dumpCommand entry point. * * \note This is a blocking call. * \note This does not call the MPP's \em pathIssueCmd entry point * * \param[in] path Path to issue command to. * \param[in] command Command to issue on path. * * \retval VMK_OK Dump command was issued successfully and * the command's status is valid. * \retval VMK_FAILURE The adapter backing the path is not enabled. * \retval VMK_TIMEOUT Command timed out and should NOT be retried. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiIssueSyncDumpCommand( vmk_ScsiPath *path, vmk_ScsiCommand *command); /* *********************************************************************** * vmk_ScsiIssueSyncFilterCommandWithRetries -- */ /** * * \ingroup MPP * * \brief Issue a synchronous command on a device. * * This function issues a command on the device on behalf of * the Filter or VAAI plugin and waits for the command to complete * before returning. The device is opened before command is issued, * and is closed after the command completes. The caller can specify * the buffer to use for any data transfer using either the data and * dataLen parameters or vmkCmd->sgArray, but not both. * * The command gets retried for basic low level failures such * as device busy, queue full, and some check conditions. * * \note Only Filters and VAAI plugins can use this API. * \note This is a blocking call. * \note The calling world sleeps until the command completes. * * \param[in] vmkPlugin Issuing plugin. * Has to be Filter or VAAI type. * \param[in] vmkDevice The device the cmd is to be issued to. * \param[in] vmkCmd Command to be issued. * \param[in] data Read/write data associated with * the command. * \param[in] dataLen Length of the read/write data * associated with the command, * or NULL if vmkCmd->sgArray is used. * * \return The IO issue status * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiIssueSyncFilterCommandWithRetries( vmk_ScsiPlugin *vmkPlugin, struct vmk_ScsiDevice *vmkDevice, vmk_ScsiCommand *vmkCmd, vmk_uint8 *data, vmk_ByteCountSmall dataLen); /* *********************************************************************** * vmk_ScsiRegisterEventHandler -- */ /** * * \ingroup MPP * * \brief Add an Event Handler for the specific masked event types * on the specified adapter. * * This function registers a handler that will be called as certain * events on the passed adapter occur. * * \see vmk_ScsiAdapterEvents. * \see vmk_ScsiUnRegisterEventHandler(). * * \note This is a non-blocking call. * \note When the callback is called, it should not grab any locks * below minor rank 7, major rank SP_RANK_SCSI. * * \param[in] adapterName Adapter name to register callback for. * \param[in] mask Events to be notified of as a bit mask. * \param[in] handlerCbk Callback to be called when an event * occurs. * * \retval VMK_OK Event handler successfully registered. * \retval VMK_INVALID_ADAPTER The passed adapter does not exist. * \retval VMK_NO_MEMORY Failed to allocate memory for event. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiRegisterEventHandler(const vmk_Name *adapterName, vmk_uint32 mask, vmk_EventHandlerCbk handlerCbk); /* *********************************************************************** * vmk_ScsiUnRegisterEventHandler -- */ /** * * \ingroup MPP * * \brief Remove an Event Handler for the specific masked event types * on the specified adapter. * * This function unregisters an event handler earlier registered by * vmk_ScsiRegisterEventHandler. All arguments need to match those that * were used to register the handler in order for the call to succeed. * * \see vmk_ScsiRegisterEventHandler(). * * \note This is a non-blocking call. * * \param[in] adapterName Name of the adapter to unregister for events. * \param[in] mask Event bit mask to unregister. * \param[in] handlerCbk Event callback to be unregistered. * * \retval VMK_OK Event handler successfully unregistered. * \retval VMK_INVALID_ADAPTER The passed adapter does not exist. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiUnRegisterEventHandler(const vmk_Name *adapterName, vmk_uint32 mask, vmk_EventHandlerCbk handlerCbk); /* *********************************************************************** * vmk_ScsiAllocatePlugin -- */ /** * * \ingroup MPP * * \brief Allocate a plugin data structure. * * This function will allocate a plugin structure for use when * registering the plugin with PSA. The structure should be freed * with vmk_ScsiFreePlugin() again when it is no longer registered. * * \see vmk_ScsiRegisterPlugin(). * \see vmk_ScsiUnregisterPlugin(). * \see vmk_ScsiFreePlugin(). * * \note This is a blocking call. * * \post The plugin MUST be freed through vmk_ScsiFreePlugin(). * * \param[in] heapID Heap id to allocate memory from. * \param[in] pluginName Name of allocating plugin. * * \return Pointer to vmk_ScsiPlugin structure or NULL if memory * could not be allocated for the structure. * *********************************************************************** */ vmk_ScsiPlugin *vmk_ScsiAllocatePlugin( vmk_HeapID heapID, char *pluginName); /* *********************************************************************** * vmk_ScsiFreePlugin -- */ /** * * \ingroup MPP * * \brief Free a plugin data structure allocated by * vmk_ScsiAllocatePlugin(). * * \see vmk_ScsiAllocatePlugin(). * \see vmk_ScsiUnregisterPlugin(). * * \note This is a blocking call. * * \pre The plugin structure must first be unregistered with PSA (or * never have been registered). * * \param[in] plugin Plugin to free. * *********************************************************************** */ void vmk_ScsiFreePlugin( vmk_ScsiPlugin *plugin); /* *********************************************************************** * vmk_ScsiRegisterPlugin -- */ /** * * \ingroup MPP * * \brief Register a plugin with SCSI. * * This function will register a plugin with PSA. * * \see vmk_ScsiAllocatePlugin(). * \see vmk_ScsiUnregisterPlugin(). * * \note This is a blocking call. * * \pre The vmk_ScsiPlugin structure MUST have been allocated through * vmk_ScsiAllocatePlugin(). * * \param[in] plugin Plugin to register. * * \retval VKM_OK Successfully registered the plugin. * \retval VMK_EXISTS The plugin is already registered with PSA. * \retval VMK_NOT_SUPPORTED The API revision the plugin is compiled * for is incompatible with the ESX server. * \retval VMK_BAD_PARAM The plugin's type is invalid/unsupported * or some required entry points are not set. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiRegisterPlugin( vmk_ScsiPlugin *plugin); /* *********************************************************************** * vmk_ScsiUnregisterPlugin -- */ /** * * \ingroup MPP * * \brief Unregister a plugin previously registered via * vmk_ScsiRegisterPlugin(). * * This function is used to unregister a plugin that has previously * been successfully registered with PSA. Before a plugin can be * unregistered it must not have any paths claimed or devices * registered. * The plugin must also have a state of VMK_SCSI_PLUGIN_STATE_DISABLED * when this function is called, which has to be set through * vmkScsiSetPluginState() - the latter will ensure that no claim * operations will be passed to the plugin. * * \see vmk_ScsiFreePlugin(). * \see vmk_ScsiSetPluginState(). * * \note This is a blocking call. * * \pre The plugin should have released all its SCSI resources (paths, * devices, ...). * \pre The plugin state must be VMK_SCSI_PLUGIN_STATE_DISABLED. * * \param[in] plugin Plugin to unregister. * * \retval VMK_OK Successfully unregistered the plugin. * \retval VMK_BAD_PARAM The plugin was already not registered. * \retval VMK_BUSY The plugin state was not set to disabled. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiUnregisterPlugin( vmk_ScsiPlugin *plugin); /* *********************************************************************** * vmk_ScsiSetPluginState-- */ /** * * \ingroup MPP * * \brief Set the current state of the plugin. * * This function sets the plugin state to one of the possible values * defined by the vmk_ScsiPluginState enum. The plugin will normally * operate in ENABLED mode and when the \em pathClaimBegin entry point * is called the plugin should (temporarily) set it to CLAIM_PATHS and * then set it back to ENABLED when the \em pathClaimEnd entry point is * later invoked. Lastly it should be set to DISABLED before the * plugin is finally unregistered. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] plugin Plugin to set state to. * \param[in] state New state to set. * *********************************************************************** */ void vmk_ScsiSetPluginState( vmk_ScsiPlugin *plugin, vmk_ScsiPluginState state); /* *********************************************************************** * vmk_ScsiGetPluginState-- */ /** * * \ingroup MPP * * \brief Get the current state of the plugin. * * \see vmk_ScsiSetPluginState(). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] plugin Plugin to get state from. * *********************************************************************** */ vmk_ScsiPluginState vmk_ScsiGetPluginState( vmk_ScsiPlugin *plugin); /* *********************************************************************** * vmk_ScsiIncReserveGeneration -- */ /** * * \ingroup MPP * * \brief Increment the reservation generation count of the device. * * This function is used to tell the PSA layer that a reservation was * broken/cleared by the MP plugin and thus PSA should fail any * reservation sensitive transactions using the previous generation. * * The intent is that an MP plugin calls this if it has to do a failover * while a SCSI-2 reservation is held on the device and thus has to * force a LU reset on the new path (or if it has to do a LU reset for * any other reason - or invokes/knows about any other operation that * will clear or has cleared the held reservation). * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \note This call should only be used by MP plugins. * * \param[in] vmkDevice Device whose reservation generation to bump. * *********************************************************************** */ void vmk_ScsiIncReserveGeneration(vmk_ScsiDevice *vmkDevice); /* *********************************************************************** * vmk_ScsiCommandMaxCommands -- */ /** * * \ingroup MPP * * \brief Maximum outstanding SCSI commands * * This returns the maximum number of SCSI commands that the VMkernel * SCSI command slab allocator supports. These many SCSI commands can * be outstanding in the ESX kernel at any time. * * Any slab in a plugin, that is created for the purpose of allocating * any per-command plugin data structures, should be sized per this, to * ensure that at any time we have enough plugin objects for all the * SCSI commands. * *********************************************************************** */ vmk_uint32 vmk_ScsiCommandMaxCommands(void); /* *********************************************************************** * vmk_ScsiCommandMaxFree -- */ /** * * \ingroup MPP * * \brief Maximum idle SCSI commands * * This returns the maximum number of SCSI commands that the SCSI command * allocator will keep in its cache for fast allocation. Any more freed * SCSI commands are freed to the slab heap, for better memory utilization. * * This should be used by plugins as a good guidance value while creating * their own slabs for any per-command object allocation. * *********************************************************************** */ vmk_uint32 vmk_ScsiCommandMaxFree(void); /* *********************************************************************** * vmk_ScsiDefaultDeviceGetBoolAttr -- */ /** * * \ingroup MPP * * \brief Determine if a device attribute is supported by a device. * * PSA invokes this function by default if the isSSD() and * isLocal() plugin-entry points are not specified. * * The behaviour for various device attributes is outlined below. * * - VMK_SCSI_DEVICE_BOOL_ATTR_PSEUDO * - Device is not a pseudo-device. Always return VMK_FALSE in result. * * - VMK_SCSI_DEVICE_BOOL_ATTR_SSD * - Issue a T10-standards-based EVPD inquiry (B1H - Block Device * Characteristics VPD Page) to determine if the given device is SSD. * SSD Devices report a medium rotation rate of 0x1 (non-rotating medium). * * - VMK_SCSI_DEVICE_BOOL_ATTR_LOCAL * - Determine if the device is local based on storage transport type of * the adapter associated with the device. Devices residing on the * following storage transports are considered local by default. * - VMK_STORAGE_ADAPTER_TRANSPORT_UNKNOWN * - VMK_STORAGE_ADAPTER_BLOCK * - VMK_STORAGE_ADAPTER_SATA * - VMK_STORAGE_ADAPTER_USB * - VMK_STORAGE_ADAPTER_IDE * - VMK_STORAGE_ADAPTER_PSCSI * * \see vmk_ScsiDeviceOps * * \note This is a blocking call. * * \param[in] device SCSI Device to be probed. * \param[in] attr Device attribute to probe for. * \param[out] result Flag indicating device supports the attribute. * Valid only if return status is VMK_OK. * * \retval VMK_OK Device attribute status obtained successfully. * \retval VMK_NO_MEMORY Internal memory allocation failure. * \retval VMK_BAD_PARAM Invalid input device or attribute. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiDefaultDeviceGetBoolAttr( vmk_ScsiDevice *device, vmk_ScsiDeviceBoolAttribute attr, vmk_Bool *result); #endif /* _VMKAPI_MPP_H_ */ /** @} */ /** @} */