Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fcoe_sysfs.c
Go to the documentation of this file.
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 
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) ||
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  int i; \
214  char *name = NULL; \
215  \
216  for (i = 0; i < ARRAY_SIZE(table); i++) { \
217  if (table[i].value == table_key) { \
218  name = table[i].name; \
219  break; \
220  } \
221  } \
222  return name; \
223 }
224 
225 static struct {
227  char *name;
228 } fcf_state_names[] = {
229  { FCOE_FCF_STATE_UNKNOWN, "Unknown" },
230  { FCOE_FCF_STATE_DISCONNECTED, "Disconnected" },
231  { FCOE_FCF_STATE_CONNECTED, "Connected" },
232 };
234 #define FCOE_FCF_STATE_MAX_NAMELEN 50
235 
236 static ssize_t show_fcf_state(struct device *dev,
237  struct device_attribute *attr,
238  char *buf)
239 {
240  struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
241  const char *name;
242  name = get_fcoe_fcf_state_name(fcf->state);
243  if (!name)
244  return -EINVAL;
245  return snprintf(buf, FCOE_FCF_STATE_MAX_NAMELEN, "%s\n", name);
246 }
247 static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL);
248 
249 static struct {
250  enum fip_conn_type value;
251  char *name;
252 } fip_conn_type_names[] = {
253  { FIP_CONN_TYPE_UNKNOWN, "Unknown" },
254  { FIP_CONN_TYPE_FABRIC, "Fabric" },
255  { FIP_CONN_TYPE_VN2VN, "VN2VN" },
256 };
257 fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
258 #define FCOE_CTLR_MODE_MAX_NAMELEN 50
259 
260 static ssize_t show_ctlr_mode(struct device *dev,
261  struct device_attribute *attr,
262  char *buf)
263 {
264  struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
265  const char *name;
266 
267  if (ctlr->f->get_fcoe_ctlr_mode)
268  ctlr->f->get_fcoe_ctlr_mode(ctlr);
269 
270  name = get_fcoe_ctlr_mode_name(ctlr->mode);
271  if (!name)
272  return -EINVAL;
274  "%s\n", name);
275 }
276 static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO,
277  show_ctlr_mode, NULL);
278 
279 static ssize_t
280 store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
281  struct device_attribute *attr,
282  const char *buf, size_t count)
283 {
284  struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
285  struct fcoe_fcf_device *fcf;
286  unsigned long val;
287  int rc;
288 
289  rc = fcoe_str_to_dev_loss(buf, &val);
290  if (rc)
291  return rc;
292 
294  mutex_lock(&ctlr->lock);
295  list_for_each_entry(fcf, &ctlr->fcfs, peers)
296  fcoe_fcf_set_dev_loss_tmo(fcf, val);
297  mutex_unlock(&ctlr->lock);
298  return count;
299 }
300 fcoe_ctlr_private_show_function(fcf_dev_loss_tmo, "%d\n", 20, );
301 static FCOE_DEVICE_ATTR(ctlr, fcf_dev_loss_tmo, S_IRUGO | S_IWUSR,
302  show_fcoe_ctlr_device_fcf_dev_loss_tmo,
303  store_private_fcoe_ctlr_fcf_dev_loss_tmo);
304 
305 /* Link Error Status Block (LESB) */
306 fcoe_ctlr_rd_attr(link_fail, "%u\n", 20);
307 fcoe_ctlr_rd_attr(vlink_fail, "%u\n", 20);
308 fcoe_ctlr_rd_attr(miss_fka, "%u\n", 20);
309 fcoe_ctlr_rd_attr(symb_err, "%u\n", 20);
310 fcoe_ctlr_rd_attr(err_block, "%u\n", 20);
311 fcoe_ctlr_rd_attr(fcs_error, "%u\n", 20);
312 
313 fcoe_fcf_private_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);
314 fcoe_fcf_private_rd_attr_cast(switch_name, "0x%llx\n", 20, unsigned long long);
317 fcoe_fcf_private_rd_attr(vfid, "%u\n", 20);
318 fcoe_fcf_private_rd_attr(mac, "%pM\n", 20);
320 fcoe_fcf_rd_attr(selected, "%u\n", 20);
321 fcoe_fcf_rd_attr(vlan_id, "%u\n", 20);
322 
324 static ssize_t
325 store_fcoe_fcf_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
326  const char *buf, size_t count)
327 {
328  struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
329  unsigned long val;
330  int rc;
331 
332  rc = fcoe_str_to_dev_loss(buf, &val);
333  if (rc)
334  return rc;
335 
336  rc = fcoe_fcf_set_dev_loss_tmo(fcf, val);
337  if (rc)
338  return rc;
339  return count;
340 }
342  show_fcoe_fcf_device_dev_loss_tmo,
343  store_fcoe_fcf_dev_loss_tmo);
344 
345 static struct attribute *fcoe_ctlr_lesb_attrs[] = {
346  &device_attr_fcoe_ctlr_link_fail.attr,
347  &device_attr_fcoe_ctlr_vlink_fail.attr,
348  &device_attr_fcoe_ctlr_miss_fka.attr,
349  &device_attr_fcoe_ctlr_symb_err.attr,
350  &device_attr_fcoe_ctlr_err_block.attr,
351  &device_attr_fcoe_ctlr_fcs_error.attr,
352  NULL,
353 };
354 
355 static struct attribute_group fcoe_ctlr_lesb_attr_group = {
356  .name = "lesb",
357  .attrs = fcoe_ctlr_lesb_attrs,
358 };
359 
360 static struct attribute *fcoe_ctlr_attrs[] = {
361  &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
362  &device_attr_fcoe_ctlr_mode.attr,
363  NULL,
364 };
365 
366 static struct attribute_group fcoe_ctlr_attr_group = {
367  .attrs = fcoe_ctlr_attrs,
368 };
369 
370 static const struct attribute_group *fcoe_ctlr_attr_groups[] = {
371  &fcoe_ctlr_attr_group,
372  &fcoe_ctlr_lesb_attr_group,
373  NULL,
374 };
375 
376 static struct attribute *fcoe_fcf_attrs[] = {
377  &device_attr_fcoe_fcf_fabric_name.attr,
378  &device_attr_fcoe_fcf_switch_name.attr,
379  &device_attr_fcoe_fcf_dev_loss_tmo.attr,
380  &device_attr_fcoe_fcf_fc_map.attr,
381  &device_attr_fcoe_fcf_vfid.attr,
382  &device_attr_fcoe_fcf_mac.attr,
383  &device_attr_fcoe_fcf_priority.attr,
384  &device_attr_fcoe_fcf_fka_period.attr,
385  &device_attr_fcoe_fcf_state.attr,
386  &device_attr_fcoe_fcf_selected.attr,
387  &device_attr_fcoe_fcf_vlan_id.attr,
388  NULL
389 };
390 
391 static struct attribute_group fcoe_fcf_attr_group = {
392  .attrs = fcoe_fcf_attrs,
393 };
394 
395 static const struct attribute_group *fcoe_fcf_attr_groups[] = {
396  &fcoe_fcf_attr_group,
397  NULL,
398 };
399 
401 
402 static int fcoe_bus_match(struct device *dev,
403  struct device_driver *drv)
404 {
405  if (dev->bus == &fcoe_bus_type)
406  return 1;
407  return 0;
408 }
409 
416 static void fcoe_ctlr_device_release(struct device *dev)
417 {
418  struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
419  kfree(ctlr);
420 }
421 
428 static void fcoe_fcf_device_release(struct device *dev)
429 {
430  struct fcoe_fcf_device *fcf = dev_to_fcf(dev);
431  kfree(fcf);
432 }
433 
435  .name = "fcoe_ctlr",
436  .groups = fcoe_ctlr_attr_groups,
437  .release = fcoe_ctlr_device_release,
438 };
439 
441  .name = "fcoe_fcf",
442  .groups = fcoe_fcf_attr_groups,
443  .release = fcoe_fcf_device_release,
444 };
445 
446 struct bus_type fcoe_bus_type = {
447  .name = "fcoe",
448  .match = &fcoe_bus_match,
449 };
450 
456 {
457  if (!fcoe_ctlr_work_q(ctlr)) {
459  "ERROR: FIP Ctlr '%d' attempted to flush work, "
460  "when no workqueue created.\n", ctlr->id);
461  dump_stack();
462  return;
463  }
464 
466 }
467 
477  struct work_struct *work)
478 {
479  if (unlikely(!fcoe_ctlr_work_q(ctlr))) {
481  "ERROR: FIP Ctlr '%d' attempted to queue work, "
482  "when no workqueue created.\n", ctlr->id);
483  dump_stack();
484 
485  return -EINVAL;
486  }
487 
488  return queue_work(fcoe_ctlr_work_q(ctlr), work);
489 }
490 
496 {
497  if (!fcoe_ctlr_devloss_work_q(ctlr)) {
499  "ERROR: FIP Ctlr '%d' attempted to flush work, "
500  "when no workqueue created.\n", ctlr->id);
501  dump_stack();
502  return;
503  }
504 
506 }
507 
518  struct delayed_work *work,
519  unsigned long delay)
520 {
521  if (unlikely(!fcoe_ctlr_devloss_work_q(ctlr))) {
523  "ERROR: FIP Ctlr '%d' attempted to queue work, "
524  "when no workqueue created.\n", ctlr->id);
525  dump_stack();
526 
527  return -EINVAL;
528  }
529 
530  return queue_delayed_work(fcoe_ctlr_devloss_work_q(ctlr), work, delay);
531 }
532 
533 static int fcoe_fcf_device_match(struct fcoe_fcf_device *new,
534  struct fcoe_fcf_device *old)
535 {
536  if (new->switch_name == old->switch_name &&
537  new->fabric_name == old->fabric_name &&
538  new->fc_map == old->fc_map &&
539  compare_ether_addr(new->mac, old->mac) == 0)
540  return 1;
541  return 0;
542 }
543 
557  int priv_size)
558 {
559  struct fcoe_ctlr_device *ctlr;
560  int error = 0;
561 
562  ctlr = kzalloc(sizeof(struct fcoe_ctlr_device) + priv_size,
563  GFP_KERNEL);
564  if (!ctlr)
565  goto out;
566 
567  ctlr->id = atomic_inc_return(&ctlr_num) - 1;
568  ctlr->f = f;
569  INIT_LIST_HEAD(&ctlr->fcfs);
570  mutex_init(&ctlr->lock);
571  ctlr->dev.parent = parent;
572  ctlr->dev.bus = &fcoe_bus_type;
573  ctlr->dev.type = &fcoe_ctlr_device_type;
574 
576 
577  snprintf(ctlr->work_q_name, sizeof(ctlr->work_q_name),
578  "ctlr_wq_%d", ctlr->id);
580  ctlr->work_q_name);
581  if (!ctlr->work_q)
582  goto out_del;
583 
585  sizeof(ctlr->devloss_work_q_name),
586  "ctlr_dl_wq_%d", ctlr->id);
588  ctlr->devloss_work_q_name);
589  if (!ctlr->devloss_work_q)
590  goto out_del_q;
591 
592  dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id);
593  error = device_register(&ctlr->dev);
594  if (error)
595  goto out_del_q2;
596 
597  return ctlr;
598 
599 out_del_q2:
601  ctlr->devloss_work_q = NULL;
602 out_del_q:
603  destroy_workqueue(ctlr->work_q);
604  ctlr->work_q = NULL;
605 out_del:
606  kfree(ctlr);
607 out:
608  return NULL;
609 }
611 
633 {
634  struct fcoe_fcf_device *fcf, *next;
635  /* Remove any attached fcfs */
636  mutex_lock(&ctlr->lock);
637  list_for_each_entry_safe(fcf, next,
638  &ctlr->fcfs, peers) {
639  list_del(&fcf->peers);
642  }
643  mutex_unlock(&ctlr->lock);
644 
646 
648  ctlr->devloss_work_q = NULL;
649  destroy_workqueue(ctlr->work_q);
650  ctlr->work_q = NULL;
651 
652  device_unregister(&ctlr->dev);
653 }
655 
663 static void fcoe_fcf_device_final_delete(struct work_struct *work)
664 {
665  struct fcoe_fcf_device *fcf =
667  struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
668 
669  /*
670  * Cancel any outstanding timers. These should really exist
671  * only when rmmod'ing the LLDD and we're asking for
672  * immediate termination of the rports
673  */
676 
677  device_unregister(&fcf->dev);
678 }
679 
687 static void fip_timeout_deleted_fcf(struct work_struct *work)
688 {
689  struct fcoe_fcf_device *fcf =
690  container_of(work, struct fcoe_fcf_device, dev_loss_work.work);
691  struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
692 
693  mutex_lock(&ctlr->lock);
694 
695  /*
696  * If the fcf is deleted or reconnected before the timer
697  * fires the devloss queue will be flushed, but the state will
698  * either be CONNECTED or DELETED. If that is the case we
699  * cancel deleting the fcf.
700  */
702  goto out;
703 
704  dev_printk(KERN_ERR, &fcf->dev,
705  "FIP fcf connection time out: removing fcf\n");
706 
707  list_del(&fcf->peers);
710 
711 out:
712  mutex_unlock(&ctlr->lock);
713 }
714 
725 {
726  struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf);
727  int timeout = fcf->dev_loss_tmo;
728 
729  if (fcf->state != FCOE_FCF_STATE_CONNECTED)
730  return;
731 
733 
734  /*
735  * FCF will only be re-connected by the LLD calling
736  * fcoe_fcf_device_add, and it should be setting up
737  * priv then.
738  */
739  fcf->priv = NULL;
740 
742  timeout * HZ);
743 }
745 
754  struct fcoe_fcf_device *new_fcf)
755 {
756  struct fcoe_fcf_device *fcf;
757  int error = 0;
758 
759  list_for_each_entry(fcf, &ctlr->fcfs, peers) {
760  if (fcoe_fcf_device_match(new_fcf, fcf)) {
761  if (fcf->state == FCOE_FCF_STATE_CONNECTED)
762  return fcf;
763 
765 
768 
769  return fcf;
770  }
771  }
772 
773  fcf = kzalloc(sizeof(struct fcoe_fcf_device), GFP_ATOMIC);
774  if (unlikely(!fcf))
775  goto out;
776 
777  INIT_WORK(&fcf->delete_work, fcoe_fcf_device_final_delete);
778  INIT_DELAYED_WORK(&fcf->dev_loss_work, fip_timeout_deleted_fcf);
779 
780  fcf->dev.parent = &ctlr->dev;
781  fcf->dev.bus = &fcoe_bus_type;
782  fcf->dev.type = &fcoe_fcf_device_type;
783  fcf->id = atomic_inc_return(&fcf_num) - 1;
785 
786  fcf->dev_loss_tmo = ctlr->fcf_dev_loss_tmo;
787 
788  dev_set_name(&fcf->dev, "fcf_%d", fcf->id);
789 
790  fcf->fabric_name = new_fcf->fabric_name;
791  fcf->switch_name = new_fcf->switch_name;
792  fcf->fc_map = new_fcf->fc_map;
793  fcf->vfid = new_fcf->vfid;
794  memcpy(fcf->mac, new_fcf->mac, ETH_ALEN);
795  fcf->priority = new_fcf->priority;
796  fcf->fka_period = new_fcf->fka_period;
797  fcf->selected = new_fcf->selected;
798 
799  error = device_register(&fcf->dev);
800  if (error)
801  goto out_del;
802 
804  list_add_tail(&fcf->peers, &ctlr->fcfs);
805 
806  return fcf;
807 
808 out_del:
809  kfree(fcf);
810 out:
811  return NULL;
812 }
814 
816 {
817  int error;
818 
819  atomic_set(&ctlr_num, 0);
820  atomic_set(&fcf_num, 0);
821 
822  error = bus_register(&fcoe_bus_type);
823  if (error)
824  return error;
825 
826  return 0;
827 }
828 
830 {
831  bus_unregister(&fcoe_bus_type);
832 }