Commit 8d55e507d24c6db7eb012c379c62912e642eb75e

Authored by Robert Love
Committed by James Bottomley
1 parent 9a74e884ee

[SCSI] fcoe, bnx2fc, libfcoe: SW FCoE and bnx2fc use FCoE Syfs

This patch has the SW FCoE driver and the bnx2fc
driver make use of the new fcoe_sysfs API added
earlier in this patch series.

After this patch a fcoe_ctlr_device is allocated with
private data in this order.

+------------------+   +------------------+
| fcoe_ctlr_device |   | fcoe_ctlr_device |
+------------------+   +------------------+
| fcoe_ctlr        |   | fcoe_ctlr        |
+------------------+   +------------------+
| fcoe_interface   |   | bnx2fc_interface |
+------------------+   +------------------+

libfcoe also takes part in this new model since it
discovers and manages fcoe_fcf instances. The memory
allocation is different for FCFs. I didn't want to
impact libfcoe's fcoe_fcf processing, so this patch
creates fcoe_fcf_device instances for each discovered
fcoe_fcf. The two are paired using a (void * priv)
member of the fcoe_ctlr_device. This allows libfcoe
to continue maintaining its list of fcoe_fcf instances
and simply attaches and detaches them from existing
or new fcoe_fcf_device instances.

Signed-off-by: Robert Love <robert.w.love@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

Showing 4 changed files with 285 additions and 25 deletions Side-by-side Diff

drivers/scsi/bnx2fc/bnx2fc_fcoe.c
... ... @@ -54,6 +54,7 @@
54 54 static struct libfc_function_template bnx2fc_libfc_fcn_templ;
55 55 static struct scsi_host_template bnx2fc_shost_template;
56 56 static struct fc_function_template bnx2fc_transport_function;
  57 +static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ;
57 58 static struct fc_function_template bnx2fc_vport_xport_function;
58 59 static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode);
59 60 static void __bnx2fc_destroy(struct bnx2fc_interface *interface);
... ... @@ -88,6 +89,7 @@
88 89 static void bnx2fc_stop(struct bnx2fc_interface *interface);
89 90 static int __init bnx2fc_mod_init(void);
90 91 static void __exit bnx2fc_mod_exit(void);
  92 +static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev);
91 93  
92 94 unsigned int bnx2fc_debug_level;
93 95 module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR);
... ... @@ -118,6 +120,41 @@
118 120 __fcoe_get_lesb(lport, fc_lesb, netdev);
119 121 }
120 122  
  123 +static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
  124 +{
  125 + struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
  126 + struct net_device *netdev = bnx2fc_netdev(fip->lp);
  127 + struct fcoe_fc_els_lesb *fcoe_lesb;
  128 + struct fc_els_lesb fc_lesb;
  129 +
  130 + __fcoe_get_lesb(fip->lp, &fc_lesb, netdev);
  131 + fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb);
  132 +
  133 + ctlr_dev->lesb.lesb_link_fail =
  134 + ntohl(fcoe_lesb->lesb_link_fail);
  135 + ctlr_dev->lesb.lesb_vlink_fail =
  136 + ntohl(fcoe_lesb->lesb_vlink_fail);
  137 + ctlr_dev->lesb.lesb_miss_fka =
  138 + ntohl(fcoe_lesb->lesb_miss_fka);
  139 + ctlr_dev->lesb.lesb_symb_err =
  140 + ntohl(fcoe_lesb->lesb_symb_err);
  141 + ctlr_dev->lesb.lesb_err_block =
  142 + ntohl(fcoe_lesb->lesb_err_block);
  143 + ctlr_dev->lesb.lesb_fcs_error =
  144 + ntohl(fcoe_lesb->lesb_fcs_error);
  145 +}
  146 +EXPORT_SYMBOL(bnx2fc_ctlr_get_lesb);
  147 +
  148 +static void bnx2fc_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev)
  149 +{
  150 + struct fcoe_ctlr_device *ctlr_dev =
  151 + fcoe_fcf_dev_to_ctlr_dev(fcf_dev);
  152 + struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
  153 + struct bnx2fc_interface *fcoe = fcoe_ctlr_priv(ctlr);
  154 +
  155 + fcf_dev->vlan_id = fcoe->vlan_id;
  156 +}
  157 +
