diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-17 20:54:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-17 20:54:40 -0400 |
commit | c55d267de274d308927b60c3e740c1a826832317 (patch) | |
tree | 21b53a8c725d9f9650f60d94b349459d5b8dae10 /drivers/scsi/fcoe | |
parent | 61ef46fd45c3c62dc7c880a45dd2aa841b9af8fb (diff) | |
parent | bc898c97f7ba24def788d9f80786cf028a197122 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (170 commits)
[SCSI] scsi_dh_rdac: Add MD36xxf into device list
[SCSI] scsi_debug: add consecutive medium errors
[SCSI] libsas: fix ata list corruption issue
[SCSI] hpsa: export resettable host attribute
[SCSI] hpsa: move device attributes to avoid forward declarations
[SCSI] scsi_debug: Logical Block Provisioning (SBC3r26)
[SCSI] sd: Logical Block Provisioning update
[SCSI] Include protection operation in SCSI command trace
[SCSI] hpsa: fix incorrect PCI IDs and add two new ones (2nd try)
[SCSI] target: Fix volume size misreporting for volumes > 2TB
[SCSI] bnx2fc: Broadcom FCoE offload driver
[SCSI] fcoe: fix broken fcoe interface reset
[SCSI] fcoe: precedence bug in fcoe_filter_frames()
[SCSI] libfcoe: Remove stale fcoe-netdev entries
[SCSI] libfcoe: Move FCOE_MTU definition from fcoe.h to libfcoe.h
[SCSI] libfc: introduce __fc_fill_fc_hdr that accepts fc_hdr as an argument
[SCSI] fcoe, libfc: initialize EM anchors list and then update npiv EMs
[SCSI] Revert "[SCSI] libfc: fix exchange being deleted when the abort itself is timed out"
[SCSI] libfc: Fixing a memory leak when destroying an interface
[SCSI] megaraid_sas: Version and Changelog update
...
Fix up trivial conflicts due to whitespace differences in
drivers/scsi/libsas/{sas_ata.c,sas_scsi_host.c}
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r-- | drivers/scsi/fcoe/Makefile | 2 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 621 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe.h | 50 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe_ctlr.c (renamed from drivers/scsi/fcoe/libfcoe.c) | 40 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe_transport.c | 770 | ||||
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.h | 31 |
6 files changed, 1038 insertions, 476 deletions
diff --git a/drivers/scsi/fcoe/Makefile b/drivers/scsi/fcoe/Makefile index 950f27615c76..f6d37d0271f7 100644 --- a/drivers/scsi/fcoe/Makefile +++ b/drivers/scsi/fcoe/Makefile | |||
@@ -1,2 +1,4 @@ | |||
1 | obj-$(CONFIG_FCOE) += fcoe.o | 1 | obj-$(CONFIG_FCOE) += fcoe.o |
2 | obj-$(CONFIG_LIBFCOE) += libfcoe.o | 2 | obj-$(CONFIG_LIBFCOE) += libfcoe.o |
3 | |||
4 | libfcoe-objs := fcoe_ctlr.o fcoe_transport.o | ||
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 3becc6a20a4f..bde6ee5333eb 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
32 | #include <linux/sysfs.h> | 32 | #include <linux/sysfs.h> |
33 | #include <linux/ctype.h> | 33 | #include <linux/ctype.h> |
34 | #include <linux/workqueue.h> | ||
34 | #include <scsi/scsi_tcq.h> | 35 | #include <scsi/scsi_tcq.h> |
35 | #include <scsi/scsicam.h> | 36 | #include <scsi/scsicam.h> |
36 | #include <scsi/scsi_transport.h> | 37 | #include <scsi/scsi_transport.h> |
@@ -58,6 +59,8 @@ MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \ | |||
58 | 59 | ||
59 | DEFINE_MUTEX(fcoe_config_mutex); | 60 | DEFINE_MUTEX(fcoe_config_mutex); |
60 | 61 | ||
62 | static struct workqueue_struct *fcoe_wq; | ||
63 | |||
61 | /* fcoe_percpu_clean completion. Waiter protected by fcoe_create_mutex */ | 64 | /* fcoe_percpu_clean completion. Waiter protected by fcoe_create_mutex */ |
62 | static DECLARE_COMPLETION(fcoe_flush_completion); | 65 | static DECLARE_COMPLETION(fcoe_flush_completion); |
63 | 66 | ||
@@ -72,7 +75,6 @@ static int fcoe_xmit(struct fc_lport *, struct fc_frame *); | |||
72 | static int fcoe_rcv(struct sk_buff *, struct net_device *, | 75 | static int fcoe_rcv(struct sk_buff *, struct net_device *, |
73 | struct packet_type *, struct net_device *); | 76 | struct packet_type *, struct net_device *); |
74 | static int fcoe_percpu_receive_thread(void *); | 77 | static int fcoe_percpu_receive_thread(void *); |
75 | static void fcoe_clean_pending_queue(struct fc_lport *); | ||
76 | static void fcoe_percpu_clean(struct fc_lport *); | 78 | static void fcoe_percpu_clean(struct fc_lport *); |
77 | static int fcoe_link_speed_update(struct fc_lport *); | 79 | static int fcoe_link_speed_update(struct fc_lport *); |
78 | static int fcoe_link_ok(struct fc_lport *); | 80 | static int fcoe_link_ok(struct fc_lport *); |
@@ -80,7 +82,6 @@ static int fcoe_link_ok(struct fc_lport *); | |||
80 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); | 82 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); |
81 | static int fcoe_hostlist_add(const struct fc_lport *); | 83 | static int fcoe_hostlist_add(const struct fc_lport *); |
82 | 84 | ||
83 | static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *); | ||
84 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); | 85 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); |
85 | static void fcoe_dev_setup(void); | 86 | static void fcoe_dev_setup(void); |
86 | static void fcoe_dev_cleanup(void); | 87 | static void fcoe_dev_cleanup(void); |
@@ -101,10 +102,11 @@ static int fcoe_ddp_done(struct fc_lport *, u16); | |||
101 | 102 | ||
102 | static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *); | 103 | static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *); |
103 | 104 | ||
104 | static int fcoe_create(const char *, struct kernel_param *); | 105 | static bool fcoe_match(struct net_device *netdev); |
105 | static int fcoe_destroy(const char *, struct kernel_param *); | 106 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode); |
106 | static int fcoe_enable(const char *, struct kernel_param *); | 107 | static int fcoe_destroy(struct net_device *netdev); |
107 | static int fcoe_disable(const char *, struct kernel_param *); | 108 | static int fcoe_enable(struct net_device *netdev); |
109 | static int fcoe_disable(struct net_device *netdev); | ||
108 | 110 | ||
109 | static struct fc_seq *fcoe_elsct_send(struct fc_lport *, | 111 | static struct fc_seq *fcoe_elsct_send(struct fc_lport *, |
110 | u32 did, struct fc_frame *, | 112 | u32 did, struct fc_frame *, |
@@ -117,24 +119,6 @@ static void fcoe_recv_frame(struct sk_buff *skb); | |||
117 | 119 | ||
118 | static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *); | 120 | static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *); |
119 | 121 | ||
120 | module_param_call(create, fcoe_create, NULL, (void *)FIP_MODE_FABRIC, S_IWUSR); | ||
121 | __MODULE_PARM_TYPE(create, "string"); | ||
122 | MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface"); | ||
123 | module_param_call(create_vn2vn, fcoe_create, NULL, | ||
124 | (void *)FIP_MODE_VN2VN, S_IWUSR); | ||
125 | __MODULE_PARM_TYPE(create_vn2vn, "string"); | ||
126 | MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance " | ||
127 | "on an Ethernet interface"); | ||
128 | module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); | ||
129 | __MODULE_PARM_TYPE(destroy, "string"); | ||
130 | MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface"); | ||
131 | module_param_call(enable, fcoe_enable, NULL, NULL, S_IWUSR); | ||
132 | __MODULE_PARM_TYPE(enable, "string"); | ||
133 | MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface."); | ||
134 | module_param_call(disable, fcoe_disable, NULL, NULL, S_IWUSR); | ||
135 | __MODULE_PARM_TYPE(disable, "string"); | ||
136 | MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); | ||
137 | |||
138 | /* notification function for packets from net device */ | 122 | /* notification function for packets from net device */ |
139 | static struct notifier_block fcoe_notifier = { | 123 | static struct notifier_block fcoe_notifier = { |
140 | .notifier_call = fcoe_device_notification, | 124 | .notifier_call = fcoe_device_notification, |
@@ -145,8 +129,8 @@ static struct notifier_block fcoe_cpu_notifier = { | |||
145 | .notifier_call = fcoe_cpu_callback, | 129 | .notifier_call = fcoe_cpu_callback, |
146 | }; | 130 | }; |
147 | 131 | ||
148 | static struct scsi_transport_template *fcoe_transport_template; | 132 | static struct scsi_transport_template *fcoe_nport_scsi_transport; |
149 | static struct scsi_transport_template *fcoe_vport_transport_template; | 133 | static struct scsi_transport_template *fcoe_vport_scsi_transport; |
150 | 134 | ||
151 | static int fcoe_vport_destroy(struct fc_vport *); | 135 | static int fcoe_vport_destroy(struct fc_vport *); |
152 | static int fcoe_vport_create(struct fc_vport *, bool disabled); | 136 | static int fcoe_vport_create(struct fc_vport *, bool disabled); |
@@ -163,7 +147,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { | |||
163 | .lport_set_port_id = fcoe_set_port_id, | 147 | .lport_set_port_id = fcoe_set_port_id, |
164 | }; | 148 | }; |
165 | 149 | ||
166 | struct fc_function_template fcoe_transport_function = { | 150 | struct fc_function_template fcoe_nport_fc_functions = { |
167 | .show_host_node_name = 1, | 151 | .show_host_node_name = 1, |
168 | .show_host_port_name = 1, | 152 | .show_host_port_name = 1, |
169 | .show_host_supported_classes = 1, | 153 | .show_host_supported_classes = 1, |
@@ -203,7 +187,7 @@ struct fc_function_template fcoe_transport_function = { | |||
203 | .bsg_request = fc_lport_bsg_request, | 187 | .bsg_request = fc_lport_bsg_request, |
204 | }; | 188 | }; |
205 | 189 | ||
206 | struct fc_function_template fcoe_vport_transport_function = { | 190 | struct fc_function_template fcoe_vport_fc_functions = { |
207 | .show_host_node_name = 1, | 191 | .show_host_node_name = 1, |
208 | .show_host_port_name = 1, | 192 | .show_host_port_name = 1, |
209 | .show_host_supported_classes = 1, | 193 | .show_host_supported_classes = 1, |
@@ -354,10 +338,18 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | |||
354 | struct fcoe_interface *fcoe; | 338 | struct fcoe_interface *fcoe; |
355 | int err; | 339 | int err; |
356 | 340 | ||
341 | if (!try_module_get(THIS_MODULE)) { | ||
342 | FCOE_NETDEV_DBG(netdev, | ||
343 | "Could not get a reference to the module\n"); | ||
344 | fcoe = ERR_PTR(-EBUSY); | ||
345 | goto out; | ||
346 | } | ||
347 | |||
357 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); | 348 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); |
358 | if (!fcoe) { | 349 | if (!fcoe) { |
359 | FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); | 350 | FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); |
360 | return NULL; | 351 | fcoe = ERR_PTR(-ENOMEM); |
352 | goto out_nomod; | ||
361 | } | 353 | } |
362 | 354 | ||
363 | dev_hold(netdev); | 355 | dev_hold(netdev); |
@@ -376,9 +368,15 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | |||
376 | fcoe_ctlr_destroy(&fcoe->ctlr); | 368 | fcoe_ctlr_destroy(&fcoe->ctlr); |
377 | kfree(fcoe); | 369 | kfree(fcoe); |
378 | dev_put(netdev); | 370 | dev_put(netdev); |
379 | return NULL; | 371 | fcoe = ERR_PTR(err); |
372 | goto out_nomod; | ||
380 | } | 373 | } |
381 | 374 | ||
375 | goto out; | ||
376 | |||
377 | out_nomod: | ||
378 | module_put(THIS_MODULE); | ||
379 | out: | ||
382 | return fcoe; | 380 | return fcoe; |
383 | } | 381 | } |
384 | 382 | ||
@@ -440,6 +438,7 @@ static void fcoe_interface_release(struct kref *kref) | |||
440 | fcoe_ctlr_destroy(&fcoe->ctlr); | 438 | fcoe_ctlr_destroy(&fcoe->ctlr); |
441 | kfree(fcoe); | 439 | kfree(fcoe); |
442 | dev_put(netdev); | 440 | dev_put(netdev); |
441 | module_put(THIS_MODULE); | ||
443 | } | 442 | } |
444 | 443 | ||
445 | /** | 444 | /** |
@@ -503,7 +502,7 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
503 | static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) | 502 | static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) |
504 | { | 503 | { |
505 | struct fcoe_port *port = lport_priv(lport); | 504 | struct fcoe_port *port = lport_priv(lport); |
506 | struct fcoe_interface *fcoe = port->fcoe; | 505 | struct fcoe_interface *fcoe = port->priv; |
507 | 506 | ||
508 | rtnl_lock(); | 507 | rtnl_lock(); |
509 | if (!is_zero_ether_addr(port->data_src_addr)) | 508 | if (!is_zero_ether_addr(port->data_src_addr)) |
@@ -559,17 +558,6 @@ static int fcoe_lport_config(struct fc_lport *lport) | |||
559 | } | 558 | } |
560 | 559 | ||
561 | /** | 560 | /** |
562 | * fcoe_queue_timer() - The fcoe queue timer | ||
563 | * @lport: The local port | ||
564 | * | ||
565 | * Calls fcoe_check_wait_queue on timeout | ||
566 | */ | ||
567 | static void fcoe_queue_timer(ulong lport) | ||
568 | { | ||
569 | fcoe_check_wait_queue((struct fc_lport *)lport, NULL); | ||
570 | } | ||
571 | |||
572 | /** | ||
573 | * fcoe_get_wwn() - Get the world wide name from LLD if it supports it | 561 | * fcoe_get_wwn() - Get the world wide name from LLD if it supports it |
574 | * @netdev: the associated net device | 562 | * @netdev: the associated net device |
575 | * @wwn: the output WWN | 563 | * @wwn: the output WWN |
@@ -648,7 +636,7 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
648 | 636 | ||
649 | /* Setup lport private data to point to fcoe softc */ | 637 | /* Setup lport private data to point to fcoe softc */ |
650 | port = lport_priv(lport); | 638 | port = lport_priv(lport); |
651 | fcoe = port->fcoe; | 639 | fcoe = port->priv; |
652 | 640 | ||
653 | /* | 641 | /* |
654 | * Determine max frame size based on underlying device and optional | 642 | * Determine max frame size based on underlying device and optional |
@@ -706,9 +694,9 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev) | |||
706 | lport->host->max_cmd_len = FCOE_MAX_CMD_LEN; | 694 | lport->host->max_cmd_len = FCOE_MAX_CMD_LEN; |
707 | 695 | ||
708 | if (lport->vport) | 696 | if (lport->vport) |
709 | lport->host->transportt = fcoe_vport_transport_template; | 697 | lport->host->transportt = fcoe_vport_scsi_transport; |
710 | else | 698 | else |
711 | lport->host->transportt = fcoe_transport_template; | 699 | lport->host->transportt = fcoe_nport_scsi_transport; |
712 | 700 | ||
713 | /* add the new host to the SCSI-ml */ | 701 | /* add the new host to the SCSI-ml */ |
714 | rc = scsi_add_host(lport->host, dev); | 702 | rc = scsi_add_host(lport->host, dev); |
@@ -758,7 +746,7 @@ bool fcoe_oem_match(struct fc_frame *fp) | |||
758 | static inline int fcoe_em_config(struct fc_lport *lport) | 746 | static inline int fcoe_em_config(struct fc_lport *lport) |
759 | { | 747 | { |
760 | struct fcoe_port *port = lport_priv(lport); | 748 | struct fcoe_port *port = lport_priv(lport); |
761 | struct fcoe_interface *fcoe = port->fcoe; | 749 | struct fcoe_interface *fcoe = port->priv; |
762 | struct fcoe_interface *oldfcoe = NULL; | 750 | struct fcoe_interface *oldfcoe = NULL; |
763 | struct net_device *old_real_dev, *cur_real_dev; | 751 | struct net_device *old_real_dev, *cur_real_dev; |
764 | u16 min_xid = FCOE_MIN_XID; | 752 | u16 min_xid = FCOE_MIN_XID; |
@@ -842,7 +830,7 @@ skip_oem: | |||
842 | static void fcoe_if_destroy(struct fc_lport *lport) | 830 | static void fcoe_if_destroy(struct fc_lport *lport) |
843 | { | 831 | { |
844 | struct fcoe_port *port = lport_priv(lport); | 832 | struct fcoe_port *port = lport_priv(lport); |
845 | struct fcoe_interface *fcoe = port->fcoe; | 833 | struct fcoe_interface *fcoe = port->priv; |
846 | struct net_device *netdev = fcoe->netdev; | 834 | struct net_device *netdev = fcoe->netdev; |
847 | 835 | ||
848 | FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); | 836 | FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); |
@@ -884,7 +872,6 @@ static void fcoe_if_destroy(struct fc_lport *lport) | |||
884 | 872 | ||
885 | /* Release the Scsi_Host */ | 873 | /* Release the Scsi_Host */ |
886 | scsi_host_put(lport->host); | 874 | scsi_host_put(lport->host); |
887 | module_put(THIS_MODULE); | ||
888 | } | 875 | } |
889 | 876 | ||
890 | /** | 877 | /** |
@@ -939,8 +926,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
939 | struct device *parent, int npiv) | 926 | struct device *parent, int npiv) |
940 | { | 927 | { |
941 | struct net_device *netdev = fcoe->netdev; | 928 | struct net_device *netdev = fcoe->netdev; |
942 | struct fc_lport *lport = NULL; | 929 | struct fc_lport *lport, *n_port; |
943 | struct fcoe_port *port; | 930 | struct fcoe_port *port; |
931 | struct Scsi_Host *shost; | ||
944 | int rc; | 932 | int rc; |
945 | /* | 933 | /* |
946 | * parent is only a vport if npiv is 1, | 934 | * parent is only a vport if npiv is 1, |
@@ -950,13 +938,11 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
950 | 938 | ||
951 | FCOE_NETDEV_DBG(netdev, "Create Interface\n"); | 939 | FCOE_NETDEV_DBG(netdev, "Create Interface\n"); |
952 | 940 | ||
953 | if (!npiv) { | 941 | if (!npiv) |
954 | lport = libfc_host_alloc(&fcoe_shost_template, | 942 | lport = libfc_host_alloc(&fcoe_shost_template, sizeof(*port)); |
955 | sizeof(struct fcoe_port)); | 943 | else |
956 | } else { | 944 | lport = libfc_vport_create(vport, sizeof(*port)); |
957 | lport = libfc_vport_create(vport, | 945 | |
958 | sizeof(struct fcoe_port)); | ||
959 | } | ||
960 | if (!lport) { | 946 | if (!lport) { |
961 | FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); | 947 | FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); |
962 | rc = -ENOMEM; | 948 | rc = -ENOMEM; |
@@ -964,7 +950,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
964 | } | 950 | } |
965 | port = lport_priv(lport); | 951 | port = lport_priv(lport); |
966 | port->lport = lport; | 952 | port->lport = lport; |
967 | port->fcoe = fcoe; | 953 | port->priv = fcoe; |
954 | port->max_queue_depth = FCOE_MAX_QUEUE_DEPTH; | ||
955 | port->min_queue_depth = FCOE_MIN_QUEUE_DEPTH; | ||
968 | INIT_WORK(&port->destroy_work, fcoe_destroy_work); | 956 | INIT_WORK(&port->destroy_work, fcoe_destroy_work); |
969 | 957 | ||
970 | /* configure a fc_lport including the exchange manager */ | 958 | /* configure a fc_lport including the exchange manager */ |
@@ -1007,24 +995,27 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
1007 | goto out_lp_destroy; | 995 | goto out_lp_destroy; |
1008 | } | 996 | } |
1009 | 997 | ||
1010 | if (!npiv) { | 998 | /* |
1011 | /* | 999 | * fcoe_em_alloc() and fcoe_hostlist_add() both |
1012 | * fcoe_em_alloc() and fcoe_hostlist_add() both | 1000 | * need to be atomic with respect to other changes to the |
1013 | * need to be atomic with respect to other changes to the | 1001 | * hostlist since fcoe_em_alloc() looks for an existing EM |
1014 | * hostlist since fcoe_em_alloc() looks for an existing EM | 1002 | * instance on host list updated by fcoe_hostlist_add(). |
1015 | * instance on host list updated by fcoe_hostlist_add(). | 1003 | * |
1016 | * | 1004 | * This is currently handled through the fcoe_config_mutex |
1017 | * This is currently handled through the fcoe_config_mutex | 1005 | * begin held. |
1018 | * begin held. | 1006 | */ |
1019 | */ | 1007 | if (!npiv) |
1020 | |||
1021 | /* lport exch manager allocation */ | 1008 | /* lport exch manager allocation */ |
1022 | rc = fcoe_em_config(lport); | 1009 | rc = fcoe_em_config(lport); |
1023 | if (rc) { | 1010 | else { |
1024 | FCOE_NETDEV_DBG(netdev, "Could not configure the EM " | 1011 | shost = vport_to_shost(vport); |
1025 | "for the interface\n"); | 1012 | n_port = shost_priv(shost); |
1026 | goto out_lp_destroy; | 1013 | rc = fc_exch_mgr_list_clone(n_port, lport); |
1027 | } | 1014 | } |
1015 | |||
1016 | if (rc) { | ||
1017 | FCOE_NETDEV_DBG(netdev, "Could not configure the EM\n"); | ||
1018 | goto out_lp_destroy; | ||
1028 | } | 1019 | } |
1029 | 1020 | ||
1030 | fcoe_interface_get(fcoe); | 1021 | fcoe_interface_get(fcoe); |
@@ -1048,11 +1039,12 @@ out: | |||
1048 | static int __init fcoe_if_init(void) | 1039 | static int __init fcoe_if_init(void) |
1049 | { | 1040 | { |
1050 | /* attach to scsi transport */ | 1041 | /* attach to scsi transport */ |
1051 | fcoe_transport_template = fc_attach_transport(&fcoe_transport_function); | 1042 | fcoe_nport_scsi_transport = |
1052 | fcoe_vport_transport_template = | 1043 | fc_attach_transport(&fcoe_nport_fc_functions); |
1053 | fc_attach_transport(&fcoe_vport_transport_function); | 1044 | fcoe_vport_scsi_transport = |
1045 | fc_attach_transport(&fcoe_vport_fc_functions); | ||
1054 | 1046 | ||
1055 | if (!fcoe_transport_template) { | 1047 | if (!fcoe_nport_scsi_transport) { |
1056 | printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); | 1048 | printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); |
1057 | return -ENODEV; | 1049 | return -ENODEV; |
1058 | } | 1050 | } |
@@ -1069,10 +1061,10 @@ static int __init fcoe_if_init(void) | |||
1069 | */ | 1061 | */ |
1070 | int __exit fcoe_if_exit(void) | 1062 | int __exit fcoe_if_exit(void) |
1071 | { | 1063 | { |
1072 | fc_release_transport(fcoe_transport_template); | 1064 | fc_release_transport(fcoe_nport_scsi_transport); |
1073 | fc_release_transport(fcoe_vport_transport_template); | 1065 | fc_release_transport(fcoe_vport_scsi_transport); |
1074 | fcoe_transport_template = NULL; | 1066 | fcoe_nport_scsi_transport = NULL; |
1075 | fcoe_vport_transport_template = NULL; | 1067 | fcoe_vport_scsi_transport = NULL; |
1076 | return 0; | 1068 | return 0; |
1077 | } | 1069 | } |
1078 | 1070 | ||
@@ -1359,108 +1351,22 @@ err2: | |||
1359 | } | 1351 | } |
1360 | 1352 | ||
1361 | /** | 1353 | /** |
1362 | * fcoe_start_io() - Start FCoE I/O | 1354 | * fcoe_alloc_paged_crc_eof() - Allocate a page to be used for the trailer CRC |
1363 | * @skb: The packet to be transmitted | ||
1364 | * | ||
1365 | * This routine is called from the net device to start transmitting | ||
1366 | * FCoE packets. | ||
1367 | * | ||
1368 | * Returns: 0 for success | ||
1369 | */ | ||
1370 | static inline int fcoe_start_io(struct sk_buff *skb) | ||
1371 | { | ||
1372 | struct sk_buff *nskb; | ||
1373 | int rc; | ||
1374 | |||
1375 | nskb = skb_clone(skb, GFP_ATOMIC); | ||
1376 | rc = dev_queue_xmit(nskb); | ||
1377 | if (rc != 0) | ||
1378 | return rc; | ||
1379 | kfree_skb(skb); | ||
1380 | return 0; | ||
1381 | } | ||
1382 | |||
1383 | /** | ||
1384 | * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC | ||
1385 | * @skb: The packet to be transmitted | 1355 | * @skb: The packet to be transmitted |
1386 | * @tlen: The total length of the trailer | 1356 | * @tlen: The total length of the trailer |
1387 | * | 1357 | * |
1388 | * This routine allocates a page for frame trailers. The page is re-used if | ||
1389 | * there is enough room left on it for the current trailer. If there isn't | ||
1390 | * enough buffer left a new page is allocated for the trailer. Reference to | ||
1391 | * the page from this function as well as the skbs using the page fragments | ||
1392 | * ensure that the page is freed at the appropriate time. | ||
1393 | * | ||
1394 | * Returns: 0 for success | 1358 | * Returns: 0 for success |
1395 | */ | 1359 | */ |
1396 | static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) | 1360 | static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen) |
1397 | { | 1361 | { |
1398 | struct fcoe_percpu_s *fps; | 1362 | struct fcoe_percpu_s *fps; |
1399 | struct page *page; | 1363 | int rc; |
1400 | 1364 | ||
1401 | fps = &get_cpu_var(fcoe_percpu); | 1365 | fps = &get_cpu_var(fcoe_percpu); |
1402 | page = fps->crc_eof_page; | 1366 | rc = fcoe_get_paged_crc_eof(skb, tlen, fps); |
1403 | if (!page) { | ||
1404 | page = alloc_page(GFP_ATOMIC); | ||
1405 | if (!page) { | ||
1406 | put_cpu_var(fcoe_percpu); | ||
1407 | return -ENOMEM; | ||
1408 | } | ||
1409 | fps->crc_eof_page = page; | ||
1410 | fps->crc_eof_offset = 0; | ||
1411 | } | ||
1412 | |||
1413 | get_page(page); | ||
1414 | skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, | ||
1415 | fps->crc_eof_offset, tlen); | ||
1416 | skb->len += tlen; | ||
1417 | skb->data_len += tlen; | ||
1418 | skb->truesize += tlen; | ||
1419 | fps->crc_eof_offset += sizeof(struct fcoe_crc_eof); | ||
1420 | |||
1421 | if (fps->crc_eof_offset >= PAGE_SIZE) { | ||
1422 | fps->crc_eof_page = NULL; | ||
1423 | fps->crc_eof_offset = 0; | ||
1424 | put_page(page); | ||
1425 | } | ||
1426 | put_cpu_var(fcoe_percpu); | 1367 | put_cpu_var(fcoe_percpu); |
1427 | return 0; | ||
1428 | } | ||
1429 | 1368 | ||
1430 | /** | 1369 | return rc; |
1431 | * fcoe_fc_crc() - Calculates the CRC for a given frame | ||
1432 | * @fp: The frame to be checksumed | ||
1433 | * | ||
1434 | * This uses crc32() routine to calculate the CRC for a frame | ||
1435 | * | ||
1436 | * Return: The 32 bit CRC value | ||
1437 | */ | ||
1438 | u32 fcoe_fc_crc(struct fc_frame *fp) | ||
1439 | { | ||
1440 | struct sk_buff *skb = fp_skb(fp); | ||
1441 | struct skb_frag_struct *frag; | ||
1442 | unsigned char *data; | ||
1443 | unsigned long off, len, clen; | ||
1444 | u32 crc; | ||
1445 | unsigned i; | ||
1446 | |||
1447 | crc = crc32(~0, skb->data, skb_headlen(skb)); | ||
1448 | |||
1449 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
1450 | frag = &skb_shinfo(skb)->frags[i]; | ||
1451 | off = frag->page_offset; | ||
1452 | len = frag->size; | ||
1453 | while (len > 0) { | ||
1454 | clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); | ||
1455 | data = kmap_atomic(frag->page + (off >> PAGE_SHIFT), | ||
1456 | KM_SKB_DATA_SOFTIRQ); | ||
1457 | crc = crc32(crc, data + (off & ~PAGE_MASK), clen); | ||
1458 | kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ); | ||
1459 | off += clen; | ||
1460 | len -= clen; | ||
1461 | } | ||
1462 | } | ||
1463 | return crc; | ||
1464 | } | 1370 | } |
1465 | 1371 | ||
1466 | /** | 1372 | /** |
@@ -1483,7 +1389,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1483 | unsigned int tlen; /* trailer length */ | 1389 | unsigned int tlen; /* trailer length */ |
1484 | unsigned int elen; /* eth header, may include vlan */ | 1390 | unsigned int elen; /* eth header, may include vlan */ |
1485 | struct fcoe_port *port = lport_priv(lport); | 1391 | struct fcoe_port *port = lport_priv(lport); |
1486 | struct fcoe_interface *fcoe = port->fcoe; | 1392 | struct fcoe_interface *fcoe = port->priv; |
1487 | u8 sof, eof; | 1393 | u8 sof, eof; |
1488 | struct fcoe_hdr *hp; | 1394 | struct fcoe_hdr *hp; |
1489 | 1395 | ||
@@ -1524,7 +1430,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1524 | /* copy port crc and eof to the skb buff */ | 1430 | /* copy port crc and eof to the skb buff */ |
1525 | if (skb_is_nonlinear(skb)) { | 1431 | if (skb_is_nonlinear(skb)) { |
1526 | skb_frag_t *frag; | 1432 | skb_frag_t *frag; |
1527 | if (fcoe_get_paged_crc_eof(skb, tlen)) { | 1433 | if (fcoe_alloc_paged_crc_eof(skb, tlen)) { |
1528 | kfree_skb(skb); | 1434 | kfree_skb(skb); |
1529 | return -ENOMEM; | 1435 | return -ENOMEM; |
1530 | } | 1436 | } |
@@ -1604,6 +1510,56 @@ static void fcoe_percpu_flush_done(struct sk_buff *skb) | |||
1604 | } | 1510 | } |
1605 | 1511 | ||
1606 | /** | 1512 | /** |
1513 | * fcoe_filter_frames() - filter out bad fcoe frames, i.e. bad CRC | ||
1514 | * @lport: The local port the frame was received on | ||
1515 | * @fp: The received frame | ||
1516 | * | ||
1517 | * Return: 0 on passing filtering checks | ||
1518 | */ | ||
1519 | static inline int fcoe_filter_frames(struct fc_lport *lport, | ||
1520 | struct fc_frame *fp) | ||
1521 | { | ||
1522 | struct fcoe_interface *fcoe; | ||
1523 | struct fc_frame_header *fh; | ||
1524 | struct sk_buff *skb = (struct sk_buff *)fp; | ||
1525 | struct fcoe_dev_stats *stats; | ||
1526 | |||
1527 | /* | ||
1528 | * We only check CRC if no offload is available and if it is | ||
1529 | * it's solicited data, in which case, the FCP layer would | ||
1530 | * check it during the copy. | ||
1531 | */ | ||
1532 | if (lport->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY) | ||
1533 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | ||
1534 | else | ||
1535 | fr_flags(fp) |= FCPHF_CRC_UNCHECKED; | ||
1536 | |||
1537 | fh = (struct fc_frame_header *) skb_transport_header(skb); | ||
1538 | fh = fc_frame_header_get(fp); | ||
1539 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP) | ||
1540 | return 0; | ||
1541 | |||
1542 | fcoe = ((struct fcoe_port *)lport_priv(lport))->priv; | ||
1543 | if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && | ||
1544 | ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { | ||
1545 | FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n"); | ||
1546 | return -EINVAL; | ||
1547 | } | ||
1548 | |||
1549 | if (!(fr_flags(fp) & FCPHF_CRC_UNCHECKED) || | ||
1550 | le32_to_cpu(fr_crc(fp)) == ~crc32(~0, skb->data, skb->len)) { | ||
1551 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | ||
1552 | return 0; | ||
1553 | } | ||
1554 | |||
1555 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); | ||
1556 | stats->InvalidCRCCount++; | ||
1557 | if (stats->InvalidCRCCount < 5) | ||
1558 | printk(KERN_WARNING "fcoe: dropping frame with CRC error\n"); | ||
1559 | return -EINVAL; | ||
1560 | } | ||
1561 | |||
1562 | /** | ||
1607 | * fcoe_recv_frame() - process a single received frame | 1563 | * fcoe_recv_frame() - process a single received frame |
1608 | * @skb: frame to process | 1564 | * @skb: frame to process |
1609 | */ | 1565 | */ |
@@ -1613,7 +1569,6 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1613 | struct fc_lport *lport; | 1569 | struct fc_lport *lport; |
1614 | struct fcoe_rcv_info *fr; | 1570 | struct fcoe_rcv_info *fr; |
1615 | struct fcoe_dev_stats *stats; | 1571 | struct fcoe_dev_stats *stats; |
1616 | struct fc_frame_header *fh; | ||
1617 | struct fcoe_crc_eof crc_eof; | 1572 | struct fcoe_crc_eof crc_eof; |
1618 | struct fc_frame *fp; | 1573 | struct fc_frame *fp; |
1619 | struct fcoe_port *port; | 1574 | struct fcoe_port *port; |
@@ -1644,7 +1599,6 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1644 | * was done in fcoe_rcv already. | 1599 | * was done in fcoe_rcv already. |
1645 | */ | 1600 | */ |
1646 | hp = (struct fcoe_hdr *) skb_network_header(skb); | 1601 | hp = (struct fcoe_hdr *) skb_network_header(skb); |
1647 | fh = (struct fc_frame_header *) skb_transport_header(skb); | ||
1648 | 1602 | ||
1649 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); | 1603 | stats = per_cpu_ptr(lport->dev_stats, get_cpu()); |
1650 | if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { | 1604 | if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { |
@@ -1677,35 +1631,11 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1677 | if (pskb_trim(skb, fr_len)) | 1631 | if (pskb_trim(skb, fr_len)) |
1678 | goto drop; | 1632 | goto drop; |
1679 | 1633 | ||
1680 | /* | 1634 | if (!fcoe_filter_frames(lport, fp)) { |
1681 | * We only check CRC if no offload is available and if it is | 1635 | put_cpu(); |
1682 | * it's solicited data, in which case, the FCP layer would | 1636 | fc_exch_recv(lport, fp); |
1683 | * check it during the copy. | 1637 | return; |
1684 | */ | ||
1685 | if (lport->crc_offload && | ||
1686 | skb->ip_summed == CHECKSUM_UNNECESSARY) | ||
1687 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | ||
1688 | else | ||
1689 | fr_flags(fp) |= FCPHF_CRC_UNCHECKED; | ||
1690 | |||
1691 | fh = fc_frame_header_get(fp); | ||
1692 | if ((fh->fh_r_ctl != FC_RCTL_DD_SOL_DATA || | ||
1693 | fh->fh_type != FC_TYPE_FCP) && | ||
1694 | (fr_flags(fp) & FCPHF_CRC_UNCHECKED)) { | ||
1695 | if (le32_to_cpu(fr_crc(fp)) != | ||
1696 | ~crc32(~0, skb->data, fr_len)) { | ||
1697 | if (stats->InvalidCRCCount < 5) | ||
1698 | printk(KERN_WARNING "fcoe: dropping " | ||
1699 | "frame with CRC error\n"); | ||
1700 | stats->InvalidCRCCount++; | ||
1701 | goto drop; | ||
1702 | } | ||
1703 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | ||
1704 | } | 1638 | } |
1705 | put_cpu(); | ||
1706 | fc_exch_recv(lport, fp); | ||
1707 | return; | ||
1708 | |||
1709 | drop: | 1639 | drop: |
1710 | stats->ErrorFrames++; | 1640 | stats->ErrorFrames++; |
1711 | put_cpu(); | 1641 | put_cpu(); |
@@ -1744,64 +1674,6 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1744 | } | 1674 | } |
1745 | 1675 | ||
1746 | /** | 1676 | /** |
1747 | * fcoe_check_wait_queue() - Attempt to clear the transmit backlog | ||
1748 | * @lport: The local port whose backlog is to be cleared | ||
1749 | * | ||
1750 | * This empties the wait_queue, dequeues the head of the wait_queue queue | ||
1751 | * and calls fcoe_start_io() for each packet. If all skb have been | ||
1752 | * transmitted it returns the qlen. If an error occurs it restores | ||
1753 | * wait_queue (to try again later) and returns -1. | ||
1754 | * | ||
1755 | * The wait_queue is used when the skb transmit fails. The failed skb | ||
1756 | * will go in the wait_queue which will be emptied by the timer function or | ||
1757 | * by the next skb transmit. | ||
1758 | */ | ||
1759 | static void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb) | ||
1760 | { | ||
1761 | struct fcoe_port *port = lport_priv(lport); | ||
1762 | int rc; | ||
1763 | |||
1764 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
1765 | |||
1766 | if (skb) | ||
1767 | __skb_queue_tail(&port->fcoe_pending_queue, skb); | ||
1768 | |||
1769 | if (port->fcoe_pending_queue_active) | ||
1770 | goto out; | ||
1771 | port->fcoe_pending_queue_active = 1; | ||
1772 | |||
1773 | while (port->fcoe_pending_queue.qlen) { | ||
1774 | /* keep qlen > 0 until fcoe_start_io succeeds */ | ||
1775 | port->fcoe_pending_queue.qlen++; | ||
1776 | skb = __skb_dequeue(&port->fcoe_pending_queue); | ||
1777 | |||
1778 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
1779 | rc = fcoe_start_io(skb); | ||
1780 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
1781 | |||
1782 | if (rc) { | ||
1783 | __skb_queue_head(&port->fcoe_pending_queue, skb); | ||
1784 | /* undo temporary increment above */ | ||
1785 | port->fcoe_pending_queue.qlen--; | ||
1786 | break; | ||
1787 | } | ||
1788 | /* undo temporary increment above */ | ||
1789 | port->fcoe_pending_queue.qlen--; | ||
1790 | } | ||
1791 | |||
1792 | if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) | ||
1793 | lport->qfull = 0; | ||
1794 | if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) | ||
1795 | mod_timer(&port->timer, jiffies + 2); | ||
1796 | port->fcoe_pending_queue_active = 0; | ||
1797 | out: | ||
1798 | if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) | ||
1799 | lport->qfull = 1; | ||
1800 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
1801 | return; | ||
1802 | } | ||
1803 | |||
1804 | /** | ||
1805 | * fcoe_dev_setup() - Setup the link change notification interface | 1677 | * fcoe_dev_setup() - Setup the link change notification interface |
1806 | */ | 1678 | */ |
1807 | static void fcoe_dev_setup(void) | 1679 | static void fcoe_dev_setup(void) |
@@ -1872,7 +1744,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1872 | list_del(&fcoe->list); | 1744 | list_del(&fcoe->list); |
1873 | port = lport_priv(fcoe->ctlr.lp); | 1745 | port = lport_priv(fcoe->ctlr.lp); |
1874 | fcoe_interface_cleanup(fcoe); | 1746 | fcoe_interface_cleanup(fcoe); |
1875 | schedule_work(&port->destroy_work); | 1747 | queue_work(fcoe_wq, &port->destroy_work); |
1876 | goto out; | 1748 | goto out; |
1877 | break; | 1749 | break; |
1878 | case NETDEV_FEAT_CHANGE: | 1750 | case NETDEV_FEAT_CHANGE: |
@@ -1898,39 +1770,16 @@ out: | |||
1898 | } | 1770 | } |
1899 | 1771 | ||
1900 | /** | 1772 | /** |
1901 | * fcoe_if_to_netdev() - Parse a name buffer to get a net device | ||
1902 | * @buffer: The name of the net device | ||
1903 | * | ||
1904 | * Returns: NULL or a ptr to net_device | ||
1905 | */ | ||
1906 | static struct net_device *fcoe_if_to_netdev(const char *buffer) | ||
1907 | { | ||
1908 | char *cp; | ||
1909 | char ifname[IFNAMSIZ + 2]; | ||
1910 | |||
1911 | if (buffer) { | ||
1912 | strlcpy(ifname, buffer, IFNAMSIZ); | ||
1913 | cp = ifname + strlen(ifname); | ||
1914 | while (--cp >= ifname && *cp == '\n') | ||
1915 | *cp = '\0'; | ||
1916 | return dev_get_by_name(&init_net, ifname); | ||
1917 | } | ||
1918 | return NULL; | ||
1919 | } | ||
1920 | |||
1921 | /** | ||
1922 | * fcoe_disable() - Disables a FCoE interface | 1773 | * fcoe_disable() - Disables a FCoE interface |
1923 | * @buffer: The name of the Ethernet interface to be disabled | 1774 | * @netdev : The net_device object the Ethernet interface to create on |
1924 | * @kp: The associated kernel parameter | ||
1925 | * | 1775 | * |
1926 | * Called from sysfs. | 1776 | * Called from fcoe transport. |
1927 | * | 1777 | * |
1928 | * Returns: 0 for success | 1778 | * Returns: 0 for success |
1929 | */ | 1779 | */ |
1930 | static int fcoe_disable(const char *buffer, struct kernel_param *kp) | 1780 | static int fcoe_disable(struct net_device *netdev) |
1931 | { | 1781 | { |
1932 | struct fcoe_interface *fcoe; | 1782 | struct fcoe_interface *fcoe; |
1933 | struct net_device *netdev; | ||
1934 | int rc = 0; | 1783 | int rc = 0; |
1935 | 1784 | ||
1936 | mutex_lock(&fcoe_config_mutex); | 1785 | mutex_lock(&fcoe_config_mutex); |
@@ -1946,16 +1795,9 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp) | |||
1946 | } | 1795 | } |
1947 | #endif | 1796 | #endif |
1948 | 1797 | ||
1949 | netdev = fcoe_if_to_netdev(buffer); | ||
1950 | if (!netdev) { | ||
1951 | rc = -ENODEV; | ||
1952 | goto out_nodev; | ||
1953 | } | ||
1954 | |||
1955 | if (!rtnl_trylock()) { | 1798 | if (!rtnl_trylock()) { |
1956 | dev_put(netdev); | ||
1957 | mutex_unlock(&fcoe_config_mutex); | 1799 | mutex_unlock(&fcoe_config_mutex); |
1958 | return restart_syscall(); | 1800 | return -ERESTARTSYS; |
1959 | } | 1801 | } |
1960 | 1802 | ||
1961 | fcoe = fcoe_hostlist_lookup_port(netdev); | 1803 | fcoe = fcoe_hostlist_lookup_port(netdev); |
@@ -1967,7 +1809,6 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp) | |||
1967 | } else | 1809 | } else |
1968 | rc = -ENODEV; | 1810 | rc = -ENODEV; |
1969 | 1811 | ||
1970 | dev_put(netdev); | ||
1971 | out_nodev: | 1812 | out_nodev: |
1972 | mutex_unlock(&fcoe_config_mutex); | 1813 | mutex_unlock(&fcoe_config_mutex); |
1973 | return rc; | 1814 | return rc; |
@@ -1975,17 +1816,15 @@ out_nodev: | |||
1975 | 1816 | ||
1976 | /** | 1817 | /** |
1977 | * fcoe_enable() - Enables a FCoE interface | 1818 | * fcoe_enable() - Enables a FCoE interface |
1978 | * @buffer: The name of the Ethernet interface to be enabled | 1819 | * @netdev : The net_device object the Ethernet interface to create on |
1979 | * @kp: The associated kernel parameter | ||
1980 | * | 1820 | * |
1981 | * Called from sysfs. | 1821 | * Called from fcoe transport. |
1982 | * | 1822 | * |
1983 | * Returns: 0 for success | 1823 | * Returns: 0 for success |
1984 | */ | 1824 | */ |
1985 | static int fcoe_enable(const char *buffer, struct kernel_param *kp) | 1825 | static int fcoe_enable(struct net_device *netdev) |
1986 | { | 1826 | { |
1987 | struct fcoe_interface *fcoe; | 1827 | struct fcoe_interface *fcoe; |
1988 | struct net_device *netdev; | ||
1989 | int rc = 0; | 1828 | int rc = 0; |
1990 | 1829 | ||
1991 | mutex_lock(&fcoe_config_mutex); | 1830 | mutex_lock(&fcoe_config_mutex); |
@@ -2000,17 +1839,9 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp) | |||
2000 | goto out_nodev; | 1839 | goto out_nodev; |
2001 | } | 1840 | } |
2002 | #endif | 1841 | #endif |
2003 | |||
2004 | netdev = fcoe_if_to_netdev(buffer); | ||
2005 | if (!netdev) { | ||
2006 | rc = -ENODEV; | ||
2007 | goto out_nodev; | ||
2008 | } | ||
2009 | |||
2010 | if (!rtnl_trylock()) { | 1842 | if (!rtnl_trylock()) { |
2011 | dev_put(netdev); | ||
2012 | mutex_unlock(&fcoe_config_mutex); | 1843 | mutex_unlock(&fcoe_config_mutex); |
2013 | return restart_syscall(); | 1844 | return -ERESTARTSYS; |
2014 | } | 1845 | } |
2015 | 1846 | ||
2016 | fcoe = fcoe_hostlist_lookup_port(netdev); | 1847 | fcoe = fcoe_hostlist_lookup_port(netdev); |
@@ -2021,7 +1852,6 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp) | |||
2021 | else if (!fcoe_link_ok(fcoe->ctlr.lp)) | 1852 | else if (!fcoe_link_ok(fcoe->ctlr.lp)) |
2022 | fcoe_ctlr_link_up(&fcoe->ctlr); | 1853 | fcoe_ctlr_link_up(&fcoe->ctlr); |
2023 | 1854 | ||
2024 | dev_put(netdev); | ||
2025 | out_nodev: | 1855 | out_nodev: |
2026 | mutex_unlock(&fcoe_config_mutex); | 1856 | mutex_unlock(&fcoe_config_mutex); |
2027 | return rc; | 1857 | return rc; |
@@ -2029,17 +1859,15 @@ out_nodev: | |||
2029 | 1859 | ||
2030 | /** | 1860 | /** |
2031 | * fcoe_destroy() - Destroy a FCoE interface | 1861 | * fcoe_destroy() - Destroy a FCoE interface |
2032 | * @buffer: The name of the Ethernet interface to be destroyed | 1862 | * @netdev : The net_device object the Ethernet interface to create on |
2033 | * @kp: The associated kernel parameter | ||
2034 | * | 1863 | * |
2035 | * Called from sysfs. | 1864 | * Called from fcoe transport |
2036 | * | 1865 | * |
2037 | * Returns: 0 for success | 1866 | * Returns: 0 for success |
2038 | */ | 1867 | */ |
2039 | static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | 1868 | static int fcoe_destroy(struct net_device *netdev) |
2040 | { | 1869 | { |
2041 | struct fcoe_interface *fcoe; | 1870 | struct fcoe_interface *fcoe; |
2042 | struct net_device *netdev; | ||
2043 | int rc = 0; | 1871 | int rc = 0; |
2044 | 1872 | ||
2045 | mutex_lock(&fcoe_config_mutex); | 1873 | mutex_lock(&fcoe_config_mutex); |
@@ -2054,32 +1882,21 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | |||
2054 | goto out_nodev; | 1882 | goto out_nodev; |
2055 | } | 1883 | } |
2056 | #endif | 1884 | #endif |
2057 | |||
2058 | netdev = fcoe_if_to_netdev(buffer); | ||
2059 | if (!netdev) { | ||
2060 | rc = -ENODEV; | ||
2061 | goto out_nodev; | ||
2062 | } | ||
2063 | |||
2064 | if (!rtnl_trylock()) { | 1885 | if (!rtnl_trylock()) { |
2065 | dev_put(netdev); | ||
2066 | mutex_unlock(&fcoe_config_mutex); | 1886 | mutex_unlock(&fcoe_config_mutex); |
2067 | return restart_syscall(); | 1887 | return -ERESTARTSYS; |
2068 | } | 1888 | } |
2069 | 1889 | ||
2070 | fcoe = fcoe_hostlist_lookup_port(netdev); | 1890 | fcoe = fcoe_hostlist_lookup_port(netdev); |
2071 | if (!fcoe) { | 1891 | if (!fcoe) { |
2072 | rtnl_unlock(); | 1892 | rtnl_unlock(); |
2073 | rc = -ENODEV; | 1893 | rc = -ENODEV; |
2074 | goto out_putdev; | 1894 | goto out_nodev; |
2075 | } | 1895 | } |
2076 | fcoe_interface_cleanup(fcoe); | 1896 | fcoe_interface_cleanup(fcoe); |
2077 | list_del(&fcoe->list); | 1897 | list_del(&fcoe->list); |
2078 | /* RTNL mutex is dropped by fcoe_if_destroy */ | 1898 | /* RTNL mutex is dropped by fcoe_if_destroy */ |
2079 | fcoe_if_destroy(fcoe->ctlr.lp); | 1899 | fcoe_if_destroy(fcoe->ctlr.lp); |
2080 | |||
2081 | out_putdev: | ||
2082 | dev_put(netdev); | ||
2083 | out_nodev: | 1900 | out_nodev: |
2084 | mutex_unlock(&fcoe_config_mutex); | 1901 | mutex_unlock(&fcoe_config_mutex); |
2085 | return rc; | 1902 | return rc; |
@@ -2102,27 +1919,39 @@ static void fcoe_destroy_work(struct work_struct *work) | |||
2102 | } | 1919 | } |
2103 | 1920 | ||
2104 | /** | 1921 | /** |
1922 | * fcoe_match() - Check if the FCoE is supported on the given netdevice | ||
1923 | * @netdev : The net_device object the Ethernet interface to create on | ||
1924 | * | ||
1925 | * Called from fcoe transport. | ||
1926 | * | ||
1927 | * Returns: always returns true as this is the default FCoE transport, | ||
1928 | * i.e., support all netdevs. | ||
1929 | */ | ||
1930 | static bool fcoe_match(struct net_device *netdev) | ||
1931 | { | ||
1932 | return true; | ||
1933 | } | ||
1934 | |||
1935 | /** | ||
2105 | * fcoe_create() - Create a fcoe interface | 1936 | * fcoe_create() - Create a fcoe interface |
2106 | * @buffer: The name of the Ethernet interface to create on | 1937 | * @netdev : The net_device object the Ethernet interface to create on |
2107 | * @kp: The associated kernel param | 1938 | * @fip_mode: The FIP mode for this creation |
2108 | * | 1939 | * |
2109 | * Called from sysfs. | 1940 | * Called from fcoe transport |
2110 | * | 1941 | * |
2111 | * Returns: 0 for success | 1942 | * Returns: 0 for success |
2112 | */ | 1943 | */ |
2113 | static int fcoe_create(const char *buffer, struct kernel_param *kp) | 1944 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) |
2114 | { | 1945 | { |
2115 | enum fip_state fip_mode = (enum fip_state)(long)kp->arg; | ||
2116 | int rc; | 1946 | int rc; |
2117 | struct fcoe_interface *fcoe; | 1947 | struct fcoe_interface *fcoe; |
2118 | struct fc_lport *lport; | 1948 | struct fc_lport *lport; |
2119 | struct net_device *netdev; | ||
2120 | 1949 | ||
2121 | mutex_lock(&fcoe_config_mutex); | 1950 | mutex_lock(&fcoe_config_mutex); |
2122 | 1951 | ||
2123 | if (!rtnl_trylock()) { | 1952 | if (!rtnl_trylock()) { |
2124 | mutex_unlock(&fcoe_config_mutex); | 1953 | mutex_unlock(&fcoe_config_mutex); |
2125 | return restart_syscall(); | 1954 | return -ERESTARTSYS; |
2126 | } | 1955 | } |
2127 | 1956 | ||
2128 | #ifdef CONFIG_FCOE_MODULE | 1957 | #ifdef CONFIG_FCOE_MODULE |
@@ -2133,31 +1962,20 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
2133 | */ | 1962 | */ |
2134 | if (THIS_MODULE->state != MODULE_STATE_LIVE) { | 1963 | if (THIS_MODULE->state != MODULE_STATE_LIVE) { |
2135 | rc = -ENODEV; | 1964 | rc = -ENODEV; |
2136 | goto out_nomod; | ||
2137 | } | ||
2138 | #endif | ||
2139 | |||
2140 | if (!try_module_get(THIS_MODULE)) { | ||
2141 | rc = -EINVAL; | ||
2142 | goto out_nomod; | ||
2143 | } | ||
2144 | |||
2145 | netdev = fcoe_if_to_netdev(buffer); | ||
2146 | if (!netdev) { | ||
2147 | rc = -ENODEV; | ||
2148 | goto out_nodev; | 1965 | goto out_nodev; |
2149 | } | 1966 | } |
1967 | #endif | ||
2150 | 1968 | ||
2151 | /* look for existing lport */ | 1969 | /* look for existing lport */ |
2152 | if (fcoe_hostlist_lookup(netdev)) { | 1970 | if (fcoe_hostlist_lookup(netdev)) { |
2153 | rc = -EEXIST; | 1971 | rc = -EEXIST; |
2154 | goto out_putdev; | 1972 | goto out_nodev; |
2155 | } | 1973 | } |
2156 | 1974 | ||
2157 | fcoe = fcoe_interface_create(netdev, fip_mode); | 1975 | fcoe = fcoe_interface_create(netdev, fip_mode); |
2158 | if (!fcoe) { | 1976 | if (IS_ERR(fcoe)) { |
2159 | rc = -ENOMEM; | 1977 | rc = PTR_ERR(fcoe); |
2160 | goto out_putdev; | 1978 | goto out_nodev; |
2161 | } | 1979 | } |
2162 | 1980 | ||
2163 | lport = fcoe_if_create(fcoe, &netdev->dev, 0); | 1981 | lport = fcoe_if_create(fcoe, &netdev->dev, 0); |
@@ -2186,18 +2004,13 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
2186 | * should be holding a reference taken in fcoe_if_create(). | 2004 | * should be holding a reference taken in fcoe_if_create(). |
2187 | */ | 2005 | */ |
2188 | fcoe_interface_put(fcoe); | 2006 | fcoe_interface_put(fcoe); |
2189 | dev_put(netdev); | ||
2190 | rtnl_unlock(); | 2007 | rtnl_unlock(); |
2191 | mutex_unlock(&fcoe_config_mutex); | 2008 | mutex_unlock(&fcoe_config_mutex); |
2192 | 2009 | ||
2193 | return 0; | 2010 | return 0; |
2194 | out_free: | 2011 | out_free: |
2195 | fcoe_interface_put(fcoe); | 2012 | fcoe_interface_put(fcoe); |
2196 | out_putdev: | ||
2197 | dev_put(netdev); | ||
2198 | out_nodev: | 2013 | out_nodev: |
2199 | module_put(THIS_MODULE); | ||
2200 | out_nomod: | ||
2201 | rtnl_unlock(); | 2014 | rtnl_unlock(); |
2202 | mutex_unlock(&fcoe_config_mutex); | 2015 | mutex_unlock(&fcoe_config_mutex); |
2203 | return rc; | 2016 | return rc; |
@@ -2212,8 +2025,7 @@ out_nomod: | |||
2212 | */ | 2025 | */ |
2213 | int fcoe_link_speed_update(struct fc_lport *lport) | 2026 | int fcoe_link_speed_update(struct fc_lport *lport) |
2214 | { | 2027 | { |
2215 | struct fcoe_port *port = lport_priv(lport); | 2028 | struct net_device *netdev = fcoe_netdev(lport); |
2216 | struct net_device *netdev = port->fcoe->netdev; | ||
2217 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; | 2029 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; |
2218 | 2030 | ||
2219 | if (!dev_ethtool_get_settings(netdev, &ecmd)) { | 2031 | if (!dev_ethtool_get_settings(netdev, &ecmd)) { |
@@ -2244,8 +2056,7 @@ int fcoe_link_speed_update(struct fc_lport *lport) | |||
2244 | */ | 2056 | */ |
2245 | int fcoe_link_ok(struct fc_lport *lport) | 2057 | int fcoe_link_ok(struct fc_lport *lport) |
2246 | { | 2058 | { |
2247 | struct fcoe_port *port = lport_priv(lport); | 2059 | struct net_device *netdev = fcoe_netdev(lport); |
2248 | struct net_device *netdev = port->fcoe->netdev; | ||
2249 | 2060 | ||
2250 | if (netif_oper_up(netdev)) | 2061 | if (netif_oper_up(netdev)) |
2251 | return 0; | 2062 | return 0; |
@@ -2309,24 +2120,6 @@ void fcoe_percpu_clean(struct fc_lport *lport) | |||
2309 | } | 2120 | } |
2310 | 2121 | ||
2311 | /** | 2122 | /** |
2312 | * fcoe_clean_pending_queue() - Dequeue a skb and free it | ||
2313 | * @lport: The local port to dequeue a skb on | ||
2314 | */ | ||
2315 | void fcoe_clean_pending_queue(struct fc_lport *lport) | ||
2316 | { | ||
2317 | struct fcoe_port *port = lport_priv(lport); | ||
2318 | struct sk_buff *skb; | ||
2319 | |||
2320 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
2321 | while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) { | ||
2322 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
2323 | kfree_skb(skb); | ||
2324 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
2325 | } | ||
2326 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
2327 | } | ||
2328 | |||
2329 | /** | ||
2330 | * fcoe_reset() - Reset a local port | 2123 | * fcoe_reset() - Reset a local port |
2331 | * @shost: The SCSI host associated with the local port to be reset | 2124 | * @shost: The SCSI host associated with the local port to be reset |
2332 | * | 2125 | * |
@@ -2335,7 +2128,13 @@ void fcoe_clean_pending_queue(struct fc_lport *lport) | |||
2335 | int fcoe_reset(struct Scsi_Host *shost) | 2128 | int fcoe_reset(struct Scsi_Host *shost) |
2336 | { | 2129 | { |
2337 | struct fc_lport *lport = shost_priv(shost); | 2130 | struct fc_lport *lport = shost_priv(shost); |
2338 | fc_lport_reset(lport); | 2131 | struct fcoe_port *port = lport_priv(lport); |
2132 | struct fcoe_interface *fcoe = port->priv; | ||
2133 | |||
2134 | fcoe_ctlr_link_down(&fcoe->ctlr); | ||
2135 | fcoe_clean_pending_queue(fcoe->ctlr.lp); | ||
2136 | if (!fcoe_link_ok(fcoe->ctlr.lp)) | ||
2137 | fcoe_ctlr_link_up(&fcoe->ctlr); | ||
2339 | return 0; | 2138 | return 0; |
2340 | } | 2139 | } |
2341 | 2140 | ||
@@ -2393,12 +2192,24 @@ static int fcoe_hostlist_add(const struct fc_lport *lport) | |||
2393 | fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport)); | 2192 | fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport)); |
2394 | if (!fcoe) { | 2193 | if (!fcoe) { |
2395 | port = lport_priv(lport); | 2194 | port = lport_priv(lport); |
2396 | fcoe = port->fcoe; | 2195 | fcoe = port->priv; |
2397 | list_add_tail(&fcoe->list, &fcoe_hostlist); | 2196 | list_add_tail(&fcoe->list, &fcoe_hostlist); |
2398 | } | 2197 | } |
2399 | return 0; | 2198 | return 0; |
2400 | } | 2199 | } |
2401 | 2200 | ||
2201 | |||
2202 | static struct fcoe_transport fcoe_sw_transport = { | ||
2203 | .name = {FCOE_TRANSPORT_DEFAULT}, | ||
2204 | .attached = false, | ||
2205 | .list = LIST_HEAD_INIT(fcoe_sw_transport.list), | ||
2206 | .match = fcoe_match, | ||
2207 | .create = fcoe_create, | ||
2208 | .destroy = fcoe_destroy, | ||
2209 | .enable = fcoe_enable, | ||
2210 | .disable = fcoe_disable, | ||
2211 | }; | ||
2212 | |||
2402 | /** | 2213 | /** |
2403 | * fcoe_init() - Initialize fcoe.ko | 2214 | * fcoe_init() - Initialize fcoe.ko |
2404 | * | 2215 | * |
@@ -2410,6 +2221,18 @@ static int __init fcoe_init(void) | |||
2410 | unsigned int cpu; | 2221 | unsigned int cpu; |
2411 | int rc = 0; | 2222 | int rc = 0; |
2412 | 2223 | ||
2224 | fcoe_wq = alloc_workqueue("fcoe", 0, 0); | ||
2225 | if (!fcoe_wq) | ||
2226 | return -ENOMEM; | ||
2227 | |||
2228 | /* register as a fcoe transport */ | ||
2229 | rc = fcoe_transport_attach(&fcoe_sw_transport); | ||
2230 | if (rc) { | ||
2231 | printk(KERN_ERR "failed to register an fcoe transport, check " | ||
2232 | "if libfcoe is loaded\n"); | ||
2233 | return rc; | ||
2234 | } | ||
2235 | |||
2413 | mutex_lock(&fcoe_config_mutex); | 2236 | mutex_lock(&fcoe_config_mutex); |
2414 | 2237 | ||
2415 | for_each_possible_cpu(cpu) { | 2238 | for_each_possible_cpu(cpu) { |
@@ -2440,6 +2263,7 @@ out_free: | |||
2440 | fcoe_percpu_thread_destroy(cpu); | 2263 | fcoe_percpu_thread_destroy(cpu); |
2441 | } | 2264 | } |
2442 | mutex_unlock(&fcoe_config_mutex); | 2265 | mutex_unlock(&fcoe_config_mutex); |
2266 | destroy_workqueue(fcoe_wq); | ||
2443 | return rc; | 2267 | return rc; |
2444 | } | 2268 | } |
2445 | module_init(fcoe_init); | 2269 | module_init(fcoe_init); |
@@ -2465,7 +2289,7 @@ static void __exit fcoe_exit(void) | |||
2465 | list_del(&fcoe->list); | 2289 | list_del(&fcoe->list); |
2466 | port = lport_priv(fcoe->ctlr.lp); | 2290 | port = lport_priv(fcoe->ctlr.lp); |
2467 | fcoe_interface_cleanup(fcoe); | 2291 | fcoe_interface_cleanup(fcoe); |
2468 | schedule_work(&port->destroy_work); | 2292 | queue_work(fcoe_wq, &port->destroy_work); |
2469 | } | 2293 | } |
2470 | rtnl_unlock(); | 2294 | rtnl_unlock(); |
2471 | 2295 | ||
@@ -2476,16 +2300,21 @@ static void __exit fcoe_exit(void) | |||
2476 | 2300 | ||
2477 | mutex_unlock(&fcoe_config_mutex); | 2301 | mutex_unlock(&fcoe_config_mutex); |
2478 | 2302 | ||
2479 | /* flush any asyncronous interface destroys, | 2303 | /* |
2480 | * this should happen after the netdev notifier is unregistered */ | 2304 | * destroy_work's may be chained but destroy_workqueue() |
2481 | flush_scheduled_work(); | 2305 | * can take care of them. Just kill the fcoe_wq. |
2482 | /* That will flush out all the N_Ports on the hostlist, but now we | 2306 | */ |
2483 | * may have NPIV VN_Ports scheduled for destruction */ | 2307 | destroy_workqueue(fcoe_wq); |
2484 | flush_scheduled_work(); | ||
2485 | 2308 | ||
2486 | /* detach from scsi transport | 2309 | /* |
2487 | * must happen after all destroys are done, therefor after the flush */ | 2310 | * Detaching from the scsi transport must happen after all |
2311 | * destroys are done on the fcoe_wq. destroy_workqueue will | ||
2312 | * enusre the fcoe_wq is flushed. | ||
2313 | */ | ||
2488 | fcoe_if_exit(); | 2314 | fcoe_if_exit(); |
2315 | |||
2316 | /* detach from fcoe transport */ | ||
2317 | fcoe_transport_detach(&fcoe_sw_transport); | ||
2489 | } | 2318 | } |
2490 | module_exit(fcoe_exit); | 2319 | module_exit(fcoe_exit); |
2491 | 2320 | ||
@@ -2557,7 +2386,7 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did, | |||
2557 | void *arg, u32 timeout) | 2386 | void *arg, u32 timeout) |
2558 | { | 2387 | { |
2559 | struct fcoe_port *port = lport_priv(lport); | 2388 | struct fcoe_port *port = lport_priv(lport); |
2560 | struct fcoe_interface *fcoe = port->fcoe; | 2389 | struct fcoe_interface *fcoe = port->priv; |
2561 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 2390 | struct fcoe_ctlr *fip = &fcoe->ctlr; |
2562 | struct fc_frame_header *fh = fc_frame_header_get(fp); | 2391 | struct fc_frame_header *fh = fc_frame_header_get(fp); |
2563 | 2392 | ||
@@ -2590,7 +2419,7 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled) | |||
2590 | struct Scsi_Host *shost = vport_to_shost(vport); | 2419 | struct Scsi_Host *shost = vport_to_shost(vport); |
2591 | struct fc_lport *n_port = shost_priv(shost); | 2420 | struct fc_lport *n_port = shost_priv(shost); |
2592 | struct fcoe_port *port = lport_priv(n_port); | 2421 | struct fcoe_port *port = lport_priv(n_port); |
2593 | struct fcoe_interface *fcoe = port->fcoe; | 2422 | struct fcoe_interface *fcoe = port->priv; |
2594 | struct net_device *netdev = fcoe->netdev; | 2423 | struct net_device *netdev = fcoe->netdev; |
2595 | struct fc_lport *vn_port; | 2424 | struct fc_lport *vn_port; |
2596 | 2425 | ||
@@ -2630,7 +2459,7 @@ static int fcoe_vport_destroy(struct fc_vport *vport) | |||
2630 | mutex_lock(&n_port->lp_mutex); | 2459 | mutex_lock(&n_port->lp_mutex); |
2631 | list_del(&vn_port->list); | 2460 | list_del(&vn_port->list); |
2632 | mutex_unlock(&n_port->lp_mutex); | 2461 | mutex_unlock(&n_port->lp_mutex); |
2633 | schedule_work(&port->destroy_work); | 2462 | queue_work(fcoe_wq, &port->destroy_work); |
2634 | return 0; | 2463 | return 0; |
2635 | } | 2464 | } |
2636 | 2465 | ||
@@ -2734,7 +2563,7 @@ static void fcoe_set_port_id(struct fc_lport *lport, | |||
2734 | u32 port_id, struct fc_frame *fp) | 2563 | u32 port_id, struct fc_frame *fp) |
2735 | { | 2564 | { |
2736 | struct fcoe_port *port = lport_priv(lport); | 2565 | struct fcoe_port *port = lport_priv(lport); |
2737 | struct fcoe_interface *fcoe = port->fcoe; | 2566 | struct fcoe_interface *fcoe = port->priv; |
2738 | 2567 | ||
2739 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) | 2568 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) |
2740 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); | 2569 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); |
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index c69b2c56c2d1..408a6fd78fb4 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
25 | 25 | ||
26 | #define FCOE_MAX_QUEUE_DEPTH 256 | 26 | #define FCOE_MAX_QUEUE_DEPTH 256 |
27 | #define FCOE_LOW_QUEUE_DEPTH 32 | 27 | #define FCOE_MIN_QUEUE_DEPTH 32 |
28 | 28 | ||
29 | #define FCOE_WORD_TO_BYTE 4 | 29 | #define FCOE_WORD_TO_BYTE 4 |
30 | 30 | ||
@@ -40,12 +40,6 @@ | |||
40 | #define FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */ | 40 | #define FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */ |
41 | #define FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */ | 41 | #define FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */ |
42 | 42 | ||
43 | /* | ||
44 | * Max MTU for FCoE: 14 (FCoE header) + 24 (FC header) + 2112 (max FC payload) | ||
45 | * + 4 (FC CRC) + 4 (FCoE trailer) = 2158 bytes | ||
46 | */ | ||
47 | #define FCOE_MTU 2158 | ||
48 | |||
49 | unsigned int fcoe_debug_logging; | 43 | unsigned int fcoe_debug_logging; |
50 | module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); | 44 | module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); |
51 | MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); | 45 | MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); |
@@ -71,21 +65,6 @@ do { \ | |||
71 | netdev->name, ##args);) | 65 | netdev->name, ##args);) |
72 | 66 | ||
73 | /** | 67 | /** |
74 | * struct fcoe_percpu_s - The per-CPU context for FCoE receive threads | ||
75 | * @thread: The thread context | ||
76 | * @fcoe_rx_list: The queue of pending packets to process | ||
77 | * @page: The memory page for calculating frame trailer CRCs | ||
78 | * @crc_eof_offset: The offset into the CRC page pointing to available | ||
79 | * memory for a new trailer | ||
80 | */ | ||
81 | struct fcoe_percpu_s { | ||
82 | struct task_struct *thread; | ||
83 | struct sk_buff_head fcoe_rx_list; | ||
84 | struct page *crc_eof_page; | ||
85 | int crc_eof_offset; | ||
86 | }; | ||
87 | |||
88 | /** | ||
89 | * struct fcoe_interface - A FCoE interface | 68 | * struct fcoe_interface - A FCoE interface |
90 | * @list: Handle for a list of FCoE interfaces | 69 | * @list: Handle for a list of FCoE interfaces |
91 | * @netdev: The associated net device | 70 | * @netdev: The associated net device |
@@ -108,30 +87,6 @@ struct fcoe_interface { | |||
108 | struct kref kref; | 87 | struct kref kref; |
109 | }; | 88 | }; |
110 | 89 | ||
111 | /** | ||
112 | * struct fcoe_port - The FCoE private structure | ||
113 | * @fcoe: The associated fcoe interface | ||
114 | * @lport: The associated local port | ||
115 | * @fcoe_pending_queue: The pending Rx queue of skbs | ||
116 | * @fcoe_pending_queue_active: Indicates if the pending queue is active | ||
117 | * @timer: The queue timer | ||
118 | * @destroy_work: Handle for work context | ||
119 | * (to prevent RTNL deadlocks) | ||
120 | * @data_srt_addr: Source address for data | ||
121 | * | ||
122 | * An instance of this structure is to be allocated along with the | ||
123 | * Scsi_Host and libfc fc_lport structures. | ||
124 | */ | ||
125 | struct fcoe_port { | ||
126 | struct fcoe_interface *fcoe; | ||
127 | struct fc_lport *lport; | ||
128 | struct sk_buff_head fcoe_pending_queue; | ||
129 | u8 fcoe_pending_queue_active; | ||
130 | struct timer_list timer; | ||
131 | struct work_struct destroy_work; | ||
132 | u8 data_src_addr[ETH_ALEN]; | ||
133 | }; | ||
134 | |||
135 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) | 90 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) |
136 | 91 | ||
137 | /** | 92 | /** |
@@ -140,7 +95,8 @@ struct fcoe_port { | |||
140 | */ | 95 | */ |
141 | static inline struct net_device *fcoe_netdev(const struct fc_lport *lport) | 96 | static inline struct net_device *fcoe_netdev(const struct fc_lport *lport) |
142 | { | 97 | { |
143 | return ((struct fcoe_port *)lport_priv(lport))->fcoe->netdev; | 98 | return ((struct fcoe_interface *) |
99 | ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; | ||
144 | } | 100 | } |
145 | 101 | ||
146 | #endif /* _FCOE_H_ */ | 102 | #endif /* _FCOE_H_ */ |
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 625c6be25396..c93f007e702f 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
@@ -44,9 +44,7 @@ | |||
44 | #include <scsi/libfc.h> | 44 | #include <scsi/libfc.h> |
45 | #include <scsi/libfcoe.h> | 45 | #include <scsi/libfcoe.h> |
46 | 46 | ||
47 | MODULE_AUTHOR("Open-FCoE.org"); | 47 | #include "libfcoe.h" |
48 | MODULE_DESCRIPTION("FIP discovery protocol support for FCoE HBAs"); | ||
49 | MODULE_LICENSE("GPL v2"); | ||
50 | 48 | ||
51 | #define FCOE_CTLR_MIN_FKA 500 /* min keep alive (mS) */ | 49 | #define FCOE_CTLR_MIN_FKA 500 /* min keep alive (mS) */ |
52 | #define FCOE_CTLR_DEF_FKA FIP_DEF_FKA /* default keep alive (mS) */ | 50 | #define FCOE_CTLR_DEF_FKA FIP_DEF_FKA /* default keep alive (mS) */ |
@@ -66,31 +64,7 @@ static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS; | |||
66 | static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS; | 64 | static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS; |
67 | static u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS; | 65 | static u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS; |
68 | 66 | ||
69 | unsigned int libfcoe_debug_logging; | 67 | static const char * const fcoe_ctlr_states[] = { |
70 | module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); | ||
71 | MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); | ||
72 | |||
73 | #define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */ | ||
74 | #define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */ | ||
75 | |||
76 | #define LIBFCOE_CHECK_LOGGING(LEVEL, CMD) \ | ||
77 | do { \ | ||
78 | if (unlikely(libfcoe_debug_logging & LEVEL)) \ | ||
79 | do { \ | ||
80 | CMD; \ | ||
81 | } while (0); \ | ||
82 | } while (0) | ||
83 | |||
84 | #define LIBFCOE_DBG(fmt, args...) \ | ||
85 | LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \ | ||
86 | printk(KERN_INFO "libfcoe: " fmt, ##args);) | ||
87 | |||
88 | #define LIBFCOE_FIP_DBG(fip, fmt, args...) \ | ||
89 | LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING, \ | ||
90 | printk(KERN_INFO "host%d: fip: " fmt, \ | ||
91 | (fip)->lp->host->host_no, ##args);) | ||
92 | |||
93 | static const char *fcoe_ctlr_states[] = { | ||
94 | [FIP_ST_DISABLED] = "DISABLED", | 68 | [FIP_ST_DISABLED] = "DISABLED", |
95 | [FIP_ST_LINK_WAIT] = "LINK_WAIT", | 69 | [FIP_ST_LINK_WAIT] = "LINK_WAIT", |
96 | [FIP_ST_AUTO] = "AUTO", | 70 | [FIP_ST_AUTO] = "AUTO", |
@@ -308,8 +282,8 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) | |||
308 | struct fip_mac_desc mac; | 282 | struct fip_mac_desc mac; |
309 | struct fip_wwn_desc wwnn; | 283 | struct fip_wwn_desc wwnn; |
310 | struct fip_size_desc size; | 284 | struct fip_size_desc size; |
311 | } __attribute__((packed)) desc; | 285 | } __packed desc; |
312 | } __attribute__((packed)) *sol; | 286 | } __packed * sol; |
313 | u32 fcoe_size; | 287 | u32 fcoe_size; |
314 | 288 | ||
315 | skb = dev_alloc_skb(sizeof(*sol)); | 289 | skb = dev_alloc_skb(sizeof(*sol)); |
@@ -456,7 +430,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, | |||
456 | struct ethhdr eth; | 430 | struct ethhdr eth; |
457 | struct fip_header fip; | 431 | struct fip_header fip; |
458 | struct fip_mac_desc mac; | 432 | struct fip_mac_desc mac; |
459 | } __attribute__((packed)) *kal; | 433 | } __packed * kal; |
460 | struct fip_vn_desc *vn; | 434 | struct fip_vn_desc *vn; |
461 | u32 len; | 435 | u32 len; |
462 | struct fc_lport *lp; | 436 | struct fc_lport *lp; |
@@ -527,7 +501,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
527 | struct ethhdr eth; | 501 | struct ethhdr eth; |
528 | struct fip_header fip; | 502 | struct fip_header fip; |
529 | struct fip_encaps encaps; | 503 | struct fip_encaps encaps; |
530 | } __attribute__((packed)) *cap; | 504 | } __packed * cap; |
531 | struct fc_frame_header *fh; | 505 | struct fc_frame_header *fh; |
532 | struct fip_mac_desc *mac; | 506 | struct fip_mac_desc *mac; |
533 | struct fcoe_fcf *fcf; | 507 | struct fcoe_fcf *fcf; |
@@ -1819,7 +1793,7 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip, | |||
1819 | struct fip_mac_desc mac; | 1793 | struct fip_mac_desc mac; |
1820 | struct fip_wwn_desc wwnn; | 1794 | struct fip_wwn_desc wwnn; |
1821 | struct fip_vn_desc vn; | 1795 | struct fip_vn_desc vn; |
1822 | } __attribute__((packed)) *frame; | 1796 | } __packed * frame; |
1823 | struct fip_fc4_feat *ff; | 1797 | struct fip_fc4_feat *ff; |
1824 | struct fip_size_desc *size; | 1798 | struct fip_size_desc *size; |
1825 | u32 fcp_feat; | 1799 | u32 fcp_feat; |
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c new file mode 100644 index 000000000000..258684101bfd --- /dev/null +++ b/drivers/scsi/fcoe/fcoe_transport.c | |||
@@ -0,0 +1,770 @@ | |||
1 | /* | ||
2 | * Copyright(c) 2008 - 2011 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/types.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/crc32.h> | ||
27 | #include <scsi/libfcoe.h> | ||
28 | |||
29 | #include "libfcoe.h" | ||
30 | |||
31 | MODULE_AUTHOR("Open-FCoE.org"); | ||
32 | MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs"); | ||
33 | MODULE_LICENSE("GPL v2"); | ||
34 | |||
35 | static int fcoe_transport_create(const char *, struct kernel_param *); | ||
36 | static int fcoe_transport_destroy(const char *, struct kernel_param *); | ||
37 | static int fcoe_transport_show(char *buffer, const struct kernel_param *kp); | ||
38 | static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device); | ||
39 | static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device); | ||
40 | static int fcoe_transport_enable(const char *, struct kernel_param *); | ||
41 | static int fcoe_transport_disable(const char *, struct kernel_param *); | ||
42 | static int libfcoe_device_notification(struct notifier_block *notifier, | ||
43 | ulong event, void *ptr); | ||
44 | |||
45 | static LIST_HEAD(fcoe_transports); | ||
46 | static DEFINE_MUTEX(ft_mutex); | ||
47 | static LIST_HEAD(fcoe_netdevs); | ||
48 | static DEFINE_MUTEX(fn_mutex); | ||
49 | |||
50 | unsigned int libfcoe_debug_logging; | ||
51 | module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); | ||
52 | MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); | ||
53 | |||
54 | module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR); | ||
55 | __MODULE_PARM_TYPE(show, "string"); | ||
56 | MODULE_PARM_DESC(show, " Show attached FCoE transports"); | ||
57 | |||
58 | module_param_call(create, fcoe_transport_create, NULL, | ||
59 | (void *)FIP_MODE_FABRIC, S_IWUSR); | ||
60 | __MODULE_PARM_TYPE(create, "string"); | ||
61 | MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface"); | ||
62 | |||
63 | module_param_call(create_vn2vn, fcoe_transport_create, NULL, | ||
64 | (void *)FIP_MODE_VN2VN, S_IWUSR); | ||
65 | __MODULE_PARM_TYPE(create_vn2vn, "string"); | ||
66 | MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance " | ||
67 | "on an Ethernet interface"); | ||
68 | |||
69 | module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR); | ||
70 | __MODULE_PARM_TYPE(destroy, "string"); | ||
71 | MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface"); | ||
72 | |||
73 | module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR); | ||
74 | __MODULE_PARM_TYPE(enable, "string"); | ||
75 | MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface."); | ||
76 | |||
77 | module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR); | ||
78 | __MODULE_PARM_TYPE(disable, "string"); | ||
79 | MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); | ||
80 | |||
81 | /* notification function for packets from net device */ | ||
82 | static struct notifier_block libfcoe_notifier = { | ||
83 | .notifier_call = libfcoe_device_notification, | ||
84 | }; | ||
85 | |||
86 | /** | ||
87 | * fcoe_fc_crc() - Calculates the CRC for a given frame | ||
88 | * @fp: The frame to be checksumed | ||
89 | * | ||
90 | * This uses crc32() routine to calculate the CRC for a frame | ||
91 | * | ||
92 | * Return: The 32 bit CRC value | ||
93 | */ | ||
94 | u32 fcoe_fc_crc(struct fc_frame *fp) | ||
95 | { | ||
96 | struct sk_buff *skb = fp_skb(fp); | ||
97 | struct skb_frag_struct *frag; | ||
98 | unsigned char *data; | ||
99 | unsigned long off, len, clen; | ||
100 | u32 crc; | ||
101 | unsigned i; | ||
102 | |||
103 | crc = crc32(~0, skb->data, skb_headlen(skb)); | ||
104 | |||
105 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
106 | frag = &skb_shinfo(skb)->frags[i]; | ||
107 | off = frag->page_offset; | ||
108 | len = frag->size; | ||
109 | while (len > 0) { | ||
110 | clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); | ||
111 | data = kmap_atomic(frag->page + (off >> PAGE_SHIFT), | ||
112 | KM_SKB_DATA_SOFTIRQ); | ||
113 | crc = crc32(crc, data + (off & ~PAGE_MASK), clen); | ||
114 | kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ); | ||
115 | off += clen; | ||
116 | len -= clen; | ||
117 | } | ||
118 | } | ||
119 | return crc; | ||
120 | } | ||
121 | EXPORT_SYMBOL_GPL(fcoe_fc_crc); | ||
122 | |||
123 | /** | ||
124 | * fcoe_start_io() - Start FCoE I/O | ||
125 | * @skb: The packet to be transmitted | ||
126 | * | ||
127 | * This routine is called from the net device to start transmitting | ||
128 | * FCoE packets. | ||
129 | * | ||
130 | * Returns: 0 for success | ||
131 | */ | ||
132 | int fcoe_start_io(struct sk_buff *skb) | ||
133 | { | ||
134 | struct sk_buff *nskb; | ||
135 | int rc; | ||
136 | |||
137 | nskb = skb_clone(skb, GFP_ATOMIC); | ||
138 | if (!nskb) | ||
139 | return -ENOMEM; | ||
140 | rc = dev_queue_xmit(nskb); | ||
141 | if (rc != 0) | ||
142 | return rc; | ||
143 | kfree_skb(skb); | ||
144 | return 0; | ||
145 | } | ||
146 | EXPORT_SYMBOL_GPL(fcoe_start_io); | ||
147 | |||
148 | |||
149 | /** | ||
150 | * fcoe_clean_pending_queue() - Dequeue a skb and free it | ||
151 | * @lport: The local port to dequeue a skb on | ||
152 | */ | ||
153 | void fcoe_clean_pending_queue(struct fc_lport *lport) | ||
154 | { | ||
155 | struct fcoe_port *port = lport_priv(lport); | ||
156 | struct sk_buff *skb; | ||
157 | |||
158 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
159 | while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) { | ||
160 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
161 | kfree_skb(skb); | ||
162 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
163 | } | ||
164 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
165 | } | ||
166 | EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); | ||
167 | |||
168 | /** | ||
169 | * fcoe_check_wait_queue() - Attempt to clear the transmit backlog | ||
170 | * @lport: The local port whose backlog is to be cleared | ||
171 | * | ||
172 | * This empties the wait_queue, dequeues the head of the wait_queue queue | ||
173 | * and calls fcoe_start_io() for each packet. If all skb have been | ||
174 | * transmitted it returns the qlen. If an error occurs it restores | ||
175 | * wait_queue (to try again later) and returns -1. | ||
176 | * | ||
177 | * The wait_queue is used when the skb transmit fails. The failed skb | ||
178 | * will go in the wait_queue which will be emptied by the timer function or | ||
179 | * by the next skb transmit. | ||
180 | */ | ||
181 | void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb) | ||
182 | { | ||
183 | struct fcoe_port *port = lport_priv(lport); | ||
184 | int rc; | ||
185 | |||
186 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
187 | |||
188 | if (skb) | ||
189 | __skb_queue_tail(&port->fcoe_pending_queue, skb); | ||
190 | |||
191 | if (port->fcoe_pending_queue_active) | ||
192 | goto out; | ||
193 | port->fcoe_pending_queue_active = 1; | ||
194 | |||
195 | while (port->fcoe_pending_queue.qlen) { | ||
196 | /* keep qlen > 0 until fcoe_start_io succeeds */ | ||
197 | port->fcoe_pending_queue.qlen++; | ||
198 | skb = __skb_dequeue(&port->fcoe_pending_queue); | ||
199 | |||
200 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
201 | rc = fcoe_start_io(skb); | ||
202 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
203 | |||
204 | if (rc) { | ||
205 | __skb_queue_head(&port->fcoe_pending_queue, skb); | ||
206 | /* undo temporary increment above */ | ||
207 | port->fcoe_pending_queue.qlen--; | ||
208 | break; | ||
209 | } | ||
210 | /* undo temporary increment above */ | ||
211 | port->fcoe_pending_queue.qlen--; | ||
212 | } | ||
213 | |||
214 | if (port->fcoe_pending_queue.qlen < port->min_queue_depth) | ||
215 | lport->qfull = 0; | ||
216 | if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) | ||
217 | mod_timer(&port->timer, jiffies + 2); | ||
218 | port->fcoe_pending_queue_active = 0; | ||
219 | out: | ||
220 | if (port->fcoe_pending_queue.qlen > port->max_queue_depth) | ||
221 | lport->qfull = 1; | ||
222 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
223 | } | ||
224 | EXPORT_SYMBOL_GPL(fcoe_check_wait_queue); | ||
225 | |||
226 | /** | ||
227 | * fcoe_queue_timer() - The fcoe queue timer | ||
228 | * @lport: The local port | ||
229 | * | ||
230 | * Calls fcoe_check_wait_queue on timeout | ||
231 | */ | ||
232 | void fcoe_queue_timer(ulong lport) | ||
233 | { | ||
234 | fcoe_check_wait_queue((struct fc_lport *)lport, NULL); | ||
235 | } | ||
236 | EXPORT_SYMBOL_GPL(fcoe_queue_timer); | ||
237 | |||
238 | /** | ||
239 | * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC | ||
240 | * @skb: The packet to be transmitted | ||
241 | * @tlen: The total length of the trailer | ||
242 | * @fps: The fcoe context | ||
243 | * | ||
244 | * This routine allocates a page for frame trailers. The page is re-used if | ||
245 | * there is enough room left on it for the current trailer. If there isn't | ||
246 | * enough buffer left a new page is allocated for the trailer. Reference to | ||
247 | * the page from this function as well as the skbs using the page fragments | ||
248 | * ensure that the page is freed at the appropriate time. | ||
249 | * | ||
250 | * Returns: 0 for success | ||
251 | */ | ||
252 | int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen, | ||
253 | struct fcoe_percpu_s *fps) | ||
254 | { | ||
255 | struct page *page; | ||
256 | |||
257 | page = fps->crc_eof_page; | ||
258 | if (!page) { | ||
259 | page = alloc_page(GFP_ATOMIC); | ||
260 | if (!page) | ||
261 | return -ENOMEM; | ||
262 | |||
263 | fps->crc_eof_page = page; | ||
264 | fps->crc_eof_offset = 0; | ||
265 | } | ||
266 | |||
267 | get_page(page); | ||
268 | skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, | ||
269 | fps->crc_eof_offset, tlen); | ||
270 | skb->len += tlen; | ||
271 | skb->data_len += tlen; | ||
272 | skb->truesize += tlen; | ||
273 | fps->crc_eof_offset += sizeof(struct fcoe_crc_eof); | ||
274 | |||
275 | if (fps->crc_eof_offset >= PAGE_SIZE) { | ||
276 | fps->crc_eof_page = NULL; | ||
277 | fps->crc_eof_offset = 0; | ||
278 | put_page(page); | ||
279 | } | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof); | ||
284 | |||
285 | /** | ||
286 | * fcoe_transport_lookup - find an fcoe transport that matches a netdev | ||
287 | * @netdev: The netdev to look for from all attached transports | ||
288 | * | ||
289 | * Returns : ptr to the fcoe transport that supports this netdev or NULL | ||
290 | * if not found. | ||
291 | * | ||
292 | * The ft_mutex should be held when this is called | ||
293 | */ | ||
294 | static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev) | ||
295 | { | ||
296 | struct fcoe_transport *ft = NULL; | ||
297 | |||
298 | list_for_each_entry(ft, &fcoe_transports, list) | ||
299 | if (ft->match && ft->match(netdev)) | ||
300 | return ft; | ||
301 | return NULL; | ||
302 | } | ||
303 | |||
304 | /** | ||
305 | * fcoe_transport_attach - Attaches an FCoE transport | ||
306 | * @ft: The fcoe transport to be attached | ||
307 | * | ||
308 | * Returns : 0 for success | ||
309 | */ | ||
310 | int fcoe_transport_attach(struct fcoe_transport *ft) | ||
311 | { | ||
312 | int rc = 0; | ||
313 | |||
314 | mutex_lock(&ft_mutex); | ||
315 | if (ft->attached) { | ||
316 | LIBFCOE_TRANSPORT_DBG("transport %s already attached\n", | ||
317 | ft->name); | ||
318 | rc = -EEXIST; | ||
319 | goto out_attach; | ||
320 | } | ||
321 | |||
322 | /* Add default transport to the tail */ | ||
323 | if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT)) | ||
324 | list_add(&ft->list, &fcoe_transports); | ||
325 | else | ||
326 | list_add_tail(&ft->list, &fcoe_transports); | ||
327 | |||
328 | ft->attached = true; | ||
329 | LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name); | ||
330 | |||
331 | out_attach: | ||
332 | mutex_unlock(&ft_mutex); | ||
333 | return rc; | ||
334 | } | ||
335 | EXPORT_SYMBOL(fcoe_transport_attach); | ||
336 | |||
337 | /** | ||
338 | * fcoe_transport_attach - Detaches an FCoE transport | ||
339 | * @ft: The fcoe transport to be attached | ||
340 | * | ||
341 | * Returns : 0 for success | ||
342 | */ | ||
343 | int fcoe_transport_detach(struct fcoe_transport *ft) | ||
344 | { | ||
345 | int rc = 0; | ||
346 | |||
347 | mutex_lock(&ft_mutex); | ||
348 | if (!ft->attached) { | ||
349 | LIBFCOE_TRANSPORT_DBG("transport %s already detached\n", | ||
350 | ft->name); | ||
351 | rc = -ENODEV; | ||
352 | goto out_attach; | ||
353 | } | ||
354 | |||
355 | list_del(&ft->list); | ||
356 | ft->attached = false; | ||
357 | LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name); | ||
358 | |||
359 | out_attach: | ||
360 | mutex_unlock(&ft_mutex); | ||
361 | return rc; | ||
362 | |||
363 | } | ||
364 | EXPORT_SYMBOL(fcoe_transport_detach); | ||
365 | |||
366 | static int fcoe_transport_show(char *buffer, const struct kernel_param *kp) | ||
367 | { | ||
368 | int i, j; | ||
369 | struct fcoe_transport *ft = NULL; | ||
370 | |||
371 | i = j = sprintf(buffer, "Attached FCoE transports:"); | ||
372 | mutex_lock(&ft_mutex); | ||
373 | list_for_each_entry(ft, &fcoe_transports, list) { | ||
374 | i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name); | ||
375 | if (i >= PAGE_SIZE) | ||
376 | break; | ||
377 | } | ||
378 | mutex_unlock(&ft_mutex); | ||
379 | if (i == j) | ||
380 | i += snprintf(&buffer[i], IFNAMSIZ, "none"); | ||
381 | return i; | ||
382 | } | ||
383 | |||
384 | static int __init fcoe_transport_init(void) | ||
385 | { | ||
386 | register_netdevice_notifier(&libfcoe_notifier); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int __exit fcoe_transport_exit(void) | ||
391 | { | ||
392 | struct fcoe_transport *ft; | ||
393 | |||
394 | unregister_netdevice_notifier(&libfcoe_notifier); | ||
395 | mutex_lock(&ft_mutex); | ||
396 | list_for_each_entry(ft, &fcoe_transports, list) | ||
397 | printk(KERN_ERR "FCoE transport %s is still attached!\n", | ||
398 | ft->name); | ||
399 | mutex_unlock(&ft_mutex); | ||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | |||
404 | static int fcoe_add_netdev_mapping(struct net_device *netdev, | ||
405 | struct fcoe_transport *ft) | ||
406 | { | ||
407 | struct fcoe_netdev_mapping *nm; | ||
408 | |||
409 | nm = kmalloc(sizeof(*nm), GFP_KERNEL); | ||
410 | if (!nm) { | ||
411 | printk(KERN_ERR "Unable to allocate netdev_mapping"); | ||
412 | return -ENOMEM; | ||
413 | } | ||
414 | |||
415 | nm->netdev = netdev; | ||
416 | nm->ft = ft; | ||
417 | |||
418 | mutex_lock(&fn_mutex); | ||
419 | list_add(&nm->list, &fcoe_netdevs); | ||
420 | mutex_unlock(&fn_mutex); | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | |||
425 | static void fcoe_del_netdev_mapping(struct net_device *netdev) | ||
426 | { | ||
427 | struct fcoe_netdev_mapping *nm = NULL, *tmp; | ||
428 | |||
429 | mutex_lock(&fn_mutex); | ||
430 | list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) { | ||
431 | if (nm->netdev == netdev) { | ||
432 | list_del(&nm->list); | ||
433 | kfree(nm); | ||
434 | mutex_unlock(&fn_mutex); | ||
435 | return; | ||
436 | } | ||
437 | } | ||
438 | mutex_unlock(&fn_mutex); | ||
439 | } | ||
440 | |||
441 | |||
442 | /** | ||
443 | * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which | ||
444 | * it was created | ||
445 | * | ||
446 | * Returns : ptr to the fcoe transport that supports this netdev or NULL | ||
447 | * if not found. | ||
448 | * | ||
449 | * The ft_mutex should be held when this is called | ||
450 | */ | ||
451 | static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev) | ||
452 | { | ||
453 | struct fcoe_transport *ft = NULL; | ||
454 | struct fcoe_netdev_mapping *nm; | ||
455 | |||
456 | mutex_lock(&fn_mutex); | ||
457 | list_for_each_entry(nm, &fcoe_netdevs, list) { | ||
458 | if (netdev == nm->netdev) { | ||
459 | ft = nm->ft; | ||
460 | mutex_unlock(&fn_mutex); | ||
461 | return ft; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | mutex_unlock(&fn_mutex); | ||
466 | return NULL; | ||
467 | } | ||
468 | |||
469 | /** | ||
470 | * fcoe_if_to_netdev() - Parse a name buffer to get a net device | ||
471 | * @buffer: The name of the net device | ||
472 | * | ||
473 | * Returns: NULL or a ptr to net_device | ||
474 | */ | ||
475 | static struct net_device *fcoe_if_to_netdev(const char *buffer) | ||
476 | { | ||
477 | char *cp; | ||
478 | char ifname[IFNAMSIZ + 2]; | ||
479 | |||
480 | if (buffer) { | ||
481 | strlcpy(ifname, buffer, IFNAMSIZ); | ||
482 | cp = ifname + strlen(ifname); | ||
483 | while (--cp >= ifname && *cp == '\n') | ||
484 | *cp = '\0'; | ||
485 | return dev_get_by_name(&init_net, ifname); | ||
486 | } | ||
487 | return NULL; | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * libfcoe_device_notification() - Handler for net device events | ||
492 | * @notifier: The context of the notification | ||
493 | * @event: The type of event | ||
494 | * @ptr: The net device that the event was on | ||
495 | * | ||
496 | * This function is called by the Ethernet driver in case of link change event. | ||
497 | * | ||
498 | * Returns: 0 for success | ||
499 | */ | ||
500 | static int libfcoe_device_notification(struct notifier_block *notifier, | ||
501 | ulong event, void *ptr) | ||
502 | { | ||
503 | struct net_device *netdev = ptr; | ||
504 | |||
505 | switch (event) { | ||
506 | case NETDEV_UNREGISTER: | ||
507 | printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n", | ||
508 | netdev->name); | ||
509 | fcoe_del_netdev_mapping(netdev); | ||
510 | break; | ||
511 | } | ||
512 | return NOTIFY_OK; | ||
513 | } | ||
514 | |||
515 | |||
516 | /** | ||
517 | * fcoe_transport_create() - Create a fcoe interface | ||
518 | * @buffer: The name of the Ethernet interface to create on | ||
519 | * @kp: The associated kernel param | ||
520 | * | ||
521 | * Called from sysfs. This holds the ft_mutex while calling the | ||
522 | * registered fcoe transport's create function. | ||
523 | * | ||
524 | * Returns: 0 for success | ||
525 | */ | ||
526 | static int fcoe_transport_create(const char *buffer, struct kernel_param *kp) | ||
527 | { | ||
528 | int rc = -ENODEV; | ||
529 | struct net_device *netdev = NULL; | ||
530 | struct fcoe_transport *ft = NULL; | ||
531 | enum fip_state fip_mode = (enum fip_state)(long)kp->arg; | ||
532 | |||
533 | if (!mutex_trylock(&ft_mutex)) | ||
534 | return restart_syscall(); | ||
535 | |||
536 | #ifdef CONFIG_LIBFCOE_MODULE | ||
537 | /* | ||
538 | * Make sure the module has been initialized, and is not about to be | ||
539 | * removed. Module parameter sysfs files are writable before the | ||
540 | * module_init function is called and after module_exit. | ||
541 | */ | ||
542 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
543 | goto out_nodev; | ||
544 | #endif | ||
545 | |||
546 | netdev = fcoe_if_to_netdev(buffer); | ||
547 | if (!netdev) { | ||
548 | LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer); | ||
549 | goto out_nodev; | ||
550 | } | ||
551 | |||
552 | ft = fcoe_netdev_map_lookup(netdev); | ||
553 | if (ft) { | ||
554 | LIBFCOE_TRANSPORT_DBG("transport %s already has existing " | ||
555 | "FCoE instance on %s.\n", | ||
556 | ft->name, netdev->name); | ||
557 | rc = -EEXIST; | ||
558 | goto out_putdev; | ||
559 | } | ||
560 | |||
561 | ft = fcoe_transport_lookup(netdev); | ||
562 | if (!ft) { | ||
563 | LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", | ||
564 | netdev->name); | ||
565 | goto out_putdev; | ||
566 | } | ||
567 | |||
568 | rc = fcoe_add_netdev_mapping(netdev, ft); | ||
569 | if (rc) { | ||
570 | LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping " | ||
571 | "for FCoE transport %s for %s.\n", | ||
572 | ft->name, netdev->name); | ||
573 | goto out_putdev; | ||
574 | } | ||
575 | |||
576 | /* pass to transport create */ | ||
577 | rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV; | ||
578 | if (rc) | ||
579 | fcoe_del_netdev_mapping(netdev); | ||
580 | |||
581 | LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n", | ||
582 | ft->name, (rc) ? "failed" : "succeeded", | ||
583 | netdev->name); | ||
584 | |||
585 | out_putdev: | ||
586 | dev_put(netdev); | ||
587 | out_nodev: | ||
588 | mutex_unlock(&ft_mutex); | ||
589 | if (rc == -ERESTARTSYS) | ||
590 | return restart_syscall(); | ||
591 | else | ||
592 | return rc; | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * fcoe_transport_destroy() - Destroy a FCoE interface | ||
597 | * @buffer: The name of the Ethernet interface to be destroyed | ||
598 | * @kp: The associated kernel parameter | ||
599 | * | ||
600 | * Called from sysfs. This holds the ft_mutex while calling the | ||
601 | * registered fcoe transport's destroy function. | ||
602 | * | ||
603 | * Returns: 0 for success | ||
604 | */ | ||
605 | static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp) | ||
606 | { | ||
607 | int rc = -ENODEV; | ||
608 | struct net_device *netdev = NULL; | ||
609 | struct fcoe_transport *ft = NULL; | ||
610 | |||
611 | if (!mutex_trylock(&ft_mutex)) | ||
612 | return restart_syscall(); | ||
613 | |||
614 | #ifdef CONFIG_LIBFCOE_MODULE | ||
615 | /* | ||
616 | * Make sure the module has been initialized, and is not about to be | ||
617 | * removed. Module parameter sysfs files are writable before the | ||
618 | * module_init function is called and after module_exit. | ||
619 | */ | ||
620 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
621 | goto out_nodev; | ||
622 | #endif | ||
623 | |||
624 | netdev = fcoe_if_to_netdev(buffer); | ||
625 | if (!netdev) { | ||
626 | LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer); | ||
627 | goto out_nodev; | ||
628 | } | ||
629 | |||
630 | ft = fcoe_netdev_map_lookup(netdev); | ||
631 | if (!ft) { | ||
632 | LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", | ||
633 | netdev->name); | ||
634 | goto out_putdev; | ||
635 | } | ||
636 | |||
637 | /* pass to transport destroy */ | ||
638 | rc = ft->destroy ? ft->destroy(netdev) : -ENODEV; | ||
639 | fcoe_del_netdev_mapping(netdev); | ||
640 | LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n", | ||
641 | ft->name, (rc) ? "failed" : "succeeded", | ||
642 | netdev->name); | ||
643 | |||
644 | out_putdev: | ||
645 | dev_put(netdev); | ||
646 | out_nodev: | ||
647 | mutex_unlock(&ft_mutex); | ||
648 | |||
649 | if (rc == -ERESTARTSYS) | ||
650 | return restart_syscall(); | ||
651 | else | ||
652 | return rc; | ||
653 | } | ||
654 | |||
655 | /** | ||
656 | * fcoe_transport_disable() - Disables a FCoE interface | ||
657 | * @buffer: The name of the Ethernet interface to be disabled | ||
658 | * @kp: The associated kernel parameter | ||
659 | * | ||
660 | * Called from sysfs. | ||
661 | * | ||
662 | * Returns: 0 for success | ||
663 | */ | ||
664 | static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp) | ||
665 | { | ||
666 | int rc = -ENODEV; | ||
667 | struct net_device *netdev = NULL; | ||
668 | struct fcoe_transport *ft = NULL; | ||
669 | |||
670 | if (!mutex_trylock(&ft_mutex)) | ||
671 | return restart_syscall(); | ||
672 | |||
673 | #ifdef CONFIG_LIBFCOE_MODULE | ||
674 | /* | ||
675 | * Make sure the module has been initialized, and is not about to be | ||
676 | * removed. Module parameter sysfs files are writable before the | ||
677 | * module_init function is called and after module_exit. | ||
678 | */ | ||
679 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
680 | goto out_nodev; | ||
681 | #endif | ||
682 | |||
683 | netdev = fcoe_if_to_netdev(buffer); | ||
684 | if (!netdev) | ||
685 | goto out_nodev; | ||
686 | |||
687 | ft = fcoe_netdev_map_lookup(netdev); | ||
688 | if (!ft) | ||
689 | goto out_putdev; | ||
690 | |||
691 | rc = ft->disable ? ft->disable(netdev) : -ENODEV; | ||
692 | |||
693 | out_putdev: | ||
694 | dev_put(netdev); | ||
695 | out_nodev: | ||
696 | mutex_unlock(&ft_mutex); | ||
697 | |||
698 | if (rc == -ERESTARTSYS) | ||
699 | return restart_syscall(); | ||
700 | else | ||
701 | return rc; | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * fcoe_transport_enable() - Enables a FCoE interface | ||
706 | * @buffer: The name of the Ethernet interface to be enabled | ||
707 | * @kp: The associated kernel parameter | ||
708 | * | ||
709 | * Called from sysfs. | ||
710 | * | ||
711 | * Returns: 0 for success | ||
712 | */ | ||
713 | static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) | ||
714 | { | ||
715 | int rc = -ENODEV; | ||
716 | struct net_device *netdev = NULL; | ||
717 | struct fcoe_transport *ft = NULL; | ||
718 | |||
719 | if (!mutex_trylock(&ft_mutex)) | ||
720 | return restart_syscall(); | ||
721 | |||
722 | #ifdef CONFIG_LIBFCOE_MODULE | ||
723 | /* | ||
724 | * Make sure the module has been initialized, and is not about to be | ||
725 | * removed. Module parameter sysfs files are writable before the | ||
726 | * module_init function is called and after module_exit. | ||
727 | */ | ||
728 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
729 | goto out_nodev; | ||
730 | #endif | ||
731 | |||
732 | netdev = fcoe_if_to_netdev(buffer); | ||
733 | if (!netdev) | ||
734 | goto out_nodev; | ||
735 | |||
736 | ft = fcoe_netdev_map_lookup(netdev); | ||
737 | if (!ft) | ||
738 | goto out_putdev; | ||
739 | |||
740 | rc = ft->enable ? ft->enable(netdev) : -ENODEV; | ||
741 | |||
742 | out_putdev: | ||
743 | dev_put(netdev); | ||
744 | out_nodev: | ||
745 | mutex_unlock(&ft_mutex); | ||
746 | if (rc == -ERESTARTSYS) | ||
747 | return restart_syscall(); | ||
748 | else | ||
749 | return rc; | ||
750 | } | ||
751 | |||
752 | /** | ||
753 | * libfcoe_init() - Initialization routine for libfcoe.ko | ||
754 | */ | ||
755 | static int __init libfcoe_init(void) | ||
756 | { | ||
757 | fcoe_transport_init(); | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | module_init(libfcoe_init); | ||
762 | |||
763 | /** | ||
764 | * libfcoe_exit() - Tear down libfcoe.ko | ||
765 | */ | ||
766 | static void __exit libfcoe_exit(void) | ||
767 | { | ||
768 | fcoe_transport_exit(); | ||
769 | } | ||
770 | module_exit(libfcoe_exit); | ||
diff --git a/drivers/scsi/fcoe/libfcoe.h b/drivers/scsi/fcoe/libfcoe.h new file mode 100644 index 000000000000..6af5fc3a17d8 --- /dev/null +++ b/drivers/scsi/fcoe/libfcoe.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #ifndef _FCOE_LIBFCOE_H_ | ||
2 | #define _FCOE_LIBFCOE_H_ | ||
3 | |||
4 | extern unsigned int libfcoe_debug_logging; | ||
5 | #define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */ | ||
6 | #define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */ | ||
7 | #define LIBFCOE_TRANSPORT_LOGGING 0x04 /* FCoE transport logging */ | ||
8 | |||
9 | #define LIBFCOE_CHECK_LOGGING(LEVEL, CMD) \ | ||
10 | do { \ | ||
11 | if (unlikely(libfcoe_debug_logging & LEVEL)) \ | ||
12 | do { \ | ||
13 | CMD; \ | ||
14 | } while (0); \ | ||
15 | } while (0) | ||
16 | |||
17 | #define LIBFCOE_DBG(fmt, args...) \ | ||
18 | LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \ | ||
19 | printk(KERN_INFO "libfcoe: " fmt, ##args);) | ||
20 | |||
21 | #define LIBFCOE_FIP_DBG(fip, fmt, args...) \ | ||
22 | LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING, \ | ||
23 | printk(KERN_INFO "host%d: fip: " fmt, \ | ||
24 | (fip)->lp->host->host_no, ##args);) | ||
25 | |||
26 | #define LIBFCOE_TRANSPORT_DBG(fmt, args...) \ | ||
27 | LIBFCOE_CHECK_LOGGING(LIBFCOE_TRANSPORT_LOGGING, \ | ||
28 | printk(KERN_INFO "%s: " fmt, \ | ||
29 | __func__, ##args);) | ||
30 | |||
31 | #endif /* _FCOE_LIBFCOE_H_ */ | ||