diff options
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 1522 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe.h | 82 | ||||
-rw-r--r-- | drivers/scsi/fcoe/libfcoe.c | 436 |
3 files changed, 1354 insertions, 686 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 704b8e034946..f01b9b44e8aa 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/if_ether.h> | 26 | #include <linux/if_ether.h> |
27 | #include <linux/if_vlan.h> | 27 | #include <linux/if_vlan.h> |
28 | #include <linux/crc32.h> | 28 | #include <linux/crc32.h> |
29 | #include <linux/slab.h> | ||
29 | #include <linux/cpu.h> | 30 | #include <linux/cpu.h> |
30 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
31 | #include <linux/sysfs.h> | 32 | #include <linux/sysfs.h> |
@@ -66,14 +67,14 @@ LIST_HEAD(fcoe_hostlist); | |||
66 | DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); | 67 | DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); |
67 | 68 | ||
68 | /* Function Prototypes */ | 69 | /* Function Prototypes */ |
69 | static int fcoe_reset(struct Scsi_Host *shost); | 70 | static int fcoe_reset(struct Scsi_Host *); |
70 | static int fcoe_xmit(struct fc_lport *, struct fc_frame *); | 71 | static int fcoe_xmit(struct fc_lport *, struct fc_frame *); |
71 | static int fcoe_rcv(struct sk_buff *, struct net_device *, | 72 | static int fcoe_rcv(struct sk_buff *, struct net_device *, |
72 | struct packet_type *, struct net_device *); | 73 | struct packet_type *, struct net_device *); |
73 | static int fcoe_percpu_receive_thread(void *arg); | 74 | static int fcoe_percpu_receive_thread(void *); |
74 | static void fcoe_clean_pending_queue(struct fc_lport *lp); | 75 | static void fcoe_clean_pending_queue(struct fc_lport *); |
75 | static void fcoe_percpu_clean(struct fc_lport *lp); | 76 | static void fcoe_percpu_clean(struct fc_lport *); |
76 | static int fcoe_link_ok(struct fc_lport *lp); | 77 | static int fcoe_link_ok(struct fc_lport *); |
77 | 78 | ||
78 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); | 79 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); |
79 | static int fcoe_hostlist_add(const struct fc_lport *); | 80 | static int fcoe_hostlist_add(const struct fc_lport *); |
@@ -82,15 +83,77 @@ static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *); | |||
82 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); | 83 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); |
83 | static void fcoe_dev_setup(void); | 84 | static void fcoe_dev_setup(void); |
84 | static void fcoe_dev_cleanup(void); | 85 | static void fcoe_dev_cleanup(void); |
85 | static struct fcoe_interface * | 86 | static struct fcoe_interface |
86 | fcoe_hostlist_lookup_port(const struct net_device *dev); | 87 | *fcoe_hostlist_lookup_port(const struct net_device *); |
88 | |||
89 | static int fcoe_fip_recv(struct sk_buff *, struct net_device *, | ||
90 | struct packet_type *, struct net_device *); | ||
91 | |||
92 | static void fcoe_fip_send(struct fcoe_ctlr *, struct sk_buff *); | ||
93 | static void fcoe_update_src_mac(struct fc_lport *, u8 *); | ||
94 | static u8 *fcoe_get_src_mac(struct fc_lport *); | ||
95 | static void fcoe_destroy_work(struct work_struct *); | ||
96 | |||
97 | static int fcoe_ddp_setup(struct fc_lport *, u16, struct scatterlist *, | ||
98 | unsigned int); | ||
99 | static int fcoe_ddp_done(struct fc_lport *, u16); | ||
100 | |||
101 | static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *); | ||
102 | |||
103 | static int fcoe_create(const char *, struct kernel_param *); | ||
104 | static int fcoe_destroy(const char *, struct kernel_param *); | ||
105 | static int fcoe_enable(const char *, struct kernel_param *); | ||
106 | static int fcoe_disable(const char *, struct kernel_param *); | ||
107 | |||
108 | static struct fc_seq *fcoe_elsct_send(struct fc_lport *, | ||
109 | u32 did, struct fc_frame *, | ||
110 | unsigned int op, | ||
111 | void (*resp)(struct fc_seq *, | ||
112 | struct fc_frame *, | ||
113 | void *), | ||
114 | void *, u32 timeout); | ||
115 | static void fcoe_recv_frame(struct sk_buff *skb); | ||
87 | 116 | ||
88 | /* notification function from net device */ | 117 | static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *); |
118 | |||
119 | module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); | ||
120 | __MODULE_PARM_TYPE(create, "string"); | ||
121 | MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface"); | ||
122 | module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); | ||
123 | __MODULE_PARM_TYPE(destroy, "string"); | ||
124 | MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface"); | ||
125 | module_param_call(enable, fcoe_enable, NULL, NULL, S_IWUSR); | ||
126 | __MODULE_PARM_TYPE(enable, "string"); | ||
127 | MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface."); | ||
128 | module_param_call(disable, fcoe_disable, NULL, NULL, S_IWUSR); | ||
129 | __MODULE_PARM_TYPE(disable, "string"); | ||
130 | MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); | ||
131 | |||
132 | /* notification function for packets from net device */ | ||
89 | static struct notifier_block fcoe_notifier = { | 133 | static struct notifier_block fcoe_notifier = { |
90 | .notifier_call = fcoe_device_notification, | 134 | .notifier_call = fcoe_device_notification, |
91 | }; | 135 | }; |
92 | 136 | ||
93 | static struct scsi_transport_template *scsi_transport_fcoe_sw; | 137 | /* notification function for CPU hotplug events */ |
138 | static struct notifier_block fcoe_cpu_notifier = { | ||
139 | .notifier_call = fcoe_cpu_callback, | ||
140 | }; | ||
141 | |||
142 | static struct scsi_transport_template *fcoe_transport_template; | ||
143 | static struct scsi_transport_template *fcoe_vport_transport_template; | ||
144 | |||
145 | static int fcoe_vport_destroy(struct fc_vport *); | ||
146 | static int fcoe_vport_create(struct fc_vport *, bool disabled); | ||
147 | static int fcoe_vport_disable(struct fc_vport *, bool disable); | ||
148 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); | ||
149 | |||
150 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | ||
151 | .frame_send = fcoe_xmit, | ||
152 | .ddp_setup = fcoe_ddp_setup, | ||
153 | .ddp_done = fcoe_ddp_done, | ||
154 | .elsct_send = fcoe_elsct_send, | ||
155 | .get_lesb = fcoe_get_lesb, | ||
156 | }; | ||
94 | 157 | ||
95 | struct fc_function_template fcoe_transport_function = { | 158 | struct fc_function_template fcoe_transport_function = { |
96 | .show_host_node_name = 1, | 159 | .show_host_node_name = 1, |
@@ -123,6 +186,48 @@ struct fc_function_template fcoe_transport_function = { | |||
123 | .issue_fc_host_lip = fcoe_reset, | 186 | .issue_fc_host_lip = fcoe_reset, |
124 | 187 | ||
125 | .terminate_rport_io = fc_rport_terminate_io, | 188 | .terminate_rport_io = fc_rport_terminate_io, |
189 | |||
190 | .vport_create = fcoe_vport_create, | ||
191 | .vport_delete = fcoe_vport_destroy, | ||
192 | .vport_disable = fcoe_vport_disable, | ||
193 | .set_vport_symbolic_name = fcoe_set_vport_symbolic_name, | ||
194 | |||
195 | .bsg_request = fc_lport_bsg_request, | ||
196 | }; | ||
197 | |||
198 | struct fc_function_template fcoe_vport_transport_function = { | ||
199 | .show_host_node_name = 1, | ||
200 | .show_host_port_name = 1, | ||
201 | .show_host_supported_classes = 1, | ||
202 | .show_host_supported_fc4s = 1, | ||
203 | .show_host_active_fc4s = 1, | ||
204 | .show_host_maxframe_size = 1, | ||
205 | |||
206 | .show_host_port_id = 1, | ||
207 | .show_host_supported_speeds = 1, | ||
208 | .get_host_speed = fc_get_host_speed, | ||
209 | .show_host_speed = 1, | ||
210 | .show_host_port_type = 1, | ||
211 | .get_host_port_state = fc_get_host_port_state, | ||
212 | .show_host_port_state = 1, | ||
213 | .show_host_symbolic_name = 1, | ||
214 | |||
215 | .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv), | ||
216 | .show_rport_maxframe_size = 1, | ||
217 | .show_rport_supported_classes = 1, | ||
218 | |||
219 | .show_host_fabric_name = 1, | ||
220 | .show_starget_node_name = 1, | ||
221 | .show_starget_port_name = 1, | ||
222 | .show_starget_port_id = 1, | ||
223 | .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo, | ||
224 | .show_rport_dev_loss_tmo = 1, | ||
225 | .get_fc_host_stats = fc_get_host_stats, | ||
226 | .issue_fc_host_lip = fcoe_reset, | ||
227 | |||
228 | .terminate_rport_io = fc_rport_terminate_io, | ||
229 | |||
230 | .bsg_request = fc_lport_bsg_request, | ||
126 | }; | 231 | }; |
127 | 232 | ||
128 | static struct scsi_host_template fcoe_shost_template = { | 233 | static struct scsi_host_template fcoe_shost_template = { |
@@ -137,20 +242,17 @@ static struct scsi_host_template fcoe_shost_template = { | |||
137 | .change_queue_depth = fc_change_queue_depth, | 242 | .change_queue_depth = fc_change_queue_depth, |
138 | .change_queue_type = fc_change_queue_type, | 243 | .change_queue_type = fc_change_queue_type, |
139 | .this_id = -1, | 244 | .this_id = -1, |
140 | .cmd_per_lun = 32, | 245 | .cmd_per_lun = 3, |
141 | .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS, | 246 | .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS, |
142 | .use_clustering = ENABLE_CLUSTERING, | 247 | .use_clustering = ENABLE_CLUSTERING, |
143 | .sg_tablesize = SG_ALL, | 248 | .sg_tablesize = SG_ALL, |
144 | .max_sectors = 0xffff, | 249 | .max_sectors = 0xffff, |
145 | }; | 250 | }; |
146 | 251 | ||
147 | static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, | ||
148 | struct packet_type *ptype, | ||
149 | struct net_device *orig_dev); | ||
150 | /** | 252 | /** |
151 | * fcoe_interface_setup() | 253 | * fcoe_interface_setup() - Setup a FCoE interface |
152 | * @fcoe: new fcoe_interface | 254 | * @fcoe: The new FCoE interface |
153 | * @netdev : ptr to the associated netdevice struct | 255 | * @netdev: The net device that the fcoe interface is on |
154 | * | 256 | * |
155 | * Returns : 0 for success | 257 | * Returns : 0 for success |
156 | * Locking: must be called with the RTNL mutex held | 258 | * Locking: must be called with the RTNL mutex held |
@@ -160,23 +262,36 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, | |||
160 | { | 262 | { |
161 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 263 | struct fcoe_ctlr *fip = &fcoe->ctlr; |
162 | struct netdev_hw_addr *ha; | 264 | struct netdev_hw_addr *ha; |
265 | struct net_device *real_dev; | ||
163 | u8 flogi_maddr[ETH_ALEN]; | 266 | u8 flogi_maddr[ETH_ALEN]; |
267 | const struct net_device_ops *ops; | ||
164 | 268 | ||
165 | fcoe->netdev = netdev; | 269 | fcoe->netdev = netdev; |
166 | 270 | ||
271 | /* Let LLD initialize for FCoE */ | ||
272 | ops = netdev->netdev_ops; | ||
273 | if (ops->ndo_fcoe_enable) { | ||
274 | if (ops->ndo_fcoe_enable(netdev)) | ||
275 | FCOE_NETDEV_DBG(netdev, "Failed to enable FCoE" | ||
276 | " specific feature for LLD.\n"); | ||
277 | } | ||
278 | |||
167 | /* Do not support for bonding device */ | 279 | /* Do not support for bonding device */ |
168 | if ((netdev->priv_flags & IFF_MASTER_ALB) || | 280 | if ((netdev->priv_flags & IFF_MASTER_ALB) || |
169 | (netdev->priv_flags & IFF_SLAVE_INACTIVE) || | 281 | (netdev->priv_flags & IFF_SLAVE_INACTIVE) || |
170 | (netdev->priv_flags & IFF_MASTER_8023AD)) { | 282 | (netdev->priv_flags & IFF_MASTER_8023AD)) { |
283 | FCOE_NETDEV_DBG(netdev, "Bonded interfaces not supported\n"); | ||
171 | return -EOPNOTSUPP; | 284 | return -EOPNOTSUPP; |
172 | } | 285 | } |
173 | 286 | ||
174 | /* look for SAN MAC address, if multiple SAN MACs exist, only | 287 | /* look for SAN MAC address, if multiple SAN MACs exist, only |
175 | * use the first one for SPMA */ | 288 | * use the first one for SPMA */ |
289 | real_dev = (netdev->priv_flags & IFF_802_1Q_VLAN) ? | ||
290 | vlan_dev_real_dev(netdev) : netdev; | ||
176 | rcu_read_lock(); | 291 | rcu_read_lock(); |
177 | for_each_dev_addr(netdev, ha) { | 292 | for_each_dev_addr(real_dev, ha) { |
178 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && | 293 | if ((ha->type == NETDEV_HW_ADDR_T_SAN) && |
179 | (is_valid_ether_addr(fip->ctl_src_addr))) { | 294 | (is_valid_ether_addr(ha->addr))) { |
180 | memcpy(fip->ctl_src_addr, ha->addr, ETH_ALEN); | 295 | memcpy(fip->ctl_src_addr, ha->addr, ETH_ALEN); |
181 | fip->spma = 1; | 296 | fip->spma = 1; |
182 | break; | 297 | break; |
@@ -216,19 +331,16 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, | |||
216 | return 0; | 331 | return 0; |
217 | } | 332 | } |
218 | 333 | ||
219 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb); | ||
220 | static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new); | ||
221 | static void fcoe_destroy_work(struct work_struct *work); | ||
222 | |||
223 | /** | 334 | /** |
224 | * fcoe_interface_create() | 335 | * fcoe_interface_create() - Create a FCoE interface on a net device |
225 | * @netdev: network interface | 336 | * @netdev: The net device to create the FCoE interface on |
226 | * | 337 | * |
227 | * Returns: pointer to a struct fcoe_interface or NULL on error | 338 | * Returns: pointer to a struct fcoe_interface or NULL on error |
228 | */ | 339 | */ |
229 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) | 340 | static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) |
230 | { | 341 | { |
231 | struct fcoe_interface *fcoe; | 342 | struct fcoe_interface *fcoe; |
343 | int err; | ||
232 | 344 | ||
233 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); | 345 | fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); |
234 | if (!fcoe) { | 346 | if (!fcoe) { |
@@ -245,15 +357,22 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) | |||
245 | fcoe_ctlr_init(&fcoe->ctlr); | 357 | fcoe_ctlr_init(&fcoe->ctlr); |
246 | fcoe->ctlr.send = fcoe_fip_send; | 358 | fcoe->ctlr.send = fcoe_fip_send; |
247 | fcoe->ctlr.update_mac = fcoe_update_src_mac; | 359 | fcoe->ctlr.update_mac = fcoe_update_src_mac; |
360 | fcoe->ctlr.get_src_addr = fcoe_get_src_mac; | ||
248 | 361 | ||
249 | fcoe_interface_setup(fcoe, netdev); | 362 | err = fcoe_interface_setup(fcoe, netdev); |
363 | if (err) { | ||
364 | fcoe_ctlr_destroy(&fcoe->ctlr); | ||
365 | kfree(fcoe); | ||
366 | dev_put(netdev); | ||
367 | return NULL; | ||
368 | } | ||
250 | 369 | ||
251 | return fcoe; | 370 | return fcoe; |
252 | } | 371 | } |
253 | 372 | ||
254 | /** | 373 | /** |
255 | * fcoe_interface_cleanup() - clean up netdev configurations | 374 | * fcoe_interface_cleanup() - Clean up a FCoE interface |
256 | * @fcoe: | 375 | * @fcoe: The FCoE interface to be cleaned up |
257 | * | 376 | * |
258 | * Caller must be holding the RTNL mutex | 377 | * Caller must be holding the RTNL mutex |
259 | */ | 378 | */ |
@@ -262,6 +381,7 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | |||
262 | struct net_device *netdev = fcoe->netdev; | 381 | struct net_device *netdev = fcoe->netdev; |
263 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 382 | struct fcoe_ctlr *fip = &fcoe->ctlr; |
264 | u8 flogi_maddr[ETH_ALEN]; | 383 | u8 flogi_maddr[ETH_ALEN]; |
384 | const struct net_device_ops *ops; | ||
265 | 385 | ||
266 | /* | 386 | /* |
267 | * Don't listen for Ethernet packets anymore. | 387 | * Don't listen for Ethernet packets anymore. |
@@ -276,16 +396,22 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) | |||
276 | /* Delete secondary MAC addresses */ | 396 | /* Delete secondary MAC addresses */ |
277 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); | 397 | memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); |
278 | dev_unicast_delete(netdev, flogi_maddr); | 398 | dev_unicast_delete(netdev, flogi_maddr); |
279 | if (!is_zero_ether_addr(fip->data_src_addr)) | ||
280 | dev_unicast_delete(netdev, fip->data_src_addr); | ||
281 | if (fip->spma) | 399 | if (fip->spma) |
282 | dev_unicast_delete(netdev, fip->ctl_src_addr); | 400 | dev_unicast_delete(netdev, fip->ctl_src_addr); |
283 | dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); | 401 | dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); |
402 | |||
403 | /* Tell the LLD we are done w/ FCoE */ | ||
404 | ops = netdev->netdev_ops; | ||
405 | if (ops->ndo_fcoe_disable) { | ||
406 | if (ops->ndo_fcoe_disable(netdev)) | ||
407 | FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE" | ||
408 | " specific feature for LLD.\n"); | ||
409 | } | ||
284 | } | 410 | } |
285 | 411 | ||
286 | /** | 412 | /** |
287 | * fcoe_interface_release() - fcoe_port kref release function | 413 | * fcoe_interface_release() - fcoe_port kref release function |
288 | * @kref: embedded reference count in an fcoe_interface struct | 414 | * @kref: Embedded reference count in an fcoe_interface struct |
289 | */ | 415 | */ |
290 | static void fcoe_interface_release(struct kref *kref) | 416 | static void fcoe_interface_release(struct kref *kref) |
291 | { | 417 | { |
@@ -301,8 +427,8 @@ static void fcoe_interface_release(struct kref *kref) | |||
301 | } | 427 | } |
302 | 428 | ||
303 | /** | 429 | /** |
304 | * fcoe_interface_get() | 430 | * fcoe_interface_get() - Get a reference to a FCoE interface |
305 | * @fcoe: | 431 | * @fcoe: The FCoE interface to be held |
306 | */ | 432 | */ |
307 | static inline void fcoe_interface_get(struct fcoe_interface *fcoe) | 433 | static inline void fcoe_interface_get(struct fcoe_interface *fcoe) |
308 | { | 434 | { |
@@ -310,8 +436,8 @@ static inline void fcoe_interface_get(struct fcoe_interface *fcoe) | |||
310 | } | 436 | } |
311 | 437 | ||
312 | /** | 438 | /** |
313 | * fcoe_interface_put() | 439 | * fcoe_interface_put() - Put a reference to a FCoE interface |
314 | * @fcoe: | 440 | * @fcoe: The FCoE interface to be released |
315 | */ | 441 | */ |
316 | static inline void fcoe_interface_put(struct fcoe_interface *fcoe) | 442 | static inline void fcoe_interface_put(struct fcoe_interface *fcoe) |
317 | { | 443 | { |
@@ -319,15 +445,16 @@ static inline void fcoe_interface_put(struct fcoe_interface *fcoe) | |||
319 | } | 445 | } |
320 | 446 | ||
321 | /** | 447 | /** |
322 | * fcoe_fip_recv - handle a received FIP frame. | 448 | * fcoe_fip_recv() - Handler for received FIP frames |
323 | * @skb: the receive skb | 449 | * @skb: The receive skb |
324 | * @dev: associated &net_device | 450 | * @netdev: The associated net device |
325 | * @ptype: the &packet_type structure which was used to register this handler. | 451 | * @ptype: The packet_type structure which was used to register this handler |
326 | * @orig_dev: original receive &net_device, in case @dev is a bond. | 452 | * @orig_dev: The original net_device the the skb was received on. |
453 | * (in case dev is a bond) | ||
327 | * | 454 | * |
328 | * Returns: 0 for success | 455 | * Returns: 0 for success |
329 | */ | 456 | */ |
330 | static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, | 457 | static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev, |
331 | struct packet_type *ptype, | 458 | struct packet_type *ptype, |
332 | struct net_device *orig_dev) | 459 | struct net_device *orig_dev) |
333 | { | 460 | { |
@@ -339,9 +466,9 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, | |||
339 | } | 466 | } |
340 | 467 | ||
341 | /** | 468 | /** |
342 | * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame. | 469 | * fcoe_fip_send() - Send an Ethernet-encapsulated FIP frame |
343 | * @fip: FCoE controller. | 470 | * @fip: The FCoE controller |
344 | * @skb: FIP Packet. | 471 | * @skb: The FIP packet to be sent |
345 | */ | 472 | */ |
346 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | 473 | static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) |
347 | { | 474 | { |
@@ -350,88 +477,118 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
350 | } | 477 | } |
351 | 478 | ||
352 | /** | 479 | /** |
353 | * fcoe_update_src_mac() - Update Ethernet MAC filters. | 480 | * fcoe_update_src_mac() - Update the Ethernet MAC filters |
354 | * @fip: FCoE controller. | 481 | * @lport: The local port to update the source MAC on |
355 | * @old: Unicast MAC address to delete if the MAC is non-zero. | 482 | * @addr: Unicast MAC address to add |
356 | * @new: Unicast MAC address to add. | ||
357 | * | 483 | * |
358 | * Remove any previously-set unicast MAC filter. | 484 | * Remove any previously-set unicast MAC filter. |
359 | * Add secondary FCoE MAC address filter for our OUI. | 485 | * Add secondary FCoE MAC address filter for our OUI. |
360 | */ | 486 | */ |
361 | static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) | 487 | static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) |
362 | { | 488 | { |
363 | struct fcoe_interface *fcoe; | 489 | struct fcoe_port *port = lport_priv(lport); |
490 | struct fcoe_interface *fcoe = port->fcoe; | ||
364 | 491 | ||
365 | fcoe = fcoe_from_ctlr(fip); | ||
366 | rtnl_lock(); | 492 | rtnl_lock(); |
367 | if (!is_zero_ether_addr(old)) | 493 | if (!is_zero_ether_addr(port->data_src_addr)) |
368 | dev_unicast_delete(fcoe->netdev, old); | 494 | dev_unicast_delete(fcoe->netdev, port->data_src_addr); |
369 | dev_unicast_add(fcoe->netdev, new); | 495 | if (!is_zero_ether_addr(addr)) |
496 | dev_unicast_add(fcoe->netdev, addr); | ||
497 | memcpy(port->data_src_addr, addr, ETH_ALEN); | ||
370 | rtnl_unlock(); | 498 | rtnl_unlock(); |
371 | } | 499 | } |
372 | 500 | ||
373 | /** | 501 | /** |
374 | * fcoe_lport_config() - sets up the fc_lport | 502 | * fcoe_get_src_mac() - return the Ethernet source address for an lport |
375 | * @lp: ptr to the fc_lport | 503 | * @lport: libfc lport |
504 | */ | ||
505 | static u8 *fcoe_get_src_mac(struct fc_lport *lport) | ||
506 | { | ||
507 | struct fcoe_port *port = lport_priv(lport); | ||
508 | |||
509 | return port->data_src_addr; | ||
510 | } | ||
511 | |||
512 | /** | ||
513 | * fcoe_lport_config() - Set up a local port | ||
514 | * @lport: The local port to be setup | ||
376 | * | 515 | * |
377 | * Returns: 0 for success | 516 | * Returns: 0 for success |
378 | */ | 517 | */ |
379 | static int fcoe_lport_config(struct fc_lport *lp) | 518 | static int fcoe_lport_config(struct fc_lport *lport) |
380 | { | 519 | { |
381 | lp->link_up = 0; | 520 | lport->link_up = 0; |
382 | lp->qfull = 0; | 521 | lport->qfull = 0; |
383 | lp->max_retry_count = 3; | 522 | lport->max_retry_count = 3; |
384 | lp->max_rport_retry_count = 3; | 523 | lport->max_rport_retry_count = 3; |
385 | lp->e_d_tov = 2 * 1000; /* FC-FS default */ | 524 | lport->e_d_tov = 2 * 1000; /* FC-FS default */ |
386 | lp->r_a_tov = 2 * 2 * 1000; | 525 | lport->r_a_tov = 2 * 2 * 1000; |
387 | lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | | 526 | lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS | |
388 | FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL); | 527 | FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL); |
389 | 528 | lport->does_npiv = 1; | |
390 | fc_lport_init_stats(lp); | 529 | |
530 | fc_lport_init_stats(lport); | ||
391 | 531 | ||
392 | /* lport fc_lport related configuration */ | 532 | /* lport fc_lport related configuration */ |
393 | fc_lport_config(lp); | 533 | fc_lport_config(lport); |
394 | 534 | ||
395 | /* offload related configuration */ | 535 | /* offload related configuration */ |
396 | lp->crc_offload = 0; | 536 | lport->crc_offload = 0; |
397 | lp->seq_offload = 0; | 537 | lport->seq_offload = 0; |
398 | lp->lro_enabled = 0; | 538 | lport->lro_enabled = 0; |
399 | lp->lro_xid = 0; | 539 | lport->lro_xid = 0; |
400 | lp->lso_max = 0; | 540 | lport->lso_max = 0; |
401 | 541 | ||
402 | return 0; | 542 | return 0; |
403 | } | 543 | } |
404 | 544 | ||
405 | /** | 545 | /** |
406 | * fcoe_queue_timer() - fcoe queue timer | 546 | * fcoe_queue_timer() - The fcoe queue timer |
407 | * @lp: the fc_lport pointer | 547 | * @lport: The local port |
408 | * | 548 | * |
409 | * Calls fcoe_check_wait_queue on timeout | 549 | * Calls fcoe_check_wait_queue on timeout |
550 | */ | ||
551 | static void fcoe_queue_timer(ulong lport) | ||
552 | { | ||
553 | fcoe_check_wait_queue((struct fc_lport *)lport, NULL); | ||
554 | } | ||
555 | |||
556 | /** | ||
557 | * fcoe_get_wwn() - Get the world wide name from LLD if it supports it | ||
558 | * @netdev: the associated net device | ||
559 | * @wwn: the output WWN | ||
560 | * @type: the type of WWN (WWPN or WWNN) | ||
410 | * | 561 | * |
562 | * Returns: 0 for success | ||
411 | */ | 563 | */ |
412 | static void fcoe_queue_timer(ulong lp) | 564 | static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type) |
413 | { | 565 | { |
414 | fcoe_check_wait_queue((struct fc_lport *)lp, NULL); | 566 | const struct net_device_ops *ops = netdev->netdev_ops; |
567 | |||
568 | if (ops->ndo_fcoe_get_wwn) | ||
569 | return ops->ndo_fcoe_get_wwn(netdev, wwn, type); | ||
570 | return -EINVAL; | ||
415 | } | 571 | } |
416 | 572 | ||
417 | /** | 573 | /** |
418 | * fcoe_netdev_config() - Set up netdev for SW FCoE | 574 | * fcoe_netdev_config() - Set up net devive for SW FCoE |
419 | * @lp : ptr to the fc_lport | 575 | * @lport: The local port that is associated with the net device |
420 | * @netdev : ptr to the associated netdevice struct | 576 | * @netdev: The associated net device |
421 | * | 577 | * |
422 | * Must be called after fcoe_lport_config() as it will use lport mutex | 578 | * Must be called after fcoe_lport_config() as it will use local port mutex |
423 | * | 579 | * |
424 | * Returns : 0 for success | 580 | * Returns: 0 for success |
425 | */ | 581 | */ |
426 | static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | 582 | static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) |
427 | { | 583 | { |
428 | u32 mfs; | 584 | u32 mfs; |
429 | u64 wwnn, wwpn; | 585 | u64 wwnn, wwpn; |
430 | struct fcoe_interface *fcoe; | 586 | struct fcoe_interface *fcoe; |
431 | struct fcoe_port *port; | 587 | struct fcoe_port *port; |
588 | int vid = 0; | ||
432 | 589 | ||
433 | /* Setup lport private data to point to fcoe softc */ | 590 | /* Setup lport private data to point to fcoe softc */ |
434 | port = lport_priv(lp); | 591 | port = lport_priv(lport); |
435 | fcoe = port->fcoe; | 592 | fcoe = port->fcoe; |
436 | 593 | ||
437 | /* | 594 | /* |
@@ -439,86 +596,116 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) | |||
439 | * user-configured limit. If the MFS is too low, fcoe_link_ok() | 596 | * user-configured limit. If the MFS is too low, fcoe_link_ok() |
440 | * will return 0, so do this first. | 597 | * will return 0, so do this first. |
441 | */ | 598 | */ |
442 | mfs = netdev->mtu - (sizeof(struct fcoe_hdr) + | 599 | mfs = netdev->mtu; |
443 | sizeof(struct fcoe_crc_eof)); | 600 | if (netdev->features & NETIF_F_FCOE_MTU) { |
444 | if (fc_set_mfs(lp, mfs)) | 601 | mfs = FCOE_MTU; |
602 | FCOE_NETDEV_DBG(netdev, "Supports FCOE_MTU of %d bytes\n", mfs); | ||
603 | } | ||
604 | mfs -= (sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof)); | ||
605 | if (fc_set_mfs(lport, mfs)) | ||
445 | return -EINVAL; | 606 | return -EINVAL; |
446 | 607 | ||
447 | /* offload features support */ | 608 | /* offload features support */ |
448 | if (netdev->features & NETIF_F_SG) | 609 | if (netdev->features & NETIF_F_SG) |
449 | lp->sg_supp = 1; | 610 | lport->sg_supp = 1; |
450 | 611 | ||
451 | if (netdev->features & NETIF_F_FCOE_CRC) { | 612 | if (netdev->features & NETIF_F_FCOE_CRC) { |
452 | lp->crc_offload = 1; | 613 | lport->crc_offload = 1; |
453 | FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n"); | 614 | FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n"); |
454 | } | 615 | } |
455 | if (netdev->features & NETIF_F_FSO) { | 616 | if (netdev->features & NETIF_F_FSO) { |
456 | lp->seq_offload = 1; | 617 | lport->seq_offload = 1; |
457 | lp->lso_max = netdev->gso_max_size; | 618 | lport->lso_max = netdev->gso_max_size; |
458 | FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n", | 619 | FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n", |
459 | lp->lso_max); | 620 | lport->lso_max); |
460 | } | 621 | } |
461 | if (netdev->fcoe_ddp_xid) { | 622 | if (netdev->fcoe_ddp_xid) { |
462 | lp->lro_enabled = 1; | 623 | lport->lro_enabled = 1; |
463 | lp->lro_xid = netdev->fcoe_ddp_xid; | 624 | lport->lro_xid = netdev->fcoe_ddp_xid; |
464 | FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n", | 625 | FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n", |
465 | lp->lro_xid); | 626 | lport->lro_xid); |
466 | } | 627 | } |
467 | skb_queue_head_init(&port->fcoe_pending_queue); | 628 | skb_queue_head_init(&port->fcoe_pending_queue); |
468 | port->fcoe_pending_queue_active = 0; | 629 | port->fcoe_pending_queue_active = 0; |
469 | setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lp); | 630 | setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport); |
470 | 631 | ||
471 | wwnn = fcoe_wwn_from_mac(netdev->dev_addr, 1, 0); | 632 | if (!lport->vport) { |
472 | fc_set_wwnn(lp, wwnn); | 633 | /* |
473 | /* XXX - 3rd arg needs to be vlan id */ | 634 | * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN: |
474 | wwpn = fcoe_wwn_from_mac(netdev->dev_addr, 2, 0); | 635 | * For WWNN, we use NAA 1 w/ bit 27-16 of word 0 as 0. |
475 | fc_set_wwpn(lp, wwpn); | 636 | * For WWPN, we use NAA 2 w/ bit 27-16 of word 0 from VLAN ID |
637 | */ | ||
638 | if (netdev->priv_flags & IFF_802_1Q_VLAN) | ||
639 | vid = vlan_dev_vlan_id(netdev); | ||
640 | |||
641 | if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) | ||
642 | wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0); | ||
643 | fc_set_wwnn(lport, wwnn); | ||
644 | if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) | ||
645 | wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, | ||
646 | 2, vid); | ||
647 | fc_set_wwpn(lport, wwpn); | ||
648 | } | ||
476 | 649 | ||
477 | return 0; | 650 | return 0; |
478 | } | 651 | } |
479 | 652 | ||
480 | /** | 653 | /** |
481 | * fcoe_shost_config() - Sets up fc_lport->host | 654 | * fcoe_shost_config() - Set up the SCSI host associated with a local port |
482 | * @lp : ptr to the fc_lport | 655 | * @lport: The local port |
483 | * @shost : ptr to the associated scsi host | 656 | * @shost: The SCSI host to associate with the local port |
484 | * @dev : device associated to scsi host | 657 | * @dev: The device associated with the SCSI host |
485 | * | 658 | * |
486 | * Must be called after fcoe_lport_config() and fcoe_netdev_config() | 659 | * Must be called after fcoe_lport_config() and fcoe_netdev_config() |
487 | * | 660 | * |
488 | * Returns : 0 for success | 661 | * Returns: 0 for success |
489 | */ | 662 | */ |
490 | static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, | 663 | static int fcoe_shost_config(struct fc_lport *lport, struct Scsi_Host *shost, |
491 | struct device *dev) | 664 | struct device *dev) |
492 | { | 665 | { |
493 | int rc = 0; | 666 | int rc = 0; |
494 | 667 | ||
495 | /* lport scsi host config */ | 668 | /* lport scsi host config */ |
496 | lp->host = shost; | 669 | lport->host->max_lun = FCOE_MAX_LUN; |
497 | 670 | lport->host->max_id = FCOE_MAX_FCP_TARGET; | |
498 | lp->host->max_lun = FCOE_MAX_LUN; | 671 | lport->host->max_channel = 0; |
499 | lp->host->max_id = FCOE_MAX_FCP_TARGET; | 672 | if (lport->vport) |
500 | lp->host->max_channel = 0; | 673 | lport->host->transportt = fcoe_vport_transport_template; |
501 | lp->host->transportt = scsi_transport_fcoe_sw; | 674 | else |
675 | lport->host->transportt = fcoe_transport_template; | ||
502 | 676 | ||
503 | /* add the new host to the SCSI-ml */ | 677 | /* add the new host to the SCSI-ml */ |
504 | rc = scsi_add_host(lp->host, dev); | 678 | rc = scsi_add_host(lport->host, dev); |
505 | if (rc) { | 679 | if (rc) { |
506 | FCOE_NETDEV_DBG(fcoe_netdev(lp), "fcoe_shost_config: " | 680 | FCOE_NETDEV_DBG(fcoe_netdev(lport), "fcoe_shost_config: " |
507 | "error on scsi_add_host\n"); | 681 | "error on scsi_add_host\n"); |
508 | return rc; | 682 | return rc; |
509 | } | 683 | } |
510 | sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s", | 684 | |
511 | FCOE_NAME, FCOE_VERSION, | 685 | if (!lport->vport) |
512 | fcoe_netdev(lp)->name); | 686 | fc_host_max_npiv_vports(lport->host) = USHORT_MAX; |
687 | |||
688 | snprintf(fc_host_symbolic_name(lport->host), FC_SYMBOLIC_NAME_SIZE, | ||
689 | "%s v%s over %s", FCOE_NAME, FCOE_VERSION, | ||
690 | fcoe_netdev(lport)->name); | ||
513 | 691 | ||
514 | return 0; | 692 | return 0; |
515 | } | 693 | } |
516 | 694 | ||
517 | /* | 695 | /** |
518 | * fcoe_oem_match() - match for read types IO | 696 | * fcoe_oem_match() - The match routine for the offloaded exchange manager |
519 | * @fp: the fc_frame for new IO. | 697 | * @fp: The I/O frame |
698 | * | ||
699 | * This routine will be associated with an exchange manager (EM). When | ||
700 | * the libfc exchange handling code is looking for an EM to use it will | ||
701 | * call this routine and pass it the frame that it wishes to send. This | ||
702 | * routine will return True if the associated EM is to be used and False | ||
703 | * if the echange code should continue looking for an EM. | ||
704 | * | ||
705 | * The offload EM that this routine is associated with will handle any | ||
706 | * packets that are for SCSI read requests. | ||
520 | * | 707 | * |
521 | * Returns : true for read types IO, otherwise returns false. | 708 | * Returns: True for read types I/O, otherwise returns false. |
522 | */ | 709 | */ |
523 | bool fcoe_oem_match(struct fc_frame *fp) | 710 | bool fcoe_oem_match(struct fc_frame *fp) |
524 | { | 711 | { |
@@ -527,14 +714,14 @@ bool fcoe_oem_match(struct fc_frame *fp) | |||
527 | } | 714 | } |
528 | 715 | ||
529 | /** | 716 | /** |
530 | * fcoe_em_config() - allocates em for this lport | 717 | * fcoe_em_config() - Allocate and configure an exchange manager |
531 | * @lp: the fcoe that em is to allocated for | 718 | * @lport: The local port that the new EM will be associated with |
532 | * | 719 | * |
533 | * Returns : 0 on success | 720 | * Returns: 0 on success |
534 | */ | 721 | */ |
535 | static inline int fcoe_em_config(struct fc_lport *lp) | 722 | static inline int fcoe_em_config(struct fc_lport *lport) |
536 | { | 723 | { |
537 | struct fcoe_port *port = lport_priv(lp); | 724 | struct fcoe_port *port = lport_priv(lport); |
538 | struct fcoe_interface *fcoe = port->fcoe; | 725 | struct fcoe_interface *fcoe = port->fcoe; |
539 | struct fcoe_interface *oldfcoe = NULL; | 726 | struct fcoe_interface *oldfcoe = NULL; |
540 | struct net_device *old_real_dev, *cur_real_dev; | 727 | struct net_device *old_real_dev, *cur_real_dev; |
@@ -545,8 +732,9 @@ static inline int fcoe_em_config(struct fc_lport *lp) | |||
545 | * Check if need to allocate an em instance for | 732 | * Check if need to allocate an em instance for |
546 | * offload exchange ids to be shared across all VN_PORTs/lport. | 733 | * offload exchange ids to be shared across all VN_PORTs/lport. |
547 | */ | 734 | */ |
548 | if (!lp->lro_enabled || !lp->lro_xid || (lp->lro_xid >= max_xid)) { | 735 | if (!lport->lro_enabled || !lport->lro_xid || |
549 | lp->lro_xid = 0; | 736 | (lport->lro_xid >= max_xid)) { |
737 | lport->lro_xid = 0; | ||
550 | goto skip_oem; | 738 | goto skip_oem; |
551 | } | 739 | } |
552 | 740 | ||
@@ -572,16 +760,16 @@ static inline int fcoe_em_config(struct fc_lport *lp) | |||
572 | } | 760 | } |
573 | 761 | ||
574 | if (fcoe->oem) { | 762 | if (fcoe->oem) { |
575 | if (!fc_exch_mgr_add(lp, fcoe->oem, fcoe_oem_match)) { | 763 | if (!fc_exch_mgr_add(lport, fcoe->oem, fcoe_oem_match)) { |
576 | printk(KERN_ERR "fcoe_em_config: failed to add " | 764 | printk(KERN_ERR "fcoe_em_config: failed to add " |
577 | "offload em:%p on interface:%s\n", | 765 | "offload em:%p on interface:%s\n", |
578 | fcoe->oem, fcoe->netdev->name); | 766 | fcoe->oem, fcoe->netdev->name); |
579 | return -ENOMEM; | 767 | return -ENOMEM; |
580 | } | 768 | } |
581 | } else { | 769 | } else { |
582 | fcoe->oem = fc_exch_mgr_alloc(lp, FC_CLASS_3, | 770 | fcoe->oem = fc_exch_mgr_alloc(lport, FC_CLASS_3, |
583 | FCOE_MIN_XID, lp->lro_xid, | 771 | FCOE_MIN_XID, lport->lro_xid, |
584 | fcoe_oem_match); | 772 | fcoe_oem_match); |
585 | if (!fcoe->oem) { | 773 | if (!fcoe->oem) { |
586 | printk(KERN_ERR "fcoe_em_config: failed to allocate " | 774 | printk(KERN_ERR "fcoe_em_config: failed to allocate " |
587 | "em for offload exches on interface:%s\n", | 775 | "em for offload exches on interface:%s\n", |
@@ -593,10 +781,10 @@ static inline int fcoe_em_config(struct fc_lport *lp) | |||
593 | /* | 781 | /* |
594 | * Exclude offload EM xid range from next EM xid range. | 782 | * Exclude offload EM xid range from next EM xid range. |
595 | */ | 783 | */ |
596 | min_xid += lp->lro_xid + 1; | 784 | min_xid += lport->lro_xid + 1; |
597 | 785 | ||
598 | skip_oem: | 786 | skip_oem: |
599 | if (!fc_exch_mgr_alloc(lp, FC_CLASS_3, min_xid, max_xid, NULL)) { | 787 | if (!fc_exch_mgr_alloc(lport, FC_CLASS_3, min_xid, max_xid, NULL)) { |
600 | printk(KERN_ERR "fcoe_em_config: failed to " | 788 | printk(KERN_ERR "fcoe_em_config: failed to " |
601 | "allocate em on interface %s\n", fcoe->netdev->name); | 789 | "allocate em on interface %s\n", fcoe->netdev->name); |
602 | return -ENOMEM; | 790 | return -ENOMEM; |
@@ -606,8 +794,8 @@ skip_oem: | |||
606 | } | 794 | } |
607 | 795 | ||
608 | /** | 796 | /** |
609 | * fcoe_if_destroy() - FCoE software HBA tear-down function | 797 | * fcoe_if_destroy() - Tear down a SW FCoE instance |
610 | * @lport: fc_lport to destroy | 798 | * @lport: The local port to be destroyed |
611 | */ | 799 | */ |
612 | static void fcoe_if_destroy(struct fc_lport *lport) | 800 | static void fcoe_if_destroy(struct fc_lport *lport) |
613 | { | 801 | { |
@@ -630,6 +818,11 @@ static void fcoe_if_destroy(struct fc_lport *lport) | |||
630 | /* Free existing transmit skbs */ | 818 | /* Free existing transmit skbs */ |
631 | fcoe_clean_pending_queue(lport); | 819 | fcoe_clean_pending_queue(lport); |
632 | 820 | ||
821 | rtnl_lock(); | ||
822 | if (!is_zero_ether_addr(port->data_src_addr)) | ||
823 | dev_unicast_delete(netdev, port->data_src_addr); | ||
824 | rtnl_unlock(); | ||
825 | |||
633 | /* receives may not be stopped until after this */ | 826 | /* receives may not be stopped until after this */ |
634 | fcoe_interface_put(fcoe); | 827 | fcoe_interface_put(fcoe); |
635 | 828 | ||
@@ -650,82 +843,89 @@ static void fcoe_if_destroy(struct fc_lport *lport) | |||
650 | scsi_host_put(lport->host); | 843 | scsi_host_put(lport->host); |
651 | } | 844 | } |
652 | 845 | ||
653 | /* | 846 | /** |
654 | * fcoe_ddp_setup - calls LLD's ddp_setup through net_device | 847 | * fcoe_ddp_setup() - Call a LLD's ddp_setup through the net device |
655 | * @lp: the corresponding fc_lport | 848 | * @lport: The local port to setup DDP for |
656 | * @xid: the exchange id for this ddp transfer | 849 | * @xid: The exchange ID for this DDP transfer |
657 | * @sgl: the scatterlist describing this transfer | 850 | * @sgl: The scatterlist describing this transfer |
658 | * @sgc: number of sg items | 851 | * @sgc: The number of sg items |
659 | * | 852 | * |
660 | * Returns : 0 no ddp | 853 | * Returns: 0 if the DDP context was not configured |
661 | */ | 854 | */ |
662 | static int fcoe_ddp_setup(struct fc_lport *lp, u16 xid, | 855 | static int fcoe_ddp_setup(struct fc_lport *lport, u16 xid, |
663 | struct scatterlist *sgl, unsigned int sgc) | 856 | struct scatterlist *sgl, unsigned int sgc) |
664 | { | 857 | { |
665 | struct net_device *n = fcoe_netdev(lp); | 858 | struct net_device *netdev = fcoe_netdev(lport); |
666 | 859 | ||
667 | if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup) | 860 | if (netdev->netdev_ops->ndo_fcoe_ddp_setup) |
668 | return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc); | 861 | return netdev->netdev_ops->ndo_fcoe_ddp_setup(netdev, |
862 | xid, sgl, | ||
863 | sgc); | ||
669 | 864 | ||
670 | return 0; | 865 | return 0; |
671 | } | 866 | } |
672 | 867 | ||
673 | /* | 868 | /** |
674 | * fcoe_ddp_done - calls LLD's ddp_done through net_device | 869 | * fcoe_ddp_done() - Call a LLD's ddp_done through the net device |
675 | * @lp: the corresponding fc_lport | 870 | * @lport: The local port to complete DDP on |
676 | * @xid: the exchange id for this ddp transfer | 871 | * @xid: The exchange ID for this DDP transfer |
677 | * | 872 | * |
678 | * Returns : the length of data that have been completed by ddp | 873 | * Returns: the length of data that have been completed by DDP |
679 | */ | 874 | */ |
680 | static int fcoe_ddp_done(struct fc_lport *lp, u16 xid) | 875 | static int fcoe_ddp_done(struct fc_lport *lport, u16 xid) |
681 | { | 876 | { |
682 | struct net_device *n = fcoe_netdev(lp); | 877 | struct net_device *netdev = fcoe_netdev(lport); |
683 | 878 | ||
684 | if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done) | 879 | if (netdev->netdev_ops->ndo_fcoe_ddp_done) |
685 | return n->netdev_ops->ndo_fcoe_ddp_done(n, xid); | 880 | return netdev->netdev_ops->ndo_fcoe_ddp_done(netdev, xid); |
686 | return 0; | 881 | return 0; |
687 | } | 882 | } |
688 | 883 | ||
689 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | ||
690 | .frame_send = fcoe_xmit, | ||
691 | .ddp_setup = fcoe_ddp_setup, | ||
692 | .ddp_done = fcoe_ddp_done, | ||
693 | }; | ||
694 | |||
695 | /** | 884 | /** |
696 | * fcoe_if_create() - this function creates the fcoe port | 885 | * fcoe_if_create() - Create a FCoE instance on an interface |
697 | * @fcoe: fcoe_interface structure to create an fc_lport instance on | 886 | * @fcoe: The FCoE interface to create a local port on |
698 | * @parent: device pointer to be the parent in sysfs for the SCSI host | 887 | * @parent: The device pointer to be the parent in sysfs for the SCSI host |
888 | * @npiv: Indicates if the port is a vport or not | ||
699 | * | 889 | * |
700 | * Creates fc_lport struct and scsi_host for lport, configures lport. | 890 | * Creates a fc_lport instance and a Scsi_Host instance and configure them. |
701 | * | 891 | * |
702 | * Returns : The allocated fc_lport or an error pointer | 892 | * Returns: The allocated fc_lport or an error pointer |
703 | */ | 893 | */ |
704 | static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | 894 | static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, |
705 | struct device *parent) | 895 | struct device *parent, int npiv) |
706 | { | 896 | { |
707 | int rc; | 897 | struct net_device *netdev = fcoe->netdev; |
708 | struct fc_lport *lport = NULL; | 898 | struct fc_lport *lport = NULL; |
709 | struct fcoe_port *port; | 899 | struct fcoe_port *port; |
710 | struct Scsi_Host *shost; | 900 | struct Scsi_Host *shost; |
711 | struct net_device *netdev = fcoe->netdev; | 901 | int rc; |
902 | /* | ||
903 | * parent is only a vport if npiv is 1, | ||
904 | * but we'll only use vport in that case so go ahead and set it | ||
905 | */ | ||
906 | struct fc_vport *vport = dev_to_vport(parent); | ||
712 | 907 | ||
713 | FCOE_NETDEV_DBG(netdev, "Create Interface\n"); | 908 | FCOE_NETDEV_DBG(netdev, "Create Interface\n"); |
714 | 909 | ||
715 | shost = libfc_host_alloc(&fcoe_shost_template, | 910 | if (!npiv) { |
716 | sizeof(struct fcoe_port)); | 911 | lport = libfc_host_alloc(&fcoe_shost_template, |
717 | if (!shost) { | 912 | sizeof(struct fcoe_port)); |
913 | } else { | ||
914 | lport = libfc_vport_create(vport, | ||
915 | sizeof(struct fcoe_port)); | ||
916 | } | ||
917 | if (!lport) { | ||
718 | FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); | 918 | FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); |
719 | rc = -ENOMEM; | 919 | rc = -ENOMEM; |
720 | goto out; | 920 | goto out; |
721 | } | 921 | } |
722 | lport = shost_priv(shost); | 922 | shost = lport->host; |
723 | port = lport_priv(lport); | 923 | port = lport_priv(lport); |
724 | port->lport = lport; | 924 | port->lport = lport; |
725 | port->fcoe = fcoe; | 925 | port->fcoe = fcoe; |
726 | INIT_WORK(&port->destroy_work, fcoe_destroy_work); | 926 | INIT_WORK(&port->destroy_work, fcoe_destroy_work); |
727 | 927 | ||
728 | /* configure fc_lport, e.g., em */ | 928 | /* configure a fc_lport including the exchange manager */ |
729 | rc = fcoe_lport_config(lport); | 929 | rc = fcoe_lport_config(lport); |
730 | if (rc) { | 930 | if (rc) { |
731 | FCOE_NETDEV_DBG(netdev, "Could not configure lport for the " | 931 | FCOE_NETDEV_DBG(netdev, "Could not configure lport for the " |
@@ -733,6 +933,13 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
733 | goto out_host_put; | 933 | goto out_host_put; |
734 | } | 934 | } |
735 | 935 | ||
936 | if (npiv) { | ||
937 | FCOE_NETDEV_DBG(netdev, "Setting vport names, 0x%llX 0x%llX\n", | ||
938 | vport->node_name, vport->port_name); | ||
939 | fc_set_wwnn(lport, vport->node_name); | ||
940 | fc_set_wwpn(lport, vport->port_name); | ||
941 | } | ||
942 | |||
736 | /* configure lport network properties */ | 943 | /* configure lport network properties */ |
737 | rc = fcoe_netdev_config(lport, netdev); | 944 | rc = fcoe_netdev_config(lport, netdev); |
738 | if (rc) { | 945 | if (rc) { |
@@ -757,21 +964,24 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
757 | goto out_lp_destroy; | 964 | goto out_lp_destroy; |
758 | } | 965 | } |
759 | 966 | ||
760 | /* | 967 | if (!npiv) { |
761 | * fcoe_em_alloc() and fcoe_hostlist_add() both | 968 | /* |
762 | * need to be atomic with respect to other changes to the hostlist | 969 | * fcoe_em_alloc() and fcoe_hostlist_add() both |
763 | * since fcoe_em_alloc() looks for an existing EM | 970 | * need to be atomic with respect to other changes to the |
764 | * instance on host list updated by fcoe_hostlist_add(). | 971 | * hostlist since fcoe_em_alloc() looks for an existing EM |
765 | * | 972 | * instance on host list updated by fcoe_hostlist_add(). |
766 | * This is currently handled through the fcoe_config_mutex begin held. | 973 | * |
767 | */ | 974 | * This is currently handled through the fcoe_config_mutex |
975 | * begin held. | ||
976 | */ | ||
768 | 977 | ||
769 | /* lport exch manager allocation */ | 978 | /* lport exch manager allocation */ |
770 | rc = fcoe_em_config(lport); | 979 | rc = fcoe_em_config(lport); |
771 | if (rc) { | 980 | if (rc) { |
772 | FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the " | 981 | FCOE_NETDEV_DBG(netdev, "Could not configure the EM " |
773 | "interface\n"); | 982 | "for the interface\n"); |
774 | goto out_lp_destroy; | 983 | goto out_lp_destroy; |
984 | } | ||
775 | } | 985 | } |
776 | 986 | ||
777 | fcoe_interface_get(fcoe); | 987 | fcoe_interface_get(fcoe); |
@@ -786,17 +996,20 @@ out: | |||
786 | } | 996 | } |
787 | 997 | ||
788 | /** | 998 | /** |
789 | * fcoe_if_init() - attach to scsi transport | 999 | * fcoe_if_init() - Initialization routine for fcoe.ko |
790 | * | 1000 | * |
791 | * Returns : 0 on success | 1001 | * Attaches the SW FCoE transport to the FC transport |
1002 | * | ||
1003 | * Returns: 0 on success | ||
792 | */ | 1004 | */ |
793 | static int __init fcoe_if_init(void) | 1005 | static int __init fcoe_if_init(void) |
794 | { | 1006 | { |
795 | /* attach to scsi transport */ | 1007 | /* attach to scsi transport */ |
796 | scsi_transport_fcoe_sw = | 1008 | fcoe_transport_template = fc_attach_transport(&fcoe_transport_function); |
797 | fc_attach_transport(&fcoe_transport_function); | 1009 | fcoe_vport_transport_template = |
1010 | fc_attach_transport(&fcoe_vport_transport_function); | ||
798 | 1011 | ||
799 | if (!scsi_transport_fcoe_sw) { | 1012 | if (!fcoe_transport_template) { |
800 | printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); | 1013 | printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); |
801 | return -ENODEV; | 1014 | return -ENODEV; |
802 | } | 1015 | } |
@@ -805,20 +1018,24 @@ static int __init fcoe_if_init(void) | |||
805 | } | 1018 | } |
806 | 1019 | ||
807 | /** | 1020 | /** |
808 | * fcoe_if_exit() - detach from scsi transport | 1021 | * fcoe_if_exit() - Tear down fcoe.ko |
1022 | * | ||
1023 | * Detaches the SW FCoE transport from the FC transport | ||
809 | * | 1024 | * |
810 | * Returns : 0 on success | 1025 | * Returns: 0 on success |
811 | */ | 1026 | */ |
812 | int __exit fcoe_if_exit(void) | 1027 | int __exit fcoe_if_exit(void) |
813 | { | 1028 | { |
814 | fc_release_transport(scsi_transport_fcoe_sw); | 1029 | fc_release_transport(fcoe_transport_template); |
815 | scsi_transport_fcoe_sw = NULL; | 1030 | fc_release_transport(fcoe_vport_transport_template); |
1031 | fcoe_transport_template = NULL; | ||
1032 | fcoe_vport_transport_template = NULL; | ||
816 | return 0; | 1033 | return 0; |
817 | } | 1034 | } |
818 | 1035 | ||
819 | /** | 1036 | /** |
820 | * fcoe_percpu_thread_create() - Create a receive thread for an online cpu | 1037 | * fcoe_percpu_thread_create() - Create a receive thread for an online CPU |
821 | * @cpu: cpu index for the online cpu | 1038 | * @cpu: The CPU index of the CPU to create a receive thread for |
822 | */ | 1039 | */ |
823 | static void fcoe_percpu_thread_create(unsigned int cpu) | 1040 | static void fcoe_percpu_thread_create(unsigned int cpu) |
824 | { | 1041 | { |
@@ -841,8 +1058,8 @@ static void fcoe_percpu_thread_create(unsigned int cpu) | |||
841 | } | 1058 | } |
842 | 1059 | ||
843 | /** | 1060 | /** |
844 | * fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu | 1061 | * fcoe_percpu_thread_destroy() - Remove the receive thread of a CPU |
845 | * @cpu: cpu index the rx thread is to be removed | 1062 | * @cpu: The CPU index of the CPU whose receive thread is to be destroyed |
846 | * | 1063 | * |
847 | * Destroys a per-CPU Rx thread. Any pending skbs are moved to the | 1064 | * Destroys a per-CPU Rx thread. Any pending skbs are moved to the |
848 | * current CPU's Rx thread. If the thread being destroyed is bound to | 1065 | * current CPU's Rx thread. If the thread being destroyed is bound to |
@@ -890,7 +1107,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu) | |||
890 | } else { | 1107 | } else { |
891 | /* | 1108 | /* |
892 | * The targeted CPU is not initialized and cannot accept | 1109 | * The targeted CPU is not initialized and cannot accept |
893 | * new skbs. Unlock the targeted CPU and drop the skbs | 1110 | * new skbs. Unlock the targeted CPU and drop the skbs |
894 | * on the CPU that is going offline. | 1111 | * on the CPU that is going offline. |
895 | */ | 1112 | */ |
896 | while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) | 1113 | while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) |
@@ -931,12 +1148,12 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu) | |||
931 | } | 1148 | } |
932 | 1149 | ||
933 | /** | 1150 | /** |
934 | * fcoe_cpu_callback() - fcoe cpu hotplug event callback | 1151 | * fcoe_cpu_callback() - Handler for CPU hotplug events |
935 | * @nfb: callback data block | 1152 | * @nfb: The callback data block |
936 | * @action: event triggering the callback | 1153 | * @action: The event triggering the callback |
937 | * @hcpu: index for the cpu of this event | 1154 | * @hcpu: The index of the CPU that the event is for |
938 | * | 1155 | * |
939 | * This creates or destroys per cpu data for fcoe | 1156 | * This creates or destroys per-CPU data for fcoe |
940 | * | 1157 | * |
941 | * Returns NOTIFY_OK always. | 1158 | * Returns NOTIFY_OK always. |
942 | */ | 1159 | */ |
@@ -962,25 +1179,22 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, | |||
962 | return NOTIFY_OK; | 1179 | return NOTIFY_OK; |
963 | } | 1180 | } |
964 | 1181 | ||
965 | static struct notifier_block fcoe_cpu_notifier = { | ||
966 | .notifier_call = fcoe_cpu_callback, | ||
967 | }; | ||
968 | |||
969 | /** | 1182 | /** |
970 | * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ | 1183 | * fcoe_rcv() - Receive packets from a net device |
971 | * @skb: the receive skb | 1184 | * @skb: The received packet |
972 | * @dev: associated net device | 1185 | * @netdev: The net device that the packet was received on |
973 | * @ptype: context | 1186 | * @ptype: The packet type context |
974 | * @olddev: last device | 1187 | * @olddev: The last device net device |
975 | * | 1188 | * |
976 | * this function will receive the packet and build fc frame and pass it up | 1189 | * This routine is called by NET_RX_SOFTIRQ. It receives a packet, builds a |
1190 | * FC frame and passes the frame to libfc. | ||
977 | * | 1191 | * |
978 | * Returns: 0 for success | 1192 | * Returns: 0 for success |
979 | */ | 1193 | */ |
980 | int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | 1194 | int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, |
981 | struct packet_type *ptype, struct net_device *olddev) | 1195 | struct packet_type *ptype, struct net_device *olddev) |
982 | { | 1196 | { |
983 | struct fc_lport *lp; | 1197 | struct fc_lport *lport; |
984 | struct fcoe_rcv_info *fr; | 1198 | struct fcoe_rcv_info *fr; |
985 | struct fcoe_interface *fcoe; | 1199 | struct fcoe_interface *fcoe; |
986 | struct fc_frame_header *fh; | 1200 | struct fc_frame_header *fh; |
@@ -988,15 +1202,15 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
988 | unsigned int cpu; | 1202 | unsigned int cpu; |
989 | 1203 | ||
990 | fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); | 1204 | fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); |
991 | lp = fcoe->ctlr.lp; | 1205 | lport = fcoe->ctlr.lp; |
992 | if (unlikely(lp == NULL)) { | 1206 | if (unlikely(!lport)) { |
993 | FCOE_NETDEV_DBG(dev, "Cannot find hba structure"); | 1207 | FCOE_NETDEV_DBG(netdev, "Cannot find hba structure"); |
994 | goto err2; | 1208 | goto err2; |
995 | } | 1209 | } |
996 | if (!lp->link_up) | 1210 | if (!lport->link_up) |
997 | goto err2; | 1211 | goto err2; |
998 | 1212 | ||
999 | FCOE_NETDEV_DBG(dev, "skb_info: len:%d data_len:%d head:%p " | 1213 | FCOE_NETDEV_DBG(netdev, "skb_info: len:%d data_len:%d head:%p " |
1000 | "data:%p tail:%p end:%p sum:%d dev:%s", | 1214 | "data:%p tail:%p end:%p sum:%d dev:%s", |
1001 | skb->len, skb->data_len, skb->head, skb->data, | 1215 | skb->len, skb->data_len, skb->head, skb->data, |
1002 | skb_tail_pointer(skb), skb_end_pointer(skb), | 1216 | skb_tail_pointer(skb), skb_end_pointer(skb), |
@@ -1004,7 +1218,7 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1004 | 1218 | ||
1005 | /* check for FCOE packet type */ | 1219 | /* check for FCOE packet type */ |
1006 | if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { | 1220 | if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { |
1007 | FCOE_NETDEV_DBG(dev, "Wrong FC type frame"); | 1221 | FCOE_NETDEV_DBG(netdev, "Wrong FC type frame"); |
1008 | goto err; | 1222 | goto err; |
1009 | } | 1223 | } |
1010 | 1224 | ||
@@ -1013,14 +1227,14 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1013 | * and FC headers are pulled into the linear data area. | 1227 | * and FC headers are pulled into the linear data area. |
1014 | */ | 1228 | */ |
1015 | if (unlikely((skb->len < FCOE_MIN_FRAME) || | 1229 | if (unlikely((skb->len < FCOE_MIN_FRAME) || |
1016 | !pskb_may_pull(skb, FCOE_HEADER_LEN))) | 1230 | !pskb_may_pull(skb, FCOE_HEADER_LEN))) |
1017 | goto err; | 1231 | goto err; |
1018 | 1232 | ||
1019 | skb_set_transport_header(skb, sizeof(struct fcoe_hdr)); | 1233 | skb_set_transport_header(skb, sizeof(struct fcoe_hdr)); |
1020 | fh = (struct fc_frame_header *) skb_transport_header(skb); | 1234 | fh = (struct fc_frame_header *) skb_transport_header(skb); |
1021 | 1235 | ||
1022 | fr = fcoe_dev_from_skb(skb); | 1236 | fr = fcoe_dev_from_skb(skb); |
1023 | fr->fr_dev = lp; | 1237 | fr->fr_dev = lport; |
1024 | fr->ptype = ptype; | 1238 | fr->ptype = ptype; |
1025 | 1239 | ||
1026 | /* | 1240 | /* |
@@ -1042,12 +1256,12 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1042 | * the first CPU now. For non-SMP systems this | 1256 | * the first CPU now. For non-SMP systems this |
1043 | * will check the same CPU twice. | 1257 | * will check the same CPU twice. |
1044 | */ | 1258 | */ |
1045 | FCOE_NETDEV_DBG(dev, "CPU is online, but no receive thread " | 1259 | FCOE_NETDEV_DBG(netdev, "CPU is online, but no receive thread " |
1046 | "ready for incoming skb- using first online " | 1260 | "ready for incoming skb- using first online " |
1047 | "CPU.\n"); | 1261 | "CPU.\n"); |
1048 | 1262 | ||
1049 | spin_unlock_bh(&fps->fcoe_rx_list.lock); | 1263 | spin_unlock_bh(&fps->fcoe_rx_list.lock); |
1050 | cpu = first_cpu(cpu_online_map); | 1264 | cpu = cpumask_first(cpu_online_mask); |
1051 | fps = &per_cpu(fcoe_percpu, cpu); | 1265 | fps = &per_cpu(fcoe_percpu, cpu); |
1052 | spin_lock_bh(&fps->fcoe_rx_list.lock); | 1266 | spin_lock_bh(&fps->fcoe_rx_list.lock); |
1053 | if (!fps->thread) { | 1267 | if (!fps->thread) { |
@@ -1061,15 +1275,29 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1061 | * this skb. We also have this receive thread locked, | 1275 | * this skb. We also have this receive thread locked, |
1062 | * so we're free to queue skbs into it's queue. | 1276 | * so we're free to queue skbs into it's queue. |
1063 | */ | 1277 | */ |
1064 | __skb_queue_tail(&fps->fcoe_rx_list, skb); | ||
1065 | if (fps->fcoe_rx_list.qlen == 1) | ||
1066 | wake_up_process(fps->thread); | ||
1067 | 1278 | ||
1068 | spin_unlock_bh(&fps->fcoe_rx_list.lock); | 1279 | /* If this is a SCSI-FCP frame, and this is already executing on the |
1280 | * correct CPU, and the queue for this CPU is empty, then go ahead | ||
1281 | * and process the frame directly in the softirq context. | ||
1282 | * This lets us process completions without context switching from the | ||
1283 | * NET_RX softirq, to our receive processing thread, and then back to | ||
1284 | * BLOCK softirq context. | ||
1285 | */ | ||
1286 | if (fh->fh_type == FC_TYPE_FCP && | ||
1287 | cpu == smp_processor_id() && | ||
1288 | skb_queue_empty(&fps->fcoe_rx_list)) { | ||
1289 | spin_unlock_bh(&fps->fcoe_rx_list.lock); | ||
1290 | fcoe_recv_frame(skb); | ||
1291 | } else { | ||
1292 | __skb_queue_tail(&fps->fcoe_rx_list, skb); | ||
1293 | if (fps->fcoe_rx_list.qlen == 1) | ||
1294 | wake_up_process(fps->thread); | ||
1295 | spin_unlock_bh(&fps->fcoe_rx_list.lock); | ||
1296 | } | ||
1069 | 1297 | ||
1070 | return 0; | 1298 | return 0; |
1071 | err: | 1299 | err: |
1072 | fc_lport_get_stats(lp)->ErrorFrames++; | 1300 | fc_lport_get_stats(lport)->ErrorFrames++; |
1073 | 1301 | ||
1074 | err2: | 1302 | err2: |
1075 | kfree_skb(skb); | 1303 | kfree_skb(skb); |
@@ -1077,17 +1305,21 @@ err2: | |||
1077 | } | 1305 | } |
1078 | 1306 | ||
1079 | /** | 1307 | /** |
1080 | * fcoe_start_io() - pass to netdev to start xmit for fcoe | 1308 | * fcoe_start_io() - Start FCoE I/O |
1081 | * @skb: the skb to be xmitted | 1309 | * @skb: The packet to be transmitted |
1310 | * | ||
1311 | * This routine is called from the net device to start transmitting | ||
1312 | * FCoE packets. | ||
1082 | * | 1313 | * |
1083 | * Returns: 0 for success | 1314 | * Returns: 0 for success |
1084 | */ | 1315 | */ |
1085 | static inline int fcoe_start_io(struct sk_buff *skb) | 1316 | static inline int fcoe_start_io(struct sk_buff *skb) |
1086 | { | 1317 | { |
1318 | struct sk_buff *nskb; | ||
1087 | int rc; | 1319 | int rc; |
1088 | 1320 | ||
1089 | skb_get(skb); | 1321 | nskb = skb_clone(skb, GFP_ATOMIC); |
1090 | rc = dev_queue_xmit(skb); | 1322 | rc = dev_queue_xmit(nskb); |
1091 | if (rc != 0) | 1323 | if (rc != 0) |
1092 | return rc; | 1324 | return rc; |
1093 | kfree_skb(skb); | 1325 | kfree_skb(skb); |
@@ -1095,9 +1327,15 @@ static inline int fcoe_start_io(struct sk_buff *skb) | |||
1095 | } | 1327 | } |
1096 | 1328 | ||
1097 | /** | 1329 | /** |
1098 | * fcoe_get_paged_crc_eof() - in case we need to alloc a page for crc_eof | 1330 | * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC |
1099 | * @skb: the skb to be xmitted | 1331 | * @skb: The packet to be transmitted |
1100 | * @tlen: total len | 1332 | * @tlen: The total length of the trailer |
1333 | * | ||
1334 | * This routine allocates a page for frame trailers. The page is re-used if | ||
1335 | * there is enough room left on it for the current trailer. If there isn't | ||
1336 | * enough buffer left a new page is allocated for the trailer. Reference to | ||
1337 | * the page from this function as well as the skbs using the page fragments | ||
1338 | * ensure that the page is freed at the appropriate time. | ||
1101 | * | 1339 | * |
1102 | * Returns: 0 for success | 1340 | * Returns: 0 for success |
1103 | */ | 1341 | */ |
@@ -1136,11 +1374,12 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) | |||
1136 | } | 1374 | } |
1137 | 1375 | ||
1138 | /** | 1376 | /** |
1139 | * fcoe_fc_crc() - calculates FC CRC in this fcoe skb | 1377 | * fcoe_fc_crc() - Calculates the CRC for a given frame |
1140 | * @fp: the fc_frame containing data to be checksummed | 1378 | * @fp: The frame to be checksumed |
1141 | * | 1379 | * |
1142 | * This uses crc32() to calculate the crc for port frame | 1380 | * This uses crc32() routine to calculate the CRC for a frame |
1143 | * Return : 32 bit crc | 1381 | * |
1382 | * Return: The 32 bit CRC value | ||
1144 | */ | 1383 | */ |
1145 | u32 fcoe_fc_crc(struct fc_frame *fp) | 1384 | u32 fcoe_fc_crc(struct fc_frame *fp) |
1146 | { | 1385 | { |
@@ -1171,13 +1410,13 @@ u32 fcoe_fc_crc(struct fc_frame *fp) | |||
1171 | } | 1410 | } |
1172 | 1411 | ||
1173 | /** | 1412 | /** |
1174 | * fcoe_xmit() - FCoE frame transmit function | 1413 | * fcoe_xmit() - Transmit a FCoE frame |
1175 | * @lp: the associated local fcoe | 1414 | * @lport: The local port that the frame is to be transmitted for |
1176 | * @fp: the fc_frame to be transmitted | 1415 | * @fp: The frame to be transmitted |
1177 | * | 1416 | * |
1178 | * Return : 0 for success | 1417 | * Return: 0 for success |
1179 | */ | 1418 | */ |
1180 | int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | 1419 | int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) |
1181 | { | 1420 | { |
1182 | int wlen; | 1421 | int wlen; |
1183 | u32 crc; | 1422 | u32 crc; |
@@ -1189,7 +1428,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1189 | unsigned int hlen; /* header length implies the version */ | 1428 | unsigned int hlen; /* header length implies the version */ |
1190 | unsigned int tlen; /* trailer length */ | 1429 | unsigned int tlen; /* trailer length */ |
1191 | unsigned int elen; /* eth header, may include vlan */ | 1430 | unsigned int elen; /* eth header, may include vlan */ |
1192 | struct fcoe_port *port = lport_priv(lp); | 1431 | struct fcoe_port *port = lport_priv(lport); |
1193 | struct fcoe_interface *fcoe = port->fcoe; | 1432 | struct fcoe_interface *fcoe = port->fcoe; |
1194 | u8 sof, eof; | 1433 | u8 sof, eof; |
1195 | struct fcoe_hdr *hp; | 1434 | struct fcoe_hdr *hp; |
@@ -1200,13 +1439,13 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1200 | skb = fp_skb(fp); | 1439 | skb = fp_skb(fp); |
1201 | wlen = skb->len / FCOE_WORD_TO_BYTE; | 1440 | wlen = skb->len / FCOE_WORD_TO_BYTE; |
1202 | 1441 | ||
1203 | if (!lp->link_up) { | 1442 | if (!lport->link_up) { |
1204 | kfree_skb(skb); | 1443 | kfree_skb(skb); |
1205 | return 0; | 1444 | return 0; |
1206 | } | 1445 | } |
1207 | 1446 | ||
1208 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && | 1447 | if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && |
1209 | fcoe_ctlr_els_send(&fcoe->ctlr, skb)) | 1448 | fcoe_ctlr_els_send(&fcoe->ctlr, lport, skb)) |
1210 | return 0; | 1449 | return 0; |
1211 | 1450 | ||
1212 | sof = fr_sof(fp); | 1451 | sof = fr_sof(fp); |
@@ -1218,7 +1457,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1218 | wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE; | 1457 | wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE; |
1219 | 1458 | ||
1220 | /* crc offload */ | 1459 | /* crc offload */ |
1221 | if (likely(lp->crc_offload)) { | 1460 | if (likely(lport->crc_offload)) { |
1222 | skb->ip_summed = CHECKSUM_PARTIAL; | 1461 | skb->ip_summed = CHECKSUM_PARTIAL; |
1223 | skb->csum_start = skb_headroom(skb); | 1462 | skb->csum_start = skb_headroom(skb); |
1224 | skb->csum_offset = skb->len; | 1463 | skb->csum_offset = skb->len; |
@@ -1271,7 +1510,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1271 | if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) | 1510 | if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) |
1272 | memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); | 1511 | memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); |
1273 | else | 1512 | else |
1274 | memcpy(eh->h_source, fcoe->ctlr.data_src_addr, ETH_ALEN); | 1513 | memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); |
1275 | 1514 | ||
1276 | hp = (struct fcoe_hdr *)(eh + 1); | 1515 | hp = (struct fcoe_hdr *)(eh + 1); |
1277 | memset(hp, 0, sizeof(*hp)); | 1516 | memset(hp, 0, sizeof(*hp)); |
@@ -1280,7 +1519,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1280 | hp->fcoe_sof = sof; | 1519 | hp->fcoe_sof = sof; |
1281 | 1520 | ||
1282 | /* fcoe lso, mss is in max_payload which is non-zero for FCP data */ | 1521 | /* fcoe lso, mss is in max_payload which is non-zero for FCP data */ |
1283 | if (lp->seq_offload && fr_max_payload(fp)) { | 1522 | if (lport->seq_offload && fr_max_payload(fp)) { |
1284 | skb_shinfo(skb)->gso_type = SKB_GSO_FCOE; | 1523 | skb_shinfo(skb)->gso_type = SKB_GSO_FCOE; |
1285 | skb_shinfo(skb)->gso_size = fr_max_payload(fp); | 1524 | skb_shinfo(skb)->gso_size = fr_max_payload(fp); |
1286 | } else { | 1525 | } else { |
@@ -1288,23 +1527,23 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) | |||
1288 | skb_shinfo(skb)->gso_size = 0; | 1527 | skb_shinfo(skb)->gso_size = 0; |
1289 | } | 1528 | } |
1290 | /* update tx stats: regardless if LLD fails */ | 1529 | /* update tx stats: regardless if LLD fails */ |
1291 | stats = fc_lport_get_stats(lp); | 1530 | stats = fc_lport_get_stats(lport); |
1292 | stats->TxFrames++; | 1531 | stats->TxFrames++; |
1293 | stats->TxWords += wlen; | 1532 | stats->TxWords += wlen; |
1294 | 1533 | ||
1295 | /* send down to lld */ | 1534 | /* send down to lld */ |
1296 | fr_dev(fp) = lp; | 1535 | fr_dev(fp) = lport; |
1297 | if (port->fcoe_pending_queue.qlen) | 1536 | if (port->fcoe_pending_queue.qlen) |
1298 | fcoe_check_wait_queue(lp, skb); | 1537 | fcoe_check_wait_queue(lport, skb); |
1299 | else if (fcoe_start_io(skb)) | 1538 | else if (fcoe_start_io(skb)) |
1300 | fcoe_check_wait_queue(lp, skb); | 1539 | fcoe_check_wait_queue(lport, skb); |
1301 | 1540 | ||
1302 | return 0; | 1541 | return 0; |
1303 | } | 1542 | } |
1304 | 1543 | ||
1305 | /** | 1544 | /** |
1306 | * fcoe_percpu_flush_done() - Indicate percpu queue flush completion. | 1545 | * fcoe_percpu_flush_done() - Indicate per-CPU queue flush completion |
1307 | * @skb: the skb being completed. | 1546 | * @skb: The completed skb (argument required by destructor) |
1308 | */ | 1547 | */ |
1309 | static void fcoe_percpu_flush_done(struct sk_buff *skb) | 1548 | static void fcoe_percpu_flush_done(struct sk_buff *skb) |
1310 | { | 1549 | { |
@@ -1312,26 +1551,134 @@ static void fcoe_percpu_flush_done(struct sk_buff *skb) | |||
1312 | } | 1551 | } |
1313 | 1552 | ||
1314 | /** | 1553 | /** |
1315 | * fcoe_percpu_receive_thread() - recv thread per cpu | 1554 | * fcoe_recv_frame() - process a single received frame |
1316 | * @arg: ptr to the fcoe per cpu struct | 1555 | * @skb: frame to process |
1317 | * | ||
1318 | * Return: 0 for success | ||
1319 | */ | 1556 | */ |
1320 | int fcoe_percpu_receive_thread(void *arg) | 1557 | static void fcoe_recv_frame(struct sk_buff *skb) |
1321 | { | 1558 | { |
1322 | struct fcoe_percpu_s *p = arg; | ||
1323 | u32 fr_len; | 1559 | u32 fr_len; |
1324 | struct fc_lport *lp; | 1560 | struct fc_lport *lport; |
1325 | struct fcoe_rcv_info *fr; | 1561 | struct fcoe_rcv_info *fr; |
1326 | struct fcoe_dev_stats *stats; | 1562 | struct fcoe_dev_stats *stats; |
1327 | struct fc_frame_header *fh; | 1563 | struct fc_frame_header *fh; |
1328 | struct sk_buff *skb; | ||
1329 | struct fcoe_crc_eof crc_eof; | 1564 | struct fcoe_crc_eof crc_eof; |
1330 | struct fc_frame *fp; | 1565 | struct fc_frame *fp; |
1331 | u8 *mac = NULL; | 1566 | u8 *mac = NULL; |
1332 | struct fcoe_port *port; | 1567 | struct fcoe_port *port; |
1333 | struct fcoe_hdr *hp; | 1568 | struct fcoe_hdr *hp; |
1334 | 1569 | ||
1570 | fr = fcoe_dev_from_skb(skb); | ||
1571 | lport = fr->fr_dev; | ||
1572 | if (unlikely(!lport)) { | ||
1573 | if (skb->destructor != fcoe_percpu_flush_done) | ||
1574 | FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb"); | ||
1575 | kfree_skb(skb); | ||
1576 | return; | ||
1577 | } | ||
1578 | |||
1579 | FCOE_NETDEV_DBG(skb->dev, "skb_info: len:%d data_len:%d " | ||
1580 | "head:%p data:%p tail:%p end:%p sum:%d dev:%s", | ||
1581 | skb->len, skb->data_len, | ||
1582 | skb->head, skb->data, skb_tail_pointer(skb), | ||
1583 | skb_end_pointer(skb), skb->csum, | ||
1584 | skb->dev ? skb->dev->name : "<NULL>"); | ||
1585 | |||
1586 | /* | ||
1587 | * Save source MAC address before discarding header. | ||
1588 | */ | ||
1589 | port = lport_priv(lport); | ||
1590 | if (skb_is_nonlinear(skb)) | ||
1591 | skb_linearize(skb); /* not ideal */ | ||
1592 | mac = eth_hdr(skb)->h_source; | ||
1593 | |||
1594 | /* | ||
1595 | * Frame length checks and setting up the header pointers | ||
1596 | * was done in fcoe_rcv already. | ||
1597 | */ | ||
1598 | hp = (struct fcoe_hdr *) skb_network_header(skb); | ||
1599 | fh = (struct fc_frame_header *) skb_transport_header(skb); | ||
1600 | |||
1601 | stats = fc_lport_get_stats(lport); | ||
1602 | if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { | ||
1603 | if (stats->ErrorFrames < 5) | ||
1604 | printk(KERN_WARNING "fcoe: FCoE version " | ||
1605 | "mismatch: The frame has " | ||
1606 | "version %x, but the " | ||
1607 | "initiator supports version " | ||
1608 | "%x\n", FC_FCOE_DECAPS_VER(hp), | ||
1609 | FC_FCOE_VER); | ||
1610 | stats->ErrorFrames++; | ||
1611 | kfree_skb(skb); | ||
1612 | return; | ||
1613 | } | ||
1614 | |||
1615 | skb_pull(skb, sizeof(struct fcoe_hdr)); | ||
1616 | fr_len = skb->len - sizeof(struct fcoe_crc_eof); | ||
1617 | |||
1618 | stats->RxFrames++; | ||
1619 | stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; | ||
1620 | |||
1621 | fp = (struct fc_frame *)skb; | ||
1622 | fc_frame_init(fp); | ||
1623 | fr_dev(fp) = lport; | ||
1624 | fr_sof(fp) = hp->fcoe_sof; | ||
1625 | |||
1626 | /* Copy out the CRC and EOF trailer for access */ | ||
1627 | if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) { | ||
1628 | kfree_skb(skb); | ||
1629 | return; | ||
1630 | } | ||
1631 | fr_eof(fp) = crc_eof.fcoe_eof; | ||
1632 | fr_crc(fp) = crc_eof.fcoe_crc32; | ||
1633 | if (pskb_trim(skb, fr_len)) { | ||
1634 | kfree_skb(skb); | ||
1635 | return; | ||
1636 | } | ||
1637 | |||
1638 | /* | ||
1639 | * We only check CRC if no offload is available and if it is | ||
1640 | * it's solicited data, in which case, the FCP layer would | ||
1641 | * check it during the copy. | ||
1642 | */ | ||
1643 | if (lport->crc_offload && | ||
1644 | skb->ip_summed == CHECKSUM_UNNECESSARY) | ||
1645 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | ||
1646 | else | ||
1647 | fr_flags(fp) |= FCPHF_CRC_UNCHECKED; | ||
1648 | |||
1649 | fh = fc_frame_header_get(fp); | ||
1650 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && | ||
1651 | fh->fh_type == FC_TYPE_FCP) { | ||
1652 | fc_exch_recv(lport, fp); | ||
1653 | return; | ||
1654 | } | ||
1655 | if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { | ||
1656 | if (le32_to_cpu(fr_crc(fp)) != | ||
1657 | ~crc32(~0, skb->data, fr_len)) { | ||
1658 | if (stats->InvalidCRCCount < 5) | ||
1659 | printk(KERN_WARNING "fcoe: dropping " | ||
1660 | "frame with CRC error\n"); | ||
1661 | stats->InvalidCRCCount++; | ||
1662 | stats->ErrorFrames++; | ||
1663 | fc_frame_free(fp); | ||
1664 | return; | ||
1665 | } | ||
1666 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | ||
1667 | } | ||
1668 | fc_exch_recv(lport, fp); | ||
1669 | } | ||
1670 | |||
1671 | /** | ||
1672 | * fcoe_percpu_receive_thread() - The per-CPU packet receive thread | ||
1673 | * @arg: The per-CPU context | ||
1674 | * | ||
1675 | * Return: 0 for success | ||
1676 | */ | ||
1677 | int fcoe_percpu_receive_thread(void *arg) | ||
1678 | { | ||
1679 | struct fcoe_percpu_s *p = arg; | ||
1680 | struct sk_buff *skb; | ||
1681 | |||
1335 | set_user_nice(current, -20); | 1682 | set_user_nice(current, -20); |
1336 | 1683 | ||
1337 | while (!kthread_should_stop()) { | 1684 | while (!kthread_should_stop()) { |
@@ -1347,129 +1694,27 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1347 | spin_lock_bh(&p->fcoe_rx_list.lock); | 1694 | spin_lock_bh(&p->fcoe_rx_list.lock); |
1348 | } | 1695 | } |
1349 | spin_unlock_bh(&p->fcoe_rx_list.lock); | 1696 | spin_unlock_bh(&p->fcoe_rx_list.lock); |
1350 | fr = fcoe_dev_from_skb(skb); | 1697 | fcoe_recv_frame(skb); |
1351 | lp = fr->fr_dev; | ||
1352 | if (unlikely(lp == NULL)) { | ||
1353 | if (skb->destructor != fcoe_percpu_flush_done) | ||
1354 | FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb"); | ||
1355 | kfree_skb(skb); | ||
1356 | continue; | ||
1357 | } | ||
1358 | |||
1359 | FCOE_NETDEV_DBG(skb->dev, "skb_info: len:%d data_len:%d " | ||
1360 | "head:%p data:%p tail:%p end:%p sum:%d dev:%s", | ||
1361 | skb->len, skb->data_len, | ||
1362 | skb->head, skb->data, skb_tail_pointer(skb), | ||
1363 | skb_end_pointer(skb), skb->csum, | ||
1364 | skb->dev ? skb->dev->name : "<NULL>"); | ||
1365 | |||
1366 | /* | ||
1367 | * Save source MAC address before discarding header. | ||
1368 | */ | ||
1369 | port = lport_priv(lp); | ||
1370 | if (skb_is_nonlinear(skb)) | ||
1371 | skb_linearize(skb); /* not ideal */ | ||
1372 | mac = eth_hdr(skb)->h_source; | ||
1373 | |||
1374 | /* | ||
1375 | * Frame length checks and setting up the header pointers | ||
1376 | * was done in fcoe_rcv already. | ||
1377 | */ | ||
1378 | hp = (struct fcoe_hdr *) skb_network_header(skb); | ||
1379 | fh = (struct fc_frame_header *) skb_transport_header(skb); | ||
1380 | |||
1381 | stats = fc_lport_get_stats(lp); | ||
1382 | if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { | ||
1383 | if (stats->ErrorFrames < 5) | ||
1384 | printk(KERN_WARNING "fcoe: FCoE version " | ||
1385 | "mismatch: The frame has " | ||
1386 | "version %x, but the " | ||
1387 | "initiator supports version " | ||
1388 | "%x\n", FC_FCOE_DECAPS_VER(hp), | ||
1389 | FC_FCOE_VER); | ||
1390 | stats->ErrorFrames++; | ||
1391 | kfree_skb(skb); | ||
1392 | continue; | ||
1393 | } | ||
1394 | |||
1395 | skb_pull(skb, sizeof(struct fcoe_hdr)); | ||
1396 | fr_len = skb->len - sizeof(struct fcoe_crc_eof); | ||
1397 | |||
1398 | stats->RxFrames++; | ||
1399 | stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; | ||
1400 | |||
1401 | fp = (struct fc_frame *)skb; | ||
1402 | fc_frame_init(fp); | ||
1403 | fr_dev(fp) = lp; | ||
1404 | fr_sof(fp) = hp->fcoe_sof; | ||
1405 | |||
1406 | /* Copy out the CRC and EOF trailer for access */ | ||
1407 | if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) { | ||
1408 | kfree_skb(skb); | ||
1409 | continue; | ||
1410 | } | ||
1411 | fr_eof(fp) = crc_eof.fcoe_eof; | ||
1412 | fr_crc(fp) = crc_eof.fcoe_crc32; | ||
1413 | if (pskb_trim(skb, fr_len)) { | ||
1414 | kfree_skb(skb); | ||
1415 | continue; | ||
1416 | } | ||
1417 | |||
1418 | /* | ||
1419 | * We only check CRC if no offload is available and if it is | ||
1420 | * it's solicited data, in which case, the FCP layer would | ||
1421 | * check it during the copy. | ||
1422 | */ | ||
1423 | if (lp->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY) | ||
1424 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | ||
1425 | else | ||
1426 | fr_flags(fp) |= FCPHF_CRC_UNCHECKED; | ||
1427 | |||
1428 | fh = fc_frame_header_get(fp); | ||
1429 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && | ||
1430 | fh->fh_type == FC_TYPE_FCP) { | ||
1431 | fc_exch_recv(lp, fp); | ||
1432 | continue; | ||
1433 | } | ||
1434 | if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { | ||
1435 | if (le32_to_cpu(fr_crc(fp)) != | ||
1436 | ~crc32(~0, skb->data, fr_len)) { | ||
1437 | if (stats->InvalidCRCCount < 5) | ||
1438 | printk(KERN_WARNING "fcoe: dropping " | ||
1439 | "frame with CRC error\n"); | ||
1440 | stats->InvalidCRCCount++; | ||
1441 | stats->ErrorFrames++; | ||
1442 | fc_frame_free(fp); | ||
1443 | continue; | ||
1444 | } | ||
1445 | fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; | ||
1446 | } | ||
1447 | if (unlikely(port->fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN) && | ||
1448 | fcoe_ctlr_recv_flogi(&port->fcoe->ctlr, fp, mac)) { | ||
1449 | fc_frame_free(fp); | ||
1450 | continue; | ||
1451 | } | ||
1452 | fc_exch_recv(lp, fp); | ||
1453 | } | 1698 | } |
1454 | return 0; | 1699 | return 0; |
1455 | } | 1700 | } |
1456 | 1701 | ||
1457 | /** | 1702 | /** |
1458 | * fcoe_check_wait_queue() - attempt to clear the transmit backlog | 1703 | * fcoe_check_wait_queue() - Attempt to clear the transmit backlog |
1459 | * @lp: the fc_lport | 1704 | * @lport: The local port whose backlog is to be cleared |
1460 | * | 1705 | * |
1461 | * This empties the wait_queue, dequeue the head of the wait_queue queue | 1706 | * This empties the wait_queue, dequeues the head of the wait_queue queue |
1462 | * and calls fcoe_start_io() for each packet, if all skb have been | 1707 | * and calls fcoe_start_io() for each packet. If all skb have been |
1463 | * transmitted, return qlen or -1 if a error occurs, then restore | 1708 | * transmitted it returns the qlen. If an error occurs it restores |
1464 | * wait_queue and try again later. | 1709 | * wait_queue (to try again later) and returns -1. |
1465 | * | 1710 | * |
1466 | * The wait_queue is used when the skb transmit fails. skb will go | 1711 | * The wait_queue is used when the skb transmit fails. The failed skb |
1467 | * in the wait_queue which will be emptied by the timer function or | 1712 | * will go in the wait_queue which will be emptied by the timer function or |
1468 | * by the next skb transmit. | 1713 | * by the next skb transmit. |
1469 | */ | 1714 | */ |
1470 | static void fcoe_check_wait_queue(struct fc_lport *lp, struct sk_buff *skb) | 1715 | static void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb) |
1471 | { | 1716 | { |
1472 | struct fcoe_port *port = lport_priv(lp); | 1717 | struct fcoe_port *port = lport_priv(lport); |
1473 | int rc; | 1718 | int rc; |
1474 | 1719 | ||
1475 | spin_lock_bh(&port->fcoe_pending_queue.lock); | 1720 | spin_lock_bh(&port->fcoe_pending_queue.lock); |
@@ -1501,19 +1746,19 @@ static void fcoe_check_wait_queue(struct fc_lport *lp, struct sk_buff *skb) | |||
1501 | } | 1746 | } |
1502 | 1747 | ||
1503 | if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) | 1748 | if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) |
1504 | lp->qfull = 0; | 1749 | lport->qfull = 0; |
1505 | if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) | 1750 | if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) |
1506 | mod_timer(&port->timer, jiffies + 2); | 1751 | mod_timer(&port->timer, jiffies + 2); |
1507 | port->fcoe_pending_queue_active = 0; | 1752 | port->fcoe_pending_queue_active = 0; |
1508 | out: | 1753 | out: |
1509 | if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) | 1754 | if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) |
1510 | lp->qfull = 1; | 1755 | lport->qfull = 1; |
1511 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | 1756 | spin_unlock_bh(&port->fcoe_pending_queue.lock); |
1512 | return; | 1757 | return; |
1513 | } | 1758 | } |
1514 | 1759 | ||
1515 | /** | 1760 | /** |
1516 | * fcoe_dev_setup() - setup link change notification interface | 1761 | * fcoe_dev_setup() - Setup the link change notification interface |
1517 | */ | 1762 | */ |
1518 | static void fcoe_dev_setup(void) | 1763 | static void fcoe_dev_setup(void) |
1519 | { | 1764 | { |
@@ -1521,7 +1766,7 @@ static void fcoe_dev_setup(void) | |||
1521 | } | 1766 | } |
1522 | 1767 | ||
1523 | /** | 1768 | /** |
1524 | * fcoe_dev_cleanup() - cleanup link change notification interface | 1769 | * fcoe_dev_cleanup() - Cleanup the link change notification interface |
1525 | */ | 1770 | */ |
1526 | static void fcoe_dev_cleanup(void) | 1771 | static void fcoe_dev_cleanup(void) |
1527 | { | 1772 | { |
@@ -1529,19 +1774,19 @@ static void fcoe_dev_cleanup(void) | |||
1529 | } | 1774 | } |
1530 | 1775 | ||
1531 | /** | 1776 | /** |
1532 | * fcoe_device_notification() - netdev event notification callback | 1777 | * fcoe_device_notification() - Handler for net device events |
1533 | * @notifier: context of the notification | 1778 | * @notifier: The context of the notification |
1534 | * @event: type of event | 1779 | * @event: The type of event |
1535 | * @ptr: fixed array for output parsed ifname | 1780 | * @ptr: The net device that the event was on |
1536 | * | 1781 | * |
1537 | * This function is called by the ethernet driver in case of link change event | 1782 | * This function is called by the Ethernet driver in case of link change event. |
1538 | * | 1783 | * |
1539 | * Returns: 0 for success | 1784 | * Returns: 0 for success |
1540 | */ | 1785 | */ |
1541 | static int fcoe_device_notification(struct notifier_block *notifier, | 1786 | static int fcoe_device_notification(struct notifier_block *notifier, |
1542 | ulong event, void *ptr) | 1787 | ulong event, void *ptr) |
1543 | { | 1788 | { |
1544 | struct fc_lport *lp = NULL; | 1789 | struct fc_lport *lport = NULL; |
1545 | struct net_device *netdev = ptr; | 1790 | struct net_device *netdev = ptr; |
1546 | struct fcoe_interface *fcoe; | 1791 | struct fcoe_interface *fcoe; |
1547 | struct fcoe_port *port; | 1792 | struct fcoe_port *port; |
@@ -1552,11 +1797,11 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1552 | 1797 | ||
1553 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { | 1798 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { |
1554 | if (fcoe->netdev == netdev) { | 1799 | if (fcoe->netdev == netdev) { |
1555 | lp = fcoe->ctlr.lp; | 1800 | lport = fcoe->ctlr.lp; |
1556 | break; | 1801 | break; |
1557 | } | 1802 | } |
1558 | } | 1803 | } |
1559 | if (lp == NULL) { | 1804 | if (!lport) { |
1560 | rc = NOTIFY_DONE; | 1805 | rc = NOTIFY_DONE; |
1561 | goto out; | 1806 | goto out; |
1562 | } | 1807 | } |
@@ -1570,10 +1815,12 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1570 | case NETDEV_CHANGE: | 1815 | case NETDEV_CHANGE: |
1571 | break; | 1816 | break; |
1572 | case NETDEV_CHANGEMTU: | 1817 | case NETDEV_CHANGEMTU: |
1818 | if (netdev->features & NETIF_F_FCOE_MTU) | ||
1819 | break; | ||
1573 | mfs = netdev->mtu - (sizeof(struct fcoe_hdr) + | 1820 | mfs = netdev->mtu - (sizeof(struct fcoe_hdr) + |
1574 | sizeof(struct fcoe_crc_eof)); | 1821 | sizeof(struct fcoe_crc_eof)); |
1575 | if (mfs >= FC_MIN_MAX_FRAME) | 1822 | if (mfs >= FC_MIN_MAX_FRAME) |
1576 | fc_set_mfs(lp, mfs); | 1823 | fc_set_mfs(lport, mfs); |
1577 | break; | 1824 | break; |
1578 | case NETDEV_REGISTER: | 1825 | case NETDEV_REGISTER: |
1579 | break; | 1826 | break; |
@@ -1588,22 +1835,22 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1588 | FCOE_NETDEV_DBG(netdev, "Unknown event %ld " | 1835 | FCOE_NETDEV_DBG(netdev, "Unknown event %ld " |
1589 | "from netdev netlink\n", event); | 1836 | "from netdev netlink\n", event); |
1590 | } | 1837 | } |
1591 | if (link_possible && !fcoe_link_ok(lp)) | 1838 | if (link_possible && !fcoe_link_ok(lport)) |
1592 | fcoe_ctlr_link_up(&fcoe->ctlr); | 1839 | fcoe_ctlr_link_up(&fcoe->ctlr); |
1593 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { | 1840 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { |
1594 | stats = fc_lport_get_stats(lp); | 1841 | stats = fc_lport_get_stats(lport); |
1595 | stats->LinkFailureCount++; | 1842 | stats->LinkFailureCount++; |
1596 | fcoe_clean_pending_queue(lp); | 1843 | fcoe_clean_pending_queue(lport); |
1597 | } | 1844 | } |
1598 | out: | 1845 | out: |
1599 | return rc; | 1846 | return rc; |
1600 | } | 1847 | } |
1601 | 1848 | ||
1602 | /** | 1849 | /** |
1603 | * fcoe_if_to_netdev() - parse a name buffer to get netdev | 1850 | * fcoe_if_to_netdev() - Parse a name buffer to get a net device |
1604 | * @buffer: incoming buffer to be copied | 1851 | * @buffer: The name of the net device |
1605 | * | 1852 | * |
1606 | * Returns: NULL or ptr to net_device | 1853 | * Returns: NULL or a ptr to net_device |
1607 | */ | 1854 | */ |
1608 | static struct net_device *fcoe_if_to_netdev(const char *buffer) | 1855 | static struct net_device *fcoe_if_to_netdev(const char *buffer) |
1609 | { | 1856 | { |
@@ -1621,9 +1868,109 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) | |||
1621 | } | 1868 | } |
1622 | 1869 | ||
1623 | /** | 1870 | /** |
1624 | * fcoe_destroy() - handles the destroy from sysfs | 1871 | * fcoe_disable() - Disables a FCoE interface |
1625 | * @buffer: expected to be an eth if name | 1872 | * @buffer: The name of the Ethernet interface to be disabled |
1626 | * @kp: associated kernel param | 1873 | * @kp: The associated kernel parameter |
1874 | * | ||
1875 | * Called from sysfs. | ||
1876 | * | ||
1877 | * Returns: 0 for success | ||
1878 | */ | ||
1879 | static int fcoe_disable(const char *buffer, struct kernel_param *kp) | ||
1880 | { | ||
1881 | struct fcoe_interface *fcoe; | ||
1882 | struct net_device *netdev; | ||
1883 | int rc = 0; | ||
1884 | |||
1885 | mutex_lock(&fcoe_config_mutex); | ||
1886 | #ifdef CONFIG_FCOE_MODULE | ||
1887 | /* | ||
1888 | * Make sure the module has been initialized, and is not about to be | ||
1889 | * removed. Module paramter sysfs files are writable before the | ||
1890 | * module_init function is called and after module_exit. | ||
1891 | */ | ||
1892 | if (THIS_MODULE->state != MODULE_STATE_LIVE) { | ||
1893 | rc = -ENODEV; | ||
1894 | goto out_nodev; | ||
1895 | } | ||
1896 | #endif | ||
1897 | |||
1898 | netdev = fcoe_if_to_netdev(buffer); | ||
1899 | if (!netdev) { | ||
1900 | rc = -ENODEV; | ||
1901 | goto out_nodev; | ||
1902 | } | ||
1903 | |||
1904 | rtnl_lock(); | ||
1905 | fcoe = fcoe_hostlist_lookup_port(netdev); | ||
1906 | rtnl_unlock(); | ||
1907 | |||
1908 | if (fcoe) | ||
1909 | fc_fabric_logoff(fcoe->ctlr.lp); | ||
1910 | else | ||
1911 | rc = -ENODEV; | ||
1912 | |||
1913 | dev_put(netdev); | ||
1914 | out_nodev: | ||
1915 | mutex_unlock(&fcoe_config_mutex); | ||
1916 | return rc; | ||
1917 | } | ||
1918 | |||
1919 | /** | ||
1920 | * fcoe_enable() - Enables a FCoE interface | ||
1921 | * @buffer: The name of the Ethernet interface to be enabled | ||
1922 | * @kp: The associated kernel parameter | ||
1923 | * | ||
1924 | * Called from sysfs. | ||
1925 | * | ||
1926 | * Returns: 0 for success | ||
1927 | */ | ||
1928 | static int fcoe_enable(const char *buffer, struct kernel_param *kp) | ||
1929 | { | ||
1930 | struct fcoe_interface *fcoe; | ||
1931 | struct net_device *netdev; | ||
1932 | int rc = 0; | ||
1933 | |||
1934 | mutex_lock(&fcoe_config_mutex); | ||
1935 | #ifdef CONFIG_FCOE_MODULE | ||
1936 | /* | ||
1937 | * Make sure the module has been initialized, and is not about to be | ||
1938 | * removed. Module paramter sysfs files are writable before the | ||
1939 | * module_init function is called and after module_exit. | ||
1940 | */ | ||
1941 | if (THIS_MODULE->state != MODULE_STATE_LIVE) { | ||
1942 | rc = -ENODEV; | ||
1943 | goto out_nodev; | ||
1944 | } | ||
1945 | #endif | ||
1946 | |||
1947 | netdev = fcoe_if_to_netdev(buffer); | ||
1948 | if (!netdev) { | ||
1949 | rc = -ENODEV; | ||
1950 | goto out_nodev; | ||
1951 | } | ||
1952 | |||
1953 | rtnl_lock(); | ||
1954 | fcoe = fcoe_hostlist_lookup_port(netdev); | ||
1955 | rtnl_unlock(); | ||
1956 | |||
1957 | if (fcoe) | ||
1958 | rc = fc_fabric_login(fcoe->ctlr.lp); | ||
1959 | else | ||
1960 | rc = -ENODEV; | ||
1961 | |||
1962 | dev_put(netdev); | ||
1963 | out_nodev: | ||
1964 | mutex_unlock(&fcoe_config_mutex); | ||
1965 | return rc; | ||
1966 | } | ||
1967 | |||
1968 | /** | ||
1969 | * fcoe_destroy() - Destroy a FCoE interface | ||
1970 | * @buffer: The name of the Ethernet interface to be destroyed | ||
1971 | * @kp: The associated kernel parameter | ||
1972 | * | ||
1973 | * Called from sysfs. | ||
1627 | * | 1974 | * |
1628 | * Returns: 0 for success | 1975 | * Returns: 0 for success |
1629 | */ | 1976 | */ |
@@ -1631,7 +1978,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | |||
1631 | { | 1978 | { |
1632 | struct fcoe_interface *fcoe; | 1979 | struct fcoe_interface *fcoe; |
1633 | struct net_device *netdev; | 1980 | struct net_device *netdev; |
1634 | int rc; | 1981 | int rc = 0; |
1635 | 1982 | ||
1636 | mutex_lock(&fcoe_config_mutex); | 1983 | mutex_lock(&fcoe_config_mutex); |
1637 | #ifdef CONFIG_FCOE_MODULE | 1984 | #ifdef CONFIG_FCOE_MODULE |
@@ -1663,6 +2010,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) | |||
1663 | fcoe_interface_cleanup(fcoe); | 2010 | fcoe_interface_cleanup(fcoe); |
1664 | rtnl_unlock(); | 2011 | rtnl_unlock(); |
1665 | fcoe_if_destroy(fcoe->ctlr.lp); | 2012 | fcoe_if_destroy(fcoe->ctlr.lp); |
2013 | module_put(THIS_MODULE); | ||
2014 | |||
1666 | out_putdev: | 2015 | out_putdev: |
1667 | dev_put(netdev); | 2016 | dev_put(netdev); |
1668 | out_nodev: | 2017 | out_nodev: |
@@ -1670,6 +2019,10 @@ out_nodev: | |||
1670 | return rc; | 2019 | return rc; |
1671 | } | 2020 | } |
1672 | 2021 | ||
2022 | /** | ||
2023 | * fcoe_destroy_work() - Destroy a FCoE port in a deferred work context | ||
2024 | * @work: Handle to the FCoE port to be destroyed | ||
2025 | */ | ||
1673 | static void fcoe_destroy_work(struct work_struct *work) | 2026 | static void fcoe_destroy_work(struct work_struct *work) |
1674 | { | 2027 | { |
1675 | struct fcoe_port *port; | 2028 | struct fcoe_port *port; |
@@ -1681,9 +2034,11 @@ static void fcoe_destroy_work(struct work_struct *work) | |||
1681 | } | 2034 | } |
1682 | 2035 | ||
1683 | /** | 2036 | /** |
1684 | * fcoe_create() - Handles the create call from sysfs | 2037 | * fcoe_create() - Create a fcoe interface |
1685 | * @buffer: expected to be an eth if name | 2038 | * @buffer: The name of the Ethernet interface to create on |
1686 | * @kp: associated kernel param | 2039 | * @kp: The associated kernel param |
2040 | * | ||
2041 | * Called from sysfs. | ||
1687 | * | 2042 | * |
1688 | * Returns: 0 for success | 2043 | * Returns: 0 for success |
1689 | */ | 2044 | */ |
@@ -1707,6 +2062,11 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
1707 | } | 2062 | } |
1708 | #endif | 2063 | #endif |
1709 | 2064 | ||
2065 | if (!try_module_get(THIS_MODULE)) { | ||
2066 | rc = -EINVAL; | ||
2067 | goto out_nomod; | ||
2068 | } | ||
2069 | |||
1710 | rtnl_lock(); | 2070 | rtnl_lock(); |
1711 | netdev = fcoe_if_to_netdev(buffer); | 2071 | netdev = fcoe_if_to_netdev(buffer); |
1712 | if (!netdev) { | 2072 | if (!netdev) { |
@@ -1726,7 +2086,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
1726 | goto out_putdev; | 2086 | goto out_putdev; |
1727 | } | 2087 | } |
1728 | 2088 | ||
1729 | lport = fcoe_if_create(fcoe, &netdev->dev); | 2089 | lport = fcoe_if_create(fcoe, &netdev->dev, 0); |
1730 | if (IS_ERR(lport)) { | 2090 | if (IS_ERR(lport)) { |
1731 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", | 2091 | printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", |
1732 | netdev->name); | 2092 | netdev->name); |
@@ -1747,31 +2107,31 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) | |||
1747 | if (!fcoe_link_ok(lport)) | 2107 | if (!fcoe_link_ok(lport)) |
1748 | fcoe_ctlr_link_up(&fcoe->ctlr); | 2108 | fcoe_ctlr_link_up(&fcoe->ctlr); |
1749 | 2109 | ||
1750 | rc = 0; | ||
1751 | out_free: | ||
1752 | /* | 2110 | /* |
1753 | * Release from init in fcoe_interface_create(), on success lport | 2111 | * Release from init in fcoe_interface_create(), on success lport |
1754 | * should be holding a reference taken in fcoe_if_create(). | 2112 | * should be holding a reference taken in fcoe_if_create(). |
1755 | */ | 2113 | */ |
1756 | fcoe_interface_put(fcoe); | 2114 | fcoe_interface_put(fcoe); |
2115 | dev_put(netdev); | ||
2116 | rtnl_unlock(); | ||
2117 | mutex_unlock(&fcoe_config_mutex); | ||
2118 | |||
2119 | return 0; | ||
2120 | out_free: | ||
2121 | fcoe_interface_put(fcoe); | ||
1757 | out_putdev: | 2122 | out_putdev: |
1758 | dev_put(netdev); | 2123 | dev_put(netdev); |
1759 | out_nodev: | 2124 | out_nodev: |
1760 | rtnl_unlock(); | 2125 | rtnl_unlock(); |
2126 | module_put(THIS_MODULE); | ||
2127 | out_nomod: | ||
1761 | mutex_unlock(&fcoe_config_mutex); | 2128 | mutex_unlock(&fcoe_config_mutex); |
1762 | return rc; | 2129 | return rc; |
1763 | } | 2130 | } |
1764 | 2131 | ||
1765 | module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR); | ||
1766 | __MODULE_PARM_TYPE(create, "string"); | ||
1767 | MODULE_PARM_DESC(create, "Create fcoe fcoe using net device passed in."); | ||
1768 | module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); | ||
1769 | __MODULE_PARM_TYPE(destroy, "string"); | ||
1770 | MODULE_PARM_DESC(destroy, "Destroy fcoe fcoe"); | ||
1771 | |||
1772 | /** | 2132 | /** |
1773 | * fcoe_link_ok() - Check if link is ok for the fc_lport | 2133 | * fcoe_link_ok() - Check if the link is OK for a local port |
1774 | * @lp: ptr to the fc_lport | 2134 | * @lport: The local port to check link on |
1775 | * | 2135 | * |
1776 | * Any permanently-disqualifying conditions have been previously checked. | 2136 | * Any permanently-disqualifying conditions have been previously checked. |
1777 | * This also updates the speed setting, which may change with link for 100/1000. | 2137 | * This also updates the speed setting, which may change with link for 100/1000. |
@@ -1783,26 +2143,26 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe fcoe"); | |||
1783 | * Returns: 0 if link is OK for use by FCoE. | 2143 | * Returns: 0 if link is OK for use by FCoE. |
1784 | * | 2144 | * |
1785 | */ | 2145 | */ |
1786 | int fcoe_link_ok(struct fc_lport *lp) | 2146 | int fcoe_link_ok(struct fc_lport *lport) |
1787 | { | 2147 | { |
1788 | struct fcoe_port *port = lport_priv(lp); | 2148 | struct fcoe_port *port = lport_priv(lport); |
1789 | struct net_device *dev = port->fcoe->netdev; | 2149 | struct net_device *netdev = port->fcoe->netdev; |
1790 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; | 2150 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; |
1791 | 2151 | ||
1792 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && | 2152 | if ((netdev->flags & IFF_UP) && netif_carrier_ok(netdev) && |
1793 | (!dev_ethtool_get_settings(dev, &ecmd))) { | 2153 | (!dev_ethtool_get_settings(netdev, &ecmd))) { |
1794 | lp->link_supported_speeds &= | 2154 | lport->link_supported_speeds &= |
1795 | ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); | 2155 | ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); |
1796 | if (ecmd.supported & (SUPPORTED_1000baseT_Half | | 2156 | if (ecmd.supported & (SUPPORTED_1000baseT_Half | |
1797 | SUPPORTED_1000baseT_Full)) | 2157 | SUPPORTED_1000baseT_Full)) |
1798 | lp->link_supported_speeds |= FC_PORTSPEED_1GBIT; | 2158 | lport->link_supported_speeds |= FC_PORTSPEED_1GBIT; |
1799 | if (ecmd.supported & SUPPORTED_10000baseT_Full) | 2159 | if (ecmd.supported & SUPPORTED_10000baseT_Full) |
1800 | lp->link_supported_speeds |= | 2160 | lport->link_supported_speeds |= |
1801 | FC_PORTSPEED_10GBIT; | 2161 | FC_PORTSPEED_10GBIT; |
1802 | if (ecmd.speed == SPEED_1000) | 2162 | if (ecmd.speed == SPEED_1000) |
1803 | lp->link_speed = FC_PORTSPEED_1GBIT; | 2163 | lport->link_speed = FC_PORTSPEED_1GBIT; |
1804 | if (ecmd.speed == SPEED_10000) | 2164 | if (ecmd.speed == SPEED_10000) |
1805 | lp->link_speed = FC_PORTSPEED_10GBIT; | 2165 | lport->link_speed = FC_PORTSPEED_10GBIT; |
1806 | 2166 | ||
1807 | return 0; | 2167 | return 0; |
1808 | } | 2168 | } |
@@ -1810,8 +2170,8 @@ int fcoe_link_ok(struct fc_lport *lp) | |||
1810 | } | 2170 | } |
1811 | 2171 | ||
1812 | /** | 2172 | /** |
1813 | * fcoe_percpu_clean() - Clear the pending skbs for an lport | 2173 | * fcoe_percpu_clean() - Clear all pending skbs for an local port |
1814 | * @lp: the fc_lport | 2174 | * @lport: The local port whose skbs are to be cleared |
1815 | * | 2175 | * |
1816 | * Must be called with fcoe_create_mutex held to single-thread completion. | 2176 | * Must be called with fcoe_create_mutex held to single-thread completion. |
1817 | * | 2177 | * |
@@ -1820,7 +2180,7 @@ int fcoe_link_ok(struct fc_lport *lp) | |||
1820 | * there no packets that will be handled by the lport, but also that any | 2180 | * there no packets that will be handled by the lport, but also that any |
1821 | * threads already handling packet have returned. | 2181 | * threads already handling packet have returned. |
1822 | */ | 2182 | */ |
1823 | void fcoe_percpu_clean(struct fc_lport *lp) | 2183 | void fcoe_percpu_clean(struct fc_lport *lport) |
1824 | { | 2184 | { |
1825 | struct fcoe_percpu_s *pp; | 2185 | struct fcoe_percpu_s *pp; |
1826 | struct fcoe_rcv_info *fr; | 2186 | struct fcoe_rcv_info *fr; |
@@ -1838,7 +2198,7 @@ void fcoe_percpu_clean(struct fc_lport *lp) | |||
1838 | skb = next) { | 2198 | skb = next) { |
1839 | next = skb->next; | 2199 | next = skb->next; |
1840 | fr = fcoe_dev_from_skb(skb); | 2200 | fr = fcoe_dev_from_skb(skb); |
1841 | if (fr->fr_dev == lp) { | 2201 | if (fr->fr_dev == lport) { |
1842 | __skb_unlink(skb, list); | 2202 | __skb_unlink(skb, list); |
1843 | kfree_skb(skb); | 2203 | kfree_skb(skb); |
1844 | } | 2204 | } |
@@ -1867,13 +2227,11 @@ void fcoe_percpu_clean(struct fc_lport *lp) | |||
1867 | 2227 | ||
1868 | /** | 2228 | /** |
1869 | * fcoe_clean_pending_queue() - Dequeue a skb and free it | 2229 | * fcoe_clean_pending_queue() - Dequeue a skb and free it |
1870 | * @lp: the corresponding fc_lport | 2230 | * @lport: The local port to dequeue a skb on |
1871 | * | ||
1872 | * Returns: none | ||
1873 | */ | 2231 | */ |
1874 | void fcoe_clean_pending_queue(struct fc_lport *lp) | 2232 | void fcoe_clean_pending_queue(struct fc_lport *lport) |
1875 | { | 2233 | { |
1876 | struct fcoe_port *port = lport_priv(lp); | 2234 | struct fcoe_port *port = lport_priv(lport); |
1877 | struct sk_buff *skb; | 2235 | struct sk_buff *skb; |
1878 | 2236 | ||
1879 | spin_lock_bh(&port->fcoe_pending_queue.lock); | 2237 | spin_lock_bh(&port->fcoe_pending_queue.lock); |
@@ -1886,10 +2244,10 @@ void fcoe_clean_pending_queue(struct fc_lport *lp) | |||
1886 | } | 2244 | } |
1887 | 2245 | ||
1888 | /** | 2246 | /** |
1889 | * fcoe_reset() - Resets the fcoe | 2247 | * fcoe_reset() - Reset a local port |
1890 | * @shost: shost the reset is from | 2248 | * @shost: The SCSI host associated with the local port to be reset |
1891 | * | 2249 | * |
1892 | * Returns: always 0 | 2250 | * Returns: Always 0 (return value required by FC transport template) |
1893 | */ | 2251 | */ |
1894 | int fcoe_reset(struct Scsi_Host *shost) | 2252 | int fcoe_reset(struct Scsi_Host *shost) |
1895 | { | 2253 | { |
@@ -1899,30 +2257,33 @@ int fcoe_reset(struct Scsi_Host *shost) | |||
1899 | } | 2257 | } |
1900 | 2258 | ||
1901 | /** | 2259 | /** |
1902 | * fcoe_hostlist_lookup_port() - find the corresponding lport by a given device | 2260 | * fcoe_hostlist_lookup_port() - Find the FCoE interface associated with a net device |
1903 | * @dev: this is currently ptr to net_device | 2261 | * @netdev: The net device used as a key |
1904 | * | 2262 | * |
1905 | * Returns: NULL or the located fcoe_port | 2263 | * Locking: Must be called with the RNL mutex held. |
1906 | * Locking: must be called with the RNL mutex held | 2264 | * |
2265 | * Returns: NULL or the FCoE interface | ||
1907 | */ | 2266 | */ |
1908 | static struct fcoe_interface * | 2267 | static struct fcoe_interface * |
1909 | fcoe_hostlist_lookup_port(const struct net_device *dev) | 2268 | fcoe_hostlist_lookup_port(const struct net_device *netdev) |
1910 | { | 2269 | { |
1911 | struct fcoe_interface *fcoe; | 2270 | struct fcoe_interface *fcoe; |
1912 | 2271 | ||
1913 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { | 2272 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { |
1914 | if (fcoe->netdev == dev) | 2273 | if (fcoe->netdev == netdev) |
1915 | return fcoe; | 2274 | return fcoe; |
1916 | } | 2275 | } |
1917 | return NULL; | 2276 | return NULL; |
1918 | } | 2277 | } |
1919 | 2278 | ||
1920 | /** | 2279 | /** |
1921 | * fcoe_hostlist_lookup() - Find the corresponding lport by netdev | 2280 | * fcoe_hostlist_lookup() - Find the local port associated with a |
1922 | * @netdev: ptr to net_device | 2281 | * given net device |
2282 | * @netdev: The netdevice used as a key | ||
1923 | * | 2283 | * |
1924 | * Returns: 0 for success | 2284 | * Locking: Must be called with the RTNL mutex held |
1925 | * Locking: must be called with the RTNL mutex held | 2285 | * |
2286 | * Returns: NULL or the local port | ||
1926 | */ | 2287 | */ |
1927 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) | 2288 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) |
1928 | { | 2289 | { |
@@ -1933,11 +2294,13 @@ static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) | |||
1933 | } | 2294 | } |
1934 | 2295 | ||
1935 | /** | 2296 | /** |
1936 | * fcoe_hostlist_add() - Add a lport to lports list | 2297 | * fcoe_hostlist_add() - Add the FCoE interface identified by a local |
1937 | * @lp: ptr to the fc_lport to be added | 2298 | * port to the hostlist |
2299 | * @lport: The local port that identifies the FCoE interface to be added | ||
1938 | * | 2300 | * |
1939 | * Returns: 0 for success | ||
1940 | * Locking: must be called with the RTNL mutex held | 2301 | * Locking: must be called with the RTNL mutex held |
2302 | * | ||
2303 | * Returns: 0 for success | ||
1941 | */ | 2304 | */ |
1942 | static int fcoe_hostlist_add(const struct fc_lport *lport) | 2305 | static int fcoe_hostlist_add(const struct fc_lport *lport) |
1943 | { | 2306 | { |
@@ -1954,15 +2317,15 @@ static int fcoe_hostlist_add(const struct fc_lport *lport) | |||
1954 | } | 2317 | } |
1955 | 2318 | ||
1956 | /** | 2319 | /** |
1957 | * fcoe_init() - fcoe module loading initialization | 2320 | * fcoe_init() - Initialize fcoe.ko |
1958 | * | 2321 | * |
1959 | * Returns 0 on success, negative on failure | 2322 | * Returns: 0 on success, or a negative value on failure |
1960 | */ | 2323 | */ |
1961 | static int __init fcoe_init(void) | 2324 | static int __init fcoe_init(void) |
1962 | { | 2325 | { |
2326 | struct fcoe_percpu_s *p; | ||
1963 | unsigned int cpu; | 2327 | unsigned int cpu; |
1964 | int rc = 0; | 2328 | int rc = 0; |
1965 | struct fcoe_percpu_s *p; | ||
1966 | 2329 | ||
1967 | mutex_lock(&fcoe_config_mutex); | 2330 | mutex_lock(&fcoe_config_mutex); |
1968 | 2331 | ||
@@ -1999,15 +2362,15 @@ out_free: | |||
1999 | module_init(fcoe_init); | 2362 | module_init(fcoe_init); |
2000 | 2363 | ||
2001 | /** | 2364 | /** |
2002 | * fcoe_exit() - fcoe module unloading cleanup | 2365 | * fcoe_exit() - Clean up fcoe.ko |
2003 | * | 2366 | * |
2004 | * Returns 0 on success, negative on failure | 2367 | * Returns: 0 on success or a negative value on failure |
2005 | */ | 2368 | */ |
2006 | static void __exit fcoe_exit(void) | 2369 | static void __exit fcoe_exit(void) |
2007 | { | 2370 | { |
2008 | unsigned int cpu; | ||
2009 | struct fcoe_interface *fcoe, *tmp; | 2371 | struct fcoe_interface *fcoe, *tmp; |
2010 | struct fcoe_port *port; | 2372 | struct fcoe_port *port; |
2373 | unsigned int cpu; | ||
2011 | 2374 | ||
2012 | mutex_lock(&fcoe_config_mutex); | 2375 | mutex_lock(&fcoe_config_mutex); |
2013 | 2376 | ||
@@ -2033,9 +2396,238 @@ static void __exit fcoe_exit(void) | |||
2033 | /* flush any asyncronous interface destroys, | 2396 | /* flush any asyncronous interface destroys, |
2034 | * this should happen after the netdev notifier is unregistered */ | 2397 | * this should happen after the netdev notifier is unregistered */ |
2035 | flush_scheduled_work(); | 2398 | flush_scheduled_work(); |
2399 | /* That will flush out all the N_Ports on the hostlist, but now we | ||
2400 | * may have NPIV VN_Ports scheduled for destruction */ | ||
2401 | flush_scheduled_work(); | ||
2036 | 2402 | ||
2037 | /* detach from scsi transport | 2403 | /* detach from scsi transport |
2038 | * must happen after all destroys are done, therefor after the flush */ | 2404 | * must happen after all destroys are done, therefor after the flush */ |
2039 | fcoe_if_exit(); | 2405 | fcoe_if_exit(); |
2040 | } | 2406 | } |
2041 | module_exit(fcoe_exit); | 2407 | module_exit(fcoe_exit); |
2408 | |||
2409 | /** | ||
2410 | * fcoe_flogi_resp() - FCoE specific FLOGI and FDISC response handler | ||
2411 | * @seq: active sequence in the FLOGI or FDISC exchange | ||
2412 | * @fp: response frame, or error encoded in a pointer (timeout) | ||
2413 | * @arg: pointer the the fcoe_ctlr structure | ||
2414 | * | ||
2415 | * This handles MAC address managment for FCoE, then passes control on to | ||
2416 | * the libfc FLOGI response handler. | ||
2417 | */ | ||
2418 | static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | ||
2419 | { | ||
2420 | struct fcoe_ctlr *fip = arg; | ||
2421 | struct fc_exch *exch = fc_seq_exch(seq); | ||
2422 | struct fc_lport *lport = exch->lp; | ||
2423 | u8 *mac; | ||
2424 | |||
2425 | if (IS_ERR(fp)) | ||
2426 | goto done; | ||
2427 | |||
2428 | mac = fr_cb(fp)->granted_mac; | ||
2429 | if (is_zero_ether_addr(mac)) { | ||
2430 | /* pre-FIP */ | ||
2431 | if (fcoe_ctlr_recv_flogi(fip, lport, fp)) { | ||
2432 | fc_frame_free(fp); | ||
2433 | return; | ||
2434 | } | ||
2435 | } | ||
2436 | fcoe_update_src_mac(lport, mac); | ||
2437 | done: | ||
2438 | fc_lport_flogi_resp(seq, fp, lport); | ||
2439 | } | ||
2440 | |||
2441 | /** | ||
2442 | * fcoe_logo_resp() - FCoE specific LOGO response handler | ||
2443 | * @seq: active sequence in the LOGO exchange | ||
2444 | * @fp: response frame, or error encoded in a pointer (timeout) | ||
2445 | * @arg: pointer the the fcoe_ctlr structure | ||
2446 | * | ||
2447 | * This handles MAC address managment for FCoE, then passes control on to | ||
2448 | * the libfc LOGO response handler. | ||
2449 | */ | ||
2450 | static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | ||
2451 | { | ||
2452 | struct fc_lport *lport = arg; | ||
2453 | static u8 zero_mac[ETH_ALEN] = { 0 }; | ||
2454 | |||
2455 | if (!IS_ERR(fp)) | ||
2456 | fcoe_update_src_mac(lport, zero_mac); | ||
2457 | fc_lport_logo_resp(seq, fp, lport); | ||
2458 | } | ||
2459 | |||
2460 | /** | ||
2461 | * fcoe_elsct_send - FCoE specific ELS handler | ||
2462 | * | ||
2463 | * This does special case handling of FIP encapsualted ELS exchanges for FCoE, | ||
2464 | * using FCoE specific response handlers and passing the FIP controller as | ||
2465 | * the argument (the lport is still available from the exchange). | ||
2466 | * | ||
2467 | * Most of the work here is just handed off to the libfc routine. | ||
2468 | */ | ||
2469 | static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did, | ||
2470 | struct fc_frame *fp, unsigned int op, | ||
2471 | void (*resp)(struct fc_seq *, | ||
2472 | struct fc_frame *, | ||
2473 | void *), | ||
2474 | void *arg, u32 timeout) | ||
2475 | { | ||
2476 | struct fcoe_port *port = lport_priv(lport); | ||
2477 | struct fcoe_interface *fcoe = port->fcoe; | ||
2478 | struct fcoe_ctlr *fip = &fcoe->ctlr; | ||
2479 | struct fc_frame_header *fh = fc_frame_header_get(fp); | ||
2480 | |||
2481 | switch (op) { | ||
2482 | case ELS_FLOGI: | ||
2483 | case ELS_FDISC: | ||
2484 | return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp, | ||
2485 | fip, timeout); | ||
2486 | case ELS_LOGO: | ||
2487 | /* only hook onto fabric logouts, not port logouts */ | ||
2488 | if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI) | ||
2489 | break; | ||
2490 | return fc_elsct_send(lport, did, fp, op, fcoe_logo_resp, | ||
2491 | lport, timeout); | ||
2492 | } | ||
2493 | return fc_elsct_send(lport, did, fp, op, resp, arg, timeout); | ||
2494 | } | ||
2495 | |||
2496 | /** | ||
2497 | * fcoe_vport_create() - create an fc_host/scsi_host for a vport | ||
2498 | * @vport: fc_vport object to create a new fc_host for | ||
2499 | * @disabled: start the new fc_host in a disabled state by default? | ||
2500 | * | ||
2501 | * Returns: 0 for success | ||
2502 | */ | ||
2503 | static int fcoe_vport_create(struct fc_vport *vport, bool disabled) | ||
2504 | { | ||
2505 | struct Scsi_Host *shost = vport_to_shost(vport); | ||
2506 | struct fc_lport *n_port = shost_priv(shost); | ||
2507 | struct fcoe_port *port = lport_priv(n_port); | ||
2508 | struct fcoe_interface *fcoe = port->fcoe; | ||
2509 | struct net_device *netdev = fcoe->netdev; | ||
2510 | struct fc_lport *vn_port; | ||
2511 | |||
2512 | mutex_lock(&fcoe_config_mutex); | ||
2513 | vn_port = fcoe_if_create(fcoe, &vport->dev, 1); | ||
2514 | mutex_unlock(&fcoe_config_mutex); | ||
2515 | |||
2516 | if (IS_ERR(vn_port)) { | ||
2517 | printk(KERN_ERR "fcoe: fcoe_vport_create(%s) failed\n", | ||
2518 | netdev->name); | ||
2519 | return -EIO; | ||
2520 | } | ||
2521 | |||
2522 | if (disabled) { | ||
2523 | fc_vport_set_state(vport, FC_VPORT_DISABLED); | ||
2524 | } else { | ||
2525 | vn_port->boot_time = jiffies; | ||
2526 | fc_fabric_login(vn_port); | ||
2527 | fc_vport_setlink(vn_port); | ||
2528 | } | ||
2529 | return 0; | ||
2530 | } | ||
2531 | |||
2532 | /** | ||
2533 | * fcoe_vport_destroy() - destroy the fc_host/scsi_host for a vport | ||
2534 | * @vport: fc_vport object that is being destroyed | ||
2535 | * | ||
2536 | * Returns: 0 for success | ||
2537 | */ | ||
2538 | static int fcoe_vport_destroy(struct fc_vport *vport) | ||
2539 | { | ||
2540 | struct Scsi_Host *shost = vport_to_shost(vport); | ||
2541 | struct fc_lport *n_port = shost_priv(shost); | ||
2542 | struct fc_lport *vn_port = vport->dd_data; | ||
2543 | struct fcoe_port *port = lport_priv(vn_port); | ||
2544 | |||
2545 | mutex_lock(&n_port->lp_mutex); | ||
2546 | list_del(&vn_port->list); | ||
2547 | mutex_unlock(&n_port->lp_mutex); | ||
2548 | schedule_work(&port->destroy_work); | ||
2549 | return 0; | ||
2550 | } | ||
2551 | |||
2552 | /** | ||
2553 | * fcoe_vport_disable() - change vport state | ||
2554 | * @vport: vport to bring online/offline | ||
2555 | * @disable: should the vport be disabled? | ||
2556 | */ | ||
2557 | static int fcoe_vport_disable(struct fc_vport *vport, bool disable) | ||
2558 | { | ||
2559 | struct fc_lport *lport = vport->dd_data; | ||
2560 | |||
2561 | if (disable) { | ||
2562 | fc_vport_set_state(vport, FC_VPORT_DISABLED); | ||
2563 | fc_fabric_logoff(lport); | ||
2564 | } else { | ||
2565 | lport->boot_time = jiffies; | ||
2566 | fc_fabric_login(lport); | ||
2567 | fc_vport_setlink(lport); | ||
2568 | } | ||
2569 | |||
2570 | return 0; | ||
2571 | } | ||
2572 | |||
2573 | /** | ||
2574 | * fcoe_vport_set_symbolic_name() - append vport string to symbolic name | ||
2575 | * @vport: fc_vport with a new symbolic name string | ||
2576 | * | ||
2577 | * After generating a new symbolic name string, a new RSPN_ID request is | ||
2578 | * sent to the name server. There is no response handler, so if it fails | ||
2579 | * for some reason it will not be retried. | ||
2580 | */ | ||
2581 | static void fcoe_set_vport_symbolic_name(struct fc_vport *vport) | ||
2582 | { | ||
2583 | struct fc_lport *lport = vport->dd_data; | ||
2584 | struct fc_frame *fp; | ||
2585 | size_t len; | ||
2586 | |||
2587 | snprintf(fc_host_symbolic_name(lport->host), FC_SYMBOLIC_NAME_SIZE, | ||
2588 | "%s v%s over %s : %s", FCOE_NAME, FCOE_VERSION, | ||
2589 | fcoe_netdev(lport)->name, vport->symbolic_name); | ||
2590 | |||
2591 | if (lport->state != LPORT_ST_READY) | ||
2592 | return; | ||
2593 | |||
2594 | len = strnlen(fc_host_symbolic_name(lport->host), 255); | ||
2595 | fp = fc_frame_alloc(lport, | ||
2596 | sizeof(struct fc_ct_hdr) + | ||
2597 | sizeof(struct fc_ns_rspn) + len); | ||
2598 | if (!fp) | ||
2599 | return; | ||
2600 | lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RSPN_ID, | ||
2601 | NULL, NULL, 3 * lport->r_a_tov); | ||
2602 | } | ||
2603 | |||
2604 | /** | ||
2605 | * fcoe_get_lesb() - Fill the FCoE Link Error Status Block | ||
2606 | * @lport: the local port | ||
2607 | * @fc_lesb: the link error status block | ||
2608 | */ | ||
2609 | static void fcoe_get_lesb(struct fc_lport *lport, | ||
2610 | struct fc_els_lesb *fc_lesb) | ||
2611 | { | ||
2612 | unsigned int cpu; | ||
2613 | u32 lfc, vlfc, mdac; | ||
2614 | struct fcoe_dev_stats *devst; | ||
2615 | struct fcoe_fc_els_lesb *lesb; | ||
2616 | struct net_device *netdev = fcoe_netdev(lport); | ||
2617 | |||
2618 | lfc = 0; | ||
2619 | vlfc = 0; | ||
2620 | mdac = 0; | ||
2621 | lesb = (struct fcoe_fc_els_lesb *)fc_lesb; | ||
2622 | memset(lesb, 0, sizeof(*lesb)); | ||
2623 | for_each_possible_cpu(cpu) { | ||
2624 | devst = per_cpu_ptr(lport->dev_stats, cpu); | ||
2625 | lfc += devst->LinkFailureCount; | ||
2626 | vlfc += devst->VLinkFailureCount; | ||
2627 | mdac += devst->MissDiscAdvCount; | ||
2628 | } | ||
2629 | lesb->lesb_link_fail = htonl(lfc); | ||
2630 | lesb->lesb_vlink_fail = htonl(vlfc); | ||
2631 | lesb->lesb_miss_fka = htonl(mdac); | ||
2632 | lesb->lesb_fcs_error = htonl(dev_get_stats(netdev)->rx_crc_errors); | ||
2633 | } | ||
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index ce7f60fb1bc0..c69b2c56c2d1 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h | |||
@@ -32,7 +32,7 @@ | |||
32 | #define FCOE_NAME "fcoe" | 32 | #define FCOE_NAME "fcoe" |
33 | #define FCOE_VENDOR "Open-FCoE.org" | 33 | #define FCOE_VENDOR "Open-FCoE.org" |
34 | 34 | ||
35 | #define FCOE_MAX_LUN 255 | 35 | #define FCOE_MAX_LUN 0xFFFF |
36 | #define FCOE_MAX_FCP_TARGET 256 | 36 | #define FCOE_MAX_FCP_TARGET 256 |
37 | 37 | ||
38 | #define FCOE_MAX_OUTSTANDING_COMMANDS 1024 | 38 | #define FCOE_MAX_OUTSTANDING_COMMANDS 1024 |
@@ -40,11 +40,17 @@ | |||
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 | |||
43 | unsigned int fcoe_debug_logging; | 49 | unsigned int fcoe_debug_logging; |
44 | module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); | 50 | module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); |
45 | MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); | 51 | MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); |
46 | 52 | ||
47 | #define FCOE_LOGGING 0x01 /* General logging, not categorized */ | 53 | #define FCOE_LOGGING 0x01 /* General logging, not categorized */ |
48 | #define FCOE_NETDEV_LOGGING 0x02 /* Netdevice logging */ | 54 | #define FCOE_NETDEV_LOGGING 0x02 /* Netdevice logging */ |
49 | 55 | ||
50 | #define FCOE_CHECK_LOGGING(LEVEL, CMD) \ | 56 | #define FCOE_CHECK_LOGGING(LEVEL, CMD) \ |
@@ -64,8 +70,13 @@ do { \ | |||
64 | printk(KERN_INFO "fcoe: %s: " fmt, \ | 70 | printk(KERN_INFO "fcoe: %s: " fmt, \ |
65 | netdev->name, ##args);) | 71 | netdev->name, ##args);) |
66 | 72 | ||
67 | /* | 73 | /** |
68 | * this percpu struct for fcoe | 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 | ||
69 | */ | 80 | */ |
70 | struct fcoe_percpu_s { | 81 | struct fcoe_percpu_s { |
71 | struct task_struct *thread; | 82 | struct task_struct *thread; |
@@ -74,37 +85,62 @@ struct fcoe_percpu_s { | |||
74 | int crc_eof_offset; | 85 | int crc_eof_offset; |
75 | }; | 86 | }; |
76 | 87 | ||
77 | /* | 88 | /** |
78 | * an FCoE interface, 1:1 with netdev | 89 | * struct fcoe_interface - A FCoE interface |
90 | * @list: Handle for a list of FCoE interfaces | ||
91 | * @netdev: The associated net device | ||
92 | * @fcoe_packet_type: FCoE packet type | ||
93 | * @fip_packet_type: FIP packet type | ||
94 | * @ctlr: The FCoE controller (for FIP) | ||
95 | * @oem: The offload exchange manager for all local port | ||
96 | * instances associated with this port | ||
97 | * @kref: The kernel reference | ||
98 | * | ||
99 | * This structure is 1:1 with a net devive. | ||
79 | */ | 100 | */ |
80 | struct fcoe_interface { | 101 | struct fcoe_interface { |
81 | struct list_head list; | 102 | struct list_head list; |
82 | struct net_device *netdev; | 103 | struct net_device *netdev; |
83 | struct packet_type fcoe_packet_type; | 104 | struct packet_type fcoe_packet_type; |
84 | struct packet_type fip_packet_type; | 105 | struct packet_type fip_packet_type; |
85 | struct fcoe_ctlr ctlr; | 106 | struct fcoe_ctlr ctlr; |
86 | struct fc_exch_mgr *oem; /* offload exchange manager */ | 107 | struct fc_exch_mgr *oem; |
87 | struct kref kref; | 108 | struct kref kref; |
88 | }; | 109 | }; |
89 | 110 | ||
90 | /* | 111 | /** |
91 | * the FCoE private structure that's allocated along with the | 112 | * struct fcoe_port - The FCoE private structure |
92 | * Scsi_Host and libfc fc_lport structures | 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. | ||
93 | */ | 124 | */ |
94 | struct fcoe_port { | 125 | struct fcoe_port { |
95 | struct fcoe_interface *fcoe; | 126 | struct fcoe_interface *fcoe; |
96 | struct fc_lport *lport; | 127 | struct fc_lport *lport; |
97 | struct sk_buff_head fcoe_pending_queue; | 128 | struct sk_buff_head fcoe_pending_queue; |
98 | u8 fcoe_pending_queue_active; | 129 | u8 fcoe_pending_queue_active; |
99 | struct timer_list timer; /* queue timer */ | 130 | struct timer_list timer; |
100 | struct work_struct destroy_work; /* to prevent rtnl deadlocks */ | 131 | struct work_struct destroy_work; |
132 | u8 data_src_addr[ETH_ALEN]; | ||
101 | }; | 133 | }; |
102 | 134 | ||
103 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) | 135 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) |
104 | 136 | ||
105 | static inline struct net_device *fcoe_netdev(const struct fc_lport *lp) | 137 | /** |
138 | * fcoe_netdev() - Return the net device associated with a local port | ||
139 | * @lport: The local port to get the net device from | ||
140 | */ | ||
141 | static inline struct net_device *fcoe_netdev(const struct fc_lport *lport) | ||
106 | { | 142 | { |
107 | return ((struct fcoe_port *)lport_priv(lp))->fcoe->netdev; | 143 | return ((struct fcoe_port *)lport_priv(lport))->fcoe->netdev; |
108 | } | 144 | } |
109 | 145 | ||
110 | #endif /* _FCOE_H_ */ | 146 | #endif /* _FCOE_H_ */ |
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 11ae5c94608b..3440da48d169 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/if_vlan.h> | 31 | #include <linux/if_vlan.h> |
32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
33 | #include <linux/bitops.h> | 33 | #include <linux/bitops.h> |
34 | #include <linux/slab.h> | ||
34 | #include <net/rtnetlink.h> | 35 | #include <net/rtnetlink.h> |
35 | 36 | ||
36 | #include <scsi/fc/fc_els.h> | 37 | #include <scsi/fc/fc_els.h> |
@@ -59,26 +60,30 @@ unsigned int libfcoe_debug_logging; | |||
59 | module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); | 60 | module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); |
60 | MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); | 61 | MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); |
61 | 62 | ||
62 | #define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */ | 63 | #define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */ |
63 | #define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */ | 64 | #define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */ |
64 | 65 | ||
65 | #define LIBFCOE_CHECK_LOGGING(LEVEL, CMD) \ | 66 | #define LIBFCOE_CHECK_LOGGING(LEVEL, CMD) \ |
66 | do { \ | 67 | do { \ |
67 | if (unlikely(libfcoe_debug_logging & LEVEL)) \ | 68 | if (unlikely(libfcoe_debug_logging & LEVEL)) \ |
68 | do { \ | 69 | do { \ |
69 | CMD; \ | 70 | CMD; \ |
70 | } while (0); \ | 71 | } while (0); \ |
71 | } while (0) | 72 | } while (0) |
72 | 73 | ||
73 | #define LIBFCOE_DBG(fmt, args...) \ | 74 | #define LIBFCOE_DBG(fmt, args...) \ |
74 | LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \ | 75 | LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \ |
75 | printk(KERN_INFO "libfcoe: " fmt, ##args);) | 76 | printk(KERN_INFO "libfcoe: " fmt, ##args);) |
76 | 77 | ||
77 | #define LIBFCOE_FIP_DBG(fmt, args...) \ | 78 | #define LIBFCOE_FIP_DBG(fip, fmt, args...) \ |
78 | LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING, \ | 79 | LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING, \ |
79 | printk(KERN_INFO "fip: " fmt, ##args);) | 80 | printk(KERN_INFO "host%d: fip: " fmt, \ |
81 | (fip)->lp->host->host_no, ##args);) | ||
80 | 82 | ||
81 | /* | 83 | /** |
84 | * fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid | ||
85 | * @fcf: The FCF to check | ||
86 | * | ||
82 | * Return non-zero if FCF fcoe_size has been validated. | 87 | * Return non-zero if FCF fcoe_size has been validated. |
83 | */ | 88 | */ |
84 | static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf) | 89 | static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf) |
@@ -86,7 +91,10 @@ static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf) | |||
86 | return (fcf->flags & FIP_FL_SOL) != 0; | 91 | return (fcf->flags & FIP_FL_SOL) != 0; |
87 | } | 92 | } |
88 | 93 | ||
89 | /* | 94 | /** |
95 | * fcoe_ctlr_fcf_usable() - Check if a FCF is usable | ||
96 | * @fcf: The FCF to check | ||
97 | * | ||
90 | * Return non-zero if the FCF is usable. | 98 | * Return non-zero if the FCF is usable. |
91 | */ | 99 | */ |
92 | static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf) | 100 | static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf) |
@@ -97,12 +105,13 @@ static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf) | |||
97 | } | 105 | } |
98 | 106 | ||
99 | /** | 107 | /** |
100 | * fcoe_ctlr_init() - Initialize the FCoE Controller instance. | 108 | * fcoe_ctlr_init() - Initialize the FCoE Controller instance |
101 | * @fip: FCoE controller. | 109 | * @fip: The FCoE controller to initialize |
102 | */ | 110 | */ |
103 | void fcoe_ctlr_init(struct fcoe_ctlr *fip) | 111 | void fcoe_ctlr_init(struct fcoe_ctlr *fip) |
104 | { | 112 | { |
105 | fip->state = FIP_ST_LINK_WAIT; | 113 | fip->state = FIP_ST_LINK_WAIT; |
114 | fip->mode = FIP_ST_AUTO; | ||
106 | INIT_LIST_HEAD(&fip->fcfs); | 115 | INIT_LIST_HEAD(&fip->fcfs); |
107 | spin_lock_init(&fip->lock); | 116 | spin_lock_init(&fip->lock); |
108 | fip->flogi_oxid = FC_XID_UNKNOWN; | 117 | fip->flogi_oxid = FC_XID_UNKNOWN; |
@@ -114,8 +123,8 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip) | |||
114 | EXPORT_SYMBOL(fcoe_ctlr_init); | 123 | EXPORT_SYMBOL(fcoe_ctlr_init); |
115 | 124 | ||
116 | /** | 125 | /** |
117 | * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller. | 126 | * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller |
118 | * @fip: FCoE controller. | 127 | * @fip: The FCoE controller whose FCFs are to be reset |
119 | * | 128 | * |
120 | * Called with &fcoe_ctlr lock held. | 129 | * Called with &fcoe_ctlr lock held. |
121 | */ | 130 | */ |
@@ -134,8 +143,8 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) | |||
134 | } | 143 | } |
135 | 144 | ||
136 | /** | 145 | /** |
137 | * fcoe_ctlr_destroy() - Disable and tear-down the FCoE controller. | 146 | * fcoe_ctlr_destroy() - Disable and tear down a FCoE controller |
138 | * @fip: FCoE controller. | 147 | * @fip: The FCoE controller to tear down |
139 | * | 148 | * |
140 | * This is called by FCoE drivers before freeing the &fcoe_ctlr. | 149 | * This is called by FCoE drivers before freeing the &fcoe_ctlr. |
141 | * | 150 | * |
@@ -148,9 +157,7 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) | |||
148 | void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) | 157 | void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) |
149 | { | 158 | { |
150 | cancel_work_sync(&fip->recv_work); | 159 | cancel_work_sync(&fip->recv_work); |
151 | spin_lock_bh(&fip->fip_recv_list.lock); | 160 | skb_queue_purge(&fip->fip_recv_list); |
152 | __skb_queue_purge(&fip->fip_recv_list); | ||
153 | spin_unlock_bh(&fip->fip_recv_list.lock); | ||
154 | 161 | ||
155 | spin_lock_bh(&fip->lock); | 162 | spin_lock_bh(&fip->lock); |
156 | fip->state = FIP_ST_DISABLED; | 163 | fip->state = FIP_ST_DISABLED; |
@@ -162,8 +169,8 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) | |||
162 | EXPORT_SYMBOL(fcoe_ctlr_destroy); | 169 | EXPORT_SYMBOL(fcoe_ctlr_destroy); |
163 | 170 | ||
164 | /** | 171 | /** |
165 | * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port. | 172 | * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port |
166 | * @fip: FCoE controller. | 173 | * @fip: The FCoE controller to get the maximum FCoE size from |
167 | * | 174 | * |
168 | * Returns the maximum packet size including the FCoE header and trailer, | 175 | * Returns the maximum packet size including the FCoE header and trailer, |
169 | * but not including any Ethernet or VLAN headers. | 176 | * but not including any Ethernet or VLAN headers. |
@@ -180,9 +187,9 @@ static inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip) | |||
180 | } | 187 | } |
181 | 188 | ||
182 | /** | 189 | /** |
183 | * fcoe_ctlr_solicit() - Send a solicitation. | 190 | * fcoe_ctlr_solicit() - Send a FIP solicitation |
184 | * @fip: FCoE controller. | 191 | * @fip: The FCoE controller to send the solicitation on |
185 | * @fcf: Destination FCF. If NULL, a multicast solicitation is sent. | 192 | * @fcf: The destination FCF (if NULL, a multicast solicitation is sent) |
186 | */ | 193 | */ |
187 | static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) | 194 | static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) |
188 | { | 195 | { |
@@ -241,8 +248,8 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) | |||
241 | } | 248 | } |
242 | 249 | ||
243 | /** | 250 | /** |
244 | * fcoe_ctlr_link_up() - Start FCoE controller. | 251 | * fcoe_ctlr_link_up() - Start FCoE controller |
245 | * @fip: FCoE controller. | 252 | * @fip: The FCoE controller to start |
246 | * | 253 | * |
247 | * Called from the LLD when the network link is ready. | 254 | * Called from the LLD when the network link is ready. |
248 | */ | 255 | */ |
@@ -255,11 +262,12 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) | |||
255 | spin_unlock_bh(&fip->lock); | 262 | spin_unlock_bh(&fip->lock); |
256 | fc_linkup(fip->lp); | 263 | fc_linkup(fip->lp); |
257 | } else if (fip->state == FIP_ST_LINK_WAIT) { | 264 | } else if (fip->state == FIP_ST_LINK_WAIT) { |
258 | fip->state = FIP_ST_AUTO; | 265 | fip->state = fip->mode; |
259 | fip->last_link = 1; | 266 | fip->last_link = 1; |
260 | fip->link = 1; | 267 | fip->link = 1; |
261 | spin_unlock_bh(&fip->lock); | 268 | spin_unlock_bh(&fip->lock); |
262 | LIBFCOE_FIP_DBG("%s", "setting AUTO mode.\n"); | 269 | if (fip->state == FIP_ST_AUTO) |
270 | LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); | ||
263 | fc_linkup(fip->lp); | 271 | fc_linkup(fip->lp); |
264 | fcoe_ctlr_solicit(fip, NULL); | 272 | fcoe_ctlr_solicit(fip, NULL); |
265 | } else | 273 | } else |
@@ -268,45 +276,23 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) | |||
268 | EXPORT_SYMBOL(fcoe_ctlr_link_up); | 276 | EXPORT_SYMBOL(fcoe_ctlr_link_up); |
269 | 277 | ||
270 | /** | 278 | /** |
271 | * fcoe_ctlr_reset() - Reset FIP. | 279 | * fcoe_ctlr_reset() - Reset a FCoE controller |
272 | * @fip: FCoE controller. | 280 | * @fip: The FCoE controller to reset |
273 | * @new_state: FIP state to be entered. | ||
274 | * | ||
275 | * Returns non-zero if the link was up and now isn't. | ||
276 | */ | 281 | */ |
277 | static int fcoe_ctlr_reset(struct fcoe_ctlr *fip, enum fip_state new_state) | 282 | static void fcoe_ctlr_reset(struct fcoe_ctlr *fip) |
278 | { | 283 | { |
279 | struct fc_lport *lp = fip->lp; | ||
280 | int link_dropped; | ||
281 | |||
282 | spin_lock_bh(&fip->lock); | ||
283 | fcoe_ctlr_reset_fcfs(fip); | 284 | fcoe_ctlr_reset_fcfs(fip); |
284 | del_timer(&fip->timer); | 285 | del_timer(&fip->timer); |
285 | fip->state = new_state; | ||
286 | fip->ctlr_ka_time = 0; | 286 | fip->ctlr_ka_time = 0; |
287 | fip->port_ka_time = 0; | 287 | fip->port_ka_time = 0; |
288 | fip->sol_time = 0; | 288 | fip->sol_time = 0; |
289 | fip->flogi_oxid = FC_XID_UNKNOWN; | 289 | fip->flogi_oxid = FC_XID_UNKNOWN; |
290 | fip->map_dest = 0; | 290 | fip->map_dest = 0; |
291 | fip->last_link = 0; | ||
292 | link_dropped = fip->link; | ||
293 | fip->link = 0; | ||
294 | spin_unlock_bh(&fip->lock); | ||
295 | |||
296 | if (link_dropped) | ||
297 | fc_linkdown(lp); | ||
298 | |||
299 | if (new_state == FIP_ST_ENABLED) { | ||
300 | fcoe_ctlr_solicit(fip, NULL); | ||
301 | fc_linkup(lp); | ||
302 | link_dropped = 0; | ||
303 | } | ||
304 | return link_dropped; | ||
305 | } | 291 | } |
306 | 292 | ||
307 | /** | 293 | /** |
308 | * fcoe_ctlr_link_down() - Stop FCoE controller. | 294 | * fcoe_ctlr_link_down() - Stop a FCoE controller |
309 | * @fip: FCoE controller. | 295 | * @fip: The FCoE controller to be stopped |
310 | * | 296 | * |
311 | * Returns non-zero if the link was up and now isn't. | 297 | * Returns non-zero if the link was up and now isn't. |
312 | * | 298 | * |
@@ -315,15 +301,29 @@ static int fcoe_ctlr_reset(struct fcoe_ctlr *fip, enum fip_state new_state) | |||
315 | */ | 301 | */ |
316 | int fcoe_ctlr_link_down(struct fcoe_ctlr *fip) | 302 | int fcoe_ctlr_link_down(struct fcoe_ctlr *fip) |
317 | { | 303 | { |
318 | return fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT); | 304 | int link_dropped; |
305 | |||
306 | LIBFCOE_FIP_DBG(fip, "link down.\n"); | ||
307 | spin_lock_bh(&fip->lock); | ||
308 | fcoe_ctlr_reset(fip); | ||
309 | link_dropped = fip->link; | ||
310 | fip->link = 0; | ||
311 | fip->last_link = 0; | ||
312 | fip->state = FIP_ST_LINK_WAIT; | ||
313 | spin_unlock_bh(&fip->lock); | ||
314 | |||
315 | if (link_dropped) | ||
316 | fc_linkdown(fip->lp); | ||
317 | return link_dropped; | ||
319 | } | 318 | } |
320 | EXPORT_SYMBOL(fcoe_ctlr_link_down); | 319 | EXPORT_SYMBOL(fcoe_ctlr_link_down); |
321 | 320 | ||
322 | /** | 321 | /** |
323 | * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF. | 322 | * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF |
324 | * @fip: FCoE controller. | 323 | * @fip: The FCoE controller to send the FKA on |
325 | * @ports: 0 for controller keep-alive, 1 for port keep-alive. | 324 | * @lport: libfc fc_lport to send from |
326 | * @sa: source MAC address. | 325 | * @ports: 0 for controller keep-alive, 1 for port keep-alive |
326 | * @sa: The source MAC address | ||
327 | * | 327 | * |
328 | * A controller keep-alive is sent every fka_period (typically 8 seconds). | 328 | * A controller keep-alive is sent every fka_period (typically 8 seconds). |
329 | * The source MAC is the native MAC address. | 329 | * The source MAC is the native MAC address. |
@@ -332,7 +332,9 @@ EXPORT_SYMBOL(fcoe_ctlr_link_down); | |||
332 | * The source MAC is the assigned mapped source address. | 332 | * The source MAC is the assigned mapped source address. |
333 | * The destination is the FCF's F-port. | 333 | * The destination is the FCF's F-port. |
334 | */ | 334 | */ |
335 | static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | 335 | static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, |
336 | struct fc_lport *lport, | ||
337 | int ports, u8 *sa) | ||
336 | { | 338 | { |
337 | struct sk_buff *skb; | 339 | struct sk_buff *skb; |
338 | struct fip_kal { | 340 | struct fip_kal { |
@@ -350,8 +352,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
350 | if (!fcf || !fc_host_port_id(lp->host)) | 352 | if (!fcf || !fc_host_port_id(lp->host)) |
351 | return; | 353 | return; |
352 | 354 | ||
353 | len = fcoe_ctlr_fcoe_size(fip) + sizeof(struct ethhdr); | 355 | len = sizeof(*kal) + ports * sizeof(*vn); |
354 | BUG_ON(len < sizeof(*kal) + sizeof(*vn)); | ||
355 | skb = dev_alloc_skb(len); | 356 | skb = dev_alloc_skb(len); |
356 | if (!skb) | 357 | if (!skb) |
357 | return; | 358 | return; |
@@ -366,7 +367,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
366 | kal->fip.fip_op = htons(FIP_OP_CTRL); | 367 | kal->fip.fip_op = htons(FIP_OP_CTRL); |
367 | kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE; | 368 | kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE; |
368 | kal->fip.fip_dl_len = htons((sizeof(kal->mac) + | 369 | kal->fip.fip_dl_len = htons((sizeof(kal->mac) + |
369 | ports * sizeof(*vn)) / FIP_BPW); | 370 | ports * sizeof(*vn)) / FIP_BPW); |
370 | kal->fip.fip_flags = htons(FIP_FL_FPMA); | 371 | kal->fip.fip_flags = htons(FIP_FL_FPMA); |
371 | if (fip->spma) | 372 | if (fip->spma) |
372 | kal->fip.fip_flags |= htons(FIP_FL_SPMA); | 373 | kal->fip.fip_flags |= htons(FIP_FL_SPMA); |
@@ -374,16 +375,14 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
374 | kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; | 375 | kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; |
375 | kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; | 376 | kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; |
376 | memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); | 377 | memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); |
377 | |||
378 | if (ports) { | 378 | if (ports) { |
379 | vn = (struct fip_vn_desc *)(kal + 1); | 379 | vn = (struct fip_vn_desc *)(kal + 1); |
380 | vn->fd_desc.fip_dtype = FIP_DT_VN_ID; | 380 | vn->fd_desc.fip_dtype = FIP_DT_VN_ID; |
381 | vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; | 381 | vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; |
382 | memcpy(vn->fd_mac, fip->data_src_addr, ETH_ALEN); | 382 | memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN); |
383 | hton24(vn->fd_fc_id, fc_host_port_id(lp->host)); | 383 | hton24(vn->fd_fc_id, fc_host_port_id(lp->host)); |
384 | put_unaligned_be64(lp->wwpn, &vn->fd_wwpn); | 384 | put_unaligned_be64(lp->wwpn, &vn->fd_wwpn); |
385 | } | 385 | } |
386 | |||
387 | skb_put(skb, len); | 386 | skb_put(skb, len); |
388 | skb->protocol = htons(ETH_P_FIP); | 387 | skb->protocol = htons(ETH_P_FIP); |
389 | skb_reset_mac_header(skb); | 388 | skb_reset_mac_header(skb); |
@@ -392,10 +391,10 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
392 | } | 391 | } |
393 | 392 | ||
394 | /** | 393 | /** |
395 | * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it. | 394 | * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it |
396 | * @fip: FCoE controller. | 395 | * @fip: The FCoE controller for the ELS frame |
397 | * @dtype: FIP descriptor type for the frame. | 396 | * @dtype: The FIP descriptor type for the frame |
398 | * @skb: FCoE ELS frame including FC header but no FCoE headers. | 397 | * @skb: The FCoE ELS frame including FC header but no FCoE headers |
399 | * | 398 | * |
400 | * Returns non-zero error code on failure. | 399 | * Returns non-zero error code on failure. |
401 | * | 400 | * |
@@ -405,7 +404,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) | |||
405 | * Headroom includes the FIP encapsulation description, FIP header, and | 404 | * Headroom includes the FIP encapsulation description, FIP header, and |
406 | * Ethernet header. The tailroom is for the FIP MAC descriptor. | 405 | * Ethernet header. The tailroom is for the FIP MAC descriptor. |
407 | */ | 406 | */ |
408 | static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | 407 | static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, |
409 | u8 dtype, struct sk_buff *skb) | 408 | u8 dtype, struct sk_buff *skb) |
410 | { | 409 | { |
411 | struct fip_encaps_head { | 410 | struct fip_encaps_head { |
@@ -449,8 +448,8 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
449 | memset(mac, 0, sizeof(mac)); | 448 | memset(mac, 0, sizeof(mac)); |
450 | mac->fd_desc.fip_dtype = FIP_DT_MAC; | 449 | mac->fd_desc.fip_dtype = FIP_DT_MAC; |
451 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; | 450 | mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; |
452 | if (dtype != FIP_DT_FLOGI) | 451 | if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) |
453 | memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN); | 452 | memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); |
454 | else if (fip->spma) | 453 | else if (fip->spma) |
455 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); | 454 | memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); |
456 | 455 | ||
@@ -463,6 +462,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
463 | /** | 462 | /** |
464 | * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate. | 463 | * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate. |
465 | * @fip: FCoE controller. | 464 | * @fip: FCoE controller. |
465 | * @lport: libfc fc_lport to send from | ||
466 | * @skb: FCoE ELS frame including FC header but no FCoE headers. | 466 | * @skb: FCoE ELS frame including FC header but no FCoE headers. |
467 | * | 467 | * |
468 | * Returns a non-zero error code if the frame should not be sent. | 468 | * Returns a non-zero error code if the frame should not be sent. |
@@ -471,11 +471,13 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, | |||
471 | * The caller must check that the length is a multiple of 4. | 471 | * The caller must check that the length is a multiple of 4. |
472 | * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). | 472 | * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). |
473 | */ | 473 | */ |
474 | int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | 474 | int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, |
475 | struct sk_buff *skb) | ||
475 | { | 476 | { |
476 | struct fc_frame_header *fh; | 477 | struct fc_frame_header *fh; |
477 | u16 old_xid; | 478 | u16 old_xid; |
478 | u8 op; | 479 | u8 op; |
480 | u8 mac[ETH_ALEN]; | ||
479 | 481 | ||
480 | fh = (struct fc_frame_header *)skb->data; | 482 | fh = (struct fc_frame_header *)skb->data; |
481 | op = *(u8 *)(fh + 1); | 483 | op = *(u8 *)(fh + 1); |
@@ -498,6 +500,8 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
498 | 500 | ||
499 | if (fip->state == FIP_ST_NON_FIP) | 501 | if (fip->state == FIP_ST_NON_FIP) |
500 | return 0; | 502 | return 0; |
503 | if (!fip->sel_fcf) | ||
504 | goto drop; | ||
501 | 505 | ||
502 | switch (op) { | 506 | switch (op) { |
503 | case ELS_FLOGI: | 507 | case ELS_FLOGI: |
@@ -530,14 +534,15 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
530 | * FLOGI. | 534 | * FLOGI. |
531 | */ | 535 | */ |
532 | fip->flogi_oxid = FC_XID_UNKNOWN; | 536 | fip->flogi_oxid = FC_XID_UNKNOWN; |
533 | fc_fcoe_set_mac(fip->data_src_addr, fh->fh_s_id); | 537 | fc_fcoe_set_mac(mac, fh->fh_d_id); |
538 | fip->update_mac(lport, mac); | ||
534 | return 0; | 539 | return 0; |
535 | default: | 540 | default: |
536 | if (fip->state != FIP_ST_ENABLED) | 541 | if (fip->state != FIP_ST_ENABLED) |
537 | goto drop; | 542 | goto drop; |
538 | return 0; | 543 | return 0; |
539 | } | 544 | } |
540 | if (fcoe_ctlr_encaps(fip, op, skb)) | 545 | if (fcoe_ctlr_encaps(fip, lport, op, skb)) |
541 | goto drop; | 546 | goto drop; |
542 | fip->send(fip, skb); | 547 | fip->send(fip, skb); |
543 | return -EINPROGRESS; | 548 | return -EINPROGRESS; |
@@ -547,9 +552,9 @@ drop: | |||
547 | } | 552 | } |
548 | EXPORT_SYMBOL(fcoe_ctlr_els_send); | 553 | EXPORT_SYMBOL(fcoe_ctlr_els_send); |
549 | 554 | ||
550 | /* | 555 | /** |
551 | * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller. | 556 | * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller |
552 | * @fip: FCoE controller. | 557 | * @fip: The FCoE controller to free FCFs on |
553 | * | 558 | * |
554 | * Called with lock held. | 559 | * Called with lock held. |
555 | * | 560 | * |
@@ -558,14 +563,28 @@ EXPORT_SYMBOL(fcoe_ctlr_els_send); | |||
558 | * times its keep-alive period including fuzz. | 563 | * times its keep-alive period including fuzz. |
559 | * | 564 | * |
560 | * In addition, determine the time when an FCF selection can occur. | 565 | * In addition, determine the time when an FCF selection can occur. |
566 | * | ||
567 | * Also, increment the MissDiscAdvCount when no advertisement is received | ||
568 | * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB). | ||
561 | */ | 569 | */ |
562 | static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | 570 | static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) |
563 | { | 571 | { |
564 | struct fcoe_fcf *fcf; | 572 | struct fcoe_fcf *fcf; |
565 | struct fcoe_fcf *next; | 573 | struct fcoe_fcf *next; |
566 | unsigned long sel_time = 0; | 574 | unsigned long sel_time = 0; |
575 | unsigned long mda_time = 0; | ||
567 | 576 | ||
568 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { | 577 | list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { |
578 | mda_time = fcf->fka_period + (fcf->fka_period >> 1); | ||
579 | if ((fip->sel_fcf == fcf) && | ||
580 | (time_after(jiffies, fcf->time + mda_time))) { | ||
581 | mod_timer(&fip->timer, jiffies + mda_time); | ||
582 | fc_lport_get_stats(fip->lp)->MissDiscAdvCount++; | ||
583 | printk(KERN_INFO "libfcoe: host%d: Missing Discovery " | ||
584 | "Advertisement for fab %llx count %lld\n", | ||
585 | fip->lp->host->host_no, fcf->fabric_name, | ||
586 | fc_lport_get_stats(fip->lp)->MissDiscAdvCount); | ||
587 | } | ||
569 | if (time_after(jiffies, fcf->time + fcf->fka_period * 3 + | 588 | if (time_after(jiffies, fcf->time + fcf->fka_period * 3 + |
570 | msecs_to_jiffies(FIP_FCF_FUZZ * 3))) { | 589 | msecs_to_jiffies(FIP_FCF_FUZZ * 3))) { |
571 | if (fip->sel_fcf == fcf) | 590 | if (fip->sel_fcf == fcf) |
@@ -574,6 +593,7 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
574 | WARN_ON(!fip->fcf_count); | 593 | WARN_ON(!fip->fcf_count); |
575 | fip->fcf_count--; | 594 | fip->fcf_count--; |
576 | kfree(fcf); | 595 | kfree(fcf); |
596 | fc_lport_get_stats(fip->lp)->VLinkFailureCount++; | ||
577 | } else if (fcoe_ctlr_mtu_valid(fcf) && | 597 | } else if (fcoe_ctlr_mtu_valid(fcf) && |
578 | (!sel_time || time_before(sel_time, fcf->time))) { | 598 | (!sel_time || time_before(sel_time, fcf->time))) { |
579 | sel_time = fcf->time; | 599 | sel_time = fcf->time; |
@@ -590,14 +610,16 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) | |||
590 | } | 610 | } |
591 | 611 | ||
592 | /** | 612 | /** |
593 | * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry. | 613 | * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry |
594 | * @skb: received FIP advertisement frame | 614 | * @fip: The FCoE controller receiving the advertisement |
595 | * @fcf: resulting FCF entry. | 615 | * @skb: The received FIP advertisement frame |
616 | * @fcf: The resulting FCF entry | ||
596 | * | 617 | * |
597 | * Returns zero on a valid parsed advertisement, | 618 | * Returns zero on a valid parsed advertisement, |
598 | * otherwise returns non zero value. | 619 | * otherwise returns non zero value. |
599 | */ | 620 | */ |
600 | static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf) | 621 | static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, |
622 | struct sk_buff *skb, struct fcoe_fcf *fcf) | ||
601 | { | 623 | { |
602 | struct fip_header *fiph; | 624 | struct fip_header *fiph; |
603 | struct fip_desc *desc = NULL; | 625 | struct fip_desc *desc = NULL; |
@@ -636,7 +658,7 @@ static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf) | |||
636 | ((struct fip_mac_desc *)desc)->fd_mac, | 658 | ((struct fip_mac_desc *)desc)->fd_mac, |
637 | ETH_ALEN); | 659 | ETH_ALEN); |
638 | if (!is_valid_ether_addr(fcf->fcf_mac)) { | 660 | if (!is_valid_ether_addr(fcf->fcf_mac)) { |
639 | LIBFCOE_FIP_DBG("Invalid MAC address " | 661 | LIBFCOE_FIP_DBG(fip, "Invalid MAC address " |
640 | "in FIP adv\n"); | 662 | "in FIP adv\n"); |
641 | return -EINVAL; | 663 | return -EINVAL; |
642 | } | 664 | } |
@@ -659,6 +681,8 @@ static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf) | |||
659 | if (dlen != sizeof(struct fip_fka_desc)) | 681 | if (dlen != sizeof(struct fip_fka_desc)) |
660 | goto len_err; | 682 | goto len_err; |
661 | fka = (struct fip_fka_desc *)desc; | 683 | fka = (struct fip_fka_desc *)desc; |
684 | if (fka->fd_flags & FIP_FKA_ADV_D) | ||
685 | fcf->fd_flags = 1; | ||
662 | t = ntohl(fka->fd_fka_period); | 686 | t = ntohl(fka->fd_fka_period); |
663 | if (t >= FCOE_CTLR_MIN_FKA) | 687 | if (t >= FCOE_CTLR_MIN_FKA) |
664 | fcf->fka_period = msecs_to_jiffies(t); | 688 | fcf->fka_period = msecs_to_jiffies(t); |
@@ -670,7 +694,7 @@ static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf) | |||
670 | case FIP_DT_LOGO: | 694 | case FIP_DT_LOGO: |
671 | case FIP_DT_ELP: | 695 | case FIP_DT_ELP: |
672 | default: | 696 | default: |
673 | LIBFCOE_FIP_DBG("unexpected descriptor type %x " | 697 | LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x " |
674 | "in FIP adv\n", desc->fip_dtype); | 698 | "in FIP adv\n", desc->fip_dtype); |
675 | /* standard says ignore unknown descriptors >= 128 */ | 699 | /* standard says ignore unknown descriptors >= 128 */ |
676 | if (desc->fip_dtype < FIP_DT_VENDOR_BASE) | 700 | if (desc->fip_dtype < FIP_DT_VENDOR_BASE) |
@@ -687,15 +711,15 @@ static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf) | |||
687 | return 0; | 711 | return 0; |
688 | 712 | ||
689 | len_err: | 713 | len_err: |
690 | LIBFCOE_FIP_DBG("FIP length error in descriptor type %x len %zu\n", | 714 | LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n", |
691 | desc->fip_dtype, dlen); | 715 | desc->fip_dtype, dlen); |
692 | return -EINVAL; | 716 | return -EINVAL; |
693 | } | 717 | } |
694 | 718 | ||
695 | /** | 719 | /** |
696 | * fcoe_ctlr_recv_adv() - Handle an incoming advertisement. | 720 | * fcoe_ctlr_recv_adv() - Handle an incoming advertisement |
697 | * @fip: FCoE controller. | 721 | * @fip: The FCoE controller receiving the advertisement |
698 | * @skb: Received FIP packet. | 722 | * @skb: The received FIP packet |
699 | */ | 723 | */ |
700 | static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | 724 | static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) |
701 | { | 725 | { |
@@ -706,7 +730,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
706 | int first = 0; | 730 | int first = 0; |
707 | int mtu_valid; | 731 | int mtu_valid; |
708 | 732 | ||
709 | if (fcoe_ctlr_parse_adv(skb, &new)) | 733 | if (fcoe_ctlr_parse_adv(fip, skb, &new)) |
710 | return; | 734 | return; |
711 | 735 | ||
712 | spin_lock_bh(&fip->lock); | 736 | spin_lock_bh(&fip->lock); |
@@ -752,7 +776,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
752 | mtu_valid = fcoe_ctlr_mtu_valid(fcf); | 776 | mtu_valid = fcoe_ctlr_mtu_valid(fcf); |
753 | fcf->time = jiffies; | 777 | fcf->time = jiffies; |
754 | if (!found) { | 778 | if (!found) { |
755 | LIBFCOE_FIP_DBG("New FCF for fab %llx map %x val %d\n", | 779 | LIBFCOE_FIP_DBG(fip, "New FCF for fab %llx map %x val %d\n", |
756 | fcf->fabric_name, fcf->fc_map, mtu_valid); | 780 | fcf->fabric_name, fcf->fc_map, mtu_valid); |
757 | } | 781 | } |
758 | 782 | ||
@@ -778,7 +802,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
778 | */ | 802 | */ |
779 | if (mtu_valid && !fip->sel_time && fcoe_ctlr_fcf_usable(fcf)) { | 803 | if (mtu_valid && !fip->sel_time && fcoe_ctlr_fcf_usable(fcf)) { |
780 | fip->sel_time = jiffies + | 804 | fip->sel_time = jiffies + |
781 | msecs_to_jiffies(FCOE_CTLR_START_DELAY); | 805 | msecs_to_jiffies(FCOE_CTLR_START_DELAY); |
782 | if (!timer_pending(&fip->timer) || | 806 | if (!timer_pending(&fip->timer) || |
783 | time_before(fip->sel_time, fip->timer.expires)) | 807 | time_before(fip->sel_time, fip->timer.expires)) |
784 | mod_timer(&fip->timer, fip->sel_time); | 808 | mod_timer(&fip->timer, fip->sel_time); |
@@ -788,15 +812,15 @@ out: | |||
788 | } | 812 | } |
789 | 813 | ||
790 | /** | 814 | /** |
791 | * fcoe_ctlr_recv_els() - Handle an incoming FIP-encapsulated ELS frame. | 815 | * fcoe_ctlr_recv_els() - Handle an incoming FIP encapsulated ELS frame |
792 | * @fip: FCoE controller. | 816 | * @fip: The FCoE controller which received the packet |
793 | * @skb: Received FIP packet. | 817 | * @skb: The received FIP packet |
794 | */ | 818 | */ |
795 | static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | 819 | static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) |
796 | { | 820 | { |
797 | struct fc_lport *lp = fip->lp; | 821 | struct fc_lport *lport = fip->lp; |
798 | struct fip_header *fiph; | 822 | struct fip_header *fiph; |
799 | struct fc_frame *fp; | 823 | struct fc_frame *fp = (struct fc_frame *)skb; |
800 | struct fc_frame_header *fh = NULL; | 824 | struct fc_frame_header *fh = NULL; |
801 | struct fip_desc *desc; | 825 | struct fip_desc *desc; |
802 | struct fip_encaps *els; | 826 | struct fip_encaps *els; |
@@ -831,10 +855,11 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
831 | ((struct fip_mac_desc *)desc)->fd_mac, | 855 | ((struct fip_mac_desc *)desc)->fd_mac, |
832 | ETH_ALEN); | 856 | ETH_ALEN); |
833 | if (!is_valid_ether_addr(granted_mac)) { | 857 | if (!is_valid_ether_addr(granted_mac)) { |
834 | LIBFCOE_FIP_DBG("Invalid MAC address " | 858 | LIBFCOE_FIP_DBG(fip, "Invalid MAC address " |
835 | "in FIP ELS\n"); | 859 | "in FIP ELS\n"); |
836 | goto drop; | 860 | goto drop; |
837 | } | 861 | } |
862 | memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); | ||
838 | break; | 863 | break; |
839 | case FIP_DT_FLOGI: | 864 | case FIP_DT_FLOGI: |
840 | case FIP_DT_FDISC: | 865 | case FIP_DT_FDISC: |
@@ -850,7 +875,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
850 | els_dtype = desc->fip_dtype; | 875 | els_dtype = desc->fip_dtype; |
851 | break; | 876 | break; |
852 | default: | 877 | default: |
853 | LIBFCOE_FIP_DBG("unexpected descriptor type %x " | 878 | LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x " |
854 | "in FIP adv\n", desc->fip_dtype); | 879 | "in FIP adv\n", desc->fip_dtype); |
855 | /* standard says ignore unknown descriptors >= 128 */ | 880 | /* standard says ignore unknown descriptors >= 128 */ |
856 | if (desc->fip_dtype < FIP_DT_VENDOR_BASE) | 881 | if (desc->fip_dtype < FIP_DT_VENDOR_BASE) |
@@ -867,11 +892,8 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
867 | 892 | ||
868 | if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP && | 893 | if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP && |
869 | fip->flogi_oxid == ntohs(fh->fh_ox_id) && | 894 | fip->flogi_oxid == ntohs(fh->fh_ox_id) && |
870 | els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) { | 895 | els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) |
871 | fip->flogi_oxid = FC_XID_UNKNOWN; | 896 | fip->flogi_oxid = FC_XID_UNKNOWN; |
872 | fip->update_mac(fip, fip->data_src_addr, granted_mac); | ||
873 | memcpy(fip->data_src_addr, granted_mac, ETH_ALEN); | ||
874 | } | ||
875 | 897 | ||
876 | /* | 898 | /* |
877 | * Convert skb into an fc_frame containing only the ELS. | 899 | * Convert skb into an fc_frame containing only the ELS. |
@@ -882,32 +904,32 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
882 | fc_frame_init(fp); | 904 | fc_frame_init(fp); |
883 | fr_sof(fp) = FC_SOF_I3; | 905 | fr_sof(fp) = FC_SOF_I3; |
884 | fr_eof(fp) = FC_EOF_T; | 906 | fr_eof(fp) = FC_EOF_T; |
885 | fr_dev(fp) = lp; | 907 | fr_dev(fp) = lport; |
886 | 908 | ||
887 | stats = fc_lport_get_stats(lp); | 909 | stats = fc_lport_get_stats(lport); |
888 | stats->RxFrames++; | 910 | stats->RxFrames++; |
889 | stats->RxWords += skb->len / FIP_BPW; | 911 | stats->RxWords += skb->len / FIP_BPW; |
890 | 912 | ||
891 | fc_exch_recv(lp, fp); | 913 | fc_exch_recv(lport, fp); |
892 | return; | 914 | return; |
893 | 915 | ||
894 | len_err: | 916 | len_err: |
895 | LIBFCOE_FIP_DBG("FIP length error in descriptor type %x len %zu\n", | 917 | LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n", |
896 | desc->fip_dtype, dlen); | 918 | desc->fip_dtype, dlen); |
897 | drop: | 919 | drop: |
898 | kfree_skb(skb); | 920 | kfree_skb(skb); |
899 | } | 921 | } |
900 | 922 | ||
901 | /** | 923 | /** |
902 | * fcoe_ctlr_recv_els() - Handle an incoming link reset frame. | 924 | * fcoe_ctlr_recv_els() - Handle an incoming link reset frame |
903 | * @fip: FCoE controller. | 925 | * @fip: The FCoE controller that received the frame |
904 | * @fh: Received FIP header. | 926 | * @fh: The received FIP header |
905 | * | 927 | * |
906 | * There may be multiple VN_Port descriptors. | 928 | * There may be multiple VN_Port descriptors. |
907 | * The overall length has already been checked. | 929 | * The overall length has already been checked. |
908 | */ | 930 | */ |
909 | static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | 931 | static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, |
910 | struct fip_header *fh) | 932 | struct fip_header *fh) |
911 | { | 933 | { |
912 | struct fip_desc *desc; | 934 | struct fip_desc *desc; |
913 | struct fip_mac_desc *mp; | 935 | struct fip_mac_desc *mp; |
@@ -916,13 +938,13 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
916 | size_t rlen; | 938 | size_t rlen; |
917 | size_t dlen; | 939 | size_t dlen; |
918 | struct fcoe_fcf *fcf = fip->sel_fcf; | 940 | struct fcoe_fcf *fcf = fip->sel_fcf; |
919 | struct fc_lport *lp = fip->lp; | 941 | struct fc_lport *lport = fip->lp; |
920 | u32 desc_mask; | 942 | u32 desc_mask; |
921 | 943 | ||
922 | LIBFCOE_FIP_DBG("Clear Virtual Link received\n"); | 944 | LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); |
923 | if (!fcf) | 945 | if (!fcf) |
924 | return; | 946 | return; |
925 | if (!fcf || !fc_host_port_id(lp->host)) | 947 | if (!fcf || !fc_host_port_id(lport->host)) |
926 | return; | 948 | return; |
927 | 949 | ||
928 | /* | 950 | /* |
@@ -958,9 +980,10 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
958 | if (dlen < sizeof(*vp)) | 980 | if (dlen < sizeof(*vp)) |
959 | return; | 981 | return; |
960 | if (compare_ether_addr(vp->fd_mac, | 982 | if (compare_ether_addr(vp->fd_mac, |
961 | fip->data_src_addr) == 0 && | 983 | fip->get_src_addr(lport)) == 0 && |
962 | get_unaligned_be64(&vp->fd_wwpn) == lp->wwpn && | 984 | get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn && |
963 | ntoh24(vp->fd_fc_id) == fc_host_port_id(lp->host)) | 985 | ntoh24(vp->fd_fc_id) == |
986 | fc_host_port_id(lport->host)) | ||
964 | desc_mask &= ~BIT(FIP_DT_VN_ID); | 987 | desc_mask &= ~BIT(FIP_DT_VN_ID); |
965 | break; | 988 | break; |
966 | default: | 989 | default: |
@@ -977,33 +1000,39 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
977 | * reset only if all required descriptors were present and valid. | 1000 | * reset only if all required descriptors were present and valid. |
978 | */ | 1001 | */ |
979 | if (desc_mask) { | 1002 | if (desc_mask) { |
980 | LIBFCOE_FIP_DBG("missing descriptors mask %x\n", desc_mask); | 1003 | LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n", |
1004 | desc_mask); | ||
981 | } else { | 1005 | } else { |
982 | LIBFCOE_FIP_DBG("performing Clear Virtual Link\n"); | 1006 | LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); |
983 | fcoe_ctlr_reset(fip, FIP_ST_ENABLED); | 1007 | |
1008 | spin_lock_bh(&fip->lock); | ||
1009 | fc_lport_get_stats(lport)->VLinkFailureCount++; | ||
1010 | fcoe_ctlr_reset(fip); | ||
1011 | spin_unlock_bh(&fip->lock); | ||
1012 | |||
1013 | fc_lport_reset(fip->lp); | ||
1014 | fcoe_ctlr_solicit(fip, NULL); | ||
984 | } | 1015 | } |
985 | } | 1016 | } |
986 | 1017 | ||
987 | /** | 1018 | /** |
988 | * fcoe_ctlr_recv() - Receive a FIP frame. | 1019 | * fcoe_ctlr_recv() - Receive a FIP packet |
989 | * @fip: FCoE controller. | 1020 | * @fip: The FCoE controller that received the packet |
990 | * @skb: Received FIP packet. | 1021 | * @skb: The received FIP packet |
991 | * | 1022 | * |
992 | * This is called from NET_RX_SOFTIRQ. | 1023 | * This may be called from either NET_RX_SOFTIRQ or IRQ. |
993 | */ | 1024 | */ |
994 | void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) | 1025 | void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) |
995 | { | 1026 | { |
996 | spin_lock_bh(&fip->fip_recv_list.lock); | 1027 | skb_queue_tail(&fip->fip_recv_list, skb); |
997 | __skb_queue_tail(&fip->fip_recv_list, skb); | ||
998 | spin_unlock_bh(&fip->fip_recv_list.lock); | ||
999 | schedule_work(&fip->recv_work); | 1028 | schedule_work(&fip->recv_work); |
1000 | } | 1029 | } |
1001 | EXPORT_SYMBOL(fcoe_ctlr_recv); | 1030 | EXPORT_SYMBOL(fcoe_ctlr_recv); |
1002 | 1031 | ||
1003 | /** | 1032 | /** |
1004 | * fcoe_ctlr_recv_handler() - Receive a FIP frame. | 1033 | * fcoe_ctlr_recv_handler() - Receive a FIP frame |
1005 | * @fip: FCoE controller. | 1034 | * @fip: The FCoE controller that received the frame |
1006 | * @skb: Received FIP packet. | 1035 | * @skb: The received FIP frame |
1007 | * | 1036 | * |
1008 | * Returns non-zero if the frame is dropped. | 1037 | * Returns non-zero if the frame is dropped. |
1009 | */ | 1038 | */ |
@@ -1038,7 +1067,7 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
1038 | fip->map_dest = 0; | 1067 | fip->map_dest = 0; |
1039 | fip->state = FIP_ST_ENABLED; | 1068 | fip->state = FIP_ST_ENABLED; |
1040 | state = FIP_ST_ENABLED; | 1069 | state = FIP_ST_ENABLED; |
1041 | LIBFCOE_FIP_DBG("Using FIP mode\n"); | 1070 | LIBFCOE_FIP_DBG(fip, "Using FIP mode\n"); |
1042 | } | 1071 | } |
1043 | spin_unlock_bh(&fip->lock); | 1072 | spin_unlock_bh(&fip->lock); |
1044 | if (state != FIP_ST_ENABLED) | 1073 | if (state != FIP_ST_ENABLED) |
@@ -1060,8 +1089,8 @@ drop: | |||
1060 | } | 1089 | } |
1061 | 1090 | ||
1062 | /** | 1091 | /** |
1063 | * fcoe_ctlr_select() - Select the best FCF, if possible. | 1092 | * fcoe_ctlr_select() - Select the best FCF (if possible) |
1064 | * @fip: FCoE controller. | 1093 | * @fip: The FCoE controller |
1065 | * | 1094 | * |
1066 | * If there are conflicting advertisements, no FCF can be chosen. | 1095 | * If there are conflicting advertisements, no FCF can be chosen. |
1067 | * | 1096 | * |
@@ -1073,11 +1102,11 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) | |||
1073 | struct fcoe_fcf *best = NULL; | 1102 | struct fcoe_fcf *best = NULL; |
1074 | 1103 | ||
1075 | list_for_each_entry(fcf, &fip->fcfs, list) { | 1104 | list_for_each_entry(fcf, &fip->fcfs, list) { |
1076 | LIBFCOE_FIP_DBG("consider FCF for fab %llx VFID %d map %x " | 1105 | LIBFCOE_FIP_DBG(fip, "consider FCF for fab %llx VFID %d map %x " |
1077 | "val %d\n", fcf->fabric_name, fcf->vfid, | 1106 | "val %d\n", fcf->fabric_name, fcf->vfid, |
1078 | fcf->fc_map, fcoe_ctlr_mtu_valid(fcf)); | 1107 | fcf->fc_map, fcoe_ctlr_mtu_valid(fcf)); |
1079 | if (!fcoe_ctlr_fcf_usable(fcf)) { | 1108 | if (!fcoe_ctlr_fcf_usable(fcf)) { |
1080 | LIBFCOE_FIP_DBG("FCF for fab %llx map %x %svalid " | 1109 | LIBFCOE_FIP_DBG(fip, "FCF for fab %llx map %x %svalid " |
1081 | "%savailable\n", fcf->fabric_name, | 1110 | "%savailable\n", fcf->fabric_name, |
1082 | fcf->fc_map, (fcf->flags & FIP_FL_SOL) | 1111 | fcf->fc_map, (fcf->flags & FIP_FL_SOL) |
1083 | ? "" : "in", (fcf->flags & FIP_FL_AVAIL) | 1112 | ? "" : "in", (fcf->flags & FIP_FL_AVAIL) |
@@ -1091,7 +1120,7 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) | |||
1091 | if (fcf->fabric_name != best->fabric_name || | 1120 | if (fcf->fabric_name != best->fabric_name || |
1092 | fcf->vfid != best->vfid || | 1121 | fcf->vfid != best->vfid || |
1093 | fcf->fc_map != best->fc_map) { | 1122 | fcf->fc_map != best->fc_map) { |
1094 | LIBFCOE_FIP_DBG("Conflicting fabric, VFID, " | 1123 | LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, " |
1095 | "or FC-MAP\n"); | 1124 | "or FC-MAP\n"); |
1096 | return; | 1125 | return; |
1097 | } | 1126 | } |
@@ -1102,8 +1131,8 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) | |||
1102 | } | 1131 | } |
1103 | 1132 | ||
1104 | /** | 1133 | /** |
1105 | * fcoe_ctlr_timeout() - FIP timer function. | 1134 | * fcoe_ctlr_timeout() - FIP timeout handler |
1106 | * @arg: &fcoe_ctlr pointer. | 1135 | * @arg: The FCoE controller that timed out |
1107 | * | 1136 | * |
1108 | * Ages FCFs. Triggers FCF selection if possible. Sends keep-alives. | 1137 | * Ages FCFs. Triggers FCF selection if possible. Sends keep-alives. |
1109 | */ | 1138 | */ |
@@ -1113,8 +1142,6 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1113 | struct fcoe_fcf *sel; | 1142 | struct fcoe_fcf *sel; |
1114 | struct fcoe_fcf *fcf; | 1143 | struct fcoe_fcf *fcf; |
1115 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); | 1144 | unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); |
1116 | u8 send_ctlr_ka; | ||
1117 | u8 send_port_ka; | ||
1118 | 1145 | ||
1119 | spin_lock_bh(&fip->lock); | 1146 | spin_lock_bh(&fip->lock); |
1120 | if (fip->state == FIP_ST_DISABLED) { | 1147 | if (fip->state == FIP_ST_DISABLED) { |
@@ -1140,53 +1167,47 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1140 | fip->lp->host->host_no, sel->fcf_mac); | 1167 | fip->lp->host->host_no, sel->fcf_mac); |
1141 | memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); | 1168 | memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); |
1142 | fip->port_ka_time = jiffies + | 1169 | fip->port_ka_time = jiffies + |
1143 | msecs_to_jiffies(FIP_VN_KA_PERIOD); | 1170 | msecs_to_jiffies(FIP_VN_KA_PERIOD); |
1144 | fip->ctlr_ka_time = jiffies + sel->fka_period; | 1171 | fip->ctlr_ka_time = jiffies + sel->fka_period; |
1145 | fip->link = 1; | ||
1146 | } else { | 1172 | } else { |
1147 | printk(KERN_NOTICE "libfcoe: host%d: " | 1173 | printk(KERN_NOTICE "libfcoe: host%d: " |
1148 | "FIP Fibre-Channel Forwarder timed out. " | 1174 | "FIP Fibre-Channel Forwarder timed out. " |
1149 | "Starting FCF discovery.\n", | 1175 | "Starting FCF discovery.\n", |
1150 | fip->lp->host->host_no); | 1176 | fip->lp->host->host_no); |
1151 | fip->link = 0; | 1177 | fip->reset_req = 1; |
1178 | schedule_work(&fip->link_work); | ||
1152 | } | 1179 | } |
1153 | schedule_work(&fip->link_work); | ||
1154 | } | 1180 | } |
1155 | 1181 | ||
1156 | send_ctlr_ka = 0; | 1182 | if (sel && !sel->fd_flags) { |
1157 | send_port_ka = 0; | ||
1158 | if (sel) { | ||
1159 | if (time_after_eq(jiffies, fip->ctlr_ka_time)) { | 1183 | if (time_after_eq(jiffies, fip->ctlr_ka_time)) { |
1160 | fip->ctlr_ka_time = jiffies + sel->fka_period; | 1184 | fip->ctlr_ka_time = jiffies + sel->fka_period; |
1161 | send_ctlr_ka = 1; | 1185 | fip->send_ctlr_ka = 1; |
1162 | } | 1186 | } |
1163 | if (time_after(next_timer, fip->ctlr_ka_time)) | 1187 | if (time_after(next_timer, fip->ctlr_ka_time)) |
1164 | next_timer = fip->ctlr_ka_time; | 1188 | next_timer = fip->ctlr_ka_time; |
1165 | 1189 | ||
1166 | if (time_after_eq(jiffies, fip->port_ka_time)) { | 1190 | if (time_after_eq(jiffies, fip->port_ka_time)) { |
1167 | fip->port_ka_time += jiffies + | 1191 | fip->port_ka_time = jiffies + |
1168 | msecs_to_jiffies(FIP_VN_KA_PERIOD); | 1192 | msecs_to_jiffies(FIP_VN_KA_PERIOD); |
1169 | send_port_ka = 1; | 1193 | fip->send_port_ka = 1; |
1170 | } | 1194 | } |
1171 | if (time_after(next_timer, fip->port_ka_time)) | 1195 | if (time_after(next_timer, fip->port_ka_time)) |
1172 | next_timer = fip->port_ka_time; | 1196 | next_timer = fip->port_ka_time; |
1173 | mod_timer(&fip->timer, next_timer); | 1197 | mod_timer(&fip->timer, next_timer); |
1174 | } else if (fip->sel_time) { | 1198 | } else if (fip->sel_time) { |
1175 | next_timer = fip->sel_time + | 1199 | next_timer = fip->sel_time + |
1176 | msecs_to_jiffies(FCOE_CTLR_START_DELAY); | 1200 | msecs_to_jiffies(FCOE_CTLR_START_DELAY); |
1177 | mod_timer(&fip->timer, next_timer); | 1201 | mod_timer(&fip->timer, next_timer); |
1178 | } | 1202 | } |
1203 | if (fip->send_ctlr_ka || fip->send_port_ka) | ||
1204 | schedule_work(&fip->link_work); | ||
1179 | spin_unlock_bh(&fip->lock); | 1205 | spin_unlock_bh(&fip->lock); |
1180 | |||
1181 | if (send_ctlr_ka) | ||
1182 | fcoe_ctlr_send_keep_alive(fip, 0, fip->ctl_src_addr); | ||
1183 | if (send_port_ka) | ||
1184 | fcoe_ctlr_send_keep_alive(fip, 1, fip->data_src_addr); | ||
1185 | } | 1206 | } |
1186 | 1207 | ||
1187 | /** | 1208 | /** |
1188 | * fcoe_ctlr_link_work() - worker thread function for link changes. | 1209 | * fcoe_ctlr_link_work() - Worker thread function for link changes |
1189 | * @work: pointer to link_work member inside &fcoe_ctlr. | 1210 | * @work: Handle to a FCoE controller |
1190 | * | 1211 | * |
1191 | * See if the link status has changed and if so, report it. | 1212 | * See if the link status has changed and if so, report it. |
1192 | * | 1213 | * |
@@ -1196,27 +1217,49 @@ static void fcoe_ctlr_timeout(unsigned long arg) | |||
1196 | static void fcoe_ctlr_link_work(struct work_struct *work) | 1217 | static void fcoe_ctlr_link_work(struct work_struct *work) |
1197 | { | 1218 | { |
1198 | struct fcoe_ctlr *fip; | 1219 | struct fcoe_ctlr *fip; |
1220 | struct fc_lport *vport; | ||
1221 | u8 *mac; | ||
1199 | int link; | 1222 | int link; |
1200 | int last_link; | 1223 | int last_link; |
1224 | int reset; | ||
1201 | 1225 | ||
1202 | fip = container_of(work, struct fcoe_ctlr, link_work); | 1226 | fip = container_of(work, struct fcoe_ctlr, link_work); |
1203 | spin_lock_bh(&fip->lock); | 1227 | spin_lock_bh(&fip->lock); |
1204 | last_link = fip->last_link; | 1228 | last_link = fip->last_link; |
1205 | link = fip->link; | 1229 | link = fip->link; |
1206 | fip->last_link = link; | 1230 | fip->last_link = link; |
1231 | reset = fip->reset_req; | ||
1232 | fip->reset_req = 0; | ||
1207 | spin_unlock_bh(&fip->lock); | 1233 | spin_unlock_bh(&fip->lock); |
1208 | 1234 | ||
1209 | if (last_link != link) { | 1235 | if (last_link != link) { |
1210 | if (link) | 1236 | if (link) |
1211 | fc_linkup(fip->lp); | 1237 | fc_linkup(fip->lp); |
1212 | else | 1238 | else |
1213 | fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT); | 1239 | fc_linkdown(fip->lp); |
1240 | } else if (reset && link) | ||
1241 | fc_lport_reset(fip->lp); | ||
1242 | |||
1243 | if (fip->send_ctlr_ka) { | ||
1244 | fip->send_ctlr_ka = 0; | ||
1245 | fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr); | ||
1246 | } | ||
1247 | if (fip->send_port_ka) { | ||
1248 | fip->send_port_ka = 0; | ||
1249 | mutex_lock(&fip->lp->lp_mutex); | ||
1250 | mac = fip->get_src_addr(fip->lp); | ||
1251 | fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac); | ||
1252 | list_for_each_entry(vport, &fip->lp->vports, list) { | ||
1253 | mac = fip->get_src_addr(vport); | ||
1254 | fcoe_ctlr_send_keep_alive(fip, vport, 1, mac); | ||
1255 | } | ||
1256 | mutex_unlock(&fip->lp->lp_mutex); | ||
1214 | } | 1257 | } |
1215 | } | 1258 | } |
1216 | 1259 | ||
1217 | /** | 1260 | /** |
1218 | * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames. | 1261 | * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames |
1219 | * @recv_work: pointer to recv_work member inside &fcoe_ctlr. | 1262 | * @recv_work: Handle to a FCoE controller |
1220 | */ | 1263 | */ |
1221 | static void fcoe_ctlr_recv_work(struct work_struct *recv_work) | 1264 | static void fcoe_ctlr_recv_work(struct work_struct *recv_work) |
1222 | { | 1265 | { |
@@ -1224,20 +1267,14 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) | |||
1224 | struct sk_buff *skb; | 1267 | struct sk_buff *skb; |
1225 | 1268 | ||
1226 | fip = container_of(recv_work, struct fcoe_ctlr, recv_work); | 1269 | fip = container_of(recv_work, struct fcoe_ctlr, recv_work); |
1227 | spin_lock_bh(&fip->fip_recv_list.lock); | 1270 | while ((skb = skb_dequeue(&fip->fip_recv_list))) |
1228 | while ((skb = __skb_dequeue(&fip->fip_recv_list))) { | ||
1229 | spin_unlock_bh(&fip->fip_recv_list.lock); | ||
1230 | fcoe_ctlr_recv_handler(fip, skb); | 1271 | fcoe_ctlr_recv_handler(fip, skb); |
1231 | spin_lock_bh(&fip->fip_recv_list.lock); | ||
1232 | } | ||
1233 | spin_unlock_bh(&fip->fip_recv_list.lock); | ||
1234 | } | 1272 | } |
1235 | 1273 | ||
1236 | /** | 1274 | /** |
1237 | * fcoe_ctlr_recv_flogi() - snoop Pre-FIP receipt of FLOGI response or request. | 1275 | * fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response |
1238 | * @fip: FCoE controller. | 1276 | * @fip: The FCoE controller |
1239 | * @fp: FC frame. | 1277 | * @fp: The FC frame to snoop |
1240 | * @sa: Ethernet source MAC address from received FCoE frame. | ||
1241 | * | 1278 | * |
1242 | * Snoop potential response to FLOGI or even incoming FLOGI. | 1279 | * Snoop potential response to FLOGI or even incoming FLOGI. |
1243 | * | 1280 | * |
@@ -1245,15 +1282,18 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) | |||
1245 | * by fip->flogi_oxid != FC_XID_UNKNOWN. | 1282 | * by fip->flogi_oxid != FC_XID_UNKNOWN. |
1246 | * | 1283 | * |
1247 | * The caller is responsible for freeing the frame. | 1284 | * The caller is responsible for freeing the frame. |
1285 | * Fill in the granted_mac address. | ||
1248 | * | 1286 | * |
1249 | * Return non-zero if the frame should not be delivered to libfc. | 1287 | * Return non-zero if the frame should not be delivered to libfc. |
1250 | */ | 1288 | */ |
1251 | int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) | 1289 | int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, |
1290 | struct fc_frame *fp) | ||
1252 | { | 1291 | { |
1253 | struct fc_frame_header *fh; | 1292 | struct fc_frame_header *fh; |
1254 | u8 op; | 1293 | u8 op; |
1255 | u8 mac[ETH_ALEN]; | 1294 | u8 *sa; |
1256 | 1295 | ||
1296 | sa = eth_hdr(&fp->skb)->h_source; | ||
1257 | fh = fc_frame_header_get(fp); | 1297 | fh = fc_frame_header_get(fp); |
1258 | if (fh->fh_type != FC_TYPE_ELS) | 1298 | if (fh->fh_type != FC_TYPE_ELS) |
1259 | return 0; | 1299 | return 0; |
@@ -1268,7 +1308,8 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) | |||
1268 | return -EINVAL; | 1308 | return -EINVAL; |
1269 | } | 1309 | } |
1270 | fip->state = FIP_ST_NON_FIP; | 1310 | fip->state = FIP_ST_NON_FIP; |
1271 | LIBFCOE_FIP_DBG("received FLOGI LS_ACC using non-FIP mode\n"); | 1311 | LIBFCOE_FIP_DBG(fip, |
1312 | "received FLOGI LS_ACC using non-FIP mode\n"); | ||
1272 | 1313 | ||
1273 | /* | 1314 | /* |
1274 | * FLOGI accepted. | 1315 | * FLOGI accepted. |
@@ -1283,11 +1324,8 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) | |||
1283 | fip->map_dest = 0; | 1324 | fip->map_dest = 0; |
1284 | } | 1325 | } |
1285 | fip->flogi_oxid = FC_XID_UNKNOWN; | 1326 | fip->flogi_oxid = FC_XID_UNKNOWN; |
1286 | memcpy(mac, fip->data_src_addr, ETH_ALEN); | ||
1287 | fc_fcoe_set_mac(fip->data_src_addr, fh->fh_d_id); | ||
1288 | spin_unlock_bh(&fip->lock); | 1327 | spin_unlock_bh(&fip->lock); |
1289 | 1328 | fc_fcoe_set_mac(fr_cb(fp)->granted_mac, fh->fh_d_id); | |
1290 | fip->update_mac(fip, mac, fip->data_src_addr); | ||
1291 | } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { | 1329 | } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { |
1292 | /* | 1330 | /* |
1293 | * Save source MAC for point-to-point responses. | 1331 | * Save source MAC for point-to-point responses. |
@@ -1297,7 +1335,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) | |||
1297 | memcpy(fip->dest_addr, sa, ETH_ALEN); | 1335 | memcpy(fip->dest_addr, sa, ETH_ALEN); |
1298 | fip->map_dest = 0; | 1336 | fip->map_dest = 0; |
1299 | if (fip->state == FIP_ST_NON_FIP) | 1337 | if (fip->state == FIP_ST_NON_FIP) |
1300 | LIBFCOE_FIP_DBG("received FLOGI REQ, " | 1338 | LIBFCOE_FIP_DBG(fip, "received FLOGI REQ, " |
1301 | "using non-FIP mode\n"); | 1339 | "using non-FIP mode\n"); |
1302 | fip->state = FIP_ST_NON_FIP; | 1340 | fip->state = FIP_ST_NON_FIP; |
1303 | } | 1341 | } |
@@ -1308,10 +1346,10 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) | |||
1308 | EXPORT_SYMBOL(fcoe_ctlr_recv_flogi); | 1346 | EXPORT_SYMBOL(fcoe_ctlr_recv_flogi); |
1309 | 1347 | ||
1310 | /** | 1348 | /** |
1311 | * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN. | 1349 | * fcoe_wwn_from_mac() - Converts a 48-bit IEEE MAC address to a 64-bit FC WWN |
1312 | * @mac: mac address | 1350 | * @mac: The MAC address to convert |
1313 | * @scheme: check port | 1351 | * @scheme: The scheme to use when converting |
1314 | * @port: port indicator for converting | 1352 | * @port: The port indicator for converting |
1315 | * | 1353 | * |
1316 | * Returns: u64 fc world wide name | 1354 | * Returns: u64 fc world wide name |
1317 | */ | 1355 | */ |
@@ -1349,24 +1387,26 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], | |||
1349 | EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); | 1387 | EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); |
1350 | 1388 | ||
1351 | /** | 1389 | /** |
1352 | * fcoe_libfc_config() - sets up libfc related properties for lport | 1390 | * fcoe_libfc_config() - Sets up libfc related properties for local port |
1353 | * @lp: ptr to the fc_lport | 1391 | * @lp: The local port to configure libfc for |
1354 | * @tt: libfc function template | 1392 | * @tt: The libfc function template |
1355 | * | 1393 | * |
1356 | * Returns : 0 for success | 1394 | * Returns : 0 for success |
1357 | */ | 1395 | */ |
1358 | int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) | 1396 | int fcoe_libfc_config(struct fc_lport *lport, |
1397 | struct libfc_function_template *tt) | ||
1359 | { | 1398 | { |
1360 | /* Set the function pointers set by the LLDD */ | 1399 | /* Set the function pointers set by the LLDD */ |
1361 | memcpy(&lp->tt, tt, sizeof(*tt)); | 1400 | memcpy(&lport->tt, tt, sizeof(*tt)); |
1362 | if (fc_fcp_init(lp)) | 1401 | if (fc_fcp_init(lport)) |
1363 | return -ENOMEM; | 1402 | return -ENOMEM; |
1364 | fc_exch_init(lp); | 1403 | fc_exch_init(lport); |
1365 | fc_elsct_init(lp); | 1404 | fc_elsct_init(lport); |
1366 | fc_lport_init(lp); | 1405 | fc_lport_init(lport); |
1367 | fc_rport_init(lp); | 1406 | fc_rport_init(lport); |
1368 | fc_disc_init(lp); | 1407 | fc_disc_init(lport); |
1369 | 1408 | ||
1370 | return 0; | 1409 | return 0; |
1371 | } | 1410 | } |
1372 | EXPORT_SYMBOL_GPL(fcoe_libfc_config); | 1411 | EXPORT_SYMBOL_GPL(fcoe_libfc_config); |
1412 | |||