121 158 static void bnx2fc_clean_rx_queue(struct fc_lport *lp)
122 159 {
123 160 struct fcoe_percpu_s *bg;
... ... @@ -1235,6 +1272,7 @@
1235 1272  
1236 1273 static void bnx2fc_interface_release(struct kref *kref)
1237 1274 {
  1275 + struct fcoe_ctlr_device *ctlr_dev;
1238 1276 struct bnx2fc_interface *interface;
1239 1277 struct fcoe_ctlr *ctlr;
1240 1278 struct net_device *netdev;
1241 1279  
... ... @@ -1243,13 +1281,14 @@
1243 1281 BNX2FC_MISC_DBG("Interface is being released\n");
1244 1282  
1245 1283 ctlr = bnx2fc_to_ctlr(interface);
  1284 + ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr);
1246 1285 netdev = interface->netdev;
1247 1286  
1248 1287 /* tear-down FIP controller */
1249 1288 if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags))
1250 1289 fcoe_ctlr_destroy(ctlr);
1251 1290  
1252   - kfree(ctlr);
  1291 + fcoe_ctlr_device_delete(ctlr_dev);
1253 1292  
1254 1293 dev_put(netdev);
1255 1294 module_put(THIS_MODULE);
1256 1295  
1257 1296  
... ... @@ -1342,17 +1381,20 @@
1342 1381 struct net_device *netdev,
1343 1382 enum fip_state fip_mode)
1344 1383 {
  1384 + struct fcoe_ctlr_device *ctlr_dev;
1345 1385 struct bnx2fc_interface *interface;
1346 1386 struct fcoe_ctlr *ctlr;
1347 1387 int size;
1348 1388 int rc = 0;
1349 1389  
1350 1390 size = (sizeof(*interface) + sizeof(struct fcoe_ctlr));
1351   - ctlr = kzalloc(size, GFP_KERNEL);
1352   - if (!ctlr) {
  1391 + ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &bnx2fc_fcoe_sysfs_templ,
  1392 + size);
  1393 + if (!ctlr_dev) {
1353 1394 printk(KERN_ERR PFX "Unable to allocate interface structure\n");
1354 1395 return NULL;
1355 1396 }
  1397 + ctlr = fcoe_ctlr_device_priv(ctlr_dev);
1356 1398 interface = fcoe_ctlr_priv(ctlr);
1357 1399 dev_hold(netdev);
1358 1400 kref_init(&interface->kref);
... ... @@ -1372,7 +1414,7 @@
1372 1414  
1373 1415 fcoe_ctlr_destroy(ctlr);
1374 1416 dev_put(netdev);
1375   - kfree(ctlr);
  1417 + fcoe_ctlr_device_delete(ctlr_dev);
1376 1418 return NULL;
1377 1419 }
1378 1420  
... ... @@ -2470,6 +2512,19 @@
2470 2512  
2471 2513 module_init(bnx2fc_mod_init);
2472 2514 module_exit(bnx2fc_mod_exit);
  2515 +
  2516 +static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ = {
  2517 + .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode,
  2518 + .get_fcoe_ctlr_link_fail = bnx2fc_ctlr_get_lesb,
  2519 + .get_fcoe_ctlr_vlink_fail = bnx2fc_ctlr_get_lesb,
  2520 + .get_fcoe_ctlr_miss_fka = bnx2fc_ctlr_get_lesb,
  2521 + .get_fcoe_ctlr_symb_err = bnx2fc_ctlr_get_lesb,
  2522 + .get_fcoe_ctlr_err_block = bnx2fc_ctlr_get_lesb,
  2523 + .get_fcoe_ctlr_fcs_error = bnx2fc_ctlr_get_lesb,
  2524 +
  2525 + .get_fcoe_fcf_selected = fcoe_fcf_get_selected,
  2526 + .get_fcoe_fcf_vlan_id = bnx2fc_fcf_get_vlan_id,
  2527 +};
