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