fcpvar.h revision fcf3ce441efd61da9bb2884968af01cb7c1452cc
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _FCPVAR_H
#define _FCPVAR_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
/*
* Maximum number of times FCP will re-issue a REPORTS_LUNS command if the
* device couldn't return all of them in the submitted buffer.
*/
#define FCP_MAX_REPORTLUNS_ATTEMPTS 2
/*
* Maximum number of LUNs supported. This limit is enforced to accommodate
* certain HBAs.
*/
#define FCP_MAX_LUNS_SUPPORTED 65535
/*
* Stuff to be defined in fc_ulpif.h FIXIT
*/
#define PORT_DEVICE_CREATE 0x40
#define SCMD_REPORT_LUN 0xa0 /* SCSI cmd to report on LUNs */
#define SCMD_INQUIRY_LWWN_SIZE 32 /* Max WWN size */
#define SCMD_INQUIRY_PAGE83 0xF0 /* Internal opcode for page 0x83 */
#define FC4_SCSI_FCP 0x08 /* our (SCSI) FC4 type number */
#define FCP_QUEUE_DELAY (4)
#define FCP_FAILED_DELAY 20
#define FCP_RESET_DELAY 3 /* target reset delay of 3 secs */
#define FCP_OFFLINE_DELAY 20 /* 20 seconds is 2*RA_TOV_els */
/*
* Highest possible timeout value to indicate
* the watch thread to return the I/O
*/
#define FCP_INVALID_TIMEOUT (0xFFFFFFFF)
/*
* The max inquiry page 83 size as expected in the code today
* is 0xf0 bytes. Defining a constant to make it easy incase
* this needs to be changed at a later time.
*/
#define SCMD_MAX_INQUIRY_PAGE83_SIZE 0xF0
/*
* Events generated for Target drivers; "SUNW,sf:" prefix
* is a legacy fcal stuff hardcoded into ssd via the use of
* FCAL_INSERT_EVENT defined in an fcal header file; We
* just need to continue to use this.
*/
#define FCAL_INSERT_EVENT "SUNW,sf:DEVICE-INSERTION.1"
#define FCAL_REMOVE_EVENT "SUNW,sf:DEVICE-REMOVAL.1"
/*
* for debug trace
*/
#define FCP_STACK_DEPTH 14
/*
* All the stuff above needs to move intp appropriate header files.
*/
#define FCP_NUM_HASH 128
#define FCP_HASH(x) ((x[0] + x[1] + x[2] + x[3] +\
x[4] + x[5] + x[6] + x[7]) & \
(FCP_NUM_HASH-1))
#define FCP_STATEC_MASK (FC_STATE_OFFLINE | FC_STATE_ONLINE |\
FC_STATE_LOOP | FC_STATE_NAMESERVICE |\
FC_STATE_RESET |\
FC_STATE_RESET_REQUESTED |\
FC_STATE_LIP | FC_STATE_DEVICE_CHANGE)
#define PKT_PRIV_SIZE 2
#ifdef KSTATS_CODE
/*
* fcp_stats : Statistics provided for fcp.
*/
struct fcp_stats {
uint_t version; /* version of this struct */
uint_t lip_count; /* lips forced by fcp */
uint_t link_reset_count; /* lip failures, ie, no ONLINE */
/* response after forcing lip */
uint_t ncmds; /* outstanding commands */
uint_t throttle_limit; /* current throttle limit */
char drvr_name[MAXNAMELEN]; /* Name of driver, NULL term. */
};
#endif
/*
* Structure fcp_port
* --------------------
*
* This structure is the FCP representation of an N_Port on a local FC HBA card.
* This is the master structure off of which all the others will be hanging at
* some point and is the Solaris per-instance soft-state structure.
*/
struct fcp_port {
/*
* This mutex protects the access to this structure (or most of its
* fields).
*/
kmutex_t port_mutex;
/*
* This is the link to the next fcp_port structure in the global
* list. The head of the global list is fcp_port_head and is
* defined in fcp.c. This field is NULL for the last element of
* the global list.
*/
struct fcp_port *port_next;
/*
* This field points to the head of a list of internal requests that
* will be retried later. Examples of internal requests are:
* 'Send a PRLI ELS', 'Send a PRLO ELS', 'Send a PLOGI ELS' or
* 'Send an Inquiry command'. If the submission of the request to the
* fp/fctl module failed (for a set of specific reasons) and the
* request can be resubmitted later, it is queued here. The watchdog
* timer (fcp_watch()) will walk this queue and resubmit the requests.
*/
struct fcp_ipkt *port_ipkt_list;
/*
* This seems to be used as a temporary device counter during a
* discovery process (or reconfiguration as some comments put it).
* It seems to be initialized in fcp_statec_callback() with the
* number of devices that fp/fctl saw after the line came up and
* is supposed to reached zero when the reconfiguration process is
* over.
*/
int port_tmp_cnt;
/*
* This is supposed to indicate the state of this port. It is a
* bitmap which means several bits can be set simultaneously. The list
* of the different bits and their meaning is given further down in
* this file.
*/
uint32_t port_state;
/*
* This field is initialized at the very end of the function
* fcp_handle_port_attach() if the attachment of the port was
* successful. It is set to the value stored in lbolt64 at the
* time of the attachment. This value is only used in the function
* fcp_scsi_bus_config(). It is used to determine the value of the
* parameter timeout when ndi_busop_bus_config() and cv_wait() are
* called. It actually serves to figure out how long the enumeration
* can be delayed (the max value being FCP_INIT_WAIT_TIMEOUT).
*/
int64_t port_attach_time;
/*
* This field contains the topology of the SAN the port is connected
* to.
*/
uint32_t port_topology;
/*
* This field contains the local port ID. It is provided by fp/fctl
* when calling fcp_statec_callback() and fcp_port_attach(). This
* value is used to build Fibre Channel headers (like for PLOGI or
* PRLI).
*/
uint32_t port_id;
/*
* This field keeps track of the physical port state (fcp_port being
* more like the FCP software port state). The information stored here
* is provided by fp/fctl except in two instances: in
* fcp_handle_port_attach() and fcp_handle_port_resume(). The values
* this field can take are defined in fctl.h.
*/
uint32_t port_phys_state;
/*
* This field points to the first element of a list of fcp_reset_elem
* structures. Those structures are created when the target driver
* calls fcp_reset_target(). The target or the LUN specified by the
* target driver is reset by sending a Task Management command. After
* the response has been received, a fcp_reset_elem structure is
* queued here and will remain queued for FCP_RESET_DELAY. While
* the fcp_reset_elem structure is in this queue the LUNs of
* the target to reset or the LUN to reset is set to LUN_BUSY state.
* In fcp_watch() the timeout is tested. If the timout has expired,
* the fcp_reset_elem structure is unqueued and freed, and all the
* active commands for the target or LUNs are aborted.
*/
struct fcp_reset_elem *port_reset_list;
/*
* This points to the first element of a list of fcp_tgt_elem
* structures. This list is a list of targets to offline. The list
* is walked in fcp_watch(). After the target is offlined the
* structure fcp_tgt_elem is freed.
*/
struct fcp_tgt_elem *port_offline_tgts;
/*
* This points to the first element of a list of fcp_lun_elem
* structures. This list is a list of LUNs to offline. The list
* is walked in fcp_watch(). After the lun is offlined the
* structure fcp_lun_elem is freed.
*/
struct fcp_lun_elem *port_offline_luns;
/*
* This field is a counter initialized to 1 when the port attaches.
* It is incremented when the line goes from online to offline and
* vice versa. It is also incremented when the port detaches. The
* value stored in this counter is used as a reference in time of the
* link state. For example, when the line comes up internal requests
* are generated (fcp_ipkt) such as PRLI and INQUIRY. Those requests
* are tagged with the value contained in this field at the time the
* request is built. When the callback for the request is called, the
* current value of port_link_cnt is checked against the one set in
* the internal request structure. If they don't match, it means the
* the request is not relevant anymore to the current line state and
* must be discarded (in between a request is issued and the callback
* routine is called the line may have bounced). This is the way FCP
* identifies the requests that were hanging out when the state of the
* line changed.
*/
uint32_t port_link_cnt;
/*
* This field, as its name suggests, specifies a deadline for the
* overall discovery process. It is initialized in three cases:
*
* 1) When the line goes from the offline state to the online state.
* 2) When the FP/FCTL called fcp_statec_callback() indicating that
* a notification was received from the fabric indicating that a new
* port showed up or that one disappeared.
* 3) In the fcp_create_on_demand() function (called because of an
* ioctl).
*
* In all instances it is set to:
*
* fcp_watchdog_time + FCP_ICMD_DEADLINE
*
* In all those instances a discovery process is started or extended
* (2). The value stored in port_deadline is only checked in one
* function: fcp_is_retryable(). That function checks if an
* internal command (fcp_ipkt) is retryable or not. Usually
* there's a counter that limits the number of times a command is
* retried (Max value is FCP_MAX_RETRIES). However, even if the
* counter hasn't exceeded that value, the command will not be retried
* past the deadline. This means that the discovery process has to
* be finished before port_deadline. In other words, an internal
* command retry capability is limited numerically and in time.
*/
int port_deadline;
/*
* This is the Node WWN of the local port. It is initialized
* during the port attachment.
*/
la_wwn_t port_nwwn;
/*
* This is the Port WWN of the local port. It is initialized during
* the port attachment.
*/
la_wwn_t port_pwwn;
/*
* This is the fp/fctl port handle.
*/
opaque_t *port_fp_handle;
/*
* The following 4 fields handle the queue of fcp_pkt outstanding for
* this port.
*
* port_pkt_mutex Protects the access to the queue
* port_pkt_head Points to the head of the queue
* port_pkt_tail Points to the tail of the queue
* port_npkts Number of commands outstanding (used only when
* DEBUG is defined).
*/
kmutex_t port_pkt_mutex;
uint32_t port_npkts;
struct fcp_pkt *port_pkt_head;
struct fcp_pkt *port_pkt_tail;
/*
* This field is the counter of allocated and currently active
* fcp_ipkt.
*/
int port_ipkt_cnt;
/*
* Port instance provided by FP/FCTL. It is actually deduced using
* ddi_get_instance() in fcp_port_attach().
*/
uint32_t port_instance;
/*
* Maximum number of exchanges the underlying physical FibreChannel
* port can handle. This field is initialized during the port
* attachment but is never used.
*/
uint32_t port_max_exch;
/*
* This port stores the behavior expected of the underlying FCA driver
* when a port reset occurs. The values stored here are defined in the
* file fc_types.h.
*/
fc_reset_action_t port_reset_action;
/*
* This port stores the DMA behavior of the underlying FCA driver. It
* is checked only once in fcp_prepare_pkt() and, as the comment
* suggests, to work around an issue with an Intel PCI bridge.
*/
fc_dma_behavior_t port_cmds_dma_flags;
/*
* The value stored here indicates if the underlying FCA driver
* supports DMA transfers with non SCSI data (Ex: PRLI request).
*/
fc_fcp_dma_t port_fcp_dma;
/*
* This field contains the size of the private space required by the
* underlying FCA driver in a FibreChannel packet (fc_packet_t).
*/
uint32_t port_priv_pkt_len;
/*
* This field contains the port's modlink info. It is provided by
* FP/FCTL during the port attachment.
*/
struct modlinkage port_fp_modlinkage;
/*
* DMA attributes for data packets, commands and responses.
*/
ddi_dma_attr_t port_data_dma_attr;
ddi_dma_attr_t port_cmd_dma_attr;
ddi_dma_attr_t port_resp_dma_attr;
ddi_device_acc_attr_t port_dma_acc_attr;
/*
* Field containing the hba_tran structure registered with SCSA.
*/
struct scsi_hba_tran *port_tran;
/*
* Device info structure provided by fp/fctl when the port attaches and
* representing the local physical fibre channel port.
*/
dev_info_t *port_dip;
/*
* Head of the list of callback routines to call when a bus reset
* occurs. This list is populated by the targets drivers by calling
* fcp_scsi_reset_notify() (tran_reset_notify(9E)).
*/
struct scsi_reset_notify_entry *port_reset_notify_listf;
/*
* for framework event management
*/
ndi_event_definition_t *port_ndi_event_defs;
ndi_event_hdl_t port_ndi_event_hdl;
ndi_event_set_t port_ndi_events;
/*
* hash lists of targets attached to this port. The hashing is based
* on the WWN.
*/
struct fcp_tgt *port_tgt_hash_table[FCP_NUM_HASH];
/*
* per-Port control flag. By default mpxio is enabled on ports unless
* explicitly disabled through driver.conf.
*/
int port_mpxio;
/*
* Value used as a flag to determine if the throttling has been
* set/initialized in the FCA driver.
*/
int port_notify;
/*
* This field contains a string initialized at attachment time and used
* when calling the function the function fc_trace_debug() (through
* the macro FCP_TRACE and FCP_DTRACE) to identify the port that
* logged the message.
*/
char port_instbuf[24];
uchar_t port_boot_wwn[FC_WWN_SIZE];
#ifdef DEBUG
/*
* Use once in fcp_finish_init() when calling getpcstack().
*/
int port_finish_depth;
pc_t port_finish_stack[FCP_STACK_DEPTH];
#endif /* DEBUG */
/*
* Condition variable used during the bus enumeration process.
*/
kcondvar_t port_config_cv;
/*
* Size (in bytes) required to hold the cookies of a scatter/gather
* list.
*/
int port_dmacookie_sz;
};
/*
* We need to save the target change count values in a map tag so as
* to uniquely identify the cause and handle it better as they change
* counts are bound to change upon receiving more state changes.
*/
typedef int fcp_map_tag_t;
/*
* fcp_state definitions.
*/
#define FCP_STATE_INIT 0x0001
#define FCP_STATE_OFFLINE 0x0002
#define FCP_STATE_ONLINE 0x0004
#define FCP_STATE_SUSPENDED 0x0008
#define FCP_STATE_POWER_DOWN 0x0010
#define FCP_STATE_ONLINING 0x0020
#define FCP_STATE_DETACHING 0x0040
#define FCP_STATE_IN_WATCHDOG 0x0080
#define FCP_STATE_IN_MDI 0x0100 /* Not in S8/S9 */
#define FCP_STATE_NS_REG_FAILED 0x0200 /* Diff value from S8/S9 */
/*
* FCP_STATE_IN_CB_DEVC indicates that we're handling a state change
* notification that will be changing the state of devices. This is an
* indication to fcp_scsi_start that the target's status might change.
*/
#define FCP_STATE_IN_CB_DEVC 0x0400
#define FCP_MAX_DEVICES 127
/* To remember that dip was allocated for a lun on this target. */
#define FCP_DEVICE_CREATED 0x1
#define FCP_EVENT_TAG_INSERT 0
#define FCP_EVENT_TAG_REMOVE 1
/*
* fcp_pkt: FCP packet
* ---------------------
*
* This structure is the one initialized/created in the tran_init_pkt(9E). It
* embeds the fc_packet structure eventually passed to fp/fctl as well as
* the scsi_pkt returned by tran_init_pkt(9E) to the target driver. There is
* a 1-to-1 correlation between the scsi_pkt, the fcp_pkt and the
* fc_packet.
*
* This is what a fcp_pkt looks like after allocation:
*
* +================================+
* +---> | struct scsi_pkt |
* | | |
* | +--- | pkt_ha_private |
* | | | |
* | | +================================+
* | |
* | | +================================+
* | +--> | struct fcp_pkt | <---------+
* +----- | cmd_pkt | |
* | cmd_fp_pkt | ---+ |
* +--------->| cmd_fcp_rsp[] | | |
* | +------->| cmd_fcp_cmd[] | | |
* | | |--------------------------------| | |
* | | | struct fc_packet | <--+ |
* | | | | |
* | | | pkt_ulp_private | ----------+
* | | | pkt_fca_private | -----+
* | | | pkt_data_cookie | ---+ |
* | | | pkt_cmdlen | | |
* | |(a) | pkt_rsplen | | |
* | +--------| .......... pkt_cmd ........... | ---|-|-------+
* | (a) | pkt_cmd_cookie | ---|-|-----+ |
* +----------| .......... pkt_resp .......... | ---|-|---+ | |
* | pkt_resp_cookie | ---|-|-+ | | |
* | pkt_cmd_dma | | | | | | |
* | pkt_cmd_acc | | | | | | |
* +================================+ | | | | | |
* | dma_cookies | <--+ | | | | |
* | | | | | | |
* +================================+ | | | | |
* | fca_private | <----+ | | | |
* | | | | | |
* +================================+ | | | |
* | | | |
* | | | |
* +================================+ (b) | | | |
* | fcp_resp cookies | <------+ | | |
* | | | | |
* +================================+ | | |
* | | |
* +================================+ (b) | | |
* | fcp_resp | <--------+ | |
* | (DMA resources associated) | | |
* +================================+ | |
* | |
* | |
* | |
* +================================+ (b) | |
* | fcp_cmd cookies | <----------+ |
* | | |
* +================================+ |
* |
* +================================+ (b) |
* | fcp_cmd | <------------+
* | (DMA resources associated) |
* +================================+
*
*
* (a) The underlying FCA does NOT support DMA for this field
* (b) The underlying FCA supports DMA for this field
*/
struct fcp_pkt {
/*
* The two following fields are used to queue fcp_pkt in the double
* link list of the lun structure. The packet is queued in
* tran_init_pkt(9E) and unqueued in tran_destroy_pkt(9E).
*/
struct fcp_pkt *cmd_forw;
struct fcp_pkt *cmd_back;
/*
* This field is used to queue the packet in the single link list of the
* port structure. The port keeps a list of all the commands issued
* through it and scans it, for example, when all of those commands
* have to be aborted.
*/
struct fcp_pkt *cmd_next;
/*
* This field points back to the scsi_pkt.
*/
struct scsi_pkt *cmd_pkt;
/*
* This field points to the field cmd_fc_packet defined further in this
* same structure.
*/
struct fc_packet *cmd_fp_pkt;
/*
* Structure where the FCP_CMD information unit is going to be built.
*/
fcp_cmd_t cmd_fcp_cmd;
/*
* State of the packet. The values for the state seem to indicate
* that it isn't a bitmap. However, in several instances the code
* treats it as a bitmap doing a "&= ~FCP_PKT_ISSUED" to it
* eventhough the value stored is always checked using "!=" and "==".
*/
uint_t cmd_state;
/*
* This field is a bitmap indicating if
* the cmd is queued
*/
uint_t cmd_flags;
/* Contains the number of bytes DMA mappped. */
uint_t cmd_dmacount;
/*
* Contains the timeout value for the packet. This is not a delay or
* a delta but an absolute value.
*/
uint_t cmd_timeout;
/*
* This array is used to store the FCP_RSP information unit returned by
* the device when the underlying FCA cannot DMA it in.
*/
char cmd_fcp_rsp[FCP_MAX_RSP_IU_SIZE];
/*
* This is the fc_packet structure used to forward the request to
* fp/fctl.
*/
struct fc_packet cmd_fc_packet;
};
/*
* fcp_ipkt : Packet for internal commands.
* ------------------------------------------
*
* +================================+
* | struct fcp_ipkt | <---------+
* | (kmem_zalloc()) | |
* | ipkt_fpkt | ---+ |
* | | | |
* | ipkt_cmdlen = cmd_len | | |
* | | | |
* | | | |
* | | | |
* |--------------------------------| | |
* | struct fc_packet | <--+ |
* | | |
* | pkt_ulp_private | ----------+
* | pkt_fca_private | -----+
* | pkt_data_cookie | ---+ |
* | pkt_cmdlen | | |
* | pkt_rsplen | | |
* | pkt_cmd ...................... | ---|-|-------+
* | pkt_cmd_cookie | ---|-|-----+ |
* | pkt_resp ..................... | ---|-|---+ | |
* | pkt_resp_cookie | ---|-|-+ | | |
* | pkt_cmd_dma | | | | | | |
* | pkt_cmd_acc | | | | | | |
* +================================+ | | | | | |
* | dma_cookies | <--+ | | | | |
* | | | | | | |
* | | | | | | |
* | | | | | | |
* +================================+ | | | | |
* | fca_private | <----+ | | | |
* | | | | | |
* | | | | | |
* | | | | | |
* +================================+ | | | |
* | | | |
* | | | |
* +================================+ (b) | | | |
* | fcp_resp cookies | <------+ | | |
* | | | | |
* +================================+ | | |
* | | |
* +================================+ (b) | | |
* | fcp_resp | <--------+ | |
* | (DMA resources associated) | | |
* +================================+ | |
* | |
* | |
* | |
* +================================+ (b) | |
* | fcp_cmd cookies | <----------+ |
* | | |
* +================================+ |
* |
* +================================+ (b) |
* | fcp_cmd | <------------+
* | (DMA resources associated) |
* +================================+
*
* (a) The underlying FCA does NOT support DMA for this field
* (b) The underlying FCA supports DMA for this field
*/
struct fcp_ipkt {
/*
* Pointer to the port (fcp_port) in behalf of which this internal
* packet was allocated.
*/
struct fcp_port *ipkt_port;
/*
* Pointer to the target (fcp_tgt) in behalf of which this internal
* packet was allocated.
*/
struct fcp_tgt *ipkt_tgt;
/*
* Pointer to the lun (fcp_lun) in behalf of which this internal
* packet was allocated. This field is only meaningful when the
* internal packet has been allocated for a "scsi passthru" command or
* for an internal SCSI command such as REPORT LUNs and INQUIRY.
*/
struct fcp_lun *ipkt_lun;
/*
* Fields used to queue the internal packet into the double linked list
* of the FCP port (fcp_port).
*/
struct fcp_ipkt *ipkt_next;
struct fcp_ipkt *ipkt_prev;
/*
* This field points to the field ipkt_fc_packet defined farther in
* this same structure.
*/
struct fc_packet *ipkt_fpkt;
/*
* This is the timeout value for the internal packet. It seems to
* increase with the number of retries. It is initialized like this
* in the code:
*
* icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++
*
* First time ipkt_retries is zero. As it increases, the timeout
* value for the internal packet also increases.
*/
uint32_t ipkt_restart;
/*
* Link state counter when the internal packet was built.
*/
uint32_t ipkt_link_cnt;
int ipkt_cause;
uint32_t ipkt_cmdlen;
uint32_t ipkt_resplen;
uint32_t ipkt_datalen;
/*
* Counter of the times an internal packet has been retried. Its
* value is checked against FCP_MAX_RETRIES.
*/
uint32_t ipkt_retries;
uint32_t ipkt_change_cnt;
int ipkt_nodma;
/*
* Semaphore used to wait for completion on.
*/
ksema_t ipkt_sema;
/*
* Opcode indicating what internal command the packet contains (PLOGI,
* PRLI, INQUIRY...).
*/
uchar_t ipkt_opcode;
/*
* FC packet.
*/
struct fc_packet ipkt_fc_packet;
};
/*
* cmd_state definitions
*/
#define FCP_PKT_IDLE 0x1
#define FCP_PKT_ISSUED 0x2
#define FCP_PKT_ABORTING 0x3
/*
* These are the defined cmd_flags for this structure.
*/
#define CFLAG_IN_QUEUE 0x2000 /* command in fcp queue */
/*
* Target structure
* ----------------
*
* This structure holds the information relative to a SCSI target. This
* structure doesn't represent the object registered with the OS (NDI or
* MPxIO...).
*/
struct fcp_tgt {
/*
* This field is used to queue the target structure in one of the
* buckets of the fcp_port target hash table port_tgt_hash_table[].
*/
struct fcp_tgt *tgt_next;
/* Points to the fcp_port the target belongs to. */
struct fcp_port *tgt_port;
/*
* This field is a bitmap indicating the state of the target. Several
* bits can be set simultaneously.
*/
uint32_t tgt_state;
/*
* State controlling if the LUNs attached to this target will be
* automatically onlined or not.
*/
uint32_t tgt_node_state;
/*
* Mutex protecting this structure.
*/
kmutex_t tgt_mutex;
/*
* List of LUNs (single link list).
*/
struct fcp_lun *tgt_lun;
opaque_t tgt_fca_dev;
/*
* Number of LUNs in this target.
*/
uint_t tgt_lun_cnt;
/*
* Counter of LUNs to probe. It is used during the discovery
* process. Starts with the number of LUNs returned by REPORT_LUN
* and is decremented until it reaches zero.
*/
uint_t tgt_tmp_cnt;
/*
* fp/fctl handle for the "port_device".
*/
opaque_t tgt_pd_handle;
/*
* Node World Wide Name.
*/
la_wwn_t tgt_node_wwn;
/*
* Port World Wide Name.
*/
la_wwn_t tgt_port_wwn;
/*
* Fibre Channel Port ID.
*/
uint32_t tgt_d_id;
/*
* Fibre Channel Port ID. Uses bit fields to represent it.
*/
uint32_t tgt_hard_addr;
/*
* Becomes 1 when the LUNs are created.
*/
uchar_t tgt_device_created;
/*
* Counter of how many REPORT_LUN commands were sent. It is used to
* allow the REPORT_LUN command to be sent twice in case the buffer
* allocated the first time wasn't big enough.
*/
uchar_t tgt_report_lun_cnt;
/*
* This field is incremented each time the field tgt_state is updated.
* Its use is similar to the use of the field port_link_cnt in the
* fcp_port structure. The internal packets are, for example, tagged
* with the value stored here.
*/
uint32_t tgt_change_cnt;
/*
* This field contains the cause of the last change in state.
*/
int tgt_statec_cause;
/*
* The following two fields indicate whether the remote port is an
* FCP initiator or an FCP target. They are treated as booleans.
*/
uchar_t tgt_icap; /* Initiator */
uchar_t tgt_tcap; /* Target */
#ifdef DEBUG
/*
* Updated in fcp_call_finish_init_held() when DEBUG is defined
*/
int tgt_tmp_cnt_depth;
pc_t tgt_tmp_cnt_stack[FCP_STACK_DEPTH];
#endif /* DEBUG */
/*
* This field holds the timer id of the timer started when a LUN
* reconfiguration is needed for the target. The reconfiguration
* is done in the timeout function.
*/
timeout_id_t tgt_tid;
int tgt_done;
/*
* Bitmap used to trace the discovery process.
*/
uint32_t tgt_trace;
/*
* This field is used when the code is sorting out which devices
* were known which ones are new and which ones went away.
*/
uint32_t tgt_aux_state;
/*
* Number of internal packets allocated in behalf of the target.
*/
int tgt_ipkt_cnt;
/*
* used to detect user unconfig when auto configuration is enabled.
*/
uint32_t tgt_manual_config_only;
};
/*
* Target States
*/
#define FCP_TGT_INIT 0x01
#define FCP_TGT_BUSY 0x02
#define FCP_TGT_MARK 0x04
#define FCP_TGT_OFFLINE 0x08
#define FCP_TGT_ORPHAN 0x80
#define FCP_TGT_ILLREQ 0x10
/*
* Target Aux Stat
*/
#define FCP_TGT_TAGGED 0x01
/*
* Target discovery tracing
*/
#define FCP_TGT_TRACE_1 0x00000001
#define FCP_TGT_TRACE_2 0x00000002
#define FCP_TGT_TRACE_3 0x00000004
#define FCP_TGT_TRACE_4 0x00000008
#define FCP_TGT_TRACE_5 0x00000010
#define FCP_TGT_TRACE_6 0x00000020
#define FCP_TGT_TRACE_7 0x00000040
#define FCP_TGT_TRACE_8 0x00000080
#define FCP_TGT_TRACE_9 0x00000100
#define FCP_TGT_TRACE_10 0x00000200
#define FCP_TGT_TRACE_11 0x00000400
#define FCP_TGT_TRACE_12 0x00000800
#define FCP_TGT_TRACE_13 0x00001000
#define FCP_TGT_TRACE_14 0x00002000
#define FCP_TGT_TRACE_15 0x00004000
#define FCP_TGT_TRACE_16 0x00008000
#define FCP_TGT_TRACE_17 0x00010000
#define FCP_TGT_TRACE_18 0x00020000
#define FCP_TGT_TRACE_19 0x00040000
#define FCP_TGT_TRACE_20 0x00080000
#define FCP_TGT_TRACE_21 0x00100000
#define FCP_TGT_TRACE_22 0x00200000
#define FCP_TGT_TRACE_23 0x00400000
#define FCP_TGT_TRACE_24 0x00800000
#define FCP_TGT_TRACE_25 0x01000000
#define FCP_TGT_TRACE_26 0x02000000
#define FCP_TGT_TRACE_27 0x04000000
#define FCP_TGT_TRACE_28 0x08000000
#define FCP_TGT_TRACE_29 0x10000000
#ifndef __lock_lint
#define FCP_TGT_TRACE(ptgt, tcount, bit) {\
if (ptgt) {\
if (ptgt->tgt_change_cnt == tcount) {\
ptgt->tgt_trace |= bit;\
}\
}\
}
#else /* __lock_lint */
#define FCP_TGT_TRACE(ptgt, tcount, bit)
#endif /* __lock_lint */
/*
* state change cause
*/
#define FCP_CAUSE_TGT_CHANGE 0x01
#define FCP_CAUSE_LINK_CHANGE 0x02
#define FCP_CAUSE_LINK_DOWN 0x04
#define FCP_CAUSE_USER_CREATE 0x08
/*
* Target node states (applicable to LUNs behind the target)
*/
#define FCP_TGT_NODE_NONE 0x00 /* No node exists */
#define FCP_TGT_NODE_ON_DEMAND 0x01 /* create only upon request */
#define FCP_TGT_NODE_PRESENT 0x02 /* Node exists; rediscover it */
#define FCP_NO_CHANGE 0x1
#define FCP_LINK_CHANGE 0x2
#define FCP_DEV_CHANGE 0x3
/* hotplug event struct */
struct fcp_hp_event {
int (*callback)();
void *arg;
};
/*
* We talk to both NDI and MDI framework to enumerate our child devices.
* We internally define a generic child handle and assign either dev_info
* or mdi_pathinfo handle depending on the device.
*/
typedef void *child_info_t;
#define CIP(child) ((child_info_t *)(child))
#define DIP(child) ((dev_info_t *)(child))
#define PIP(child) ((mdi_pathinfo_t *)(child))
/*
* LUN structure
* -------------
*
* This structure holds the information relative to a SCSI LUN. This
* structure is the one representing the object registered with the OS (NDI
* or MPxIO...).
*/
struct fcp_lun {
/*
* Mutex protecting the access to this structure.
*/
kmutex_t lun_mutex;
/*
* Logical unit number. It is a SCSI3 format.
*/
fcp_ent_addr_t lun_addr;
/*
* The two following fields are respectively the head and tail of a
* double link list of fcp_packets. It is populated in
* tran_init_pkt(9E) (fcp_scsi_init_pkt) and emptied in
* tran_destroy_pkt(9E) (fcp_scsi_destroy_pkt).
*/
struct fcp_pkt *lun_pkt_head;
struct fcp_pkt *lun_pkt_tail;
/*
* This field is treated like a union. It may contain the dev_info_t
* or the mdi_pathinfo_t depending on how the device associated with
* this LUN was registered.
*/
child_info_t *lun_cip;
/*
* Online/Offline event count.
*/
int lun_event_count;
/*
* Back pointer to the target the LUN belongs to.
*/
struct fcp_tgt *lun_tgt;
/*
* Bit map reflecting the state of the LUN.
*/
uint_t lun_state;
/*
* LUN type (disk, tape...). The value stored here is taken from the
* inquiry data.
*/
uchar_t lun_type;
/*
* This field is incremented each time fcp_scsi_tgt_init()
* (tran_tgt_init(9E)) is called and decremented each time
* fcp_scsi_tgt_free() (tran_tgt_free(9E)) is called. The
* incrementation and decrementation will also have an effect on
* lun_state bit FCP_SCSI_LUN_TGT_INIT.
*/
uchar_t lun_tgt_count;
/*
* LUN number as it is returned by REPORT_LUNS.
*/
uint16_t lun_num;
/*
* Pointer to the next LUN.
*/
struct fcp_lun *lun_next;
/*
* SCSI Host Bus Adapter (HBA) driver transport vector structure.
*/
struct scsi_hba_tran *lun_tran;
/*
* per-Lun control flag. A value of '1' means the LUN is managed by
* mpxio. A value of '0' means the LUN has been physically enumerated
* as a child of corresponding port driver node.
*/
int lun_mpxio;
/*
* Length of the GUID.
*/
size_t lun_guid_size;
/*
* Pointer to a buffer that contains the GUID.
*/
char *lun_guid;
/*
* Pointer to a buffer that contains the old GUID.
*/
char *lun_old_guid;
/*
* Length of the old GUID
*/
size_t lun_old_guid_size;
/*
* Bitmap used to track the LUN discovery process.
*/
uint32_t lun_trace;
/*
* Bitmap representing the SCSI capabilities.
*/
uchar_t lun_cap;
/*
* LUN inquiry data (as returned by the INQUIRY command).
*/
struct scsi_inquiry lun_inq;
};
/*
* Lun discovery tracing
*/
#define FCP_LUN_TRACE_1 0x0000001
#define FCP_LUN_TRACE_2 0x0000002
#define FCP_LUN_TRACE_3 0x0000004
#define FCP_LUN_TRACE_4 0x0000008
#define FCP_LUN_TRACE_5 0x0000010
#define FCP_LUN_TRACE_6 0x0000020
#define FCP_LUN_TRACE_7 0x0000040
#define FCP_LUN_TRACE_8 0x0000080
#define FCP_LUN_TRACE_9 0x0000100
#define FCP_LUN_TRACE_10 0x0000200
#define FCP_LUN_TRACE_11 0x0000400
#define FCP_LUN_TRACE_12 0x0000800
#define FCP_LUN_TRACE_13 0x0001000
#define FCP_LUN_TRACE_14 0x0002000
#define FCP_LUN_TRACE_15 0x0004000
#define FCP_LUN_TRACE_16 0x0008000
#define FCP_LUN_TRACE_17 0x0010000
#define FCP_LUN_TRACE_18 0x0020000
#define FCP_LUN_TRACE_19 0x0040000
#define FCP_LUN_TRACE_20 0x0080000
#define FCP_LUN_TRACE_21 0x0100000
#define FCP_LUN_TRACE_22 0x0200000
#define FCP_LUN_TRACE_23 0x0400000
#define FCP_LUN_TRACE_24 0x0800000
#define FCP_LUN_TRACE_25 0x1000000
#define FCP_LUN_TRACE_26 0x2000000
#define FCP_LUN_TRACE_27 0x4000000
#define FCP_LUN_TRACE_28 0x8000000
#define FCP_LUN_TRACE(plun, bit) {\
if (plun && plun->lun_tgt) {\
mutex_enter(&plun->lun_tgt->tgt_mutex);\
plun->lun_trace |= bit;\
mutex_exit(&plun->lun_tgt->tgt_mutex);\
}\
}
#define FCP_LUN_CAP_RESET 0x01
/*
* Lun State -- these have the same values as the target states so
* that they can be interchanged (in cases where the same state occurs
* for both targets and luns)
*/
#define FCP_LUN_INIT FCP_TGT_INIT
#define FCP_LUN_BUSY FCP_TGT_BUSY
#define FCP_LUN_MARK FCP_TGT_MARK
#define FCP_LUN_OFFLINE FCP_TGT_OFFLINE
#define FCP_SCSI_LUN_TGT_INIT 0x20 /* target/LUNs all inited */
#define FCP_LUN_DISAPPEARED 0x40
/*
* Use the below flag with caution as it is can cause a delay in
* fcp_scsi_start() which is in the normal I/O performance path
*/
#define FCP_LUN_ONLINING 0x80
/*
* Set the below flag when the DTYPE or GUID of a LUN changes during discovery
*/
#define FCP_LUN_CHANGED 0x100
/*
* This flag is used specifically for the special lun: lun 0.
*/
#define FCP_LUN_DEVICE_NOT_CONNECTED 0x200
/*
* Report Lun Format
*/
struct fcp_reportlun_resp {
uint32_t num_lun; /* num LUNs * 8 */
uint32_t reserved;
longlong_t lun_string[1];
};
/*
* This structure actually represents a request executed by the hot plug task.
*/
struct fcp_hp_elem {
/*
* FCP port concerned by the request.
*/
struct fcp_port *port;
/*
* LUN concerned by the request.
*/
struct fcp_lun *lun;
/*
* dev_info_t or mdi_pathinfo_t pointer.
*/
child_info_t *cip;
/*
* What to do (offline, online...).
*/
int what;
/*
* FLags used when calling NDI fucntions.
*/
int flags;
/*
* Link state change count when the structure was created.
*/
int link_cnt;
/*
* Target state change count when the structure was created.
*/
int tgt_cnt;
/*
* Online/Offline count when this event was queued.
*/
int event_cnt;
/*
* This is the flag protected by the mutex and condition variable
* defined further in this structure. It is the flag indicating
* that the hot plug task is done with the treatment of the structure.
*/
int wait;
/*
* This is where the result of the request is returned when the sender
* waits for the completion.
*/
int result;
/*
* Condition variable used when wait is true.
*/
kcondvar_t cv;
/*
* Mutex used in conjunction with the previous condition variable.
*/
kmutex_t mutex;
};
struct fcp_reset_elem {
struct fcp_reset_elem *next;
struct fcp_tgt *tgt;
struct fcp_lun *lun;
clock_t timeout;
uint_t tgt_cnt;
};
/*
* This structure is used to offline targets. It is queued in the FCP port
* structure single linked list port_offline_tgts and walked by the watchdog
* timer.
*/
struct fcp_tgt_elem {
/*
* Points to the next element of the list.
*/
struct fcp_tgt_elem *next;
/*
* Points to the target to offline.
*/
struct fcp_tgt *ptgt;
/*
* Absolute time after which the target must be offlined.
*/
int time;
/*
* Link state change count when the structure was created.
*/
int link_cnt;
/*
* Target state change count when the structure was created.
*/
int tgt_cnt;
/*
* Flags providing information for the offline (when calling mdi or
* ndi).
*/
int flags;
};
/*
* This structure is used to offline LUNs. It is queued in the FCP port
* structure single linked list port_offline_luns and walked by the watchdog
* timer.
*/
struct fcp_lun_elem {
/*
* Points to the next element of the list.
*/
struct fcp_lun_elem *next;
/*
* Points to the LUN to offline.
*/
struct fcp_lun *plun;
/*
* Absolute time after which the LUN must be offlined.
*/
int time;
/*
* Link state change count when the structure was created.
*/
int link_cnt;
/*
* Target state change count when the structure was created.
*/
int tgt_cnt;
/*
* Flags providing information for the offline (when calling mdi or
* ndi).
*/
int flags;
};
/*
* LUN masking
*/
typedef struct fcp_black_list_entry {
/*
* Points to the next element of the list.
*/
struct fcp_black_list_entry *next;
/*
* Port WWN of the target.
*/
la_wwn_t wwn;
/*
* LUN number which need to be masked.
*/
uint32_t lun;
/*
* Counter of access times.
*/
int masked;
} fcp_black_list_entry_t;
#define ADDR2FCP(ap) (struct fcp_port *) \
((ap)->a_hba_tran->tran_hba_private)
#define ADDR2LUN(ap) (struct fcp_lun *)((ap)->a_hba_tran->tran_tgt_private)
#define CMD2PKT(cmd) ((cmd)->cmd_pkt)
#define PKT2CMD(pkt) ((struct fcp_pkt *)pkt->pkt_ha_private)
/*
* timeout values
*/
#define FCP_ELS_TIMEOUT 20 /* 20 seconds */
#define FCP_SCSI_CMD_TIMEOUT 25 /* 30 seconds */
#define FCP_POLL_TIMEOUT 60 /* 60 seconds */
#define FCP_TIMEOUT_DELTA 2 /* 2 seconds */
#define FCP_ICMD_DEADLINE 120 /* 60 seconds */
#define FCP_MAX_RETRIES 4
#if !defined(__lint)
_NOTE(MUTEX_PROTECTS_DATA(fcp_port::port_mutex,
fcp_port::port_state fcp_tgt::tgt_change_cnt
fcp_port::fcp_next fcp_port::port_tgt_hash_table
fcp_port::port_link_cnt fcp_port::port_reset_list
fcp_port::port_tmp_cnt fcp_port::port_ipkt_list
fcp_tgt::tgt_next))
_NOTE(MUTEX_PROTECTS_DATA(fcp_port::port_pkt_mutex,
fcp_port::port_pkt_head fcp_port::port_pkt_tail
fcp_port::port_npkts))
_NOTE(MUTEX_PROTECTS_DATA(fcp_tgt::tgt_mutex,
fcp_tgt::tgt_state fcp_tgt::tgt_device_created
fcp_tgt::tgt_icap fcp_tgt::tgt_tcap
fcp_tgt::tgt_tid fcp_tgt::tgt_pd_handle fcp_tgt::tgt_tmp_cnt
fcp_tgt::tgt_statec_cause fcp_lun::lun_next fcp_lun::lun_state))
_NOTE(LOCK_ORDER(fcp_port::fcp_mutex fcp_tgt::tgt_mutex))
_NOTE(LOCK_ORDER(fcp_tgt::tgt_mutex fcp_lun::lun_mutex))
_NOTE(MUTEX_PROTECTS_DATA(fcp_lun::lun_mutex,
fcp_lun::lun_pkt_head fcp_lun::lun_pkt_tail
fcp_lun::lun_cip fcp_lun::lun_mpxio))
_NOTE(DATA_READABLE_WITHOUT_LOCK( fcp_tgt::tgt_state))
_NOTE(DATA_READABLE_WITHOUT_LOCK( fcp_tgt::tgt_pd_handle))
_NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_tgt::tgt_tid))
_NOTE(SCHEME_PROTECTS_DATA("Safe Data",
fcp_port::port_dma_acc_attr
fcp_port::port_fcp_dma fcp_port::fcp_tran
fcp_port::port_ndi_events fcp_port::port_ndi_event_defs
fcp_port::port_pkt_cache fcp_port::port_dip fcp_port::port_phys_state
fcp_port::port_reset_action fcp_port::port_cmds_dma_flags
fcp_port::port_fp_handle fcp_port::port_instance
fcp_port::port_fp_modlinkage fcp_port::port_max_exch
fcp_port::port_priv_pkt_len fcp_port::port_id
fcp_port::port_topology fcp_port::port_deadline fcp_port::port_mpxio
fcp_tgt::tgt_d_id fcp_tgt::tgt_hard_addr fcp_tgt::tgt_lun_cnt
fcp_tgt::tgt_port fcp_lun::lun_num fcp_lun::lun_tgt
fcp_lun::lun_type
fcp_lun::lun_guid_size fcp_lun::lun_guid
fcp_hp_elem::lun fcp_hp_elem::flags fcp_hp_elem::cip
fcp_hp_elem::what fcp_hp_elem::tgt_cnt fcp_hp_elem::tgt_cnt
fcp_hp_elem::link_cnt fcp_reset_elem fcp_pkt fcp_ipkt
scsi_pkt scsi_arq_status scsi_device scsi_hba_tran scsi_cdb))
#endif /* __lint */
#define FCP_CP_IN(s, d, handle, len) (ddi_rep_get8((handle), \
(uint8_t *)(d), (uint8_t *)(s), \
(len), DDI_DEV_AUTOINCR))
#define FCP_CP_OUT(s, d, handle, len) (ddi_rep_put8((handle), \
(uint8_t *)(s), (uint8_t *)(d), \
(len), DDI_DEV_AUTOINCR))
#define FCP_ONLINE 0x1
#define FCP_OFFLINE 0x2
#define FCP_MPXIO_PATH_CLEAR_BUSY 0x3
#define FCP_MPXIO_PATH_SET_BUSY 0x4
#define FCP_IDLE 0x00
#define FCP_OPEN 0x01
#define FCP_EXCL 0x02
#define FCP_BUSY 0x04
#define LFA(x) (x & 0xFFFF00)
#define FCP_SET 1
#define FCP_RESET 0
/* init() and attach() wait timeout values (in usecs) */
#define FCP_INIT_WAIT_TIMEOUT 60000000 /* 60 seconds */
#define FCP_ATTACH_WAIT_TIMEOUT 10000000 /* 10 seconds */
#ifdef TRUE
#undef TRUE
#endif
#define TRUE 1
#ifdef FALSE
#undef FALSE
#endif
#define FALSE 0
#define UNDEFINED -1
/* for softstate */
#define FCP_INIT_ITEMS 5
#ifdef __cplusplus
}
#endif
#endif /* _FCPVAR_H */