2473 2528  
2474 2529 static struct fc_function_template bnx2fc_transport_function = {
2475 2530 .show_host_node_name = 1,
drivers/scsi/fcoe/fcoe.c
... ... @@ -41,6 +41,7 @@
41 41  
42 42 #include <scsi/fc/fc_encaps.h>
43 43 #include <scsi/fc/fc_fip.h>
  44 +#include <scsi/fc/fc_fcoe.h>
44 45  
45 46 #include <scsi/libfc.h>
46 47 #include <scsi/fc_frame.h>
47 48  
... ... @@ -150,7 +151,22 @@
150 151 static int fcoe_vport_disable(struct fc_vport *, bool disable);
151 152 static void fcoe_set_vport_symbolic_name(struct fc_vport *);
152 153 static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
  154 +static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *);
  155 +static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *);
153 156  
  157 +static struct fcoe_sysfs_function_template fcoe_sysfs_templ = {
  158 + .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode,
  159 + .get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb,
  160 + .get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb,
  161 + .get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb,
  162 + .get_fcoe_ctlr_symb_err = fcoe_ctlr_get_lesb,
  163 + .get_fcoe_ctlr_err_block = fcoe_ctlr_get_lesb,
  164 + .get_fcoe_ctlr_fcs_error = fcoe_ctlr_get_lesb,
  165 +
  166 + .get_fcoe_fcf_selected = fcoe_fcf_get_selected,
  167 + .get_fcoe_fcf_vlan_id = fcoe_fcf_get_vlan_id,
  168 +};
  169 +
154 170 static struct libfc_function_template fcoe_libfc_fcn_templ = {
155 171 .frame_send = fcoe_xmit,
156 172 .ddp_setup = fcoe_ddp_setup,
... ... @@ -366,6 +382,7 @@
366 382 static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
367 383 enum fip_state fip_mode)
368 384 {
  385 + struct fcoe_ctlr_device *ctlr_dev;
369 386 struct fcoe_ctlr *ctlr;
370 387 struct fcoe_interface *fcoe;
371 388 int size;
372 389  
... ... @@ -379,14 +396,17 @@
379 396 }
380 397  
381 398 size = sizeof(struct fcoe_ctlr) + sizeof(struct fcoe_interface);
382   - ctlr = kzalloc(size, GFP_KERNEL);
383   - fcoe = fcoe_ctlr_priv(ctlr);
384   - if (!fcoe) {
385   - FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n");
  399 + ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &fcoe_sysfs_templ,
  400 + size);
  401 + if (!ctlr_dev) {
  402 + FCOE_DBG("Failed to add fcoe_ctlr_device\n");
386 403 fcoe = ERR_PTR(-ENOMEM);
387 404 goto out_putmod;
388 405 }
389 406  
  407 + ctlr = fcoe_ctlr_device_priv(ctlr_dev);
  408 + fcoe = fcoe_ctlr_priv(ctlr);
  409 +
390 410 dev_hold(netdev);
391 411  
392 412 /*
... ... @@ -400,6 +420,7 @@
400 420 err = fcoe_interface_setup(fcoe, netdev);
401 421 if (err) {
402 422 fcoe_ctlr_destroy(ctlr);
  423 + fcoe_ctlr_device_delete(ctlr_dev);
403 424 dev_put(netdev);
404 425 fcoe = ERR_PTR(err);
405 426 goto out_putmod;
... ... @@ -466,6 +487,7 @@
466 487 {
467 488 struct net_device *netdev = fcoe->netdev;
468 489 struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
  490 + struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
469 491  
470 492 rtnl_lock();
471 493 if (!fcoe->removed)
... ... @@ -476,7 +498,7 @@
476 498 /* tear-down the FCoE controller */
477 499 fcoe_ctlr_destroy(fip);
478 500 scsi_host_put(fip->lp->host);
479   - kfree(fip);
  501 + fcoe_ctlr_device_delete(ctlr_dev);
