scsi_transport_fc.c revision d16794f6ac8d9b50f62e02a6e6175ae1a30d0ccd
1/* 2 * FiberChannel transport specific attributes exported to sysfs. 3 * 4 * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 * ======== 21 * 22 * Copyright (C) 2004-2005 James Smart, Emulex Corporation 23 * Rewrite for host, target, device, and remote port attributes, 24 * statistics, and service functions... 25 * 26 */ 27#include <linux/module.h> 28#include <linux/init.h> 29#include <scsi/scsi_device.h> 30#include <scsi/scsi_host.h> 31#include <scsi/scsi_transport.h> 32#include <scsi/scsi_transport_fc.h> 33#include "scsi_priv.h" 34 35#define FC_PRINTK(x, l, f, a...) printk(l "scsi(%d:%d:%d:%d): " f, (x)->host->host_no, (x)->channel, (x)->id, (x)->lun , ##a) 36 37/* 38 * Redefine so that we can have same named attributes in the 39 * sdev/starget/host objects. 40 */ 41#define FC_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ 42struct class_device_attribute class_device_attr_##_prefix##_##_name = \ 43 __ATTR(_name,_mode,_show,_store) 44 45#define fc_enum_name_search(title, table_type, table) \ 46static const char *get_fc_##title##_name(enum table_type table_key) \ 47{ \ 48 int i; \ 49 char *name = NULL; \ 50 \ 51 for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ 52 if (table[i].value == table_key) { \ 53 name = table[i].name; \ 54 break; \ 55 } \ 56 } \ 57 return name; \ 58} 59 60#define fc_enum_name_match(title, table_type, table) \ 61static int get_fc_##title##_match(const char *table_key, \ 62 enum table_type *value) \ 63{ \ 64 int i; \ 65 \ 66 for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ 67 if (strncmp(table_key, table[i].name, \ 68 table[i].matchlen) == 0) { \ 69 *value = table[i].value; \ 70 return 0; /* success */ \ 71 } \ 72 } \ 73 return 1; /* failure */ \ 74} 75 76 77/* Convert fc_port_type values to ascii string name */ 78static struct { 79 enum fc_port_type value; 80 char *name; 81} fc_port_type_names[] = { 82 { FC_PORTTYPE_UNKNOWN, "Unknown" }, 83 { FC_PORTTYPE_OTHER, "Other" }, 84 { FC_PORTTYPE_NOTPRESENT, "Not Present" }, 85 { FC_PORTTYPE_NPORT, "NPort (fabric via point-to-point)" }, 86 { FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" }, 87 { FC_PORTTYPE_LPORT, "LPort (private loop)" }, 88 { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection" }, 89}; 90fc_enum_name_search(port_type, fc_port_type, fc_port_type_names) 91#define FC_PORTTYPE_MAX_NAMELEN 50 92 93 94/* Convert fc_port_state values to ascii string name */ 95static struct { 96 enum fc_port_state value; 97 char *name; 98} fc_port_state_names[] = { 99 { FC_PORTSTATE_UNKNOWN, "Unknown" }, 100 { FC_PORTSTATE_NOTPRESENT, "Not Present" }, 101 { FC_PORTSTATE_ONLINE, "Online" }, 102 { FC_PORTSTATE_OFFLINE, "Offline" }, 103 { FC_PORTSTATE_BLOCKED, "Blocked" }, 104 { FC_PORTSTATE_BYPASSED, "Bypassed" }, 105 { FC_PORTSTATE_DIAGNOSTICS, "Diagnostics" }, 106 { FC_PORTSTATE_LINKDOWN, "Linkdown" }, 107 { FC_PORTSTATE_ERROR, "Error" }, 108 { FC_PORTSTATE_LOOPBACK, "Loopback" }, 109}; 110fc_enum_name_search(port_state, fc_port_state, fc_port_state_names) 111#define FC_PORTSTATE_MAX_NAMELEN 20 112 113 114/* Convert fc_tgtid_binding_type values to ascii string name */ 115static struct { 116 enum fc_tgtid_binding_type value; 117 char *name; 118 int matchlen; 119} fc_tgtid_binding_type_names[] = { 120 { FC_TGTID_BIND_NONE, "none", 4 }, 121 { FC_TGTID_BIND_BY_WWPN, "wwpn (World Wide Port Name)", 4 }, 122 { FC_TGTID_BIND_BY_WWNN, "wwnn (World Wide Node Name)", 4 }, 123 { FC_TGTID_BIND_BY_ID, "port_id (FC Address)", 7 }, 124}; 125fc_enum_name_search(tgtid_bind_type, fc_tgtid_binding_type, 126 fc_tgtid_binding_type_names) 127fc_enum_name_match(tgtid_bind_type, fc_tgtid_binding_type, 128 fc_tgtid_binding_type_names) 129#define FC_BINDTYPE_MAX_NAMELEN 30 130 131 132#define fc_bitfield_name_search(title, table) \ 133static ssize_t \ 134get_fc_##title##_names(u32 table_key, char *buf) \ 135{ \ 136 char *prefix = ""; \ 137 ssize_t len = 0; \ 138 int i; \ 139 \ 140 for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ 141 if (table[i].value & table_key) { \ 142 len += sprintf(buf + len, "%s%s", \ 143 prefix, table[i].name); \ 144 prefix = ", "; \ 145 } \ 146 } \ 147 len += sprintf(buf + len, "\n"); \ 148 return len; \ 149} 150 151 152/* Convert FC_COS bit values to ascii string name */ 153static struct { 154 u32 value; 155 char *name; 156} fc_cos_names[] = { 157 { FC_COS_CLASS1, "Class 1" }, 158 { FC_COS_CLASS2, "Class 2" }, 159 { FC_COS_CLASS3, "Class 3" }, 160 { FC_COS_CLASS4, "Class 4" }, 161 { FC_COS_CLASS6, "Class 6" }, 162}; 163fc_bitfield_name_search(cos, fc_cos_names) 164 165 166/* Convert FC_PORTSPEED bit values to ascii string name */ 167static struct { 168 u32 value; 169 char *name; 170} fc_port_speed_names[] = { 171 { FC_PORTSPEED_1GBIT, "1 Gbit" }, 172 { FC_PORTSPEED_2GBIT, "2 Gbit" }, 173 { FC_PORTSPEED_4GBIT, "4 Gbit" }, 174 { FC_PORTSPEED_10GBIT, "10 Gbit" }, 175 { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" }, 176}; 177fc_bitfield_name_search(port_speed, fc_port_speed_names) 178 179 180static int 181show_fc_fc4s (char *buf, u8 *fc4_list) 182{ 183 int i, len=0; 184 185 for (i = 0; i < FC_FC4_LIST_SIZE; i++, fc4_list++) 186 len += sprintf(buf + len , "0x%02x ", *fc4_list); 187 len += sprintf(buf + len, "\n"); 188 return len; 189} 190 191 192/* Convert FC_RPORT_ROLE bit values to ascii string name */ 193static struct { 194 u32 value; 195 char *name; 196} fc_remote_port_role_names[] = { 197 { FC_RPORT_ROLE_FCP_TARGET, "FCP Target" }, 198 { FC_RPORT_ROLE_FCP_INITIATOR, "FCP Initiator" }, 199 { FC_RPORT_ROLE_IP_PORT, "IP Port" }, 200}; 201fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names) 202 203/* 204 * Define roles that are specific to port_id. Values are relative to ROLE_MASK. 205 */ 206#define FC_WELLKNOWN_PORTID_MASK 0xfffff0 207#define FC_WELLKNOWN_ROLE_MASK 0x00000f 208#define FC_FPORT_PORTID 0x00000e 209#define FC_FABCTLR_PORTID 0x00000d 210#define FC_DIRSRVR_PORTID 0x00000c 211#define FC_TIMESRVR_PORTID 0x00000b 212#define FC_MGMTSRVR_PORTID 0x00000a 213 214 215static void fc_timeout_blocked_rport(void *data); 216static void fc_scsi_scan_rport(void *data); 217static void fc_rport_terminate(struct fc_rport *rport); 218 219/* 220 * Attribute counts pre object type... 221 * Increase these values if you add attributes 222 */ 223#define FC_STARGET_NUM_ATTRS 3 224#define FC_RPORT_NUM_ATTRS 9 225#define FC_HOST_NUM_ATTRS 15 226 227struct fc_internal { 228 struct scsi_transport_template t; 229 struct fc_function_template *f; 230 231 /* 232 * For attributes : each object has : 233 * An array of the actual attributes structures 234 * An array of null-terminated pointers to the attribute 235 * structures - used for mid-layer interaction. 236 * 237 * The attribute containers for the starget and host are are 238 * part of the midlayer. As the remote port is specific to the 239 * fc transport, we must provide the attribute container. 240 */ 241 struct class_device_attribute private_starget_attrs[ 242 FC_STARGET_NUM_ATTRS]; 243 struct class_device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1]; 244 245 struct class_device_attribute private_host_attrs[FC_HOST_NUM_ATTRS]; 246 struct class_device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1]; 247 248 struct transport_container rport_attr_cont; 249 struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS]; 250 struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1]; 251}; 252 253#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t) 254 255static int fc_target_setup(struct transport_container *tc, struct device *dev, 256 struct class_device *cdev) 257{ 258 struct scsi_target *starget = to_scsi_target(dev); 259 struct fc_rport *rport = starget_to_rport(starget); 260 261 /* 262 * if parent is remote port, use values from remote port. 263 * Otherwise, this host uses the fc_transport, but not the 264 * remote port interface. As such, initialize to known non-values. 265 */ 266 if (rport) { 267 fc_starget_node_name(starget) = rport->node_name; 268 fc_starget_port_name(starget) = rport->port_name; 269 fc_starget_port_id(starget) = rport->port_id; 270 } else { 271 fc_starget_node_name(starget) = -1; 272 fc_starget_port_name(starget) = -1; 273 fc_starget_port_id(starget) = -1; 274 } 275 276 return 0; 277} 278 279static DECLARE_TRANSPORT_CLASS(fc_transport_class, 280 "fc_transport", 281 fc_target_setup, 282 NULL, 283 NULL); 284 285static int fc_host_setup(struct transport_container *tc, struct device *dev, 286 struct class_device *cdev) 287{ 288 struct Scsi_Host *shost = dev_to_shost(dev); 289 290 /* 291 * Set default values easily detected by the midlayer as 292 * failure cases. The scsi lldd is responsible for initializing 293 * all transport attributes to valid values per host. 294 */ 295 fc_host_node_name(shost) = -1; 296 fc_host_port_name(shost) = -1; 297 fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED; 298 memset(fc_host_supported_fc4s(shost), 0, 299 sizeof(fc_host_supported_fc4s(shost))); 300 memset(fc_host_symbolic_name(shost), 0, 301 sizeof(fc_host_symbolic_name(shost))); 302 fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN; 303 fc_host_maxframe_size(shost) = -1; 304 memset(fc_host_serial_number(shost), 0, 305 sizeof(fc_host_serial_number(shost))); 306 307 fc_host_port_id(shost) = -1; 308 fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; 309 fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; 310 memset(fc_host_active_fc4s(shost), 0, 311 sizeof(fc_host_active_fc4s(shost))); 312 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; 313 fc_host_fabric_name(shost) = -1; 314 315 fc_host_tgtid_bind_type(shost) = FC_TGTID_BIND_BY_WWPN; 316 317 INIT_LIST_HEAD(&fc_host_rports(shost)); 318 INIT_LIST_HEAD(&fc_host_rport_bindings(shost)); 319 fc_host_next_rport_number(shost) = 0; 320 fc_host_next_target_id(shost) = 0; 321 322 return 0; 323} 324 325static DECLARE_TRANSPORT_CLASS(fc_host_class, 326 "fc_host", 327 fc_host_setup, 328 NULL, 329 NULL); 330 331/* 332 * Setup and Remove actions for remote ports are handled 333 * in the service functions below. 334 */ 335static DECLARE_TRANSPORT_CLASS(fc_rport_class, 336 "fc_remote_ports", 337 NULL, 338 NULL, 339 NULL); 340 341/* 342 * Module Parameters 343 */ 344 345/* 346 * dev_loss_tmo: the default number of seconds that the FC transport 347 * should insulate the loss of a remote port. 348 * The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT. 349 */ 350static unsigned int fc_dev_loss_tmo = SCSI_DEVICE_BLOCK_MAX_TIMEOUT; 351 352module_param_named(dev_loss_tmo, fc_dev_loss_tmo, int, S_IRUGO|S_IWUSR); 353MODULE_PARM_DESC(dev_loss_tmo, 354 "Maximum number of seconds that the FC transport should" 355 " insulate the loss of a remote port. Once this value is" 356 " exceeded, the scsi target is removed. Value should be" 357 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT."); 358 359 360static __init int fc_transport_init(void) 361{ 362 int error = transport_class_register(&fc_host_class); 363 if (error) 364 return error; 365 error = transport_class_register(&fc_rport_class); 366 if (error) 367 return error; 368 return transport_class_register(&fc_transport_class); 369} 370 371static void __exit fc_transport_exit(void) 372{ 373 transport_class_unregister(&fc_transport_class); 374 transport_class_unregister(&fc_rport_class); 375 transport_class_unregister(&fc_host_class); 376} 377 378/* 379 * FC Remote Port Attribute Management 380 */ 381 382#define fc_rport_show_function(field, format_string, sz, cast) \ 383static ssize_t \ 384show_fc_rport_##field (struct class_device *cdev, char *buf) \ 385{ \ 386 struct fc_rport *rport = transport_class_to_rport(cdev); \ 387 struct Scsi_Host *shost = rport_to_shost(rport); \ 388 struct fc_internal *i = to_fc_internal(shost->transportt); \ 389 if (i->f->get_rport_##field) \ 390 i->f->get_rport_##field(rport); \ 391 return snprintf(buf, sz, format_string, cast rport->field); \ 392} 393 394#define fc_rport_store_function(field) \ 395static ssize_t \ 396store_fc_rport_##field(struct class_device *cdev, const char *buf, \ 397 size_t count) \ 398{ \ 399 int val; \ 400 struct fc_rport *rport = transport_class_to_rport(cdev); \ 401 struct Scsi_Host *shost = rport_to_shost(rport); \ 402 struct fc_internal *i = to_fc_internal(shost->transportt); \ 403 val = simple_strtoul(buf, NULL, 0); \ 404 i->f->set_rport_##field(rport, val); \ 405 return count; \ 406} 407 408#define fc_rport_rd_attr(field, format_string, sz) \ 409 fc_rport_show_function(field, format_string, sz, ) \ 410static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \ 411 show_fc_rport_##field, NULL) 412 413#define fc_rport_rd_attr_cast(field, format_string, sz, cast) \ 414 fc_rport_show_function(field, format_string, sz, (cast)) \ 415static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \ 416 show_fc_rport_##field, NULL) 417 418#define fc_rport_rw_attr(field, format_string, sz) \ 419 fc_rport_show_function(field, format_string, sz, ) \ 420 fc_rport_store_function(field) \ 421static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO | S_IWUSR, \ 422 show_fc_rport_##field, \ 423 store_fc_rport_##field) 424 425 426#define fc_private_rport_show_function(field, format_string, sz, cast) \ 427static ssize_t \ 428show_fc_rport_##field (struct class_device *cdev, char *buf) \ 429{ \ 430 struct fc_rport *rport = transport_class_to_rport(cdev); \ 431 return snprintf(buf, sz, format_string, cast rport->field); \ 432} 433 434#define fc_private_rport_rd_attr(field, format_string, sz) \ 435 fc_private_rport_show_function(field, format_string, sz, ) \ 436static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \ 437 show_fc_rport_##field, NULL) 438 439#define fc_private_rport_rd_attr_cast(field, format_string, sz, cast) \ 440 fc_private_rport_show_function(field, format_string, sz, (cast)) \ 441static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \ 442 show_fc_rport_##field, NULL) 443 444 445#define fc_private_rport_rd_enum_attr(title, maxlen) \ 446static ssize_t \ 447show_fc_rport_##title (struct class_device *cdev, char *buf) \ 448{ \ 449 struct fc_rport *rport = transport_class_to_rport(cdev); \ 450 const char *name; \ 451 name = get_fc_##title##_name(rport->title); \ 452 if (!name) \ 453 return -EINVAL; \ 454 return snprintf(buf, maxlen, "%s\n", name); \ 455} \ 456static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \ 457 show_fc_rport_##title, NULL) 458 459 460#define SETUP_RPORT_ATTRIBUTE_RD(field) \ 461 i->private_rport_attrs[count] = class_device_attr_rport_##field; \ 462 i->private_rport_attrs[count].attr.mode = S_IRUGO; \ 463 i->private_rport_attrs[count].store = NULL; \ 464 i->rport_attrs[count] = &i->private_rport_attrs[count]; \ 465 if (i->f->show_rport_##field) \ 466 count++ 467 468#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(field) \ 469 i->private_rport_attrs[count] = class_device_attr_rport_##field; \ 470 i->private_rport_attrs[count].attr.mode = S_IRUGO; \ 471 i->private_rport_attrs[count].store = NULL; \ 472 i->rport_attrs[count] = &i->private_rport_attrs[count]; \ 473 count++ 474 475#define SETUP_RPORT_ATTRIBUTE_RW(field) \ 476 i->private_rport_attrs[count] = class_device_attr_rport_##field; \ 477 if (!i->f->set_rport_##field) { \ 478 i->private_rport_attrs[count].attr.mode = S_IRUGO; \ 479 i->private_rport_attrs[count].store = NULL; \ 480 } \ 481 i->rport_attrs[count] = &i->private_rport_attrs[count]; \ 482 if (i->f->show_rport_##field) \ 483 count++ 484 485 486/* The FC Transport Remote Port Attributes: */ 487 488/* Fixed Remote Port Attributes */ 489 490fc_private_rport_rd_attr(maxframe_size, "%u bytes\n", 20); 491 492static ssize_t 493show_fc_rport_supported_classes (struct class_device *cdev, char *buf) 494{ 495 struct fc_rport *rport = transport_class_to_rport(cdev); 496 if (rport->supported_classes == FC_COS_UNSPECIFIED) 497 return snprintf(buf, 20, "unspecified\n"); 498 return get_fc_cos_names(rport->supported_classes, buf); 499} 500static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO, 501 show_fc_rport_supported_classes, NULL); 502 503/* Dynamic Remote Port Attributes */ 504 505fc_rport_rw_attr(dev_loss_tmo, "%d\n", 20); 506 507 508/* Private Remote Port Attributes */ 509 510fc_private_rport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); 511fc_private_rport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); 512fc_private_rport_rd_attr(port_id, "0x%06x\n", 20); 513 514static ssize_t 515show_fc_rport_roles (struct class_device *cdev, char *buf) 516{ 517 struct fc_rport *rport = transport_class_to_rport(cdev); 518 519 /* identify any roles that are port_id specific */ 520 if ((rport->port_id != -1) && 521 (rport->port_id & FC_WELLKNOWN_PORTID_MASK) == 522 FC_WELLKNOWN_PORTID_MASK) { 523 switch (rport->port_id & FC_WELLKNOWN_ROLE_MASK) { 524 case FC_FPORT_PORTID: 525 return snprintf(buf, 30, "Fabric Port\n"); 526 case FC_FABCTLR_PORTID: 527 return snprintf(buf, 30, "Fabric Controller\n"); 528 case FC_DIRSRVR_PORTID: 529 return snprintf(buf, 30, "Directory Server\n"); 530 case FC_TIMESRVR_PORTID: 531 return snprintf(buf, 30, "Time Server\n"); 532 case FC_MGMTSRVR_PORTID: 533 return snprintf(buf, 30, "Management Server\n"); 534 default: 535 return snprintf(buf, 30, "Unknown Fabric Entity\n"); 536 } 537 } else { 538 if (rport->roles == FC_RPORT_ROLE_UNKNOWN) 539 return snprintf(buf, 20, "unknown\n"); 540 return get_fc_remote_port_roles_names(rport->roles, buf); 541 } 542} 543static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO, 544 show_fc_rport_roles, NULL); 545 546fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN); 547fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20); 548 549 550 551/* 552 * FC SCSI Target Attribute Management 553 */ 554 555/* 556 * Note: in the target show function we recognize when the remote 557 * port is in the heirarchy and do not allow the driver to get 558 * involved in sysfs functions. The driver only gets involved if 559 * it's the "old" style that doesn't use rports. 560 */ 561#define fc_starget_show_function(field, format_string, sz, cast) \ 562static ssize_t \ 563show_fc_starget_##field (struct class_device *cdev, char *buf) \ 564{ \ 565 struct scsi_target *starget = transport_class_to_starget(cdev); \ 566 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ 567 struct fc_internal *i = to_fc_internal(shost->transportt); \ 568 struct fc_rport *rport = starget_to_rport(starget); \ 569 if (rport) \ 570 fc_starget_##field(starget) = rport->field; \ 571 else if (i->f->get_starget_##field) \ 572 i->f->get_starget_##field(starget); \ 573 return snprintf(buf, sz, format_string, \ 574 cast fc_starget_##field(starget)); \ 575} 576 577#define fc_starget_rd_attr(field, format_string, sz) \ 578 fc_starget_show_function(field, format_string, sz, ) \ 579static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \ 580 show_fc_starget_##field, NULL) 581 582#define fc_starget_rd_attr_cast(field, format_string, sz, cast) \ 583 fc_starget_show_function(field, format_string, sz, (cast)) \ 584static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \ 585 show_fc_starget_##field, NULL) 586 587#define SETUP_STARGET_ATTRIBUTE_RD(field) \ 588 i->private_starget_attrs[count] = class_device_attr_starget_##field; \ 589 i->private_starget_attrs[count].attr.mode = S_IRUGO; \ 590 i->private_starget_attrs[count].store = NULL; \ 591 i->starget_attrs[count] = &i->private_starget_attrs[count]; \ 592 if (i->f->show_starget_##field) \ 593 count++ 594 595#define SETUP_STARGET_ATTRIBUTE_RW(field) \ 596 i->private_starget_attrs[count] = class_device_attr_starget_##field; \ 597 if (!i->f->set_starget_##field) { \ 598 i->private_starget_attrs[count].attr.mode = S_IRUGO; \ 599 i->private_starget_attrs[count].store = NULL; \ 600 } \ 601 i->starget_attrs[count] = &i->private_starget_attrs[count]; \ 602 if (i->f->show_starget_##field) \ 603 count++ 604 605/* The FC Transport SCSI Target Attributes: */ 606fc_starget_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); 607fc_starget_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); 608fc_starget_rd_attr(port_id, "0x%06x\n", 20); 609 610 611/* 612 * Host Attribute Management 613 */ 614 615#define fc_host_show_function(field, format_string, sz, cast) \ 616static ssize_t \ 617show_fc_host_##field (struct class_device *cdev, char *buf) \ 618{ \ 619 struct Scsi_Host *shost = transport_class_to_shost(cdev); \ 620 struct fc_internal *i = to_fc_internal(shost->transportt); \ 621 if (i->f->get_host_##field) \ 622 i->f->get_host_##field(shost); \ 623 return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \ 624} 625 626#define fc_host_store_function(field) \ 627static ssize_t \ 628store_fc_host_##field(struct class_device *cdev, const char *buf, \ 629 size_t count) \ 630{ \ 631 int val; \ 632 struct Scsi_Host *shost = transport_class_to_shost(cdev); \ 633 struct fc_internal *i = to_fc_internal(shost->transportt); \ 634 \ 635 val = simple_strtoul(buf, NULL, 0); \ 636 i->f->set_host_##field(shost, val); \ 637 return count; \ 638} 639 640#define fc_host_rd_attr(field, format_string, sz) \ 641 fc_host_show_function(field, format_string, sz, ) \ 642static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \ 643 show_fc_host_##field, NULL) 644 645#define fc_host_rd_attr_cast(field, format_string, sz, cast) \ 646 fc_host_show_function(field, format_string, sz, (cast)) \ 647static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \ 648 show_fc_host_##field, NULL) 649 650#define fc_host_rw_attr(field, format_string, sz) \ 651 fc_host_show_function(field, format_string, sz, ) \ 652 fc_host_store_function(field) \ 653static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR, \ 654 show_fc_host_##field, \ 655 store_fc_host_##field) 656 657#define fc_host_rd_enum_attr(title, maxlen) \ 658static ssize_t \ 659show_fc_host_##title (struct class_device *cdev, char *buf) \ 660{ \ 661 struct Scsi_Host *shost = transport_class_to_shost(cdev); \ 662 struct fc_internal *i = to_fc_internal(shost->transportt); \ 663 const char *name; \ 664 if (i->f->get_host_##title) \ 665 i->f->get_host_##title(shost); \ 666 name = get_fc_##title##_name(fc_host_##title(shost)); \ 667 if (!name) \ 668 return -EINVAL; \ 669 return snprintf(buf, maxlen, "%s\n", name); \ 670} \ 671static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL) 672 673#define SETUP_HOST_ATTRIBUTE_RD(field) \ 674 i->private_host_attrs[count] = class_device_attr_host_##field; \ 675 i->private_host_attrs[count].attr.mode = S_IRUGO; \ 676 i->private_host_attrs[count].store = NULL; \ 677 i->host_attrs[count] = &i->private_host_attrs[count]; \ 678 if (i->f->show_host_##field) \ 679 count++ 680 681#define SETUP_HOST_ATTRIBUTE_RW(field) \ 682 i->private_host_attrs[count] = class_device_attr_host_##field; \ 683 if (!i->f->set_host_##field) { \ 684 i->private_host_attrs[count].attr.mode = S_IRUGO; \ 685 i->private_host_attrs[count].store = NULL; \ 686 } \ 687 i->host_attrs[count] = &i->private_host_attrs[count]; \ 688 if (i->f->show_host_##field) \ 689 count++ 690 691 692#define fc_private_host_show_function(field, format_string, sz, cast) \ 693static ssize_t \ 694show_fc_host_##field (struct class_device *cdev, char *buf) \ 695{ \ 696 struct Scsi_Host *shost = transport_class_to_shost(cdev); \ 697 return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \ 698} 699 700#define fc_private_host_rd_attr(field, format_string, sz) \ 701 fc_private_host_show_function(field, format_string, sz, ) \ 702static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \ 703 show_fc_host_##field, NULL) 704 705#define fc_private_host_rd_attr_cast(field, format_string, sz, cast) \ 706 fc_private_host_show_function(field, format_string, sz, (cast)) \ 707static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \ 708 show_fc_host_##field, NULL) 709 710#define SETUP_PRIVATE_HOST_ATTRIBUTE_RD(field) \ 711 i->private_host_attrs[count] = class_device_attr_host_##field; \ 712 i->private_host_attrs[count].attr.mode = S_IRUGO; \ 713 i->private_host_attrs[count].store = NULL; \ 714 i->host_attrs[count] = &i->private_host_attrs[count]; \ 715 count++ 716 717#define SETUP_PRIVATE_HOST_ATTRIBUTE_RW(field) \ 718 i->private_host_attrs[count] = class_device_attr_host_##field; \ 719 i->host_attrs[count] = &i->private_host_attrs[count]; \ 720 count++ 721 722 723/* Fixed Host Attributes */ 724 725static ssize_t 726show_fc_host_supported_classes (struct class_device *cdev, char *buf) 727{ 728 struct Scsi_Host *shost = transport_class_to_shost(cdev); 729 730 if (fc_host_supported_classes(shost) == FC_COS_UNSPECIFIED) 731 return snprintf(buf, 20, "unspecified\n"); 732 733 return get_fc_cos_names(fc_host_supported_classes(shost), buf); 734} 735static FC_CLASS_DEVICE_ATTR(host, supported_classes, S_IRUGO, 736 show_fc_host_supported_classes, NULL); 737 738static ssize_t 739show_fc_host_supported_fc4s (struct class_device *cdev, char *buf) 740{ 741 struct Scsi_Host *shost = transport_class_to_shost(cdev); 742 return (ssize_t)show_fc_fc4s(buf, fc_host_supported_fc4s(shost)); 743} 744static FC_CLASS_DEVICE_ATTR(host, supported_fc4s, S_IRUGO, 745 show_fc_host_supported_fc4s, NULL); 746 747static ssize_t 748show_fc_host_supported_speeds (struct class_device *cdev, char *buf) 749{ 750 struct Scsi_Host *shost = transport_class_to_shost(cdev); 751 752 if (fc_host_supported_speeds(shost) == FC_PORTSPEED_UNKNOWN) 753 return snprintf(buf, 20, "unknown\n"); 754 755 return get_fc_port_speed_names(fc_host_supported_speeds(shost), buf); 756} 757static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO, 758 show_fc_host_supported_speeds, NULL); 759 760 761fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); 762fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); 763fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1)); 764fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); 765fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); 766 767 768/* Dynamic Host Attributes */ 769 770static ssize_t 771show_fc_host_active_fc4s (struct class_device *cdev, char *buf) 772{ 773 struct Scsi_Host *shost = transport_class_to_shost(cdev); 774 struct fc_internal *i = to_fc_internal(shost->transportt); 775 776 if (i->f->get_host_active_fc4s) 777 i->f->get_host_active_fc4s(shost); 778 779 return (ssize_t)show_fc_fc4s(buf, fc_host_active_fc4s(shost)); 780} 781static FC_CLASS_DEVICE_ATTR(host, active_fc4s, S_IRUGO, 782 show_fc_host_active_fc4s, NULL); 783 784static ssize_t 785show_fc_host_speed (struct class_device *cdev, char *buf) 786{ 787 struct Scsi_Host *shost = transport_class_to_shost(cdev); 788 struct fc_internal *i = to_fc_internal(shost->transportt); 789 790 if (i->f->get_host_speed) 791 i->f->get_host_speed(shost); 792 793 if (fc_host_speed(shost) == FC_PORTSPEED_UNKNOWN) 794 return snprintf(buf, 20, "unknown\n"); 795 796 return get_fc_port_speed_names(fc_host_speed(shost), buf); 797} 798static FC_CLASS_DEVICE_ATTR(host, speed, S_IRUGO, 799 show_fc_host_speed, NULL); 800 801 802fc_host_rd_attr(port_id, "0x%06x\n", 20); 803fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN); 804fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN); 805fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long); 806 807 808/* Private Host Attributes */ 809 810static ssize_t 811show_fc_private_host_tgtid_bind_type(struct class_device *cdev, char *buf) 812{ 813 struct Scsi_Host *shost = transport_class_to_shost(cdev); 814 const char *name; 815 816 name = get_fc_tgtid_bind_type_name(fc_host_tgtid_bind_type(shost)); 817 if (!name) 818 return -EINVAL; 819 return snprintf(buf, FC_BINDTYPE_MAX_NAMELEN, "%s\n", name); 820} 821 822#define get_list_head_entry(pos, head, member) \ 823 pos = list_entry((head)->next, typeof(*pos), member) 824 825static ssize_t 826store_fc_private_host_tgtid_bind_type(struct class_device *cdev, 827 const char *buf, size_t count) 828{ 829 struct Scsi_Host *shost = transport_class_to_shost(cdev); 830 struct fc_rport *rport; 831 enum fc_tgtid_binding_type val; 832 unsigned long flags; 833 834 if (get_fc_tgtid_bind_type_match(buf, &val)) 835 return -EINVAL; 836 837 /* if changing bind type, purge all unused consistent bindings */ 838 if (val != fc_host_tgtid_bind_type(shost)) { 839 spin_lock_irqsave(shost->host_lock, flags); 840 while (!list_empty(&fc_host_rport_bindings(shost))) { 841 get_list_head_entry(rport, 842 &fc_host_rport_bindings(shost), peers); 843 spin_unlock_irqrestore(shost->host_lock, flags); 844 fc_rport_terminate(rport); 845 spin_lock_irqsave(shost->host_lock, flags); 846 } 847 spin_unlock_irqrestore(shost->host_lock, flags); 848 } 849 850 fc_host_tgtid_bind_type(shost) = val; 851 return count; 852} 853 854static FC_CLASS_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR, 855 show_fc_private_host_tgtid_bind_type, 856 store_fc_private_host_tgtid_bind_type); 857 858/* 859 * Host Statistics Management 860 */ 861 862/* Show a given an attribute in the statistics group */ 863static ssize_t 864fc_stat_show(const struct class_device *cdev, char *buf, unsigned long offset) 865{ 866 struct Scsi_Host *shost = transport_class_to_shost(cdev); 867 struct fc_internal *i = to_fc_internal(shost->transportt); 868 struct fc_host_statistics *stats; 869 ssize_t ret = -ENOENT; 870 871 if (offset > sizeof(struct fc_host_statistics) || 872 offset % sizeof(u64) != 0) 873 WARN_ON(1); 874 875 if (i->f->get_fc_host_stats) { 876 stats = (i->f->get_fc_host_stats)(shost); 877 if (stats) 878 ret = snprintf(buf, 20, "0x%llx\n", 879 (unsigned long long)*(u64 *)(((u8 *) stats) + offset)); 880 } 881 return ret; 882} 883 884 885/* generate a read-only statistics attribute */ 886#define fc_host_statistic(name) \ 887static ssize_t show_fcstat_##name(struct class_device *cd, char *buf) \ 888{ \ 889 return fc_stat_show(cd, buf, \ 890 offsetof(struct fc_host_statistics, name)); \ 891} \ 892static FC_CLASS_DEVICE_ATTR(host, name, S_IRUGO, show_fcstat_##name, NULL) 893 894fc_host_statistic(seconds_since_last_reset); 895fc_host_statistic(tx_frames); 896fc_host_statistic(tx_words); 897fc_host_statistic(rx_frames); 898fc_host_statistic(rx_words); 899fc_host_statistic(lip_count); 900fc_host_statistic(nos_count); 901fc_host_statistic(error_frames); 902fc_host_statistic(dumped_frames); 903fc_host_statistic(link_failure_count); 904fc_host_statistic(loss_of_sync_count); 905fc_host_statistic(loss_of_signal_count); 906fc_host_statistic(prim_seq_protocol_err_count); 907fc_host_statistic(invalid_tx_word_count); 908fc_host_statistic(invalid_crc_count); 909fc_host_statistic(fcp_input_requests); 910fc_host_statistic(fcp_output_requests); 911fc_host_statistic(fcp_control_requests); 912fc_host_statistic(fcp_input_megabytes); 913fc_host_statistic(fcp_output_megabytes); 914 915static ssize_t 916fc_reset_statistics(struct class_device *cdev, const char *buf, 917 size_t count) 918{ 919 struct Scsi_Host *shost = transport_class_to_shost(cdev); 920 struct fc_internal *i = to_fc_internal(shost->transportt); 921 922 /* ignore any data value written to the attribute */ 923 if (i->f->reset_fc_host_stats) { 924 i->f->reset_fc_host_stats(shost); 925 return count; 926 } 927 928 return -ENOENT; 929} 930static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL, 931 fc_reset_statistics); 932 933 934static struct attribute *fc_statistics_attrs[] = { 935 &class_device_attr_host_seconds_since_last_reset.attr, 936 &class_device_attr_host_tx_frames.attr, 937 &class_device_attr_host_tx_words.attr, 938 &class_device_attr_host_rx_frames.attr, 939 &class_device_attr_host_rx_words.attr, 940 &class_device_attr_host_lip_count.attr, 941 &class_device_attr_host_nos_count.attr, 942 &class_device_attr_host_error_frames.attr, 943 &class_device_attr_host_dumped_frames.attr, 944 &class_device_attr_host_link_failure_count.attr, 945 &class_device_attr_host_loss_of_sync_count.attr, 946 &class_device_attr_host_loss_of_signal_count.attr, 947 &class_device_attr_host_prim_seq_protocol_err_count.attr, 948 &class_device_attr_host_invalid_tx_word_count.attr, 949 &class_device_attr_host_invalid_crc_count.attr, 950 &class_device_attr_host_fcp_input_requests.attr, 951 &class_device_attr_host_fcp_output_requests.attr, 952 &class_device_attr_host_fcp_control_requests.attr, 953 &class_device_attr_host_fcp_input_megabytes.attr, 954 &class_device_attr_host_fcp_output_megabytes.attr, 955 &class_device_attr_host_reset_statistics.attr, 956 NULL 957}; 958 959static struct attribute_group fc_statistics_group = { 960 .name = "statistics", 961 .attrs = fc_statistics_attrs, 962}; 963 964static int fc_host_match(struct attribute_container *cont, 965 struct device *dev) 966{ 967 struct Scsi_Host *shost; 968 struct fc_internal *i; 969 970 if (!scsi_is_host_device(dev)) 971 return 0; 972 973 shost = dev_to_shost(dev); 974 if (!shost->transportt || shost->transportt->host_attrs.ac.class 975 != &fc_host_class.class) 976 return 0; 977 978 i = to_fc_internal(shost->transportt); 979 980 return &i->t.host_attrs.ac == cont; 981} 982 983static int fc_target_match(struct attribute_container *cont, 984 struct device *dev) 985{ 986 struct Scsi_Host *shost; 987 struct fc_internal *i; 988 989 if (!scsi_is_target_device(dev)) 990 return 0; 991 992 shost = dev_to_shost(dev->parent); 993 if (!shost->transportt || shost->transportt->host_attrs.ac.class 994 != &fc_host_class.class) 995 return 0; 996 997 i = to_fc_internal(shost->transportt); 998 999 return &i->t.target_attrs.ac == cont; 1000} 1001 1002static void fc_rport_dev_release(struct device *dev) 1003{ 1004 struct fc_rport *rport = dev_to_rport(dev); 1005 put_device(dev->parent); 1006 kfree(rport); 1007} 1008 1009int scsi_is_fc_rport(const struct device *dev) 1010{ 1011 return dev->release == fc_rport_dev_release; 1012} 1013EXPORT_SYMBOL(scsi_is_fc_rport); 1014 1015static int fc_rport_match(struct attribute_container *cont, 1016 struct device *dev) 1017{ 1018 struct Scsi_Host *shost; 1019 struct fc_internal *i; 1020 1021 if (!scsi_is_fc_rport(dev)) 1022 return 0; 1023 1024 shost = dev_to_shost(dev->parent); 1025 if (!shost->transportt || shost->transportt->host_attrs.ac.class 1026 != &fc_host_class.class) 1027 return 0; 1028 1029 i = to_fc_internal(shost->transportt); 1030 1031 return &i->rport_attr_cont.ac == cont; 1032} 1033 1034 1035/* 1036 * Must be called with shost->host_lock held 1037 */ 1038static struct device *fc_target_parent(struct Scsi_Host *shost, 1039 int channel, uint id) 1040{ 1041 struct fc_rport *rport; 1042 1043 list_for_each_entry(rport, &fc_host_rports(shost), peers) 1044 if ((rport->channel == channel) && 1045 (rport->scsi_target_id == id)) 1046 return &rport->dev; 1047 1048 return NULL; 1049} 1050 1051struct scsi_transport_template * 1052fc_attach_transport(struct fc_function_template *ft) 1053{ 1054 struct fc_internal *i = kmalloc(sizeof(struct fc_internal), 1055 GFP_KERNEL); 1056 int count; 1057 1058 if (unlikely(!i)) 1059 return NULL; 1060 1061 memset(i, 0, sizeof(struct fc_internal)); 1062 1063 i->t.target_attrs.ac.attrs = &i->starget_attrs[0]; 1064 i->t.target_attrs.ac.class = &fc_transport_class.class; 1065 i->t.target_attrs.ac.match = fc_target_match; 1066 i->t.target_size = sizeof(struct fc_starget_attrs); 1067 transport_container_register(&i->t.target_attrs); 1068 1069 i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1070 i->t.host_attrs.ac.class = &fc_host_class.class; 1071 i->t.host_attrs.ac.match = fc_host_match; 1072 i->t.host_size = sizeof(struct fc_host_attrs); 1073 if (ft->get_fc_host_stats) 1074 i->t.host_attrs.statistics = &fc_statistics_group; 1075 transport_container_register(&i->t.host_attrs); 1076 1077 i->rport_attr_cont.ac.attrs = &i->rport_attrs[0]; 1078 i->rport_attr_cont.ac.class = &fc_rport_class.class; 1079 i->rport_attr_cont.ac.match = fc_rport_match; 1080 transport_container_register(&i->rport_attr_cont); 1081 1082 i->f = ft; 1083 1084 /* Transport uses the shost workq for scsi scanning */ 1085 i->t.create_work_queue = 1; 1086 1087 i->t.target_parent = fc_target_parent; 1088 1089 /* 1090 * Setup SCSI Target Attributes. 1091 */ 1092 count = 0; 1093 SETUP_STARGET_ATTRIBUTE_RD(node_name); 1094 SETUP_STARGET_ATTRIBUTE_RD(port_name); 1095 SETUP_STARGET_ATTRIBUTE_RD(port_id); 1096 1097 BUG_ON(count > FC_STARGET_NUM_ATTRS); 1098 1099 i->starget_attrs[count] = NULL; 1100 1101 1102 /* 1103 * Setup SCSI Host Attributes. 1104 */ 1105 count=0; 1106 SETUP_HOST_ATTRIBUTE_RD(node_name); 1107 SETUP_HOST_ATTRIBUTE_RD(port_name); 1108 SETUP_HOST_ATTRIBUTE_RD(supported_classes); 1109 SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); 1110 SETUP_HOST_ATTRIBUTE_RD(symbolic_name); 1111 SETUP_HOST_ATTRIBUTE_RD(supported_speeds); 1112 SETUP_HOST_ATTRIBUTE_RD(maxframe_size); 1113 SETUP_HOST_ATTRIBUTE_RD(serial_number); 1114 1115 SETUP_HOST_ATTRIBUTE_RD(port_id); 1116 SETUP_HOST_ATTRIBUTE_RD(port_type); 1117 SETUP_HOST_ATTRIBUTE_RD(port_state); 1118 SETUP_HOST_ATTRIBUTE_RD(active_fc4s); 1119 SETUP_HOST_ATTRIBUTE_RD(speed); 1120 SETUP_HOST_ATTRIBUTE_RD(fabric_name); 1121 1122 /* Transport-managed attributes */ 1123 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); 1124 1125 BUG_ON(count > FC_HOST_NUM_ATTRS); 1126 1127 i->host_attrs[count] = NULL; 1128 1129 /* 1130 * Setup Remote Port Attributes. 1131 */ 1132 count=0; 1133 SETUP_RPORT_ATTRIBUTE_RD(maxframe_size); 1134 SETUP_RPORT_ATTRIBUTE_RD(supported_classes); 1135 SETUP_RPORT_ATTRIBUTE_RW(dev_loss_tmo); 1136 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(node_name); 1137 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_name); 1138 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_id); 1139 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles); 1140 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state); 1141 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id); 1142 1143 BUG_ON(count > FC_RPORT_NUM_ATTRS); 1144 1145 i->rport_attrs[count] = NULL; 1146 1147 return &i->t; 1148} 1149EXPORT_SYMBOL(fc_attach_transport); 1150 1151void fc_release_transport(struct scsi_transport_template *t) 1152{ 1153 struct fc_internal *i = to_fc_internal(t); 1154 1155 transport_container_unregister(&i->t.target_attrs); 1156 transport_container_unregister(&i->t.host_attrs); 1157 transport_container_unregister(&i->rport_attr_cont); 1158 1159 kfree(i); 1160} 1161EXPORT_SYMBOL(fc_release_transport); 1162 1163 1164/** 1165 * fc_remove_host - called to terminate any fc_transport-related elements 1166 * for a scsi host. 1167 * @rport: remote port to be unblocked. 1168 * 1169 * This routine is expected to be called immediately preceeding the 1170 * a driver's call to scsi_remove_host(). 1171 * 1172 * WARNING: A driver utilizing the fc_transport, which fails to call 1173 * this routine prior to scsi_remote_host(), will leave dangling 1174 * objects in /sys/class/fc_remote_ports. Access to any of these 1175 * objects can result in a system crash !!! 1176 * 1177 * Notes: 1178 * This routine assumes no locks are held on entry. 1179 **/ 1180void 1181fc_remove_host(struct Scsi_Host *shost) 1182{ 1183 struct fc_rport *rport, *next_rport; 1184 1185 /* Remove any remote ports */ 1186 list_for_each_entry_safe(rport, next_rport, 1187 &fc_host_rports(shost), peers) 1188 fc_rport_terminate(rport); 1189 list_for_each_entry_safe(rport, next_rport, 1190 &fc_host_rport_bindings(shost), peers) 1191 fc_rport_terminate(rport); 1192} 1193EXPORT_SYMBOL(fc_remove_host); 1194 1195/** 1196 * fc_rport_create - allocates and creates a remote FC port. 1197 * @shost: scsi host the remote port is connected to. 1198 * @channel: Channel on shost port connected to. 1199 * @ids: The world wide names, fc address, and FC4 port 1200 * roles for the remote port. 1201 * 1202 * Allocates and creates the remoter port structure, including the 1203 * class and sysfs creation. 1204 * 1205 * Notes: 1206 * This routine assumes no locks are held on entry. 1207 **/ 1208struct fc_rport * 1209fc_rport_create(struct Scsi_Host *shost, int channel, 1210 struct fc_rport_identifiers *ids) 1211{ 1212 struct fc_host_attrs *fc_host = 1213 (struct fc_host_attrs *)shost->shost_data; 1214 struct fc_internal *fci = to_fc_internal(shost->transportt); 1215 struct fc_rport *rport; 1216 struct device *dev; 1217 unsigned long flags; 1218 int error; 1219 size_t size; 1220 1221 size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size); 1222 rport = kmalloc(size, GFP_KERNEL); 1223 if (unlikely(!rport)) { 1224 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); 1225 return NULL; 1226 } 1227 memset(rport, 0, size); 1228 1229 rport->maxframe_size = -1; 1230 rport->supported_classes = FC_COS_UNSPECIFIED; 1231 rport->dev_loss_tmo = fc_dev_loss_tmo; 1232 memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name)); 1233 memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name)); 1234 rport->port_id = ids->port_id; 1235 rport->roles = ids->roles; 1236 rport->port_state = FC_PORTSTATE_ONLINE; 1237 if (fci->f->dd_fcrport_size) 1238 rport->dd_data = &rport[1]; 1239 rport->channel = channel; 1240 1241 INIT_WORK(&rport->dev_loss_work, fc_timeout_blocked_rport, rport); 1242 INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport); 1243 1244 spin_lock_irqsave(shost->host_lock, flags); 1245 1246 rport->number = fc_host->next_rport_number++; 1247 if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) 1248 rport->scsi_target_id = fc_host->next_target_id++; 1249 else 1250 rport->scsi_target_id = -1; 1251 list_add_tail(&rport->peers, &fc_host_rports(shost)); 1252 get_device(&shost->shost_gendev); 1253 1254 spin_unlock_irqrestore(shost->host_lock, flags); 1255 1256 dev = &rport->dev; 1257 device_initialize(dev); 1258 dev->parent = get_device(&shost->shost_gendev); 1259 dev->release = fc_rport_dev_release; 1260 sprintf(dev->bus_id, "rport-%d:%d-%d", 1261 shost->host_no, channel, rport->number); 1262 transport_setup_device(dev); 1263 1264 error = device_add(dev); 1265 if (error) { 1266 printk(KERN_ERR "FC Remote Port device_add failed\n"); 1267 goto delete_rport; 1268 } 1269 transport_add_device(dev); 1270 transport_configure_device(dev); 1271 1272 if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) 1273 /* initiate a scan of the target */ 1274 scsi_queue_work(shost, &rport->scan_work); 1275 1276 return rport; 1277 1278delete_rport: 1279 transport_destroy_device(dev); 1280 put_device(dev->parent); 1281 spin_lock_irqsave(shost->host_lock, flags); 1282 list_del(&rport->peers); 1283 put_device(&shost->shost_gendev); 1284 spin_unlock_irqrestore(shost->host_lock, flags); 1285 put_device(dev->parent); 1286 kfree(rport); 1287 return NULL; 1288} 1289 1290/** 1291 * fc_remote_port_add - notifies the fc transport of the existence 1292 * of a remote FC port. 1293 * @shost: scsi host the remote port is connected to. 1294 * @channel: Channel on shost port connected to. 1295 * @ids: The world wide names, fc address, and FC4 port 1296 * roles for the remote port. 1297 * 1298 * The LLDD calls this routine to notify the transport of the existence 1299 * of a remote port. The LLDD provides the unique identifiers (wwpn,wwn) 1300 * of the port, it's FC address (port_id), and the FC4 roles that are 1301 * active for the port. 1302 * 1303 * For ports that are FCP targets (aka scsi targets), the FC transport 1304 * maintains consistent target id bindings on behalf of the LLDD. 1305 * A consistent target id binding is an assignment of a target id to 1306 * a remote port identifier, which persists while the scsi host is 1307 * attached. The remote port can disappear, then later reappear, and 1308 * it's target id assignment remains the same. This allows for shifts 1309 * in FC addressing (if binding by wwpn or wwnn) with no apparent 1310 * changes to the scsi subsystem which is based on scsi host number and 1311 * target id values. Bindings are only valid during the attachment of 1312 * the scsi host. If the host detaches, then later re-attaches, target 1313 * id bindings may change. 1314 * 1315 * This routine is responsible for returning a remote port structure. 1316 * The routine will search the list of remote ports it maintains 1317 * internally on behalf of consistent target id mappings. If found, the 1318 * remote port structure will be reused. Otherwise, a new remote port 1319 * structure will be allocated. 1320 * 1321 * Whenever a remote port is allocated, a new fc_remote_port class 1322 * device is created. 1323 * 1324 * Should not be called from interrupt context. 1325 * 1326 * Notes: 1327 * This routine assumes no locks are held on entry. 1328 **/ 1329struct fc_rport * 1330fc_remote_port_add(struct Scsi_Host *shost, int channel, 1331 struct fc_rport_identifiers *ids) 1332{ 1333 struct fc_rport *rport; 1334 unsigned long flags; 1335 int match = 0; 1336 1337 if (likely((ids->roles & FC_RPORT_ROLE_FCP_TARGET) && 1338 (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE))) { 1339 1340 /* search for a matching consistent binding */ 1341 1342 spin_lock_irqsave(shost->host_lock, flags); 1343 1344 list_for_each_entry(rport, &fc_host_rport_bindings(shost), 1345 peers) { 1346 if (rport->channel != channel) 1347 continue; 1348 1349 switch (fc_host_tgtid_bind_type(shost)) { 1350 case FC_TGTID_BIND_BY_WWPN: 1351 if (rport->port_name == ids->port_name) 1352 match = 1; 1353 break; 1354 case FC_TGTID_BIND_BY_WWNN: 1355 if (rport->node_name == ids->node_name) 1356 match = 1; 1357 break; 1358 case FC_TGTID_BIND_BY_ID: 1359 if (rport->port_id == ids->port_id) 1360 match = 1; 1361 break; 1362 case FC_TGTID_BIND_NONE: /* to keep compiler happy */ 1363 break; 1364 } 1365 1366 if (match) { 1367 list_move_tail(&rport->peers, 1368 &fc_host_rports(shost)); 1369 break; 1370 } 1371 } 1372 1373 spin_unlock_irqrestore(shost->host_lock, flags); 1374 1375 if (match) { 1376 memcpy(&rport->node_name, &ids->node_name, 1377 sizeof(rport->node_name)); 1378 memcpy(&rport->port_name, &ids->port_name, 1379 sizeof(rport->port_name)); 1380 rport->port_id = ids->port_id; 1381 rport->roles = ids->roles; 1382 rport->port_state = FC_PORTSTATE_ONLINE; 1383 1384 if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) 1385 /* initiate a scan of the target */ 1386 scsi_queue_work(shost, &rport->scan_work); 1387 1388 return rport; 1389 } 1390 } 1391 1392 /* No consistent binding found - create new remote port entry */ 1393 rport = fc_rport_create(shost, channel, ids); 1394 1395 return rport; 1396} 1397EXPORT_SYMBOL(fc_remote_port_add); 1398 1399/* 1400 * fc_rport_tgt_remove - Removes the scsi target on the remote port 1401 * @rport: The remote port to be operated on 1402 */ 1403static void 1404fc_rport_tgt_remove(struct fc_rport *rport) 1405{ 1406 struct Scsi_Host *shost = rport_to_shost(rport); 1407 1408 scsi_target_unblock(&rport->dev); 1409 1410 /* Stop anything on the workq */ 1411 if (!cancel_delayed_work(&rport->dev_loss_work)) 1412 flush_scheduled_work(); 1413 scsi_flush_work(shost); 1414 1415 scsi_remove_target(&rport->dev); 1416} 1417 1418/* 1419 * fc_rport_terminate - this routine tears down and deallocates a remote port. 1420 * @rport: The remote port to be terminated 1421 * 1422 * Notes: 1423 * This routine assumes no locks are held on entry. 1424 */ 1425static void 1426fc_rport_terminate(struct fc_rport *rport) 1427{ 1428 struct Scsi_Host *shost = rport_to_shost(rport); 1429 struct device *dev = &rport->dev; 1430 unsigned long flags; 1431 1432 fc_rport_tgt_remove(rport); 1433 1434 transport_remove_device(dev); 1435 device_del(dev); 1436 transport_destroy_device(dev); 1437 spin_lock_irqsave(shost->host_lock, flags); 1438 list_del(&rport->peers); 1439 spin_unlock_irqrestore(shost->host_lock, flags); 1440 put_device(&shost->shost_gendev); 1441} 1442 1443/** 1444 * fc_remote_port_delete - notifies the fc transport that a remote 1445 * port is no longer in existence. 1446 * @rport: The remote port that no longer exists 1447 * 1448 * The LLDD calls this routine to notify the transport that a remote 1449 * port is no longer part of the topology. Note: Although a port 1450 * may no longer be part of the topology, it may persist in the remote 1451 * ports displayed by the fc_host. This is done so that target id 1452 * mappings (managed via the remote port structures), are always visible 1453 * as long as the mapping is valid, regardless of port state, 1454 * 1455 * If the remote port is not an FCP Target, it will be fully torn down 1456 * and deallocated, including the fc_remote_port class device. 1457 * 1458 * If the remote port is an FCP Target, the port structure will be 1459 * marked as Not Present, but will remain as long as there is a valid 1460 * SCSI target id mapping associated with the port structure. Validity 1461 * is determined by the binding type. If binding by wwpn, then the port 1462 * structure is always valid and will not be deallocated until the host 1463 * is removed. If binding by wwnn, then the port structure is valid 1464 * until another port with the same node name is found in the topology. 1465 * If binding by port id (fc address), then the port structure is valid 1466 * valid until another port with the same address is identified. 1467 * 1468 * Called from interrupt or normal process context. 1469 * 1470 * Notes: 1471 * This routine assumes no locks are held on entry. 1472 **/ 1473void 1474fc_remote_port_delete(struct fc_rport *rport) 1475{ 1476 struct Scsi_Host *shost = rport_to_shost(rport); 1477 unsigned long flags; 1478 1479 /* If no scsi target id mapping or consistent binding type, delete it */ 1480 if ((rport->scsi_target_id == -1) || 1481 (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE)) { 1482 fc_rport_terminate(rport); 1483 return; 1484 } 1485 1486 fc_rport_tgt_remove(rport); 1487 1488 spin_lock_irqsave(shost->host_lock, flags); 1489 list_move_tail(&rport->peers, &fc_host_rport_bindings(shost)); 1490 spin_unlock_irqrestore(shost->host_lock, flags); 1491 1492 /* 1493 * Note: We do not remove or clear the hostdata area. This allows 1494 * host-specific target data to persist along with the 1495 * scsi_target_id. It's up to the host to manage it's hostdata area. 1496 */ 1497 1498 /* 1499 * Reinitialize port attributes that may change if the port comes back. 1500 */ 1501 rport->maxframe_size = -1; 1502 rport->supported_classes = FC_COS_UNSPECIFIED; 1503 rport->roles = FC_RPORT_ROLE_UNKNOWN; 1504 rport->port_state = FC_PORTSTATE_NOTPRESENT; 1505 1506 /* remove the identifiers that aren't used in the consisting binding */ 1507 switch (fc_host_tgtid_bind_type(shost)) { 1508 case FC_TGTID_BIND_BY_WWPN: 1509 rport->node_name = -1; 1510 rport->port_id = -1; 1511 break; 1512 case FC_TGTID_BIND_BY_WWNN: 1513 rport->port_name = -1; 1514 rport->port_id = -1; 1515 break; 1516 case FC_TGTID_BIND_BY_ID: 1517 rport->node_name = -1; 1518 rport->port_name = -1; 1519 break; 1520 case FC_TGTID_BIND_NONE: /* to keep compiler happy */ 1521 break; 1522 } 1523} 1524EXPORT_SYMBOL(fc_remote_port_delete); 1525 1526/** 1527 * fc_remote_port_rolechg - notifies the fc transport that the roles 1528 * on a remote may have changed. 1529 * @rport: The remote port that changed. 1530 * 1531 * The LLDD calls this routine to notify the transport that the roles 1532 * on a remote port may have changed. The largest effect of this is 1533 * if a port now becomes a FCP Target, it must be allocated a 1534 * scsi target id. If the port is no longer a FCP target, any 1535 * scsi target id value assigned to it will persist in case the 1536 * role changes back to include FCP Target. No changes in the scsi 1537 * midlayer will be invoked if the role changes (in the expectation 1538 * that the role will be resumed. If it doesn't normal error processing 1539 * will take place). 1540 * 1541 * Should not be called from interrupt context. 1542 * 1543 * Notes: 1544 * This routine assumes no locks are held on entry. 1545 **/ 1546void 1547fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) 1548{ 1549 struct Scsi_Host *shost = rport_to_shost(rport); 1550 struct fc_host_attrs *fc_host = 1551 (struct fc_host_attrs *)shost->shost_data; 1552 unsigned long flags; 1553 int create = 0; 1554 1555 rport->roles = roles; 1556 1557 spin_lock_irqsave(shost->host_lock, flags); 1558 if ((rport->scsi_target_id == -1) && 1559 (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { 1560 rport->scsi_target_id = fc_host->next_target_id++; 1561 create = 1; 1562 } 1563 spin_unlock_irqrestore(shost->host_lock, flags); 1564 1565 if (create) 1566 /* initiate a scan of the target */ 1567 scsi_queue_work(shost, &rport->scan_work); 1568} 1569EXPORT_SYMBOL(fc_remote_port_rolechg); 1570 1571/** 1572 * fc_timeout_blocked_rport - Timeout handler for blocked remote port 1573 * that fails to return in the alloted time. 1574 * @data: scsi target that failed to reappear in the alloted time. 1575 **/ 1576static void 1577fc_timeout_blocked_rport(void *data) 1578{ 1579 struct fc_rport *rport = (struct fc_rport *)data; 1580 1581 rport->port_state = FC_PORTSTATE_OFFLINE; 1582 1583 dev_printk(KERN_ERR, &rport->dev, 1584 "blocked FC remote port time out: removing target\n"); 1585 1586 /* 1587 * As this only occurs if the remote port (scsi target) 1588 * went away and didn't come back - we'll remove 1589 * all attached scsi devices. 1590 */ 1591 scsi_target_unblock(&rport->dev); 1592 scsi_remove_target(&rport->dev); 1593} 1594 1595/** 1596 * fc_remote_port_block - temporarily block any scsi traffic to a remote port. 1597 * @rport: remote port to be blocked. 1598 * 1599 * scsi lldd's with a FC transport call this routine to temporarily stop 1600 * all scsi traffic to a remote port. If the port is not a SCSI target, 1601 * no action is taken. If the port is a SCSI target, all attached devices 1602 * are placed into a SDEV_BLOCK state and a timer is started. The timer is 1603 * represents the maximum amount of time the port may be blocked. If the 1604 * timer expires, the port is considered non-existent and the attached 1605 * scsi devices will be removed. 1606 * 1607 * Called from interrupt or normal process context. 1608 * 1609 * Returns zero if successful or error if not 1610 * 1611 * Notes: 1612 * This routine assumes no locks are held on entry. 1613 * 1614 * The timeout and timer types are extracted from the fc transport 1615 * attributes from the caller's rport pointer. 1616 **/ 1617int 1618fc_remote_port_block(struct fc_rport *rport) 1619{ 1620 int timeout = rport->dev_loss_tmo; 1621 struct work_struct *work = &rport->dev_loss_work; 1622 1623 if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT) 1624 return -EINVAL; 1625 1626 scsi_target_block(&rport->dev); 1627 1628 /* cap the length the devices can be blocked */ 1629 schedule_delayed_work(work, timeout * HZ); 1630 1631 rport->port_state = FC_PORTSTATE_BLOCKED; 1632 return 0; 1633} 1634EXPORT_SYMBOL(fc_remote_port_block); 1635 1636/** 1637 * fc_remote_port_unblock - restart any blocked scsi traffic to a remote port. 1638 * @rport: remote port to be unblocked. 1639 * 1640 * scsi lld's with a FC transport call this routine to restart IO to all 1641 * devices associated with the caller's scsi target following a fc_target_block 1642 * request. Called from interrupt or normal process context. 1643 * 1644 * Notes: 1645 * This routine assumes no locks are held on entry. 1646 **/ 1647 void 1648fc_remote_port_unblock(struct fc_rport *rport) 1649{ 1650 struct work_struct *work = &rport->dev_loss_work; 1651 struct Scsi_Host *shost = rport_to_shost(rport); 1652 1653 /* 1654 * Stop the target timer first. Take no action on the del_timer 1655 * failure as the state machine state change will validate the 1656 * transaction. 1657 */ 1658 if (!cancel_delayed_work(work)) 1659 flush_scheduled_work(); 1660 1661 if (rport->port_state == FC_PORTSTATE_OFFLINE) 1662 /* 1663 * initiate a scan of the target as the target has 1664 * been torn down. 1665 */ 1666 scsi_queue_work(shost, &rport->scan_work); 1667 else 1668 scsi_target_unblock(&rport->dev); 1669 1670 rport->port_state = FC_PORTSTATE_ONLINE; 1671} 1672EXPORT_SYMBOL(fc_remote_port_unblock); 1673 1674/** 1675 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port. 1676 * @data: remote port to be scanned. 1677 **/ 1678static void 1679fc_scsi_scan_rport(void *data) 1680{ 1681 struct fc_rport *rport = (struct fc_rport *)data; 1682 1683 scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id, 1684 SCAN_WILD_CARD, 1); 1685} 1686 1687 1688MODULE_AUTHOR("Martin Hicks"); 1689MODULE_DESCRIPTION("FC Transport Attributes"); 1690MODULE_LICENSE("GPL"); 1691 1692module_init(fc_transport_init); 1693module_exit(fc_transport_exit); 1694