1 /* 2 * Copyright(c) 2011 - 2012 Intel Corporation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 * 17 * Maintained at www.Open-FCoE.org 18 */ 19 20 #include <linux/module.h> 21 #include <linux/types.h> 22 #include <linux/kernel.h> 23 #include <linux/etherdevice.h> 24 25 #include <scsi/fcoe_sysfs.h> 26 27 static atomic_t ctlr_num; 28 static atomic_t fcf_num; 29 30 /* 31 * fcoe_fcf_dev_loss_tmo: the default number of seconds that fcoe sysfs 32 * should insulate the loss of a fcf. 33 */ 34 static unsigned int fcoe_fcf_dev_loss_tmo = 1800; /* seconds */ 35 36 module_param_named(fcf_dev_loss_tmo, fcoe_fcf_dev_loss_tmo, 37 uint, S_IRUGO|S_IWUSR); 38 MODULE_PARM_DESC(fcf_dev_loss_tmo, 39 "Maximum number of seconds that libfcoe should" 40 " insulate the loss of a fcf. Once this value is" 41 " exceeded, the fcf is removed."); 42 43 /* 44 * These are used by the fcoe_*_show_function routines, they 45 * are intentionally placed in the .c file as they're not intended 46 * for use throughout the code. 47 */ 48 #define fcoe_ctlr_id(x) \ 49 ((x)->id) 50 #define fcoe_ctlr_work_q_name(x) \ 51 ((x)->work_q_name) 52 #define fcoe_ctlr_work_q(x) \ 53 ((x)->work_q) 54 #define fcoe_ctlr_devloss_work_q_name(x) \ 55 ((x)->devloss_work_q_name) 56 #define fcoe_ctlr_devloss_work_q(x) \ 57 ((x)->devloss_work_q) 58 #define fcoe_ctlr_mode(x) \ 59 ((x)->mode) 60 #define fcoe_ctlr_fcf_dev_loss_tmo(x) \ 61 ((x)->fcf_dev_loss_tmo) 62 #define fcoe_ctlr_link_fail(x) \ 63 ((x)->lesb.lesb_link_fail) 64 #define fcoe_ctlr_vlink_fail(x) \ 65 ((x)->lesb.lesb_vlink_fail) 66 #define fcoe_ctlr_miss_fka(x) \ 67 ((x)->lesb.lesb_miss_fka) 68 #define fcoe_ctlr_symb_err(x) \ 69 ((x)->lesb.lesb_symb_err) 70 #define fcoe_ctlr_err_block(x) \ 71 ((x)->lesb.lesb_err_block) 72 #define fcoe_ctlr_fcs_error(x) \ 73 ((x)->lesb.lesb_fcs_error) 74 #define fcoe_fcf_state(x) \ 75 ((x)->state) 76 #define fcoe_fcf_fabric_name(x) \ 77 ((x)->fabric_name) 78 #define fcoe_fcf_switch_name(x) \ 79 ((x)->switch_name) 80 #define fcoe_fcf_fc_map(x) \ 81 ((x)->fc_map) 82 #define fcoe_fcf_vfid(x) \ 83 ((x)->vfid) 84 #define fcoe_fcf_mac(x) \ 85 ((x)->mac) 86 #define fcoe_fcf_priority(x) \ 87 ((x)->priority) 88 #define fcoe_fcf_fka_period(x) \ 89 ((x)->fka_period) 90 #define fcoe_fcf_dev_loss_tmo(x) \ 91 ((x)->dev_loss_tmo) 92 #define fcoe_fcf_selected(x) \ 93 ((x)->selected) 94 #define fcoe_fcf_vlan_id(x) \ 95 ((x)->vlan_id) 96 97 /* 98 * dev_loss_tmo attribute 99 */ 100 static int fcoe_str_to_dev_loss(const char *buf, unsigned long *val) 101 { 102 int ret; 103 104 ret = kstrtoul(buf, 0, val); 105 if (ret) 106 return -EINVAL; 107 /* 108 * Check for overflow; dev_loss_tmo is u32 109 */ 110 if (*val > UINT_MAX) 111 return -EINVAL; 112 113 return 0; 114 } 115 116 static int fcoe_fcf_set_dev_loss_tmo(struct fcoe_fcf_device *fcf, 117 unsigned long val) 118 { 119 if ((fcf->state == FCOE_FCF_STATE_UNKNOWN) || 120 (fcf->state == FCOE_FCF_STATE_DISCONNECTED) || 121 (fcf->state == FCOE_FCF_STATE_DELETED)) 122 return -EBUSY; 123 /* 124 * Check for overflow; dev_loss_tmo is u32 125 */ 126 if (val > UINT_MAX) 127 return -EINVAL; 128 129 fcoe_fcf_dev_loss_tmo(fcf) = val; 130 return 0; 131 } 132 133 #define FCOE_DEVICE_ATTR(_prefix, _name, _mode, _show, _store) \ 134 struct device_attribute device_attr_fcoe_##_prefix##_##_name = \ 135 __ATTR(_name, _mode, _show, _store) 136 137 #define fcoe_ctlr_show_function(field, format_string, sz, cast) \ 138 static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \ 139 struct device_attribute *attr, \ 140 char *buf) \ 141 { \ 142 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); \ 143 if (ctlr->f->get_fcoe_ctlr_##field) \ 144 ctlr->f->get_fcoe_ctlr_##field(ctlr); \ 145 return snprintf(buf, sz, format_string, \ 146 cast fcoe_ctlr_##field(ctlr)); \ 147 } 148 149 #define fcoe_fcf_show_function(field, format_string, sz, cast) \ 150 static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \ 151 struct device_attribute *attr, \ 152 char *buf) \ 153 { \ 154 struct fcoe_fcf_device *fcf = dev_to_fcf(dev); \ 155 struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); \ 156 if (ctlr->f->get_fcoe_fcf_##field) \ 157 ctlr->f->get_fcoe_fcf_##field(fcf); \ 158 return snprintf(buf, sz, format_string, \ 159 cast fcoe_fcf_##field(fcf)); \ 160 } 161 162 #define fcoe_ctlr_private_show_function(field, format_string, sz, cast) \ 163 static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \ 164 struct device_attribute *attr, \ 165 char *buf) \ 166 { \ 167 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); \ 168 return snprintf(buf, sz, format_string, cast fcoe_ctlr_##field(ctlr)); \ 169 } 170 171 #define fcoe_fcf_private_show_function(field, format_string, sz, cast) \ 172 static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \ 173 struct device_attribute *attr, \ 174 char *buf) \ 175 { \ 176 struct fcoe_fcf_device *fcf = dev_to_fcf(dev); \ 177 return snprintf(buf, sz, format_string, cast fcoe_fcf_##field(fcf)); \ 178 } 179 180 #define fcoe_ctlr_private_rd_attr(field, format_string, sz) \ 181 fcoe_ctlr_private_show_function(field, format_string, sz, ) \ 182 static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ 183 show_fcoe_ctlr_device_##field, NULL) 184 185 #define fcoe_ctlr_rd_attr(field, format_string, sz) \ 186 fcoe_ctlr_show_function(field, format_string, sz, ) \ 187 static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ 188 show_fcoe_ctlr_device_##field, NULL) 189 190 #define fcoe_fcf_rd_attr(field, format_string, sz) \ 191 fcoe_fcf_show_function(field, format_string, sz, ) \ 192 static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ 193 show_fcoe_fcf_device_##field, NULL) 194 195 #define fcoe_fcf_private_rd_attr(field, format_string, sz) \ 196 fcoe_fcf_private_show_function(field, format_string, sz, ) \ 197 static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ 198 show_fcoe_fcf_device_##field, NULL) 199 200 #define fcoe_ctlr_private_rd_attr_cast(field, format_string, sz, cast) \ 201 fcoe_ctlr_private_show_function(field, format_string, sz, (cast)) \ 202 static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ 203 show_fcoe_ctlr_device_##field, NULL) 204 205 #define fcoe_fcf_private_rd_attr_cast(field, format_string, sz, cast) \ 206 fcoe_fcf_private_show_function(field, format_string, sz, (cast)) \ 207 static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ 208 show_fcoe_fcf_device_##field, NULL) 209 210 #define fcoe_enum_name_search(title, table_type, table) \ 211 static const char *get_fcoe_##title##_name(enum table_type table_key) \ 212 { \ 213 if (table_key < 0 || table_key >= ARRAY_SIZE(table)) \ 214 return NULL; \ 215 return table[table_key]; \ 216 } 217 218 static char *fip_conn_type_names[] = { 219 [ FIP_CONN_TYPE_UNKNOWN ] = "Unknown", 220 [ FIP_CONN_TYPE_FABRIC ] = "Fabric", 221 [ FIP_CONN_TYPE_VN2VN ] = "VN2VN", 222 }; 223 fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names) 224 #define FCOE_CTLR_MODE_MAX_NAMELEN 50 225 226 static char *fcf_state_names[] = { 227 [ FCOE_FCF_STATE_UNKNOWN ] = "Unknown", 228 [ FCOE_FCF_STATE_DISCONNECTED ] = "Disconnected", 229 [ FCOE_FCF_STATE_CONNECTED ] = "Connected", 230 }; 231 fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names) 232 #define FCOE_FCF_STATE_MAX_NAMELEN 50 233 234 static ssize_t show_fcf_state(struct device *dev, 235 struct device_attribute *attr, 236 char *buf) 237 { 238 struct fcoe_fcf_device *fcf = dev_to_fcf(dev); 239 const char *name; 240 name = get_fcoe_fcf_state_name(fcf->state); 241 if (!name) 242 return -EINVAL; 243 return snprintf(buf, FCOE_FCF_STATE_MAX_NAMELEN, "%s\n", name); 244 } 245 static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL); 246 247 #define FCOE_MAX_MODENAME_LEN 20 248 static ssize_t show_ctlr_mode(struct device *dev, 249 struct device_attribute *attr, 250 char *buf) 251 { 252 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); 253 const char *name; 254 255 if (ctlr->f->get_fcoe_ctlr_mode) 256 ctlr->f->get_fcoe_ctlr_mode(ctlr); 257 258 name = get_fcoe_ctlr_mode_name(ctlr->mode); 259 if (!name) 260 return -EINVAL; 261 return snprintf(buf, FCOE_CTLR_MODE_MAX_NAMELEN, 262 "%s\n", name); 263 } 264 static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO, 265 show_ctlr_mode, NULL); 266 267 static ssize_t 268 store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev, 269 struct device_attribute *attr, 270 const char *buf, size_t count) 271 { 272 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); 273 struct fcoe_fcf_device *fcf; 274 unsigned long val; 275 int rc; 276 277 rc = fcoe_str_to_dev_loss(buf, &val); 278 if (rc) 279 return rc; 280 281 fcoe_ctlr_fcf_dev_loss_tmo(ctlr) = val; 282 mutex_lock(&ctlr->lock); 283 list_for_each_entry(fcf, &ctlr->fcfs, peers) 284 fcoe_fcf_set_dev_loss_tmo(fcf, val); 285 mutex_unlock(&ctlr->lock); 286 return count; 287 } 288 fcoe_ctlr_private_show_function(fcf_dev_loss_tmo, "%d\n", 20, ); 289 static FCOE_DEVICE_ATTR(ctlr, fcf_dev_loss_tmo, S_IRUGO | S_IWUSR, 290 show_fcoe_ctlr_device_fcf_dev_loss_tmo, 291 store_private_fcoe_ctlr_fcf_dev_loss_tmo); 292 293 /* Link Error Status Block (LESB) */ 294 fcoe_ctlr_rd_attr(link_fail, "%u\n", 20); 295 fcoe_ctlr_rd_attr(vlink_fail, "%u\n", 20); 296 fcoe_ctlr_rd_attr(miss_fka, "%u\n", 20); 297 fcoe_ctlr_rd_attr(symb_err, "%u\n", 20); 298 fcoe_ctlr_rd_attr(err_block, "%u\n", 20); 299 fcoe_ctlr_rd_attr(fcs_error, "%u\n", 20); 300 301 fcoe_fcf_private_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long); 302 fcoe_fcf_private_rd_attr_cast(switch_name, "0x%llx\n", 20, unsigned long long); 303 fcoe_fcf_private_rd_attr(priority, "%u\n", 20); 304 fcoe_fcf_private_rd_attr(fc_map, "0x%x\n", 20); 305 fcoe_fcf_private_rd_attr(vfid, "%u\n", 20); 306 fcoe_fcf_private_rd_attr(mac, "%pM\n", 20); 307 fcoe_fcf_private_rd_attr(fka_period, "%u\n", 20); 308 fcoe_fcf_rd_attr(selected, "%u\n", 20); 309 fcoe_fcf_rd_attr(vlan_id, "%u\n", 20); 310 311 fcoe_fcf_private_show_function(dev_loss_tmo, "%d\n", 20, ) 312 static ssize_t 313 store_fcoe_fcf_dev_loss_tmo(struct device *dev, struct device_attribute *attr, 314 const char *buf, size_t count) 315 { 316 struct fcoe_fcf_device *fcf = dev_to_fcf(dev); 317 unsigned long val; 318 int rc; 319 320 rc = fcoe_str_to_dev_loss(buf, &val); 321 if (rc) 322 return rc; 323 324 rc = fcoe_fcf_set_dev_loss_tmo(fcf, val); 325 if (rc) 326 return rc; 327 return count; 328 } 329 static FCOE_DEVICE_ATTR(fcf, dev_loss_tmo, S_IRUGO | S_IWUSR, 330 show_fcoe_fcf_device_dev_loss_tmo, 331 store_fcoe_fcf_dev_loss_tmo); 332 333 static struct attribute *fcoe_ctlr_lesb_attrs[] = { 334 &device_attr_fcoe_ctlr_link_fail.attr, 335 &device_attr_fcoe_ctlr_vlink_fail.attr, 336 &device_attr_fcoe_ctlr_miss_fka.attr, 337 &device_attr_fcoe_ctlr_symb_err.attr, 338 &device_attr_fcoe_ctlr_err_block.attr, 339 &device_attr_fcoe_ctlr_fcs_error.attr, 340 NULL, 341 }; 342 343 static struct attribute_group fcoe_ctlr_lesb_attr_group = { 344 .name = "lesb", 345 .attrs = fcoe_ctlr_lesb_attrs, 346 }; 347 348 static struct attribute *fcoe_ctlr_attrs[] = { 349 &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr, 350 &device_attr_fcoe_ctlr_mode.attr, 351 NULL, 352 }; 353 354 static struct attribute_group fcoe_ctlr_attr_group = { 355 .attrs = fcoe_ctlr_attrs, 356 }; 357 358 static const struct attribute_group *fcoe_ctlr_attr_groups[] = { 359 &fcoe_ctlr_attr_group, 360 &fcoe_ctlr_lesb_attr_group, 361 NULL, 362 }; 363 364 static struct attribute *fcoe_fcf_attrs[] = { 365 &device_attr_fcoe_fcf_fabric_name.attr, 366 &device_attr_fcoe_fcf_switch_name.attr, 367 &device_attr_fcoe_fcf_dev_loss_tmo.attr, 368 &device_attr_fcoe_fcf_fc_map.attr, 369 &device_attr_fcoe_fcf_vfid.attr, 370 &device_attr_fcoe_fcf_mac.attr, 371 &device_attr_fcoe_fcf_priority.attr, 372 &device_attr_fcoe_fcf_fka_period.attr, 373 &device_attr_fcoe_fcf_state.attr, 374 &device_attr_fcoe_fcf_selected.attr, 375 &device_attr_fcoe_fcf_vlan_id.attr, 376 NULL 377 }; 378 379 static struct attribute_group fcoe_fcf_attr_group = { 380 .attrs = fcoe_fcf_attrs, 381 }; 382 383 static const struct attribute_group *fcoe_fcf_attr_groups[] = { 384 &fcoe_fcf_attr_group, 385 NULL, 386 }; 387 388 struct bus_type fcoe_bus_type; 389 390 static int fcoe_bus_match(struct device *dev, 391 struct device_driver *drv) 392 { 393 if (dev->bus == &fcoe_bus_type) 394 return 1; 395 return 0; 396 } 397 398 /** 399 * fcoe_ctlr_device_release() - Release the FIP ctlr memory 400 * @dev: Pointer to the FIP ctlr's embedded device 401 * 402 * Called when the last FIP ctlr reference is released. 403 */ 404 static void fcoe_ctlr_device_release(struct device *dev) 405 { 406 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); 407 kfree(ctlr); 408 } 409 410 /** 411 * fcoe_fcf_device_release() - Release the FIP fcf memory 412 * @dev: Pointer to the fcf's embedded device 413 * 414 * Called when the last FIP fcf reference is released. 415 */ 416 static void fcoe_fcf_device_release(struct device *dev) 417 { 418 struct fcoe_fcf_device *fcf = dev_to_fcf(dev); 419 kfree(fcf); 420 } 421 422 struct device_type fcoe_ctlr_device_type = { 423 .name = "fcoe_ctlr", 424 .groups = fcoe_ctlr_attr_groups, 425 .release = fcoe_ctlr_device_release, 426 }; 427 428 struct device_type fcoe_fcf_device_type = { 429 .name = "fcoe_fcf", 430 .groups = fcoe_fcf_attr_groups, 431 .release = fcoe_fcf_device_release, 432 }; 433 434 struct bus_type fcoe_bus_type = { 435 .name = "fcoe", 436 .match = &fcoe_bus_match, 437 }; 438 439 /** 440 * fcoe_ctlr_device_flush_work() - Flush a FIP ctlr's workqueue 441 * @ctlr: Pointer to the FIP ctlr whose workqueue is to be flushed 442 */ 443 void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr) 444 { 445 if (!fcoe_ctlr_work_q(ctlr)) { 446 printk(KERN_ERR 447 "ERROR: FIP Ctlr '%d' attempted to flush work, " 448 "when no workqueue created.\n", ctlr->id); 449 dump_stack(); 450 return; 451 } 452 453 flush_workqueue(fcoe_ctlr_work_q(ctlr)); 454 } 455 456 /** 457 * fcoe_ctlr_device_queue_work() - Schedule work for a FIP ctlr's workqueue 458 * @ctlr: Pointer to the FIP ctlr who owns the devloss workqueue 459 * @work: Work to queue for execution 460 * 461 * Return value: 462 * 1 on success / 0 already queued / < 0 for error 463 */ 464 int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr, 465 struct work_struct *work) 466 { 467 if (unlikely(!fcoe_ctlr_work_q(ctlr))) { 468 printk(KERN_ERR 469 "ERROR: FIP Ctlr '%d' attempted to queue work, " 470 "when no workqueue created.\n", ctlr->id); 471 dump_stack(); 472 473 return -EINVAL; 474 } 475 476 return queue_work(fcoe_ctlr_work_q(ctlr), work); 477 } 478 479 /** 480 * fcoe_ctlr_device_flush_devloss() - Flush a FIP ctlr's devloss workqueue 481 * @ctlr: Pointer to FIP ctlr whose workqueue is to be flushed 482 */ 483 void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr) 484 { 485 if (!fcoe_ctlr_devloss_work_q(ctlr)) { 486 printk(KERN_ERR 487 "ERROR: FIP Ctlr '%d' attempted to flush work, " 488 "when no workqueue created.\n", ctlr->id); 489 dump_stack(); 490 return; 491 } 492 493 flush_workqueue(fcoe_ctlr_devloss_work_q(ctlr)); 494 } 495 496 /** 497 * fcoe_ctlr_device_queue_devloss_work() - Schedule work for a FIP ctlr's devloss workqueue 498 * @ctlr: Pointer to the FIP ctlr who owns the devloss workqueue 499 * @work: Work to queue for execution 500 * @delay: jiffies to delay the work queuing 501 * 502 * Return value: 503 * 1 on success / 0 already queued / < 0 for error 504 */ 505 int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr, 506 struct delayed_work *work, 507 unsigned long delay) 508 { 509 if (unlikely(!fcoe_ctlr_devloss_work_q(ctlr))) { 510 printk(KERN_ERR 511 "ERROR: FIP Ctlr '%d' attempted to queue work, " 512 "when no workqueue created.\n", ctlr->id); 513 dump_stack(); 514 515 return -EINVAL; 516 } 517 518 return queue_delayed_work(fcoe_ctlr_devloss_work_q(ctlr), work, delay); 519 } 520 521 static int fcoe_fcf_device_match(struct fcoe_fcf_device *new, 522 struct fcoe_fcf_device *old) 523 { 524 if (new->switch_name == old->switch_name && 525 new->fabric_name == old->fabric_name && 526 new->fc_map == old->fc_map && 527 compare_ether_addr(new->mac, old->mac) == 0) 528 return 1; 529 return 0; 530 } 531 532 /** 533 * fcoe_ctlr_device_add() - Add a FIP ctlr to sysfs 534 * @parent: The parent device to which the fcoe_ctlr instance 535 * should be attached 536 * @f: The LLD's FCoE sysfs function template pointer 537 * @priv_size: Size to be allocated with the fcoe_ctlr_device for the LLD 538 * 539 * This routine allocates a FIP ctlr object with some additional memory 540 * for the LLD. The FIP ctlr is initialized, added to sysfs and then 541 * attributes are added to it. 542 */ 543 struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent, 544 struct fcoe_sysfs_function_template *f, 545 int priv_size) 546 { 547 struct fcoe_ctlr_device *ctlr; 548 int error = 0; 549 550 ctlr = kzalloc(sizeof(struct fcoe_ctlr_device) + priv_size, 551 GFP_KERNEL); 552 if (!ctlr) 553 goto out; 554 555 ctlr->id = atomic_inc_return(&ctlr_num) - 1; 556 ctlr->f = f; 557 INIT_LIST_HEAD(&ctlr->fcfs); 558 mutex_init(&ctlr->lock); 559 ctlr->dev.parent = parent; 560 ctlr->dev.bus = &fcoe_bus_type; 561 ctlr->dev.type = &fcoe_ctlr_device_type; 562 563 ctlr->fcf_dev_loss_tmo = fcoe_fcf_dev_loss_tmo; 564 565 snprintf(ctlr->work_q_name, sizeof(ctlr->work_q_name), 566 "ctlr_wq_%d", ctlr->id); 567 ctlr->work_q = create_singlethread_workqueue( 568 ctlr->work_q_name); 569 if (!ctlr->work_q) 570 goto out_del; 571 572 snprintf(ctlr->devloss_work_q_name, 573 sizeof(ctlr->devloss_work_q_name), 574 "ctlr_dl_wq_%d", ctlr->id); 575 ctlr->devloss_work_q = create_singlethread_workqueue( 576 ctlr->devloss_work_q_name); 577 if (!ctlr->devloss_work_q) 578 goto out_del_q; 579 580 dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id); 581 error = device_register(&ctlr->dev); 582 if (error) 583 goto out_del_q2; 584 585 return ctlr; 586 587 out_del_q2: 588 destroy_workqueue(ctlr->devloss_work_q); 589 ctlr->devloss_work_q = NULL; 590 out_del_q: 591 destroy_workqueue(ctlr->work_q); 592 ctlr->work_q = NULL; 593 out_del: 594 kfree(ctlr); 595 out: 596 return NULL; 597 } 598 EXPORT_SYMBOL_GPL(fcoe_ctlr_device_add); 599 600 /** 601 * fcoe_ctlr_device_delete() - Delete a FIP ctlr and its subtree from sysfs 602 * @ctlr: A pointer to the ctlr to be deleted 603 * 604 * Deletes a FIP ctlr and any fcfs attached 605 * to it. Deleting fcfs will cause their childen 606 * to be deleted as well. 607 * 608 * The ctlr is detached from sysfs and it's resources 609 * are freed (work q), but the memory is not freed 610 * until its last reference is released. 611 * 612 * This routine expects no locks to be held before 613 * calling. 614 * 615 * TODO: Currently there are no callbacks to clean up LLD data 616 * for a fcoe_fcf_device. LLDs must keep this in mind as they need 617 * to clean up each of their LLD data for all fcoe_fcf_device before 618 * calling fcoe_ctlr_device_delete. 619 */ 620 void fcoe_ctlr_device_delete(struct fcoe_ctlr_device *ctlr) 621 { 622 struct fcoe_fcf_device *fcf, *next; 623 /* Remove any attached fcfs */ 624 mutex_lock(&ctlr->lock); 625 list_for_each_entry_safe(fcf, next, 626 &ctlr->fcfs, peers) { 627 list_del(&fcf->peers); 628 fcf->state = FCOE_FCF_STATE_DELETED; 629 fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work); 630 } 631 mutex_unlock(&ctlr->lock); 632 633 fcoe_ctlr_device_flush_work(ctlr); 634 635 destroy_workqueue(ctlr->devloss_work_q); 636 ctlr->devloss_work_q = NULL; 637 destroy_workqueue(ctlr->work_q); 638 ctlr->work_q = NULL; 639 640 device_unregister(&ctlr->dev); 641 } 642 EXPORT_SYMBOL_GPL(fcoe_ctlr_device_delete); 643 644 /** 645 * fcoe_fcf_device_final_delete() - Final delete routine 646 * @work: The FIP fcf's embedded work struct 647 * 648 * It is expected that the fcf has been removed from 649 * the FIP ctlr's list before calling this routine. 650 */ 651 static void fcoe_fcf_device_final_delete(struct work_struct *work) 652 { 653 struct fcoe_fcf_device *fcf = 654 container_of(work, struct fcoe_fcf_device, delete_work); 655 struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); 656 657 /* 658 * Cancel any outstanding timers. These should really exist 659 * only when rmmod'ing the LLDD and we're asking for 660 * immediate termination of the rports 661 */ 662 if (!cancel_delayed_work(&fcf->dev_loss_work)) 663 fcoe_ctlr_device_flush_devloss(ctlr); 664 665 device_unregister(&fcf->dev); 666 } 667 668 /** 669 * fip_timeout_deleted_fcf() - Delete a fcf when the devloss timer fires 670 * @work: The FIP fcf's embedded work struct 671 * 672 * Removes the fcf from the FIP ctlr's list of fcfs and 673 * queues the final deletion. 674 */ 675 static void fip_timeout_deleted_fcf(struct work_struct *work) 676 { 677 struct fcoe_fcf_device *fcf = 678 container_of(work, struct fcoe_fcf_device, dev_loss_work.work); 679 struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); 680 681 mutex_lock(&ctlr->lock); 682 683 /* 684 * If the fcf is deleted or reconnected before the timer 685 * fires the devloss queue will be flushed, but the state will 686 * either be CONNECTED or DELETED. If that is the case we 687 * cancel deleting the fcf. 688 */ 689 if (fcf->state != FCOE_FCF_STATE_DISCONNECTED) 690 goto out; 691 692 dev_printk(KERN_ERR, &fcf->dev, 693 "FIP fcf connection time out: removing fcf\n"); 694 695 list_del(&fcf->peers); 696 fcf->state = FCOE_FCF_STATE_DELETED; 697 fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work); 698 699 out: 700 mutex_unlock(&ctlr->lock); 701 } 702 703 /** 704 * fcoe_fcf_device_delete() - Delete a FIP fcf 705 * @fcf: Pointer to the fcf which is to be deleted 706 * 707 * Queues the FIP fcf on the devloss workqueue 708 * 709 * Expects the ctlr_attrs mutex to be held for fcf 710 * state change. 711 */ 712 void fcoe_fcf_device_delete(struct fcoe_fcf_device *fcf) 713 { 714 struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); 715 int timeout = fcf->dev_loss_tmo; 716 717 if (fcf->state != FCOE_FCF_STATE_CONNECTED) 718 return; 719 720 fcf->state = FCOE_FCF_STATE_DISCONNECTED; 721 722 /* 723 * FCF will only be re-connected by the LLD calling 724 * fcoe_fcf_device_add, and it should be setting up 725 * priv then. 726 */ 727 fcf->priv = NULL; 728 729 fcoe_ctlr_device_queue_devloss_work(ctlr, &fcf->dev_loss_work, 730 timeout * HZ); 731 } 732 EXPORT_SYMBOL_GPL(fcoe_fcf_device_delete); 733 734 /** 735 * fcoe_fcf_device_add() - Add a FCoE sysfs fcoe_fcf_device to the system 736 * @ctlr: The fcoe_ctlr_device that will be the fcoe_fcf_device parent 737 * @new_fcf: A temporary FCF used for lookups on the current list of fcfs 738 * 739 * Expects to be called with the ctlr->lock held 740 */ 741 struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr, 742 struct fcoe_fcf_device *new_fcf) 743 { 744 struct fcoe_fcf_device *fcf; 745 int error = 0; 746 747 list_for_each_entry(fcf, &ctlr->fcfs, peers) { 748 if (fcoe_fcf_device_match(new_fcf, fcf)) { 749 if (fcf->state == FCOE_FCF_STATE_CONNECTED) 750 return fcf; 751 752 fcf->state = FCOE_FCF_STATE_CONNECTED; 753 754 if (!cancel_delayed_work(&fcf->dev_loss_work)) 755 fcoe_ctlr_device_flush_devloss(ctlr); 756 757 return fcf; 758 } 759 } 760 761 fcf = kzalloc(sizeof(struct fcoe_fcf_device), GFP_ATOMIC); 762 if (unlikely(!fcf)) 763 goto out; 764 765 INIT_WORK(&fcf->delete_work, fcoe_fcf_device_final_delete); 766 INIT_DELAYED_WORK(&fcf->dev_loss_work, fip_timeout_deleted_fcf); 767 768 fcf->dev.parent = &ctlr->dev; 769 fcf->dev.bus = &fcoe_bus_type; 770 fcf->dev.type = &fcoe_fcf_device_type; 771 fcf->id = atomic_inc_return(&fcf_num) - 1; 772 fcf->state = FCOE_FCF_STATE_UNKNOWN; 773 774 fcf->dev_loss_tmo = ctlr->fcf_dev_loss_tmo; 775 776 dev_set_name(&fcf->dev, "fcf_%d", fcf->id); 777 778 fcf->fabric_name = new_fcf->fabric_name; 779 fcf->switch_name = new_fcf->switch_name; 780 fcf->fc_map = new_fcf->fc_map; 781 fcf->vfid = new_fcf->vfid; 782 memcpy(fcf->mac, new_fcf->mac, ETH_ALEN); 783 fcf->priority = new_fcf->priority; 784 fcf->fka_period = new_fcf->fka_period; 785 fcf->selected = new_fcf->selected; 786 787 error = device_register(&fcf->dev); 788 if (error) 789 goto out_del; 790 791 fcf->state = FCOE_FCF_STATE_CONNECTED; 792 list_add_tail(&fcf->peers, &ctlr->fcfs); 793 794 return fcf; 795 796 out_del: 797 kfree(fcf); 798 out: 799 return NULL; 800 } 801 EXPORT_SYMBOL_GPL(fcoe_fcf_device_add); 802 803 int __init fcoe_sysfs_setup(void) 804 { 805 int error; 806 807 atomic_set(&ctlr_num, 0); 808 atomic_set(&fcf_num, 0); 809 810 error = bus_register(&fcoe_bus_type); 811 if (error) 812 return error; 813 814 return 0; 815 } 816 817 void __exit fcoe_sysfs_teardown(void) 818 { 819 bus_unregister(&fcoe_bus_type); 820 } 821