480 502 dev_put(netdev);
481 503 module_put(THIS_MODULE);
482 504 }
... ... @@ -2196,6 +2218,7 @@
2196 2218 static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
2197 2219 {
2198 2220 int rc = 0;
  2221 + struct fcoe_ctlr_device *ctlr_dev;
2199 2222 struct fcoe_ctlr *ctlr;
2200 2223 struct fcoe_interface *fcoe;
2201 2224 struct fc_lport *lport;
... ... @@ -2216,8 +2239,8 @@
2216 2239 }
2217 2240  
2218 2241 ctlr = fcoe_to_ctlr(fcoe);
2219   -
2220   - lport = fcoe_if_create(fcoe, &netdev->dev, 0);
  2242 + ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr);
  2243 + lport = fcoe_if_create(fcoe, &ctlr_dev->dev, 0);
2221 2244 if (IS_ERR(lport)) {
2222 2245 printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
2223 2246 netdev->name);
... ... @@ -2766,6 +2789,40 @@
2766 2789 struct net_device *netdev = fcoe_netdev(lport);
2767 2790  
2768 2791 __fcoe_get_lesb(lport, fc_lesb, netdev);
  2792 +}
  2793 +
  2794 +static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
  2795 +{
  2796 + struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
  2797 + struct net_device *netdev = fcoe_netdev(fip->lp);
  2798 + struct fcoe_fc_els_lesb *fcoe_lesb;
  2799 + struct fc_els_lesb fc_lesb;
  2800 +
  2801 + __fcoe_get_lesb(fip->lp, &fc_lesb, netdev);
  2802 + fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb);
  2803 +
  2804 + ctlr_dev->lesb.lesb_link_fail =
  2805 + ntohl(fcoe_lesb->lesb_link_fail);
  2806 + ctlr_dev->lesb.lesb_vlink_fail =
  2807 + ntohl(fcoe_lesb->lesb_vlink_fail);
  2808 + ctlr_dev->lesb.lesb_miss_fka =
  2809 + ntohl(fcoe_lesb->lesb_miss_fka);
  2810 + ctlr_dev->lesb.lesb_symb_err =
  2811 + ntohl(fcoe_lesb->lesb_symb_err);
  2812 + ctlr_dev->lesb.lesb_err_block =
  2813 + ntohl(fcoe_lesb->lesb_err_block);
  2814 + ctlr_dev->lesb.lesb_fcs_error =
  2815 + ntohl(fcoe_lesb->lesb_fcs_error);
  2816 +}
  2817 +
  2818 +static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev)
  2819 +{
  2820 + struct fcoe_ctlr_device *ctlr_dev =
  2821 + fcoe_fcf_dev_to_ctlr_dev(fcf_dev);
  2822 + struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
  2823 + struct fcoe_interface *fcoe = fcoe_ctlr_priv(ctlr);
  2824 +
  2825 + fcf_dev->vlan_id = vlan_dev_vlan_id(fcoe->netdev);
2769 2826 }
2770 2827  
2771 2828 /**
drivers/scsi/fcoe/fcoe_ctlr.c
... ... @@ -160,6 +160,76 @@
160 160 }
161 161 EXPORT_SYMBOL(fcoe_ctlr_init);
162 162  
  163 +static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new)
  164 +{
  165 + struct fcoe_ctlr *fip = new->fip;
  166 + struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
  167 + struct fcoe_fcf_device temp, *fcf_dev;
  168 + int rc = 0;
  169 +
  170 + LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n",
  171 + new->fabric_name, new->fcf_mac);
  172 +
  173 + mutex_lock(&ctlr_dev->lock);
  174 +
  175 + temp.fabric_name = new->fabric_name;
  176 + temp.switch_name = new->switch_name;
  177 + temp.fc_map = new->fc_map;
  178 + temp.vfid = new->vfid;
  179 + memcpy(temp.mac, new->fcf_mac, ETH_ALEN);
  180 + temp.priority = new->pri;
  181 + temp.fka_period = new->fka_period;
  182 + temp.selected = 0; /* default to unselected */
  183 +
  184 + fcf_dev = fcoe_fcf_device_add(ctlr_dev, &temp);
  185 + if (unlikely(!fcf_dev)) {
  186 + rc = -ENOMEM;
  187 + goto out;
  188 + }
  189 +
  190 + /*
  191 + * The fcoe_sysfs layer can return a CONNECTED fcf that
  192 + * has a priv (fcf was never deleted) or a CONNECTED fcf
  193 + * that doesn't have a priv (fcf was deleted). However,
  194 + * libfcoe will always delete FCFs before trying to add
  195 + * them. This is ensured because both recv_adv and
  196 + * age_fcfs are protected by the the fcoe_ctlr's mutex.
  197 + * This means that we should never get a FCF with a
  198 + * non-NULL priv pointer.
  199 + */
  200 + BUG_ON(fcf_dev->priv);
  201 +
  202 + fcf_dev->priv = new;
  203 + new->fcf_dev = fcf_dev;
  204 +
  205 + list_add(&new->list, &fip->fcfs);
  206 + fip->fcf_count++;
  207 +
  208 +out:
  209 + mutex_unlock(&ctlr_dev->lock);
  210 + return rc;
  211 +}
  212 +
  213 +static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new)
  214 +{
  215 + struct fcoe_ctlr *fip = new->fip;
  216 + struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
  217 + struct fcoe_fcf_device *fcf_dev;
  218 +
  219 + list_del(&new->list);
  220 + fip->fcf_count--;
  221 +
  222 + mutex_lock(&ctlr_dev->lock);
  223 +
  224 + fcf_dev = fcoe_fcf_to_fcf_dev(new);
  225 + WARN_ON(!fcf_dev);
  226 + new->fcf_dev = NULL;
  227 + fcoe_fcf_device_delete(fcf_dev);
  228 + kfree(new);
  229 +
  230 + mutex_unlock(&ctlr_dev->lock);
  231 +}
  232 +
