diff options
author | Robert Love <robert.w.love@intel.com> | 2012-05-22 22:06:26 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-05-23 04:43:13 -0400 |
commit | 8d55e507d24c6db7eb012c379c62912e642eb75e (patch) | |
tree | 5118b221cf9eab4ad040c9e1bcabb794e57dc906 /drivers/scsi/fcoe | |
parent | 9a74e884ee71dbf3d0967b0321d7b4529a04826c (diff) |
[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>
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 71 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe_ctlr.c | 159 |
2 files changed, 209 insertions, 21 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 4bb42e19d537..fe30b1b65e1d 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | #include <scsi/fc/fc_encaps.h> | 42 | #include <scsi/fc/fc_encaps.h> |
43 | #include <scsi/fc/fc_fip.h> | 43 | #include <scsi/fc/fc_fip.h> |
44 | #include <scsi/fc/fc_fcoe.h> | ||
44 | 45 | ||
45 | #include <scsi/libfc.h> | 46 | #include <scsi/libfc.h> |
46 | #include <scsi/fc_frame.h> | 47 | #include <scsi/fc_frame.h> |
@@ -150,6 +151,21 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled); | |||
150 | static int fcoe_vport_disable(struct fc_vport *, bool disable); | 151 | static int fcoe_vport_disable(struct fc_vport *, bool disable); |
151 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); | 152 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); |
152 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); | 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 *); | ||
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 | }; | ||
153 | 169 | ||
154 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | 170 | static struct libfc_function_template fcoe_libfc_fcn_templ = { |
155 | .frame_send = fcoe_xmit, | 171 | .frame_send = fcoe_xmit, |
@@ -366,6 +382,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, | |||
366 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | 382 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, |
367 | enum fip_state fip_mode) | 383 | enum fip_state fip_mode) |
368 | { | 384 | { |
385 | struct fcoe_ctlr_device *ctlr_dev; | ||
369 | struct fcoe_ctlr *ctlr; | 386 | struct fcoe_ctlr *ctlr; |
370 | struct fcoe_interface *fcoe; | 387 | struct fcoe_interface *fcoe; |
371 | int size; | 388 | int size; |
@@ -379,14 +396,17 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | |||
379 | } | 396 | } |
380 | 397 | ||
381 | size = sizeof(struct fcoe_ctlr) + sizeof(struct fcoe_interface); | 398 | size = sizeof(struct fcoe_ctlr) + sizeof(struct fcoe_interface); |
382 | ctlr = kzalloc(size, GFP_KERNEL); | 399 | ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &fcoe_sysfs_templ, |
383 | fcoe = fcoe_ctlr_priv(ctlr); | 400 | size); |
384 | if (!fcoe) { | 401 | if (!ctlr_dev) { |
385 | FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); | 402 | FCOE_DBG("Failed to add fcoe_ctlr_device\n"); |
386 | fcoe = ERR_PTR(-ENOMEM); | 403 | fcoe = ERR_PTR(-ENOMEM); |
387 | goto out_putmod; | 404 | goto out_putmod; |
388 | } | 405 | } |
389 | 406 | ||
407 | ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||
408 | fcoe = fcoe_ctlr_priv(ctlr); | ||
409 | |||
390 | dev_hold(netdev); | 410 | dev_hold(netdev); |
391 | 411 | ||
392 | /* | 412 | /* |
@@ -400,6 +420,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | |||
400 | err = fcoe_interface_setup(fcoe, netdev); | 420 | err = fcoe_interface_setup(fcoe, netdev); |
401 | if (err) { | 421 | if (err) { |
402 | fcoe_ctlr_destroy(ctlr); | 422 | fcoe_ctlr_destroy(ctlr); |
423 | fcoe_ctlr_device_delete(ctlr_dev); | ||
403 | dev_put(netdev); | 424 | dev_put(netdev); |
404 | fcoe = ERR_PTR(err); | 425 | fcoe = ERR_PTR(err); |
405 | goto out_putmod; | 426 | goto out_putmod; |
@@ -466,6 +487,7 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | |||
466 | { | 487 | { |
467 | struct net_device *netdev = fcoe->netdev; | 488 | struct net_device *netdev = fcoe->netdev; |
468 | struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); | 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 | rtnl_lock(); | 492 | rtnl_lock(); |
471 | if (!fcoe->removed) | 493 | if (!fcoe->removed) |
@@ -476,7 +498,7 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | |||
476 | /* tear-down the FCoE controller */ | 498 | /* tear-down the FCoE controller */ |
477 | fcoe_ctlr_destroy(fip); | 499 | fcoe_ctlr_destroy(fip); |
478 | scsi_host_put(fip->lp->host); | 500 | scsi_host_put(fip->lp->host); |
479 | kfree(fip); | 501 | fcoe_ctlr_device_delete(ctlr_dev); |
480 | dev_put(netdev); | 502 | dev_put(netdev); |
481 | module_put(THIS_MODULE); | 503 | module_put(THIS_MODULE); |
482 | } | 504 | } |
@@ -2196,6 +2218,7 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) | |||
2196 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | 2218 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) |
2197 | { | 2219 | { |
2198 | int rc = 0; | 2220 | int rc = 0; |
2221 | struct fcoe_ctlr_device *ctlr_dev; | ||
2199 | struct fcoe_ctlr *ctlr; | 2222 | struct fcoe_ctlr *ctlr; |
2200 | struct fcoe_interface *fcoe; | 2223 | struct fcoe_interface *fcoe; |
2201 | struct fc_lport *lport; | 2224 | struct fc_lport *lport; |
@@ -2216,8 +2239,8 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2216 | } | 2239 | } |
2217 | 2240 | ||
2218 | ctlr = fcoe_to_ctlr(fcoe); | 2241 | ctlr = fcoe_to_ctlr(fcoe); |
2219 | 2242 | ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr); | |
2220 | lport = fcoe_if_create(fcoe, &netdev->dev, 0); | 2243 | lport = fcoe_if_create(fcoe, &ctlr_dev->dev, 0); |
2221 | if (IS_ERR(lport)) { | 2244 | if (IS_ERR(lport)) { |
2222 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", | 2245 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", |
2223 | netdev->name); | 2246 | netdev->name); |
@@ -2768,6 +2791,40 @@ static void fcoe_get_lesb(struct fc_lport *lport, | |||
2768 | __fcoe_get_lesb(lport, fc_lesb, netdev); | 2791 | __fcoe_get_lesb(lport, fc_lesb, netdev); |
2769 | } | 2792 | } |
2770 | 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); | ||
2826 | } | ||
2827 | |||
2771 | /** | 2828 | /** |
2772 | * fcoe_set_port_id() - Callback from libfc when Port_ID is set. | 2829 | * fcoe_set_port_id() - Callback from libfc when Port_ID is set. |
2773 | * @lport: the local port | 2830 | * @lport: the local port |
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 5a4c7250aa77..d68d57241ee6 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
@@ -160,6 +160,76 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) | |||
160 | } | 160 | } |
161 | EXPORT_SYMBOL(fcoe_ctlr_init); | 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 | * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller | 234 | * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller |
165 | * @fip: The FCoE controller whose FCFs are to be reset | 235 | * @fip: The FCoE controller whose FCFs are to be reset |
@@ -173,10 +243,10 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) | |||
173 | 243 | ||
174 | fip->sel_fcf = NULL; | 244 | fip->sel_fcf = NULL; |
175 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { | 245 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { |
176 | list_del(&fcf->list); | 246 | fcoe_sysfs_fcf_del(fcf); |
177 | kfree(fcf); | ||
178 | } | 247 | } |
179 | fip->fcf_count = 0; | 248 | WARN_ON(fip->fcf_count); |
249 | |||
180 | fip->sel_time = 0; | 250 | fip->sel_time = 0; |
181 | } | 251 | } |
182 | 252 | ||
@@ -717,8 +787,11 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
717 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); | 787 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); |
718 | unsigned long deadline; | 788 | unsigned long deadline; |
719 | unsigned long sel_time = 0; | 789 | unsigned long sel_time = 0; |
790 | struct list_head del_list; | ||
720 | struct fcoe_dev_stats *stats; | 791 | struct fcoe_dev_stats *stats; |
721 | 792 | ||
793 | INIT_LIST_HEAD(&del_list); | ||
794 | |||
722 | stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu()); | 795 | stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu()); |
723 | 796 | ||
724 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { | 797 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { |
@@ -739,10 +812,13 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
739 | if (time_after_eq(jiffies, deadline)) { | 812 | if (time_after_eq(jiffies, deadline)) { |
740 | if (fip->sel_fcf == fcf) | 813 | if (fip->sel_fcf == fcf) |
741 | fip->sel_fcf = NULL; | 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 | list_del(&fcf->list); | 820 | list_del(&fcf->list); |
743 | WARN_ON(!fip->fcf_count); | 821 | list_add(&fcf->list, &del_list); |
744 | fip->fcf_count--; | ||
745 | kfree(fcf); | ||
746 | stats->VLinkFailureCount++; | 822 | stats->VLinkFailureCount++; |
747 | } else { | 823 | } else { |
748 | if (time_after(next_timer, deadline)) | 824 | if (time_after(next_timer, deadline)) |
@@ -753,6 +829,12 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
753 | } | 829 | } |
754 | } | 830 | } |
755 | put_cpu(); | 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 | if (sel_time && !fip->sel_fcf && !fip->sel_time) { | 838 | if (sel_time && !fip->sel_fcf && !fip->sel_time) { |
757 | sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); | 839 | sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); |
758 | fip->sel_time = sel_time; | 840 | fip->sel_time = sel_time; |
@@ -903,23 +985,23 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
903 | { | 985 | { |
904 | struct fcoe_fcf *fcf; | 986 | struct fcoe_fcf *fcf; |
905 | struct fcoe_fcf new; | 987 | struct fcoe_fcf new; |
906 | struct fcoe_fcf *found; | ||
907 | unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV); | 988 | unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV); |
908 | int first = 0; | 989 | int first = 0; |
909 | int mtu_valid; | 990 | int mtu_valid; |
991 | int found = 0; | ||
992 | int rc = 0; | ||
910 | 993 | ||
911 | if (fcoe_ctlr_parse_adv(fip, skb, &new)) | 994 | if (fcoe_ctlr_parse_adv(fip, skb, &new)) |
912 | return; | 995 | return; |
913 | 996 | ||
914 | mutex_lock(&fip->ctlr_mutex); | 997 | mutex_lock(&fip->ctlr_mutex); |
915 | first = list_empty(&fip->fcfs); | 998 | first = list_empty(&fip->fcfs); |
916 | found = NULL; | ||
917 | list_for_each_entry(fcf, &fip->fcfs, list) { | 999 | list_for_each_entry(fcf, &fip->fcfs, list) { |
918 | if (fcf->switch_name == new.switch_name && | 1000 | if (fcf->switch_name == new.switch_name && |
919 | fcf->fabric_name == new.fabric_name && | 1001 | fcf->fabric_name == new.fabric_name && |
920 | fcf->fc_map == new.fc_map && | 1002 | fcf->fc_map == new.fc_map && |
921 | compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { | 1003 | compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { |
922 | found = fcf; | 1004 | found = 1; |
923 | break; | 1005 | break; |
924 | } | 1006 | } |
925 | } | 1007 | } |
@@ -931,9 +1013,16 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
931 | if (!fcf) | 1013 | if (!fcf) |
932 | goto out; | 1014 | goto out; |
933 | 1015 | ||
934 | fip->fcf_count++; | ||
935 | memcpy(fcf, &new, sizeof(new)); | 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 | } else { | 1026 | } else { |
938 | /* | 1027 | /* |
939 | * Update the FCF's keep-alive descriptor flags. | 1028 | * Update the FCF's keep-alive descriptor flags. |
@@ -954,6 +1043,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
954 | fcf->fka_period = new.fka_period; | 1043 | fcf->fka_period = new.fka_period; |
955 | memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN); | 1044 | memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN); |
956 | } | 1045 | } |
1046 | |||
957 | mtu_valid = fcoe_ctlr_mtu_valid(fcf); | 1047 | mtu_valid = fcoe_ctlr_mtu_valid(fcf); |
958 | fcf->time = jiffies; | 1048 | fcf->time = jiffies; |
959 | if (!found) | 1049 | if (!found) |
@@ -996,6 +1086,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
996 | time_before(fip->sel_time, fip->timer.expires)) | 1086 | time_before(fip->sel_time, fip->timer.expires)) |
997 | mod_timer(&fip->timer, fip->sel_time); | 1087 | mod_timer(&fip->timer, fip->sel_time); |
998 | } | 1088 | } |
1089 | |||
999 | out: | 1090 | out: |
1000 | mutex_unlock(&fip->ctlr_mutex); | 1091 | mutex_unlock(&fip->ctlr_mutex); |
1001 | } | 1092 | } |
@@ -2718,9 +2809,9 @@ unlock: | |||
2718 | 2809 | ||
2719 | /** | 2810 | /** |
2720 | * fcoe_libfc_config() - Sets up libfc related properties for local port | 2811 | * fcoe_libfc_config() - Sets up libfc related properties for local port |
2721 | * @lp: The local port to configure libfc for | 2812 | * @lport: The local port to configure libfc for |
2722 | * @fip: The FCoE controller in use by the local port | 2813 | * @fip: The FCoE controller in use by the local port |
2723 | * @tt: The libfc function template | 2814 | * @tt: The libfc function template |
2724 | * @init_fcp: If non-zero, the FCP portion of libfc should be initialized | 2815 | * @init_fcp: If non-zero, the FCP portion of libfc should be initialized |
2725 | * | 2816 | * |
2726 | * Returns : 0 for success | 2817 | * Returns : 0 for success |
@@ -2753,3 +2844,43 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip, | |||
2753 | return 0; | 2844 | return 0; |
2754 | } | 2845 | } |
2755 | EXPORT_SYMBOL_GPL(fcoe_libfc_config); | 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); | ||