diff options
| author | James Smart <James.Smart@Emulex.Com> | 2007-04-27 12:41:09 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-16 09:36:15 -0400 |
| commit | a53eb5e060c0ec7245c8f93b9dcd94afa6041e06 (patch) | |
| tree | 5e5747a715142c6eb1b89f9550477e2d1df318f0 /include/scsi | |
| parent | 7b104bcb8e460e45a1aebe3da9b86aacdb4cab12 (diff) | |
[SCSI] FC Transport support for vports based on NPIV
This patch provides support for FC virtual ports based on NPIV.
For information on the interfaces and design, please read the
Documentation/scsi/scsi_fc_transport.txt file enclosed within
the patch.
The RFC was originally posted here:
http://marc.info/?l=linux-scsi&m=117226959918393&w=2
Changes from the initial RFC:
- Bug fix: needed a transport_class_unregister() for the vport class
- Create a symlink to the vport in the shost device if it is not the
parent of the vport.
- Made symbolic name writable so it can be set after creation
- Made the temporary fc_vport_identifiers struct private to the
transport.
- Deleted the vport_id field from the vport. I couldn't find any good
use for it (and symname is a good replacement).
- Made the vport_state and vport_last_state "private" attributes.
Added the fc_vport_set_state() helper function to manage state
transitions
- Updated vport_create() to allow a vport to be created in a disabled
state.
- Added INITIALIZING and FAILED vport states
- Added VPCERR_xxx defines for errors to be returned from vport_create()
- Created a Documentation/scsi/scsi_fc_transport.txt file that describes
the interfaces and expected LLDD behaviors.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'include/scsi')
| -rw-r--r-- | include/scsi/scsi_transport_fc.h | 173 |
1 files changed, 166 insertions, 7 deletions
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 1e797308640a..81ea7b4bf81e 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | * | 19 | * |
| 20 | * ======== | 20 | * ======== |
| 21 | * | 21 | * |
| 22 | * Copyright (C) 2004-2005 James Smart, Emulex Corporation | 22 | * Copyright (C) 2004-2007 James Smart, Emulex Corporation |
| 23 | * Rewrite for host, target, device, and remote port attributes, | 23 | * Rewrite for host, target, device, and remote port attributes, |
| 24 | * statistics, and service functions... | 24 | * statistics, and service functions... |
| 25 | * | 25 | * |
| @@ -62,8 +62,10 @@ enum fc_port_type { | |||
| 62 | FC_PORTTYPE_NLPORT, /* (Public) Loop w/ FLPort */ | 62 | FC_PORTTYPE_NLPORT, /* (Public) Loop w/ FLPort */ |
| 63 | FC_PORTTYPE_LPORT, /* (Private) Loop w/o FLPort */ | 63 | FC_PORTTYPE_LPORT, /* (Private) Loop w/o FLPort */ |
| 64 | FC_PORTTYPE_PTP, /* Point to Point w/ another NPort */ | 64 | FC_PORTTYPE_PTP, /* Point to Point w/ another NPort */ |
| 65 | FC_PORTTYPE_NPIV, /* VPORT based on NPIV */ | ||
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 68 | |||
| 67 | /* | 69 | /* |
| 68 | * fc_port_state: If you alter this, you also need to alter scsi_transport_fc.c | 70 | * fc_port_state: If you alter this, you also need to alter scsi_transport_fc.c |
| 69 | * (for the ascii descriptions). | 71 | * (for the ascii descriptions). |
| @@ -83,6 +85,25 @@ enum fc_port_state { | |||
| 83 | }; | 85 | }; |
| 84 | 86 | ||
| 85 | 87 | ||
| 88 | /* | ||
| 89 | * fc_vport_state: If you alter this, you also need to alter | ||
| 90 | * scsi_transport_fc.c (for the ascii descriptions). | ||
| 91 | */ | ||
| 92 | enum fc_vport_state { | ||
| 93 | FC_VPORT_UNKNOWN, | ||
| 94 | FC_VPORT_ACTIVE, | ||
| 95 | FC_VPORT_DISABLED, | ||
| 96 | FC_VPORT_LINKDOWN, | ||
| 97 | FC_VPORT_INITIALIZING, | ||
| 98 | FC_VPORT_NO_FABRIC_SUPP, | ||
| 99 | FC_VPORT_NO_FABRIC_RSCS, | ||
| 100 | FC_VPORT_FABRIC_LOGOUT, | ||
| 101 | FC_VPORT_FABRIC_REJ_WWN, | ||
| 102 | FC_VPORT_FAILED, | ||
| 103 | }; | ||
| 104 | |||
| 105 | |||
| 106 | |||
| 86 | /* | 107 | /* |
| 87 | * FC Classes of Service | 108 | * FC Classes of Service |
| 88 | * Note: values are not enumerated, as they can be "or'd" together | 109 | * Note: values are not enumerated, as they can be "or'd" together |
| @@ -124,18 +145,115 @@ enum fc_tgtid_binding_type { | |||
| 124 | }; | 145 | }; |
| 125 | 146 | ||
| 126 | /* | 147 | /* |
| 127 | * FC Remote Port Roles | 148 | * FC Port Roles |
| 128 | * Note: values are not enumerated, as they can be "or'd" together | 149 | * Note: values are not enumerated, as they can be "or'd" together |
| 129 | * for reporting (e.g. report roles). If you alter this list, | 150 | * for reporting (e.g. report roles). If you alter this list, |
| 130 | * you also need to alter scsi_transport_fc.c (for the ascii descriptions). | 151 | * you also need to alter scsi_transport_fc.c (for the ascii descriptions). |
| 131 | */ | 152 | */ |
| 132 | #define FC_RPORT_ROLE_UNKNOWN 0x00 | 153 | #define FC_PORT_ROLE_UNKNOWN 0x00 |
| 133 | #define FC_RPORT_ROLE_FCP_TARGET 0x01 | 154 | #define FC_PORT_ROLE_FCP_TARGET 0x01 |
| 134 | #define FC_RPORT_ROLE_FCP_INITIATOR 0x02 | 155 | #define FC_PORT_ROLE_FCP_INITIATOR 0x02 |
| 135 | #define FC_RPORT_ROLE_IP_PORT 0x04 | 156 | #define FC_PORT_ROLE_IP_PORT 0x04 |
| 157 | |||
| 158 | /* The following are for compatibility */ | ||
| 159 | #define FC_RPORT_ROLE_UNKNOWN FC_PORT_ROLE_UNKNOWN | ||
| 160 | #define FC_RPORT_ROLE_FCP_TARGET FC_PORT_ROLE_FCP_TARGET | ||
| 161 | #define FC_RPORT_ROLE_FCP_INITIATOR FC_PORT_ROLE_FCP_INITIATOR | ||
| 162 | #define FC_RPORT_ROLE_IP_PORT FC_PORT_ROLE_IP_PORT | ||
| 163 | |||
| 164 | |||
| 165 | /* Macro for use in defining Virtual Port attributes */ | ||
| 166 | #define FC_VPORT_ATTR(_name,_mode,_show,_store) \ | ||
| 167 | struct class_device_attribute class_device_attr_vport_##_name = \ | ||
| 168 | __ATTR(_name,_mode,_show,_store) | ||
| 136 | 169 | ||
| 137 | 170 | ||
| 138 | /* | 171 | /* |
| 172 | * FC Virtual Port Attributes | ||
| 173 | * | ||
| 174 | * This structure exists for each FC port is a virtual FC port. Virtual | ||
| 175 | * ports share the physical link with the Physical port. Each virtual | ||
| 176 | * ports has a unique presense on the SAN, and may be instantiated via | ||
| 177 | * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a | ||
| 178 | * unique presense, each vport has it's own view of the fabric, | ||
| 179 | * authentication priviledge, and priorities. | ||
| 180 | * | ||
| 181 | * A virtual port may support 1 or more FC4 roles. Typically it is a | ||
| 182 | * FCP Initiator. It could be a FCP Target, or exist sole for an IP over FC | ||
| 183 | * roles. FC port attributes for the vport will be reported on any | ||
| 184 | * fc_host class object allocated for an FCP Initiator. | ||
| 185 | * | ||
| 186 | * -- | ||
| 187 | * | ||
| 188 | * Fixed attributes are not expected to change. The driver is | ||
| 189 | * expected to set these values after receiving the fc_vport structure | ||
| 190 | * via the vport_create() call from the transport. | ||
| 191 | * The transport fully manages all get functions w/o driver interaction. | ||
| 192 | * | ||
| 193 | * Dynamic attributes are expected to change. The driver participates | ||
| 194 | * in all get/set operations via functions provided by the driver. | ||
| 195 | * | ||
| 196 | * Private attributes are transport-managed values. They are fully | ||
| 197 | * managed by the transport w/o driver interaction. | ||
| 198 | */ | ||
| 199 | |||
| 200 | #define FC_VPORT_SYMBOLIC_NAMELEN 64 | ||
| 201 | struct fc_vport { | ||
| 202 | /* Fixed Attributes */ | ||
| 203 | |||
| 204 | /* Dynamic Attributes */ | ||
| 205 | |||
| 206 | /* Private (Transport-managed) Attributes */ | ||
| 207 | enum fc_vport_state vport_state; | ||
| 208 | enum fc_vport_state vport_last_state; | ||
| 209 | u64 node_name; | ||
| 210 | u64 port_name; | ||
| 211 | u32 roles; | ||
| 212 | u32 vport_id; /* Admin Identifier for the vport */ | ||
| 213 | enum fc_port_type vport_type; | ||
| 214 | char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN]; | ||
| 215 | |||
| 216 | /* exported data */ | ||
| 217 | void *dd_data; /* Used for driver-specific storage */ | ||
| 218 | |||
| 219 | /* internal data */ | ||
| 220 | struct Scsi_Host *shost; /* Physical Port Parent */ | ||
| 221 | unsigned int channel; | ||
| 222 | u32 number; | ||
| 223 | u8 flags; | ||
| 224 | struct list_head peers; | ||
| 225 | struct device dev; | ||
| 226 | } __attribute__((aligned(sizeof(unsigned long)))); | ||
| 227 | |||
| 228 | /* bit field values for struct fc_vport "flags" field: */ | ||
| 229 | #define FC_VPORT_CREATING 0x01 | ||
| 230 | #define FC_VPORT_DELETING 0x02 | ||
| 231 | #define FC_VPORT_DELETED 0x04 | ||
| 232 | #define FC_VPORT_DEL 0x06 /* Any DELETE state */ | ||
| 233 | |||
| 234 | #define dev_to_vport(d) \ | ||
| 235 | container_of(d, struct fc_vport, dev) | ||
| 236 | #define transport_class_to_vport(classdev) \ | ||
| 237 | dev_to_vport(classdev->dev) | ||
| 238 | #define vport_to_shost(v) \ | ||
| 239 | (v->shost) | ||
| 240 | #define vport_to_shost_channel(v) \ | ||
| 241 | (v->channel) | ||
| 242 | #define vport_to_parent(v) \ | ||
| 243 | (v->dev.parent) | ||
| 244 | |||
| 245 | |||
| 246 | /* Error return codes for vport_create() callback */ | ||
| 247 | #define VPCERR_UNSUPPORTED -ENOSYS /* no driver/adapter | ||
| 248 | support */ | ||
| 249 | #define VPCERR_BAD_WWN -ENOTUNIQ /* driver validation | ||
| 250 | of WWNs failed */ | ||
| 251 | #define VPCERR_NO_FABRIC_SUPP -EOPNOTSUPP /* Fabric connection | ||
| 252 | is loop or the | ||
| 253 | Fabric Port does | ||
| 254 | not support NPIV */ | ||
| 255 | |||
| 256 | /* | ||
| 139 | * fc_rport_identifiers: This set of data contains all elements | 257 | * fc_rport_identifiers: This set of data contains all elements |
| 140 | * to uniquely identify a remote FC port. The driver uses this data | 258 | * to uniquely identify a remote FC port. The driver uses this data |
| 141 | * to report the existence of a remote FC port in the topology. Internally, | 259 | * to report the existence of a remote FC port in the topology. Internally, |
| @@ -149,6 +267,7 @@ struct fc_rport_identifiers { | |||
| 149 | u32 roles; | 267 | u32 roles; |
| 150 | }; | 268 | }; |
| 151 | 269 | ||
| 270 | |||
| 152 | /* Macro for use in defining Remote Port attributes */ | 271 | /* Macro for use in defining Remote Port attributes */ |
| 153 | #define FC_RPORT_ATTR(_name,_mode,_show,_store) \ | 272 | #define FC_RPORT_ATTR(_name,_mode,_show,_store) \ |
| 154 | struct class_device_attribute class_device_attr_rport_##_name = \ | 273 | struct class_device_attribute class_device_attr_rport_##_name = \ |
| @@ -343,6 +462,7 @@ struct fc_host_attrs { | |||
| 343 | u8 supported_fc4s[FC_FC4_LIST_SIZE]; | 462 | u8 supported_fc4s[FC_FC4_LIST_SIZE]; |
| 344 | u32 supported_speeds; | 463 | u32 supported_speeds; |
| 345 | u32 maxframe_size; | 464 | u32 maxframe_size; |
| 465 | u16 max_npiv_vports; | ||
| 346 | char serial_number[FC_SERIAL_NUMBER_SIZE]; | 466 | char serial_number[FC_SERIAL_NUMBER_SIZE]; |
| 347 | 467 | ||
| 348 | /* Dynamic Attributes */ | 468 | /* Dynamic Attributes */ |
| @@ -361,8 +481,11 @@ struct fc_host_attrs { | |||
| 361 | /* internal data */ | 481 | /* internal data */ |
| 362 | struct list_head rports; | 482 | struct list_head rports; |
| 363 | struct list_head rport_bindings; | 483 | struct list_head rport_bindings; |
| 484 | struct list_head vports; | ||
| 364 | u32 next_rport_number; | 485 | u32 next_rport_number; |
| 365 | u32 next_target_id; | 486 | u32 next_target_id; |
| 487 | u32 next_vport_number; | ||
| 488 | u16 npiv_vports_inuse; | ||
| 366 | 489 | ||
| 367 | /* work queues for rport state manipulation */ | 490 | /* work queues for rport state manipulation */ |
| 368 | char work_q_name[KOBJ_NAME_LEN]; | 491 | char work_q_name[KOBJ_NAME_LEN]; |
| @@ -388,6 +511,8 @@ struct fc_host_attrs { | |||
| 388 | (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds) | 511 | (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds) |
| 389 | #define fc_host_maxframe_size(x) \ | 512 | #define fc_host_maxframe_size(x) \ |
| 390 | (((struct fc_host_attrs *)(x)->shost_data)->maxframe_size) | 513 | (((struct fc_host_attrs *)(x)->shost_data)->maxframe_size) |
| 514 | #define fc_host_max_npiv_vports(x) \ | ||
| 515 | (((struct fc_host_attrs *)(x)->shost_data)->max_npiv_vports) | ||
| 391 | #define fc_host_serial_number(x) \ | 516 | #define fc_host_serial_number(x) \ |
| 392 | (((struct fc_host_attrs *)(x)->shost_data)->serial_number) | 517 | (((struct fc_host_attrs *)(x)->shost_data)->serial_number) |
| 393 | #define fc_host_port_id(x) \ | 518 | #define fc_host_port_id(x) \ |
| @@ -412,10 +537,16 @@ struct fc_host_attrs { | |||
| 412 | (((struct fc_host_attrs *)(x)->shost_data)->rports) | 537 | (((struct fc_host_attrs *)(x)->shost_data)->rports) |
| 413 | #define fc_host_rport_bindings(x) \ | 538 | #define fc_host_rport_bindings(x) \ |
| 414 | (((struct fc_host_attrs *)(x)->shost_data)->rport_bindings) | 539 | (((struct fc_host_attrs *)(x)->shost_data)->rport_bindings) |
| 540 | #define fc_host_vports(x) \ | ||
| 541 | (((struct fc_host_attrs *)(x)->shost_data)->vports) | ||
| 415 | #define fc_host_next_rport_number(x) \ | 542 | #define fc_host_next_rport_number(x) \ |
| 416 | (((struct fc_host_attrs *)(x)->shost_data)->next_rport_number) | 543 | (((struct fc_host_attrs *)(x)->shost_data)->next_rport_number) |
| 417 | #define fc_host_next_target_id(x) \ | 544 | #define fc_host_next_target_id(x) \ |
| 418 | (((struct fc_host_attrs *)(x)->shost_data)->next_target_id) | 545 | (((struct fc_host_attrs *)(x)->shost_data)->next_target_id) |
| 546 | #define fc_host_next_vport_number(x) \ | ||
| 547 | (((struct fc_host_attrs *)(x)->shost_data)->next_vport_number) | ||
| 548 | #define fc_host_npiv_vports_inuse(x) \ | ||
| 549 | (((struct fc_host_attrs *)(x)->shost_data)->npiv_vports_inuse) | ||
| 419 | #define fc_host_work_q_name(x) \ | 550 | #define fc_host_work_q_name(x) \ |
| 420 | (((struct fc_host_attrs *)(x)->shost_data)->work_q_name) | 551 | (((struct fc_host_attrs *)(x)->shost_data)->work_q_name) |
| 421 | #define fc_host_work_q(x) \ | 552 | #define fc_host_work_q(x) \ |
| @@ -452,8 +583,14 @@ struct fc_function_template { | |||
| 452 | void (*dev_loss_tmo_callbk)(struct fc_rport *); | 583 | void (*dev_loss_tmo_callbk)(struct fc_rport *); |
| 453 | void (*terminate_rport_io)(struct fc_rport *); | 584 | void (*terminate_rport_io)(struct fc_rport *); |
| 454 | 585 | ||
| 586 | void (*set_vport_symbolic_name)(struct fc_vport *); | ||
| 587 | int (*vport_create)(struct fc_vport *, bool); | ||
| 588 | int (*vport_disable)(struct fc_vport *, bool); | ||
| 589 | int (*vport_delete)(struct fc_vport *); | ||
| 590 | |||
| 455 | /* allocation lengths for host-specific data */ | 591 | /* allocation lengths for host-specific data */ |
| 456 | u32 dd_fcrport_size; | 592 | u32 dd_fcrport_size; |
| 593 | u32 dd_fcvport_size; | ||
| 457 | 594 | ||
| 458 | /* | 595 | /* |
| 459 | * The driver sets these to tell the transport class it | 596 | * The driver sets these to tell the transport class it |
| @@ -512,7 +649,7 @@ fc_remote_port_chkready(struct fc_rport *rport) | |||
| 512 | 649 | ||
| 513 | switch (rport->port_state) { | 650 | switch (rport->port_state) { |
| 514 | case FC_PORTSTATE_ONLINE: | 651 | case FC_PORTSTATE_ONLINE: |
| 515 | if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) | 652 | if (rport->roles & FC_PORT_ROLE_FCP_TARGET) |
| 516 | result = 0; | 653 | result = 0; |
| 517 | else if (rport->flags & FC_RPORT_DEVLOSS_PENDING) | 654 | else if (rport->flags & FC_RPORT_DEVLOSS_PENDING) |
| 518 | result = DID_IMM_RETRY << 16; | 655 | result = DID_IMM_RETRY << 16; |
| @@ -549,6 +686,27 @@ static inline void u64_to_wwn(u64 inm, u8 *wwn) | |||
| 549 | wwn[7] = inm & 0xff; | 686 | wwn[7] = inm & 0xff; |
| 550 | } | 687 | } |
| 551 | 688 | ||
| 689 | /** | ||
| 690 | * fc_vport_set_state() - called to set a vport's state. Saves the old state, | ||
| 691 | * excepting the transitory states of initializing and sending the ELS | ||
| 692 | * traffic to instantiate the vport on the link. | ||
| 693 | * | ||
| 694 | * Assumes the driver has surrounded this with the proper locking to ensure | ||
| 695 | * a coherent state change. | ||
| 696 | * | ||
| 697 | * @vport: virtual port whose state is changing | ||
| 698 | * @new_state: new state | ||
| 699 | **/ | ||
| 700 | static inline void | ||
| 701 | fc_vport_set_state(struct fc_vport *vport, enum fc_vport_state new_state) | ||
| 702 | { | ||
| 703 | if ((new_state != FC_VPORT_UNKNOWN) && | ||
| 704 | (new_state != FC_VPORT_INITIALIZING)) | ||
| 705 | vport->vport_last_state = vport->vport_state; | ||
| 706 | vport->vport_state = new_state; | ||
| 707 | } | ||
| 708 | |||
| 709 | |||
| 552 | struct scsi_transport_template *fc_attach_transport( | 710 | struct scsi_transport_template *fc_attach_transport( |
| 553 | struct fc_function_template *); | 711 | struct fc_function_template *); |
| 554 | void fc_release_transport(struct scsi_transport_template *); | 712 | void fc_release_transport(struct scsi_transport_template *); |
| @@ -567,5 +725,6 @@ void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, | |||
| 567 | * be sure to read the Vendor Type and ID formatting requirements | 725 | * be sure to read the Vendor Type and ID formatting requirements |
| 568 | * specified in scsi_netlink.h | 726 | * specified in scsi_netlink.h |
| 569 | */ | 727 | */ |
| 728 | int fc_vport_terminate(struct fc_vport *vport); | ||
| 570 | 729 | ||
| 571 | #endif /* SCSI_TRANSPORT_FC_H */ | 730 | #endif /* SCSI_TRANSPORT_FC_H */ |