163 233 /**
164 234 * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller
165 235 * @fip: The FCoE controller whose FCFs are to be reset
166 236  
... ... @@ -173,10 +243,10 @@
173 243  
174 244 fip->sel_fcf = NULL;
175 245 list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
176   - list_del(&fcf->list);
177   - kfree(fcf);
  246 + fcoe_sysfs_fcf_del(fcf);
178 247 }
179   - fip->fcf_count = 0;
  248 + WARN_ON(fip->fcf_count);
  249 +
180 250 fip->sel_time = 0;
181 251 }
182 252  
183 253  
... ... @@ -717,8 +787,11 @@
717 787 unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
718 788 unsigned long deadline;
719 789 unsigned long sel_time = 0;
  790 + struct list_head del_list;
720 791 struct fcoe_dev_stats *stats;
721 792  
  793 + INIT_LIST_HEAD(&del_list);
  794 +
722 795 stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu());
723 796  
724 797 list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
725 798  
... ... @@ -739,10 +812,13 @@
739 812 if (time_after_eq(jiffies, deadline)) {
740 813 if (fip->sel_fcf == fcf)
741 814 fip->sel_fcf = NULL;
  815 + /*
  816 + * Move to delete list so we can call
  817 + * fcoe_sysfs_fcf_del (which can sleep)
  818 + * after the put_cpu().
  819 + */
742 820 list_del(&fcf->list);
743   - WARN_ON(!fip->fcf_count);
744   - fip->fcf_count--;
745   - kfree(fcf);
  821 + list_add(&fcf->list, &del_list);
746 822 stats->VLinkFailureCount++;
747 823 } else {
748 824 if (time_after(next_timer, deadline))
... ... @@ -753,6 +829,12 @@
753 829 }
754 830 }
755 831 put_cpu();
  832 +
  833 + list_for_each_entry_safe(fcf, next, &del_list, list) {
  834 + /* Removes fcf from current list */
  835 + fcoe_sysfs_fcf_del(fcf);
  836 + }
  837 +
756 838 if (sel_time && !fip->sel_fcf && !fip->sel_time) {
757 839 sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
758 840 fip->sel_time = sel_time;
759 841  
760 842  
761 843  
... ... @@ -903,23 +985,23 @@
903 985 {
904 986 struct fcoe_fcf *fcf;
905 987 struct fcoe_fcf new;
906   - struct fcoe_fcf *found;
907 988 unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
908 989 int first = 0;
909 990 int mtu_valid;
  991 + int found = 0;
  992 + int rc = 0;
910 993  
911 994 if (fcoe_ctlr_parse_adv(fip, skb, &new))
912 995 return;
913 996  
914 997 mutex_lock(&fip->ctlr_mutex);
915 998 first = list_empty(&fip->fcfs);
916   - found = NULL;
917 999 list_for_each_entry(fcf, &fip->fcfs, list) {
918 1000 if (fcf->switch_name == new.switch_name &&
919 1001 fcf->fabric_name == new.fabric_name &&
920 1002 fcf->fc_map == new.fc_map &&
921 1003 compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) {
922   - found = fcf;
  1004 + found = 1;
923 1005 break;
924 1006 }
925 1007 }
926 1008  
... ... @@ -931,9 +1013,16 @@
931 1013 if (!fcf)
932 1014 goto out;
933 1015  
934   - fip->fcf_count++;
935 1016 memcpy(fcf, &new, sizeof(new));
936   - list_add(&fcf->list, &fip->fcfs);
  1017 + fcf->fip = fip;
  1018 + rc = fcoe_sysfs_fcf_add(fcf);
  1019 + if (rc) {
  1020 + printk(KERN_ERR "Failed to allocate sysfs instance "
  1021 + "for FCF, fab %16.16llx mac %pM\n",
  1022 + new.fabric_name, new.fcf_mac);
  1023 + kfree(fcf);
  1024 + goto out;
  1025 + }
937 1026 } else {
938 1027 /*
939 1028 * Update the FCF's keep-alive descriptor flags.
... ... @@ -954,6 +1043,7 @@
954 1043 fcf->fka_period = new.fka_period;
955 1044 memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
956 1045 }
  1046 +
957 1047 mtu_valid = fcoe_ctlr_mtu_valid(fcf);
958 1048 fcf->time = jiffies;
959 1049 if (!found)
... ... @@ -996,6 +1086,7 @@
996 1086 time_before(fip->sel_time, fip->timer.expires))
997 1087 mod_timer(&fip->timer, fip->sel_time);
998 1088 }
  1089 +
999 1090 out:
1000 1091 mutex_unlock(&fip->ctlr_mutex);
1001 1092 }
... ... @@ -2718,9 +2809,9 @@
2718 2809  
2719 2810 /**
2720 2811 * fcoe_libfc_config() - Sets up libfc related properties for local port
2721   - * @lp: The local port to configure libfc for
2722   - * @fip: The FCoE controller in use by the local port
2723   - * @tt: The libfc function template
  2812 + * @lport: The local port to configure libfc for
  2813 + * @fip: The FCoE controller in use by the local port
  2814 + * @tt: The libfc function template
2724 2815 * @init_fcp: If non-zero, the FCP portion of libfc should be initialized
2725 2816 *
2726 2817 * Returns : 0 for success
... ... @@ -2753,4 +2844,44 @@
2753 2844 return 0;
2754 2845 }
2755 2846 EXPORT_SYMBOL_GPL(fcoe_libfc_config);
  2847 +
  2848 +void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev)
  2849 +{
  2850 + struct fcoe_ctlr_device *ctlr_dev = fcoe_fcf_dev_to_ctlr_dev(fcf_dev);
  2851 + struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
  2852 + struct fcoe_fcf *fcf;
  2853 +
  2854 + mutex_lock(&fip->ctlr_mutex);
  2855 + mutex_lock(&ctlr_dev->lock);
  2856 +
  2857 + fcf = fcoe_fcf_device_priv(fcf_dev);
  2858 + if (fcf)
  2859 + fcf_dev->selected = (fcf == fip->sel_fcf) ? 1 : 0;
  2860 + else
  2861 + fcf_dev->selected = 0;
  2862 +
  2863 + mutex_unlock(&ctlr_dev->lock);
  2864 + mutex_unlock(&fip->ctlr_mutex);
  2865 +}
  2866 +EXPORT_SYMBOL(fcoe_fcf_get_selected);
  2867 +
  2868 +void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
  2869 +{
  2870 + struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
  2871 +
  2872 + mutex_lock(&ctlr->ctlr_mutex);
  2873 + switch (ctlr->mode) {
  2874 + case FIP_MODE_FABRIC:
  2875 + ctlr_dev->mode = FIP_CONN_TYPE_FABRIC;
  2876 + break;
  2877 + case FIP_MODE_VN2VN:
  2878 + ctlr_dev->mode = FIP_CONN_TYPE_VN2VN;
  2879 + break;
  2880 + default:
  2881 + ctlr_dev->mode = FIP_CONN_TYPE_UNKNOWN;
  2882 + break;
  2883 + }
  2884 + mutex_unlock(&ctlr->ctlr_mutex);
  2885 +}
  2886 +EXPORT_SYMBOL(fcoe_ctlr_get_fip_mode);
include/scsi/libfcoe.h
... ... @@ -168,9 +168,16 @@
168 168 return (void *)(ctlr + 1);
169 169 }
170 170  
  171 +#define fcoe_ctlr_to_ctlr_dev(x) \
  172 + (struct fcoe_ctlr_device *)(((struct fcoe_ctlr_device *)(x)) - 1)
  173 +
171 174 /**
172 175 * struct fcoe_fcf - Fibre-Channel Forwarder
173 176 * @list: list linkage
  177 + * @event_work: Work for FC Transport actions queue
  178 + * @event: The event to be processed
  179 + * @fip: The controller that the FCF was discovered on
  180 + * @fcf_dev: The associated fcoe_fcf_device instance
174 181 * @time: system time (jiffies) when an advertisement was last received
175 182 * @switch_name: WWN of switch from advertisement
176 183 * @fabric_name: WWN of fabric from advertisement
... ... @@ -192,6 +199,9 @@
192 199 */
193 200 struct fcoe_fcf {
194 201 struct list_head list;
  202 + struct work_struct event_work;
  203 + struct fcoe_ctlr *fip;
  204 + struct fcoe_fcf_device *fcf_dev;
195 205 unsigned long time;
196 206  
197 207 u64 switch_name;
... ... @@ -208,6 +218,9 @@
208 218 u8 fd_flags:1;
209 219 };
210 220  
  221 +#define fcoe_fcf_to_fcf_dev(x) \
  222 + ((x)->fcf_dev)
  223 +
211 224 /**
212 225 * struct fcoe_rport - VN2VN remote port
213 226 * @time: time of create or last beacon packet received from node
... ... @@ -342,6 +355,10 @@
342 355 void fcoe_queue_timer(ulong lport);
343 356 int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
344 357 struct fcoe_percpu_s *fps);
  358 +
  359 +/* FCoE Sysfs helpers */
  360 +void fcoe_fcf_get_selected(struct fcoe_fcf_device *);
  361 +void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *);
345 362  
346 363 /**
347 364 * struct netdev_list